From ca6ee0e9ef85e744bf55ea24aa31091f42efc4dd Mon Sep 17 00:00:00 2001 From: Evgeny Kryshen Date: Mon, 9 Jun 2025 14:07:23 +0300 Subject: [PATCH 001/871] [Common] Setting processRun2 to true by default (#11514) --- Common/TableProducer/eventSelection.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Common/TableProducer/eventSelection.cxx b/Common/TableProducer/eventSelection.cxx index b06e98b84c5..3c989f1848a 100644 --- a/Common/TableProducer/eventSelection.cxx +++ b/Common/TableProducer/eventSelection.cxx @@ -1223,7 +1223,7 @@ struct LumiTask { LOGP(debug, "Dummy process function for Run 2"); } - PROCESS_SWITCH(LumiTask, processRun2, "Process Run2 lumi task", false); + PROCESS_SWITCH(LumiTask, processRun2, "Process Run2 lumi task", true); void processRun3(BCsWithBcSelsRun3 const& bcs, aod::FT0s const&) { From 77cdd75a1a3376b8b94aeeeb017f8bc52128f34f Mon Sep 17 00:00:00 2001 From: basiach <74355517+basiach@users.noreply.github.com> Date: Mon, 9 Jun 2025 14:33:33 +0200 Subject: [PATCH 002/871] [PWGCF] FemtoUniverse - Adding centrality for MC cascades and a PDG histogram (#11517) Co-authored-by: Barbara Chytla --- .../femtoUniverseProducerTask.cxx | 41 +++++++++++++++++++ .../Tasks/femtoUniverseEfficiencyBase.cxx | 6 +++ ...toUniversePairTaskTrackCascadeExtended.cxx | 7 +++- 3 files changed, 52 insertions(+), 2 deletions(-) diff --git a/PWGCF/FemtoUniverse/TableProducer/femtoUniverseProducerTask.cxx b/PWGCF/FemtoUniverse/TableProducer/femtoUniverseProducerTask.cxx index 00ed3161ce7..e9a07329468 100644 --- a/PWGCF/FemtoUniverse/TableProducer/femtoUniverseProducerTask.cxx +++ b/PWGCF/FemtoUniverse/TableProducer/femtoUniverseProducerTask.cxx @@ -2336,6 +2336,47 @@ struct FemtoUniverseProducerTask { } PROCESS_SWITCH(FemtoUniverseProducerTask, processTruthAndFullMCCasc, "Provide both MC truth and reco for tracks and Cascades", false); + void processTruthAndFullMCCentRun3Casc( + aod::McCollisions const& mccols, + aod::McParticles const& mcParticles, + aod::FemtoFullCollisionCentRun3MCs const& collisions, + soa::Filtered> const& tracks, + soa::Join const& fullCascades, + aod::BCsWithTimestamps const&) + { + + // recos + std::set recoMcIds; + for (const auto& col : collisions) { + auto groupedTracks = tracks.sliceBy(perCollisionTracks, col.globalIndex()); + auto groupedCascParts = fullCascades.sliceBy(perCollisionCascs, col.globalIndex()); + getMagneticFieldTesla(col.bc_as()); + const auto colcheck = fillCollisionsCentRun3(col); + if (colcheck) { + fillTracks(groupedTracks); + fillCascade(col, groupedCascParts, groupedTracks); + } + for (const auto& track : groupedTracks) { + if (trackCuts.isSelectedMinimal(track)) + recoMcIds.insert(track.mcParticleId()); + } + } + + // truth + for (const auto& mccol : mccols) { + auto groupedCollisions = collisions.sliceBy(recoCollsPerMCCollCentPbPb, mccol.globalIndex()); + for (const auto& col : groupedCollisions) { + const auto colcheck = fillMCTruthCollisionsCentRun3(col); // fills the reco collisions for mc collision + if (colcheck) { + auto groupedMCParticles = mcParticles.sliceBy(perMCCollision, mccol.globalIndex()); + outputCollExtra(1.0, 1.0); + fillParticles(groupedMCParticles, recoMcIds); // fills mc particles + } + } + } + } + PROCESS_SWITCH(FemtoUniverseProducerTask, processTruthAndFullMCCentRun3Casc, "Provide both MC truth and reco for tracks and cascades with centrality", false); + Preslice> perCollisionD0s = aod::track::collisionId; void processTrackD0MC(aod::McCollisions const& mccols, aod::TracksWMc const&, diff --git a/PWGCF/FemtoUniverse/Tasks/femtoUniverseEfficiencyBase.cxx b/PWGCF/FemtoUniverse/Tasks/femtoUniverseEfficiencyBase.cxx index 92e42134f0a..5397acf05dc 100644 --- a/PWGCF/FemtoUniverse/Tasks/femtoUniverseEfficiencyBase.cxx +++ b/PWGCF/FemtoUniverse/Tasks/femtoUniverseEfficiencyBase.cxx @@ -160,6 +160,7 @@ struct FemtoUniverseEfficiencyBase { trackHistoPartOneRec.init(&qaRegistry, confTempFitVarpTBins, confTempFitVarDCABins, 0, confPDGCodePartOne, confIsDebug); registryMCOrigin.add("part1/hPt", " ;#it{p}_{T} (GeV/c); Entries", {HistType::kTH1F, {{240, 0, 6}}}); registryPDG.add("part1/PDGvspT", "PDG;#it{p}_{T} (GeV/c); PDG", {HistType::kTH2F, {{500, 0, 5}, {16001, -8000.5, 8000.5}}}); + registryPDG.add("part1/PDGvspTall", "PDG;#it{p}_{T} (GeV/c); PDG", {HistType::kTH2F, {{500, 0, 5}, {16001, -8000.5, 8000.5}}}); if (confParticleTypePartOne == uint8_t(aod::femtouniverseparticle::ParticleType::kV0)) { trackHistoV0OneRec.init(&qaRegistry, confTempFitVarpTBins, confTempFitVarCPABins, 0, confPDGCodePartOne, confIsDebug); trackHistoV0OneChildPosRec.init(&qaRegistry, confTempFitVarpTBins, confTempFitVarDCABins, 0, 0, confIsDebug, "posChildV0_1"); @@ -169,6 +170,7 @@ struct FemtoUniverseEfficiencyBase { } registryPDG.add("part2/PDGvspT", "PDG;#it{p}_{T} (GeV/c); PDG", {HistType::kTH2F, {{500, 0, 5}, {16001, -8000.5, 8000.5}}}); + registryPDG.add("part2/PDGvspTall", "PDG;#it{p}_{T} (GeV/c); PDG", {HistType::kTH2F, {{500, 0, 5}, {16001, -8000.5, 8000.5}}}); if (!confIsSame) { trackHistoPartTwoGen.init(&qaRegistry, confTempFitVarpTBins, confTempFitVarPDGBins, 0, confPDGCodePartTwo, false); trackHistoPartTwoRec.init(&qaRegistry, confTempFitVarpTBins, confTempFitVarDCABins, 0, confPDGCodePartTwo, confIsDebug); @@ -373,6 +375,8 @@ struct FemtoUniverseEfficiencyBase { continue; } + registryPDG.fill(HIST("part1/PDGvspTall"), part.pt(), mcParticle.pdgMCTruth()); + if (!(std::abs(mcParticle.pdgMCTruth()) == std::abs(confPDGCodePartOne))) { continue; } @@ -397,6 +401,8 @@ struct FemtoUniverseEfficiencyBase { continue; } + registryPDG.fill(HIST("part2/PDGvspTall"), part.pt(), mcParticle.pdgMCTruth()); + if (!(std::abs(mcParticle.pdgMCTruth()) == std::abs(confPDGCodePartTwo))) { continue; } diff --git a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackCascadeExtended.cxx b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackCascadeExtended.cxx index e4ebe2db60a..026cabb1367 100644 --- a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackCascadeExtended.cxx +++ b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackCascadeExtended.cxx @@ -631,6 +631,8 @@ struct femtoUniversePairTaskTrackCascadeExtended { // MC truth void processSameEventMCgen(const FilteredFDCollision& col, [[maybe_unused]] const FemtoFullParticles& parts) { + const int multCol = confUseCent ? col.multV0M() : col.multNtr(); + auto groupPartsOne = partsOneMCgen->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); auto groupPartsTwo = partsTwoMCgen->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); @@ -665,7 +667,7 @@ struct femtoUniversePairTaskTrackCascadeExtended { int pdgCodeCasc = static_cast(p2.pidCut()); if ((confCascType1 == 0 && pdgCodeCasc != 3334) || (confCascType1 == 2 && pdgCodeCasc != -3334) || (confCascType1 == 1 && pdgCodeCasc != 3312) || (confCascType1 == 3 && pdgCodeCasc != -3312)) continue; - sameEventCont.setPair(p1, p2, col.multNtr(), confUse3D, 1.0f); + sameEventCont.setPair(p1, p2, multCol, confUse3D, 1.0f); } } } @@ -676,6 +678,7 @@ struct femtoUniversePairTaskTrackCascadeExtended { 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 = partsOneMCgen->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); auto groupPartsTwo = partsTwoMCgen->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision2.globalIndex(), cache); @@ -692,7 +695,7 @@ struct femtoUniversePairTaskTrackCascadeExtended { int pdgCodeCasc = static_cast(p2.pidCut()); if ((confCascType1 == 0 && pdgCodeCasc != 3334) || (confCascType1 == 2 && pdgCodeCasc != -3334) || (confCascType1 == 1 && pdgCodeCasc != 3312) || (confCascType1 == 3 && pdgCodeCasc != -3312)) continue; - mixedEventCont.setPair(p1, p2, collision1.multNtr(), confUse3D, 1.0f); + mixedEventCont.setPair(p1, p2, multCol, confUse3D, 1.0f); } } } From 251b2ea844753c81487fe0dbc5cd9363f61627e8 Mon Sep 17 00:00:00 2001 From: Rahul Verma <110929992+rahulverma012@users.noreply.github.com> Date: Mon, 9 Jun 2025 20:26:52 +0530 Subject: [PATCH 003/871] [Common] modified aod::TracksQA_002 to aod::TracksQAVersion (#11485) Co-authored-by: Anton Alkin --- Common/TableProducer/occupancyTableProducer.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Common/TableProducer/occupancyTableProducer.cxx b/Common/TableProducer/occupancyTableProducer.cxx index 2e4a01ddbb1..95d1ca72dea 100644 --- a/Common/TableProducer/occupancyTableProducer.cxx +++ b/Common/TableProducer/occupancyTableProducer.cxx @@ -1692,7 +1692,7 @@ struct TrackMeanOccTableProducer { } } - using MyTracksQA = aod::TracksQA_002; + using MyTracksQA = aod::TracksQAVersion; // using MyTracksQA = aod::TracksQA_002; // Process the Data int dfCount = 0; From 18fa5fc45d2adf1a98befd9b97889c87732b4c4c Mon Sep 17 00:00:00 2001 From: Pritam Chakraborty <47203359+prchakra@users.noreply.github.com> Date: Mon, 9 Jun 2025 21:23:33 +0200 Subject: [PATCH 004/871] [PWGCF] FemtoUniverse: Fine binning the helicity angle distribution (#11521) --- PWGCF/FemtoUniverse/Tasks/femtoUniverseDebugV0.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PWGCF/FemtoUniverse/Tasks/femtoUniverseDebugV0.cxx b/PWGCF/FemtoUniverse/Tasks/femtoUniverseDebugV0.cxx index d35aa3fa779..fe1bf2e7983 100644 --- a/PWGCF/FemtoUniverse/Tasks/femtoUniverseDebugV0.cxx +++ b/PWGCF/FemtoUniverse/Tasks/femtoUniverseDebugV0.cxx @@ -85,7 +85,7 @@ struct FemtoUniverseDebugV0 { negativeChildHistos.init(&V0Registry, confChildTempFitVarpTBins, confChildTempFitVarBins, false, confPDGCodeNegativeChild, true); V0Histos.init(&V0Registry, confV0TempFitVarpTBins, confV0TempFitVarBins, false, confPDGCodeV0.value, true); - thetaRegistry.add("Theta/hTheta", " ; p (GeV/#it{c}); cos(#theta)", kTH2F, {{100, 0, 10}, {50, -5, 5}}); + thetaRegistry.add("Theta/hTheta", " ; p (GeV/#it{c}); cos(#theta)", kTH2F, {{100, 0, 10}, {110, -1.1, 1.1}}); } /// Produce QA plots for V0 selection in FemtoUniverse framework From 87a0260995873329b1f3ccc030dea8924586f1c6 Mon Sep 17 00:00:00 2001 From: skundu692 <86804743+skundu692@users.noreply.github.com> Date: Mon, 9 Jun 2025 22:09:34 +0200 Subject: [PATCH 005/871] [PWGLF] Improve variable selection in mixed event (#11522) --- .../Tasks/Strangeness/taskLambdaSpinCorr.cxx | 135 +++++++++++------- 1 file changed, 87 insertions(+), 48 deletions(-) diff --git a/PWGLF/Tasks/Strangeness/taskLambdaSpinCorr.cxx b/PWGLF/Tasks/Strangeness/taskLambdaSpinCorr.cxx index 9badfb4b4ba..0472e380aed 100644 --- a/PWGLF/Tasks/Strangeness/taskLambdaSpinCorr.cxx +++ b/PWGLF/Tasks/Strangeness/taskLambdaSpinCorr.cxx @@ -61,8 +61,8 @@ struct LfTaskLambdaSpinCorr { Configurable cfgEvtRCTFlagCheckerLimitAcceptAsBad{"cfgEvtRCTFlagCheckerLimitAcceptAsBad", true, "Evt sel: RCT flag checker treat Limited Acceptance As Bad"}; } rctCut; // mixing - Configurable cosCalculation{"cosCalculation", 1, "cos calculation"}; - Configurable mixingCombination{"mixingCombination", 1, "mixing Combination"}; + Configurable cosCalculation{"cosCalculation", 0, "cos calculation"}; + Configurable mixingCombination{"mixingCombination", 0, "mixing Combination"}; Configurable mixingEvSel{"mixingEvSel", false, "mixingEvSel"}; Configurable cfgCutOccupancy{"cfgCutOccupancy", 2000, "Occupancy cut"}; ConfigurableAxis axisVertex{"axisVertex", {5, -10, 10}, "vertex axis for bin"}; @@ -128,7 +128,8 @@ struct LfTaskLambdaSpinCorr { AxisSpec thnAxisInvMasspair{iMNbinspair, lbinIMpair, hbinIMpair, "#it{M} (GeV/#it{c}^{2})"}; histos.add("hEvtSelInfo", "hEvtSelInfo", kTH1F, {{10, 0, 10.0}}); histos.add("hPtDiff", "hPtDiff", kTH1F, {{1000, 0, 100.0}}); - histos.add("hRDiff", "hRDiff", kTH1F, {{640, 0, 16.0}}); + histos.add("hPhiDiff", "hPhiDiff", kTH1F, {{800, -8.0, 8.0}}); + histos.add("hRDiff", "hRDiff", kTH1F, {{640, -16.0, 16.0}}); histos.add("hv0Mult", "hv0Mult", kTH1F, {{10001, -0.5, 10000.5}}); histos.add("hCentrality", "Centrality distribution", kTH1F, {{configcentAxis}}); histos.add("hSparseLambdaLambda", "hSparseLambdaLambda", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisInvMass, configthnAxisPol, configcentAxis, thnAxisInvMasspair}, true); @@ -244,8 +245,8 @@ struct LfTaskLambdaSpinCorr { const ROOT::Math::PxPyPzMVector& Lambdadummy, const ROOT::Math::PxPyPzMVector& AntiLambdadummy) { - const double minMass = 1.0; - const double maxMass = 2.0; + const double minMass = 1.09; + const double maxMass = 1.14; return (lambdaTag && aLambdaTag && (Lambdadummy.M() > minMass && Lambdadummy.M() < maxMass) && (AntiLambdadummy.M() > minMass && AntiLambdadummy.M() < maxMass)); @@ -293,8 +294,8 @@ struct LfTaskLambdaSpinCorr { double cosTheta2 = proton2LambdaRF.Vect().Unit().Dot(quantizationAxis); cosThetaDiff = cosTheta1 * cosTheta2; } - - double deltaR = TMath::Sqrt(TMath::Power(particle1.Eta() - particle2.Eta(), 2.0) + TMath::Power(particle1.Phi() - particle2.Phi(), 2.0)); + double deltaPhi = RecoDecay::constrainAngle(particle1.Phi() - particle2.Phi(), 0.0); + double deltaR = TMath::Sqrt(TMath::Power(particle1.Eta() - particle2.Eta(), 2.0) + TMath::Power(deltaPhi, 2.0)); if (datatype == 0) { if (tag1 && tag3) { histos.fill(HIST("hSparseLambdaLambda"), particle1.M(), particle2.M(), cosThetaDiff, centrality, deltaR); @@ -411,7 +412,7 @@ struct LfTaskLambdaSpinCorr { return {lambdaTag, aLambdaTag, true}; // Valid candidate } - + ROOT::Math::PxPyPzMVector lambda0, antiLambda0, proton0, pion0, antiProton0, antiPion0; ROOT::Math::PxPyPzMVector lambda, antiLambda, proton, pion, antiProton, antiPion; ROOT::Math::PxPyPzMVector lambda2, antiLambda2, proton2, pion2, antiProton2, antiPion2; ROOT::Math::PxPyPzMVector lambdamc, antiLambdamc, protonmc, pionmc, antiProtonmc, antiPionmc; @@ -478,7 +479,12 @@ struct LfTaskLambdaSpinCorr { pion = ROOT::Math::PxPyPzMVector(v0.pxpos(), v0.pypos(), v0.pzpos(), o2::constants::physics::MassPionCharged); antiLambda = antiProton + pion; } - + if (lambdaTag && (lambda.M() < lbinIM || lambda.M() > hbinIM)) { + continue; + } + if (aLambdaTag && (antiLambda.M() < lbinIM || antiLambda.M() > hbinIM)) { + continue; + } auto postrack1 = v0.template posTrack_as(); auto negtrack1 = v0.template negTrack_as(); @@ -504,6 +510,12 @@ struct LfTaskLambdaSpinCorr { pion2 = ROOT::Math::PxPyPzMVector(v02.pxpos(), v02.pypos(), v02.pzpos(), o2::constants::physics::MassPionCharged); antiLambda2 = antiProton2 + pion2; } + if (lambdaTag2 && (lambda2.M() < lbinIM || lambda2.M() > hbinIM)) { + continue; + } + if (aLambdaTag2 && (antiLambda2.M() < lbinIM || antiLambda2.M() > hbinIM)) { + continue; + } auto postrack2 = v02.template posTrack_as(); auto negtrack2 = v02.template negTrack_as(); if (postrack1.globalIndex() == postrack2.globalIndex() || negtrack1.globalIndex() == negtrack2.globalIndex()) { @@ -630,8 +642,42 @@ struct LfTaskLambdaSpinCorr { if (postrack1.globalIndex() == postrack2.globalIndex() || negtrack1.globalIndex() == negtrack2.globalIndex()) { continue; } - auto samePairSumPt = t1.pt() + t2.pt(); - auto samePairR = TMath::Sqrt(TMath::Power(t1.phi() - t2.phi(), 2.0) + TMath::Power(t1.eta() - t2.eta(), 2.0)); + // auto samePairSumPt = t1.pt() + t2.pt(); + double deltaPhiSame = RecoDecay::constrainAngle(t1.phi() - t2.phi(), 0.0); + auto samePairR = TMath::Sqrt(TMath::Power(deltaPhiSame, 2.0) + TMath::Power(t1.eta() - t2.eta(), 2.0)); + + if (lambdaTag1) { + proton0 = ROOT::Math::PxPyPzMVector(t1.pxpos(), t1.pypos(), t1.pzpos(), o2::constants::physics::MassProton); + antiPion0 = ROOT::Math::PxPyPzMVector(t1.pxneg(), t1.pyneg(), t1.pzneg(), o2::constants::physics::MassPionCharged); + lambda0 = proton0 + antiPion0; + } + if (aLambdaTag1) { + antiProton0 = ROOT::Math::PxPyPzMVector(t1.pxneg(), t1.pyneg(), t1.pzneg(), o2::constants::physics::MassProton); + pion0 = ROOT::Math::PxPyPzMVector(t1.pxpos(), t1.pypos(), t1.pzpos(), o2::constants::physics::MassPionCharged); + antiLambda0 = antiProton0 + pion0; + } + if (lambdaTag1 && (lambda0.M() < lbinIM || lambda0.M() > hbinIM)) { + continue; + } + if (aLambdaTag1 && (antiLambda0.M() < lbinIM || antiLambda0.M() > hbinIM)) { + continue; + } + if (lambdaTag2) { + proton = ROOT::Math::PxPyPzMVector(t2.pxpos(), t2.pypos(), t2.pzpos(), o2::constants::physics::MassProton); + antiPion = ROOT::Math::PxPyPzMVector(t2.pxneg(), t2.pyneg(), t2.pzneg(), o2::constants::physics::MassPionCharged); + lambda = proton + antiPion; + } + if (aLambdaTag2) { + antiProton = ROOT::Math::PxPyPzMVector(t2.pxneg(), t2.pyneg(), t2.pzneg(), o2::constants::physics::MassProton); + pion = ROOT::Math::PxPyPzMVector(t2.pxpos(), t2.pypos(), t2.pzpos(), o2::constants::physics::MassPionCharged); + antiLambda = antiProton + pion; + } + if (lambdaTag2 && (lambda.M() < lbinIM || lambda.M() > hbinIM)) { + continue; + } + if (aLambdaTag2 && (antiLambda.M() < lbinIM || antiLambda.M() > hbinIM)) { + continue; + } for (const auto& t3 : groupV03) { // if (pairStatus[t3.index()][t2.index()]) { // LOGF(info, "repeat match found v0 id: (%d, %d)", t3.index(), t2.index()); @@ -653,55 +699,49 @@ struct LfTaskLambdaSpinCorr { if (lambdaTag1 != lambdaTag3 || aLambdaTag1 != aLambdaTag3) { continue; } - // if (std::abs(t1.pt() - t3.pt()) > ptMix) { - // continue; - // } - // if (std::abs(t1.eta() - t3.eta()) > etaMix) { - // continue; - // } - // if (std::abs(t1.phi() - t3.phi()) > phiMix) { - // continue; - // } - auto mixPairSumPt = t3.pt() + t2.pt(); - auto mixPairR = TMath::Sqrt(TMath::Power(t3.phi() - t2.phi(), 2.0) + TMath::Power(t3.eta() - t2.eta(), 2.0)); - histos.fill(HIST("hPtDiff"), TMath::Abs(mixPairSumPt - samePairSumPt)); - histos.fill(HIST("hRDiff"), TMath::Abs(mixPairR - samePairR)); - if (mixingCombination == 0 && std::abs(t1.pt() - t3.pt()) > ptMix) { - continue; + + if (lambdaTag3) { + proton2 = ROOT::Math::PxPyPzMVector(t3.pxpos(), t3.pypos(), t3.pzpos(), o2::constants::physics::MassProton); + antiPion2 = ROOT::Math::PxPyPzMVector(t3.pxneg(), t3.pyneg(), t3.pzneg(), o2::constants::physics::MassPionCharged); + lambda2 = proton2 + antiPion2; + } + if (aLambdaTag3) { + antiProton2 = ROOT::Math::PxPyPzMVector(t3.pxneg(), t3.pyneg(), t3.pzneg(), o2::constants::physics::MassProton); + pion2 = ROOT::Math::PxPyPzMVector(t3.pxpos(), t3.pypos(), t3.pzpos(), o2::constants::physics::MassPionCharged); + antiLambda2 = antiProton2 + pion2; } - if (mixingCombination == 0 && std::abs(t1.eta() - t3.eta()) > etaMix) { + if (lambdaTag3 && (lambda2.M() < lbinIM || lambda2.M() > hbinIM)) { continue; } - if (mixingCombination == 0 && std::abs(t1.phi() - t3.phi()) > phiMix) { + if (aLambdaTag3 && (antiLambda2.M() < lbinIM || antiLambda2.M() > hbinIM)) { continue; } + double deltaPhiMix = RecoDecay::constrainAngle(t3.phi() - t2.phi(), 0.0); + auto mixPairR = TMath::Sqrt(TMath::Power(deltaPhiMix, 2.0) + TMath::Power(t3.eta() - t2.eta(), 2.0)); + auto etaDiff = t1.eta() - t3.eta(); + auto phiDiff = RecoDecay::constrainAngle(t1.phi() - t3.phi(), 0.0); - if (mixingCombination == 1 && std::abs(mixPairSumPt - samePairSumPt) > ptMix) { + histos.fill(HIST("hPtDiff"), t1.pt() - t3.pt()); + histos.fill(HIST("hPhiDiff"), phiDiff); + histos.fill(HIST("hRDiff"), etaDiff); + + if (mixingCombination == 0 && std::abs(t1.pt() - t3.pt()) > ptMix) { continue; } - if (mixingCombination == 1 && std::abs(mixPairR - samePairR) > etaMix) { + if (mixingCombination == 0 && t1.eta() * t3.eta() > 0 && std::abs(etaDiff) > etaMix) { continue; } - if (lambdaTag2) { - proton = ROOT::Math::PxPyPzMVector(t2.pxpos(), t2.pypos(), t2.pzpos(), o2::constants::physics::MassProton); - antiPion = ROOT::Math::PxPyPzMVector(t2.pxneg(), t2.pyneg(), t2.pzneg(), o2::constants::physics::MassPionCharged); - lambda = proton + antiPion; - } - if (aLambdaTag2) { - antiProton = ROOT::Math::PxPyPzMVector(t2.pxneg(), t2.pyneg(), t2.pzneg(), o2::constants::physics::MassProton); - pion = ROOT::Math::PxPyPzMVector(t2.pxpos(), t2.pypos(), t2.pzpos(), o2::constants::physics::MassPionCharged); - antiLambda = antiProton + pion; + if (mixingCombination == 0 && phiDiff > phiMix) { + continue; } - if (lambdaTag3) { - proton2 = ROOT::Math::PxPyPzMVector(t3.pxpos(), t3.pypos(), t3.pzpos(), o2::constants::physics::MassProton); - antiPion2 = ROOT::Math::PxPyPzMVector(t3.pxneg(), t3.pyneg(), t3.pzneg(), o2::constants::physics::MassPionCharged); - lambda2 = proton2 + antiPion2; + + if (mixingCombination == 1 && std::abs(t1.pt() - t3.pt()) > ptMix) { + continue; } - if (aLambdaTag3) { - antiProton2 = ROOT::Math::PxPyPzMVector(t3.pxneg(), t3.pyneg(), t3.pzneg(), o2::constants::physics::MassProton); - pion2 = ROOT::Math::PxPyPzMVector(t3.pxpos(), t3.pypos(), t3.pzpos(), o2::constants::physics::MassPionCharged); - antiLambda2 = antiProton2 + pion2; + if (mixingCombination == 1 && std::abs(mixPairR - samePairR) > etaMix) { + continue; } + if (lambdaTag2 && lambdaTag3) { fillHistograms(1, 0, 1, 0, lambda, lambda2, proton, proton2, centrality, 2); } else if (aLambdaTag2 && aLambdaTag3) { @@ -714,7 +754,6 @@ struct LfTaskLambdaSpinCorr { continue; } pairfound = true; - // pairStatus[t3.index()][t2.index()] = true; pairStatus[t3.index()][t2.index()] = true; // LOGF(info, "v0 id: (%d, %d)", t3.index(), t2.index()); if (pairfound) { From 391cc72f9107f774b04ced9fe22e043bf51dce71 Mon Sep 17 00:00:00 2001 From: sarjeetagami <162087855+sarjeetagami@users.noreply.github.com> Date: Tue, 10 Jun 2025 02:24:16 +0530 Subject: [PATCH 006/871] [PWGLF] fix event selection hist (#11524) Co-authored-by: sarjeeta gami --- PWGLF/Tasks/Resonances/kstarpbpb.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PWGLF/Tasks/Resonances/kstarpbpb.cxx b/PWGLF/Tasks/Resonances/kstarpbpb.cxx index 0093b921c80..a8ad0497647 100644 --- a/PWGLF/Tasks/Resonances/kstarpbpb.cxx +++ b/PWGLF/Tasks/Resonances/kstarpbpb.cxx @@ -184,9 +184,9 @@ struct kstarpbpb { AxisSpec centAxis = {8, 0, 80, "V0M (%)"}; AxisSpec occupancyAxis = {occupancyBinning, "Occupancy"}; if (!fillSA) { + histos.add("hEvtSelInfo", "hEvtSelInfo", kTH1F, {{10, 0, 10.0}}); if (same) { histos.add("hSparseV2SASameEvent_V2", "hSparseV2SASameEvent_V2", HistType::kTHnSparseF, {configThnAxisInvMass, configThnAxisPt, configThnAxisV2, configThnAxisCentrality}); - histos.add("hEvtSelInfo", "hEvtSelInfo", kTH1F, {{10, 0, 10.0}}); } if (like) { histos.add("hSparseV2SAlikeEventNN_V2", "hSparseV2SAlikeEventNN_V2", HistType::kTHnSparseF, {configThnAxisInvMass, configThnAxisPt, configThnAxisV2, configThnAxisCentrality}); From 5224c360dc6521fb39050a8dbb4ef762b4876b7c Mon Sep 17 00:00:00 2001 From: Mario Ciacco Date: Mon, 9 Jun 2025 23:23:01 +0200 Subject: [PATCH 007/871] [PWGLF] use material LUT in fit and propagation (#11513) --- .../Strangeness/LFStrangeTreeCreator.cxx | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/PWGLF/TableProducer/Strangeness/LFStrangeTreeCreator.cxx b/PWGLF/TableProducer/Strangeness/LFStrangeTreeCreator.cxx index 955b4ebc142..4ab2f0cc745 100644 --- a/PWGLF/TableProducer/Strangeness/LFStrangeTreeCreator.cxx +++ b/PWGLF/TableProducer/Strangeness/LFStrangeTreeCreator.cxx @@ -157,8 +157,8 @@ struct LFStrangeTreeCreator { int mRunNumber; float d_bz; - // o2::base::MatLayerCylSet* lut = nullptr; - Configurable cfgMaterialCorrection{"cfgMaterialCorrection", static_cast(o2::base::Propagator::MatCorrType::USEMatCorrNONE), "Type of material correction"}; + o2::base::MatLayerCylSet* lut = nullptr; + Configurable cfgMaterialCorrection{"cfgMaterialCorrection", static_cast(o2::base::Propagator::MatCorrType::USEMatCorrLUT), "Type of material correction"}; ConfigurableAxis centAxis{"centAxis", {106, 0, 106}, "binning for the centrality"}; ConfigurableAxis zVtxAxis{"zVtxBins", {100, -20.f, 20.f}, "Binning for the vertex z in cm"}; @@ -248,7 +248,11 @@ struct LFStrangeTreeCreator { mRunNumber = bc.runNumber(); fitter.setBz(d_bz); - // o2::base::Propagator::Instance()->setMatLUT(lut); + lut = o2::base::MatLayerCylSet::rectifyPtrFromFile(ccdb->get("GLO/Param/MatLUT")); + o2::base::Propagator::Instance()->setMatLUT(lut); + + int mat{static_cast(cfgMaterialCorrection)}; + fitter.setMatCorrType(static_cast(mat)); } void init(o2::framework::InitContext&) @@ -261,7 +265,6 @@ struct LFStrangeTreeCreator { ccdb->setCaching(true); ccdb->setLocalObjectValidityChecking(); ccdb->setFatalWhenNull(false); - // lut = o2::base::MatLayerCylSet::rectifyPtrFromFile(ccdb->get("GLO/Param/MatLUT")); fitter.setPropagateToPCA(true); fitter.setMaxR(200.); @@ -272,8 +275,6 @@ struct LFStrangeTreeCreator { fitter.setMaxChi2(1e9); fitter.setUseAbsDCA(true); fitter.setWeightedFinalPCA(false); - int mat{static_cast(cfgMaterialCorrection)}; - fitter.setMatCorrType(static_cast(mat)); // event QA histos.add("QA/zVtx", ";#it{z}_{vtx} (cm);Entries", HistType::kTH1F, {zVtxAxis}); From cb9ff1bc2854dc917e8ea5c1b38b4aea72e66aef Mon Sep 17 00:00:00 2001 From: mherzer <96999709+mherzer28@users.noreply.github.com> Date: Mon, 9 Jun 2025 23:50:29 +0200 Subject: [PATCH 008/871] [PWGLF] added second option for mass calculation (#11459) Co-authored-by: ALICE Action Bot --- PWGLF/TableProducer/Nuspex/trHeAnalysis.cxx | 47 ++++++++++++++++----- 1 file changed, 36 insertions(+), 11 deletions(-) diff --git a/PWGLF/TableProducer/Nuspex/trHeAnalysis.cxx b/PWGLF/TableProducer/Nuspex/trHeAnalysis.cxx index a33295b6021..f00fc314870 100644 --- a/PWGLF/TableProducer/Nuspex/trHeAnalysis.cxx +++ b/PWGLF/TableProducer/Nuspex/trHeAnalysis.cxx @@ -35,6 +35,7 @@ #include "PWGLF/DataModel/LFParticleIdentification.h" #include "ReconstructionDataFormats/PID.h" #include "ReconstructionDataFormats/Track.h" +#include "PWGLF/DataModel/pidTOFGeneric.h" #include namespace o2::aod @@ -113,7 +114,7 @@ static const std::vector particleCharge{1, 2}; static const std::vector particleChargeFactor{2.3, 2.55}; static const std::vector betheBlochParNames{ "p0", "p1", "p2", "p3", "p4", "resolution"}; -constexpr float betheBlochDefault[nParticles][nBetheParams]{ +constexpr float BetheBlochDefault[nParticles][nBetheParams]{ {0.248753, 3.58634, 0.0167065, 2.29194, 0.774344, 0.07}, // triton {0.0274556, 18.3054, 3.99987e-05, 3.17219, 11.1775, @@ -126,7 +127,8 @@ using TracksFull = soa::Join; + aod::TOFSignal, aod::TrackSelectionExtension, + o2::aod::EvTimeTOFFT0ForTrack>; class Particle { @@ -186,7 +188,7 @@ struct TrHeAnalysis { } evselOptions; Configurable cfgTPCPidMethod{"cfgTPCPidMethod", false, "Using own or built in bethe parametrization"}; // false for built in - + Configurable cfgMassMethod{"cfgMassMethod", 0, "0: Using built in 1: mass calculated with beta 2: mass calculated with the event time"}; // Set the multiplity event limits Configurable cfgLowMultCut{"cfgLowMultCut", 0.0f, "Accepted multiplicity percentage lower limit"}; Configurable cfgHighMultCut{"cfgHighMultCut", 100.0f, "Accepted multiplicity percentage higher limit"}; @@ -226,7 +228,7 @@ struct TrHeAnalysis { Configurable nsigmaTPCTr{"nsigmaTPCTr", 5.f, "Value of the Nsigma TPC cut for tritons"}; Configurable nsigmaTPCHe{"nsigmaTPCHe", 5.f, "Value of the Nsigma TPC cut for helium-3"}; } nsigmaTPCvar; - Configurable> cfgBetheBlochParams{"cfgBetheBlochParams", {betheBlochDefault[0], nParticles, nBetheParams, particleNames, betheBlochParNames}, "TPC Bethe-Bloch parameterisation for light nuclei"}; + Configurable> cfgBetheBlochParams{"cfgBetheBlochParams", {BetheBlochDefault[0], nParticles, nBetheParams, particleNames, betheBlochParNames}, "TPC Bethe-Bloch parameterisation for light nuclei"}; void init(o2::framework::InitContext&) { @@ -663,12 +665,14 @@ struct TrHeAnalysis { constexpr int NNumLayers = 8; constexpr int NBitsPerLayer = 4; constexpr int NBitMask = (1 << NBitsPerLayer) - 1; + int sum = 0, n = 0; for (int i = 0; i < NNumLayers; i++) { int clsSize = (track.itsClusterSizes() >> (NBitsPerLayer * i)) & NBitMask; sum += clsSize; - if (clsSize) + if (clsSize) { n++; + } } return n > 0 ? static_cast(sum) / n : 0.f; } @@ -681,13 +685,34 @@ struct TrHeAnalysis { return hePID ? track.tpcInnerParam() / 2 : track.tpcInnerParam(); } template - float getMass(T const& track) + float getMass(const T& track) { - const float beta = track.beta(); - const float rigidity = getRigidity(track); - float gamma = 1 / std::sqrt(1 - beta * beta); - float mass = (rigidity / std::sqrt(gamma * gamma - 1)); - return mass; + if (cfgMassMethod == 0) { + return track.mass(); + } + if (cfgMassMethod == 1) { + const float beta = track.beta(); + const float rigidity = getRigidity(track); + float gamma = 1 / std::sqrt(1 - beta * beta); + float mass = (rigidity / std::sqrt(gamma * gamma - 1.f)); + return mass; + } + if (cfgMassMethod == 2) { + const float rigidity = getRigidity(track); + float tofStartTime = track.evTimeForTrack(); + float tofTime = track.tofSignal(); + constexpr float CInCmPs = 2.99792458e-2f; + float length = track.length(); + float time = tofTime - tofStartTime; + if (time > 0.f && length > 0.f) { + float beta = length / (CInCmPs * time); + float gamma = 1 / std::sqrt(1 - beta * beta); + float mass = rigidity / std::sqrt(gamma * gamma - 1.f); + return mass; + } + return -1.f; + } + return -1.f; } }; From 8970fedaaefef8f5c4e36d7381e21cc22861b2c9 Mon Sep 17 00:00:00 2001 From: Daiki Sekihata Date: Tue, 10 Jun 2025 00:27:03 +0200 Subject: [PATCH 009/871] [PWGEM/Dilepton] update dimuon analyses (#11526) --- PWGEM/Dilepton/Core/DielectronCut.h | 16 +- PWGEM/Dilepton/Core/Dilepton.h | 6 + PWGEM/Dilepton/Core/DileptonMC.h | 6 + PWGEM/Dilepton/Core/DimuonCut.cxx | 16 ++ PWGEM/Dilepton/Core/DimuonCut.h | 25 +++ PWGEM/Dilepton/Core/SingleTrackQC.h | 14 ++ PWGEM/Dilepton/Core/SingleTrackQCMC.h | 12 ++ .../treeCreatorElectronMLDDA.cxx | 177 ++++++++++-------- PWGEM/Dilepton/Tasks/createResolutionMap.cxx | 27 ++- PWGEM/Dilepton/Utils/EMTrackUtilities.h | 26 ++- 10 files changed, 226 insertions(+), 99 deletions(-) diff --git a/PWGEM/Dilepton/Core/DielectronCut.h b/PWGEM/Dilepton/Core/DielectronCut.h index 9ad54af870c..eec8c0928b9 100644 --- a/PWGEM/Dilepton/Core/DielectronCut.h +++ b/PWGEM/Dilepton/Core/DielectronCut.h @@ -359,13 +359,13 @@ class DielectronCut : public TNamed { switch (cut) { case DielectronCuts::kTrackPtRange: - return track.pt() >= mMinTrackPt && track.pt() <= mMaxTrackPt; + return track.pt() > mMinTrackPt && track.pt() < mMaxTrackPt; case DielectronCuts::kTrackEtaRange: - return track.eta() >= mMinTrackEta && track.eta() <= mMaxTrackEta; + return track.eta() > mMinTrackEta && track.eta() < mMaxTrackEta; case DielectronCuts::kTrackPhiRange: - return track.phi() >= mMinTrackPhi && track.phi() <= mMaxTrackPhi; + return track.phi() > mMinTrackPhi && track.phi() < mMaxTrackPhi; case DielectronCuts::kTPCNCls: return track.tpcNClsFound() >= mMinNClustersTPC; @@ -374,10 +374,10 @@ class DielectronCut : public TNamed return track.tpcNClsCrossedRows() >= mMinNCrossedRowsTPC; case DielectronCuts::kTPCCrossedRowsOverNCls: - return track.tpcCrossedRowsOverFindableCls() >= mMinNCrossedRowsOverFindableClustersTPC; + return track.tpcCrossedRowsOverFindableCls() > mMinNCrossedRowsOverFindableClustersTPC; case DielectronCuts::kTPCFracSharedClusters: - return track.tpcFractionSharedCls() <= mMaxFracSharedClustersTPC; + return track.tpcFractionSharedCls() < mMaxFracSharedClustersTPC; case DielectronCuts::kRelDiffPin: return mMinRelDiffPin < (track.tpcInnerParam() - track.p()) / track.p() && (track.tpcInnerParam() - track.p()) / track.p() < mMaxRelDiffPin; @@ -386,13 +386,13 @@ class DielectronCut : public TNamed return mMinChi2PerClusterTPC < track.tpcChi2NCl() && track.tpcChi2NCl() < mMaxChi2PerClusterTPC; case DielectronCuts::kDCA3Dsigma: - return mMinDca3D <= dca3DinSigma(track) && dca3DinSigma(track) <= mMaxDca3D; // in sigma for single leg + return mMinDca3D < dca3DinSigma(track) && dca3DinSigma(track) < mMaxDca3D; // in sigma for single leg case DielectronCuts::kDCAxy: - return std::fabs(track.dcaXY()) <= ((mMaxDcaXYPtDep) ? mMaxDcaXYPtDep(track.pt()) : mMaxDcaXY); + return std::fabs(track.dcaXY()) < ((mMaxDcaXYPtDep) ? mMaxDcaXYPtDep(track.pt()) : mMaxDcaXY); case DielectronCuts::kDCAz: - return std::fabs(track.dcaZ()) <= mMaxDcaZ; + return std::fabs(track.dcaZ()) < mMaxDcaZ; case DielectronCuts::kITSNCls: return mMinNClustersITS <= track.itsNCls() && track.itsNCls() <= mMaxNClustersITS; diff --git a/PWGEM/Dilepton/Core/Dilepton.h b/PWGEM/Dilepton/Core/Dilepton.h index 95bd4a0b6f8..46cecc81c87 100644 --- a/PWGEM/Dilepton/Core/Dilepton.h +++ b/PWGEM/Dilepton/Core/Dilepton.h @@ -281,6 +281,10 @@ struct Dilepton { Configurable cfg_min_rabs{"cfg_min_rabs", 17.6, "min Radius at the absorber end"}; Configurable cfg_max_rabs{"cfg_max_rabs", 89.5, "max Radius at the absorber end"}; Configurable enableTTCA{"enableTTCA", true, "Flag to enable or disable TTCA"}; + Configurable cfg_max_relDPt_wrt_matchedMCHMID{"cfg_max_relDPt_wrt_matchedMCHMID", 1e+10f, "max. relative dpt between MFT-MCH-MID and MCH-MID"}; + Configurable cfg_max_DEta_wrt_matchedMCHMID{"cfg_max_DEta_wrt_matchedMCHMID", 1e+10f, "max. deta between MFT-MCH-MID and MCH-MID"}; + Configurable cfg_max_DPhi_wrt_matchedMCHMID{"cfg_max_DPhi_wrt_matchedMCHMID", 1e+10f, "max. dphi between MFT-MCH-MID and MCH-MID"}; + Configurable> requiredMFTDisks{"requiredMFTDisks", std::vector{0}, "hit map on MFT disks [0,1,2,3,4]. logical-OR of each double-sided disk"}; } dimuoncuts; o2::aod::rctsel::RCTFlagsChecker rctChecker; @@ -749,6 +753,8 @@ struct Dilepton { fDimuonCut.SetDCAxy(0.f, dimuoncuts.cfg_max_dcaxy); fDimuonCut.SetRabs(dimuoncuts.cfg_min_rabs, dimuoncuts.cfg_max_rabs); fDimuonCut.SetMaxPDCARabsDep([&](float rabs) { return (rabs < 26.5 ? 594.f : 324.f); }); + fDimuonCut.SetMaxdPtdEtadPhiwrtMCHMID(dimuoncuts.cfg_max_relDPt_wrt_matchedMCHMID, dimuoncuts.cfg_max_DEta_wrt_matchedMCHMID, dimuoncuts.cfg_max_DPhi_wrt_matchedMCHMID); // this is relevant for global muons + fDimuonCut.SetMFTHitMap(dimuoncuts.requiredMFTDisks); } template diff --git a/PWGEM/Dilepton/Core/DileptonMC.h b/PWGEM/Dilepton/Core/DileptonMC.h index 769c6b72ec3..00cec907de5 100644 --- a/PWGEM/Dilepton/Core/DileptonMC.h +++ b/PWGEM/Dilepton/Core/DileptonMC.h @@ -273,6 +273,10 @@ struct DileptonMC { Configurable cfg_min_rabs{"cfg_min_rabs", 17.6, "min Radius at the absorber end"}; Configurable cfg_max_rabs{"cfg_max_rabs", 89.5, "max Radius at the absorber end"}; Configurable enableTTCA{"enableTTCA", true, "Flag to enable or disable TTCA"}; + Configurable cfg_max_relDPt_wrt_matchedMCHMID{"cfg_max_relDPt_wrt_matchedMCHMID", 1e+10f, "max. relative dpt between MFT-MCH-MID and MCH-MID"}; + Configurable cfg_max_DEta_wrt_matchedMCHMID{"cfg_max_DEta_wrt_matchedMCHMID", 1e+10f, "max. deta between MFT-MCH-MID and MCH-MID"}; + Configurable cfg_max_DPhi_wrt_matchedMCHMID{"cfg_max_DPhi_wrt_matchedMCHMID", 1e+10f, "max. dphi between MFT-MCH-MID and MCH-MID"}; + Configurable> requiredMFTDisks{"requiredMFTDisks", std::vector{0}, "hit map on MFT disks [0,1,2,3,4]. logical-OR of each double-sided disk"}; } dimuoncuts; o2::aod::rctsel::RCTFlagsChecker rctChecker; @@ -715,6 +719,8 @@ struct DileptonMC { fDimuonCut.SetDCAxy(0.f, dimuoncuts.cfg_max_dcaxy); fDimuonCut.SetRabs(dimuoncuts.cfg_min_rabs, dimuoncuts.cfg_max_rabs); fDimuonCut.SetMaxPDCARabsDep([&](float rabs) { return (rabs < 26.5 ? 594.f : 324.f); }); + fDimuonCut.SetMaxdPtdEtadPhiwrtMCHMID(dimuoncuts.cfg_max_relDPt_wrt_matchedMCHMID, dimuoncuts.cfg_max_DEta_wrt_matchedMCHMID, dimuoncuts.cfg_max_DPhi_wrt_matchedMCHMID); // this is relevant for global muons + fDimuonCut.SetMFTHitMap(dimuoncuts.requiredMFTDisks); } template diff --git a/PWGEM/Dilepton/Core/DimuonCut.cxx b/PWGEM/Dilepton/Core/DimuonCut.cxx index ee18a8e4232..5ee3bf3d3bd 100644 --- a/PWGEM/Dilepton/Core/DimuonCut.cxx +++ b/PWGEM/Dilepton/Core/DimuonCut.cxx @@ -119,3 +119,19 @@ void DimuonCut::SetMaxPDCARabsDep(std::function RabsDepCut) mMaxPDCARabsDep = RabsDepCut; LOG(info) << "Dimuon Cut, set max pDCA as a function of Rabs: " << mMaxPDCARabsDep(10.0); } +void DimuonCut::SetMFTHitMap(std::vector hitMap) +{ + mRequiredMFTDisks = hitMap; + for (const auto& iDisk : mRequiredMFTDisks) { + LOG(info) << "Dimuon Cut, require MFT hit on Disk: " << iDisk; + } +} +void DimuonCut::SetMaxdPtdEtadPhiwrtMCHMID(float reldPtMax, float dEtaMax, float dPhiMax) +{ + mMaxReldPtwrtMCHMID = reldPtMax; + mMaxdEtawrtMCHMID = dEtaMax; + mMaxdPhiwrtMCHMID = dPhiMax; + LOG(info) << "Dimuon Cut, set max rel. dpt between MFT-MCH-MID and associated MCH-MID: " << mMaxReldPtwrtMCHMID; + LOG(info) << "Dimuon Cut, set max deta between MFT-MCH-MID and associated MCH-MID: " << mMaxdEtawrtMCHMID; + LOG(info) << "Dimuon Cut, set max dphi between MFT-MCH-MID and associated MCH-MID: " << mMaxdPhiwrtMCHMID; +} diff --git a/PWGEM/Dilepton/Core/DimuonCut.h b/PWGEM/Dilepton/Core/DimuonCut.h index 4bb854c6b73..34d8364f65b 100644 --- a/PWGEM/Dilepton/Core/DimuonCut.h +++ b/PWGEM/Dilepton/Core/DimuonCut.h @@ -59,6 +59,8 @@ class DimuonCut : public TNamed kMatchingChi2MCHMID, kRabs, kPDCA, + kMFTHitMap, + kDPtDEtaDPhiwrtMCHMID, kNCuts }; @@ -154,6 +156,12 @@ class DimuonCut : public TNamed if (!IsSelectedTrack(track, DimuonCuts::kRabs)) { return false; } + if (track.trackType() == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) && !IsSelectedTrack(track, DimuonCuts::kMFTHitMap)) { + return false; + } + if (track.trackType() == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) && !IsSelectedTrack(track, DimuonCuts::kDPtDEtaDPhiwrtMCHMID)) { + return false; + } return true; } @@ -198,6 +206,19 @@ class DimuonCut : public TNamed case DimuonCuts::kRabs: return mMinRabs < track.rAtAbsorberEnd() && track.rAtAbsorberEnd() < mMaxRabs; + case DimuonCuts::kMFTHitMap: { + std::vector mftHitMap{checkMFTHitMap<0, 1>(track), checkMFTHitMap<2, 3>(track), checkMFTHitMap<4, 5>(track), checkMFTHitMap<6, 7>(track), checkMFTHitMap<8, 9>(track)}; + for (const auto& iDisk : mRequiredMFTDisks) { + if (!mftHitMap[iDisk]) { + return false; + } + } + return true; + } + + case DimuonCuts::kDPtDEtaDPhiwrtMCHMID: + return std::fabs(track.ptMatchedMCHMID() - track.pt()) / track.pt() < mMaxReldPtwrtMCHMID && std::sqrt(std::pow((track.etaMatchedMCHMID() - track.eta()) / mMaxdEtawrtMCHMID, 2) + std::pow((track.phiMatchedMCHMID() - track.phi()) / mMaxdPhiwrtMCHMID, 2)) < 1.f; + default: return false; } @@ -222,6 +243,8 @@ class DimuonCut : public TNamed void SetDCAxy(float min, float max); // in cm void SetRabs(float min, float max); // in cm void SetMaxPDCARabsDep(std::function RabsDepCut); + void SetMFTHitMap(std::vector hitMap); + void SetMaxdPtdEtadPhiwrtMCHMID(float reldPtMax, float dEtaMax, float dPhiMax); // this is relevant for global muons private: // pair cuts @@ -249,6 +272,8 @@ class DimuonCut : public TNamed float mMinRabs{17.6}, mMaxRabs{89.5}; float mMinDcaXY{0.0f}, mMaxDcaXY{1e10f}; + float mMaxReldPtwrtMCHMID{1e10f}, mMaxdEtawrtMCHMID{1e10f}, mMaxdPhiwrtMCHMID{1e10f}; + std::vector mRequiredMFTDisks{}; ClassDef(DimuonCut, 1); }; diff --git a/PWGEM/Dilepton/Core/SingleTrackQC.h b/PWGEM/Dilepton/Core/SingleTrackQC.h index f5f8be20518..2fc94a8a91c 100644 --- a/PWGEM/Dilepton/Core/SingleTrackQC.h +++ b/PWGEM/Dilepton/Core/SingleTrackQC.h @@ -201,6 +201,10 @@ struct SingleTrackQC { Configurable cfg_min_rabs{"cfg_min_rabs", 17.6, "min Radius at the absorber end"}; Configurable cfg_max_rabs{"cfg_max_rabs", 89.5, "max Radius at the absorber end"}; Configurable enableTTCA{"enableTTCA", true, "Flag to enable or disable TTCA"}; + Configurable cfg_max_relDPt_wrt_matchedMCHMID{"cfg_max_relDPt_wrt_matchedMCHMID", 1e+10f, "max. relative dpt between MFT-MCH-MID and MCH-MID"}; + Configurable cfg_max_DEta_wrt_matchedMCHMID{"cfg_max_DEta_wrt_matchedMCHMID", 1e+10f, "max. deta between MFT-MCH-MID and MCH-MID"}; + Configurable cfg_max_DPhi_wrt_matchedMCHMID{"cfg_max_DPhi_wrt_matchedMCHMID", 1e+10f, "max. dphi between MFT-MCH-MID and MCH-MID"}; + Configurable> requiredMFTDisks{"requiredMFTDisks", std::vector{0}, "hit map on MFT disks [0,1,2,3,4]. logical-OR of each double-sided disk"}; } dimuoncuts; o2::aod::rctsel::RCTFlagsChecker rctChecker; @@ -282,6 +286,7 @@ struct SingleTrackQC { // track info fRegistry.add("Track/positive/hs", "rec. single muon", kTHnSparseD, {axis_pt, axis_eta, axis_phi, axis_dca}, true); fRegistry.add("Track/positive/hEtaPhi_MatchMCHMID", "#eta vs. #varphi of matched MCHMID", kTH2F, {{180, 0, 2.f * M_PI}, {100, -6, -1}}, false); + fRegistry.add("Track/positive/hdEtadPhi", "#Delta#eta vs. #Delta#varphi between MFT-MCH-MID and MCH-MID;#varphi_{sa} - #varphi_{gl} (rad.);#eta_{sa} - #eta_{gl}", kTH2F, {{90, -M_PI / 4, M_PI / 4}, {100, -0.5, +0.5}}, false); fRegistry.add("Track/positive/hQoverPt", "q/pT;q/p_{T} (GeV/c)^{-1}", kTH1F, {{400, -20, 20}}, false); fRegistry.add("Track/positive/hTrackType", "track type", kTH1F, {{6, -0.5f, 5.5}}, false); fRegistry.add("Track/positive/hDCAxy", "DCA x vs. y;DCA_{x} (cm);DCA_{y} (cm)", kTH2F, {{200, -0.5f, 0.5f}, {200, -0.5f, 0.5f}}, false); @@ -452,6 +457,8 @@ struct SingleTrackQC { fDimuonCut.SetDCAxy(0.f, dimuoncuts.cfg_max_dcaxy); fDimuonCut.SetRabs(dimuoncuts.cfg_min_rabs, dimuoncuts.cfg_max_rabs); fDimuonCut.SetMaxPDCARabsDep([&](float rabs) { return (rabs < 26.5 ? 594.f : 324.f); }); + fDimuonCut.SetMaxdPtdEtadPhiwrtMCHMID(dimuoncuts.cfg_max_relDPt_wrt_matchedMCHMID, dimuoncuts.cfg_max_DEta_wrt_matchedMCHMID, dimuoncuts.cfg_max_DPhi_wrt_matchedMCHMID); // this is relevant for global muons + fDimuonCut.SetMFTHitMap(dimuoncuts.requiredMFTDisks); } template @@ -560,9 +567,15 @@ struct SingleTrackQC { weight = map_weight[track.globalIndex()]; } float dca_xy = fwdDcaXYinSigma(track); + + float deta = track.etaMatchedMCHMID() - track.eta(); + float dphi = track.phiMatchedMCHMID() - track.phi(); + o2::math_utils::bringToPMPi(dphi); + if (track.sign() > 0) { fRegistry.fill(HIST("Track/positive/hs"), track.pt(), track.eta(), track.phi(), dca_xy, weight); fRegistry.fill(HIST("Track/positive/hEtaPhi_MatchMCHMID"), track.phiMatchedMCHMID(), track.etaMatchedMCHMID(), weight); + fRegistry.fill(HIST("Track/positive/hdEtadPhi"), dphi, deta, weight); fRegistry.fill(HIST("Track/positive/hQoverPt"), track.sign() / track.pt()); fRegistry.fill(HIST("Track/positive/hTrackType"), track.trackType()); fRegistry.fill(HIST("Track/positive/hDCAxy"), track.fwdDcaX(), track.fwdDcaY()); @@ -580,6 +593,7 @@ struct SingleTrackQC { } else { fRegistry.fill(HIST("Track/negative/hs"), track.pt(), track.eta(), track.phi(), dca_xy, weight); fRegistry.fill(HIST("Track/negative/hEtaPhi_MatchMCHMID"), track.phiMatchedMCHMID(), track.etaMatchedMCHMID(), weight); + fRegistry.fill(HIST("Track/negative/hdEtadPhi"), dphi, deta, weight); fRegistry.fill(HIST("Track/negative/hQoverPt"), track.sign() / track.pt()); fRegistry.fill(HIST("Track/negative/hTrackType"), track.trackType()); fRegistry.fill(HIST("Track/negative/hDCAxy"), track.fwdDcaX(), track.fwdDcaY()); diff --git a/PWGEM/Dilepton/Core/SingleTrackQCMC.h b/PWGEM/Dilepton/Core/SingleTrackQCMC.h index f400b617f1f..481bb2e9e5e 100644 --- a/PWGEM/Dilepton/Core/SingleTrackQCMC.h +++ b/PWGEM/Dilepton/Core/SingleTrackQCMC.h @@ -207,6 +207,10 @@ struct SingleTrackQCMC { Configurable cfg_min_rabs{"cfg_min_rabs", 17.6, "min Radius at the absorber end"}; Configurable cfg_max_rabs{"cfg_max_rabs", 89.5, "max Radius at the absorber end"}; Configurable enableTTCA{"enableTTCA", true, "Flag to enable or disable TTCA"}; + Configurable cfg_max_relDPt_wrt_matchedMCHMID{"cfg_max_relDPt_wrt_matchedMCHMID", 1e+10f, "max. relative dpt between MFT-MCH-MID and MCH-MID"}; + Configurable cfg_max_DEta_wrt_matchedMCHMID{"cfg_max_DEta_wrt_matchedMCHMID", 1e+10f, "max. deta between MFT-MCH-MID and MCH-MID"}; + Configurable cfg_max_DPhi_wrt_matchedMCHMID{"cfg_max_DPhi_wrt_matchedMCHMID", 1e+10f, "max. dphi between MFT-MCH-MID and MCH-MID"}; + Configurable> requiredMFTDisks{"requiredMFTDisks", std::vector{0}, "hit map on MFT disks [0,1,2,3,4]. logical-OR of each double-sided disk"}; } dimuoncuts; o2::aod::rctsel::RCTFlagsChecker rctChecker; @@ -339,6 +343,7 @@ struct SingleTrackQCMC { fRegistry.add("Track/lf/positive/hs", "rec. single muon", kTHnSparseD, {axis_pt, axis_eta, axis_phi, axis_dca, axis_charge_gen}, true); if (cfgFillQA) { fRegistry.add("Track/lf/positive/hEtaPhi_MatchMCHMID", "#eta vs. #varphi of matched MCHMID", kTH2F, {{180, 0, 2.f * M_PI}, {100, -6, -1}}, false); + fRegistry.add("Track/lf/positive/hdEtadPhi", "#Delta#eta vs. #Delta#varphi between MFT-MCH-MID and MCH-MID;#varphi_{sa} - #varphi_{gl} (rad.);#eta_{sa} - #eta_{gl}", kTH2F, {{90, -M_PI / 4, M_PI / 4}, {100, -0.5, +0.5}}, false); fRegistry.add("Track/lf/positive/hQoverPt", "q/pT;q/p_{T} (GeV/c)^{-1}", kTH1F, {{400, -20, 20}}, false); fRegistry.add("Track/lf/positive/hTrackType", "track type", kTH1F, {{6, -0.5f, 5.5}}, false); fRegistry.add("Track/lf/positive/hDCAxy", "DCA x vs. y;DCA_{x} (cm);DCA_{y} (cm)", kTH2F, {{200, -0.5f, 0.5f}, {200, -0.5f, 0.5f}}, false); @@ -511,6 +516,8 @@ struct SingleTrackQCMC { fDimuonCut.SetDCAxy(0.f, dimuoncuts.cfg_max_dcaxy); fDimuonCut.SetRabs(dimuoncuts.cfg_min_rabs, dimuoncuts.cfg_max_rabs); fDimuonCut.SetMaxPDCARabsDep([&](float rabs) { return (rabs < 26.5 ? 594.f : 324.f); }); + fDimuonCut.SetMaxdPtdEtadPhiwrtMCHMID(dimuoncuts.cfg_max_relDPt_wrt_matchedMCHMID, dimuoncuts.cfg_max_DEta_wrt_matchedMCHMID, dimuoncuts.cfg_max_DPhi_wrt_matchedMCHMID); // this is relevant for global muons + fDimuonCut.SetMFTHitMap(dimuoncuts.requiredMFTDisks); } template @@ -670,6 +677,9 @@ struct SingleTrackQCMC { { auto mctrack = track.template emmcparticle_as(); float dca_xy = fwdDcaXYinSigma(track); + float deta = track.etaMatchedMCHMID() - track.eta(); + float dphi = track.phiMatchedMCHMID() - track.phi(); + o2::math_utils::bringToPMPi(dphi); float weight = 1.f; if (cfgApplyWeightTTCA) { @@ -681,6 +691,7 @@ struct SingleTrackQCMC { fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hs"), track.pt(), track.eta(), track.phi(), dca_xy, -mctrack.pdgCode() / pdg_lepton, weight); if (cfgFillQA) { fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hEtaPhi_MatchMCHMID"), track.phiMatchedMCHMID(), track.etaMatchedMCHMID(), weight); + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hdEtadPhi"), dphi, deta, weight); fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hQoverPt"), track.sign() / track.pt()); fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hTrackType"), track.trackType()); fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hDCAxy"), track.fwdDcaX(), track.fwdDcaY()); @@ -703,6 +714,7 @@ struct SingleTrackQCMC { fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hs"), track.pt(), track.eta(), track.phi(), dca_xy, -mctrack.pdgCode() / pdg_lepton, weight); if (cfgFillQA) { fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hEtaPhi_MatchMCHMID"), track.phiMatchedMCHMID(), track.etaMatchedMCHMID(), weight); + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hdEtadPhi"), dphi, deta, weight); fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hQoverPt"), track.sign() / track.pt()); fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hTrackType"), track.trackType()); fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hDCAxy"), track.fwdDcaX(), track.fwdDcaY()); diff --git a/PWGEM/Dilepton/TableProducer/treeCreatorElectronMLDDA.cxx b/PWGEM/Dilepton/TableProducer/treeCreatorElectronMLDDA.cxx index a24b62374f8..a0c7b6362f7 100644 --- a/PWGEM/Dilepton/TableProducer/treeCreatorElectronMLDDA.cxx +++ b/PWGEM/Dilepton/TableProducer/treeCreatorElectronMLDDA.cxx @@ -54,7 +54,7 @@ using namespace o2::constants::physics; using MyCollisions = soa::Join; using MyCollision = MyCollisions::iterator; -using MyTracks = soa::Join; using MyTrack = MyTracks::iterator; @@ -77,19 +77,18 @@ struct TreeCreatorElectronMLDDA { {"V0/hMassK0Short", "V0 mass K0S", {HistType::kTH1F, {{200, 0.4, 0.6}}}}, {"V0/hMassLambda", "V0 mass Lambda", {HistType::kTH1F, {{100, 1.08, 1.18}}}}, {"V0/hMassAntiLambda", "V0 mass AntiLambda", {HistType::kTH1F, {{100, 1.08, 1.18}}}}, - {"hMvsPhiV", "mee vs. phiv", {HistType::kTH2F, {{72, 0, M_PI}, {100, 0, 0.1}}}}, - - {"V0/hTPCdEdx_P_El", "TPC dEdx vs. p;p^{ITS-TPC} (GeV/c);TPC dE/dx", {HistType::kTH2F, {{500, 0, 5}, {200, 0, 200}}}}, - {"V0/hTPCdEdx_P_Mu", "TPC dEdx vs. p;p^{ITS-TPC} (GeV/c);TPC dE/dx", {HistType::kTH2F, {{500, 0, 5}, {200, 0, 200}}}}, - {"V0/hTPCdEdx_P_Pi", "TPC dEdx vs. p;p^{ITS-TPC} (GeV/c);TPC dE/dx", {HistType::kTH2F, {{500, 0, 5}, {200, 0, 200}}}}, - {"V0/hTPCdEdx_P_Ka", "TPC dEdx vs. p;p^{ITS-TPC} (GeV/c);TPC dE/dx", {HistType::kTH2F, {{500, 0, 5}, {200, 0, 200}}}}, - {"V0/hTPCdEdx_P_Pr", "TPC dEdx vs. p;p^{ITS-TPC} (GeV/c);TPC dE/dx", {HistType::kTH2F, {{500, 0, 5}, {200, 0, 200}}}}, - - {"V0/hTOFbeta_P_El", "TOF beta vs. p;p^{ITS-TPC} (GeV/c);TOF #beta", {HistType::kTH2F, {{500, 0, 5}, {220, 0, 1.1}}}}, - {"V0/hTOFbeta_P_Mu", "TOF beta vs. p;p^{ITS-TPC} (GeV/c);TOF #beta", {HistType::kTH2F, {{500, 0, 5}, {220, 0, 1.1}}}}, - {"V0/hTOFbeta_P_Pi", "TOF beta vs. p;p^{ITS-TPC} (GeV/c);TOF #beta", {HistType::kTH2F, {{500, 0, 5}, {220, 0, 1.1}}}}, - {"V0/hTOFbeta_P_Ka", "TOF beta vs. p;p^{ITS-TPC} (GeV/c);TOF #beta", {HistType::kTH2F, {{500, 0, 5}, {220, 0, 1.1}}}}, - {"V0/hTOFbeta_P_Pr", "TOF beta vs. p;p^{ITS-TPC} (GeV/c);TOF #beta", {HistType::kTH2F, {{500, 0, 5}, {220, 0, 1.1}}}}, + {"hMvsPhiV", "m_{ee} vs. #varphi_{V};#varphi_{V} (rad.);m_{ee} (GeV/c^{2})", {HistType::kTH2F, {{90, 0, M_PI}, {100, 0, 0.1}}}}, + + {"V0/hTPCdEdx_P_El", "TPC dEdx vs. p;p_{in} (GeV/c);TPC dE/dx", {HistType::kTH2F, {{500, 0, 5}, {200, 0, 200}}}}, + {"V0/hTPCdEdx_P_Mu", "TPC dEdx vs. p;p_{in} (GeV/c);TPC dE/dx", {HistType::kTH2F, {{500, 0, 5}, {200, 0, 200}}}}, + {"V0/hTPCdEdx_P_Pi", "TPC dEdx vs. p;p_{in} (GeV/c);TPC dE/dx", {HistType::kTH2F, {{500, 0, 5}, {200, 0, 200}}}}, + {"V0/hTPCdEdx_P_Ka", "TPC dEdx vs. p;p_{in} (GeV/c);TPC dE/dx", {HistType::kTH2F, {{500, 0, 5}, {200, 0, 200}}}}, + {"V0/hTPCdEdx_P_Pr", "TPC dEdx vs. p;p_{in} (GeV/c);TPC dE/dx", {HistType::kTH2F, {{500, 0, 5}, {200, 0, 200}}}}, + {"V0/hTOFbeta_P_El", "TOF beta vs. p;p_{in} (GeV/c);TOF #beta", {HistType::kTH2F, {{500, 0, 5}, {220, 0, 1.1}}}}, + {"V0/hTOFbeta_P_Mu", "TOF beta vs. p;p_{in} (GeV/c);TOF #beta", {HistType::kTH2F, {{500, 0, 5}, {220, 0, 1.1}}}}, + {"V0/hTOFbeta_P_Pi", "TOF beta vs. p;p_{in} (GeV/c);TOF #beta", {HistType::kTH2F, {{500, 0, 5}, {220, 0, 1.1}}}}, + {"V0/hTOFbeta_P_Ka", "TOF beta vs. p;p_{in} (GeV/c);TOF #beta", {HistType::kTH2F, {{500, 0, 5}, {220, 0, 1.1}}}}, + {"V0/hTOFbeta_P_Pr", "TOF beta vs. p;p_{in} (GeV/c);TOF #beta", {HistType::kTH2F, {{500, 0, 5}, {220, 0, 1.1}}}}, {"Cascade/hRxy_Xi", "R_{xy} of cascade vs. mass;m_{#Lambda#pi};R_{xy} (cm)", {HistType::kTH2F, {{200, 1.2, 1.4}, {200, 0, 20.f}}}}, {"Cascade/hRxy_Omega", "R_{xy} of cascade vs. mass;m_{#LambdaK};R_{xy} (cm)", {HistType::kTH2F, {{200, 1.6, 1.8}, {200, 0, 20.f}}}}, @@ -103,9 +102,7 @@ struct TreeCreatorElectronMLDDA { {"Cascade/hMassXi", "cascade mass #Xi", {HistType::kTH1F, {{200, 1.2, 1.4}}}}, {"Cascade/hMassOmega", "cascade mass #Omega", {HistType::kTH1F, {{200, 1.6, 1.8}}}}, {"Cascade/hMassPt_Xi", "cascade mass #Xi^{#pm};m_{#Lambda#pi} (GeV/c^{2});p_{T,#Lambda#pi} (GeV/c)", {HistType::kTH2F, {{200, 1.2, 1.4}, {100, 0, 10}}}}, - {"Cascade/hMassPt_Xi_bachelor", "cascade mass #Xi^{#pm};m_{#Lambda#pi} (GeV/c^{2});p_{T,#pi} (GeV/c)", {HistType::kTH2F, {{200, 1.2, 1.4}, {100, 0, 10}}}}, {"Cascade/hMassPt_Omega", "cascade mass #Omega^{#pm};m_{#LambdaK} (GeV/c^{2});p_{T,#LambdaK} (GeV/c)", {HistType::kTH2F, {{200, 1.6, 1.8}, {100, 0, 10}}}}, - {"Cascade/hMassPt_Omega_bachelor", "cascade mass #Omega^{#pm};m_{#LambdaK} (GeV/c^{2});p_{T,K} (GeV/c)", {HistType::kTH2F, {{200, 1.6, 1.8}, {100, 0, 10}}}}, }, }; @@ -386,15 +383,15 @@ struct TreeCreatorElectronMLDDA { } mDcaInfoCov.set(999, 999, 999, 999, 999); - auto track_par_cov_recalc = getTrackParCov(track); - track_par_cov_recalc.setPID(track.pidForTracking()); + auto trackParCov = getTrackParCov(track); + trackParCov.setPID(track.pidForTracking()); 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, track_par_cov_recalc, 2.f, matCorr, &mDcaInfoCov); + o2::base::Propagator::Instance()->propagateToDCABxByBz(mVtx, trackParCov, 2.f, matCorr, &mDcaInfoCov); float dcaXY = mDcaInfoCov.getY(); float dcaZ = mDcaInfoCov.getZ(); - if (std::fabs(track_par_cov_recalc.getEta()) > trackcuts.cfg_max_eta || track_par_cov_recalc.getPt() < trackcuts.cfg_min_pt) { + if (std::fabs(trackParCov.getEta()) > trackcuts.cfg_max_eta || trackParCov.getPt() < trackcuts.cfg_min_pt) { return false; } @@ -442,15 +439,15 @@ struct TreeCreatorElectronMLDDA { } mDcaInfoCov.set(999, 999, 999, 999, 999); - auto track_par_cov_recalc = getTrackParCov(track); - track_par_cov_recalc.setPID(track.pidForTracking()); + auto trackParCov = getTrackParCov(track); + trackParCov.setPID(track.pidForTracking()); 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, track_par_cov_recalc, 2.f, matCorr, &mDcaInfoCov); + o2::base::Propagator::Instance()->propagateToDCABxByBz(mVtx, trackParCov, 2.f, matCorr, &mDcaInfoCov); float dcaXY = mDcaInfoCov.getY(); // float dcaZ = mDcaInfoCov.getZ(); - if (std::fabs(track_par_cov_recalc.getEta()) > v0cuts.cfg_max_eta || track_par_cov_recalc.getPt() < v0cuts.cfg_min_pt) { + if (std::fabs(trackParCov.getEta()) > v0cuts.cfg_max_eta || trackParCov.getPt() < v0cuts.cfg_min_pt) { return false; } @@ -526,17 +523,17 @@ struct TreeCreatorElectronMLDDA { if (std::find(stored_trackIds.begin(), stored_trackIds.end(), track.globalIndex()) == stored_trackIds.end()) { mDcaInfoCov.set(999, 999, 999, 999, 999); - auto track_par_cov_recalc = getTrackParCov(track); - track_par_cov_recalc.setPID(track.pidForTracking()); + auto trackParCov = getTrackParCov(track); + trackParCov.setPID(track.pidForTracking()); 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, track_par_cov_recalc, 2.f, matCorr, &mDcaInfoCov); + o2::base::Propagator::Instance()->propagateToDCABxByBz(mVtx, trackParCov, 2.f, matCorr, &mDcaInfoCov); float dcaXY = mDcaInfoCov.getY(); float dcaZ = mDcaInfoCov.getZ(); emprimarytracks(collision.globalIndex(), collision.posZ(), collision.numContrib(), collision.trackOccupancyInTimeRange(), collision.ft0cOccupancyInTimeRange(), - track.pt(), track.eta(), track.phi(), track.tgl(), track.signed1Pt(), - dcaXY, dcaZ, track_par_cov_recalc.getSigmaY2(), track_par_cov_recalc.getSigmaZ2(), track_par_cov_recalc.getSigmaZY(), + trackParCov.getPt(), trackParCov.getEta(), trackParCov.getPhi() > 0.f ? trackParCov.getPhi() : trackParCov.getPhi() + 2 * M_PI, trackParCov.getTgl(), trackParCov.getQ2Pt(), + dcaXY, dcaZ, trackParCov.getSigmaY2(), trackParCov.getSigmaZ2(), trackParCov.getSigmaZY(), track.tpcNClsFindable(), track.tpcNClsFound(), track.tpcNClsCrossedRows(), track.tpcChi2NCl(), track.tpcInnerParam(), track.tpcSignal(), track.tpcNSigmaEl(), track.tpcNSigmaMu(), track.tpcNSigmaPi(), track.tpcNSigmaKa(), track.tpcNSigmaPr(), @@ -582,33 +579,32 @@ struct TreeCreatorElectronMLDDA { for (const auto& v0 : v0s_coll) { auto pos = v0.template posTrack_as(); auto neg = v0.template negTrack_as(); - if (!isSelectedV0Leg(collision, pos) || !isSelectedV0Leg(collision, neg)) { + // LOGF(info, "v0.globalIndex() = %d, v0.collisionId() = %d, v0.posTrackId() = %d, v0.negTrackId() = %d", v0.globalIndex(), v0.collisionId(), v0.posTrackId(), v0.negTrackId()); + + if (v0.dcaV0daughters() > v0cuts.cfg_max_dcadau) { + continue; + } + if (v0.v0cosPA() < v0cuts.cfg_min_cospa) { continue; } if (pos.sign() * neg.sign() > 0) { continue; } - - // LOGF(info, "v0.globalIndex() = %d, v0.collisionId() = %d, v0.posTrackId() = %d, v0.negTrackId() = %d", v0.globalIndex(), v0.collisionId(), v0.posTrackId(), v0.negTrackId()); + if (!isSelectedV0Leg(collision, pos) || !isSelectedV0Leg(collision, neg)) { + continue; + } registry.fill(HIST("V0/hPCA"), v0.dcaV0daughters()); registry.fill(HIST("V0/hCosPA"), v0.v0cosPA()); registry.fill(HIST("V0/hAP"), v0.alpha(), v0.qtarm()); - if (v0.dcaV0daughters() > v0cuts.cfg_max_dcadau) { - continue; - } - if (v0.v0cosPA() < v0cuts.cfg_min_cospa) { - continue; - } - if (isPion(pos) && isPion(neg)) { registry.fill(HIST("V0/hMassK0Short"), v0.mK0Short()); if (v0cuts.cfg_min_mass_k0s < v0.mK0Short() && v0.mK0Short() < v0cuts.cfg_max_mass_k0s) { - registry.fill(HIST("V0/hTPCdEdx_P_Pi"), neg.p(), neg.tpcSignal()); - registry.fill(HIST("V0/hTOFbeta_P_Pi"), neg.p(), neg.beta()); - registry.fill(HIST("V0/hTPCdEdx_P_Pi"), pos.p(), pos.tpcSignal()); - registry.fill(HIST("V0/hTOFbeta_P_Pi"), pos.p(), pos.beta()); + registry.fill(HIST("V0/hTPCdEdx_P_Pi"), neg.tpcInnerParam(), neg.tpcSignal()); + registry.fill(HIST("V0/hTOFbeta_P_Pi"), neg.tpcInnerParam(), neg.beta()); + registry.fill(HIST("V0/hTPCdEdx_P_Pi"), pos.tpcInnerParam(), pos.tpcSignal()); + registry.fill(HIST("V0/hTOFbeta_P_Pi"), pos.tpcInnerParam(), pos.beta()); if (dist01(engine) < downscaling_pion || pos.tpcInnerParam() > max_pin_for_downscaling_pion) { fillTrackTable(collision, pos, static_cast(o2::aod::pwgem::dilepton::PID_Label::kPion), static_cast(o2::aod::pwgem::dilepton::Track_Type::kSecondary), false); } @@ -623,8 +619,8 @@ struct TreeCreatorElectronMLDDA { if (dist01(engine) < downscaling_proton || pos.tpcInnerParam() > max_pin_for_downscaling_proton) { fillTrackTable(collision, pos, static_cast(o2::aod::pwgem::dilepton::PID_Label::kProton), static_cast(o2::aod::pwgem::dilepton::Track_Type::kSecondary), false); } - registry.fill(HIST("V0/hTPCdEdx_P_Pr"), pos.p(), pos.tpcSignal()); - registry.fill(HIST("V0/hTOFbeta_P_Pr"), pos.p(), pos.beta()); + registry.fill(HIST("V0/hTPCdEdx_P_Pr"), pos.tpcInnerParam(), pos.tpcSignal()); + registry.fill(HIST("V0/hTOFbeta_P_Pr"), pos.tpcInnerParam(), pos.beta()); } } if (isPionTight(pos) && isProton(neg)) { @@ -633,14 +629,14 @@ struct TreeCreatorElectronMLDDA { if (dist01(engine) < downscaling_proton || neg.tpcInnerParam() > max_pin_for_downscaling_proton) { fillTrackTable(collision, neg, static_cast(o2::aod::pwgem::dilepton::PID_Label::kProton), static_cast(o2::aod::pwgem::dilepton::Track_Type::kSecondary), false); } - registry.fill(HIST("V0/hTPCdEdx_P_Pr"), neg.p(), neg.tpcSignal()); - registry.fill(HIST("V0/hTOFbeta_P_Pr"), neg.p(), neg.beta()); + registry.fill(HIST("V0/hTPCdEdx_P_Pr"), neg.tpcInnerParam(), neg.tpcSignal()); + registry.fill(HIST("V0/hTOFbeta_P_Pr"), neg.tpcInnerParam(), neg.beta()); } } - registry.fill(HIST("V0/hMassGamma"), v0.mGamma()); - registry.fill(HIST("V0/hXY_Gamma"), v0.x(), v0.y()); - registry.fill(HIST("V0/hMassGamma_Rxy"), v0.v0radius(), v0.mGamma()); if (isElectron(pos) && isElectron(neg)) { + registry.fill(HIST("V0/hMassGamma"), v0.mGamma()); + registry.fill(HIST("V0/hXY_Gamma"), v0.x(), v0.y()); + registry.fill(HIST("V0/hMassGamma_Rxy"), v0.v0radius(), v0.mGamma()); if ((v0cuts.cfg_min_mass_photon < v0.mGamma() && v0.mGamma() < v0cuts.cfg_max_mass_photon)) { if (dist01(engine) < downscaling_electron || pos.tpcInnerParam() > max_pin_for_downscaling_electron) { fillTrackTable(collision, pos, static_cast(o2::aod::pwgem::dilepton::PID_Label::kElectron), static_cast(o2::aod::pwgem::dilepton::Track_Type::kSecondary), false); @@ -648,10 +644,10 @@ struct TreeCreatorElectronMLDDA { if (dist01(engine) < downscaling_electron || neg.tpcInnerParam() > max_pin_for_downscaling_electron) { fillTrackTable(collision, neg, static_cast(o2::aod::pwgem::dilepton::PID_Label::kElectron), static_cast(o2::aod::pwgem::dilepton::Track_Type::kSecondary), false); } - registry.fill(HIST("V0/hTPCdEdx_P_El"), neg.p(), neg.tpcSignal()); - registry.fill(HIST("V0/hTOFbeta_P_El"), neg.p(), neg.beta()); - registry.fill(HIST("V0/hTPCdEdx_P_El"), pos.p(), pos.tpcSignal()); - registry.fill(HIST("V0/hTOFbeta_P_El"), pos.p(), pos.beta()); + registry.fill(HIST("V0/hTPCdEdx_P_El"), neg.tpcInnerParam(), neg.tpcSignal()); + registry.fill(HIST("V0/hTOFbeta_P_El"), neg.tpcInnerParam(), neg.beta()); + registry.fill(HIST("V0/hTPCdEdx_P_El"), pos.tpcInnerParam(), pos.tpcSignal()); + registry.fill(HIST("V0/hTOFbeta_P_El"), pos.tpcInnerParam(), pos.beta()); } } } // end of v0 loop @@ -662,10 +658,6 @@ struct TreeCreatorElectronMLDDA { auto bachelor = cascade.template bachelor_as(); auto pos = cascade.template posTrack_as(); auto neg = cascade.template negTrack_as(); - if (!isSelectedV0Leg(collision, pos) || !isSelectedV0Leg(collision, neg) || !isSelectedV0Leg(collision, bachelor)) { - continue; - } - if (pos.sign() * neg.sign() > 0) { continue; } @@ -680,7 +672,6 @@ struct TreeCreatorElectronMLDDA { } } - registry.fill(HIST("Cascade/hMassLambda"), cascade.mLambda()); if (!(v0cuts.cfg_min_mass_lambda < cascade.mLambda() && cascade.mLambda() < v0cuts.cfg_max_mass_lambda)) { continue; } @@ -689,11 +680,6 @@ struct TreeCreatorElectronMLDDA { continue; } - registry.fill(HIST("Cascade/hV0PCA"), cascade.dcaV0daughters()); - registry.fill(HIST("Cascade/hV0CosPA"), cascade.v0cosPA(collision.posX(), collision.posY(), collision.posZ())); - 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())); - if (cascade.dcaV0daughters() > cascadecuts.cfg_max_dcadau_v0) { continue; } @@ -715,6 +701,16 @@ struct TreeCreatorElectronMLDDA { continue; } + if (!isSelectedV0Leg(collision, pos) || !isSelectedV0Leg(collision, neg) || !isSelectedV0Leg(collision, bachelor)) { + continue; + } + + registry.fill(HIST("Cascade/hMassLambda"), cascade.mLambda()); + registry.fill(HIST("Cascade/hV0PCA"), cascade.dcaV0daughters()); + registry.fill(HIST("Cascade/hV0CosPA"), cascade.v0cosPA(collision.posX(), collision.posY(), collision.posZ())); + 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 @@ -723,19 +719,17 @@ struct TreeCreatorElectronMLDDA { if (isPion(bachelor)) { registry.fill(HIST("Cascade/hMassXi"), cascade.mXi()); registry.fill(HIST("Cascade/hMassPt_Xi"), cascade.mXi(), cascade.pt()); - registry.fill(HIST("Cascade/hMassPt_Xi_bachelor"), cascade.mXi(), bachelor.p()); registry.fill(HIST("Cascade/hRxy_Xi"), cascade.mXi(), cascade.cascradius()); registry.fill(HIST("Cascade/hCTau_Xi"), cascade.mXi(), ctauXi); } if (!(cascadecuts.cfg_min_mass_Xi < cascade.mXi() && cascade.mXi() < cascadecuts.cfg_max_mass_Xi) && isKaon(bachelor)) { // reject Xi candidates registry.fill(HIST("Cascade/hMassOmega"), cascade.mOmega()); registry.fill(HIST("Cascade/hMassPt_Omega"), cascade.mOmega(), cascade.pt()); - registry.fill(HIST("Cascade/hMassPt_Omega_bachelor"), cascade.mOmega(), bachelor.p()); 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.p(), bachelor.tpcSignal()); - registry.fill(HIST("V0/hTOFbeta_P_Ka"), bachelor.p(), bachelor.beta()); + registry.fill(HIST("V0/hTPCdEdx_P_Ka"), bachelor.tpcInnerParam(), bachelor.tpcSignal()); + registry.fill(HIST("V0/hTOFbeta_P_Ka"), bachelor.tpcInnerParam(), bachelor.beta()); if (dist01(engine) < downscaling_kaon || bachelor.tpcInnerParam() > max_pin_for_downscaling_kaon) { fillTrackTable(collision, bachelor, static_cast(o2::aod::pwgem::dilepton::PID_Label::kKaon), static_cast(o2::aod::pwgem::dilepton::Track_Type::kPrimary), false); } @@ -743,21 +737,38 @@ struct TreeCreatorElectronMLDDA { } } // end of cascade loop + std::array ppos{0, 0, 0}; + std::array pneg{0, 0, 0}; + // for electron sample for validation auto posTracks_per_coll = posTracks->sliceByCached(o2::aod::track::collisionId, collision.globalIndex(), cache); auto negTracks_per_coll = negTracks->sliceByCached(o2::aod::track::collisionId, collision.globalIndex(), cache); for (const auto& [pos, neg] : combinations(CombinationsFullIndexPolicy(posTracks_per_coll, negTracks_per_coll))) { - if (!isSelectedTrack(collision, pos) || !isSelectedTrack(collision, neg)) { + if (!isElectron(pos) || !isElectron(neg)) { continue; } - if (!isElectron(pos) || !isElectron(neg)) { + if (!isSelectedTrack(collision, pos) || !isSelectedTrack(collision, neg)) { continue; } - ROOT::Math::PtEtaPhiMVector v1(neg.pt(), neg.eta(), neg.phi(), o2::constants::physics::MassElectron); - ROOT::Math::PtEtaPhiMVector v2(pos.pt(), pos.eta(), pos.phi(), o2::constants::physics::MassElectron); + auto posParCov = getTrackParCov(pos); + posParCov.setPID(pos.pidForTracking()); + 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, posParCov, 2.f, matCorr, &mDcaInfoCov); + getPxPyPz(posParCov, ppos); + + auto negParCov = getTrackParCov(neg); + negParCov.setPID(pos.pidForTracking()); + 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, negParCov, 2.f, matCorr, &mDcaInfoCov); + getPxPyPz(negParCov, pneg); + + ROOT::Math::PtEtaPhiMVector v1(negParCov.getPt(), negParCov.getEta(), negParCov.getPhi() > 0.f ? negParCov.getPhi() : negParCov.getPhi() + 2 * M_PI, o2::constants::physics::MassElectron); + ROOT::Math::PtEtaPhiMVector v2(posParCov.getPt(), posParCov.getEta(), posParCov.getPhi() > 0.f ? posParCov.getPhi() : posParCov.getPhi() + 2 * M_PI, o2::constants::physics::MassElectron); ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; - float phiv = o2::aod::pwgem::dilepton::utils::pairutil::getPhivPair(pos.px(), pos.py(), pos.pz(), neg.px(), neg.py(), neg.pz(), pos.sign(), neg.sign(), d_bz); + float phiv = o2::aod::pwgem::dilepton::utils::pairutil::getPhivPair(ppos[0], ppos[1], ppos[2], pneg[0], pneg[1], pneg[2], pos.sign(), neg.sign(), d_bz); registry.fill(HIST("hMvsPhiV"), phiv, v12.M()); if ((dalitzcuts.cfg_min_mass_ee < v12.M() && v12.M() < dalitzcuts.cfg_max_mass_ee) && (dalitzcuts.cfg_min_phiv_ee < phiv && phiv < dalitzcuts.cfg_max_phiv_ee)) { // ee from pi0 dalitz decay is found. @@ -793,19 +804,19 @@ struct MLTrackQC { { {"hTPCdEdx_P_All", "TPC dE/dx vs. p;p^{ITS-TPC} (GeV/c);TPC dE/dx", {HistType::kTH2F, {{500, 0.f, 5.f}, {200, 0, 200}}}}, {"hTOFbeta_P_All", "TOF beta vs. p;p^{ITS-TPC} (GeV/c);TOF #beta", {HistType::kTH2F, {{500, 0.f, 5.f}, {220, 0.0, 1.1}}}}, - {"hITSClusterSize_P_All", "mean ITS cluster size vs. p;p^{ITS-TPC} (GeV/c); #times cos(#lambda)", {HistType::kTH2F, {{500, 0.f, 5.f}, {64, 0.0, 16}}}}, + {"hITSobClusterSize_P_All", "mean ITSob cluster size vs. p;p^{ITS-TPC} (GeV/c); #times cos(#lambda)", {HistType::kTH2F, {{500, 0.f, 5.f}, {150, 0.0, 15}}}}, {"hTPCdEdx_P_Electron", "TPC dE/dx vs. p;p^{ITS-TPC} (GeV/c);TPC dE/dx", {HistType::kTH2F, {{500, 0.f, 5.f}, {200, 0, 200}}}}, {"hTOFbeta_P_Electron", "TOF beta vs. p;p^{ITS-TPC} (GeV/c);TOF #beta", {HistType::kTH2F, {{500, 0.f, 5.f}, {220, 0.0, 1.1}}}}, - {"hITSClusterSize_P_Electron", "mean ITS cluster size vs. p;p^{ITS-TPC} (GeV/c); #times cos(#lambda)", {HistType::kTH2F, {{500, 0.f, 5.f}, {64, 0.0, 16}}}}, + {"hITSobClusterSize_P_Electron", "mean ITSob cluster size vs. p;p^{ITS-TPC} (GeV/c); #times cos(#lambda)", {HistType::kTH2F, {{500, 0.f, 5.f}, {150, 0.0, 15}}}}, {"hTPCdEdx_P_Pion", "TPC dE/dx vs. p;p^{ITS-TPC} (GeV/c);TPC dE/dx", {HistType::kTH2F, {{500, 0.f, 5.f}, {200, 0, 200}}}}, {"hTOFbeta_P_Pion", "TOF beta vs. p;p^{ITS-TPC} (GeV/c);TOF #beta", {HistType::kTH2F, {{500, 0.f, 5.f}, {220, 0.0, 1.1}}}}, - {"hITSClusterSize_P_Pion", "mean ITS cluster size vs. p;p^{ITS-TPC} (GeV/c); #times cos(#lambda)", {HistType::kTH2F, {{500, 0.f, 5.f}, {64, 0.0, 16}}}}, + {"hITSobClusterSize_P_Pion", "mean ITSob cluster size vs. p;p^{ITS-TPC} (GeV/c); #times cos(#lambda)", {HistType::kTH2F, {{500, 0.f, 5.f}, {150, 0.0, 15}}}}, {"hTPCdEdx_P_Kaon", "TPC dE/dx vs. p;p^{ITS-TPC} (GeV/c);TPC dE/dx", {HistType::kTH2F, {{500, 0.f, 5.f}, {200, 0, 200}}}}, {"hTOFbeta_P_Kaon", "TOF beta vs. p;p^{ITS-TPC} (GeV/c);TOF #beta", {HistType::kTH2F, {{500, 0.f, 5.f}, {220, 0.0, 1.1}}}}, - {"hITSClusterSize_P_Kaon", "mean ITS cluster size vs. p;p^{ITS-TPC} (GeV/c); #times cos(#lambda)", {HistType::kTH2F, {{500, 0.f, 5.f}, {64, 0.0, 16}}}}, + {"hITSobClusterSize_P_Kaon", "mean ITSob cluster size vs. p;p^{ITS-TPC} (GeV/c); #times cos(#lambda)", {HistType::kTH2F, {{500, 0.f, 5.f}, {150, 0.0, 15}}}}, {"hTPCdEdx_P_Proton", "TPC dE/dx vs. p;p^{ITS-TPC} (GeV/c);TPC dE/dx", {HistType::kTH2F, {{500, 0.f, 5.f}, {200, 0, 200}}}}, {"hTOFbeta_P_Proton", "TOF beta vs. p;p^{ITS-TPC} (GeV/c);TOF #beta", {HistType::kTH2F, {{500, 0.f, 5.f}, {220, 0.0, 1.1}}}}, - {"hITSClusterSize_P_Proton", "mean ITS cluster size vs. p;p^{ITS-TPC} (GeV/c); #times cos(#lambda)", {HistType::kTH2F, {{500, 0.f, 5.f}, {64, 0.0, 16}}}}, + {"hITSobClusterSize_P_Proton", "mean ITSob cluster size vs. p;p^{ITS-TPC} (GeV/c); #times cos(#lambda)", {HistType::kTH2F, {{500, 0.f, 5.f}, {150, 0.0, 15}}}}, {"hTPCNsigmaEl_P", "TPC n#sigma_{e} vs. p;p^{ITS-TPC} (GeV/c);n #sigma_{e}^{TPC}", {HistType::kTH2F, {{500, 0.f, 5.f}, {100, -5, +5}}}}, {"hTPCNsigmaPi_P", "TPC n#sigma_{#pi} vs. p;p^{ITS-TPC} (GeV/c);n #sigma_{#pi}^{TPC}", {HistType::kTH2F, {{500, 0.f, 5.f}, {100, -5, +5}}}}, @@ -823,29 +834,29 @@ struct MLTrackQC { for (const auto& track : tracks) { registry.fill(HIST("hTPCdEdx_P_All"), track.p(), track.tpcSignal()); registry.fill(HIST("hTOFbeta_P_All"), track.p(), track.beta()); - registry.fill(HIST("hITSClusterSize_P_All"), track.p(), track.meanClusterSizeITS() * std::cos(std::atan(track.tgl()))); + registry.fill(HIST("hITSobClusterSize_P_All"), track.p(), track.meanClusterSizeITSob() * std::cos(std::atan(track.tgl()))); if (track.pidlabel() == static_cast(o2::aod::pwgem::dilepton::PID_Label::kElectron)) { registry.fill(HIST("hTPCdEdx_P_Electron"), track.p(), track.tpcSignal()); registry.fill(HIST("hTOFbeta_P_Electron"), track.p(), track.beta()); - registry.fill(HIST("hITSClusterSize_P_Electron"), track.p(), track.meanClusterSizeITS() * std::cos(std::atan(track.tgl()))); + registry.fill(HIST("hITSobClusterSize_P_Electron"), track.p(), track.meanClusterSizeITSob() * std::cos(std::atan(track.tgl()))); registry.fill(HIST("hTPCNsigmaEl_P"), track.p(), track.tpcNSigmaEl()); registry.fill(HIST("hTOFNsigmaEl_P"), track.p(), track.tofNSigmaEl()); } else if (track.pidlabel() == static_cast(o2::aod::pwgem::dilepton::PID_Label::kPion)) { registry.fill(HIST("hTPCdEdx_P_Pion"), track.p(), track.tpcSignal()); registry.fill(HIST("hTOFbeta_P_Pion"), track.p(), track.beta()); - registry.fill(HIST("hITSClusterSize_P_Pion"), track.p(), track.meanClusterSizeITS() * std::cos(std::atan(track.tgl()))); + registry.fill(HIST("hITSobClusterSize_P_Pion"), track.p(), track.meanClusterSizeITSob() * std::cos(std::atan(track.tgl()))); registry.fill(HIST("hTPCNsigmaPi_P"), track.p(), track.tpcNSigmaPi()); registry.fill(HIST("hTOFNsigmaPi_P"), track.p(), track.tofNSigmaPi()); } else if (track.pidlabel() == static_cast(o2::aod::pwgem::dilepton::PID_Label::kKaon)) { registry.fill(HIST("hTPCdEdx_P_Kaon"), track.p(), track.tpcSignal()); registry.fill(HIST("hTOFbeta_P_Kaon"), track.p(), track.beta()); - registry.fill(HIST("hITSClusterSize_P_Kaon"), track.p(), track.meanClusterSizeITS() * std::cos(std::atan(track.tgl()))); + registry.fill(HIST("hITSobClusterSize_P_Kaon"), track.p(), track.meanClusterSizeITSob() * std::cos(std::atan(track.tgl()))); registry.fill(HIST("hTPCNsigmaKa_P"), track.p(), track.tpcNSigmaKa()); registry.fill(HIST("hTOFNsigmaKa_P"), track.p(), track.tofNSigmaKa()); } else if (track.pidlabel() == static_cast(o2::aod::pwgem::dilepton::PID_Label::kProton)) { registry.fill(HIST("hTPCdEdx_P_Proton"), track.p(), track.tpcSignal()); registry.fill(HIST("hTOFbeta_P_Proton"), track.p(), track.beta()); - registry.fill(HIST("hITSClusterSize_P_Proton"), track.p(), track.meanClusterSizeITS() * std::cos(std::atan(track.tgl()))); + registry.fill(HIST("hITSobClusterSize_P_Proton"), track.p(), track.meanClusterSizeITSob() * std::cos(std::atan(track.tgl()))); registry.fill(HIST("hTPCNsigmaPr_P"), track.p(), track.tpcNSigmaPr()); registry.fill(HIST("hTOFNsigmaPr_P"), track.p(), track.tofNSigmaPr()); } diff --git a/PWGEM/Dilepton/Tasks/createResolutionMap.cxx b/PWGEM/Dilepton/Tasks/createResolutionMap.cxx index c6c056b5dcb..8ae6b3e563f 100644 --- a/PWGEM/Dilepton/Tasks/createResolutionMap.cxx +++ b/PWGEM/Dilepton/Tasks/createResolutionMap.cxx @@ -157,12 +157,12 @@ struct CreateResolutionMap { Configurable cfg_mid_rabs{"cfg_mid_rabs", 26.5, "middle R at absorber end for pDCA cut"}; Configurable cfg_max_pdca_forLargeR{"cfg_max_pdca_forLargeR", 324.f, "max. pDCA for large R at absorber end"}; Configurable cfg_max_pdca_forSmallR{"cfg_max_pdca_forSmallR", 594.f, "max. pDCA for small R at absorber end"}; - Configurable cfg_min_nclusters_MFT{"cfg_min_nclusters_MFT", 5, "min nclusters MFT"}; - Configurable cfg_min_nclusters_MCH{"min_min_nclusters_MCH", 5, "min nclusters MCH"}; Configurable cfg_max_reldpt{"cfg_max_reldpt", 1e+10f, "max. relative dpt between MFT-MCH-MID and MCH-MID"}; Configurable cfg_max_deta{"cfg_max_deta", 1e+10f, "max. deta between MFT-MCH-MID and MCH-MID"}; Configurable cfg_max_dphi{"cfg_max_dphi", 1e+10f, "max. dphi between MFT-MCH-MID and MCH-MID"}; Configurable refitGlobalMuon{"refitGlobalMuon", true, "flag to refit global muon"}; + Configurable requireMFTHitMap{"requireMFTHitMap", false, "flag to require MFT hit map"}; + Configurable> requiredMFTDisks{"requiredMFTDisks", std::vector{4}, "hit map on MFT disks [0,1,2,3,4]. logical-OR of each double-sided disk"}; } muoncuts; HistogramRegistry registry{"registry", {}, OutputObjHandlingPolicy::AnalysisObject}; @@ -583,6 +583,15 @@ struct CreateResolutionMap { return; } + if (muoncuts.requireMFTHitMap) { + std::vector hasMFTs{hasMFT<0, 1>(mfttrack), hasMFT<2, 3>(mfttrack), hasMFT<4, 5>(mfttrack), hasMFT<6, 7>(mfttrack), hasMFT<8, 9>(mfttrack)}; + for (int i = 0; i < static_cast(muoncuts.requiredMFTDisks->size()); i++) { + if (!hasMFTs[muoncuts.requiredMFTDisks->at(i)]) { + return; + } + } + } + } else if (muon.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack) { o2::dataformats::GlobalFwdTrack propmuonAtRabs = propagateMuon(muon, collision, propagationPoint::kToRabs); // this is necessary only for MuonStandaloneTrack float xAbs = propmuonAtRabs.getX(); @@ -680,6 +689,20 @@ struct CreateResolutionMap { return true; } + template + bool hasMFT(T const& track) + { + // logical-OR + uint64_t mftClusterSizesAndTrackFlags = track.mftClusterSizesAndTrackFlags(); + uint16_t clmap = 0; + for (unsigned int layer = begin; layer <= end; layer++) { + if ((mftClusterSizesAndTrackFlags >> (layer * 6)) & 0x3f) { + clmap |= (1 << layer); + } + } + return (clmap > 0); + } + SliceCache cache; Preslice perCollision_mid = o2::aod::track::collisionId; Preslice perCollision_fwd = o2::aod::fwdtrack::collisionId; diff --git a/PWGEM/Dilepton/Utils/EMTrackUtilities.h b/PWGEM/Dilepton/Utils/EMTrackUtilities.h index 6ac2275aee1..eb73226cd1e 100644 --- a/PWGEM/Dilepton/Utils/EMTrackUtilities.h +++ b/PWGEM/Dilepton/Utils/EMTrackUtilities.h @@ -65,12 +65,12 @@ float dcaZinSigma(T const& track) template float fwdDcaXYinSigma(T const& track) { - float cXX = track.cXXatDCA(); // in cm^2 - float cYY = track.cYYatDCA(); // in cm^2 - float cXY = track.cXYatDCA(); // in cm^2 - float dcaX = track.fwdDcaX(); // in cm - float dcaY = track.fwdDcaY(); // in cm - float det = cXX * cYY - cXY * cXY; // determinant + float cXX = track.cXXatDCA(); // in cm^2 + float cYY = track.cYYatDCA(); // in cm^2 + float cXY = track.cXYatDCA(); // in cm^2 + float dcaX = track.fwdDcaX(); // in cm + float dcaY = track.fwdDcaY(); // in cm + float det = cXX * cYY - cXY * cXY; // determinant if (det < 0) { return 999.f; @@ -88,6 +88,20 @@ float sigmaFwdDcaXY(T const& track) return dcaXY / fwdDcaXYinSigma(track); } //_______________________________________________________________________ +template +bool checkMFTHitMap(T const& track) +{ + // logical-OR + uint64_t mftClusterSizesAndTrackFlags = track.mftClusterSizesAndTrackFlags(); + uint16_t clmap = 0; + for (unsigned int layer = begin; layer <= end; layer++) { + if ((mftClusterSizesAndTrackFlags >> (layer * 6)) & 0x3f) { + clmap |= (1 << layer); + } + } + return (clmap > 0); +} +//_______________________________________________________________________ template bool isBestMatch(TTrack const& track, TCut const& cut, TTracks const& tracks) { From b51dfb4847aee36f5ff1523cde640249a702b4d4 Mon Sep 17 00:00:00 2001 From: Paola Vargas Torres <88360333+PaolaVT@users.noreply.github.com> Date: Mon, 9 Jun 2025 19:53:30 -0600 Subject: [PATCH 010/871] [PWGLF] Phi cut was added (#11527) --- PWGMM/UE/Tasks/dedxAnalysis.cxx | 45 +++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/PWGMM/UE/Tasks/dedxAnalysis.cxx b/PWGMM/UE/Tasks/dedxAnalysis.cxx index 0336638dade..34999be4f7e 100644 --- a/PWGMM/UE/Tasks/dedxAnalysis.cxx +++ b/PWGMM/UE/Tasks/dedxAnalysis.cxx @@ -28,6 +28,7 @@ #include "PWGLF/DataModel/LFStrangenessTables.h" #include "ReconstructionDataFormats/Track.h" #include "Common/Core/TrackSelectionDefaults.h" +#include "TF1.h" using namespace o2; using namespace o2::framework; @@ -58,6 +59,8 @@ struct DedxAnalysis { float pionTofCut = 1.0; float invMassCut = 0.01; float invMassCutGamma = 0.0015; + float magField = 1.0; + float pTcut = 2.0; // Configurable Parameters // Tracks cuts @@ -103,6 +106,10 @@ struct DedxAnalysis { 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}, ""}; + // phi cut fits + TF1* fphiCutHigh = nullptr; + TF1* fphiCutLow = nullptr; + TrackSelection myTrackSelection() { TrackSelection selectedTracks; @@ -130,6 +137,8 @@ struct DedxAnalysis { AxisSpec ptAxis = {binP, "pT (GeV/c)"}; AxisSpec etaAxis{8, -0.8, 0.8, "#eta"}; AxisSpec pAxis = {binP, "#it{p}/Z (GeV/c)"}; + fphiCutLow = new TF1("StandardPhiCutLow", "0.1/x/x+pi/18.0-0.025", 0, 50); + fphiCutHigh = new TF1("StandardPhiCutHigh", "0.12/x+pi/18.0+0.035", 0, 50); if (calibrationMode) { // MIP for pions registryDeDx.add( @@ -202,6 +211,11 @@ struct DedxAnalysis { "hdEdx_vs_phi", "dE/dx", HistType::kTH2F, {{100, 0.0, 6.4, "#phi"}, {dedxAxis}}); + // phi cut + registryDeDx.add( + "hpt_vs_phi", "phi cut", HistType::kTH2F, + {{ptAxis}, {100, 0.0, 6.4, "#phi"}}); + registryDeDx.add( "hbeta_vs_p_Neg", "beta", HistType::kTH2F, {{pAxis}, {100, 0.0, 1.1, "#beta"}}); @@ -375,6 +389,33 @@ struct DedxAnalysis { return true; } + // Phi cut + template + bool passedPhiCut(const T& trk, float magField, const TF1& fphiCutLow, const TF1& fphiCutHigh) + { + float pt = trk.pt(); + float phi = trk.phi(); + int charge = trk.sign(); + + if (pt < pTcut) + return true; + + if (magField < 0.) // for negatve polarity field + phi = o2::constants::math::TwoPI - phi; + if (charge < 0) // for negatve charge + phi = o2::constants::math::TwoPI - phi; + + // to center gap in the middle + phi += o2::constants::math::PI / 18.0f; + phi = std::fmod(phi, o2::constants::math::PI / 9.0f); + + if (phi < fphiCutHigh.Eval(pt) && phi > fphiCutLow.Eval(pt)) + return false; // reject track + + registryDeDx.fill(HIST("hpt_vs_phi"), pt, phi); + return true; + } + // Process Data void process(SelectedCollisions::iterator const& collision, aod::V0Datas const& fullV0s, PIDTracks const& tracks) @@ -410,6 +451,10 @@ struct DedxAnalysis { if (!mySelectionPrim.IsSelected(trk)) continue; + // phi cut + if (!passedPhiCut(trk, magField, *fphiCutLow, *fphiCutHigh)) + continue; + float signedP = trk.sign() * trk.tpcInnerParam(); // MIP calibration for pions From a5ae97a62567392cfeaaeccd3b6dc74eac1dbc5c Mon Sep 17 00:00:00 2001 From: Anantha Padmanabhan M Nair <82643666+ananthapadmanabhan18@users.noreply.github.com> Date: Tue, 10 Jun 2025 11:52:07 +0530 Subject: [PATCH 011/871] [PWGUD] Added the bc selection cuts for the new pass5 and renamed histograms (#11520) --- PWGUD/Tasks/exclusiveRhoTo4Pi.cxx | 394 ++++++++++++++++-------------- 1 file changed, 205 insertions(+), 189 deletions(-) diff --git a/PWGUD/Tasks/exclusiveRhoTo4Pi.cxx b/PWGUD/Tasks/exclusiveRhoTo4Pi.cxx index 14ffcc415a4..ac0a9459569 100644 --- a/PWGUD/Tasks/exclusiveRhoTo4Pi.cxx +++ b/PWGUD/Tasks/exclusiveRhoTo4Pi.cxx @@ -519,8 +519,11 @@ struct ExclusiveRhoTo4Pi { Configurable fv0Cut{"fv0Cut", 50., "FV0A threshold"}; Configurable ft0aCut{"ft0aCut", 150., "FT0A threshold"}; Configurable ft0cCut{"ft0cCut", 50., "FT0C threshold"}; - Configurable zdcCut{"zdcCut", 1., "ZDC threshold"}; - // Configurable occupancyCut{"occupancyCut", 1000, "Occupancy Cut"}; + Configurable zdcCut{"zdcCut", 0., "ZDC threshold"}; + Configurable sbpCut{"sbpCut", 1, "Sbp"}; + Configurable itsROFbCut{"itsROFbCut", 1, "itsROFbCut"}; + Configurable vtxITSTPCcut{"vtxITSTPCcut", 1, "vtxITSTPCcut"}; + Configurable tfbCut{"tfbCut", 1, "tfbCut"}; Configurable pvCut{"pvCut", 1.0, "Use Only PV tracks"}; Configurable numPVContrib{"numPVContrib", 4, "Number of PV Contributors"}; @@ -563,66 +566,66 @@ struct ExclusiveRhoTo4Pi { histosData.add("tpcNClsFindable", "TPC N Cls Findable; N Cls Findable; Counts", kTH1F, {{200, 0, 200}}); // TPC nSigma - histosData.add("tpcNSigmaPi_WTS", "TPC nSigma Pion with track selection; Events", kTH2F, {{1000, -15, 15}, {nBinsPt, 0, 10}}); - histosData.add("tpcNSigmaPi_WTS_PID_Pi", "TPC nSigma Pion with track selection and PID Selection of Pi; Entries", kTH2F, {{1000, -15, 15}, {nBinsPt, 0, 10}}); + histosData.add("tpcNSigmaPi_all", "TPC nSigma Pion with track selection; Events", kTH2F, {{1000, -15, 15}, {nBinsPt, 0, 10}}); + histosData.add("tpcNSigmaPi_pions", "TPC nSigma Pion with track selection and PID Selection of Pi; Entries", kTH2F, {{1000, -15, 15}, {nBinsPt, 0, 10}}); // TPC nSigma of other particles with selected pion tracks - histosData.add("tpcNSigmaKa_WTS_PID_Pi", "TPC nSigma Kaon with track selection and PID Selection of Pion; Entries", kTH2F, {{1000, -15, 15}, {nBinsPt, 0, 10}}); - histosData.add("tpcNSigmaPr_WTS_PID_Pi", "TPC nSigma Proton with track selection and PID Selection of Pion; Entries", kTH2F, {{1000, -15, 15}, {nBinsPt, 0, 10}}); - histosData.add("tpcNSigmaEl_WTS_PID_Pi", "TPC nSigma Electron with track selection and PID Selection of Pion; Entries", kTH2F, {{1000, -15, 15}, {nBinsPt, 0, 10}}); - histosData.add("tpcNSigmaMu_WTS_PID_Pi", "TPC nSigma Muon with track selection and PID Selection of Pion; Entries", kTH2F, {{1000, -15, 15}, {nBinsPt, 0, 10}}); + histosData.add("tpcNSigmaKa_pions", "TPC nSigma Kaon with track selection and PID Selection of Pion; Entries", kTH2F, {{1000, -15, 15}, {nBinsPt, 0, 10}}); + histosData.add("tpcNSigmaPr_pions", "TPC nSigma Proton with track selection and PID Selection of Pion; Entries", kTH2F, {{1000, -15, 15}, {nBinsPt, 0, 10}}); + histosData.add("tpcNSigmaEl_pions", "TPC nSigma Electron with track selection and PID Selection of Pion; Entries", kTH2F, {{1000, -15, 15}, {nBinsPt, 0, 10}}); + histosData.add("tpcNSigmaMu_pions", "TPC nSigma Muon with track selection and PID Selection of Pion; Entries", kTH2F, {{1000, -15, 15}, {nBinsPt, 0, 10}}); // TOF nSigma - histosData.add("tofNSigmaPi_WTS", "TOF nSigma Pion with track selection; Events", kTH2F, {{1000, -15, 15}, {nBinsPt, 0, 10}}); - histosData.add("tofNSigmaPi_WTS_PID_Pi", "TOF nSigma Pion with track selection and PID Selection of Pi; Entries", kTH2F, {{1000, -15, 15}, {nBinsPt, 0, 10}}); + histosData.add("tofNSigmaPi_all", "TOF nSigma Pion with track selection; Events", kTH2F, {{1000, -15, 15}, {nBinsPt, 0, 10}}); + histosData.add("tofNSigmaPi_pions", "TOF nSigma Pion with track selection and PID Selection of Pi; Entries", kTH2F, {{1000, -15, 15}, {nBinsPt, 0, 10}}); // TOF nSigma of other particles with selected pion tracks - histosData.add("tofNSigmaKa_WTS_PID_Pi", "TOF nSigma Kaon with track selection and PID Selection of Pion; Entries", kTH2F, {{1000, -15, 15}, {nBinsPt, 0, 10}}); - histosData.add("tofNSigmaPr_WTS_PID_Pi", "TOF nSigma Proton with track selection and PID Selection of Pion; Entries", kTH2F, {{1000, -15, 15}, {nBinsPt, 0, 10}}); - histosData.add("tofNSigmaEl_WTS_PID_Pi", "TOF nSigma Electron with track selection and PID Selection of Pion; Entries", kTH2F, {{1000, -15, 15}, {nBinsPt, 0, 10}}); - histosData.add("tofNSigmaMu_WTS_PID_Pi", "TOF nSigma Muon with track selection and PID Selection of Pion; Entries", kTH2F, {{1000, -15, 15}, {nBinsPt, 0, 10}}); + histosData.add("tofNSigmaKa_pions", "TOF nSigma Kaon with track selection and PID Selection of Pion; Entries", kTH2F, {{1000, -15, 15}, {nBinsPt, 0, 10}}); + histosData.add("tofNSigmaPr_pions", "TOF nSigma Proton with track selection and PID Selection of Pion; Entries", kTH2F, {{1000, -15, 15}, {nBinsPt, 0, 10}}); + histosData.add("tofNSigmaEl_pions", "TOF nSigma Electron with track selection and PID Selection of Pion; Entries", kTH2F, {{1000, -15, 15}, {nBinsPt, 0, 10}}); + histosData.add("tofNSigmaMu_pions", "TOF nSigma Muon with track selection and PID Selection of Pion; Entries", kTH2F, {{1000, -15, 15}, {nBinsPt, 0, 10}}); // Track Transverse Momentum - histosData.add("pT_track_WTS", "pT with track selection; pT [GeV/c]; Counts", kTH1F, {{nBinsPt, 0, 2}}); - histosData.add("pT_track_WTS_PID_Pi", "pT with track selection and PID selection of Pi; pT [GeV/c]; Events", kTH1F, {{nBinsPt, 0, 2}}); - histosData.add("pT_track_WTS_PID_Pi_contributed", "pT with track selection and PID selection of Pi which are contributed to selected event; pT [GeV/c]; Events", kTH1F, {{nBinsPt, 0, 2}}); + histosData.add("pT_track_all", "pT with track selection; pT [GeV/c]; Counts", kTH1F, {{nBinsPt, 0, 2}}); + histosData.add("pT_track_pions", "pT with track selection and PID selection of Pi; pT [GeV/c]; Events", kTH1F, {{nBinsPt, 0, 2}}); + histosData.add("pT_track_pions_contributed", "pT with track selection and PID selection of Pi which are contributed to selected event; pT [GeV/c]; Events", kTH1F, {{nBinsPt, 0, 2}}); // Track Rapidity - histosData.add("rapidity_track_WTS", "Rapidity with track selection; y; Counts", kTH1F, {{nBinsRapidity, -2.5, 2.5}}); - histosData.add("rapidity_track_WTS_PID_Pi", "Rapidity with track selection and PID selection of Pi; y; Events", kTH1F, {{nBinsRapidity, -2.5, 2.5}}); - histosData.add("rapidity_track_WTS_PID_Pi_contributed", "Rapidity with track selection and PID selection of Pi which are contributed to selected event; y; Events", kTH1F, {{nBinsRapidity, -2.5, 2.5}}); + histosData.add("rapidity_track_all", "Rapidity with track selection; y; Counts", kTH1F, {{nBinsRapidity, -2.5, 2.5}}); + histosData.add("rapidity_track_pions", "Rapidity with track selection and PID selection of Pi; y; Events", kTH1F, {{nBinsRapidity, -2.5, 2.5}}); + histosData.add("rapidity_track_pions_contributed", "Rapidity with track selection and PID selection of Pi which are contributed to selected event; y; Events", kTH1F, {{nBinsRapidity, -2.5, 2.5}}); // Zero charge Event Transverse Momentum - histosData.add("pT_event_0charge_WTS_PID_Pi", "Event pT in 0 Charge Events With Track Selection and PID Selection of Pi; pT [GeV/c]; Events", kTH1F, {{nBinsPt, 0, 2}}); + histosData.add("fourpion_pT_0_charge", "Event pT in 0 Charge Events With Track Selection and PID Selection of Pi; pT [GeV/c]; Events", kTH1F, {{nBinsPt, 0, 2}}); // Non Zero charge Event Transverse Momentum - histosData.add("pT_event_non0charge_WTS_PID_Pi", "Event pT in Non 0 Charge Events With Track Selection and PID Selection of Pi; pT [GeV/c]; Events", kTH1F, {{nBinsPt, 0, 2}}); + histosData.add("fourpion_pT_non_0_charge", "Event pT in Non 0 Charge Events With Track Selection and PID Selection of Pi; pT [GeV/c]; Events", kTH1F, {{nBinsPt, 0, 2}}); // Rapidity of 0 charge Events - histosData.add("rapidity_event_0charge_WTS_PID_Pi_domainA", "Rapidity of Events With Track Selection and PID Selection of Pi for p_{T} < 0.15 GeV/c; y; Events", kTH1F, {{1000, -2.5, 2.5}}); - histosData.add("rapidity_event_0charge_WTS_PID_Pi_domainB", "Rapidity of Events With Track Selection and PID Selection of Pi for 0.15< p_{T} < 0.80 GeV/c; y; Events", kTH1F, {{1000, -2.5, 2.5}}); - histosData.add("rapidity_event_0charge_WTS_PID_Pi_domainC", "Rapidity of Events With Track Selection and PID Selection of Pi for p_{T} > 0.80 GeV/c; y; Events", kTH1F, {{1000, -2.5, 2.5}}); + histosData.add("fourpion_rap_0_charge_domA", "Rapidity of Events With Track Selection and PID Selection of Pi for p_{T} < 0.15 GeV/c; y; Events", kTH1F, {{1000, -2.5, 2.5}}); + histosData.add("fourpion_rap_0_charge_domB", "Rapidity of Events With Track Selection and PID Selection of Pi for 0.15< p_{T} < 0.80 GeV/c; y; Events", kTH1F, {{1000, -2.5, 2.5}}); + histosData.add("fourpion_rap_0_charge_domC", "Rapidity of Events With Track Selection and PID Selection of Pi for p_{T} > 0.80 GeV/c; y; Events", kTH1F, {{1000, -2.5, 2.5}}); // Rapidity of non 0 charge Events - histosData.add("rapidity_event_non0charge_WTS_PID_Pi_domainA", "Rapidity of Events With Track Selection and PID Selection of Pi for p_{T} < 0.15 GeV/c; y; Events", kTH1F, {{nBinsRapidity, -2.5, 2.5}}); - histosData.add("rapidity_event_non0charge_WTS_PID_Pi_domainB", "Rapidity of Events With Track Selection and PID Selection of Pi for 0.15< p_{T} < 0.80 GeV/c$; y; Events", kTH1F, {{nBinsRapidity, -2.5, 2.5}}); - histosData.add("rapidity_event_non0charge_WTS_PID_Pi_domainC", "Rapidity of Events With Track Selection and PID Selection of Pi for p_{T} > 0.80 GeV/c; y; Events", kTH1F, {{nBinsRapidity, -2.5, 2.5}}); + histosData.add("fourpion_rap_non_0_charge_domA", "Rapidity of Events With Track Selection and PID Selection of Pi for p_{T} < 0.15 GeV/c; y; Events", kTH1F, {{nBinsRapidity, -2.5, 2.5}}); + histosData.add("fourpion_rap_non_0_charge_domB", "Rapidity of Events With Track Selection and PID Selection of Pi for 0.15< p_{T} < 0.80 GeV/c$; y; Events", kTH1F, {{nBinsRapidity, -2.5, 2.5}}); + histosData.add("fourpion_rap_non_0_charge_domC", "Rapidity of Events With Track Selection and PID Selection of Pi for p_{T} > 0.80 GeV/c; y; Events", kTH1F, {{nBinsRapidity, -2.5, 2.5}}); // Pair Invariant Mass - histosData.add("invMass_pair_1", "Invariant Mass Distribution of 2 pions 1 ; m(#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {{5000, 0, 5}}); - histosData.add("invMass_pair_2", "Invariant Mass Distribution of 2 pions 2 ; m(#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {{5000, 0, 5}}); - histosData.add("invMass_pair_3", "Invariant Mass Distribution of 2 pions 3 ; m(#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {{5000, 0, 5}}); - histosData.add("invMass_pair_4", "Invariant Mass Distribution of 2 pions 4 ; m(#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {{5000, 0, 5}}); + histosData.add("twopion_mass_1", "Invariant Mass Distribution of 2 pions 1 ; m(#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {{5000, 0, 5}}); + histosData.add("twopion_mass_2", "Invariant Mass Distribution of 2 pions 2 ; m(#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {{5000, 0, 5}}); + histosData.add("twopion_mass_3", "Invariant Mass Distribution of 2 pions 3 ; m(#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {{5000, 0, 5}}); + histosData.add("twopion_mass_4", "Invariant Mass Distribution of 2 pions 4 ; m(#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {{5000, 0, 5}}); // Invariant Mass of 0 charge events - histosData.add("invMass_event_0charge_WTS_PID_Pi_domainA", "Invariant Mass Distribution of 0 charge Events with PID Selection of Pi for p_{T} < 0.15 GeV/c; m(#pi^{+}#pi^{-}#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {{nBinsInvariantMass, invariantMassMin, invariantMassMax}}); // pT < 0.15GeV - histosData.add("invMass_event_0charge_WTS_PID_Pi_domainB", "Invariant Mass Distribution of 0 charge Events with PID Selection of Pi for 0.15< p_{T} < 0.80 GeV/c; m(#pi^{+}#pi^{-}#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {{nBinsInvariantMass, invariantMassMin, invariantMassMax}}); // 0.15GeV < pT < 0.8GeV - histosData.add("invMass_event_0charge_WTS_PID_Pi_domainC", "Invariant Mass Distribution of 0 charge Events with PID Selection of Pi for p_{T} > 0.80 GeV/c; m(#pi^{+}#pi^{-}#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {{nBinsInvariantMass, invariantMassMin, invariantMassMax}}); // 0.8GeV < pT + histosData.add("fourpion_mass_0_charge_domA", "Invariant Mass Distribution of 0 charge Events with PID Selection of Pi for p_{T} < 0.15 GeV/c; m(#pi^{+}#pi^{-}#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {{nBinsInvariantMass, invariantMassMin, invariantMassMax}}); // pT < 0.15GeV + histosData.add("fourpion_mass_0_charge_domB", "Invariant Mass Distribution of 0 charge Events with PID Selection of Pi for 0.15< p_{T} < 0.80 GeV/c; m(#pi^{+}#pi^{-}#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {{nBinsInvariantMass, invariantMassMin, invariantMassMax}}); // 0.15GeV < pT < 0.8GeV + histosData.add("fourpion_mass_0_charge_domC", "Invariant Mass Distribution of 0 charge Events with PID Selection of Pi for p_{T} > 0.80 GeV/c; m(#pi^{+}#pi^{-}#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {{nBinsInvariantMass, invariantMassMin, invariantMassMax}}); // 0.8GeV < pT // Invariant mass of non 0 charge events - histosData.add("invMass_event_non0charge_WTS_PID_Pi_domainA", "Invariant Mass Distribution of non 0 charge Events with PID Selection of Pi for p_{T} < 0.15 GeV/c; m(#pi^{+}#pi^{-}#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {{nBinsInvariantMass, invariantMassMin, invariantMassMax}}); // pT < 0.15GeV - histosData.add("invMass_event_non0charge_WTS_PID_Pi_domainB", "Invariant Mass Distribution of non 0 charge Events with PID Selection of Pi for 0.15< p_{T} < 0.80 GeV/c; m(#pi^{+}#pi^{-}#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {{nBinsInvariantMass, invariantMassMin, invariantMassMax}}); // 0.15GeV < pT < 0.8GeV - histosData.add("invMass_event_non0charge_WTS_PID_Pi_domainC", "Invariant Mass Distribution of non 0 charge Events with PID Selection of Pi for p_{T} > 0.80 GeV/c; m(#pi^{+}#pi^{-}#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {{nBinsInvariantMass, invariantMassMin, invariantMassMax}}); // 0.8GeV < pT + histosData.add("fourpion_mass_non_0_charge_domA", "Invariant Mass Distribution of non 0 charge Events with PID Selection of Pi for p_{T} < 0.15 GeV/c; m(#pi^{+}#pi^{-}#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {{nBinsInvariantMass, invariantMassMin, invariantMassMax}}); // pT < 0.15GeV + histosData.add("fourpion_mass_non_0_charge_domB", "Invariant Mass Distribution of non 0 charge Events with PID Selection of Pi for 0.15< p_{T} < 0.80 GeV/c; m(#pi^{+}#pi^{-}#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {{nBinsInvariantMass, invariantMassMin, invariantMassMax}}); // 0.15GeV < pT < 0.8GeV + histosData.add("fourpion_mass_non_0_charge_domC", "Invariant Mass Distribution of non 0 charge Events with PID Selection of Pi for p_{T} > 0.80 GeV/c; m(#pi^{+}#pi^{-}#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {{nBinsInvariantMass, invariantMassMin, invariantMassMax}}); // 0.8GeV < pT // tpc signal histosData.add("tpcSignal", "TPC dEdx vs p; p [GeV/c]; dEdx [a.u.]", kTH2F, {{500, 0, 10}, {5000, 0.0, 5000.0}}); @@ -640,12 +643,12 @@ struct ExclusiveRhoTo4Pi { histosData.add("V0A", "V0A amplitude", kTH1F, {{1000, 0.0, 100}}); // Collin Soper Theta and Phi - histosData.add("CS_phi_pair_1", "#phi Distribution; #phi; Events", kTH1F, {{nBinsPhi, -3.2, 3.2}}); - histosData.add("CS_phi_pair_2", "#phi Distribution; #phi; Events", kTH1F, {{nBinsPhi, -3.2, 3.2}}); - histosData.add("CS_costheta_pair_1", "#theta Distribution;cos(#theta); Counts", kTH1F, {{nBinsCosTheta, -1, 1}}); - histosData.add("CS_costheta_pair_2", "#theta Distribution;cos(#theta); Counts", kTH1F, {{nBinsCosTheta, -1, 1}}); - histosData.add("phi_cosTheta_pair_1", "Phi vs cosTheta; #phi; cos(#theta)", kTH2F, {{nBinsPhi, -3.2, 3.2}, {nBinsCosTheta, -1, 1}}); - histosData.add("phi_cosTheta_pair_2", "Phi vs cosTheta; #phi; cos(#theta)", kTH2F, {{nBinsPhi, -3.2, 3.2}, {nBinsCosTheta, -1, 1}}); + histosData.add("collin_soper_phi_1", "#phi Distribution; #phi; Events", kTH1F, {{nBinsPhi, -3.2, 3.2}}); + histosData.add("collin_soper_phi_2", "#phi Distribution; #phi; Events", kTH1F, {{nBinsPhi, -3.2, 3.2}}); + histosData.add("collin_soper_costheta_1", "#theta Distribution;cos(#theta); Counts", kTH1F, {{nBinsCosTheta, -1, 1}}); + histosData.add("collin_soper_costheta_2", "#theta Distribution;cos(#theta); Counts", kTH1F, {{nBinsCosTheta, -1, 1}}); + histosData.add("phi_vs_costheta_1", "Phi vs cosTheta; #phi; cos(#theta)", kTH2F, {{nBinsPhi, -3.2, 3.2}, {nBinsCosTheta, -1, 1}}); + histosData.add("phi_vs_costheta_2", "Phi vs cosTheta; #phi; cos(#theta)", kTH2F, {{nBinsPhi, -3.2, 3.2}, {nBinsCosTheta, -1, 1}}); // MC Gen Stuff @@ -679,8 +682,8 @@ struct ExclusiveRhoTo4Pi { histosMCgen.add("fourPion_phi_pair_2", "#phi Distribution; #phi; Events", kTH1F, {{nBinsPhi, -3.2, 3.2}}); histosMCgen.add("fourPion_costheta_pair_1", "#theta Distribution;cos(#theta); Events", kTH1F, {{nBinsCosTheta, -1, 1}}); histosMCgen.add("fourPion_costheta_pair_2", "#theta Distribution;cos(#theta); Events", kTH1F, {{nBinsCosTheta, -1, 1}}); - histosMCgen.add("phi_cosTheta_pair_1", "Phi vs cosTheta; #phi; cos(#theta)", kTH2F, {{nBinsPhi, -3.2, 3.2}, {nBinsCosTheta, -1, 1}}); - histosMCgen.add("phi_cosTheta_pair_2", "Phi vs cosTheta; #phi; cos(#theta)", kTH2F, {{nBinsPhi, -3.2, 3.2}, {nBinsCosTheta, -1, 1}}); + histosMCgen.add("phi_vs_costheta_1", "Phi vs cosTheta; #phi; cos(#theta)", kTH2F, {{nBinsPhi, -3.2, 3.2}, {nBinsCosTheta, -1, 1}}); + histosMCgen.add("phi_vs_costheta_2", "Phi vs cosTheta; #phi; cos(#theta)", kTH2F, {{nBinsPhi, -3.2, 3.2}, {nBinsCosTheta, -1, 1}}); // MC Reco Stuff @@ -697,66 +700,66 @@ struct ExclusiveRhoTo4Pi { histosMCreco.add("EventCounts", "Total Events; Events", kTH1F, {{10, 0, 10}}); // TPC nSigma - histosMCreco.add("tpcNSigmaPi_WTS", "TPC nSigma Pion with track selection; Events", kTH2F, {{1000, -15, 15}, {nBinsPt, 0, 10}}); - histosMCreco.add("tpcNSigmaPi_WTS_PID_Pi", "TPC nSigma Pion with track selection and PID Selection of Pi; Entries", kTH2F, {{1000, -15, 15}, {nBinsPt, 0, 10}}); + histosMCreco.add("tpcNSigmaPi_all", "TPC nSigma Pion with track selection; Events", kTH2F, {{1000, -15, 15}, {nBinsPt, 0, 10}}); + histosMCreco.add("tpcNSigmaPi_pions", "TPC nSigma Pion with track selection and PID Selection of Pi; Entries", kTH2F, {{1000, -15, 15}, {nBinsPt, 0, 10}}); // TPC nSigma of other particles with selected pion tracks - histosMCreco.add("tpcNSigmaKa_WTS_PID_Pi", "TPC nSigma Kaon with track selection and PID Selection of Pion; Entries", kTH2F, {{1000, -15, 15}, {nBinsPt, 0, 10}}); - histosMCreco.add("tpcNSigmaPr_WTS_PID_Pi", "TPC nSigma Proton with track selection and PID Selection of Pion; Entries", kTH2F, {{1000, -15, 15}, {nBinsPt, 0, 10}}); - histosMCreco.add("tpcNSigmaEl_WTS_PID_Pi", "TPC nSigma Electron with track selection and PID Selection of Pion; Entries", kTH2F, {{1000, -15, 15}, {nBinsPt, 0, 10}}); - histosMCreco.add("tpcNSigmaMu_WTS_PID_Pi", "TPC nSigma Muon with track selection and PID Selection of Pion; Entries", kTH2F, {{1000, -15, 15}, {nBinsPt, 0, 10}}); + histosMCreco.add("tpcNSigmaKa_pions", "TPC nSigma Kaon with track selection and PID Selection of Pion; Entries", kTH2F, {{1000, -15, 15}, {nBinsPt, 0, 10}}); + histosMCreco.add("tpcNSigmaPr_pions", "TPC nSigma Proton with track selection and PID Selection of Pion; Entries", kTH2F, {{1000, -15, 15}, {nBinsPt, 0, 10}}); + histosMCreco.add("tpcNSigmaEl_pions", "TPC nSigma Electron with track selection and PID Selection of Pion; Entries", kTH2F, {{1000, -15, 15}, {nBinsPt, 0, 10}}); + histosMCreco.add("tpcNSigmaMu_pions", "TPC nSigma Muon with track selection and PID Selection of Pion; Entries", kTH2F, {{1000, -15, 15}, {nBinsPt, 0, 10}}); // TOF nSigma - histosMCreco.add("tofNSigmaPi_WTS", "TOF nSigma Pion with track selection; Events", kTH2F, {{1000, -15, 15}, {nBinsPt, 0, 10}}); - histosMCreco.add("tofNSigmaPi_WTS_PID_Pi", "TOF nSigma Pion with track selection and PID Selection of Pi; Entries", kTH2F, {{1000, -15, 15}, {nBinsPt, 0, 10}}); + histosMCreco.add("tofNSigmaPi_all", "TOF nSigma Pion with track selection; Events", kTH2F, {{1000, -15, 15}, {nBinsPt, 0, 10}}); + histosMCreco.add("tofNSigmaPi_pions", "TOF nSigma Pion with track selection and PID Selection of Pi; Entries", kTH2F, {{1000, -15, 15}, {nBinsPt, 0, 10}}); // TOF nSigma of other particles with selected pion tracks - histosMCreco.add("tofNSigmaKa_WTS_PID_Pi", "TOF nSigma Kaon with track selection and PID Selection of Pion; Entries", kTH2F, {{1000, -15, 15}, {nBinsPt, 0, 10}}); - histosMCreco.add("tofNSigmaPr_WTS_PID_Pi", "TOF nSigma Proton with track selection and PID Selection of Pion; Entries", kTH2F, {{1000, -15, 15}, {nBinsPt, 0, 10}}); - histosMCreco.add("tofNSigmaEl_WTS_PID_Pi", "TOF nSigma Electron with track selection and PID Selection of Pion; Entries", kTH2F, {{1000, -15, 15}, {nBinsPt, 0, 10}}); - histosMCreco.add("tofNSigmaMu_WTS_PID_Pi", "TOF nSigma Muon with track selection and PID Selection of Pion; Entries", kTH2F, {{1000, -15, 15}, {nBinsPt, 0, 10}}); + histosMCreco.add("tofNSigmaKa_pions", "TOF nSigma Kaon with track selection and PID Selection of Pion; Entries", kTH2F, {{1000, -15, 15}, {nBinsPt, 0, 10}}); + histosMCreco.add("tofNSigmaPr_pions", "TOF nSigma Proton with track selection and PID Selection of Pion; Entries", kTH2F, {{1000, -15, 15}, {nBinsPt, 0, 10}}); + histosMCreco.add("tofNSigmaEl_pions", "TOF nSigma Electron with track selection and PID Selection of Pion; Entries", kTH2F, {{1000, -15, 15}, {nBinsPt, 0, 10}}); + histosMCreco.add("tofNSigmaMu_pions", "TOF nSigma Muon with track selection and PID Selection of Pion; Entries", kTH2F, {{1000, -15, 15}, {nBinsPt, 0, 10}}); // Track Transverse Momentum - histosMCreco.add("pT_track_WTS", "pT with track selection; pT [GeV/c]; Counts", kTH1F, {{nBinsPt, 0, 2}}); - histosMCreco.add("pT_track_WTS_PID_Pi", "pT with track selection and PID selection of Pi; pT [GeV/c]; Events", kTH1F, {{nBinsPt, 0, 2}}); - histosMCreco.add("pT_track_WTS_PID_Pi_contributed", "pT with track selection and PID selection of Pi which are contributed to selected event; pT [GeV/c]; Events", kTH1F, {{nBinsPt, 0, 2}}); + histosMCreco.add("pT_track_all", "pT with track selection; pT [GeV/c]; Counts", kTH1F, {{nBinsPt, 0, 2}}); + histosMCreco.add("pT_track_pions", "pT with track selection and PID selection of Pi; pT [GeV/c]; Events", kTH1F, {{nBinsPt, 0, 2}}); + histosMCreco.add("pT_track_pions_contributed", "pT with track selection and PID selection of Pi which are contributed to selected event; pT [GeV/c]; Events", kTH1F, {{nBinsPt, 0, 2}}); // Track Rapidity - histosMCreco.add("rapidity_track_WTS", "Rapidity with track selection; y; Counts", kTH1F, {{nBinsRapidity, -2.5, 2.5}}); - histosMCreco.add("rapidity_track_WTS_PID_Pi", "Rapidity with track selection and PID selection of Pi; y; Events", kTH1F, {{nBinsRapidity, -2.5, 2.5}}); - histosMCreco.add("rapidity_track_WTS_PID_Pi_contributed", "Rapidity with track selection and PID selection of Pi which are contributed to selected event; y; Events", kTH1F, {{nBinsRapidity, -2.5, 2.5}}); + histosMCreco.add("rapidity_track_all", "Rapidity with track selection; y; Counts", kTH1F, {{nBinsRapidity, -2.5, 2.5}}); + histosMCreco.add("rapidity_track_pions", "Rapidity with track selection and PID selection of Pi; y; Events", kTH1F, {{nBinsRapidity, -2.5, 2.5}}); + histosMCreco.add("rapidity_track_pions_contributed", "Rapidity with track selection and PID selection of Pi which are contributed to selected event; y; Events", kTH1F, {{nBinsRapidity, -2.5, 2.5}}); // Zero charge Event Transverse Momentum - histosMCreco.add("pT_event_0charge_WTS_PID_Pi", "Event pT in 0 Charge Events With Track Selection and PID Selection of Pi; pT [GeV/c]; Events", kTH1F, {{nBinsPt, 0, 2}}); + histosMCreco.add("fourpion_pT_0_charge", "Event pT in 0 Charge Events With Track Selection and PID Selection of Pi; pT [GeV/c]; Events", kTH1F, {{nBinsPt, 0, 2}}); // Non Zero charge Event Transverse Momentum - histosMCreco.add("pT_event_non0charge_WTS_PID_Pi", "Event pT in Non 0 Charge Events With Track Selection and PID Selection of Pi; pT [GeV/c]; Events", kTH1F, {{nBinsPt, 0, 2}}); + histosMCreco.add("fourpion_pT_non_0_charge", "Event pT in Non 0 Charge Events With Track Selection and PID Selection of Pi; pT [GeV/c]; Events", kTH1F, {{nBinsPt, 0, 2}}); // Rapidity of 0 charge Events - histosMCreco.add("rapidity_event_0charge_WTS_PID_Pi_domainA", "Rapidity of Events With Track Selection and PID Selection of Pi for p_{T} < 0.15 GeV/c; y; Events", kTH1F, {{1000, -2.5, 2.5}}); - histosMCreco.add("rapidity_event_0charge_WTS_PID_Pi_domainB", "Rapidity of Events With Track Selection and PID Selection of Pi for 0.15< p_{T} < 0.80 GeV/c; y; Events", kTH1F, {{1000, -2.5, 2.5}}); - histosMCreco.add("rapidity_event_0charge_WTS_PID_Pi_domainC", "Rapidity of Events With Track Selection and PID Selection of Pi for p_{T} > 0.80 GeV/c; y; Events", kTH1F, {{1000, -2.5, 2.5}}); + histosMCreco.add("fourpion_rap_0_charge_domA", "Rapidity of Events With Track Selection and PID Selection of Pi for p_{T} < 0.15 GeV/c; y; Events", kTH1F, {{1000, -2.5, 2.5}}); + histosMCreco.add("fourpion_rap_0_charge_domB", "Rapidity of Events With Track Selection and PID Selection of Pi for 0.15< p_{T} < 0.80 GeV/c; y; Events", kTH1F, {{1000, -2.5, 2.5}}); + histosMCreco.add("fourpion_rap_0_charge_domC", "Rapidity of Events With Track Selection and PID Selection of Pi for p_{T} > 0.80 GeV/c; y; Events", kTH1F, {{1000, -2.5, 2.5}}); // Rapidity of non 0 charge Events - histosMCreco.add("rapidity_event_non0charge_WTS_PID_Pi_domainA", "Rapidity of Events With Track Selection and PID Selection of Pi for p_{T} < 0.15 GeV/c; y; Events", kTH1F, {{nBinsRapidity, -2.5, 2.5}}); - histosMCreco.add("rapidity_event_non0charge_WTS_PID_Pi_domainB", "Rapidity of Events With Track Selection and PID Selection of Pi for 0.15< p_{T} < 0.80 GeV/c$; y; Events", kTH1F, {{nBinsRapidity, -2.5, 2.5}}); - histosMCreco.add("rapidity_event_non0charge_WTS_PID_Pi_domainC", "Rapidity of Events With Track Selection and PID Selection of Pi for p_{T} > 0.80 GeV/c; y; Events", kTH1F, {{nBinsRapidity, -2.5, 2.5}}); + histosMCreco.add("fourpion_rap_non_0_charge_domA", "Rapidity of Events With Track Selection and PID Selection of Pi for p_{T} < 0.15 GeV/c; y; Events", kTH1F, {{nBinsRapidity, -2.5, 2.5}}); + histosMCreco.add("fourpion_rap_non_0_charge_domB", "Rapidity of Events With Track Selection and PID Selection of Pi for 0.15< p_{T} < 0.80 GeV/c$; y; Events", kTH1F, {{nBinsRapidity, -2.5, 2.5}}); + histosMCreco.add("fourpion_rap_non_0_charge_domC", "Rapidity of Events With Track Selection and PID Selection of Pi for p_{T} > 0.80 GeV/c; y; Events", kTH1F, {{nBinsRapidity, -2.5, 2.5}}); // Pair Invariant Mass - histosMCreco.add("invMass_pair_1", "Invariant Mass Distribution of 2 pions 1 ; m(#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {{5000, 0, 5}}); - histosMCreco.add("invMass_pair_2", "Invariant Mass Distribution of 2 pions 2 ; m(#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {{5000, 0, 5}}); - histosMCreco.add("invMass_pair_3", "Invariant Mass Distribution of 2 pions 3 ; m(#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {{5000, 0, 5}}); - histosMCreco.add("invMass_pair_4", "Invariant Mass Distribution of 2 pions 4 ; m(#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {{5000, 0, 5}}); + histosMCreco.add("twopion_mass_1", "Invariant Mass Distribution of 2 pions 1 ; m(#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {{5000, 0, 5}}); + histosMCreco.add("twopion_mass_2", "Invariant Mass Distribution of 2 pions 2 ; m(#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {{5000, 0, 5}}); + histosMCreco.add("twopion_mass_3", "Invariant Mass Distribution of 2 pions 3 ; m(#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {{5000, 0, 5}}); + histosMCreco.add("twopion_mass_4", "Invariant Mass Distribution of 2 pions 4 ; m(#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {{5000, 0, 5}}); // Invariant Mass of 0 charge events - histosMCreco.add("invMass_event_0charge_WTS_PID_Pi_domainA", "Invariant Mass Distribution of 0 charge Events with PID Selection of Pi for p_{T} < 0.15 GeV/c; m(#pi^{+}#pi^{-}#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {{nBinsInvariantMass, invariantMassMin, invariantMassMax}}); // pT < 0.15GeV - histosMCreco.add("invMass_event_0charge_WTS_PID_Pi_domainB", "Invariant Mass Distribution of 0 charge Events with PID Selection of Pi for 0.15< p_{T} < 0.80 GeV/c; m(#pi^{+}#pi^{-}#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {{nBinsInvariantMass, invariantMassMin, invariantMassMax}}); // 0.15GeV < pT < 0.8GeV - histosMCreco.add("invMass_event_0charge_WTS_PID_Pi_domainC", "Invariant Mass Distribution of 0 charge Events with PID Selection of Pi for p_{T} > 0.80 GeV/c; m(#pi^{+}#pi^{-}#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {{nBinsInvariantMass, invariantMassMin, invariantMassMax}}); // 0.8GeV < pT + histosMCreco.add("fourpion_mass_0_charge_domA", "Invariant Mass Distribution of 0 charge Events with PID Selection of Pi for p_{T} < 0.15 GeV/c; m(#pi^{+}#pi^{-}#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {{nBinsInvariantMass, invariantMassMin, invariantMassMax}}); // pT < 0.15GeV + histosMCreco.add("fourpion_mass_0_charge_domB", "Invariant Mass Distribution of 0 charge Events with PID Selection of Pi for 0.15< p_{T} < 0.80 GeV/c; m(#pi^{+}#pi^{-}#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {{nBinsInvariantMass, invariantMassMin, invariantMassMax}}); // 0.15GeV < pT < 0.8GeV + histosMCreco.add("fourpion_mass_0_charge_domC", "Invariant Mass Distribution of 0 charge Events with PID Selection of Pi for p_{T} > 0.80 GeV/c; m(#pi^{+}#pi^{-}#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {{nBinsInvariantMass, invariantMassMin, invariantMassMax}}); // 0.8GeV < pT // Invariant mass of non 0 charge events - histosMCreco.add("invMass_event_non0charge_WTS_PID_Pi_domainA", "Invariant Mass Distribution of non 0 charge Events with PID Selection of Pi for p_{T} < 0.15 GeV/c; m(#pi^{+}#pi^{-}#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {{nBinsInvariantMass, invariantMassMin, invariantMassMax}}); // pT < 0.15GeV - histosMCreco.add("invMass_event_non0charge_WTS_PID_Pi_domainB", "Invariant Mass Distribution of non 0 charge Events with PID Selection of Pi for 0.15< p_{T} < 0.80 GeV/c; m(#pi^{+}#pi^{-}#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {{nBinsInvariantMass, invariantMassMin, invariantMassMax}}); // 0.15GeV < pT < 0.8GeV - histosMCreco.add("invMass_event_non0charge_WTS_PID_Pi_domainC", "Invariant Mass Distribution of non 0 charge Events with PID Selection of Pi for p_{T} > 0.80 GeV/c; m(#pi^{+}#pi^{-}#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {{nBinsInvariantMass, invariantMassMin, invariantMassMax}}); // 0.8GeV < pT + histosMCreco.add("fourpion_mass_non_0_charge_domA", "Invariant Mass Distribution of non 0 charge Events with PID Selection of Pi for p_{T} < 0.15 GeV/c; m(#pi^{+}#pi^{-}#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {{nBinsInvariantMass, invariantMassMin, invariantMassMax}}); // pT < 0.15GeV + histosMCreco.add("fourpion_mass_non_0_charge_domB", "Invariant Mass Distribution of non 0 charge Events with PID Selection of Pi for 0.15< p_{T} < 0.80 GeV/c; m(#pi^{+}#pi^{-}#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {{nBinsInvariantMass, invariantMassMin, invariantMassMax}}); // 0.15GeV < pT < 0.8GeV + histosMCreco.add("fourpion_mass_non_0_charge_domC", "Invariant Mass Distribution of non 0 charge Events with PID Selection of Pi for p_{T} > 0.80 GeV/c; m(#pi^{+}#pi^{-}#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {{nBinsInvariantMass, invariantMassMin, invariantMassMax}}); // 0.8GeV < pT // tpc signal histosMCreco.add("tpcSignal", "TPC dEdx vs p; p [GeV/c]; dEdx [a.u.]", kTH2F, {{500, 0, 10}, {5000, 0.0, 5000.0}}); @@ -774,12 +777,12 @@ struct ExclusiveRhoTo4Pi { histosMCreco.add("V0A", "V0A amplitude", kTH1F, {{1000, 0.0, 100}}); // Collin Soper Theta and Phi - histosMCreco.add("CS_phi_pair_1", "#phi Distribution; #phi; Events", kTH1F, {{nBinsPhi, -3.2, 3.2}}); - histosMCreco.add("CS_phi_pair_2", "#phi Distribution; #phi; Events", kTH1F, {{nBinsPhi, -3.2, 3.2}}); - histosMCreco.add("CS_costheta_pair_1", "#theta Distribution;cos(#theta); Counts", kTH1F, {{nBinsCosTheta, -1, 1}}); - histosMCreco.add("CS_costheta_pair_2", "#theta Distribution;cos(#theta); Counts", kTH1F, {{nBinsCosTheta, -1, 1}}); - histosMCreco.add("phi_cosTheta_pair_1", "Phi vs cosTheta; #phi; cos(#theta)", kTH2F, {{nBinsPhi, -3.2, 3.2}, {nBinsCosTheta, -1, 1}}); - histosMCreco.add("phi_cosTheta_pair_2", "Phi vs cosTheta; #phi; cos(#theta)", kTH2F, {{nBinsPhi, -3.2, 3.2}, {nBinsCosTheta, -1, 1}}); + histosMCreco.add("collin_soper_phi_1", "#phi Distribution; #phi; Events", kTH1F, {{nBinsPhi, -3.2, 3.2}}); + histosMCreco.add("collin_soper_phi_2", "#phi Distribution; #phi; Events", kTH1F, {{nBinsPhi, -3.2, 3.2}}); + histosMCreco.add("collin_soper_costheta_1", "#theta Distribution;cos(#theta); Counts", kTH1F, {{nBinsCosTheta, -1, 1}}); + histosMCreco.add("collin_soper_costheta_2", "#theta Distribution;cos(#theta); Counts", kTH1F, {{nBinsCosTheta, -1, 1}}); + histosMCreco.add("phi_vs_costheta_1", "Phi vs cosTheta; #phi; cos(#theta)", kTH2F, {{nBinsPhi, -3.2, 3.2}, {nBinsCosTheta, -1, 1}}); + histosMCreco.add("phi_vs_costheta_2", "Phi vs cosTheta; #phi; cos(#theta)", kTH2F, {{nBinsPhi, -3.2, 3.2}, {nBinsCosTheta, -1, 1}}); } // End of init function //---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- @@ -845,7 +848,9 @@ struct ExclusiveRhoTo4Pi { Filter vertexCut = (nabs(o2::aod::collision::posZ) <= vZCut) && (o2::aod::collision::numContrib == numPVContrib); Filter fitcuts = o2::aod::udcollision::totalFV0AmplitudeA < fv0Cut && o2::aod::udcollision::totalFT0AmplitudeA < ft0aCut && o2::aod::udcollision::totalFT0AmplitudeC < ft0cCut; Filter zdcCuts = (o2::aod::udzdc::energyCommonZNA < zdcCut) && (o2::aod::udzdc::energyCommonZNC < zdcCut); - using UDtracks = soa::Join; + Filter bcSelectionCut = (o2::aod::udcollision::sbp == sbpCut) && (o2::aod::udcollision::itsROFb == itsROFbCut) && (o2::aod::udcollision::vtxITSTPC == vtxITSTPCcut) && (o2::aod::udcollision::tfb == tfbCut); + Filter onlyPVtracks = o2::aod::udtrack::isPVContributor == true; + using UDtracks = soa::Filtered>; using UDCollisions = soa::Filtered>; // using UDCollision = UDCollisions::iterator; //---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- @@ -897,10 +902,10 @@ struct ExclusiveRhoTo4Pi { ROOT::Math::PxPyPzMVector selectedTrackVector(selectedTracks[i].px(), selectedTracks[i].py(), selectedTracks[i].pz(), o2::constants::physics::MassPionCharged); histosData.fill(HIST("tpcSignal"), selectedTrackVector.P(), selectedTracks[i].tpcSignal()); histosData.fill(HIST("tofBeta"), selectedTrackVector.P(), selectedTracks[i].beta()); - histosData.fill(HIST("tpcNSigmaPi_WTS"), selectedTracks[i].tpcNSigmaPi(), selectedTrackVector.Pt()); - histosData.fill(HIST("tofNSigmaPi_WTS"), selectedTracks[i].tofNSigmaPi(), selectedTrackVector.Pt()); - histosData.fill(HIST("pT_track_WTS"), selectedTrackVector.Pt()); - histosData.fill(HIST("rapidity_track_WTS"), selectedTrackVector.Rapidity()); + histosData.fill(HIST("tpcNSigmaPi_all"), selectedTracks[i].tpcNSigmaPi(), selectedTrackVector.Pt()); + histosData.fill(HIST("tofNSigmaPi_all"), selectedTracks[i].tofNSigmaPi(), selectedTrackVector.Pt()); + histosData.fill(HIST("pT_track_all"), selectedTrackVector.Pt()); + histosData.fill(HIST("rapidity_track_all"), selectedTrackVector.Rapidity()); histosData.fill(HIST("itsChi2NCl"), selectedTracks[i].itsChi2NCl()); histosData.fill(HIST("tpcChi2NCl"), selectedTracks[i].tpcChi2NCl()); histosData.fill(HIST("tpcNClsFindable"), selectedTracks[i].tpcNClsFindable()); @@ -912,24 +917,26 @@ struct ExclusiveRhoTo4Pi { ROOT::Math::PxPyPzMVector selectedPionTrackVector(selectedPionTracks[i].px(), selectedPionTracks[i].py(), selectedPionTracks[i].pz(), o2::constants::physics::MassPionCharged); histosData.fill(HIST("tpcSignal_Pi"), selectedPionTrackVector.P(), selectedPionTracks[i].tpcSignal()); histosData.fill(HIST("tofBeta_Pi"), selectedPionTrackVector.P(), selectedPionTracks[i].beta()); - histosData.fill(HIST("tpcNSigmaPi_WTS_PID_Pi"), selectedPionTracks[i].tpcNSigmaPi(), selectedPionTrackVector.Pt()); - histosData.fill(HIST("tpcNSigmaKa_WTS_PID_Pi"), selectedPionTracks[i].tpcNSigmaKa(), selectedPionTrackVector.Pt()); - histosData.fill(HIST("tpcNSigmaPr_WTS_PID_Pi"), selectedPionTracks[i].tpcNSigmaPr(), selectedPionTrackVector.Pt()); - histosData.fill(HIST("tpcNSigmaEl_WTS_PID_Pi"), selectedPionTracks[i].tpcNSigmaEl(), selectedPionTrackVector.Pt()); - histosData.fill(HIST("tpcNSigmaMu_WTS_PID_Pi"), selectedPionTracks[i].tpcNSigmaMu(), selectedPionTrackVector.Pt()); - histosData.fill(HIST("tofNSigmaPi_WTS_PID_Pi"), selectedPionTracks[i].tofNSigmaPi(), selectedPionTrackVector.Pt()); - histosData.fill(HIST("tofNSigmaKa_WTS_PID_Pi"), selectedPionTracks[i].tofNSigmaKa(), selectedPionTrackVector.Pt()); - histosData.fill(HIST("tofNSigmaPr_WTS_PID_Pi"), selectedPionTracks[i].tofNSigmaPr(), selectedPionTrackVector.Pt()); - histosData.fill(HIST("tofNSigmaEl_WTS_PID_Pi"), selectedPionTracks[i].tofNSigmaEl(), selectedPionTrackVector.Pt()); - histosData.fill(HIST("tofNSigmaMu_WTS_PID_Pi"), selectedPionTracks[i].tofNSigmaMu(), selectedPionTrackVector.Pt()); - histosData.fill(HIST("pT_track_WTS_PID_Pi"), selectedPionTrackVector.Pt()); - histosData.fill(HIST("rapidity_track_WTS_PID_Pi"), selectedPionTrackVector.Rapidity()); + histosData.fill(HIST("tpcNSigmaPi_pions"), selectedPionTracks[i].tpcNSigmaPi(), selectedPionTrackVector.Pt()); + histosData.fill(HIST("tpcNSigmaKa_pions"), selectedPionTracks[i].tpcNSigmaKa(), selectedPionTrackVector.Pt()); + histosData.fill(HIST("tpcNSigmaPr_pions"), selectedPionTracks[i].tpcNSigmaPr(), selectedPionTrackVector.Pt()); + histosData.fill(HIST("tpcNSigmaEl_pions"), selectedPionTracks[i].tpcNSigmaEl(), selectedPionTrackVector.Pt()); + histosData.fill(HIST("tpcNSigmaMu_pions"), selectedPionTracks[i].tpcNSigmaMu(), selectedPionTrackVector.Pt()); + histosData.fill(HIST("tofNSigmaPi_pions"), selectedPionTracks[i].tofNSigmaPi(), selectedPionTrackVector.Pt()); + histosData.fill(HIST("tofNSigmaKa_pions"), selectedPionTracks[i].tofNSigmaKa(), selectedPionTrackVector.Pt()); + histosData.fill(HIST("tofNSigmaPr_pions"), selectedPionTracks[i].tofNSigmaPr(), selectedPionTrackVector.Pt()); + histosData.fill(HIST("tofNSigmaEl_pions"), selectedPionTracks[i].tofNSigmaEl(), selectedPionTrackVector.Pt()); + histosData.fill(HIST("tofNSigmaMu_pions"), selectedPionTracks[i].tofNSigmaMu(), selectedPionTrackVector.Pt()); + histosData.fill(HIST("pT_track_pions"), selectedPionTrackVector.Pt()); + histosData.fill(HIST("rapidity_track_pions"), selectedPionTrackVector.Rapidity()); } // End of loop over tracks with selection and PID selection of Pions if (numSelectedPionTracks != numFourPionTracks) { return; } + histosData.fill(HIST("EventCounts"), 2); + // Check if there is at least one track with TOF in the selected events, otherwise return bool hasAtleastOneTOF = false; for (int i = 0; i < numPiPlusTracks; i++) { @@ -941,10 +948,13 @@ struct ExclusiveRhoTo4Pi { if (!hasAtleastOneTOF) { return; } + histosData.fill(HIST("EventCounts"), 3); // Selecting Events with net charge = 0 if (numPionMinusTracks == numPiMinus && numPiPlusTracks == numPiPlus) { + histosData.fill(HIST("EventCounts"), 4); + ROOT::Math::PtEtaPhiMVector k1, k2, k3, k4, k1234, k13, k14, k23, k24; ROOT::Math::PxPyPzMVector p1(selectedPionPlusTracks[0].px(), selectedPionPlusTracks[0].py(), selectedPionPlusTracks[0].pz(), o2::constants::physics::MassPionCharged); @@ -952,15 +962,15 @@ struct ExclusiveRhoTo4Pi { ROOT::Math::PxPyPzMVector p3(selectedPionMinusTracks[0].px(), selectedPionMinusTracks[0].py(), selectedPionMinusTracks[0].pz(), o2::constants::physics::MassPionCharged); ROOT::Math::PxPyPzMVector p4(selectedPionMinusTracks[1].px(), selectedPionMinusTracks[1].py(), selectedPionMinusTracks[1].pz(), o2::constants::physics::MassPionCharged); - histosData.fill(HIST("pT_track_WTS_PID_Pi_contributed"), p1.Pt()); - histosData.fill(HIST("pT_track_WTS_PID_Pi_contributed"), p2.Pt()); - histosData.fill(HIST("pT_track_WTS_PID_Pi_contributed"), p3.Pt()); - histosData.fill(HIST("pT_track_WTS_PID_Pi_contributed"), p4.Pt()); + histosData.fill(HIST("pT_track_pions_contributed"), p1.Pt()); + histosData.fill(HIST("pT_track_pions_contributed"), p2.Pt()); + histosData.fill(HIST("pT_track_pions_contributed"), p3.Pt()); + histosData.fill(HIST("pT_track_pions_contributed"), p4.Pt()); - histosData.fill(HIST("rapidity_track_WTS_PID_Pi_contributed"), p1.Rapidity()); - histosData.fill(HIST("rapidity_track_WTS_PID_Pi_contributed"), p2.Rapidity()); - histosData.fill(HIST("rapidity_track_WTS_PID_Pi_contributed"), p3.Rapidity()); - histosData.fill(HIST("rapidity_track_WTS_PID_Pi_contributed"), p4.Rapidity()); + histosData.fill(HIST("rapidity_track_pions_contributed"), p1.Rapidity()); + histosData.fill(HIST("rapidity_track_pions_contributed"), p2.Rapidity()); + histosData.fill(HIST("rapidity_track_pions_contributed"), p3.Rapidity()); + histosData.fill(HIST("rapidity_track_pions_contributed"), p4.Rapidity()); k1.SetCoordinates(p1.Pt(), p1.Eta(), p1.Phi(), o2::constants::physics::MassPionCharged); k2.SetCoordinates(p2.Pt(), p2.Eta(), p2.Phi(), o2::constants::physics::MassPionCharged); @@ -1012,31 +1022,34 @@ struct ExclusiveRhoTo4Pi { fourPiPhiPair1, fourPiPhiPair2, fourPiCosThetaPair1, fourPiCosThetaPair2); if (std::fabs(p1234.Rapidity()) < rhoRapCut) { - histosData.fill(HIST("pT_event_0charge_WTS_PID_Pi"), p1234.Pt()); + histosData.fill(HIST("fourpion_pT_0_charge"), p1234.Pt()); if (p1234.Pt() < rhoPtCut) { - histosData.fill(HIST("rapidity_event_0charge_WTS_PID_Pi_domainA"), p1234.Rapidity()); - histosData.fill(HIST("invMass_event_0charge_WTS_PID_Pi_domainA"), p1234.M()); - histosData.fill(HIST("invMass_pair_1"), (p1 + p3).M()); - histosData.fill(HIST("invMass_pair_2"), (p1 + p4).M()); - histosData.fill(HIST("invMass_pair_3"), (p2 + p3).M()); - histosData.fill(HIST("invMass_pair_4"), (p2 + p4).M()); + histosData.fill(HIST("EventCounts"), 5); + + histosData.fill(HIST("fourpion_rap_0_charge_domA"), p1234.Rapidity()); + histosData.fill(HIST("fourpion_mass_0_charge_domA"), p1234.M()); - histosData.fill(HIST("CS_phi_pair_1"), fourPiPhiPair1); - histosData.fill(HIST("CS_phi_pair_2"), fourPiPhiPair2); - histosData.fill(HIST("CS_costheta_pair_1"), fourPiCosThetaPair1); - histosData.fill(HIST("CS_costheta_pair_2"), fourPiCosThetaPair2); + histosData.fill(HIST("twopion_mass_1"), (p1 + p3).M()); + histosData.fill(HIST("twopion_mass_2"), (p1 + p4).M()); + histosData.fill(HIST("twopion_mass_3"), (p2 + p3).M()); + histosData.fill(HIST("twopion_mass_4"), (p2 + p4).M()); - histosData.fill(HIST("phi_cosTheta_pair_1"), fourPiPhiPair1, fourPiCosThetaPair1); - histosData.fill(HIST("phi_cosTheta_pair_2"), fourPiPhiPair2, fourPiCosThetaPair2); + histosData.fill(HIST("collin_soper_phi_1"), fourPiPhiPair1); + histosData.fill(HIST("collin_soper_phi_2"), fourPiPhiPair2); + histosData.fill(HIST("collin_soper_costheta_1"), fourPiCosThetaPair1); + histosData.fill(HIST("collin_soper_costheta_2"), fourPiCosThetaPair2); + + histosData.fill(HIST("phi_vs_costheta_1"), fourPiPhiPair1, fourPiCosThetaPair1); + histosData.fill(HIST("phi_vs_costheta_2"), fourPiPhiPair2, fourPiCosThetaPair2); } if (p1234.Pt() > rhoPtCut && p1234.Pt() < zeroPointEight) { - histosData.fill(HIST("rapidity_event_0charge_WTS_PID_Pi_domainB"), p1234.Rapidity()); - histosData.fill(HIST("invMass_event_0charge_WTS_PID_Pi_domainB"), p1234.M()); + histosData.fill(HIST("fourpion_rap_0_charge_domB"), p1234.Rapidity()); + histosData.fill(HIST("fourpion_mass_0_charge_domB"), p1234.M()); } if (p1234.Pt() > zeroPointEight) { - histosData.fill(HIST("rapidity_event_0charge_WTS_PID_Pi_domainC"), p1234.Rapidity()); - histosData.fill(HIST("invMass_event_0charge_WTS_PID_Pi_domainC"), p1234.M()); + histosData.fill(HIST("fourpion_rap_0_charge_domC"), p1234.Rapidity()); + histosData.fill(HIST("fourpion_mass_0_charge_domC"), p1234.M()); } } // End of Rapidity range selection @@ -1045,6 +1058,8 @@ struct ExclusiveRhoTo4Pi { // Selecting Events with net charge != 0 for estimation of background if (numPionMinusTracks != numPiMinus && numPiPlusTracks != numPiPlus) { + histosData.fill(HIST("EventCounts"), 6); + ROOT::Math::PxPyPzMVector p1(selectedPionTracks[0].px(), selectedPionTracks[0].py(), selectedPionTracks[0].pz(), o2::constants::physics::MassPionCharged); ROOT::Math::PxPyPzMVector p2(selectedPionTracks[1].px(), selectedPionTracks[1].py(), selectedPionTracks[1].pz(), o2::constants::physics::MassPionCharged); ROOT::Math::PxPyPzMVector p3(selectedPionTracks[2].px(), selectedPionTracks[2].py(), selectedPionTracks[2].pz(), o2::constants::physics::MassPionCharged); @@ -1074,19 +1089,20 @@ struct ExclusiveRhoTo4Pi { p1234.Pt(), p1234.Eta(), p1234.Phi(), p1234.Rapidity(), p1234.M()); if (std::fabs(p1234.Rapidity()) < rhoRapCut) { - histosData.fill(HIST("pT_event_non0charge_WTS_PID_Pi"), p1234.Pt()); + histosData.fill(HIST("fourpion_pT_non_0_charge"), p1234.Pt()); if (p1234.Pt() < rhoPtCut) { - histosData.fill(HIST("rapidity_event_non0charge_WTS_PID_Pi_domainA"), p1234.Rapidity()); - histosData.fill(HIST("invMass_event_non0charge_WTS_PID_Pi_domainA"), p1234.M()); + histosData.fill(HIST("EventCounts"), 7); + histosData.fill(HIST("fourpion_rap_non_0_charge_domA"), p1234.Rapidity()); + histosData.fill(HIST("fourpion_mass_non_0_charge_domA"), p1234.M()); } if (p1234.Pt() > rhoPtCut && p1234.Pt() < zeroPointEight) { - histosData.fill(HIST("rapidity_event_non0charge_WTS_PID_Pi_domainB"), p1234.Rapidity()); - histosData.fill(HIST("invMass_event_non0charge_WTS_PID_Pi_domainB"), p1234.M()); + histosData.fill(HIST("fourpion_rap_non_0_charge_domB"), p1234.Rapidity()); + histosData.fill(HIST("fourpion_mass_non_0_charge_domB"), p1234.M()); } if (p1234.Pt() > zeroPointEight) { - histosData.fill(HIST("rapidity_event_non0charge_WTS_PID_Pi_domainC"), p1234.Rapidity()); - histosData.fill(HIST("invMass_event_non0charge_WTS_PID_Pi_domainC"), p1234.M()); + histosData.fill(HIST("fourpion_rap_non_0_charge_domC"), p1234.Rapidity()); + histosData.fill(HIST("fourpion_mass_non_0_charge_domC"), p1234.M()); } } // End of Rapidity range selection } // End of Analysis for non 0 charge events @@ -1186,8 +1202,8 @@ struct ExclusiveRhoTo4Pi { histosMCgen.fill(HIST("fourPion_phi_pair_2"), phiPair2); histosMCgen.fill(HIST("fourPion_costheta_pair_1"), cosThetaPair1); histosMCgen.fill(HIST("fourPion_costheta_pair_2"), cosThetaPair2); - histosMCgen.fill(HIST("phi_cosTheta_pair_1"), phiPair1, cosThetaPair1); - histosMCgen.fill(HIST("phi_cosTheta_pair_2"), phiPair2, cosThetaPair2); + histosMCgen.fill(HIST("phi_vs_costheta_1"), phiPair1, cosThetaPair1); + histosMCgen.fill(HIST("phi_vs_costheta_2"), phiPair2, cosThetaPair2); } // End of 4 Pion MC Generation Process function PROCESS_SWITCH(ExclusiveRhoTo4Pi, processMCgen, "The Process for 4 Pion Analysis from MC Generation", false); @@ -1247,10 +1263,10 @@ struct ExclusiveRhoTo4Pi { ROOT::Math::PxPyPzMVector selectedTrackVector(selectedTracks[i].px(), selectedTracks[i].py(), selectedTracks[i].pz(), o2::constants::physics::MassPionCharged); histosMCreco.fill(HIST("tpcSignal"), selectedTrackVector.P(), selectedTracks[i].tpcSignal()); histosMCreco.fill(HIST("tofBeta"), selectedTrackVector.P(), selectedTracks[i].beta()); - histosMCreco.fill(HIST("tpcNSigmaPi_WTS"), selectedTracks[i].tpcNSigmaPi(), selectedTrackVector.Pt()); - histosMCreco.fill(HIST("tofNSigmaPi_WTS"), selectedTracks[i].tofNSigmaPi(), selectedTrackVector.Pt()); - histosMCreco.fill(HIST("pT_track_WTS"), selectedTrackVector.Pt()); - histosMCreco.fill(HIST("rapidity_track_WTS"), selectedTrackVector.Rapidity()); + histosMCreco.fill(HIST("tpcNSigmaPi_all"), selectedTracks[i].tpcNSigmaPi(), selectedTrackVector.Pt()); + histosMCreco.fill(HIST("tofNSigmaPi_all"), selectedTracks[i].tofNSigmaPi(), selectedTrackVector.Pt()); + histosMCreco.fill(HIST("pT_track_all"), selectedTrackVector.Pt()); + histosMCreco.fill(HIST("rapidity_track_all"), selectedTrackVector.Rapidity()); histosMCreco.fill(HIST("itsChi2NCl"), selectedTracks[i].itsChi2NCl()); histosMCreco.fill(HIST("tpcChi2NCl"), selectedTracks[i].tpcChi2NCl()); histosMCreco.fill(HIST("tpcNClsFindable"), selectedTracks[i].tpcNClsFindable()); @@ -1262,18 +1278,18 @@ struct ExclusiveRhoTo4Pi { ROOT::Math::PxPyPzMVector selectedPionTrackVector(selectedPionTracks[i].px(), selectedPionTracks[i].py(), selectedPionTracks[i].pz(), o2::constants::physics::MassPionCharged); histosMCreco.fill(HIST("tpcSignal_Pi"), selectedPionTrackVector.P(), selectedPionTracks[i].tpcSignal()); histosMCreco.fill(HIST("tofBeta_Pi"), selectedPionTrackVector.P(), selectedPionTracks[i].beta()); - histosMCreco.fill(HIST("tpcNSigmaPi_WTS_PID_Pi"), selectedPionTracks[i].tpcNSigmaPi(), selectedPionTrackVector.Pt()); - histosMCreco.fill(HIST("tpcNSigmaKa_WTS_PID_Pi"), selectedPionTracks[i].tpcNSigmaKa(), selectedPionTrackVector.Pt()); - histosMCreco.fill(HIST("tpcNSigmaPr_WTS_PID_Pi"), selectedPionTracks[i].tpcNSigmaPr(), selectedPionTrackVector.Pt()); - histosMCreco.fill(HIST("tpcNSigmaEl_WTS_PID_Pi"), selectedPionTracks[i].tpcNSigmaEl(), selectedPionTrackVector.Pt()); - histosMCreco.fill(HIST("tpcNSigmaMu_WTS_PID_Pi"), selectedPionTracks[i].tpcNSigmaMu(), selectedPionTrackVector.Pt()); - histosMCreco.fill(HIST("tofNSigmaPi_WTS_PID_Pi"), selectedPionTracks[i].tofNSigmaPi(), selectedPionTrackVector.Pt()); - histosMCreco.fill(HIST("tofNSigmaKa_WTS_PID_Pi"), selectedPionTracks[i].tofNSigmaKa(), selectedPionTrackVector.Pt()); - histosMCreco.fill(HIST("tofNSigmaPr_WTS_PID_Pi"), selectedPionTracks[i].tofNSigmaPr(), selectedPionTrackVector.Pt()); - histosMCreco.fill(HIST("tofNSigmaEl_WTS_PID_Pi"), selectedPionTracks[i].tofNSigmaEl(), selectedPionTrackVector.Pt()); - histosMCreco.fill(HIST("tofNSigmaMu_WTS_PID_Pi"), selectedPionTracks[i].tofNSigmaMu(), selectedPionTrackVector.Pt()); - histosMCreco.fill(HIST("pT_track_WTS_PID_Pi"), std::sqrt(selectedPionTracks[i].px() * selectedPionTracks[i].px() + selectedPionTracks[i].py() * selectedPionTracks[i].py())); - histosMCreco.fill(HIST("rapidity_track_WTS_PID_Pi"), selectedPionTrackVector.Rapidity()); + histosMCreco.fill(HIST("tpcNSigmaPi_pions"), selectedPionTracks[i].tpcNSigmaPi(), selectedPionTrackVector.Pt()); + histosMCreco.fill(HIST("tpcNSigmaKa_pions"), selectedPionTracks[i].tpcNSigmaKa(), selectedPionTrackVector.Pt()); + histosMCreco.fill(HIST("tpcNSigmaPr_pions"), selectedPionTracks[i].tpcNSigmaPr(), selectedPionTrackVector.Pt()); + histosMCreco.fill(HIST("tpcNSigmaEl_pions"), selectedPionTracks[i].tpcNSigmaEl(), selectedPionTrackVector.Pt()); + histosMCreco.fill(HIST("tpcNSigmaMu_pions"), selectedPionTracks[i].tpcNSigmaMu(), selectedPionTrackVector.Pt()); + histosMCreco.fill(HIST("tofNSigmaPi_pions"), selectedPionTracks[i].tofNSigmaPi(), selectedPionTrackVector.Pt()); + histosMCreco.fill(HIST("tofNSigmaKa_pions"), selectedPionTracks[i].tofNSigmaKa(), selectedPionTrackVector.Pt()); + histosMCreco.fill(HIST("tofNSigmaPr_pions"), selectedPionTracks[i].tofNSigmaPr(), selectedPionTrackVector.Pt()); + histosMCreco.fill(HIST("tofNSigmaEl_pions"), selectedPionTracks[i].tofNSigmaEl(), selectedPionTrackVector.Pt()); + histosMCreco.fill(HIST("tofNSigmaMu_pions"), selectedPionTracks[i].tofNSigmaMu(), selectedPionTrackVector.Pt()); + histosMCreco.fill(HIST("pT_track_pions"), std::sqrt(selectedPionTracks[i].px() * selectedPionTracks[i].px() + selectedPionTracks[i].py() * selectedPionTracks[i].py())); + histosMCreco.fill(HIST("rapidity_track_pions"), selectedPionTrackVector.Rapidity()); } // End of loop over tracks with selection and PID selection of Pions if (numSelectedPionTracks != numFourPionTracks) { @@ -1290,15 +1306,15 @@ struct ExclusiveRhoTo4Pi { ROOT::Math::PxPyPzMVector p3(selectedPionMinusTracks[0].px(), selectedPionMinusTracks[0].py(), selectedPionMinusTracks[0].pz(), o2::constants::physics::MassPionCharged); ROOT::Math::PxPyPzMVector p4(selectedPionMinusTracks[1].px(), selectedPionMinusTracks[1].py(), selectedPionMinusTracks[1].pz(), o2::constants::physics::MassPionCharged); - histosMCreco.fill(HIST("pT_track_WTS_PID_Pi_contributed"), p1.Pt()); - histosMCreco.fill(HIST("pT_track_WTS_PID_Pi_contributed"), p2.Pt()); - histosMCreco.fill(HIST("pT_track_WTS_PID_Pi_contributed"), p3.Pt()); - histosMCreco.fill(HIST("pT_track_WTS_PID_Pi_contributed"), p4.Pt()); + histosMCreco.fill(HIST("pT_track_pions_contributed"), p1.Pt()); + histosMCreco.fill(HIST("pT_track_pions_contributed"), p2.Pt()); + histosMCreco.fill(HIST("pT_track_pions_contributed"), p3.Pt()); + histosMCreco.fill(HIST("pT_track_pions_contributed"), p4.Pt()); - histosMCreco.fill(HIST("rapidity_track_WTS_PID_Pi_contributed"), p1.Rapidity()); - histosMCreco.fill(HIST("rapidity_track_WTS_PID_Pi_contributed"), p2.Rapidity()); - histosMCreco.fill(HIST("rapidity_track_WTS_PID_Pi_contributed"), p3.Rapidity()); - histosMCreco.fill(HIST("rapidity_track_WTS_PID_Pi_contributed"), p4.Rapidity()); + histosMCreco.fill(HIST("rapidity_track_pions_contributed"), p1.Rapidity()); + histosMCreco.fill(HIST("rapidity_track_pions_contributed"), p2.Rapidity()); + histosMCreco.fill(HIST("rapidity_track_pions_contributed"), p3.Rapidity()); + histosMCreco.fill(HIST("rapidity_track_pions_contributed"), p4.Rapidity()); k1.SetCoordinates(p1.Pt(), p1.Eta(), p1.Phi(), o2::constants::physics::MassPionCharged); k2.SetCoordinates(p2.Pt(), p2.Eta(), p2.Phi(), o2::constants::physics::MassPionCharged); @@ -1341,30 +1357,30 @@ struct ExclusiveRhoTo4Pi { phiPair1, phiPair2, cosThetaPair1, cosThetaPair2); if (std::fabs(p1234.Rapidity()) < rhoRapCut) { - histosMCreco.fill(HIST("pT_event_0charge_WTS_PID_Pi"), p1234.Pt()); + histosMCreco.fill(HIST("fourpion_pT_0_charge"), p1234.Pt()); if (p1234.Pt() < rhoPtCut) { - histosMCreco.fill(HIST("rapidity_event_0charge_WTS_PID_Pi_domainA"), p1234.Rapidity()); - histosMCreco.fill(HIST("invMass_event_0charge_WTS_PID_Pi_domainA"), p1234.M()); - - histosMCreco.fill(HIST("invMass_pair_1"), (p1 + p3).M()); - histosMCreco.fill(HIST("invMass_pair_2"), (p1 + p4).M()); - histosMCreco.fill(HIST("invMass_pair_3"), (p2 + p3).M()); - histosMCreco.fill(HIST("invMass_pair_4"), (p2 + p4).M()); - - histosMCreco.fill(HIST("CS_phi_pair_1"), phiPair1); - histosMCreco.fill(HIST("CS_phi_pair_2"), phiPair2); - histosMCreco.fill(HIST("CS_costheta_pair_1"), cosThetaPair1); - histosMCreco.fill(HIST("CS_costheta_pair_2"), cosThetaPair2); - histosMCreco.fill(HIST("phi_cosTheta_pair_1"), phiPair1, cosThetaPair1); - histosMCreco.fill(HIST("phi_cosTheta_pair_2"), phiPair2, cosThetaPair2); + histosMCreco.fill(HIST("fourpion_rap_0_charge_domA"), p1234.Rapidity()); + histosMCreco.fill(HIST("fourpion_mass_0_charge_domA"), p1234.M()); + + histosMCreco.fill(HIST("twopion_mass_1"), (p1 + p3).M()); + histosMCreco.fill(HIST("twopion_mass_2"), (p1 + p4).M()); + histosMCreco.fill(HIST("twopion_mass_3"), (p2 + p3).M()); + histosMCreco.fill(HIST("twopion_mass_4"), (p2 + p4).M()); + + histosMCreco.fill(HIST("collin_soper_phi_1"), phiPair1); + histosMCreco.fill(HIST("collin_soper_phi_2"), phiPair2); + histosMCreco.fill(HIST("collin_soper_costheta_1"), cosThetaPair1); + histosMCreco.fill(HIST("collin_soper_costheta_2"), cosThetaPair2); + histosMCreco.fill(HIST("phi_vs_costheta_1"), phiPair1, cosThetaPair1); + histosMCreco.fill(HIST("phi_vs_costheta_2"), phiPair2, cosThetaPair2); } if (p1234.Pt() > rhoPtCut && p1234.Pt() < zeroPointEight) { - histosMCreco.fill(HIST("rapidity_event_0charge_WTS_PID_Pi_domainB"), p1234.Rapidity()); - histosMCreco.fill(HIST("invMass_event_0charge_WTS_PID_Pi_domainB"), p1234.M()); + histosMCreco.fill(HIST("fourpion_rap_0_charge_domB"), p1234.Rapidity()); + histosMCreco.fill(HIST("fourpion_mass_0_charge_domB"), p1234.M()); } if (p1234.Pt() > zeroPointEight) { - histosMCreco.fill(HIST("rapidity_event_0charge_WTS_PID_Pi_domainC"), p1234.Rapidity()); - histosMCreco.fill(HIST("invMass_event_0charge_WTS_PID_Pi_domainC"), p1234.M()); + histosMCreco.fill(HIST("fourpion_rap_0_charge_domC"), p1234.Rapidity()); + histosMCreco.fill(HIST("fourpion_mass_0_charge_domC"), p1234.M()); } } // End of Rapidity range selection @@ -1380,19 +1396,19 @@ struct ExclusiveRhoTo4Pi { ROOT::Math::PxPyPzMVector p1234 = p1 + p2 + p3 + p4; if (std::fabs(p1234.Rapidity()) < rhoRapCut) { - histosMCreco.fill(HIST("pT_event_non0charge_WTS_PID_Pi"), p1234.Pt()); + histosMCreco.fill(HIST("fourpion_pT_non_0_charge"), p1234.Pt()); if (p1234.Pt() < rhoPtCut) { - histosMCreco.fill(HIST("rapidity_event_non0charge_WTS_PID_Pi_domainA"), p1234.Rapidity()); - histosMCreco.fill(HIST("invMass_event_non0charge_WTS_PID_Pi_domainA"), p1234.M()); + histosMCreco.fill(HIST("fourpion_rap_non_0_charge_domA"), p1234.Rapidity()); + histosMCreco.fill(HIST("fourpion_mass_non_0_charge_domA"), p1234.M()); } if (p1234.Pt() > rhoPtCut && p1234.Pt() < zeroPointEight) { - histosMCreco.fill(HIST("rapidity_event_non0charge_WTS_PID_Pi_domainB"), p1234.Rapidity()); - histosMCreco.fill(HIST("invMass_event_non0charge_WTS_PID_Pi_domainB"), p1234.M()); + histosMCreco.fill(HIST("fourpion_rap_non_0_charge_domB"), p1234.Rapidity()); + histosMCreco.fill(HIST("fourpion_mass_non_0_charge_domB"), p1234.M()); } if (p1234.Pt() > zeroPointEight) { - histosMCreco.fill(HIST("rapidity_event_non0charge_WTS_PID_Pi_domainC"), p1234.Rapidity()); - histosMCreco.fill(HIST("invMass_event_non0charge_WTS_PID_Pi_domainC"), p1234.M()); + histosMCreco.fill(HIST("fourpion_rap_non_0_charge_domC"), p1234.Rapidity()); + histosMCreco.fill(HIST("fourpion_mass_non_0_charge_domC"), p1234.M()); } } // End of Rapidity range selection From daa111fd67b2c8ae53b9d9aee5a52ebabe149a52 Mon Sep 17 00:00:00 2001 From: Shyam Kumar Date: Tue, 10 Jun 2025 09:14:46 +0200 Subject: [PATCH 012/871] [PWGHF] Selection of prompt and non-prompt scores within a defined range (#11510) --- PWGHF/HFC/Tasks/taskCorrelationDplusHadrons.cxx | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/PWGHF/HFC/Tasks/taskCorrelationDplusHadrons.cxx b/PWGHF/HFC/Tasks/taskCorrelationDplusHadrons.cxx index 339ab91a27c..834bf4d217c 100644 --- a/PWGHF/HFC/Tasks/taskCorrelationDplusHadrons.cxx +++ b/PWGHF/HFC/Tasks/taskCorrelationDplusHadrons.cxx @@ -80,7 +80,8 @@ struct HfTaskCorrelationDplusHadrons { Configurable selectionFlagDplus{"selectionFlagDplus", 7, "Selection Flag for D+"}; // 7 corresponds to topo+PID cuts Configurable selNoSameBunchPileUpColl{"selNoSameBunchPileUpColl", true, "Flag for rejecting the collisions associated with the same bunch crossing"}; Configurable> classMl{"classMl", {0, 1, 2}, "Indexes of ML scores to be stored. Three indexes max."}; - Configurable> mlScorePromptOrNonPrompt{"mlScorePromptOrNonPrompt", {0.5, 0.5, 0.5, 0.5}, "Machine learning scores for prompt or Feed-down"}; + Configurable> mlScorePromptOrNonPromptMin{"mlScorePromptOrNonPromptMin", {0.5, 0.5, 0.5, 0.5}, "Minimum Machine learning scores for prompt or Feed-down"}; + Configurable> mlScorePromptOrNonPromptMax{"mlScorePromptOrNonPromptMax", {1.0, 1.0, 1.0, 1.0}, "Maximum Machine learning scores for prompt or Feed-down"}; Configurable> mlScoreBkg{"mlScoreBkg", {0.5, 0.5, 0.5, 0.5}, "Machine learning scores for bkg"}; // pT ranges for correlation plots: the default values are those embedded in hf_cuts_dplus_to_pi_k_pi (i.e. the mass pT bins), but can be redefined via json files Configurable> binsPtCorrelations{"binsPtCorrelations", std::vector{ptBinsCorrelationsVec}, "pT bin limits for correlation plots"}; @@ -315,7 +316,7 @@ struct HfTaskCorrelationDplusHadrons { continue; } - if (bdtScorePromptOrNonPrompt < mlScorePromptOrNonPrompt->at(effBinD) || bdtScoreBkg > mlScoreBkg->at(effBinD)) { + if (bdtScorePromptOrNonPrompt < mlScorePromptOrNonPromptMin->at(effBinD) || bdtScorePromptOrNonPrompt > mlScorePromptOrNonPromptMax->at(effBinD) || bdtScoreBkg > mlScoreBkg->at(effBinD)) { continue; } double efficiencyWeightD = 1.; @@ -354,7 +355,7 @@ struct HfTaskCorrelationDplusHadrons { continue; } - if (bdtScorePromptOrNonPrompt < mlScorePromptOrNonPrompt->at(effBinD) || bdtScoreBkg > mlScoreBkg->at(effBinD)) { + if (bdtScorePromptOrNonPrompt < mlScorePromptOrNonPromptMin->at(effBinD) || bdtScorePromptOrNonPrompt > mlScorePromptOrNonPromptMax->at(effBinD) || bdtScoreBkg > mlScoreBkg->at(effBinD)) { continue; } if (trackDcaXY > dcaXYTrackMax || trackDcaZ > dcaZTrackMax || trackTpcCrossedRows < nTpcCrossedRaws) { @@ -417,7 +418,7 @@ struct HfTaskCorrelationDplusHadrons { if (ptD < binsPtEfficiencyD->front() || ptD > binsPtEfficiencyD->back()) continue; - if (bdtScorePromptOrNonPrompt < mlScorePromptOrNonPrompt->at(effBinD) || bdtScoreBkg > mlScoreBkg->at(effBinD)) { + if (bdtScorePromptOrNonPrompt < mlScorePromptOrNonPromptMin->at(effBinD) || bdtScorePromptOrNonPrompt > mlScorePromptOrNonPromptMax->at(effBinD) || bdtScoreBkg > mlScoreBkg->at(effBinD)) { continue; } double efficiencyWeightD = 1.; @@ -471,7 +472,7 @@ struct HfTaskCorrelationDplusHadrons { if (ptD < binsPtEfficiencyD->front() || ptD > binsPtEfficiencyD->back()) continue; - if (bdtScorePromptOrNonPrompt < mlScorePromptOrNonPrompt->at(effBinD) || bdtScoreBkg > mlScoreBkg->at(effBinD)) { + if (bdtScorePromptOrNonPrompt < mlScorePromptOrNonPromptMin->at(effBinD) || bdtScorePromptOrNonPrompt > mlScorePromptOrNonPromptMax->at(effBinD) || bdtScoreBkg > mlScoreBkg->at(effBinD)) { continue; } if (trackDcaXY > dcaXYTrackMax || trackDcaZ > dcaZTrackMax || trackTpcCrossedRows < nTpcCrossedRaws) { @@ -628,7 +629,7 @@ struct HfTaskCorrelationDplusHadrons { for (unsigned int iclass = 0; iclass < classMl->size(); iclass++) { outputMl[iclass] = candidate.mlProbDplusToPiKPi()[classMl->at(iclass)]; } - if (outputMl[0] > mlScoreBkg->at(o2::analysis::findBin(binsPtEfficiencyD, candidate.pt())) || outputMl[idxBdtScore] < mlScorePromptOrNonPrompt->at(o2::analysis::findBin(binsPtEfficiencyD, candidate.pt()))) { + if (outputMl[0] > mlScoreBkg->at(o2::analysis::findBin(binsPtEfficiencyD, candidate.pt())) || outputMl[idxBdtScore] < mlScorePromptOrNonPromptMin->at(o2::analysis::findBin(binsPtEfficiencyD, candidate.pt())) || outputMl[idxBdtScore] > mlScorePromptOrNonPromptMax->at(o2::analysis::findBin(binsPtEfficiencyD, candidate.pt()))) { continue; } auto collision = candidate.template collision_as>(); From e1e19500f1702a77a246ae63fd447ff4a5ca4b78 Mon Sep 17 00:00:00 2001 From: suyoupeng <109774812+15071832337@users.noreply.github.com> Date: Tue, 10 Jun 2025 17:31:15 +0800 Subject: [PATCH 013/871] [PWGLF] Lambda local polarization induced by jet in pp collision 13.6 TeV (#11529) --- .../Strangeness/lambdaJetpolarization.cxx | 61 ++++++++----------- 1 file changed, 24 insertions(+), 37 deletions(-) diff --git a/PWGLF/Tasks/Strangeness/lambdaJetpolarization.cxx b/PWGLF/Tasks/Strangeness/lambdaJetpolarization.cxx index 3acfbad4d10..cca1bdf193e 100644 --- a/PWGLF/Tasks/Strangeness/lambdaJetpolarization.cxx +++ b/PWGLF/Tasks/Strangeness/lambdaJetpolarization.cxx @@ -29,6 +29,9 @@ #include #include "TProfile2D.h" #include "PWGLF/DataModel/lambdaJetpolarization.h" +#include "Math/Vector3D.h" +#include "Math/Vector4D.h" +#include "Math/GenVector/Boost.h" #include #include @@ -351,6 +354,8 @@ struct LfMyV0s { } double massPr = o2::constants::physics::MassProton; double massLambda = o2::constants::physics::MassLambda; + double massPi = o2::constants::physics::MassPionCharged; + ROOT::Math::PxPyPzMVector ProtonVec, PionVec, LambdaVec, ProtonBoostedVec, LambdaBoostedVec; TMatrixD LorentzTransInV0frame(double ELambda, double Lambdapx, double Lambdapy, double Lambdapz) { @@ -1233,32 +1238,20 @@ struct LfMyV0s { if (passedLambdaSelection(v0, pos, neg) && ctauLambda < CtauLambda && ifpasslambda) { V0NumbersPerEventsel++; registryLongitudinalPolarization.fill(HIST("hMassVsPtLambda"), v0.pt(), v0.mLambda()); - double PLambda = sqrt(v0.px() * v0.px() + v0.py() * v0.py() + v0.pz() * v0.pz()); - double ELambda = sqrt(v0.mLambda() * v0.mLambda() + PLambda * PLambda); - double protonE = sqrt(massPr * massPr + pos.px() * pos.px() + pos.py() * pos.py() + pos.pz() * pos.pz()); - TMatrixD pLabV0(4, 1); - pLabV0(0, 0) = ELambda; - pLabV0(1, 0) = v0.px(); - pLabV0(2, 0) = v0.py(); - pLabV0(3, 0) = v0.pz(); - TMatrixD pLabproton(4, 1); - pLabproton(0, 0) = protonE; - pLabproton(1, 0) = pos.px(); - pLabproton(2, 0) = pos.py(); - pLabproton(3, 0) = pos.pz(); + ProtonVec = ROOT::Math::PxPyPzMVector(v0.pxpos(), v0.pypos(), v0.pzpos(), massPr); + PionVec = ROOT::Math::PxPyPzMVector(v0.pxneg(), v0.pyneg(), v0.pzneg(), massPi); + LambdaVec = ProtonVec + PionVec; + LambdaVec.SetM(massLambda); + ROOT::Math::Boost boost{LambdaVec.BoostToCM()}; + ProtonBoostedVec = boost(ProtonVec); + LambdaBoostedVec = boost(LambdaVec); - TMatrixD V0InV0(4, 1); - V0InV0 = LorentzTransInV0frame(ELambda, v0.px(), v0.py(), v0.pz()) * pLabV0; - registryLongitudinalPolarization.fill(HIST("V0pxInRest_frame"), V0InV0(1, 0)); - registryLongitudinalPolarization.fill(HIST("V0pyInRest_frame"), V0InV0(2, 0)); - registryLongitudinalPolarization.fill(HIST("V0pzInRest_frame"), V0InV0(3, 0)); + registryLongitudinalPolarization.fill(HIST("V0pxInRest_frame"), LambdaBoostedVec.Px()); + registryLongitudinalPolarization.fill(HIST("V0pyInRest_frame"), LambdaBoostedVec.Py()); + registryLongitudinalPolarization.fill(HIST("V0pzInRest_frame"), LambdaBoostedVec.Pz()); - TMatrixD protonInV0(4, 1); - protonInV0 = LorentzTransInV0frame(ELambda, v0.px(), v0.py(), v0.pz()) * pLabproton; - double protonPInV0 = sqrt(protonInV0(1, 0) * protonInV0(1, 0) + protonInV0(2, 0) * protonInV0(2, 0) + protonInV0(3, 0) * protonInV0(3, 0)); - - double protonCosThetainV0 = protonInV0(3, 0) / protonPInV0; + double protonCosThetainV0 = ProtonBoostedVec.Pz() / ProtonBoostedVec.P(); registryLongitudinalPolarization.fill(HIST("hprotoncosthetainV0"), protonCosThetainV0); registryLongitudinalPolarization.fill(HIST("hprotoncosSquarethetainV0"), protonCosThetainV0 * protonCosThetainV0); @@ -1272,21 +1265,15 @@ struct LfMyV0s { if (passedAntiLambdaSelection(v0, pos, neg) && ctauAntiLambda < CtauLambda && ifpasslambda) { registryLongitudinalPolarization.fill(HIST("hMassVsPtAntiLambda"), v0.pt(), v0.mAntiLambda()); - double PLambda = sqrt(v0.px() * v0.px() + v0.py() * v0.py() + v0.pz() * v0.pz()); - double ELambda = sqrt(v0.mAntiLambda() * v0.mAntiLambda() + PLambda * PLambda); - double protonE = sqrt(massPr * massPr + neg.px() * neg.px() + neg.py() * neg.py() + neg.pz() * neg.pz()); - - TMatrixD pLabproton(4, 1); - pLabproton(0, 0) = protonE; - pLabproton(1, 0) = neg.px(); - pLabproton(2, 0) = neg.py(); - pLabproton(3, 0) = neg.pz(); - - TMatrixD protonInV0(4, 1); - protonInV0 = LorentzTransInV0frame(ELambda, v0.px(), v0.py(), v0.pz()) * pLabproton; - double protonPInV0 = sqrt(protonInV0(1, 0) * protonInV0(1, 0) + protonInV0(2, 0) * protonInV0(2, 0) + protonInV0(3, 0) * protonInV0(3, 0)); + ProtonVec = ROOT::Math::PxPyPzMVector(v0.pxneg(), v0.pyneg(), v0.pzneg(), massPr); + PionVec = ROOT::Math::PxPyPzMVector(v0.pxpos(), v0.pypos(), v0.pzpos(), massPi); + LambdaVec = ProtonVec + PionVec; + LambdaVec.SetM(massLambda); + ROOT::Math::Boost boost{LambdaVec.BoostToCM()}; + ProtonBoostedVec = boost(ProtonVec); + LambdaBoostedVec = boost(LambdaVec); - double protonCosThetainV0 = protonInV0(3, 0) / protonPInV0; + double protonCosThetainV0 = ProtonBoostedVec.Pz() / ProtonBoostedVec.P(); registryLongitudinalPolarization.fill(HIST("hantiprotoncosthetainV0"), protonCosThetainV0); registryLongitudinalPolarization.fill(HIST("hantiprotoncosSquarethetainV0"), protonCosThetainV0 * protonCosThetainV0); From a1ea21ee8264dad92ff2e30e4d31ba31d621d075 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADt=20Ku=C4=8Dera?= Date: Tue, 10 Jun 2025 12:04:27 +0200 Subject: [PATCH 014/871] [Infrastructure] Configure clang-format to sort and group includes (#11448) --- .clang-format | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++- CPPLINT.cfg | 2 +- 2 files changed, 55 insertions(+), 2 deletions(-) diff --git a/.clang-format b/.clang-format index c5979d77ba1..33e5d4f9d0c 100644 --- a/.clang-format +++ b/.clang-format @@ -39,7 +39,60 @@ PenaltyBreakFirstLessLess: 120 PenaltyBreakString: 1000 PenaltyExcessCharacter: 1000000 PenaltyReturnTypeOnItsOwnLine: 200 -SortIncludes: false +SortIncludes: CaseSensitive +IncludeBlocks: Regroup +IncludeCategories: + # O2Physics, PWG + - Regex: ^(<|")PWG[A-Z]{2}/.*\.h + Priority: 2 + CaseSensitive: true + # O2Physics, non-PWG + - Regex: ^(<|")(Common|ALICE3|DPG|EventFiltering|Tools|Tutorials)/.*\.h + Priority: 3 + CaseSensitive: true + # O2 + - Regex: ^(<|")(Algorithm|CCDB|Common[A-Z]|DataFormats|DCAFitter|Detectors|EMCAL|Field|Framework|FT0|FV0|GlobalTracking|ITS|MathUtils|MFT|MCH|MID|PHOS|PID|ReconstructionDataFormats|SimulationDataFormat|TOF|TPC|ZDC).*/.*\.h + Priority: 4 + CaseSensitive: true + # ROOT + - Regex: ^(<|")(T[A-Z]|Math/|Roo[A-Z])[[:alnum:]/]+\.h + Priority: 5 + CaseSensitive: true + # known third-party: KFParticle + - Regex: ^(<|")KF[A-Z][[:alnum:]]+\.h + Priority: 6 + CaseSensitive: true + # known third-party: FastJet + - Regex: ^(<|")fastjet/ + Priority: 6 + CaseSensitive: true + # known third-party: ONNX runtime + - Regex: ^(<|")onnxruntime + Priority: 6 + CaseSensitive: true + # incomplete path to DataModel + - Regex: ^(<|").*DataModel/ + Priority: 1 + CaseSensitive: true + # other third-party + - Regex: ^(<|")([[:alnum:]_]+/)+[[:alnum:]_]+\.h + Priority: 6 + CaseSensitive: true + # other local-looking file + - Regex: ^".*\. + Priority: 1 + CaseSensitive: true + # C system + - Regex: ^(<|")[[:lower:]_]+\.h(>|") + Priority: 102 + CaseSensitive: true + # C++ system + - Regex: ^(<|")[[:lower:]_/]+(>|") + Priority: 101 + CaseSensitive: true + # rest + - Regex: .* + Priority: 100 SpaceBeforeAssignmentOperators: true SpaceBeforeParens: ControlStatements SpaceInEmptyParentheses: false diff --git a/CPPLINT.cfg b/CPPLINT.cfg index 7f7d3c357c3..96a8077f685 100644 --- a/CPPLINT.cfg +++ b/CPPLINT.cfg @@ -1 +1 @@ -filter=-build/c++11,-build/namespaces,-readability/fn_size,-readability/todo,-runtime/references,-whitespace/blank_line,-whitespace/braces,-whitespace/comments,-whitespace/indent_namespace,-whitespace/line_length,-whitespace/semicolon,-whitespace/todo +filter=-build/c++11,-build/include_order,-build/namespaces,-readability/fn_size,-readability/todo,-runtime/references,-whitespace/blank_line,-whitespace/braces,-whitespace/comments,-whitespace/indent_namespace,-whitespace/line_length,-whitespace/semicolon,-whitespace/todo From 6368dce561df5bd95908d2d39590969487532662 Mon Sep 17 00:00:00 2001 From: Oleksii Lubynets Date: Tue, 10 Jun 2025 13:20:52 +0200 Subject: [PATCH 015/871] [PWGHF] Enable ML selection in KF-based LcToPKPi reconstruction (#11489) --- PWGHF/Core/HfMlResponseLcToPKPi.h | 63 +++++++++-- PWGHF/TableProducer/candidateSelectorLc.cxx | 59 +++++++--- PWGHF/TableProducer/treeCreatorLcToPKPi.cxx | 116 +++++++++++++++++--- 3 files changed, 194 insertions(+), 44 deletions(-) diff --git a/PWGHF/Core/HfMlResponseLcToPKPi.h b/PWGHF/Core/HfMlResponseLcToPKPi.h index 405e16cfc42..ae797f32acd 100644 --- a/PWGHF/Core/HfMlResponseLcToPKPi.h +++ b/PWGHF/Core/HfMlResponseLcToPKPi.h @@ -16,8 +16,12 @@ #ifndef PWGHF_CORE_HFMLRESPONSELCTOPKPI_H_ #define PWGHF_CORE_HFMLRESPONSELCTOPKPI_H_ +#include +#include #include +#include "PWGHF/DataModel/CandidateReconstructionTables.h" + #include "PWGHF/Core/HfMlResponse.h" // Fill the map of available input features @@ -129,10 +133,22 @@ enum class InputFeaturesLcToPKPi : uint8_t { tofNSigmaPrExpPr0, tofNSigmaPiExpPi2, tpcTofNSigmaPrExpPr0, - tpcTofNSigmaPiExpPi2 + tpcTofNSigmaPiExpPi2, + kfChi2PrimProton, + kfChi2PrimKaon, + kfChi2PrimPion, + kfChi2GeoKaonPion, + kfChi2GeoProtonPion, + kfChi2GeoProtonKaon, + kfDcaKaonPion, + kfDcaProtonPion, + kfDcaProtonKaon, + kfChi2Geo, + kfChi2Topo, + kfDecayLengthNormalised }; -template +template class HfMlResponseLcToPKPi : public HfMlResponse { public: @@ -179,8 +195,6 @@ class HfMlResponseLcToPKPi : public HfMlResponse CHECK_AND_FILL_VEC_LCTOPKPI_FULL(candidate, tpcNSigmaPr2, nSigTpcPr2); CHECK_AND_FILL_VEC_LCTOPKPI_FULL(candidate, tpcNSigmaKa2, nSigTpcKa2); CHECK_AND_FILL_VEC_LCTOPKPI_FULL(candidate, tpcNSigmaPi2, nSigTpcPi2); - // CHECK_AND_FILL_VEC_LCTOPKPI_OBJECT_SIGNED(prong0, prong2, tpcNSigmaPrExpPr0, tpcNSigmaPr); - // CHECK_AND_FILL_VEC_LCTOPKPI_OBJECT_SIGNED(prong2, prong0, tpcNSigmaPiExpPi2, tpcNSigmaPi); CHECK_AND_FILL_VEC_LCTOPKPI_SIGNED(candidate, tpcNSigmaPrExpPr0, nSigTpcPr0, nSigTpcPr2); CHECK_AND_FILL_VEC_LCTOPKPI_SIGNED(candidate, tpcNSigmaPiExpPi2, nSigTpcPi2, nSigTpcPi0); // TOF PID variables @@ -193,8 +207,6 @@ class HfMlResponseLcToPKPi : public HfMlResponse CHECK_AND_FILL_VEC_LCTOPKPI_FULL(candidate, tofNSigmaPr2, nSigTofPr2); CHECK_AND_FILL_VEC_LCTOPKPI_FULL(candidate, tofNSigmaKa2, nSigTofKa2); CHECK_AND_FILL_VEC_LCTOPKPI_FULL(candidate, tofNSigmaPi2, nSigTofPi2); - // CHECK_AND_FILL_VEC_LCTOPKPI_OBJECT_SIGNED(prong0, prong2, tofNSigmaPrExpPr0, tofNSigmaPr); - // CHECK_AND_FILL_VEC_LCTOPKPI_OBJECT_SIGNED(prong2, prong0, tofNSigmaPiExpPi2, tofNSigmaPi); CHECK_AND_FILL_VEC_LCTOPKPI_SIGNED(candidate, tofNSigmaPrExpPr0, nSigTofPr0, nSigTofPr2); CHECK_AND_FILL_VEC_LCTOPKPI_SIGNED(candidate, tofNSigmaPiExpPi2, nSigTofPi2, nSigTofPi0); // Combined PID variables @@ -207,13 +219,29 @@ class HfMlResponseLcToPKPi : public HfMlResponse CHECK_AND_FILL_VEC_LCTOPKPI_FULL(candidate, tpcTofNSigmaPr0, tpcTofNSigmaPr0); CHECK_AND_FILL_VEC_LCTOPKPI_FULL(candidate, tpcTofNSigmaPr1, tpcTofNSigmaPr1); CHECK_AND_FILL_VEC_LCTOPKPI_FULL(candidate, tpcTofNSigmaPr2, tpcTofNSigmaPr2); - // CHECK_AND_FILL_VEC_LCTOPKPI_OBJECT_SIGNED(prong0, prong2, tpcTofNSigmaPrExpPr0, tpcTofNSigmaPr); - // CHECK_AND_FILL_VEC_LCTOPKPI_OBJECT_SIGNED(prong2, prong0, tpcTofNSigmaPiExpPi2, tpcTofNSigmaPi); CHECK_AND_FILL_VEC_LCTOPKPI_SIGNED(candidate, tpcTofNSigmaPrExpPr0, tpcTofNSigmaPr0, tpcTofNSigmaPr2); CHECK_AND_FILL_VEC_LCTOPKPI_SIGNED(candidate, tpcTofNSigmaPiExpPi2, tpcTofNSigmaPi2, tpcTofNSigmaPi0); } + if constexpr (reconstructionType == aod::hf_cand::VertexerType::KfParticle) { + switch (idx) { + CHECK_AND_FILL_VEC_LCTOPKPI_SIGNED(candidate, kfChi2PrimProton, kfChi2PrimProng0, kfChi2PrimProng2); + CHECK_AND_FILL_VEC_LCTOPKPI_FULL(candidate, kfChi2PrimKaon, kfChi2PrimProng1); + CHECK_AND_FILL_VEC_LCTOPKPI_SIGNED(candidate, kfChi2PrimPion, kfChi2PrimProng2, kfChi2PrimProng0); + CHECK_AND_FILL_VEC_LCTOPKPI_SIGNED(candidate, kfChi2GeoKaonPion, kfChi2GeoProng1Prong2, kfChi2GeoProng0Prong1); + CHECK_AND_FILL_VEC_LCTOPKPI_FULL(candidate, kfChi2GeoProtonPion, kfChi2GeoProng0Prong2); + CHECK_AND_FILL_VEC_LCTOPKPI_SIGNED(candidate, kfChi2GeoProtonKaon, kfChi2GeoProng0Prong1, kfChi2GeoProng1Prong2); + CHECK_AND_FILL_VEC_LCTOPKPI_SIGNED(candidate, kfDcaKaonPion, kfDcaProng1Prong2, kfDcaProng0Prong1); + CHECK_AND_FILL_VEC_LCTOPKPI_FULL(candidate, kfDcaProtonPion, kfDcaProng0Prong2); + CHECK_AND_FILL_VEC_LCTOPKPI_SIGNED(candidate, kfDcaProtonKaon, kfDcaProng0Prong1, kfDcaProng1Prong2); + CHECK_AND_FILL_VEC_LCTOPKPI(kfChi2Geo); + CHECK_AND_FILL_VEC_LCTOPKPI(kfChi2Topo); + case static_cast(InputFeaturesLcToPKPi::kfDecayLengthNormalised): { + inputFeatures.emplace_back(candidate.kfDecayLength() / candidate.kfDecayLengthError()); + break; + } + } + } } - return inputFeatures; } @@ -273,6 +301,23 @@ class HfMlResponseLcToPKPi : public HfMlResponse FILL_MAP_LCTOPKPI(tpcTofNSigmaPr2), FILL_MAP_LCTOPKPI(tpcTofNSigmaPrExpPr0), FILL_MAP_LCTOPKPI(tpcTofNSigmaPiExpPi2)}; + if constexpr (reconstructionType == aod::hf_cand::VertexerType::KfParticle) { + std::map mapKfFeatures{ + // KFParticle variables + FILL_MAP_LCTOPKPI(kfChi2PrimProton), + FILL_MAP_LCTOPKPI(kfChi2PrimKaon), + FILL_MAP_LCTOPKPI(kfChi2PrimPion), + FILL_MAP_LCTOPKPI(kfChi2GeoKaonPion), + FILL_MAP_LCTOPKPI(kfChi2GeoProtonPion), + FILL_MAP_LCTOPKPI(kfChi2GeoProtonKaon), + FILL_MAP_LCTOPKPI(kfDcaKaonPion), + FILL_MAP_LCTOPKPI(kfDcaProtonPion), + FILL_MAP_LCTOPKPI(kfDcaProtonKaon), + FILL_MAP_LCTOPKPI(kfChi2Geo), + FILL_MAP_LCTOPKPI(kfChi2Topo), + FILL_MAP_LCTOPKPI(kfDecayLengthNormalised)}; + MlResponse::mAvailableInputFeatures.insert(mapKfFeatures.begin(), mapKfFeatures.end()); + } } }; diff --git a/PWGHF/TableProducer/candidateSelectorLc.cxx b/PWGHF/TableProducer/candidateSelectorLc.cxx index 93b84c79522..d48cb5f3daa 100644 --- a/PWGHF/TableProducer/candidateSelectorLc.cxx +++ b/PWGHF/TableProducer/candidateSelectorLc.cxx @@ -93,7 +93,8 @@ struct HfCandidateSelectorLc { Configurable loadModelsFromCCDB{"loadModelsFromCCDB", false, "Flag to enable or disable the loading of models from CCDB"}; HfHelper hfHelper; - o2::analysis::HfMlResponseLcToPKPi hfMlResponse; + o2::analysis::HfMlResponseLcToPKPi hfMlResponseDCA; + o2::analysis::HfMlResponseLcToPKPi hfMlResponseKF; std::vector outputMlLcToPKPi = {}; std::vector outputMlLcToPiKP = {}; o2::ccdb::CcdbApi ccdbApi; @@ -142,15 +143,28 @@ struct HfCandidateSelectorLc { } if (applyMl) { - hfMlResponse.configure(binsPtMl, cutsMl, cutDirMl, nClassesMl); - if (loadModelsFromCCDB) { - ccdbApi.init(ccdbUrl); - hfMlResponse.setModelPathsCCDB(onnxFileNames, ccdbApi, modelPathsCCDB, timestampCCDB); - } else { - hfMlResponse.setModelPathsLocal(onnxFileNames); + if (doprocessNoBayesPidWithDCAFitterN || doprocessBayesPidWithDCAFitterN) { + hfMlResponseDCA.configure(binsPtMl, cutsMl, cutDirMl, nClassesMl); + if (loadModelsFromCCDB) { + ccdbApi.init(ccdbUrl); + hfMlResponseDCA.setModelPathsCCDB(onnxFileNames, ccdbApi, modelPathsCCDB, timestampCCDB); + } else { + hfMlResponseDCA.setModelPathsLocal(onnxFileNames); + } + hfMlResponseDCA.cacheInputFeaturesIndices(namesInputFeatures); + hfMlResponseDCA.init(); + } + if (doprocessNoBayesPidWithKFParticle || doprocessBayesPidWithKFParticle) { + hfMlResponseKF.configure(binsPtMl, cutsMl, cutDirMl, nClassesMl); + if (loadModelsFromCCDB) { + ccdbApi.init(ccdbUrl); + hfMlResponseKF.setModelPathsCCDB(onnxFileNames, ccdbApi, modelPathsCCDB, timestampCCDB); + } else { + hfMlResponseKF.setModelPathsLocal(onnxFileNames); + } + hfMlResponseKF.cacheInputFeaturesIndices(namesInputFeatures); + hfMlResponseKF.init(); } - hfMlResponse.cacheInputFeaturesIndices(namesInputFeatures); - hfMlResponse.init(); } massK0Star892 = o2::constants::physics::MassK0Star892; @@ -273,7 +287,7 @@ struct HfCandidateSelectorLc { return false; } - float massLc, massKPi; + float massLc{0.f}, massKPi{0.f}; if constexpr (reconstructionType == aod::hf_cand::VertexerType::DCAFitter) { if (trackProton.globalIndex() == candidate.prong0Id()) { massLc = hfHelper.invMassLcToPKPi(candidate); @@ -553,13 +567,24 @@ struct HfCandidateSelectorLc { isSelectedMlLcToPKPi = false; isSelectedMlLcToPiKP = false; - if (pidLcToPKPi == 1 && pidBayesLcToPKPi == 1 && topolLcToPKPi) { - std::vector inputFeaturesLcToPKPi = hfMlResponse.getInputFeatures(candidate, true); - isSelectedMlLcToPKPi = hfMlResponse.isSelectedMl(inputFeaturesLcToPKPi, candidate.pt(), outputMlLcToPKPi); - } - if (pidLcToPiKP == 1 && pidBayesLcToPiKP == 1 && topolLcToPiKP) { - std::vector inputFeaturesLcToPiKP = hfMlResponse.getInputFeatures(candidate, false); - isSelectedMlLcToPiKP = hfMlResponse.isSelectedMl(inputFeaturesLcToPiKP, candidate.pt(), outputMlLcToPiKP); + if constexpr (reconstructionType == aod::hf_cand::VertexerType::DCAFitter) { + if (pidLcToPKPi == 1 && pidBayesLcToPKPi == 1 && topolLcToPKPi) { + std::vector inputFeaturesLcToPKPi = hfMlResponseDCA.getInputFeatures(candidate, true); + isSelectedMlLcToPKPi = hfMlResponseDCA.isSelectedMl(inputFeaturesLcToPKPi, candidate.pt(), outputMlLcToPKPi); + } + if (pidLcToPiKP == 1 && pidBayesLcToPiKP == 1 && topolLcToPiKP) { + std::vector inputFeaturesLcToPiKP = hfMlResponseDCA.getInputFeatures(candidate, false); + isSelectedMlLcToPiKP = hfMlResponseDCA.isSelectedMl(inputFeaturesLcToPiKP, candidate.pt(), outputMlLcToPiKP); + } + } else { + if (pidLcToPKPi == 1 && pidBayesLcToPKPi == 1 && topolLcToPKPi) { + std::vector inputFeaturesLcToPKPi = hfMlResponseKF.getInputFeatures(candidate, true); + isSelectedMlLcToPKPi = hfMlResponseKF.isSelectedMl(inputFeaturesLcToPKPi, candidate.pt(), outputMlLcToPKPi); + } + if (pidLcToPiKP == 1 && pidBayesLcToPiKP == 1 && topolLcToPiKP) { + std::vector inputFeaturesLcToPiKP = hfMlResponseKF.getInputFeatures(candidate, false); + isSelectedMlLcToPiKP = hfMlResponseKF.isSelectedMl(inputFeaturesLcToPiKP, candidate.pt(), outputMlLcToPiKP); + } } hfMlLcToPKPiCandidate(outputMlLcToPKPi, outputMlLcToPiKP); diff --git a/PWGHF/TableProducer/treeCreatorLcToPKPi.cxx b/PWGHF/TableProducer/treeCreatorLcToPKPi.cxx index 5ad144e472e..3f53966a973 100644 --- a/PWGHF/TableProducer/treeCreatorLcToPKPi.cxx +++ b/PWGHF/TableProducer/treeCreatorLcToPKPi.cxx @@ -17,7 +17,9 @@ /// \author Nicolo' Jacazio , CERN /// \author Luigi Dello Stritto , CERN +#include #include +#include #include "CommonConstants/PhysicsConstants.h" #include "Framework/AnalysisTask.h" @@ -87,6 +89,9 @@ DECLARE_SOA_COLUMN(IsCandidateSwapped, isCandidateSwapped, int8_t); DECLARE_SOA_INDEX_COLUMN_FULL(Candidate, candidate, int, HfCand3ProngWPidPiKaPr, "_0"); DECLARE_SOA_INDEX_COLUMN(McParticle, mcParticle); DECLARE_SOA_COLUMN(Channel, channel, int8_t); // direct or resonant +DECLARE_SOA_COLUMN(MlScoreFirstClass, mlScoreFirstClass, float); +DECLARE_SOA_COLUMN(MlScoreSecondClass, mlScoreSecondClass, float); +DECLARE_SOA_COLUMN(MlScoreThirdClass, mlScoreThirdClass, float); // Events DECLARE_SOA_INDEX_COLUMN(McCollision, mcCollision); DECLARE_SOA_COLUMN(IsEventReject, isEventReject, int); @@ -238,7 +243,10 @@ DECLARE_SOA_TABLE(HfCandLcLites, "AOD", "HFCANDLCLITE", full::OriginMcRec, full::IsCandidateSwapped, full::Channel, - full::MassKPi); + full::MassKPi, + full::MlScoreFirstClass, + full::MlScoreSecondClass, + full::MlScoreThirdClass); DECLARE_SOA_TABLE(HfCollIdLCLite, "AOD", "HFCOLLIDLCLITE", full::CollisionId); @@ -316,7 +324,10 @@ DECLARE_SOA_TABLE(HfCandLcFulls, "AOD", "HFCANDLCFULL", full::IsCandidateSwapped, full::CandidateId, full::Channel, - full::MassKPi); + full::MassKPi, + full::MlScoreFirstClass, + full::MlScoreSecondClass, + full::MlScoreThirdClass); DECLARE_SOA_TABLE(HfCandLcFullEvs, "AOD", "HFCANDLCFULLEV", full::CollisionId, @@ -374,6 +385,7 @@ struct HfTreeCreatorLcToPKPi { Configurable fillCandidateLiteTable{"fillCandidateLiteTable", false, "Switch to fill lite table with candidate properties"}; Configurable fillCollIdTable{"fillCollIdTable", false, "Fill a single-column table with collision index"}; Configurable fillCandidateMcTable{"fillCandidateMcTable", false, "Switch to fill a table with MC particles matched to candidates"}; + Configurable applyMl{"applyMl", false, "Whether ML was used in candidateSelectorLc"}; Configurable keepOnlySignalMc{"keepOnlySignalMc", false, "Fill MC tree only with signal candidates"}; Configurable keepOnlyBkg{"keepOnlyBkg", false, "Fill MC tree only with background candidates"}; Configurable downSampleBkgFactor{"downSampleBkgFactor", 1., "Fraction of candidates to store in the tree"}; @@ -553,11 +565,40 @@ struct HfTreeCreatorLcToPKPi { return std::make_pair(invMass, invMassKPi); } + /// \brief function to get ML score values for the current candidate and assign them to input parameters + /// \param candidate candidate instance + /// \param candidateMlScore instance of handler of vectors with ML scores associated with the current candidate + /// \param mlScoreFirstClass ML score for belonging to the first class + /// \param mlScoreSecondClass ML score for belonging to the second class + /// \param mlScoreThirdClass ML score for belonging to the third class + /// \param candFlag flag indicating if PKPi (0) or PiKP (1) hypothesis is used + void assignMlScores(aod::HfMlLcToPKPi::iterator const& candidateMlScore, float& mlScoreFirstClass, float& mlScoreSecondClass, float& mlScoreThirdClass, int candFlag) + { + std::vector mlScores; + if (candFlag == 0) { + std::copy(candidateMlScore.mlProbLcToPKPi().begin(), candidateMlScore.mlProbLcToPKPi().end(), std::back_inserter(mlScores)); + } else { + std::copy(candidateMlScore.mlProbLcToPiKP().begin(), candidateMlScore.mlProbLcToPiKP().end(), std::back_inserter(mlScores)); + } + constexpr int IndexFirstClass{0}; + constexpr int IndexSecondClass{1}; + constexpr int IndexThirdClass{2}; + if (mlScores.size() == 0) { + return; // when candidateSelectorLc rejects a candidate by "usual", non-ML cut, the ml score vector remains empty + } + mlScoreFirstClass = mlScores.at(IndexFirstClass); + mlScoreSecondClass = mlScores.at(IndexSecondClass); + if (mlScores.size() > IndexThirdClass) { + mlScoreThirdClass = mlScores.at(IndexThirdClass); + } + } + /// \brief function to fill lite table /// \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, int candFlag) + void fillLiteTable(CandType const& candidate, aod::HfMlLcToPKPi::iterator const& candidateMlScore, int candFlag) { auto [functionInvMass, functionInvMassKPi] = evaluateInvariantMasses(candidate, candFlag); const float functionCt = hfHelper.ctLc(candidate); @@ -575,6 +616,14 @@ struct HfTreeCreatorLcToPKPi { functionFlagMcDecayChanRec = candidate.flagMcDecayChanRec(); } + float mlScoreFirstClass{UndefValueFloat}; + float mlScoreSecondClass{UndefValueFloat}; + float mlScoreThirdClass{UndefValueFloat}; + + if (applyMl) { + assignMlScores(candidateMlScore, mlScoreFirstClass, mlScoreSecondClass, mlScoreThirdClass, candFlag); + } + rowCandidateLite( candidate.posX(), candidate.posY(), @@ -618,7 +667,10 @@ struct HfTreeCreatorLcToPKPi { functionOriginMcRec, functionIsCandidateSwapped, functionFlagMcDecayChanRec, - functionInvMassKPi); + functionInvMassKPi, + mlScoreFirstClass, + mlScoreSecondClass, + mlScoreThirdClass); if (fillCollIdTable) { /// save also candidate collision indices @@ -628,9 +680,10 @@ struct HfTreeCreatorLcToPKPi { /// \brief function to fill lite table /// \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, int candFlag) + void fillFullTable(CandType const& candidate, aod::HfMlLcToPKPi::iterator const& candidateMlScore, int candFlag) { auto [functionInvMass, functionInvMassKPi] = evaluateInvariantMasses(candidate, candFlag); const float functionCt = hfHelper.ctLc(candidate); @@ -649,6 +702,14 @@ struct HfTreeCreatorLcToPKPi { functionFlagMcDecayChanRec = candidate.flagMcDecayChanRec(); } + float mlScoreFirstClass{UndefValueFloat}; + float mlScoreSecondClass{UndefValueFloat}; + float mlScoreThirdClass{UndefValueFloat}; + + if (applyMl) { + assignMlScores(candidateMlScore, mlScoreFirstClass, mlScoreSecondClass, mlScoreThirdClass, candFlag); + } + rowCandidateFull( candidate.collisionId(), candidate.posX(), @@ -722,7 +783,10 @@ struct HfTreeCreatorLcToPKPi { functionIsCandidateSwapped, candidate.globalIndex(), functionFlagMcDecayChanRec, - functionInvMassKPi); + functionInvMassKPi, + mlScoreFirstClass, + mlScoreSecondClass, + mlScoreThirdClass); } /// \brief function to fill lite table @@ -839,6 +903,7 @@ struct HfTreeCreatorLcToPKPi { void fillTablesMc(Colls const& collisions, aod::McCollisions const&, CandType const& candidates, + aod::HfMlLcToPKPi const& candidateMlScores, soa::Join const& particles, soa::Join const&, aod::BCs const&) { @@ -850,7 +915,10 @@ struct HfTreeCreatorLcToPKPi { const size_t candidatesSize = candidates.size(); reserveTables(candidatesSize, IsMc); + int iCand{0}; for (const auto& candidate : candidates) { + auto candidateMlScore = candidateMlScores.rawIteratorAt(iCand); + ++iCand; float ptProng0 = candidate.ptProng0(); auto collision = candidate.template collision_as(); auto fillTable = [&](int candFlag) { @@ -863,9 +931,9 @@ struct HfTreeCreatorLcToPKPi { const bool notSkippedBkg = isMcCandidateSignal || candidate.pt() > downSampleBkgPtMax || pseudoRndm < downSampleBkgFactor; if (passSelection && notSkippedBkg && (keepAll || (keepOnlySignalMc && isMcCandidateSignal) || (keepOnlyBkg && !isMcCandidateSignal))) { if (fillCandidateLiteTable) { - fillLiteTable(candidate, candFlag); + fillLiteTable(candidate, candidateMlScore, candFlag); } else { - fillFullTable(candidate, candFlag); + fillFullTable(candidate, candidateMlScore, candFlag); } if constexpr (reconstructionType == aod::hf_cand::VertexerType::KfParticle) { @@ -955,10 +1023,11 @@ struct HfTreeCreatorLcToPKPi { void processMcNoCentralityWithDCAFitterN(soa::Join const& collisions, aod::McCollisions const& mcCollisions, soa::Join const& candidates, + aod::HfMlLcToPKPi const& candidateMlScores, soa::Join const& particles, soa::Join const& tracks, aod::BCs const& bcs) { - fillTablesMc(collisions, mcCollisions, candidates, particles, tracks, bcs); + fillTablesMc(collisions, mcCollisions, candidates, candidateMlScores, particles, tracks, bcs); } PROCESS_SWITCH(HfTreeCreatorLcToPKPi, processMcNoCentralityWithDCAFitterN, "Process MC tree writer w/o centrality with DCAFitterN", false); @@ -971,10 +1040,11 @@ struct HfTreeCreatorLcToPKPi { void processMcWithCentralityWithDCAFitterN(soa::Join const& collisions, aod::McCollisions const& mcCollisions, soa::Join const& candidates, + aod::HfMlLcToPKPi const& candidateMlScores, soa::Join const& particles, soa::Join const& tracks, aod::BCs const& bcs) { - fillTablesMc(collisions, mcCollisions, candidates, particles, tracks, bcs); + fillTablesMc(collisions, mcCollisions, candidates, candidateMlScores, particles, tracks, bcs); } PROCESS_SWITCH(HfTreeCreatorLcToPKPi, processMcWithCentralityWithDCAFitterN, "Process MC tree writer with centrality with DCAFitterN", false); @@ -988,10 +1058,11 @@ struct HfTreeCreatorLcToPKPi { void processMcNoCentralityWithKFParticle(soa::Join const& collisions, aod::McCollisions const& mcCollisions, soa::Join const& candidates, + aod::HfMlLcToPKPi const& candidateMlScores, soa::Join const& particles, soa::Join const& tracks, aod::BCs const& bcs) { - fillTablesMc(collisions, mcCollisions, candidates, particles, tracks, bcs); + fillTablesMc(collisions, mcCollisions, candidates, candidateMlScores, particles, tracks, bcs); } PROCESS_SWITCH(HfTreeCreatorLcToPKPi, processMcNoCentralityWithKFParticle, "Process MC tree writer w/o centrality with KFParticle", false); @@ -1004,10 +1075,11 @@ struct HfTreeCreatorLcToPKPi { void processMcWithCentralityWithKFParticle(soa::Join const& collisions, aod::McCollisions const& mcCollisions, soa::Join const& candidates, + aod::HfMlLcToPKPi const& candidateMlScores, soa::Join const& particles, soa::Join const& tracks, aod::BCs const& bcs) { - fillTablesMc(collisions, mcCollisions, candidates, particles, tracks, bcs); + fillTablesMc(collisions, mcCollisions, candidates, candidateMlScores, particles, tracks, bcs); } PROCESS_SWITCH(HfTreeCreatorLcToPKPi, processMcWithCentralityWithKFParticle, "Process MC tree writer with centrality with KFParticle", false); @@ -1017,6 +1089,7 @@ struct HfTreeCreatorLcToPKPi { template void fillTablesData(Colls const& collisions, CandType const& candidates, + aod::HfMlLcToPKPi const& candidateMlScores, TracksWPid const&, aod::BCs const&) { @@ -1029,7 +1102,10 @@ struct HfTreeCreatorLcToPKPi { // Filling candidate properties + int iCand{0}; for (const auto& candidate : candidates) { + auto candidateMlScore = candidateMlScores.rawIteratorAt(iCand); + ++iCand; float ptProng0 = candidate.ptProng0(); auto collision = candidate.template collision_as(); auto fillTable = [&](int candFlag) { @@ -1037,9 +1113,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, candFlag); + fillLiteTable(candidate, candidateMlScore, candFlag); } else { - fillFullTable(candidate, candFlag); + fillFullTable(candidate, candidateMlScore, candFlag); } if constexpr (reconstructionType == aod::hf_cand::VertexerType::KfParticle) { @@ -1060,9 +1136,10 @@ struct HfTreeCreatorLcToPKPi { /// \param bcs Bunch-crossing table void processDataNoCentralityWithDCAFitterN(soa::Join const& collisions, soa::Join const& candidates, + aod::HfMlLcToPKPi const& candidateMlScores, TracksWPid const& tracks, aod::BCs const& bcs) { - fillTablesData(collisions, candidates, tracks, bcs); + fillTablesData(collisions, candidates, candidateMlScores, tracks, bcs); } PROCESS_SWITCH(HfTreeCreatorLcToPKPi, processDataNoCentralityWithDCAFitterN, "Process data tree writer w/o centrality with DCAFitterN", false); @@ -1073,9 +1150,10 @@ struct HfTreeCreatorLcToPKPi { /// \param bcs Bunch-crossing table void processDataWithCentralityWithDCAFitterN(soa::Join const& collisions, soa::Join const& candidates, + aod::HfMlLcToPKPi const& candidateMlScores, TracksWPid const& tracks, aod::BCs const& bcs) { - fillTablesData(collisions, candidates, tracks, bcs); + fillTablesData(collisions, candidates, candidateMlScores, tracks, bcs); } PROCESS_SWITCH(HfTreeCreatorLcToPKPi, processDataWithCentralityWithDCAFitterN, "Process data tree writer with centrality with DCAFitterN", true); @@ -1086,9 +1164,10 @@ struct HfTreeCreatorLcToPKPi { /// \param bcs Bunch-crossing table void processDataNoCentralityWithKFParticle(soa::Join const& collisions, soa::Join const& candidates, + aod::HfMlLcToPKPi const& candidateMlScores, TracksWPid const& tracks, aod::BCs const& bcs) { - fillTablesData(collisions, candidates, tracks, bcs); + fillTablesData(collisions, candidates, candidateMlScores, tracks, bcs); } PROCESS_SWITCH(HfTreeCreatorLcToPKPi, processDataNoCentralityWithKFParticle, "Process data tree writer w/o centrality with KFParticle", false); @@ -1099,9 +1178,10 @@ struct HfTreeCreatorLcToPKPi { /// \param bcs Bunch-crossing table void processDataWithCentralityWithKFParticle(soa::Join const& collisions, soa::Join const& candidates, + aod::HfMlLcToPKPi const& candidateMlScores, TracksWPid const& tracks, aod::BCs const& bcs) { - fillTablesData(collisions, candidates, tracks, bcs); + fillTablesData(collisions, candidates, candidateMlScores, tracks, bcs); } PROCESS_SWITCH(HfTreeCreatorLcToPKPi, processDataWithCentralityWithKFParticle, "Process data tree writer with centrality with KFParticle", false); }; From 03dcf2600487af09f6bb519e1ff661bdc8f0423b Mon Sep 17 00:00:00 2001 From: Zhengqing Wang Date: Tue, 10 Jun 2025 20:29:01 +0800 Subject: [PATCH 016/871] [PWGCF] update on ese (#11530) Co-authored-by: ALICE Action Bot --- PWGCF/Flow/Tasks/flowEsePHe3.cxx | 1564 ++++++++++++++++-------------- 1 file changed, 820 insertions(+), 744 deletions(-) diff --git a/PWGCF/Flow/Tasks/flowEsePHe3.cxx b/PWGCF/Flow/Tasks/flowEsePHe3.cxx index 61582f233b3..624043a2d31 100644 --- a/PWGCF/Flow/Tasks/flowEsePHe3.cxx +++ b/PWGCF/Flow/Tasks/flowEsePHe3.cxx @@ -36,6 +36,8 @@ #include "Framework/RunningWorkflowInfo.h" #include "Framework/StaticFor.h" +#include "DataFormatsTPC/BetheBlochAleph.h" + #include "Common/DataModel/Qvectors.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/TrackSelectionTables.h" @@ -51,42 +53,213 @@ using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; +using namespace o2::constants::physics; namespace o2::aod { -namespace flow_ese_p_he3 +namespace ese_var_table { -DECLARE_SOA_COLUMN(NPidFlag, nPidFlag, int8_t); // unqualified -1, hadron 0, proton 1, he3 2, proton+he3 3 -} // namespace flow_ese_p_he3 -DECLARE_SOA_TABLE(PHe3ESEFlags, "AOD", "PHe3ESEFlags", flow_ese_p_he3::NPidFlag); +DECLARE_SOA_COLUMN(EseVtz, eseVtz, float); +DECLARE_SOA_COLUMN(EseCentFT0C, eseCentFT0C, float); +DECLARE_SOA_COLUMN(EsePsi2FT0C, esePsi2FT0C, float); +DECLARE_SOA_COLUMN(Eseq2Tar, eseq2Tar, float); +DECLARE_SOA_COLUMN(Eseq2Ref, eseq2Ref, float); +DECLARE_SOA_COLUMN(EseTarSign, eseTarSign, int8_t); +DECLARE_SOA_COLUMN(EseTarTPCInnerParam, eseTarTPCInnerParam, float); +DECLARE_SOA_COLUMN(EseTarTPCSignal, eseTarTPCSignal, float); +DECLARE_SOA_COLUMN(EseTarPt, eseTarPt, float); +DECLARE_SOA_COLUMN(EseTarEta, eseTarEta, float); +DECLARE_SOA_COLUMN(EseTarPhi, eseTarPhi, float); +DECLARE_SOA_COLUMN(EseTarDCAxy, eseTarDCAxy, float); +DECLARE_SOA_COLUMN(EseTarDCAz, eseTarDCAz, float); +DECLARE_SOA_COLUMN(EseTarTPCNcls, eseTarTPCNcls, uint8_t); +DECLARE_SOA_COLUMN(EseTarITSNcls, eseTarITSNcls, uint8_t); +DECLARE_SOA_COLUMN(EseTarTPCChi2NDF, eseTarTPCChi2NDF, float); +DECLARE_SOA_COLUMN(EseTarITSChi2NDF, eseTarITSChi2NDF, float); +DECLARE_SOA_COLUMN(EseTarTPCNSigma, eseTarTPCNSigma, float); +DECLARE_SOA_COLUMN(EseTarTOFNSigma, eseTarTOFNSigma, float); +DECLARE_SOA_COLUMN(EseTarITSNSigma, eseTarITSNSigma, float); +DECLARE_SOA_COLUMN(EseTarITSClusSize, eseTarITSClusSize, uint32_t); +} // namespace ese_var_table + +DECLARE_SOA_TABLE(ESETable, "AOD", "ESETable", + ese_var_table::EseVtz, + ese_var_table::EseCentFT0C, + ese_var_table::EsePsi2FT0C, + ese_var_table::Eseq2Tar, + ese_var_table::Eseq2Ref, + ese_var_table::EseTarSign, + ese_var_table::EseTarTPCInnerParam, + ese_var_table::EseTarTPCSignal, + ese_var_table::EseTarPt, + ese_var_table::EseTarEta, + ese_var_table::EseTarPhi, + ese_var_table::EseTarDCAxy, + ese_var_table::EseTarDCAz, + ese_var_table::EseTarTPCNcls, + ese_var_table::EseTarITSNcls, + ese_var_table::EseTarTPCChi2NDF, + ese_var_table::EseTarITSChi2NDF, + ese_var_table::EseTarTPCNSigma, + ese_var_table::EseTarTOFNSigma, + ese_var_table::EseTarITSNSigma, + ese_var_table::EseTarITSClusSize); } // namespace o2::aod -namespace pid_flags -{ -// constexpr int8_t kUnqualified = -1; -// constexpr int8_t kUnPOIHadron = 0; -constexpr int8_t kProton = 1; -constexpr int8_t kHe3 = 2; -constexpr int8_t kProtonHe3 = 3; -} // namespace pid_flags - -namespace event_selection -{ -constexpr int kFT0AV0ASigma = 5; -} +struct ESECandidate { + float vtz; + float centFT0C; + float psi2FT0C; + float q2Tar; + float q2Ref; + int8_t signTar; + float tpcInnerParamTar; + float tpcSignalTar; + float ptTar; + float etaTar; + float phiTar; + float dcaXYTar; + float dcaZTar; + uint8_t tpcNclsTar; + uint8_t itsNclsTar; + float tpcChi2NDFTar; + float itsChi2NDFTar; + float tpcNSigmaTar; + float tofNSigmaTar; + float itsNSigmaTar; + uint32_t itsClusSizeTar; +}; -namespace fourier_mode +namespace ese_parameters { -// constexpr int kMode1 = 1; -constexpr int kMode2 = 2; -// constexpr int kMode3 = 3; -} // namespace fourier_mode +constexpr uint8_t kProton = 0; +constexpr uint8_t kDeuteron = 1; +constexpr uint8_t kTriton = 2; +constexpr uint8_t kHe3 = 3; +constexpr uint8_t kAlpha = 4; +constexpr int kFT0AV0ASigma = 5; +constexpr int kRMSMode = 0; +constexpr int kTPCMode = 1; +constexpr int kTOFOnlyMode = 2; +constexpr float Amplitudelow = 1e-8; +constexpr float Charges[5]{1.f, 1.f, 1.f, 2.f, 2.f}; +constexpr float Masses[5]{MassProton, MassDeuteron, MassTriton, MassHelium3, MassAlpha}; +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 BbMomScalingDefault[5][2]{// 0:poscharged 1:negcharged + {1., 1.}, + {1., 1.}, + {1., 1.}, + {1., 1.}, + {1., 1.}}; +constexpr int Open3DPIDPlots[3][1]{ + {0}, + {0}, + {0}}; +constexpr int OpenEvSel[10][1]{ + {1}, + {1}, + {1}, + {1}, + {1}, + {1}, + {1}, + {1}, + {0}, + {1}}; +constexpr int OpenTrackSel[7][1]{ + {1}, + {1}, + {1}, + {1}, + {1}, + {1}, + {1}}; +constexpr double TPCnSigmaCutDefault[5][2]{ + {-3., 3.}, + {-3., 3.}, + {-3., 3.}, + {-3., 3.}, + {-3., 3.}}; +constexpr double ITSnSigmaCutDefault[5][2]{ + {-3., 3.}, + {-3., 3.}, + {-3., 3.}, + {-3., 3.}, + {-3., 3.}}; +constexpr double PtPreselection[5][2]{ + {0.15, 99.}, + {0.15, 99.}, + {0.15, 99.}, + {0.15, 99.}, + {0.15, 99.}}; +static const std::vector names{"proton", "deuteron", "triton", "He3", "alpha"}; +static const std::vector chargeLabelNames{"Positive", "Negative"}; +static const std::vector betheBlochParNames{"p0", "p1", "p2", "p3", "p4", "resolution"}; +static const std::vector plot3DPIDNames{"TOF vs ITS", "ITS vs TPC", "TOF vs TPC"}; +static const std::vector openEventSelNames{"EvSelkIsGoodZvtxFT0vsPV", "EvSelkNoSameBunchPileup", "EvSelkNoCollInTimeRangeStandard", "EvSelkIsGoodITSLayersAll", "EvSelkNoCollInRofStandard", "EvSelkNoHighMultCollInPrevRof", "EvSelOccupancy", "EvSelMultCorrelationPVTracks", "EvSelMultCorrelationGlobalTracks", "EvSelV0AT0ACut"}; +static const std::vector openTrackSelNames{"passedITSNCls", "passedITSChi2NDF", "passedITSHits", "passedTPCChi2NDF", "passedTPCCrossedRowsOverNCls", "passedDCAxy", "passedDCAz"}; +static const std::vector plot3DConfigNames{"Open related 3D nSigma plots"}; +static const std::vector openEventSelConfigNames{"Open related event selection options"}; +static const std::vector openTrackSelConfigNames{"Open track selection from TrackSelection table"}; +static const std::vector pidTPCnSigmaNames{"n#sigma_{TPC} Low", "n#sigma_{TPC} High"}; +static const std::vector pidITSnSigmaNames{"n#sigma_{ITS} Low", "n#sigma_{ITS} High"}; +static const std::vector pidPtNames{"p_{T} Low", "p_{T} High"}; +std::vector eseCandidates; +// Tar ptr +std::shared_ptr hPIDQATar1D[12]; +std::shared_ptr hPIDQATar2D[4]; +std::shared_ptr hPIDQATar3D[3]; +std::shared_ptr hv2Tar[2]; +std::shared_ptr hESEQATar1D[2]; +std::shared_ptr hESEQATar2D; +std::shared_ptr hESETar; +// Ref ptr +std::shared_ptr hPIDQARef1D[12]; +std::shared_ptr hPIDQARef2D[4]; +std::shared_ptr hPIDQARef3D[3]; +std::shared_ptr hv2Ref[2]; +std::shared_ptr hESEQARef1D[2]; +std::shared_ptr hESEQARef2D; +} // namespace ese_parameters -using TracksPID = soa::Join; -struct FillPIDcolums { +using TracksPIDFull = soa::Join; - HistogramRegistry histosQA{"histosQAPID", {}, OutputObjHandlingPolicy::AnalysisObject}; +struct FlowEsePHe3 { + EventPlaneHelper helperEP; + o2::aod::ITSResponse itsResponse; + HistogramRegistry histsESE{"histsESE", {}, OutputObjHandlingPolicy::AnalysisObject}; + // process POI control + Configurable cfgTarName{"cfgTarName", "kHe3", "Name of the v2 particle: kProton, kDeuteron, kTriton, kHe3, kAlpha"}; + Configurable cfgRefName{"cfgRefName", "kProton", "Name of the q2 reference particle: kProton, kDeuteron, kTriton, kHe3, kAlpha"}; + // total control config + Configurable cfgOpenAllowCrossTrack{"cfgOpenAllowCrossTrack", false, "Allow one track to be identified as different kind of PID particles"}; + Configurable cfgOpenFullEventQA{"cfgOpenFullEventQA", true, "Open full QA plots for event QA"}; + Configurable cfgOpenPIDQA{"cfgOpenPIDQA", true, "Open PID QA plots"}; + Configurable cfgOpenv2{"cfgOpenv2", true, "Open v2(EP)and q calculation for Proton and He3"}; + Configurable cfgOpenESE{"cfgOpenESE", true, "Open ESE plots"}; + Configurable cfgOpenESEQA{"cfgOpenESEQA", true, "Open ESE QA plots"}; + Configurable> cfgOpen3DPIDPlots{"cfgOpen3DPIDPlots", {ese_parameters::Open3DPIDPlots[0], 3, 1, ese_parameters::plot3DPIDNames, ese_parameters::plot3DConfigNames}, "3D PID QA Plots switch configuration"}; + // Qvec configs + 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"}; + Configurable cfgnTotalSystem{"cfgnTotalSystem", 7, "total qvector number"}; + // pre event selection(filter) + Configurable cfgVtzCut{"cfgVtzCut", 10.0f, "Accepted z-vertex range"}; + Configurable cfgCentMin{"cfgCentMin", 0.0f, "Centrality min"}; + Configurable cfgCentMax{"cfgCentMax", 100.0f, "Centrality max"}; + // event selection configs + Configurable cfgCutOccupancyLow{"cfgCutOccupancyLow", 0, "Low boundary cut on TPC occupancy"}; + Configurable cfgCutOccupancyHigh{"cfgCutOccupancyHigh", 3000, "High boundary cut on TPC occupancy"}; + Configurable> cfgOpenEvSel{"cfgOpenEvSel", {ese_parameters::OpenEvSel[0], 10, 1, ese_parameters::openEventSelNames, ese_parameters::openEventSelConfigNames}, "Event selection switch configuration"}; + // track selection configs + Configurable> cfgOpenTrackSel{"cfgOpenTrackSel", {ese_parameters::OpenTrackSel[0], 7, 1, ese_parameters::openTrackSelNames, ese_parameters::openTrackSelConfigNames}, "Track selection switch configuration"}; Configurable cfgMinPtPID{"cfgMinPtPID", 0.15, "Minimum track #P_{t} for PID"}; Configurable cfgMaxPtPID{"cfgMaxPtPID", 99.9, "Maximum track #P_{t} for PID"}; Configurable cfgMaxEtaPID{"cfgMaxEtaPID", 0.8, "Maximum track #eta for PID"}; @@ -101,516 +274,152 @@ struct FillPIDcolums { Configurable cfgMaxDCAxy{"cfgMaxDCAxy", 99, "Maxium DCAxy for standard PID tracking"}; Configurable cfgMaxDCAz{"cfgMaxDCAz", 2, "Maxium DCAz for standard PID tracking"}; Configurable cfgPtMaxforTPCOnlyPIDPrton{"cfgPtMaxforTPCOnlyPIDPrton", 0.4, "Maxmium track pt for TPC only PID, at RMS PID mode for proton"}; - Configurable cfgPtMaxforTPCOnlyPIDHe3{"cfgPtMaxforTPCOnlyPIDHe3", 0.5, "Maxmium track pt for TPC only PID, at RMS PID mode for he3"}; - - Configurable cfgProtonPIDMode{"cfgProtonPIDMode", 2, "Proton PID mode: 0 for TPC + RMS(TPC,TOF), 1 for TPC only, 2 for TOF only"}; - Configurable cfgHe3PIDMode{"cfgHe3PIDMode", 1, "He3 PID mode: 0 for TPC + RMS(TPC,TOF), 1 for TPC only, 2 for TOF only"}; - - Configurable cfgOpenpassedITSNCls{"cfgOpenpassedITSNCls", false, "useTrackSelectionTables passedITSNCls for basic track selection"}; - Configurable cfgOpenpassedITSChi2NDF{"cfgOpenpassedITSChi2NDF", false, "useTrackSelectionTables passedITSChi2NDF for basic track selection"}; - Configurable cfgOpenpassedITSHits{"cfgOpenpassedITSHits", false, "useTrackSelectionTables passedITSHits for basic track selection"}; - Configurable cfgOpenpassedTPCChi2NDF{"cfgOpenpassedTPCChi2NDF", false, "useTrackSelectionTables passedTPCChi2NDF for basic track selection"}; - Configurable cfgOpenpassedTPCCrossedRowsOverNCls{"cfgOpenpassedTPCCrossedRowsOverNCls", false, "useTrackSelectionTables passedTPCCrossedRowsOverNCls for basic track selection"}; - Configurable cfgOpenpassedDCAxy{"cfgOpenpassedDCAxy", false, "useTrackSelectionTables passedDCAxy for basic track selection"}; - Configurable cfgOpenpassedDCAz{"cfgOpenpassedDCAz", false, "useTrackSelectionTables passedDCAz for basic track selection"}; - - Configurable cfgQuietMode{"cfgQuietMode", false, "open quiet mode for saving cpu cost and only do some basic QA plots"}; - Configurable cfgOpenPIDITSProton{"cfgOpenPIDITSProton", true, "open ITS assistance cut for proton PID"}; - Configurable cfgOpenPIDITSHe3{"cfgOpenPIDITSHe3", false, "open ITS assistance cut for He3 PID"}; - Configurable cfgOpenPIDByPtProtonMain{"cfgOpenPIDByPtProtonMain", false, "Selection Proton by pt its pt binnings for main selection"}; - Configurable cfgOpenPIDByPtHe3Main{"cfgOpenPIDByPtHe3Main", false, "Selection He3 by pt its pt binnings for main selection"}; - Configurable cfgOpenPIDByPtProtonITS{"cfgOpenPIDByPtProtonITS", false, "Selection Proton by pt its pt binnings for ITS selection"}; - Configurable cfgOpenPIDByPtHe3ITS{"cfgOpenPIDByPtHe3ITS", false, "Selection He3 by pt its pt binnings for ITS selection"}; - Configurable cfgOpenHe3ITSPtCut{"cfgOpenHe3ITSPtCut", true, "Do He3 ITS contamination cut"}; - Configurable cfgOpenAllowCrossTrack{"cfgOpenAllowCrossTrack", false, "Allow one track to be identified as different kind of PID particles"}; - - Configurable cfgOpenPlotnSigmaTOFITSPt{"cfgOpenPlotnSigmaTOFITSPt", true, "plot nSigmaTOF vs nSigmaITS vs Pt"}; - Configurable cfgOpenPlotnSigmaITSTPCPt{"cfgOpenPlotnSigmaITSTPCPt", true, "plot nSigmaITS vs nSigmaTOF vs Pt"}; - Configurable cfgOpenPlotnSigmaTOFTPCPt{"cfgOpenPlotnSigmaTOFTPCPt", true, "plot nSigmaTOF vs nSigmaTPC vs Pt"}; - - Configurable> cfgPtCutProton{"cfgPtCutProton", {0.15, 99.}, "Pt limit for Proton"}; - Configurable> cfgPtCutHe3{"cfgPtCutHe3", {0.15, 99.}, "Pt limit for He3"}; - Configurable> cfgnSigmaCutTPCProton{"cfgnSigmaCutTPCProton", {-3, 3}, "TPC nsigma cut limit for Proton"}; - Configurable> cfgnSigmaCutTPCHe3{"cfgnSigmaCutTPCHe3", {-2, 2}, "TPC nsigma cut limit for He3"}; + // PID configs + Configurable> cfgPtPreselection{"cfgPtPreselection", {ese_parameters::PtPreselection[0], 5, 2, ese_parameters::names, ese_parameters::pidPtNames}, "Pt preselection for light nuclei"}; Configurable> cfgnSigmaCutTOFProton{"cfgnSigmaCutTOFProton", {-1.5, 1.5}, "TOF nsigma cut limit for Proton"}; - Configurable> cfgnSigmaCutTOFHe3{"cfgnSigmaCutTOFHe3", {-1.5, 1.5}, "TOF nsigma cut limit for He3"}; - Configurable> cfgnSigmaCutITSProton{"cfgnSigmaCutITSProton", {-3, 3}, "ITS nsigma cut limit for Proton"}; - Configurable> cfgnSigmaCutITSHe3{"cfgnSigmaCutITSHe3", {-3, 3}, "ITS nsigma cut limit for He3"}; Configurable> cfgnSigmaCutRMSProton{"cfgnSigmaCutRMSProton", {-3, 3}, "RMS nsigma cut limit for Proton"}; - Configurable> cfgnSigmaCutRMSHe3{"cfgnSigmaCutRMSHe3", {-3, 3}, "RMS nsigma cut limit for He3"}; - - Configurable> cfgPtBinProtonPID{"cfgPtBinProtonPID", {0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.25, 1.5, 1.75, 2.0, 2.25, 2.5, 3.0, 3.5, 4.0, 5.0, 6.0}, "pt bin for pion PIDnsigma"}; - Configurable> cfgPtBinHe3PID{"cfgPtBinHe3PID", {2, 2.2, 2.4, 2.6, 2.8, 3, 3.2, 3.6, 4, 4.4, 4.8, 5.2, 5.6, 6, 6.4, 7.2, 8, 10}, "pt bin for pion PIDnsigma"}; - - Configurable> cfgnSigmaTPCProtonPtUpper{"cfgnSigmaTPCProtonPtUpper", {3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3}, "nSigmaTPC cut upper limit anchored to proton pt bins"}; - Configurable> cfgnSigmaTOFProtonPtUpper{"cfgnSigmaTOFProtonPtUpper", {1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5}, "nSigmaTOF cut upper limit anchored to proton pt bins"}; - Configurable> cfgnSigmaITSProtonPtUpper{"cfgnSigmaITSProtonPtUpper", {2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}, "nSigmaITS cut upper limit anchored to proton pt bins"}; - Configurable> cfgnSigmaRMSProtonPtUpper{"cfgnSigmaRMSProtonPtUpper", {3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3}, "nSigmaRMS cut upper limit anchored to proton pt bins"}; - Configurable> cfgnSigmaTPCProtonPtLower{"cfgnSigmaTPCProtonPtLower", {-3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3}, "nSigmaTPC cut lower limit anchored to proton pt bins"}; - Configurable> cfgnSigmaTOFProtonPtLower{"cfgnSigmaTOFProtonPtLower", {-1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5}, "nSigmaTOF cut lower limit anchored to proton pt bins"}; - Configurable> cfgnSigmaITSProtonPtLower{"cfgnSigmaITSProtonPtLower", {-2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2}, "nSigmaITS cut lower limit anchored to proton pt bins"}; - Configurable> cfgnSigmaRMSProtonPtLower{"cfgnSigmaRMSProtonPtLower", {-3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3}, "nSigmaRMS cut lower limit anchored to proton pt bins"}; - Configurable> cfgnSigmaTPCHe3PtUpper{"cfgnSigmaTPCHe3PtUpper", {3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3}, "nSigmaTPC cut upper limit anchored to He3 pt bins"}; - Configurable> cfgnSigmaTOFHe3PtUpper{"cfgnSigmaTOFHe3PtUpper", {1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5}, "nSigmaTOF cut upper limit anchored to He3 pt bins"}; - Configurable> cfgnSigmaITSHe3PtUpper{"cfgnSigmaITSHe3PtUpper", {2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}, "nSigmaITS cut upper limit anchored to He3 pt bins"}; - Configurable> cfgnSigmaRMSHe3PtUpper{"cfgnSigmaRMSHe3PtUpper", {3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3}, "nSigmaRMS cut upper limit anchored to He3 pt bins"}; - Configurable> cfgnSigmaTPCHe3PtLower{"cfgnSigmaTPCHe3PtLower", {-3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3}, "nSigmaTPC cut lower limit anchored to He3 pt bins"}; - Configurable> cfgnSigmaTOFHe3PtLower{"cfgnSigmaTOFHe3PtLower", {-1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5}, "nSigmaTOF cut lower limit anchored to He3 pt bins"}; - Configurable> cfgnSigmaITSHe3PtLower{"cfgnSigmaITSHe3PtLower", {-2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2}, "nSigmaITS cut lower limit anchored to He3 pt bins"}; - Configurable> cfgnSigmaRMSHe3PtLower{"cfgnSigmaRMSHe3PtLower", {-3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3}, "nSigmaRMS cut lower limit anchored to He3 pt bins"}; - + Configurable cfgUseSelfnSigmaTPCProton{"cfgUseSelfnSigmaTPCProton", false, "Use self nSigma TPC for Proton PID"}; + Configurable cfgProtonPIDMode{"cfgProtonPIDMode", 2, "Proton PID mode: 0 for TPC + RMS(TPC,TOF), 1 for TPC only, 2 for TOF only"}; + Configurable> cfgnSigmaTPC{"cfgnSigmaTPC", {ese_parameters::TPCnSigmaCutDefault[0], 5, 2, ese_parameters::names, ese_parameters::pidTPCnSigmaNames}, "TPC nSigma selection for light nuclei"}; + Configurable> cfgnSigmaITS{"cfgnSigmaITS", {ese_parameters::ITSnSigmaCutDefault[0], 5, 2, ese_parameters::names, ese_parameters::pidITSnSigmaNames}, "ITS nSigma selection for light nuclei"}; + // PID BBself paras config + Configurable> cfgBetheBlochParams{"cfgBetheBlochParams", {ese_parameters::BetheBlochDefault[0], 5, 6, ese_parameters::names, ese_parameters::betheBlochParNames}, "TPC Bethe-Bloch parameterisation for light nuclei"}; + Configurable> cfgMomentumScalingBetheBloch{"cfgMomentumScalingBetheBloch", {ese_parameters::BbMomScalingDefault[0], 5, 2, ese_parameters::names, ese_parameters::chargeLabelNames}, "TPC Bethe-Bloch momentum scaling for light nuclei"}; + Configurable cfgCompensatePIDinTracking{"cfgCompensatePIDinTracking", true, "If true, divide tpcInnerParam by the electric charge"}; + // Axias configs ConfigurableAxis cfgrigidityBins{"cfgrigidityBins", {200, -10.f, 10.f}, "Binning for rigidity #it{p}^{TPC}/#it{z}"}; ConfigurableAxis cfgdedxBins{"cfgdedxBins", {1000, 0.f, 1000.f}, "Binning for dE/dx"}; ConfigurableAxis cfgnSigmaBinsTPC{"cfgnSigmaBinsTPC", {200, -5.f, 5.f}, "Binning for n sigma TPC"}; ConfigurableAxis cfgnSigmaBinsTOF{"cfgnSigmaBinsTOF", {200, -5.f, 5.f}, "Binning for n sigma TOF"}; ConfigurableAxis cfgnSigmaBinsITS{"cfgnSigmaBinsITS", {200, -5.f, 5.f}, "Binning for n sigma ITS"}; - ConfigurableAxis cfgnSigmaBinsRMS{"cfgnSigmaBinsRMS", {100, 0.f, 10.f}, "Combination Binning for TPC&TOF nsigma"}; - ConfigurableAxis cfgaxisptPID{"cfgaxisptPID", {120, 0, 12}, "Binning for P_{t} PID"}; - ConfigurableAxis cfgaxispPID{"cfgaxispPID", {50, 0, 5}, "Binning for P PID"}; + ConfigurableAxis cfgaxispt{"cfgaxispt", {100, 0, 10}, "Binning for P_{t}"}; ConfigurableAxis cfgaxisetaPID{"cfgaxisetaPID", {90, -0.9, 0.9}, "Binning for Pt QA"}; ConfigurableAxis cfgaxisDCAz{"cfgaxisDCAz", {200, -1, 1}, "Binning for DCAz"}; ConfigurableAxis cfgaxisDCAxy{"cfgaxisDCAxy", {100, -0.5, 0.5}, "Binning for DCAxy"}; - ConfigurableAxis cfgaxisChi2Ncls{"cfgaxisChi2Ncls", {100, 0, 100}, "Binning for Chi2Ncls TPC/ITS"}; + ConfigurableAxis cfgaxisChi2Ncls{"cfgaxisChi2Ncls", {100, 0, 30}, "Binning for Chi2Ncls TPC/ITS"}; + ConfigurableAxis cfgaxisQvecF{"cfgaxisQvecF", {300, -1, 1}, ""}; + ConfigurableAxis cfgaxisCent{"cfgaxisCent", {90, 0, 90}, ""}; + ConfigurableAxis cfgaxisNch{"cfgaxisNch", {4000, 0, 4000}, "N_{ch}"}; + ConfigurableAxis cfgaxisT0C{"cfgaxisT0C", {70, 0, 70000}, "N_{ch} (T0C)"}; + ConfigurableAxis cfgaxisT0A{"cfgaxisT0A", {200, 0, 200000}, "N_{ch} (T0A)"}; + ConfigurableAxis cfgaxisNchPV{"cfgaxisNchPV", {4000, 0, 4000}, "N_{ch} (PV)"}; + ConfigurableAxis cfgaxisq2{"cfgaxisq2", {120, 0, 12}, "Binning for P_{t} PID"}; + ConfigurableAxis cfgaxiscos{"cfgaxiscos", {102, -1.02, 1.02}, ""}; - // Function for He3 TPC-ITS mismatching cuts referd to by chiara's slides - TF1* fNSigmaITSPt = nullptr; + uint8_t poiTar; + uint8_t poiRef; + int detId; + int refAId; + int refBId; + int detInd; + int refAInd; + int refBInd; + // Function for He3 purity cut refered from luca's slides + TF1* fMultPVCutLow = nullptr; + TF1* fMultPVCutHigh = nullptr; + TF1* fMultCutLow = nullptr; + TF1* fMultCutHigh = nullptr; + TF1* fT0AV0AMean = nullptr; + TF1* fT0AV0ASigma = nullptr; - template - bool trackSelBasic(const TrackType track) - { - if ((track.pt() < cfgMinPtPID) || (track.pt() > cfgMaxPtPID)) - return false; - if (std::abs(track.eta()) > cfgMaxEtaPID) - return false; - if (cfgOpenpassedITSNCls) { - if (!track.passedITSNCls()) - return false; - } else { - if (track.itsNCls() < cfgMinITSCls || track.itsNCls() > cfgMaxITSCls) - return false; - } - if (cfgOpenpassedITSChi2NDF) { - if (!track.passedITSChi2NDF()) - return false; - } else { - if (track.itsChi2NCl() < cfgMinChi2NClITS || track.itsChi2NCl() > cfgMaxChi2NClITS) - return false; - } - if (cfgOpenpassedITSHits) { - if (!track.passedITSHits()) - return false; - } - if (cfgOpenpassedTPCChi2NDF) { - if (!track.passedTPCChi2NDF()) - return false; - } else { - if (track.tpcChi2NCl() < cfgMinTPCChi2NCl || track.tpcChi2NCl() > cfgMaxTPCChi2NCl) - return false; - } - if (cfgOpenpassedTPCCrossedRowsOverNCls) { - if (!track.passedTPCCrossedRowsOverNCls()) - return false; - } - if (cfgOpenpassedDCAxy) { - if (!track.passedDCAxy()) - return false; - } else { - if (std::abs(track.dcaXY()) > cfgMaxDCAxy) - return false; - } - if (cfgOpenpassedDCAz) { - if (!track.passedDCAz()) - return false; - } else { - if (std::abs(track.dcaZ()) > cfgMaxDCAz) - return false; - } - if (track.tpcNClsFound() < cfgMinTPCCls || track.tpcNClsFound() > cfgMaxTPCCls) - return false; - return true; - } + Filter collisionFilter = (nabs(aod::collision::posZ) < cfgVtzCut) && (aod::cent::centFT0C > cfgCentMin) && (aod::cent::centFT0C < cfgCentMax); - template - bool pidProtonSel(const TrackType track, float nSigmaLower, float nSigmaUpper) - { // proton == 1 , He3 == 2 - if (track.pt() < cfgPtCutProton.value[0] || track.pt() > cfgPtCutProton.value[1]) - return false; - float nSigmaUse = -999; - switch (cfgProtonPIDMode) { - case 0: // RMS - nSigmaUse = (track.pt() > cfgPtMaxforTPCOnlyPIDPrton) ? std::hypot(track.tpcNSigmaPr(), track.tofNSigmaPr()) : track.tpcNSigmaPr(); - break; - case 1: // TPC only - nSigmaUse = track.tpcNSigmaPr(); - break; - case 2: // TOF only - nSigmaUse = track.tofNSigmaPr(); - break; - } - if (nSigmaUse < nSigmaLower || nSigmaUse > nSigmaUpper) { - return false; - } else { - return true; - } - } + Produces eseTable; template - bool pidHe3Sel(const TrackType track, float nSigmaLower, float nSigmaUpper) - { // proton == 1 , He3 == 2 - if (track.pt() < cfgPtCutHe3.value[0] || track.pt() > cfgPtCutHe3.value[1]) - return false; - float nSigmaUse = -999; - switch (cfgHe3PIDMode) { - case 0: // RMS - nSigmaUse = (track.pt() > cfgPtMaxforTPCOnlyPIDHe3) ? std::hypot(track.tpcNSigmaHe(), track.tofNSigmaHe()) : track.tpcNSigmaHe(); - break; - case 1: // TPC only - nSigmaUse = track.tpcNSigmaHe(); - break; - case 2: // TOF only - nSigmaUse = track.tofNSigmaHe(); - break; - } - if (nSigmaUse < nSigmaLower || nSigmaUse > nSigmaUpper) { - return false; - } else { - return true; + float getNSigmaTPCSelfBB(const TrackType track, uint8_t POI) + { + bool heliumPID = track.pidForTracking() == o2::track::PID::Helium3 || track.pidForTracking() == o2::track::PID::Alpha; + float correctedTpcInnerParam = (heliumPID && cfgCompensatePIDinTracking) ? track.tpcInnerParam() / 2 : track.tpcInnerParam(); + const int iC{track.sign() < 0}; + switch (POI) { + case ese_parameters::kProton: { + const double bgScaling[2]{ese_parameters::Charges[0] * cfgMomentumScalingBetheBloch->get(0u, 0u) / ese_parameters::Masses[0], ese_parameters::Charges[0] * cfgMomentumScalingBetheBloch->get(0u, 1u) / ese_parameters::Masses[0]}; + double expBethe{tpc::BetheBlochAleph(static_cast(correctedTpcInnerParam * bgScaling[iC]), cfgBetheBlochParams->get(0u, 0u), cfgBetheBlochParams->get(0u, 1u), cfgBetheBlochParams->get(0u, 2u), cfgBetheBlochParams->get(0u, 3u), cfgBetheBlochParams->get(0u, 4u))}; + double expSigma{expBethe * cfgBetheBlochParams->get(0u, 5u)}; + double nSigmaTPC{static_cast((track.tpcSignal() - expBethe) / expSigma)}; + return nSigmaTPC; + } + case ese_parameters::kDeuteron: { + const double bgScaling[2]{ese_parameters::Charges[1] * cfgMomentumScalingBetheBloch->get(1u, 0u) / ese_parameters::Masses[1], ese_parameters::Charges[1] * cfgMomentumScalingBetheBloch->get(1u, 1u) / ese_parameters::Masses[1]}; + double expBethe{tpc::BetheBlochAleph(static_cast(correctedTpcInnerParam * bgScaling[iC]), cfgBetheBlochParams->get(1u, 0u), cfgBetheBlochParams->get(1u, 1u), cfgBetheBlochParams->get(1u, 2u), cfgBetheBlochParams->get(1u, 3u), cfgBetheBlochParams->get(1u, 4u))}; + double expSigma{expBethe * cfgBetheBlochParams->get(1u, 5u)}; + double nSigmaTPC{static_cast((track.tpcSignal() - expBethe) / expSigma)}; + return nSigmaTPC; + } + case ese_parameters::kTriton: { + const double bgScaling[2]{ese_parameters::Charges[2] * cfgMomentumScalingBetheBloch->get(2u, 0u) / ese_parameters::Masses[2], ese_parameters::Charges[2] * cfgMomentumScalingBetheBloch->get(2u, 1u) / ese_parameters::Masses[2]}; + double expBethe{tpc::BetheBlochAleph(static_cast(correctedTpcInnerParam * bgScaling[iC]), cfgBetheBlochParams->get(2u, 0u), cfgBetheBlochParams->get(2u, 1u), cfgBetheBlochParams->get(2u, 2u), cfgBetheBlochParams->get(2u, 3u), cfgBetheBlochParams->get(2u, 4u))}; + double expSigma{expBethe * cfgBetheBlochParams->get(2u, 5u)}; + double nSigmaTPC{static_cast((track.tpcSignal() - expBethe) / expSigma)}; + return nSigmaTPC; + } + case ese_parameters::kHe3: { + const double bgScaling[2]{ese_parameters::Charges[3] * cfgMomentumScalingBetheBloch->get(3u, 0u) / ese_parameters::Masses[3], ese_parameters::Charges[3] * cfgMomentumScalingBetheBloch->get(3u, 1u) / ese_parameters::Masses[3]}; + double expBethe{tpc::BetheBlochAleph(static_cast(correctedTpcInnerParam * bgScaling[iC]), cfgBetheBlochParams->get(3u, 0u), cfgBetheBlochParams->get(3u, 1u), cfgBetheBlochParams->get(3u, 2u), cfgBetheBlochParams->get(3u, 3u), cfgBetheBlochParams->get(3u, 4u))}; + double expSigma{expBethe * cfgBetheBlochParams->get(3u, 5u)}; + double nSigmaTPC{static_cast((track.tpcSignal() - expBethe) / expSigma)}; + return nSigmaTPC; + } + case ese_parameters::kAlpha: { + const double bgScaling[2]{ese_parameters::Charges[4] * cfgMomentumScalingBetheBloch->get(4u, 0u) / ese_parameters::Masses[4], ese_parameters::Charges[4] * cfgMomentumScalingBetheBloch->get(4u, 1u) / ese_parameters::Masses[4]}; + double expBethe{tpc::BetheBlochAleph(static_cast(correctedTpcInnerParam * bgScaling[iC]), cfgBetheBlochParams->get(4u, 0u), cfgBetheBlochParams->get(4u, 1u), cfgBetheBlochParams->get(4u, 2u), cfgBetheBlochParams->get(4u, 3u), cfgBetheBlochParams->get(4u, 4u))}; + double expSigma{expBethe * cfgBetheBlochParams->get(4u, 5u)}; + double nSigmaTPC{static_cast((track.tpcSignal() - expBethe) / expSigma)}; + return nSigmaTPC; + } + default: + return -99.f; } } template - int crossTrackID(const TrackType track) + float getNSigmaTOF(const TrackType track, uint8_t POI) { - if (track.tpcNSigmaPr() < track.tpcNSigmaHe()) { - return 0; - } else { - return 1; + switch (POI) { + case ese_parameters::kProton: { + return track.tofNSigmaPr(); + } + case ese_parameters::kDeuteron: { + return track.tofNSigmaDe(); + } + case ese_parameters::kTriton: { + return track.tofNSigmaTr(); + } + case ese_parameters::kHe3: { + return track.tofNSigmaHe(); + } + case ese_parameters::kAlpha: { + return track.tofNSigmaAl(); + } + default: + return -99.f; } } - void init(InitContext const&) + template + float getNSigmaITS(const TrackType track, uint8_t POI) { - if (cfgOpenHe3ITSPtCut) { - fNSigmaITSPt = new TF1("fNSigmaITSPt", "[0]/pow(x,0.5) - [2]", 0.02, 1000); - fNSigmaITSPt->SetParameters(4.6, 0.5, 4.5); - } - AxisSpec axisITSNcls = {10, -1.5, 8.5, "ITSNcls"}; - AxisSpec axisTPCNcls = {160, 0, 160, "TPCNcls"}; - if (!cfgQuietMode) { - histosQA.add("QA/hist_dEdxTPC_All", ";#it{p}^{TPC}/#it{z} (GeV/c);d#it{E}/d#it{x}", {HistType::kTH2F, {cfgrigidityBins, cfgdedxBins}}); - histosQA.add("QA/Proton/hist_dEdxTPC_Pr", ";#it{p}^{TPC}/#it{z} (GeV/c);d#it{E}/d#it{x}", {HistType::kTH2F, {cfgrigidityBins, cfgdedxBins}}); - histosQA.add("QA/He3/hist_dEdxTPC_He3", ";#it{p}^{TPC}/#it{z} (GeV/c);d#it{E}/d#it{x}", {HistType::kTH2F, {cfgrigidityBins, cfgdedxBins}}); - histosQA.add("QA/hist_pt_All", ";#it{p}_{T};counts", {HistType::kTH1F, {cfgaxisptPID}}); - histosQA.add("QA/Proton/hist_pt_Pr", ";#it{p}_{T};counts", {HistType::kTH1F, {cfgaxisptPID}}); - histosQA.add("QA/He3/hist_pt_He3", ";#it{p}_{T};counts", {HistType::kTH1F, {cfgaxisptPID}}); - histosQA.add("QA/hist_eta_All", ";#it{#eta};counts", {HistType::kTH1F, {cfgaxisetaPID}}); - histosQA.add("QA/Proton/hist_eta_Pr", ";#it{#eta};counts", {HistType::kTH1F, {cfgaxisetaPID}}); - histosQA.add("QA/He3/hist_eta_He3", ";#it{#eta};counts", {HistType::kTH1F, {cfgaxisetaPID}}); - histosQA.add("QA/hist_ITSNcls_All", ";ITSNcls;counts", {HistType::kTH1F, {axisITSNcls}}); - histosQA.add("QA/Proton/hist_ITSNcls_Pr", ";ITSNcls;counts", {HistType::kTH1F, {axisITSNcls}}); - histosQA.add("QA/He3/hist_ITSNcls_He3", ";ITSNcls;counts", {HistType::kTH1F, {axisITSNcls}}); - histosQA.add("QA/hist_TPCNcls_All", ";TPCNcls;counts", {HistType::kTH1F, {axisTPCNcls}}); - histosQA.add("QA/Proton/hist_TPCNcls_Pr", ";TPCNcls;counts", {HistType::kTH1F, {axisTPCNcls}}); - histosQA.add("QA/He3/hist_TPCNcls_He3", ";TPCNcls;counts", {HistType::kTH1F, {axisTPCNcls}}); - histosQA.add("QA/hist_ITSChi2NDF_All", ";ITS#it{#chi^{2}}/NDF;counts", {HistType::kTH1F, {cfgaxisChi2Ncls}}); - histosQA.add("QA/Proton/hist_ITSChi2NDF_Pr", ";ITS#it{#chi^{2}}/NDF;counts", {HistType::kTH1F, {cfgaxisChi2Ncls}}); - histosQA.add("QA/He3/hist_ITSChi2NDF_He3", ";ITS#it{#chi^{2}}/NDF;counts", {HistType::kTH1F, {cfgaxisChi2Ncls}}); - histosQA.add("QA/hist_TPCChi2NDF_All", ";TPC#it{#chi^{2}}/NDF;counts", {HistType::kTH1F, {cfgaxisChi2Ncls}}); - histosQA.add("QA/Proton/hist_TPCChi2NDF_Pr", ";TPC#it{#chi^{2}}/NDF;counts", {HistType::kTH1F, {cfgaxisChi2Ncls}}); - histosQA.add("QA/He3/hist_TPCChi2NDF_He3", ";TPC#it{#chi^{2}}/NDF;counts", {HistType::kTH1F, {cfgaxisChi2Ncls}}); - histosQA.add("QA/hist_DCAxy_All", ";#it{DCA_{xy}};counts", {HistType::kTH1F, {cfgaxisDCAxy}}); - histosQA.add("QA/Proton/hist_DCAxy_Pr", ";#it{DCA_{xy}};counts", {HistType::kTH1F, {cfgaxisDCAxy}}); - histosQA.add("QA/He3/hist_DCAxy_He3", ";#it{DCA_{xy}};counts", {HistType::kTH1F, {cfgaxisDCAxy}}); - histosQA.add("QA/hist_DCAz_All", ";#it{DCA_{xy}};counts", {HistType::kTH1F, {cfgaxisDCAz}}); - histosQA.add("QA/Proton/hist_DCAz_Pr", ";#it{DCA_{xy}};counts", {HistType::kTH1F, {cfgaxisDCAz}}); - histosQA.add("QA/He3/hist_DCAz_He3", ";#it{DCA_{xy}};counts", {HistType::kTH1F, {cfgaxisDCAz}}); - histosQA.add("QA/Proton/hist_nSigmaTPC_Pr", ";n_{#sigma}TPC", {HistType::kTH1F, {cfgnSigmaBinsTPC}}); - histosQA.add("QA/Proton/hist_nSigmaTPCPt_Pr", ";#it{p}_{T};n_{#sigma}TPC", {HistType::kTH2F, {cfgaxisptPID, cfgnSigmaBinsTPC}}); - histosQA.add("QA/Proton/hist_nSigmaTOF_Pr", ";n_{#sigma}TOF", {HistType::kTH1F, {cfgnSigmaBinsTOF}}); - histosQA.add("QA/Proton/hist_nSigmaTOFPt_Pr", ";#it{p}_{T};n_{#sigma}TOF", {HistType::kTH2F, {cfgaxisptPID, cfgnSigmaBinsTOF}}); - histosQA.add("QA/Proton/hist_nSigmaITS_Pr", ";n_{#sigma}ITS", {HistType::kTH1F, {cfgnSigmaBinsITS}}); - histosQA.add("QA/Proton/hist_nSigmaITSPt_Pr", ";#it{p}_{T};n_{#sigma}ITS", {HistType::kTH2F, {cfgaxisptPID, cfgnSigmaBinsITS}}); - histosQA.add("QA/Proton/hist_nSigmaRMS_Pr", ";n_{#sigma}RMS", {HistType::kTH1F, {cfgnSigmaBinsRMS}}); - histosQA.add("QA/Proton/hist_nSigmaRMSPt_Pr", ";#it{p}_{T};n_{#sigma}RMS", {HistType::kTH2F, {cfgaxisptPID, cfgnSigmaBinsRMS}}); - histosQA.add("QA/He3/hist_nSigmaTPC_He3", ";n_{#sigma}TPC", {HistType::kTH1F, {cfgnSigmaBinsTPC}}); - histosQA.add("QA/He3/hist_nSigmaTPCPt_He3", ";#it{p}_{T};n_{#sigma}TPC", {HistType::kTH2F, {cfgaxisptPID, cfgnSigmaBinsTPC}}); - histosQA.add("QA/He3/hist_nSigmaTOF_He3", ";n_{#sigma}TOF", {HistType::kTH1F, {cfgnSigmaBinsTOF}}); - histosQA.add("QA/He3/hist_nSigmaTOFPt_He3", ";#it{p}_{T};n_{#sigma}TOF", {HistType::kTH2F, {cfgaxisptPID, cfgnSigmaBinsTOF}}); - histosQA.add("QA/He3/hist_nSigmaITS_He3", ";n_{#sigma}ITS", {HistType::kTH1F, {cfgnSigmaBinsITS}}); - histosQA.add("QA/He3/hist_nSigmaITSPt_He3", ";#it{p}_{T};n_{#sigma}ITS", {HistType::kTH2F, {cfgaxisptPID, cfgnSigmaBinsITS}}); - histosQA.add("QA/He3/hist_nSigmaRMS_He3", ";n_{#sigma}RMS", {HistType::kTH1F, {cfgnSigmaBinsRMS}}); - histosQA.add("QA/He3/hist_nSigmaRMSPt_He3", ";#it{p}_{T};n_{#sigma}RMS", {HistType::kTH2F, {cfgaxisptPID, cfgnSigmaBinsRMS}}); - if (cfgOpenHe3ITSPtCut) { - histosQA.add("QA/He3/hist_nSigmaITSPt_He3_unCuted", ";#it{p}_{T};n_{#sigma}ITS", {HistType::kTH2F, {cfgaxisptPID, cfgnSigmaBinsITS}}); + switch (POI) { + case ese_parameters::kProton: { + return itsResponse.nSigmaITS(track); } - if (cfgOpenPlotnSigmaTOFITSPt) { - histosQA.add("QA/Proton/hist_nSigmaTOFITSPt_Pr", ";n_{#sigma}TOF;n_{#sigma}ITS;#it{p}_{T}", {HistType::kTH3F, {cfgnSigmaBinsTOF, cfgnSigmaBinsITS, cfgaxisptPID}}); - histosQA.add("QA/He3/hist_nSigmaTOFITSPt_He3", ";n_{#sigma}TOF;n_{#sigma}ITS;#it{p}_{T}", {HistType::kTH3F, {cfgnSigmaBinsTOF, cfgnSigmaBinsITS, cfgaxisptPID}}); + case ese_parameters::kDeuteron: { + return itsResponse.nSigmaITS(track); } - if (cfgOpenPlotnSigmaITSTPCPt) { - histosQA.add("QA/Proton/hist_nSigmaITSTPCPt_Pr", ";n_{#sigma}ITS;n_{#sigma}TPC;#it{p}_{T}", {HistType::kTH3F, {cfgnSigmaBinsITS, cfgnSigmaBinsTPC, cfgaxisptPID}}); - histosQA.add("QA/He3/hist_nSigmaITSTPCPt_He3", ";n_{#sigma}ITS;n_{#sigma}TPC;#it{p}_{T}", {HistType::kTH3F, {cfgnSigmaBinsITS, cfgnSigmaBinsTPC, cfgaxisptPID}}); + case ese_parameters::kTriton: { + return itsResponse.nSigmaITS(track); } - if (cfgOpenPlotnSigmaTOFTPCPt) { - histosQA.add("QA/Proton/hist_nSigmaTOFTPCPt_Pr", ";n_{#sigma}TOF;n_{#sigma}TPC;#it{p}_{T}", {HistType::kTH3F, {cfgnSigmaBinsTOF, cfgnSigmaBinsTPC, cfgaxisptPID}}); - histosQA.add("QA/He3/hist_nSigmaTOFTPCPt_He3", ";n_{#sigma}TOF;n_{#sigma}TPC;#it{p}_{T}", {HistType::kTH3F, {cfgnSigmaBinsTOF, cfgnSigmaBinsTPC, cfgaxisptPID}}); + case ese_parameters::kHe3: { + return itsResponse.nSigmaITS(track); } - } - } - Produces pidEsePHe3Table; - void process(TracksPID const& tracks) - { - auto tracksWithITSPid = soa::Attach(tracks); - int8_t pidFlag; - for (const auto& track : tracksWithITSPid) { - histosQA.fill(HIST("QA/hist_dEdxTPC_All"), track.sign() * track.tpcInnerParam(), track.tpcSignal()); - histosQA.fill(HIST("QA/hist_pt_All"), track.pt()); - histosQA.fill(HIST("QA/hist_eta_All"), track.eta()); - histosQA.fill(HIST("QA/hist_ITSNcls_All"), track.itsNCls()); - histosQA.fill(HIST("QA/hist_TPCNcls_All"), track.tpcNClsFound()); - histosQA.fill(HIST("QA/hist_ITSChi2NDF_All"), track.itsChi2NCl()); - histosQA.fill(HIST("QA/hist_TPCChi2NDF_All"), track.tpcChi2NCl()); - histosQA.fill(HIST("QA/hist_DCAxy_All"), track.dcaXY()); - histosQA.fill(HIST("QA/hist_DCAz_All"), track.dcaZ()); - if (!trackSelBasic(track)) { - pidFlag = -1; - } else { - int currentPtBinPr = -1, currentPtBinHe3 = -1; - if (cfgOpenPIDByPtProtonMain || (cfgOpenPIDByPtProtonITS && cfgOpenPIDITSProton)) { - for (int i = 0; i < static_cast(cfgPtBinProtonPID.value.size()) - 1; ++i) { - if (track.pt() >= cfgPtBinProtonPID.value[i] && track.pt() < cfgPtBinProtonPID.value[i + 1]) { - currentPtBinPr = i; - break; - } - } - } - if (cfgOpenPIDByPtHe3Main || (cfgOpenPIDByPtHe3ITS && cfgOpenPIDITSHe3)) { - for (int i = 0; i < static_cast(cfgPtBinHe3PID.value.size()) - 1; ++i) { - if (track.pt() >= cfgPtBinHe3PID.value[i] && track.pt() < cfgPtBinHe3PID.value[i + 1]) { - currentPtBinHe3 = i; - break; - } - } - } - float nSigmaTPCCutPrPtLower = (currentPtBinPr == -1) ? cfgnSigmaCutTPCProton.value[0] : cfgnSigmaTPCProtonPtLower.value[currentPtBinPr]; - float nSigmaTPCCutPrPtUpper = (currentPtBinPr == -1) ? cfgnSigmaCutTPCProton.value[1] : cfgnSigmaTPCProtonPtUpper.value[currentPtBinPr]; - float nSigmaTOFCutPrPtLower = (currentPtBinPr == -1) ? cfgnSigmaCutTOFProton.value[0] : cfgnSigmaTOFProtonPtLower.value[currentPtBinPr]; - float nSigmaTOFCutPrPtUpper = (currentPtBinPr == -1) ? cfgnSigmaCutTOFProton.value[1] : cfgnSigmaTOFProtonPtUpper.value[currentPtBinPr]; - float nSigmaRMSCutPrPtLower = (currentPtBinPr == -1) ? cfgnSigmaCutRMSProton.value[0] : cfgnSigmaRMSProtonPtLower.value[currentPtBinPr]; - float nSigmaRMSCutPrPtUpper = (currentPtBinPr == -1) ? cfgnSigmaCutRMSProton.value[1] : cfgnSigmaRMSProtonPtUpper.value[currentPtBinPr]; - float nSigmaITSCutPrPtLower = (currentPtBinPr == -1) ? cfgnSigmaCutITSProton.value[0] : cfgnSigmaITSProtonPtLower.value[currentPtBinPr]; - float nSigmaITSCutPrPtUpper = (currentPtBinPr == -1) ? cfgnSigmaCutITSProton.value[1] : cfgnSigmaITSProtonPtUpper.value[currentPtBinPr]; - float nSigmaTPCCutHe3PtLower = (currentPtBinHe3 == -1) ? cfgnSigmaCutTPCHe3.value[0] : cfgnSigmaTPCHe3PtLower.value[currentPtBinHe3]; - float nSigmaTPCCutHe3PtUpper = (currentPtBinHe3 == -1) ? cfgnSigmaCutTPCHe3.value[1] : cfgnSigmaTPCHe3PtUpper.value[currentPtBinHe3]; - float nSigmaTOFCutHe3PtLower = (currentPtBinHe3 == -1) ? cfgnSigmaCutTOFHe3.value[0] : cfgnSigmaTOFHe3PtLower.value[currentPtBinHe3]; - float nSigmaTOFCutHe3PtUpper = (currentPtBinHe3 == -1) ? cfgnSigmaCutTOFHe3.value[1] : cfgnSigmaTOFHe3PtUpper.value[currentPtBinHe3]; - float nSigmaRMSCutHe3PtLower = (currentPtBinHe3 == -1) ? cfgnSigmaCutRMSHe3.value[0] : cfgnSigmaRMSHe3PtLower.value[currentPtBinHe3]; - float nSigmaRMSCutHe3PtUpper = (currentPtBinHe3 == -1) ? cfgnSigmaCutRMSHe3.value[1] : cfgnSigmaRMSHe3PtUpper.value[currentPtBinHe3]; - float nSigmaITSCutHe3PtLower = (currentPtBinHe3 == -1) ? cfgnSigmaCutITSHe3.value[0] : cfgnSigmaITSHe3PtLower.value[currentPtBinHe3]; - float nSigmaITSCutHe3PtUpper = (currentPtBinHe3 == -1) ? cfgnSigmaCutITSHe3.value[1] : cfgnSigmaITSHe3PtUpper.value[currentPtBinHe3]; - float nSigmaMainLowerPr = -999, nSigmaMainUpperPr = -999; - float nSigmaMainLowerHe3 = -999, nSigmaMainUpperHe3 = -999; - switch (cfgProtonPIDMode) { - case 0: - nSigmaMainLowerPr = nSigmaRMSCutPrPtLower; - nSigmaMainUpperPr = nSigmaRMSCutPrPtUpper; - break; - case 1: - nSigmaMainLowerPr = nSigmaTPCCutPrPtLower; - nSigmaMainUpperPr = nSigmaTPCCutPrPtUpper; - break; - case 2: - nSigmaMainLowerPr = nSigmaTOFCutPrPtLower; - nSigmaMainUpperPr = nSigmaTOFCutPrPtUpper; - break; - } - switch (cfgHe3PIDMode) { - case 0: - nSigmaMainLowerHe3 = nSigmaRMSCutHe3PtLower; - nSigmaMainUpperHe3 = nSigmaRMSCutHe3PtUpper; - break; - case 1: - nSigmaMainLowerHe3 = nSigmaTPCCutHe3PtLower; - nSigmaMainUpperHe3 = nSigmaTPCCutHe3PtUpper; - break; - case 2: - nSigmaMainLowerHe3 = nSigmaTOFCutHe3PtLower; - nSigmaMainUpperHe3 = nSigmaTOFCutHe3PtUpper; - break; - } - bool kIsPr = false, kIsHe3 = false; - // Identify Proton - if (pidProtonSel(track, nSigmaMainLowerPr, nSigmaMainUpperPr)) { - kIsPr = true; - if (cfgOpenPIDITSProton) { - if (track.itsNSigmaPr() < nSigmaITSCutPrPtLower || track.itsNSigmaPr() > nSigmaITSCutPrPtUpper) { - kIsPr = false; - } - } - } - // Identify He3 - if (pidHe3Sel(track, nSigmaMainLowerHe3, nSigmaMainUpperHe3)) { - kIsHe3 = true; - if (cfgOpenPIDITSHe3) { - if (track.itsNSigmaHe() < nSigmaITSCutHe3PtLower || track.itsNSigmaHe() > nSigmaITSCutHe3PtUpper) { - kIsHe3 = false; - } - } - } - // Cross track rejection - if (!cfgOpenAllowCrossTrack) { - if (kIsPr && kIsHe3) { - switch (crossTrackID(track)) { - case 0: - kIsPr = true; - kIsHe3 = false; - break; - case 1: - kIsPr = false; - kIsHe3 = true; - break; - } - } - } - // Filter He3 contaimination - if (cfgOpenHe3ITSPtCut && kIsHe3) { - if (!cfgQuietMode) { - histosQA.fill(HIST("QA/He3/hist_nSigmaITSPt_He3_unCuted"), track.pt(), track.itsNSigmaHe()); - } - if (track.itsNSigmaHe() < fNSigmaITSPt->Eval(track.pt())) { - kIsHe3 = false; - } - } - pidFlag = (kIsHe3 << 1) | kIsPr; - // Fill QA histograms - if (!cfgQuietMode) { - if (kIsPr) { - histosQA.fill(HIST("QA/Proton/hist_dEdxTPC_Pr"), track.sign() * track.tpcInnerParam(), track.tpcSignal()); - histosQA.fill(HIST("QA/Proton/hist_pt_Pr"), track.pt()); - histosQA.fill(HIST("QA/Proton/hist_eta_Pr"), track.eta()); - histosQA.fill(HIST("QA/Proton/hist_ITSNcls_Pr"), track.itsNCls()); - histosQA.fill(HIST("QA/Proton/hist_TPCNcls_Pr"), track.tpcNClsFound()); - histosQA.fill(HIST("QA/Proton/hist_ITSChi2NDF_Pr"), track.itsChi2NCl()); - histosQA.fill(HIST("QA/Proton/hist_TPCChi2NDF_Pr"), track.tpcChi2NCl()); - histosQA.fill(HIST("QA/Proton/hist_DCAxy_Pr"), track.dcaXY()); - histosQA.fill(HIST("QA/Proton/hist_DCAz_Pr"), track.dcaZ()); - histosQA.fill(HIST("QA/Proton/hist_nSigmaTPC_Pr"), track.tpcNSigmaPr()); - histosQA.fill(HIST("QA/Proton/hist_nSigmaTPCPt_Pr"), track.pt(), track.tpcNSigmaPr()); - histosQA.fill(HIST("QA/Proton/hist_nSigmaTOF_Pr"), track.tofNSigmaPr()); - histosQA.fill(HIST("QA/Proton/hist_nSigmaTOFPt_Pr"), track.pt(), track.tofNSigmaPr()); - histosQA.fill(HIST("QA/Proton/hist_nSigmaITS_Pr"), track.itsNSigmaPr()); - histosQA.fill(HIST("QA/Proton/hist_nSigmaITSPt_Pr"), track.pt(), track.itsNSigmaPr()); - histosQA.fill(HIST("QA/Proton/hist_nSigmaRMS_Pr"), std::hypot(track.tpcNSigmaPr(), track.tofNSigmaPr())); - histosQA.fill(HIST("QA/Proton/hist_nSigmaRMSPt_Pr"), track.pt(), std::hypot(track.tpcNSigmaPr(), track.tofNSigmaPr())); - if (cfgOpenPlotnSigmaTOFITSPt) { - histosQA.fill(HIST("QA/Proton/hist_nSigmaTOFITSPt_Pr"), track.tofNSigmaPr(), track.itsNSigmaPr(), track.pt()); - } - if (cfgOpenPlotnSigmaITSTPCPt) { - histosQA.fill(HIST("QA/Proton/hist_nSigmaITSTPCPt_Pr"), track.itsNSigmaPr(), track.tpcNSigmaPr(), track.pt()); - } - if (cfgOpenPlotnSigmaTOFTPCPt) { - histosQA.fill(HIST("QA/Proton/hist_nSigmaTOFTPCPt_Pr"), track.tofNSigmaPr(), track.tpcNSigmaPr(), track.pt()); - } - } - if (kIsHe3) { - histosQA.fill(HIST("QA/He3/hist_dEdxTPC_He3"), track.sign() * track.tpcInnerParam(), track.tpcSignal()); - histosQA.fill(HIST("QA/He3/hist_pt_He3"), track.pt()); - histosQA.fill(HIST("QA/He3/hist_eta_He3"), track.eta()); - histosQA.fill(HIST("QA/He3/hist_ITSNcls_He3"), track.itsNCls()); - histosQA.fill(HIST("QA/He3/hist_TPCNcls_He3"), track.tpcNClsFound()); - histosQA.fill(HIST("QA/He3/hist_ITSChi2NDF_He3"), track.itsChi2NCl()); - histosQA.fill(HIST("QA/He3/hist_TPCChi2NDF_He3"), track.tpcChi2NCl()); - histosQA.fill(HIST("QA/He3/hist_DCAxy_He3"), track.dcaXY()); - histosQA.fill(HIST("QA/He3/hist_DCAz_He3"), track.dcaZ()); - histosQA.fill(HIST("QA/He3/hist_nSigmaTPC_He3"), track.tpcNSigmaHe()); - histosQA.fill(HIST("QA/He3/hist_nSigmaTPCPt_He3"), track.pt(), track.tpcNSigmaHe()); - histosQA.fill(HIST("QA/He3/hist_nSigmaTOF_He3"), track.tofNSigmaHe()); - histosQA.fill(HIST("QA/He3/hist_nSigmaTOFPt_He3"), track.pt(), track.tofNSigmaHe()); - histosQA.fill(HIST("QA/He3/hist_nSigmaITS_He3"), track.itsNSigmaHe()); - histosQA.fill(HIST("QA/He3/hist_nSigmaITSPt_He3"), track.pt(), track.itsNSigmaHe()); - histosQA.fill(HIST("QA/He3/hist_nSigmaRMS_He3"), std::hypot(track.tpcNSigmaHe(), track.tofNSigmaHe())); - histosQA.fill(HIST("QA/He3/hist_nSigmaRMSPt_He3"), track.pt(), std::hypot(track.tpcNSigmaHe(), track.tofNSigmaHe())); - if (cfgOpenPlotnSigmaTOFITSPt) { - histosQA.fill(HIST("QA/He3/hist_nSigmaTOFITSPt_He3"), track.tofNSigmaHe(), track.itsNSigmaHe(), track.pt()); - } - if (cfgOpenPlotnSigmaITSTPCPt) { - histosQA.fill(HIST("QA/He3/hist_nSigmaITSTPCPt_He3"), track.itsNSigmaHe(), track.tpcNSigmaHe(), track.pt()); - } - if (cfgOpenPlotnSigmaTOFTPCPt) { - histosQA.fill(HIST("QA/He3/hist_nSigmaTOFTPCPt_He3"), track.tofNSigmaHe(), track.tpcNSigmaHe(), track.pt()); - } - } - } + case ese_parameters::kAlpha: { + return itsResponse.nSigmaITS(track); } - pidEsePHe3Table(pidFlag); + default: + return -99.f; } } -}; - -struct FlowEsePHe3 { - HistogramRegistry histos{"histosmain", {}, OutputObjHandlingPolicy::AnalysisObject}; - - Configurable> cfgnMods{"cfgnMods", {2}, "Modulation of interest"}; - 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"}; - Configurable cfgnTotalSystem{"cfgnTotalSystem", 7, "total qvector number"}; - - Configurable cfgVtzCut{"cfgVtzCut", 10.0f, "Accepted z-vertex range"}; - Configurable cfgCentMin{"cfgCentMin", 0.0f, "Centrality min"}; - Configurable cfgCentMax{"cfgCentMax", 100.0f, "Centrality max"}; - - Configurable cfgCutOccupancyLow{"cfgCutOccupancyLow", 0, "Low boundary cut on TPC occupancy"}; - Configurable cfgCutOccupancyHigh{"cfgCutOccupancyHigh", 3000, "High boundary cut on TPC occupancy"}; - Configurable cfgUseAdditionalEventCut{"cfgUseAdditionalEventCut", true, "Use additional event cut beyond sel8"}; - Configurable cfgOpenEvSelkIsGoodZvtxFT0vsPV{"cfgOpenEvSelkIsGoodZvtxFT0vsPV", true, "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"}; - Configurable cfgOpenEvSelkNoSameBunchPileup{"cfgOpenEvSelkNoSameBunchPileup", true, "rejects collisions which are associated with the same found-by-T0 bunch crossing"}; - Configurable cfgOpenEvSelkNoCollInTimeRangeStandard{"cfgOpenEvSelkNoCollInTimeRangeStandard", true, "no collisions in specified time range"}; - Configurable cfgOpenEvSelkIsGoodITSLayersAll{"cfgOpenEvSelkIsGoodITSLayersAll", true, "cut time intervals with dead ITS staves"}; - Configurable cfgOpenEvSelkNoCollInRofStandard{"cfgOpenEvSelkNoCollInRofStandard", true, "no other collisions in this Readout Frame with per-collision multiplicity above threshold"}; - Configurable cfgOpenEvSelkNoHighMultCollInPrevRof{"cfgOpenEvSelkNoHighMultCollInPrevRof", true, "veto an event if FT0C amplitude in previous ITS ROF is above threshold"}; - Configurable cfgOpenEvSelOccupancy{"cfgOpenEvSelOccupancy", true, "Occupancy cut"}; - Configurable cfgOpenEvSelMultCorrelationPVTracks{"cfgOpenEvSelMultCorrelationPVTracks", true, "Multiplicity correlation cut for PVtracks vs centrality(FT0C)"}; - Configurable cfgOpenEvSelMultCorrelationGlobalTracks{"cfgOpenEvSelMultCorrelationGlobalTracks", false, "Multiplicity correlation cut for Globaltracks vs centrality(FT0C)"}; - Configurable cfgOpenEvSelV0AT0ACut{"cfgOpenEvSelV0AT0ACut", true, "V0A T0A 5 sigma cut"}; - Configurable cfgOpenFullEventQA{"cfgOpenFullEventQA", true, "Open full QA plots for event QA"}; - Configurable cfgOpenv2q{"cfgOpenv2q", true, "Open v2(EP)and q calculation for Proton and He3"}; - Configurable cfgOpenESE{"cfgOpenESE", true, "Open ESE process"}; - Configurable cfgOpenESEChargeSeperation{"cfgOpenESEChargeSeperation", true, "Open ESE for postive and negative charge repectivily"}; - Configurable cfgOpenESEProton{"cfgOpenESEProton", true, "Open ESE Proton process"}; - Configurable cfgOpenESEHe3{"cfgOpenESEHe3", true, "Open ESE He3 process"}; - - ConfigurableAxis cfgaxisQvecF{"cfgaxisQvecF", {300, -1, 1}, ""}; - ConfigurableAxis cfgaxisCent{"cfgaxisCent", {90, 0, 90}, ""}; - ConfigurableAxis cfgaxispt{"cfgaxispt", {100, 0, 10}, ""}; - ConfigurableAxis cfgaxisCentForQA{"cfgaxisCentForQA", {100, 0, 100}, "centrality for event QA"}; - ConfigurableAxis cfgaxisNch{"cfgaxisNch", {4000, 0, 4000}, "N_{ch}"}; - ConfigurableAxis cfgaxisT0C{"cfgaxisT0C", {70, 0, 70000}, "N_{ch} (T0C)"}; - ConfigurableAxis cfgaxisT0A{"cfgaxisT0A", {200, 0, 200000}, "N_{ch} (T0A)"}; - ConfigurableAxis cfgaxisNchPV{"cfgaxisNchPV", {4000, 0, 4000}, "N_{ch} (PV)"}; - ConfigurableAxis cfgaxisq2{"cfgaxisq2", {120, 0, 12}, "Binning for P_{t} PID"}; - - EventPlaneHelper helperEP; - SliceCache cache; - - int detId; - int refAId; - int refBId; - // Additional Event selection cuts - Copy from flowGenericFramework.cxx - TF1* fMultPVCutLow = nullptr; - TF1* fMultPVCutHigh = nullptr; - TF1* fMultCutLow = nullptr; - TF1* fMultCutHigh = nullptr; - TF1* fT0AV0AMean = nullptr; - TF1* fT0AV0ASigma = nullptr; - - Filter collisionFilter = (nabs(aod::collision::posZ) < cfgVtzCut) && (aod::cent::centFT0C > cfgCentMin) && (aod::cent::centFT0C < cfgCentMax); - Filter properPIDfilter = aod::flow_ese_p_he3::nPidFlag >= (int8_t)0; // Only POI - - Partition>> protonTrackSet = ((aod::flow_ese_p_he3::nPidFlag == pid_flags::kProton) || (aod::flow_ese_p_he3::nPidFlag == pid_flags::kProtonHe3)); - Partition>> he3TrackSet = ((aod::flow_ese_p_he3::nPidFlag == pid_flags::kHe3) || (aod::flow_ese_p_he3::nPidFlag == pid_flags::kProtonHe3)); template int getDetId(const T& name) @@ -637,160 +446,409 @@ struct FlowEsePHe3 { } } + template + uint8_t getPOI(const T& POI) + { + if (POI.value == "kProton") { + return ese_parameters::kProton; + } else if (POI.value == "kDeuteron") { + return ese_parameters::kDeuteron; + } else if (POI.value == "kTriton") { + return ese_parameters::kTriton; + } else if (POI.value == "kHe3") { + return ese_parameters::kHe3; + } else if (POI.value == "kAlpha") { + return ese_parameters::kAlpha; + } else { + LOGF(warning, "Unknown POI: %s", POI.value.c_str()); + return 0; + } + } + + float calculateq2(const float qx, const float qy, const int multi) + { + if (multi <= 0) { + return 0.f; + } else { + return std::hypot(qx, qy) / std::sqrt(static_cast(multi)); + } + } + template - bool selEvent(const CollType& collision, const int multTrk, const float centrality) + bool eventSelBasic(const CollType& collision, const int64_t multTrk, const float centrality, bool fillQA) { - histos.fill(HIST("QA/histEventCountDetail"), 0.5); - if (cfgOpenEvSelkIsGoodZvtxFT0vsPV && !collision.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV)) { + if (!collision.sel8()) + return false; + if (fillQA) { + histsESE.fill(HIST("EventQA/histEventCount"), 0.5); + } + if (cfgOpenEvSel->get(0u) && !collision.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV)) { return false; } - if (cfgOpenEvSelkIsGoodZvtxFT0vsPV) { - histos.fill(HIST("QA/histEventCountDetail"), 1.5); + if (fillQA && cfgOpenEvSel->get(0u)) { + histsESE.fill(HIST("EventQA/histEventCount"), 1.5); } - if (cfgOpenEvSelkNoSameBunchPileup && !collision.selection_bit(aod::evsel::kNoSameBunchPileup)) { + if (cfgOpenEvSel->get(1u) && !collision.selection_bit(aod::evsel::kNoSameBunchPileup)) { return false; } - if (cfgOpenEvSelkNoSameBunchPileup) { - histos.fill(HIST("QA/histEventCountDetail"), 2.5); + if (fillQA && cfgOpenEvSel->get(1u)) { + histsESE.fill(HIST("EventQA/histEventCount"), 2.5); } - if (cfgOpenEvSelkNoCollInTimeRangeStandard && !collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { + if (cfgOpenEvSel->get(2u) && !collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { return false; } - if (cfgOpenEvSelkNoCollInTimeRangeStandard) { - histos.fill(HIST("QA/histEventCountDetail"), 3.5); + if (fillQA && cfgOpenEvSel->get(2u)) { + histsESE.fill(HIST("EventQA/histEventCount"), 3.5); } - if (cfgOpenEvSelkIsGoodITSLayersAll && !collision.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { + if (cfgOpenEvSel->get(3u) && !collision.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { return false; } - if (cfgOpenEvSelkIsGoodITSLayersAll) { - histos.fill(HIST("QA/histEventCountDetail"), 4.5); + if (fillQA && cfgOpenEvSel->get(3u)) { + histsESE.fill(HIST("EventQA/histEventCount"), 4.5); } - if (cfgOpenEvSelkNoCollInRofStandard && !collision.selection_bit(o2::aod::evsel::kNoCollInRofStandard)) { + if (cfgOpenEvSel->get(4u) && !collision.selection_bit(o2::aod::evsel::kNoCollInRofStandard)) { return false; } - if (cfgOpenEvSelkNoCollInRofStandard) { - histos.fill(HIST("QA/histEventCountDetail"), 5.5); + if (fillQA && cfgOpenEvSel->get(4u)) { + histsESE.fill(HIST("EventQA/histEventCount"), 5.5); } - if (cfgOpenEvSelkNoHighMultCollInPrevRof && !collision.selection_bit(o2::aod::evsel::kNoHighMultCollInPrevRof)) { + if (cfgOpenEvSel->get(5u) && !collision.selection_bit(o2::aod::evsel::kNoHighMultCollInPrevRof)) { return false; } - if (cfgOpenEvSelkNoHighMultCollInPrevRof) { - histos.fill(HIST("QA/histEventCountDetail"), 6.5); + if (fillQA && cfgOpenEvSel->get(5u)) { + histsESE.fill(HIST("EventQA/histEventCount"), 6.5); } auto multNTracksPV = collision.multNTracksPV(); auto occupancy = collision.trackOccupancyInTimeRange(); - if (cfgOpenEvSelOccupancy && (occupancy < cfgCutOccupancyLow || occupancy > cfgCutOccupancyHigh)) { + if (cfgOpenEvSel->get(6u) && (occupancy < cfgCutOccupancyLow || occupancy > cfgCutOccupancyHigh)) { return false; } - if (cfgOpenEvSelOccupancy) { - histos.fill(HIST("QA/histEventCountDetail"), 7.5); + if (fillQA && cfgOpenEvSel->get(6u)) { + histsESE.fill(HIST("EventQA/histEventCount"), 7.5); } - if (cfgOpenEvSelMultCorrelationPVTracks) { + if (cfgOpenEvSel->get(7u)) { if (multNTracksPV < fMultPVCutLow->Eval(centrality)) return false; if (multNTracksPV > fMultPVCutHigh->Eval(centrality)) return false; } - if (cfgOpenEvSelMultCorrelationPVTracks) { - histos.fill(HIST("QA/histEventCountDetail"), 8.5); + if (fillQA && cfgOpenEvSel->get(7u)) { + histsESE.fill(HIST("EventQA/histEventCount"), 8.5); } - if (cfgOpenEvSelMultCorrelationGlobalTracks) { + if (cfgOpenEvSel->get(8u)) { if (multTrk < fMultCutLow->Eval(centrality)) return false; if (multTrk > fMultCutHigh->Eval(centrality)) return false; } - if (cfgOpenEvSelMultCorrelationGlobalTracks) { - histos.fill(HIST("QA/histEventCountDetail"), 9.5); + if (fillQA && cfgOpenEvSel->get(8u)) { + histsESE.fill(HIST("EventQA/histEventCount"), 9.5); } - if (cfgOpenEvSelV0AT0ACut && (std::fabs(collision.multFV0A() - fT0AV0AMean->Eval(collision.multFT0A())) > event_selection::kFT0AV0ASigma * fT0AV0ASigma->Eval(collision.multFT0A()))) { + if (cfgOpenEvSel->get(9u) && (std::fabs(collision.multFV0A() - fT0AV0AMean->Eval(collision.multFT0A())) > ese_parameters::kFT0AV0ASigma * fT0AV0ASigma->Eval(collision.multFT0A()))) { return false; } - if (cfgOpenEvSelV0AT0ACut) { - histos.fill(HIST("QA/histEventCountDetail"), 10.5); + if (fillQA && cfgOpenEvSel->get(9u)) { + histsESE.fill(HIST("EventQA/histEventCount"), 10.5); + } + if (fillQA) { + histsESE.fill(HIST("EventQA/histVtz"), collision.posZ()); + histsESE.fill(HIST("EventQA/histCent"), centrality); } return true; } + template + bool trackSelBasic(const TrackType track) + { + if ((track.pt() < cfgMinPtPID) || (track.pt() > cfgMaxPtPID)) + return false; + if (std::abs(track.eta()) > cfgMaxEtaPID) + return false; + if (cfgOpenTrackSel->get(0u)) { + if (!track.passedITSNCls()) + return false; + } else { + if (track.itsNCls() < cfgMinITSCls || track.itsNCls() > cfgMaxITSCls) + return false; + } + if (cfgOpenTrackSel->get(1u)) { + if (!track.passedITSChi2NDF()) + return false; + } else { + if (track.itsChi2NCl() < cfgMinChi2NClITS || track.itsChi2NCl() > cfgMaxChi2NClITS) + return false; + } + if (cfgOpenTrackSel->get(2u)) { + if (!track.passedITSHits()) + return false; + } + if (cfgOpenTrackSel->get(3u)) { + if (!track.passedTPCChi2NDF()) + return false; + } else { + if (track.tpcChi2NCl() < cfgMinTPCChi2NCl || track.tpcChi2NCl() > cfgMaxTPCChi2NCl) + return false; + } + if (cfgOpenTrackSel->get(4u)) { + if (!track.passedTPCCrossedRowsOverNCls()) + return false; + } + if (cfgOpenTrackSel->get(5u)) { + if (!track.passedDCAxy()) + return false; + } else { + if (std::abs(track.dcaXY()) > cfgMaxDCAxy) + return false; + } + if (cfgOpenTrackSel->get(6u)) { + if (!track.passedDCAz()) + return false; + } else { + if (std::abs(track.dcaZ()) > cfgMaxDCAz) + return false; + } + if (track.tpcNClsFound() < cfgMinTPCCls || track.tpcNClsFound() > cfgMaxTPCCls) + return false; + return true; + } + template - void fillHistosQvec(const CollType& collision, int nmode) + void fillEventQAhistBe(const CollType collision, const int multTrk, const float centrality) { - int detInd = detId * 4 + cfgnTotalSystem * 4 * (nmode - 2); - int refAInd = refAId * 4 + cfgnTotalSystem * 4 * (nmode - 2); - int refBInd = refBId * 4 + cfgnTotalSystem * 4 * (nmode - 2); - if (nmode == fourier_mode::kMode2) { - if (collision.qvecAmp()[detId] > 1e-8) { - histos.fill(HIST("QA/histQvec_CorrL0_V2"), collision.qvecRe()[detInd], collision.qvecIm()[detInd], collision.centFT0C()); - histos.fill(HIST("QA/histQvec_CorrL1_V2"), collision.qvecRe()[detInd + 1], collision.qvecIm()[detInd + 1], collision.centFT0C()); - histos.fill(HIST("QA/histQvec_CorrL2_V2"), collision.qvecRe()[detInd + 2], collision.qvecIm()[detInd + 2], collision.centFT0C()); - histos.fill(HIST("QA/histQvec_CorrL3_V2"), collision.qvecRe()[detInd + 3], collision.qvecIm()[detInd + 3], collision.centFT0C()); - histos.fill(HIST("QA/histEvtPl_CorrL0_V2"), helperEP.GetEventPlane(collision.qvecRe()[detInd], collision.qvecIm()[detInd], nmode), collision.centFT0C()); - histos.fill(HIST("QA/histEvtPl_CorrL1_V2"), helperEP.GetEventPlane(collision.qvecRe()[detInd + 1], collision.qvecIm()[detInd + 1], nmode), collision.centFT0C()); - histos.fill(HIST("QA/histEvtPl_CorrL2_V2"), helperEP.GetEventPlane(collision.qvecRe()[detInd + 2], collision.qvecIm()[detInd + 2], nmode), collision.centFT0C()); - histos.fill(HIST("QA/histEvtPl_CorrL3_V2"), helperEP.GetEventPlane(collision.qvecRe()[detInd + 3], collision.qvecIm()[detInd + 3], nmode), collision.centFT0C()); - } - if (collision.qvecAmp()[detId] > 1e-8 && collision.qvecAmp()[refAId] > 1e-8 && collision.qvecAmp()[refBId] > 1e-8) { - histos.fill(HIST("QA/histQvecRes_SigRefAV2"), collision.centFT0C(), helperEP.GetResolution(helperEP.GetEventPlane(collision.qvecRe()[detInd + 3], collision.qvecIm()[detInd + 3], nmode), helperEP.GetEventPlane(collision.qvecRe()[refAInd + 3], collision.qvecIm()[refAInd + 3], nmode), nmode)); - histos.fill(HIST("QA/histQvecRes_SigRefBV2"), collision.centFT0C(), helperEP.GetResolution(helperEP.GetEventPlane(collision.qvecRe()[detInd + 3], collision.qvecIm()[detInd + 3], nmode), helperEP.GetEventPlane(collision.qvecRe()[refBInd + 3], collision.qvecIm()[refBInd + 3], nmode), nmode)); - histos.fill(HIST("QA/histQvecRes_RefARefBV2"), collision.centFT0C(), helperEP.GetResolution(helperEP.GetEventPlane(collision.qvecRe()[refAInd + 3], collision.qvecIm()[refAInd + 3], nmode), helperEP.GetEventPlane(collision.qvecRe()[refBInd + 3], collision.qvecIm()[refBInd + 3], nmode), nmode)); - } + histsESE.fill(HIST("EventQA/hist_globalTracks_centT0C_before"), centrality, multTrk); + histsESE.fill(HIST("EventQA/hist_PVTracks_centT0C_before"), centrality, collision.multNTracksPV()); + histsESE.fill(HIST("EventQA/hist_globalTracks_PVTracks_before"), collision.multNTracksPV(), multTrk); + histsESE.fill(HIST("EventQA/hist_globalTracks_multT0A_before"), collision.multFT0A(), multTrk); + histsESE.fill(HIST("EventQA/hist_globalTracks_multV0A_before"), collision.multFV0A(), multTrk); + histsESE.fill(HIST("EventQA/hist_multV0A_multT0A_before"), collision.multFT0A(), collision.multFV0A()); + histsESE.fill(HIST("EventQA/hist_multT0C_centT0C_before"), centrality, collision.multFT0C()); + } + + template + void fillEventQAhistAf(const CollType collision, const int multTrk, const float centrality) + { + histsESE.fill(HIST("EventQA/hist_globalTracks_centT0C_after"), centrality, multTrk); + histsESE.fill(HIST("EventQA/hist_PVTracks_centT0C_after"), centrality, collision.multNTracksPV()); + histsESE.fill(HIST("EventQA/hist_globalTracks_PVTracks_after"), collision.multNTracksPV(), multTrk); + histsESE.fill(HIST("EventQA/hist_globalTracks_multT0A_after"), collision.multFT0A(), multTrk); + histsESE.fill(HIST("EventQA/hist_globalTracks_multV0A_after"), collision.multFV0A(), multTrk); + histsESE.fill(HIST("EventQA/hist_multV0A_multT0A_after"), collision.multFT0A(), collision.multFV0A()); + histsESE.fill(HIST("EventQA/hist_multT0C_centT0C_after"), centrality, collision.multFT0C()); + } + + template + void fillTrackQAhist(const TrackType track) + { + bool heliumPID = track.pidForTracking() == o2::track::PID::Helium3 || track.pidForTracking() == o2::track::PID::Alpha; + float correctedTpcInnerParam = (heliumPID && cfgCompensatePIDinTracking) ? track.tpcInnerParam() / 2 : track.tpcInnerParam(); + histsESE.fill(HIST("TrackQA/hist_dEdxTPC_All"), track.sign() * correctedTpcInnerParam, track.tpcSignal()); + histsESE.fill(HIST("TrackQA/hist_pt_All"), track.pt()); + histsESE.fill(HIST("TrackQA/hist_eta_All"), track.eta()); + histsESE.fill(HIST("TrackQA/hist_phi_All"), track.phi()); + histsESE.fill(HIST("TrackQA/hist_DCAxy_All"), track.dcaXY()); + histsESE.fill(HIST("TrackQA/hist_DCAz_All"), track.dcaZ()); + histsESE.fill(HIST("TrackQA/hist_ITSNcls_All"), track.itsNCls()); + histsESE.fill(HIST("TrackQA/hist_TPCNcls_All"), track.tpcNClsFound()); + histsESE.fill(HIST("TrackQA/hist_ITSChi2NDF_All"), track.itsChi2NCl()); + histsESE.fill(HIST("TrackQA/hist_TPCChi2NDF_All"), track.tpcChi2NCl()); + } + + template + void fillHistosQvec(const CollType& collision) + { + int detInd = detId * 4 + cfgnTotalSystem * 4 * (2 - 2); + int refAInd = refAId * 4 + cfgnTotalSystem * 4 * (2 - 2); + int refBInd = refBId * 4 + cfgnTotalSystem * 4 * (2 - 2); + if (collision.qvecAmp()[detId] > ese_parameters::Amplitudelow) { + histsESE.fill(HIST("PlanQA/histQvec_CorrL0_V2"), collision.qvecRe()[detInd], collision.qvecIm()[detInd], collision.centFT0C()); + histsESE.fill(HIST("PlanQA/histQvec_CorrL1_V2"), collision.qvecRe()[detInd + 1], collision.qvecIm()[detInd + 1], collision.centFT0C()); + histsESE.fill(HIST("PlanQA/histQvec_CorrL2_V2"), collision.qvecRe()[detInd + 2], collision.qvecIm()[detInd + 2], collision.centFT0C()); + histsESE.fill(HIST("PlanQA/histQvec_CorrL3_V2"), collision.qvecRe()[detInd + 3], collision.qvecIm()[detInd + 3], collision.centFT0C()); + histsESE.fill(HIST("PlanQA/histEvtPl_CorrL0_V2"), helperEP.GetEventPlane(collision.qvecRe()[detInd], collision.qvecIm()[detInd], 2), collision.centFT0C()); + histsESE.fill(HIST("PlanQA/histEvtPl_CorrL1_V2"), helperEP.GetEventPlane(collision.qvecRe()[detInd + 1], collision.qvecIm()[detInd + 1], 2), collision.centFT0C()); + histsESE.fill(HIST("PlanQA/histEvtPl_CorrL2_V2"), helperEP.GetEventPlane(collision.qvecRe()[detInd + 2], collision.qvecIm()[detInd + 2], 2), collision.centFT0C()); + histsESE.fill(HIST("PlanQA/histEvtPl_CorrL3_V2"), helperEP.GetEventPlane(collision.qvecRe()[detInd + 3], collision.qvecIm()[detInd + 3], 2), collision.centFT0C()); + } + if (collision.qvecAmp()[detId] > ese_parameters::Amplitudelow && collision.qvecAmp()[refAId] > ese_parameters::Amplitudelow && collision.qvecAmp()[refBId] > ese_parameters::Amplitudelow) { + histsESE.fill(HIST("PlanQA/histQvecRes_SigRefAV2"), collision.centFT0C(), helperEP.GetResolution(helperEP.GetEventPlane(collision.qvecRe()[detInd + 3], collision.qvecIm()[detInd + 3], 2), helperEP.GetEventPlane(collision.qvecRe()[refAInd + 3], collision.qvecIm()[refAInd + 3], 2), 2)); + histsESE.fill(HIST("PlanQA/histQvecRes_SigRefBV2"), collision.centFT0C(), helperEP.GetResolution(helperEP.GetEventPlane(collision.qvecRe()[detInd + 3], collision.qvecIm()[detInd + 3], 2), helperEP.GetEventPlane(collision.qvecRe()[refBInd + 3], collision.qvecIm()[refBInd + 3], 2), 2)); + histsESE.fill(HIST("PlanQA/histQvecRes_RefARefBV2"), collision.centFT0C(), helperEP.GetResolution(helperEP.GetEventPlane(collision.qvecRe()[refAInd + 3], collision.qvecIm()[refAInd + 3], 2), helperEP.GetEventPlane(collision.qvecRe()[refBInd + 3], collision.qvecIm()[refBInd + 3], 2), 2)); } } template - float calculateq2(const TrackType tracks, float psi2, float cent, int pidmode) // pidmode 1 for proton , 2 for he3 + bool pidSel(const TrackType& track, uint8_t POI) { - int multi = tracks.size(); - if (multi > 0) { - float q2x = 0, q2y = 0; - for (const auto& track : tracks) { - q2x += std::cos(2 * track.phi()); - q2y += std::sin(2 * track.phi()); - if (pidmode == pid_flags::kProton) { - if (track.sign() > 0) { - histos.fill(HIST("V2/histCosV2EP_Pr_Pos"), track.pt(), cent, std::cos(2 * (track.phi() - psi2))); - } else { - histos.fill(HIST("V2/histCosV2EP_Pr_Neg"), track.pt(), cent, std::cos(2 * (track.phi() - psi2))); + if (track.pt() < cfgPtPreselection->get(POI, 0u) || track.pt() > cfgPtPreselection->get(POI, 1u)) { + return false; + } + float nSigmaTPC = 0.f; + float nSigmaITS = 0.f; + switch (POI) { + case ese_parameters::kProton: + if (cfgProtonPIDMode == ese_parameters::kRMSMode) { // RMS mode + float nSigmaUse = (track.pt() > cfgPtMaxforTPCOnlyPIDPrton) ? std::hypot(track.tpcNSigmaPr(), track.tofNSigmaPr()) : track.tpcNSigmaPr(); + if (nSigmaUse < cfgnSigmaCutRMSProton.value[0] || nSigmaUse > cfgnSigmaCutRMSProton.value[1]) { + return false; } - } - if (pidmode == pid_flags::kHe3) { - if (track.sign() > 0) { - histos.fill(HIST("V2/histCosV2EP_He3_Pos"), track.pt(), cent, std::cos(2 * (track.phi() - psi2))); - } else { - histos.fill(HIST("V2/histCosV2EP_He3_Neg"), track.pt(), cent, std::cos(2 * (track.phi() - psi2))); + } else if (cfgProtonPIDMode == ese_parameters::kTPCMode) { // TPC mode + nSigmaTPC = (cfgUseSelfnSigmaTPCProton ? getNSigmaTPCSelfBB(track, ese_parameters::kProton) : track.tpcNSigmaPr()); + } else if (cfgProtonPIDMode == ese_parameters::kTOFOnlyMode) { // TOF only mode + if (!track.hasTOF()) + return false; + if (track.tofNSigmaPr() < cfgnSigmaCutTOFProton.value[0] || track.tofNSigmaPr() > cfgnSigmaCutTOFProton.value[1]) { + return false; } } - } - return std::hypot(q2x, q2y) / std::sqrt(multi); - } else { - return 0; + nSigmaITS = itsResponse.nSigmaITS(track); + break; + + case ese_parameters::kDeuteron: + nSigmaTPC = getNSigmaTPCSelfBB(track, ese_parameters::kDeuteron); + nSigmaITS = itsResponse.nSigmaITS(track); + break; + + case ese_parameters::kTriton: + nSigmaTPC = getNSigmaTPCSelfBB(track, ese_parameters::kTriton); + nSigmaITS = itsResponse.nSigmaITS(track); + break; + + case ese_parameters::kHe3: + nSigmaTPC = getNSigmaTPCSelfBB(track, ese_parameters::kHe3); + nSigmaITS = itsResponse.nSigmaITS(track); + break; + + case ese_parameters::kAlpha: + nSigmaTPC = getNSigmaTPCSelfBB(track, ese_parameters::kAlpha); + nSigmaITS = itsResponse.nSigmaITS(track); + break; + + default: + LOGF(error, "Unknown POI: %d", POI); + return false; + } + if (nSigmaTPC < cfgnSigmaTPC->get(POI, 0u) || nSigmaTPC > cfgnSigmaTPC->get(POI, 1u)) { + return false; + } + if (nSigmaITS < cfgnSigmaITS->get(POI, 0u) || nSigmaITS > cfgnSigmaITS->get(POI, 1u)) { + return false; } + return true; } - template - void processESE(const TrackType tracks, float psi2, float q2, float cent, int pidmode, bool spcharge) // pidmode 1 for proton , 2 for he3 + template + void fillESECandidates(Tcoll const& collision, Ttrks const& tracks, float& q2Tarx, float& q2Tary, int& multiTar, float& q2Refx, float& q2Refy, int& multiRef) { - for (const auto& track : tracks) { - if (pidmode == pid_flags::kProton) { - if (spcharge) { + float psi2 = helperEP.GetEventPlane(collision.qvecRe()[detInd + 3], collision.qvecIm()[detInd + 3], 2); + float q2Tarinit{0.f}; + float q2Refinit{0.f}; + for (const auto& track : tracks) { // loop on tracks + if (!trackSelBasic(track)) { + continue; + } + // we fill the track info QA in the main process + fillTrackQAhist(track); + bool kIsTar{false}; + bool kIsRef{false}; + kIsTar = pidSel(track, poiTar); + kIsRef = pidSel(track, poiRef); + if (!cfgOpenAllowCrossTrack && kIsTar && kIsRef) { + if (getNSigmaTPCSelfBB(track, poiTar) < getNSigmaTPCSelfBB(track, poiRef)) { + kIsRef = false; + } else { + kIsTar = false; + } + } + if (kIsTar) { + multiTar++; + q2Tarx += std::cos(2 * track.phi()); + q2Tary += std::sin(2 * track.phi()); + bool heliumPID = track.pidForTracking() == o2::track::PID::Helium3 || track.pidForTracking() == o2::track::PID::Alpha; + float correctedTpcInnerParam = (heliumPID && cfgCompensatePIDinTracking) ? track.tpcInnerParam() / 2 : track.tpcInnerParam(); + float nSigmaTPCTar{(poiTar == ese_parameters::kProton && !cfgUseSelfnSigmaTPCProton) ? track.tpcNSigmaPr() : getNSigmaTPCSelfBB(track, poiTar)}; + float nSigmaTOFTar{getNSigmaTOF(track, poiTar)}; + float nSigmaITSTar{getNSigmaITS(track, poiTar)}; + if (cfgOpenPIDQA) { + ese_parameters::hPIDQATar1D[0]->Fill(track.pt()); + ese_parameters::hPIDQATar1D[1]->Fill(track.eta()); + ese_parameters::hPIDQATar1D[2]->Fill(track.phi()); + ese_parameters::hPIDQATar1D[3]->Fill(track.itsNCls()); + ese_parameters::hPIDQATar1D[4]->Fill(track.tpcNClsFound()); + ese_parameters::hPIDQATar1D[5]->Fill(track.itsChi2NCl()); + ese_parameters::hPIDQATar1D[6]->Fill(track.tpcChi2NCl()); + ese_parameters::hPIDQATar1D[7]->Fill(track.dcaXY()); + ese_parameters::hPIDQATar1D[8]->Fill(track.dcaZ()); + ese_parameters::hPIDQATar1D[9]->Fill(nSigmaTPCTar); + ese_parameters::hPIDQATar1D[10]->Fill(nSigmaTOFTar); + ese_parameters::hPIDQATar1D[11]->Fill(nSigmaITSTar); + ese_parameters::hPIDQATar2D[0]->Fill(track.sign() * correctedTpcInnerParam, track.tpcSignal()); + ese_parameters::hPIDQATar2D[1]->Fill(nSigmaTPCTar, track.pt()); + ese_parameters::hPIDQATar2D[2]->Fill(nSigmaTOFTar, track.pt()); + ese_parameters::hPIDQATar2D[3]->Fill(nSigmaITSTar, track.pt()); + if (cfgOpen3DPIDPlots->get(0u)) { + ese_parameters::hPIDQATar3D[0]->Fill(nSigmaTOFTar, nSigmaITSTar, track.pt()); + } + if (cfgOpen3DPIDPlots->get(1u)) { + ese_parameters::hPIDQATar3D[1]->Fill(nSigmaITSTar, nSigmaTPCTar, track.pt()); + } + if (cfgOpen3DPIDPlots->get(2u)) { + ese_parameters::hPIDQATar3D[2]->Fill(nSigmaTOFTar, nSigmaTPCTar, track.pt()); + } + } + if (cfgOpenv2) { if (track.sign() > 0) { - histos.fill(HIST("ESE/hist_v2PosPr_Cent_Pt_q2He3"), track.pt(), cent, q2, std::cos(2 * (track.phi() - psi2))); + ese_parameters::hv2Tar[0]->Fill(track.pt(), collision.centFT0C(), std::cos(2 * (track.phi() - psi2))); } else { - histos.fill(HIST("ESE/hist_v2NegPr_Cent_Pt_q2He3"), track.pt(), cent, q2, std::cos(2 * (track.phi() - psi2))); + ese_parameters::hv2Tar[1]->Fill(track.pt(), collision.centFT0C(), std::cos(2 * (track.phi() - psi2))); } - } else { - histos.fill(HIST("ESE/hist_v2Pr_Cent_Pt_q2He3"), track.pt(), cent, q2, std::cos(2 * (track.phi() - psi2))); } + ese_parameters::eseCandidates.emplace_back(ESECandidate{ + collision.posZ(), collision.centFT0C(), psi2, q2Tarinit, q2Refinit, static_cast(track.sign()), correctedTpcInnerParam, track.tpcSignal(), track.pt(), track.eta(), track.phi(), + track.dcaXY(), track.dcaZ(), static_cast(track.tpcNClsFound()), track.itsNCls(), track.tpcChi2NCl(), track.itsChi2NCl(), + nSigmaTPCTar, nSigmaTOFTar, nSigmaITSTar, track.itsClusterSizes()}); } - if (pidmode == pid_flags::kHe3) { - if (spcharge) { + if (kIsRef) { + multiRef++; + q2Refx += std::cos(2 * track.phi()); + q2Refy += std::sin(2 * track.phi()); + bool heliumPID = track.pidForTracking() == o2::track::PID::Helium3 || track.pidForTracking() == o2::track::PID::Alpha; + float correctedTpcInnerParam = (heliumPID && cfgCompensatePIDinTracking) ? track.tpcInnerParam() / 2 : track.tpcInnerParam(); + float nSigmaTPCRef{(poiRef == ese_parameters::kProton && !cfgUseSelfnSigmaTPCProton) ? track.tpcNSigmaPr() : getNSigmaTPCSelfBB(track, poiRef)}; + float nSigmaTOFRef{getNSigmaTOF(track, poiRef)}; + float nSigmaITSRef{getNSigmaITS(track, poiRef)}; + if (cfgOpenPIDQA) { + ese_parameters::hPIDQARef1D[0]->Fill(track.pt()); + ese_parameters::hPIDQARef1D[1]->Fill(track.eta()); + ese_parameters::hPIDQARef1D[2]->Fill(track.phi()); + ese_parameters::hPIDQARef1D[3]->Fill(track.itsNCls()); + ese_parameters::hPIDQARef1D[4]->Fill(track.tpcNClsFound()); + ese_parameters::hPIDQARef1D[5]->Fill(track.itsChi2NCl()); + ese_parameters::hPIDQARef1D[6]->Fill(track.tpcChi2NCl()); + ese_parameters::hPIDQARef1D[7]->Fill(track.dcaXY()); + ese_parameters::hPIDQARef1D[8]->Fill(track.dcaZ()); + ese_parameters::hPIDQARef1D[9]->Fill(nSigmaTPCRef); + ese_parameters::hPIDQARef1D[10]->Fill(nSigmaTOFRef); + ese_parameters::hPIDQARef1D[11]->Fill(nSigmaITSRef); + ese_parameters::hPIDQARef2D[0]->Fill(track.sign() * correctedTpcInnerParam, track.tpcSignal()); + ese_parameters::hPIDQARef2D[1]->Fill(nSigmaTPCRef, track.pt()); + ese_parameters::hPIDQARef2D[2]->Fill(nSigmaTOFRef, track.pt()); + ese_parameters::hPIDQARef2D[3]->Fill(nSigmaITSRef, track.pt()); + if (cfgOpen3DPIDPlots->get(0u)) { + ese_parameters::hPIDQARef3D[0]->Fill(nSigmaTOFRef, nSigmaITSRef, track.pt()); + } + if (cfgOpen3DPIDPlots->get(1u)) { + ese_parameters::hPIDQARef3D[1]->Fill(nSigmaITSRef, nSigmaTPCRef, track.pt()); + } + if (cfgOpen3DPIDPlots->get(2u)) { + ese_parameters::hPIDQARef3D[2]->Fill(nSigmaTOFRef, nSigmaTPCRef, track.pt()); + } + } + if (cfgOpenv2) { if (track.sign() > 0) { - histos.fill(HIST("ESE/hist_v2PosHe3_Cent_Pt_q2Pr"), track.pt(), cent, q2, std::cos(2 * (track.phi() - psi2))); + ese_parameters::hv2Ref[0]->Fill(track.pt(), collision.centFT0C(), std::cos(2 * (track.phi() - psi2))); } else { - histos.fill(HIST("ESE/hist_v2NegHe3_Cent_Pt_q2Pr"), track.pt(), cent, q2, std::cos(2 * (track.phi() - psi2))); + ese_parameters::hv2Ref[1]->Fill(track.pt(), collision.centFT0C(), std::cos(2 * (track.phi() - psi2))); } - } else { - histos.fill(HIST("ESE/hist_v2He3_Cent_Pt_q2Pr"), track.pt(), cent, q2, std::cos(2 * (track.phi() - psi2))); } } } @@ -798,6 +856,8 @@ struct FlowEsePHe3 { void init(InitContext const&) { + poiTar = getPOI(cfgTarName); + poiRef = getPOI(cfgRefName); detId = getDetId(cfgDetName); refAId = getDetId(cfgRefAName); refBId = getDetId(cfgRefBName); @@ -807,169 +867,186 @@ struct FlowEsePHe3 { refAId = 4; refBId = 5; } - if (cfgUseAdditionalEventCut) { - 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); - fMultPVCutLow->SetParameters(3257.29, -121.848, 1.98492, -0.0172128, 6.47528e-05, 154.756, -1.86072, -0.0274713, 0.000633499, -3.37757e-06); - 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); - fMultPVCutHigh->SetParameters(3257.29, -121.848, 1.98492, -0.0172128, 6.47528e-05, 154.756, -1.86072, -0.0274713, 0.000633499, -3.37757e-06); + detInd = detId * 4 + cfgnTotalSystem * 4 * (2 - 2); + refAInd = refAId * 4 + cfgnTotalSystem * 4 * (2 - 2); + refBInd = refBId * 4 + cfgnTotalSystem * 4 * (2 - 2); - 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); - fMultCutLow->SetParameters(1654.46, -47.2379, 0.449833, -0.0014125, 150.773, -3.67334, 0.0530503, -0.000614061, 3.15956e-06); - 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); - fMultCutHigh->SetParameters(1654.46, -47.2379, 0.449833, -0.0014125, 150.773, -3.67334, 0.0530503, -0.000614061, 3.15956e-06); + 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); + fMultPVCutLow->SetParameters(3257.29, -121.848, 1.98492, -0.0172128, 6.47528e-05, 154.756, -1.86072, -0.0274713, 0.000633499, -3.37757e-06); + 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); + fMultPVCutHigh->SetParameters(3257.29, -121.848, 1.98492, -0.0172128, 6.47528e-05, 154.756, -1.86072, -0.0274713, 0.000633499, -3.37757e-06); + 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); + fMultCutLow->SetParameters(1654.46, -47.2379, 0.449833, -0.0014125, 150.773, -3.67334, 0.0530503, -0.000614061, 3.15956e-06); + 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); + fMultCutHigh->SetParameters(1654.46, -47.2379, 0.449833, -0.0014125, 150.773, -3.67334, 0.0530503, -0.000614061, 3.15956e-06); + fT0AV0AMean = new TF1("fT0AV0AMean", "[0]+[1]*x", 0, 200000); + fT0AV0AMean->SetParameters(-1601.0581, 9.417652e-01); + fT0AV0ASigma = new TF1("fT0AV0ASigma", "[0]+[1]*x+[2]*x*x+[3]*x*x*x+[4]*x*x*x*x", 0, 200000); + fT0AV0ASigma->SetParameters(463.4144, 6.796509e-02, -9.097136e-07, 7.971088e-12, -2.600581e-17); - fT0AV0AMean = new TF1("fT0AV0AMean", "[0]+[1]*x", 0, 200000); - fT0AV0AMean->SetParameters(-1601.0581, 9.417652e-01); - fT0AV0ASigma = new TF1("fT0AV0ASigma", "[0]+[1]*x+[2]*x*x+[3]*x*x*x+[4]*x*x*x*x", 0, 200000); - fT0AV0ASigma->SetParameters(463.4144, 6.796509e-02, -9.097136e-07, 7.971088e-12, -2.600581e-17); - } + AxisSpec axisITSNcls = {10, -1.5, 8.5, "ITSNcls"}; + AxisSpec axisTPCNcls = {160, 0, 160, "TPCNcls"}; AxisSpec axisEvtPl = {100, -1.0 * constants::math::PI, constants::math::PI}; - AxisSpec axisvertexz = {100, -15., 15., "vrtx_{Z} [cm]"}; - histos.add("QA/histEventCount", "", {HistType::kTH1F, {{3, 0.0, 3.0}}}); - histos.get(HIST("QA/histEventCount"))->GetXaxis()->SetBinLabel(1, "Filtered event"); - histos.get(HIST("QA/histEventCount"))->GetXaxis()->SetBinLabel(2, "after sel8"); - histos.get(HIST("QA/histEventCount"))->GetXaxis()->SetBinLabel(3, "after additional event cut"); - if (cfgUseAdditionalEventCut) { - histos.add("QA/histEventCountDetail", "Number of Event;; Count", {HistType::kTH1F, {{11, 0, 11}}}); - histos.get(HIST("QA/histEventCountDetail"))->GetXaxis()->SetBinLabel(1, "after sel8"); - histos.get(HIST("QA/histEventCountDetail"))->GetXaxis()->SetBinLabel(2, "kIsGoodZvtxFT0vsPV"); - histos.get(HIST("QA/histEventCountDetail"))->GetXaxis()->SetBinLabel(3, "kNoSameBunchPileup"); - histos.get(HIST("QA/histEventCountDetail"))->GetXaxis()->SetBinLabel(4, "kNoCollInTimeRangeStandard"); - histos.get(HIST("QA/histEventCountDetail"))->GetXaxis()->SetBinLabel(5, "kIsGoodITSLayersAll"); - histos.get(HIST("QA/histEventCountDetail"))->GetXaxis()->SetBinLabel(6, "kNoCollInRofStandard"); - histos.get(HIST("QA/histEventCountDetail"))->GetXaxis()->SetBinLabel(7, "kNoHighMultCollInPrevRof"); - histos.get(HIST("QA/histEventCountDetail"))->GetXaxis()->SetBinLabel(8, "occupancy"); - histos.get(HIST("QA/histEventCountDetail"))->GetXaxis()->SetBinLabel(9, "MultCorrelationPVTracks"); - histos.get(HIST("QA/histEventCountDetail"))->GetXaxis()->SetBinLabel(10, "MultCorrelationGlobalTracks"); - histos.get(HIST("QA/histEventCountDetail"))->GetXaxis()->SetBinLabel(11, "cfgEvSelV0AT0ACut"); - } + AxisSpec axisPhi = {200, -2.1 * constants::math::PI, 2.1 * constants::math::PI}; + AxisSpec axisCentForQA = {100, 0, 100}; + AxisSpec axisCharge = {4, -2, 2, "Charge"}; + // hists for event level QA + histsESE.add("EventQA/histEventCount", ";Event Count;Counts", {HistType::kTH1F, {{100, 0, 100}}}); + histsESE.get(HIST("EventQA/histEventCount"))->GetXaxis()->SetBinLabel(1, "after sel8"); + histsESE.get(HIST("EventQA/histEventCount"))->GetXaxis()->SetBinLabel(2, "kIsGoodZvtxFT0vsPV"); + histsESE.get(HIST("EventQA/histEventCount"))->GetXaxis()->SetBinLabel(3, "kNoSameBunchPileup"); + histsESE.get(HIST("EventQA/histEventCount"))->GetXaxis()->SetBinLabel(4, "kNoCollInTimeRangeStandard"); + histsESE.get(HIST("EventQA/histEventCount"))->GetXaxis()->SetBinLabel(5, "kIsGoodITSLayersAll"); + histsESE.get(HIST("EventQA/histEventCount"))->GetXaxis()->SetBinLabel(6, "kNoCollInRofStandard"); + histsESE.get(HIST("EventQA/histEventCount"))->GetXaxis()->SetBinLabel(7, "kNoHighMultCollInPrevRof"); + histsESE.get(HIST("EventQA/histEventCount"))->GetXaxis()->SetBinLabel(8, "occupancy"); + histsESE.get(HIST("EventQA/histEventCount"))->GetXaxis()->SetBinLabel(9, "MultCorrelationPVTracks"); + histsESE.get(HIST("EventQA/histEventCount"))->GetXaxis()->SetBinLabel(10, "MultCorrelationGlobalTracks"); + histsESE.get(HIST("EventQA/histEventCount"))->GetXaxis()->SetBinLabel(11, "cfgEvSelV0AT0ACut"); + histsESE.add("EventQA/histVtz", ";#it{Vtz} (cm);Counts", {HistType::kTH1F, {{200, -20., +20.}}}); + histsESE.add("EventQA/histCent", ";Centrality (%);Counts", {HistType::kTH1F, {{100, 0., 100.}}}); if (cfgOpenFullEventQA) { - histos.add("QA/hist_globalTracks_centT0C_before", "before cut;Centrality T0C;mulplicity global tracks", {HistType::kTH2D, {cfgaxisCentForQA, cfgaxisNch}}); - histos.add("QA/hist_PVTracks_centT0C_before", "before cut;Centrality T0C;mulplicity PV tracks", {HistType::kTH2D, {cfgaxisCentForQA, cfgaxisNchPV}}); - histos.add("QA/hist_globalTracks_PVTracks_before", "before cut;mulplicity PV tracks;mulplicity global tracks", {HistType::kTH2D, {cfgaxisNchPV, cfgaxisNch}}); - histos.add("QA/hist_globalTracks_multT0A_before", "before cut;mulplicity T0A;mulplicity global tracks", {HistType::kTH2D, {cfgaxisT0A, cfgaxisNch}}); - histos.add("QA/hist_globalTracks_multV0A_before", "before cut;mulplicity V0A;mulplicity global tracks", {HistType::kTH2D, {cfgaxisT0A, cfgaxisNch}}); - histos.add("QA/hist_multV0A_multT0A_before", "before cut;mulplicity T0A;mulplicity V0A", {HistType::kTH2D, {cfgaxisT0A, cfgaxisT0A}}); - histos.add("QA/hist_multT0C_centT0C_before", "before cut;Centrality T0C;mulplicity T0C", {HistType::kTH2D, {cfgaxisCentForQA, cfgaxisT0C}}); - histos.add("QA/hist_globalTracks_centT0C_after", "after cut;Centrality T0C;mulplicity global tracks", {HistType::kTH2D, {cfgaxisCentForQA, cfgaxisNch}}); - histos.add("QA/hist_PVTracks_centT0C_after", "after cut;Centrality T0C;mulplicity PV tracks", {HistType::kTH2D, {cfgaxisCentForQA, cfgaxisNchPV}}); - histos.add("QA/hist_globalTracks_PVTracks_after", "after cut;mulplicity PV tracks;mulplicity global tracks", {HistType::kTH2D, {cfgaxisNchPV, cfgaxisNch}}); - histos.add("QA/hist_globalTracks_multT0A_after", "after cut;mulplicity T0A;mulplicity global tracks", {HistType::kTH2D, {cfgaxisT0A, cfgaxisNch}}); - histos.add("QA/hist_globalTracks_multV0A_after", "after cut;mulplicity V0A;mulplicity global tracks", {HistType::kTH2D, {cfgaxisT0A, cfgaxisNch}}); - histos.add("QA/hist_multV0A_multT0A_after", "after cut;mulplicity T0A;mulplicity V0A", {HistType::kTH2D, {cfgaxisT0A, cfgaxisT0A}}); - histos.add("QA/hist_multT0C_centT0C_after", "after cut;Centrality T0C;mulplicity T0C", {HistType::kTH2D, {cfgaxisCentForQA, cfgaxisT0C}}); - } - histos.add("QA/histVertexZRec", ";vrtx_{Z} [cm];counts", {HistType::kTH1F, {axisvertexz}}); - histos.add("QA/histCentrality", ";Centrality;counts", {HistType::kTH1F, {cfgaxisCentForQA}}); - histos.add("QA/histProtonNum", "ProtonNum;counts", {HistType::kTH1F, {{100, 0, 100}}}); - histos.add("QA/histHe3Num", "He3Num;counts", {HistType::kTH1F, {{20, 0, 20}}}); - histos.add("QA/histQvec_CorrL0_V2", ";#it{Q_{x}};#it{Q_{y}};Centrality", {HistType::kTH3F, {cfgaxisQvecF, cfgaxisQvecF, cfgaxisCent}}); - histos.add("QA/histQvec_CorrL1_V2", ";#it{Q_{x}};#it{Q_{y}};Centrality", {HistType::kTH3F, {cfgaxisQvecF, cfgaxisQvecF, cfgaxisCent}}); - histos.add("QA/histQvec_CorrL2_V2", ";#it{Q_{x}};#it{Q_{y}};Centrality", {HistType::kTH3F, {cfgaxisQvecF, cfgaxisQvecF, cfgaxisCent}}); - histos.add("QA/histQvec_CorrL3_V2", ";#it{Q_{x}};#it{Q_{y}};Centrality", {HistType::kTH3F, {cfgaxisQvecF, cfgaxisQvecF, cfgaxisCent}}); - histos.add("QA/histEvtPl_CorrL0_V2", ";EventPlane angle;Centrality", {HistType::kTH2F, {axisEvtPl, cfgaxisCent}}); - histos.add("QA/histEvtPl_CorrL1_V2", ";EventPlane angle;Centrality", {HistType::kTH2F, {axisEvtPl, cfgaxisCent}}); - histos.add("QA/histEvtPl_CorrL2_V2", ";EventPlane angle;Centrality", {HistType::kTH2F, {axisEvtPl, cfgaxisCent}}); - histos.add("QA/histEvtPl_CorrL3_V2", ";EventPlane angle;Centrality", {HistType::kTH2F, {axisEvtPl, cfgaxisCent}}); - histos.add("QA/histQvecRes_SigRefAV2", ";Centrality;Cos(Sig-RefA)", {HistType::kTProfile, {cfgaxisCent}}); - histos.add("QA/histQvecRes_SigRefBV2", ";Centrality;Cos(Sig-RefB)", {HistType::kTProfile, {cfgaxisCent}}); - histos.add("QA/histQvecRes_RefARefBV2", ";Centrality;Cos(RefA-RefB)", {HistType::kTProfile, {cfgaxisCent}}); - if (cfgOpenv2q) { - histos.add("V2/histCosV2EP_Pr_Pos", ";#it{p}_{T};Centrality", {HistType::kTProfile2D, {cfgaxispt, cfgaxisCent}}); - histos.add("V2/histCosV2EP_Pr_Neg", ";#it{p}_{T};Centrality", {HistType::kTProfile2D, {cfgaxispt, cfgaxisCent}}); - histos.add("V2/histCosV2EP_He3_Pos", ";#it{p}_{T};Centrality", {HistType::kTProfile2D, {cfgaxispt, cfgaxisCent}}); - histos.add("V2/histCosV2EP_He3_Neg", ";#it{p}_{T};Centrality", {HistType::kTProfile2D, {cfgaxispt, cfgaxisCent}}); - histos.add("q2/hist_q2_Cen_Pr", ";q_{2} (TPC);Centrality", {HistType::kTH2F, {cfgaxisq2, cfgaxisCent}}); - histos.add("q2/hist_q2_Cen_He3", ";q_{2} (TPC);Centrality", {HistType::kTH2F, {cfgaxisq2, cfgaxisCent}}); - histos.add("q2/hist_q2_Pr", ";q_{2} (TPC);counts", {HistType::kTH1F, {cfgaxisq2}}); - histos.add("q2/hist_q2_He3", ";q_{2} (TPC);counts", {HistType::kTH1F, {cfgaxisq2}}); + histsESE.add("EventQA/hist_globalTracks_centT0C_before", "before cut;Centrality T0C;mulplicity global tracks", {HistType::kTH2D, {axisCentForQA, cfgaxisNch}}); + histsESE.add("EventQA/hist_PVTracks_centT0C_before", "before cut;Centrality T0C;mulplicity PV tracks", {HistType::kTH2D, {axisCentForQA, cfgaxisNchPV}}); + histsESE.add("EventQA/hist_globalTracks_PVTracks_before", "before cut;mulplicity PV tracks;mulplicity global tracks", {HistType::kTH2D, {cfgaxisNchPV, cfgaxisNch}}); + histsESE.add("EventQA/hist_globalTracks_multT0A_before", "before cut;mulplicity T0A;mulplicity global tracks", {HistType::kTH2D, {cfgaxisT0A, cfgaxisNch}}); + histsESE.add("EventQA/hist_globalTracks_multV0A_before", "before cut;mulplicity V0A;mulplicity global tracks", {HistType::kTH2D, {cfgaxisT0A, cfgaxisNch}}); + histsESE.add("EventQA/hist_multV0A_multT0A_before", "before cut;mulplicity T0A;mulplicity V0A", {HistType::kTH2D, {cfgaxisT0A, cfgaxisT0A}}); + histsESE.add("EventQA/hist_multT0C_centT0C_before", "before cut;Centrality T0C;mulplicity T0C", {HistType::kTH2D, {axisCentForQA, cfgaxisT0C}}); + histsESE.add("EventQA/hist_globalTracks_centT0C_after", "after cut;Centrality T0C;mulplicity global tracks", {HistType::kTH2D, {axisCentForQA, cfgaxisNch}}); + histsESE.add("EventQA/hist_PVTracks_centT0C_after", "after cut;Centrality T0C;mulplicity PV tracks", {HistType::kTH2D, {axisCentForQA, cfgaxisNchPV}}); + histsESE.add("EventQA/hist_globalTracks_PVTracks_after", "after cut;mulplicity PV tracks;mulplicity global tracks", {HistType::kTH2D, {cfgaxisNchPV, cfgaxisNch}}); + histsESE.add("EventQA/hist_globalTracks_multT0A_after", "after cut;mulplicity T0A;mulplicity global tracks", {HistType::kTH2D, {cfgaxisT0A, cfgaxisNch}}); + histsESE.add("EventQA/hist_globalTracks_multV0A_after", "after cut;mulplicity V0A;mulplicity global tracks", {HistType::kTH2D, {cfgaxisT0A, cfgaxisNch}}); + histsESE.add("EventQA/hist_multV0A_multT0A_after", "after cut;mulplicity T0A;mulplicity V0A", {HistType::kTH2D, {cfgaxisT0A, cfgaxisT0A}}); + histsESE.add("EventQA/hist_multT0C_centT0C_after", "after cut;Centrality T0C;mulplicity T0C", {HistType::kTH2D, {axisCentForQA, cfgaxisT0C}}); } - if (cfgOpenESE) { - if (cfgOpenESEChargeSeperation) { - if (cfgOpenESEProton) { - histos.add("ESE/hist_v2PosPr_Cent_Pt_q2He3", ";#it{p}_{T};q_{2}(He3);Centrality", HistType::kTProfile3D, {cfgaxispt, cfgaxisq2, cfgaxisCent}); - histos.add("ESE/hist_v2NegPr_Cent_Pt_q2He3", ";#it{p}_{T};q_{2}(He3);Centrality", HistType::kTProfile3D, {cfgaxispt, cfgaxisq2, cfgaxisCent}); - } - if (cfgOpenESEHe3) { - histos.add("ESE/hist_v2PosHe3_Cent_Pt_q2Pr", ";#it{p}_{T};q_{2}(Proton);Centrality", HistType::kTProfile3D, {cfgaxispt, cfgaxisq2, cfgaxisCent}); - histos.add("ESE/hist_v2NegHe3_Cent_Pt_q2Pr", ";#it{p}_{T};q_{2}(Proton);Centrality", HistType::kTProfile3D, {cfgaxispt, cfgaxisq2, cfgaxisCent}); - } - } else { - if (cfgOpenESEProton) { - histos.add("ESE/hist_v2Pr_Cent_Pt_q2He3", ";#it{p}_{T};q_{2}(He3);Centrality", HistType::kTProfile3D, {cfgaxispt, cfgaxisq2, cfgaxisCent}); - } - if (cfgOpenESEHe3) { - histos.add("ESE/hist_v2He3_Cent_Pt_q2Pr", ";#it{p}_{T};q_{2}(Proton);Centrality", HistType::kTProfile3D, {cfgaxispt, cfgaxisq2, cfgaxisCent}); - } + histsESE.add("PlanQA/histQvec_CorrL0_V2", ";#it{Q_{x}};#it{Q_{y}};Centrality", {HistType::kTH3F, {cfgaxisQvecF, cfgaxisQvecF, cfgaxisCent}}); + histsESE.add("PlanQA/histQvec_CorrL1_V2", ";#it{Q_{x}};#it{Q_{y}};Centrality", {HistType::kTH3F, {cfgaxisQvecF, cfgaxisQvecF, cfgaxisCent}}); + histsESE.add("PlanQA/histQvec_CorrL2_V2", ";#it{Q_{x}};#it{Q_{y}};Centrality", {HistType::kTH3F, {cfgaxisQvecF, cfgaxisQvecF, cfgaxisCent}}); + histsESE.add("PlanQA/histQvec_CorrL3_V2", ";#it{Q_{x}};#it{Q_{y}};Centrality", {HistType::kTH3F, {cfgaxisQvecF, cfgaxisQvecF, cfgaxisCent}}); + histsESE.add("PlanQA/histEvtPl_CorrL0_V2", ";EventPlane angle;Centrality", {HistType::kTH2F, {axisEvtPl, cfgaxisCent}}); + histsESE.add("PlanQA/histEvtPl_CorrL1_V2", ";EventPlane angle;Centrality", {HistType::kTH2F, {axisEvtPl, cfgaxisCent}}); + histsESE.add("PlanQA/histEvtPl_CorrL2_V2", ";EventPlane angle;Centrality", {HistType::kTH2F, {axisEvtPl, cfgaxisCent}}); + histsESE.add("PlanQA/histEvtPl_CorrL3_V2", ";EventPlane angle;Centrality", {HistType::kTH2F, {axisEvtPl, cfgaxisCent}}); + histsESE.add("PlanQA/histQvecRes_SigRefAV2", ";Centrality;Cos(Sig-RefA)", {HistType::kTProfile, {cfgaxisCent}}); + histsESE.add("PlanQA/histQvecRes_SigRefBV2", ";Centrality;Cos(Sig-RefB)", {HistType::kTProfile, {cfgaxisCent}}); + histsESE.add("PlanQA/histQvecRes_RefARefBV2", ";Centrality;Cos(RefA-RefB)", {HistType::kTProfile, {cfgaxisCent}}); + // hists for track level QA + histsESE.add("TrackQA/hist_dEdxTPC_All", ";#it{p}^{TPC}/#it{z} (GeV/c);d#it{E}/d#it{x}", {HistType::kTH2F, {cfgrigidityBins, cfgdedxBins}}); + histsESE.add("TrackQA/hist_pt_All", ";#it{p}_{T};counts", {HistType::kTH1F, {cfgaxispt}}); + histsESE.add("TrackQA/hist_eta_All", ";#it{#eta};counts", {HistType::kTH1F, {cfgaxisetaPID}}); + histsESE.add("TrackQA/hist_phi_All", ";#it{#phi};counts", {HistType::kTH1F, {axisPhi}}); + histsESE.add("TrackQA/hist_ITSNcls_All", ";ITSNcls;counts", {HistType::kTH1F, {axisITSNcls}}); + histsESE.add("TrackQA/hist_TPCNcls_All", ";TPCNcls;counts", {HistType::kTH1F, {axisTPCNcls}}); + histsESE.add("TrackQA/hist_ITSChi2NDF_All", ";ITS#it{#chi^{2}}/NDF;counts", {HistType::kTH1F, {cfgaxisChi2Ncls}}); + histsESE.add("TrackQA/hist_TPCChi2NDF_All", ";TPC#it{#chi^{2}}/NDF;counts", {HistType::kTH1F, {cfgaxisChi2Ncls}}); + histsESE.add("TrackQA/hist_DCAxy_All", ";#it{DCA_{xy}};counts", {HistType::kTH1F, {cfgaxisDCAxy}}); + histsESE.add("TrackQA/hist_DCAz_All", ";#it{DCA_{xy}};counts", {HistType::kTH1F, {cfgaxisDCAz}}); + // v2 and ESEPlots + /// QA plots + if (cfgOpenPIDQA) { + ese_parameters::hPIDQATar2D[0] = histsESE.add(Form("ESE/TrackQA/hist_dEdxTPC_%s", cfgTarName.value.c_str()), ";#it{p}^{TPC}/#it{z} (GeV/c);d#it{E}/d#it{x}", HistType::kTH2F, {cfgrigidityBins, cfgdedxBins}); + ese_parameters::hPIDQATar1D[0] = histsESE.add(Form("ESE/TrackQA/hist_pt_%s", cfgTarName.value.c_str()), ";#it{p}_{T};counts", HistType::kTH1F, {cfgaxispt}); + ese_parameters::hPIDQATar1D[1] = histsESE.add(Form("ESE/TrackQA/hist_eta_%s", cfgTarName.value.c_str()), ";#it{#eta};counts", HistType::kTH1F, {cfgaxisetaPID}); + ese_parameters::hPIDQATar1D[2] = histsESE.add(Form("ESE/TrackQA/hist_phi_%s", cfgTarName.value.c_str()), ";#it{#phi};counts", HistType::kTH1F, {axisPhi}); + ese_parameters::hPIDQATar1D[3] = histsESE.add(Form("ESE/TrackQA/hist_ITSNcls_%s", cfgTarName.value.c_str()), ";ITSNcls;counts", HistType::kTH1F, {axisITSNcls}); + ese_parameters::hPIDQATar1D[4] = histsESE.add(Form("ESE/TrackQA/hist_TPCNcls_%s", cfgTarName.value.c_str()), ";TPCNcls;counts", HistType::kTH1F, {axisTPCNcls}); + ese_parameters::hPIDQATar1D[5] = histsESE.add(Form("ESE/TrackQA/hist_ITSChi2NDF_%s", cfgTarName.value.c_str()), ";ITS#it{#chi^{2}}/NDF;counts", HistType::kTH1F, {cfgaxisChi2Ncls}); + ese_parameters::hPIDQATar1D[6] = histsESE.add(Form("ESE/TrackQA/hist_TPCChi2NDF_%s", cfgTarName.value.c_str()), ";TPC#it{#chi^{2}}/NDF;counts", HistType::kTH1F, {cfgaxisChi2Ncls}); + ese_parameters::hPIDQATar1D[7] = histsESE.add(Form("ESE/TrackQA/hist_DCAxy_%s", cfgTarName.value.c_str()), ";#it{DCA_{xy}};counts", HistType::kTH1F, {cfgaxisDCAxy}); + ese_parameters::hPIDQATar1D[8] = histsESE.add(Form("ESE/TrackQA/hist_DCAz_%s", cfgTarName.value.c_str()), ";#it{DCA_{xy}};counts", HistType::kTH1F, {cfgaxisDCAz}); + ese_parameters::hPIDQATar1D[9] = histsESE.add(Form("ESE/TrackQA/hist_nSigmaTPC_%s", cfgTarName.value.c_str()), ";n#sigmaTPC;counts", HistType::kTH1F, {cfgnSigmaBinsTPC}); + ese_parameters::hPIDQATar2D[1] = histsESE.add(Form("ESE/TrackQA/hist_nSigmaTPC_pt_%s", cfgTarName.value.c_str()), ";#it{p}_{T};n#sigmaTPC", HistType::kTH2F, {cfgaxispt, cfgnSigmaBinsTPC}); + ese_parameters::hPIDQATar1D[10] = histsESE.add(Form("ESE/TrackQA/hist_nSigmaTOF_%s", cfgTarName.value.c_str()), ";n#sigmaTOF;counts", HistType::kTH1F, {cfgnSigmaBinsTOF}); + ese_parameters::hPIDQATar2D[2] = histsESE.add(Form("ESE/TrackQA/hist_nSigmaTOF_pt_%s", cfgTarName.value.c_str()), ";#it{p}_{T};n#sigmaTOF", HistType::kTH2F, {cfgaxispt, cfgnSigmaBinsTOF}); + ese_parameters::hPIDQATar1D[11] = histsESE.add(Form("ESE/TrackQA/hist_nSigmaITS_%s", cfgTarName.value.c_str()), ";n#sigmaITS;counts", HistType::kTH1F, {cfgnSigmaBinsITS}); + ese_parameters::hPIDQATar2D[3] = histsESE.add(Form("ESE/TrackQA/hist_nSigmaITS_pt_%s", cfgTarName.value.c_str()), ";#it{p}_{T};n#sigmaITS", HistType::kTH2F, {cfgaxispt, cfgnSigmaBinsITS}); + ese_parameters::hPIDQARef2D[0] = histsESE.add(Form("ESE/TrackQA/hist_dEdxTPC_%s", cfgRefName.value.c_str()), ";#it{p}^{TPC}/#it{z} (GeV/c);d#it{E}/d#it{x}", HistType::kTH2F, {cfgrigidityBins, cfgdedxBins}); + ese_parameters::hPIDQARef1D[0] = histsESE.add(Form("ESE/TrackQA/hist_pt_%s", cfgRefName.value.c_str()), ";#it{p}_{T};counts", HistType::kTH1F, {cfgaxispt}); + ese_parameters::hPIDQARef1D[1] = histsESE.add(Form("ESE/TrackQA/hist_eta_%s", cfgRefName.value.c_str()), ";#it{#eta};counts", HistType::kTH1F, {cfgaxisetaPID}); + ese_parameters::hPIDQARef1D[2] = histsESE.add(Form("ESE/TrackQA/hist_phi_%s", cfgRefName.value.c_str()), ";#it{#phi};counts", HistType::kTH1F, {axisPhi}); + ese_parameters::hPIDQARef1D[3] = histsESE.add(Form("ESE/TrackQA/hist_ITSNcls_%s", cfgRefName.value.c_str()), ";ITSNcls;counts", HistType::kTH1F, {axisITSNcls}); + ese_parameters::hPIDQARef1D[4] = histsESE.add(Form("ESE/TrackQA/hist_TPCNcls_%s", cfgRefName.value.c_str()), ";TPCNcls;counts", HistType::kTH1F, {axisTPCNcls}); + ese_parameters::hPIDQARef1D[5] = histsESE.add(Form("ESE/TrackQA/hist_ITSChi2NDF_%s", cfgRefName.value.c_str()), ";ITS#it{#chi^{2}}/NDF;counts", HistType::kTH1F, {cfgaxisChi2Ncls}); + ese_parameters::hPIDQARef1D[6] = histsESE.add(Form("ESE/TrackQA/hist_TPCChi2NDF_%s", cfgRefName.value.c_str()), ";TPC#it{#chi^{2}}/NDF;counts", HistType::kTH1F, {cfgaxisChi2Ncls}); + ese_parameters::hPIDQARef1D[7] = histsESE.add(Form("ESE/TrackQA/hist_DCAxy_%s", cfgRefName.value.c_str()), ";#it{DCA_{xy}};counts", HistType::kTH1F, {cfgaxisDCAxy}); + ese_parameters::hPIDQARef1D[8] = histsESE.add(Form("ESE/TrackQA/hist_DCAz_%s", cfgRefName.value.c_str()), ";#it{DCA_{xy}};counts", HistType::kTH1F, {cfgaxisDCAz}); + ese_parameters::hPIDQARef1D[9] = histsESE.add(Form("ESE/TrackQA/hist_nSigmaTPC_%s", cfgRefName.value.c_str()), ";n#sigmaTPC;counts", HistType::kTH1F, {cfgnSigmaBinsTPC}); + ese_parameters::hPIDQARef2D[1] = histsESE.add(Form("ESE/TrackQA/hist_nSigmaTPC_pt_%s", cfgRefName.value.c_str()), ";#it{p}_{T};n#sigmaTPC", HistType::kTH2F, {cfgaxispt, cfgnSigmaBinsTPC}); + ese_parameters::hPIDQARef1D[10] = histsESE.add(Form("ESE/TrackQA/hist_nSigmaTOF_%s", cfgRefName.value.c_str()), ";n#sigmaTOF;counts", HistType::kTH1F, {cfgnSigmaBinsTOF}); + ese_parameters::hPIDQARef2D[2] = histsESE.add(Form("ESE/TrackQA/hist_nSigmaTOF_pt_%s", cfgRefName.value.c_str()), ";#it{p}_{T};n#sigmaTOF", HistType::kTH2F, {cfgaxispt, cfgnSigmaBinsTOF}); + ese_parameters::hPIDQARef1D[11] = histsESE.add(Form("ESE/TrackQA/hist_nSigmaITS_%s", cfgRefName.value.c_str()), ";n#sigmaITS;counts", HistType::kTH1F, {cfgnSigmaBinsITS}); + ese_parameters::hPIDQARef2D[3] = histsESE.add(Form("ESE/TrackQA/hist_nSigmaITS_pt_%s", cfgRefName.value.c_str()), ";#it{p}_{T};n#sigmaITS", HistType::kTH2F, {cfgaxispt, cfgnSigmaBinsITS}); + if (cfgOpen3DPIDPlots->get(0u)) { + ese_parameters::hPIDQATar3D[0] = histsESE.add(Form("ESE/TrackQA/hist_nSigmaTOFITSPt_%s", cfgTarName.value.c_str()), ";n_{#sigma}TOF;n_{#sigma}ITS;#it{p}_{T}", HistType::kTH3F, {cfgnSigmaBinsTOF, cfgnSigmaBinsITS, cfgaxispt}); + ese_parameters::hPIDQARef3D[0] = histsESE.add(Form("ESE/TrackQA/hist_nSigmaTOFITSPt_%s", cfgRefName.value.c_str()), ";n_{#sigma}TOF;n_{#sigma}ITS;#it{p}_{T}", HistType::kTH3F, {cfgnSigmaBinsTOF, cfgnSigmaBinsITS, cfgaxispt}); } + if (cfgOpen3DPIDPlots->get(1u)) { + ese_parameters::hPIDQATar3D[1] = histsESE.add(Form("ESE/TrackQA/hist_nSigmaITSTPCPt_%s", cfgTarName.value.c_str()), ";n_{#sigma}ITS;n_{#sigma}TPC;#it{p}_{T}", HistType::kTH3F, {cfgnSigmaBinsITS, cfgnSigmaBinsTPC, cfgaxispt}); + ese_parameters::hPIDQARef3D[1] = histsESE.add(Form("ESE/TrackQA/hist_nSigmaITSTPCPt_%s", cfgRefName.value.c_str()), ";n_{#sigma}ITS;n_{#sigma}TPC;#it{p}_{T}", HistType::kTH3F, {cfgnSigmaBinsITS, cfgnSigmaBinsTPC, cfgaxispt}); + } + if (cfgOpen3DPIDPlots->get(2u)) { + ese_parameters::hPIDQATar3D[2] = histsESE.add(Form("ESE/TrackQA/hist_nSigmaTOFTPCPt_%s", cfgTarName.value.c_str()), ";n_{#sigma}TOF;n_{#sigma}TPC;#it{p}_{T}", HistType::kTH3F, {cfgnSigmaBinsTOF, cfgnSigmaBinsTPC, cfgaxispt}); + ese_parameters::hPIDQARef3D[2] = histsESE.add(Form("ESE/TrackQA/hist_nSigmaTOFTPCPt_%s", cfgRefName.value.c_str()), ";n_{#sigma}TOF;n_{#sigma}TPC;#it{p}_{T}", HistType::kTH3F, {cfgnSigmaBinsTOF, cfgnSigmaBinsTPC, cfgaxispt}); + } + } + // v2 plots + if (cfgOpenv2) { + ese_parameters::hv2Tar[0] = histsESE.add(Form("ESE/V2/hist_%sPosV2", cfgTarName.value.c_str()), ";#it{p}_{T};Centrality (%)", HistType::kTProfile2D, {cfgaxispt, cfgaxisCent}); + ese_parameters::hv2Tar[1] = histsESE.add(Form("ESE/V2/hist_%sNegV2", cfgTarName.value.c_str()), ";#it{p}_{T};Centrality (%)", HistType::kTProfile2D, {cfgaxispt, cfgaxisCent}); + ese_parameters::hv2Ref[0] = histsESE.add(Form("ESE/V2/hist_%sPosV2", cfgRefName.value.c_str()), ";#it{p}_{T};Centrality (%)", HistType::kTProfile2D, {cfgaxispt, cfgaxisCent}); + ese_parameters::hv2Ref[1] = histsESE.add(Form("ESE/V2/hist_%sNegV2", cfgRefName.value.c_str()), ";#it{p}_{T};Centrality (%)", HistType::kTProfile2D, {cfgaxispt, cfgaxisCent}); + } + // ESE plots + if (cfgOpenESEQA) { + ese_parameters::hESEQATar1D[0] = histsESE.add(Form("ESE/ESEQA/hist_%sNum", cfgTarName.value.c_str()), ";Num_{Proton}/Event;counts", HistType::kTH1F, {{100, 0, 100}}); + ese_parameters::hESEQATar1D[1] = histsESE.add(Form("ESE/ESEQA/hist_%sq2", cfgTarName.value.c_str()), ";#it{q}_{2};counts", HistType::kTH1F, {cfgaxisq2}); + ese_parameters::hESEQATar2D = histsESE.add(Form("ESE/ESEQA/hist_%sq2_Cent", cfgTarName.value.c_str()), ";#it{q}_{2};Centrality (%)", HistType::kTH2F, {cfgaxisq2, cfgaxisCent}); + ese_parameters::hESEQARef1D[0] = histsESE.add(Form("ESE/ESEQA/hist_%sNum", cfgRefName.value.c_str()), ";Num_{He3}/Event;counts", HistType::kTH1F, {{10, 0, 10}}); + ese_parameters::hESEQARef1D[1] = histsESE.add(Form("ESE/ESEQA/hist_%sq2", cfgRefName.value.c_str()), ";#it{q}_{2};counts", HistType::kTH1F, {cfgaxisq2}); + ese_parameters::hESEQARef2D = histsESE.add(Form("ESE/ESEQA/hist_%sq2_Cent", cfgRefName.value.c_str()), ";#it{q}_{2};Centrality (%)", HistType::kTH2F, {cfgaxisq2, cfgaxisCent}); + } + if (cfgOpenESE) { + ese_parameters::hESETar = histsESE.add(Form("ESE/ESE/histESE_%s", cfgTarName.value.c_str()), ";#it{p}_{T};Centrality (%);#it{q}_{2};cos(#phi-#Psi_{2});Charge", HistType::kTHnSparseF, {cfgaxispt, cfgaxisCent, cfgaxisq2, cfgaxiscos, axisCharge}); } } - void process(soa::Filtered>::iterator const& collision, soa::Filtered> const& tracks) + void process(soa::Filtered>::iterator const& collision, TracksPIDFull const& tracks) { - const auto cent = collision.centFT0C(); - histos.fill(HIST("QA/histEventCount"), 0.5); - if (!collision.sel8()) - return; - if (tracks.size() < 1) - return; - histos.fill(HIST("QA/histEventCount"), 1.5); - if (cfgOpenFullEventQA) { - histos.fill(HIST("QA/hist_globalTracks_centT0C_before"), cent, tracks.size()); - histos.fill(HIST("QA/hist_PVTracks_centT0C_before"), cent, collision.multNTracksPV()); - histos.fill(HIST("QA/hist_globalTracks_PVTracks_before"), collision.multNTracksPV(), tracks.size()); - histos.fill(HIST("QA/hist_globalTracks_multT0A_before"), collision.multFT0A(), tracks.size()); - histos.fill(HIST("QA/hist_globalTracks_multV0A_before"), collision.multFV0A(), tracks.size()); - histos.fill(HIST("QA/hist_multV0A_multT0A_before"), collision.multFT0A(), collision.multFV0A()); - histos.fill(HIST("QA/hist_multT0C_centT0C_before"), cent, collision.multFT0C()); - } - if (cfgUseAdditionalEventCut && !selEvent(collision, tracks.size(), cent)) { + ese_parameters::eseCandidates.clear(); + const float centrality{collision.centFT0C()}; + const int64_t multTrk{tracks.size()}; + if (cfgOpenFullEventQA) + fillEventQAhistBe(collision, multTrk, centrality); + if (!eventSelBasic(collision, multTrk, centrality, true)) return; + if (cfgOpenFullEventQA) + fillEventQAhistAf(collision, multTrk, centrality); + float q2Tarx{0.}; + float q2Tary{0.}; + float q2Refx{0.}; + float q2Refy{0.}; + int multiTar{0}; + int multiRef{0}; + fillESECandidates(collision, tracks, q2Tarx, q2Tary, multiTar, q2Refx, q2Refy, multiRef); + float q2Tar{calculateq2(q2Tarx, q2Tary, multiTar)}; + float q2Ref{calculateq2(q2Refx, q2Refy, multiRef)}; + if (cfgOpenESEQA) { + ese_parameters::hESEQATar1D[0]->Fill(multiTar); + ese_parameters::hESEQATar1D[1]->Fill(q2Tar); + ese_parameters::hESEQATar2D->Fill(q2Tar, centrality); + ese_parameters::hESEQARef1D[0]->Fill(multiRef); + ese_parameters::hESEQARef1D[1]->Fill(q2Ref); + ese_parameters::hESEQARef2D->Fill(q2Ref, centrality); } - histos.fill(HIST("QA/histEventCount"), 2.5); - histos.fill(HIST("QA/histCentrality"), cent); - histos.fill(HIST("QA/histVertexZRec"), collision.posZ()); - if (cfgOpenFullEventQA) { - histos.fill(HIST("QA/hist_globalTracks_centT0C_after"), cent, tracks.size()); - histos.fill(HIST("QA/hist_PVTracks_centT0C_after"), cent, collision.multNTracksPV()); - histos.fill(HIST("QA/hist_globalTracks_PVTracks_after"), collision.multNTracksPV(), tracks.size()); - histos.fill(HIST("QA/hist_globalTracks_multT0A_after"), collision.multFT0A(), tracks.size()); - histos.fill(HIST("QA/hist_globalTracks_multV0A_after"), collision.multFV0A(), tracks.size()); - histos.fill(HIST("QA/hist_multV0A_multT0A_after"), collision.multFT0A(), collision.multFV0A()); - histos.fill(HIST("QA/hist_multT0C_centT0C_after"), cent, collision.multFT0C()); - } - auto tracksPr = protonTrackSet->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); - auto tracksHe3 = he3TrackSet->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); - int multiPr = tracksPr.size(); - int multiHe3 = tracksHe3.size(); - // LOGF(info, Form("Collison ID + 1; Proton Num:%d; He3 Num:%d;\n", multiPr, multiHe3)); - histos.fill(HIST("QA/histProtonNum"), multiPr); - histos.fill(HIST("QA/histHe3Num"), multiHe3); - if (multiPr < 1 && multiHe3 < 1) - return; // Reject Collisions without enough POI - for (auto i = 0; i < static_cast(cfgnMods->size()); i++) { - int detIndGlobal = detId * 4 + cfgnTotalSystem * 4 * (cfgnMods->at(i) - 2); - float psiNGlobal = helperEP.GetEventPlane(collision.qvecRe()[detIndGlobal + 3], collision.qvecIm()[detIndGlobal + 3], cfgnMods->at(i)); - if (cfgnMods->at(i) == fourier_mode::kMode2) { - // LOGF(info, "Process q2\n"); - float q2Proton = calculateq2(tracksPr, psiNGlobal, cent, 1); - float q2He3 = calculateq2(tracksHe3, psiNGlobal, cent, 2); - histos.fill(HIST("q2/hist_q2_Pr"), q2Proton); - histos.fill(HIST("q2/hist_q2_He3"), q2He3); - histos.fill(HIST("q2/hist_q2_Cen_Pr"), q2Proton, cent); - histos.fill(HIST("q2/hist_q2_Cen_He3"), q2He3, cent); - if (cfgOpenESE && multiPr > 0 && multiHe3 > 0) { - // LOGF(info, "Process ESE\n"); - if (cfgOpenESEProton) { - processESE(tracksPr, psiNGlobal, q2Proton, cent, 1, cfgOpenESEChargeSeperation); - } - if (cfgOpenESEHe3) { - processESE(tracksHe3, psiNGlobal, q2He3, cent, 2, cfgOpenESEChargeSeperation); - } - } - // LOGF(info, "Process for this event over\n"); + if (multiTar == 0) + return; + for (const auto& c : ese_parameters::eseCandidates) { + eseTable(c.vtz, c.centFT0C, c.psi2FT0C, q2Tar, q2Ref, c.signTar, c.tpcInnerParamTar, c.tpcSignalTar, c.ptTar, c.etaTar, c.phiTar, c.dcaXYTar, c.dcaZTar, c.tpcNclsTar, c.itsNclsTar, c.tpcChi2NDFTar, c.itsChi2NDFTar, c.tpcNSigmaTar, c.tofNSigmaTar, c.itsNSigmaTar, c.itsClusSizeTar); + if (cfgOpenESE) { + ese_parameters::hESETar->Fill(c.ptTar, c.centFT0C, q2Ref, std::cos(2 * (c.phiTar - c.psi2FT0C)), c.signTar); } - fillHistosQvec(collision, cfgnMods->at(i)); } } }; @@ -977,7 +1054,6 @@ struct FlowEsePHe3 { WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{ - adaptAnalysisTask(cfgc), adaptAnalysisTask(cfgc), }; } From 3174ec6a33b274c00def9231243c286d689c5846 Mon Sep 17 00:00:00 2001 From: skundu692 <86804743+skundu692@users.noreply.github.com> Date: Tue, 10 Jun 2025 15:00:25 +0200 Subject: [PATCH 017/871] [PWGLF] Add new process function to run over strangeness dervide data (#11531) --- .../Tasks/Strangeness/taskLambdaSpinCorr.cxx | 363 ++++++++++++++++++ 1 file changed, 363 insertions(+) diff --git a/PWGLF/Tasks/Strangeness/taskLambdaSpinCorr.cxx b/PWGLF/Tasks/Strangeness/taskLambdaSpinCorr.cxx index 0472e380aed..00a2d9707f5 100644 --- a/PWGLF/Tasks/Strangeness/taskLambdaSpinCorr.cxx +++ b/PWGLF/Tasks/Strangeness/taskLambdaSpinCorr.cxx @@ -50,6 +50,9 @@ using namespace o2::framework::expressions; using std::array; using namespace o2::aod::rctsel; +using dauTracks = soa::Join; +using v0Candidates = soa::Join; + struct LfTaskLambdaSpinCorr { Service ccdb; @@ -375,6 +378,32 @@ struct LfTaskLambdaSpinCorr { return {lambdaTag, aLambdaTag, true}; // Valid candidate } + std::tuple getLambdaTagsDD(const auto& v0, const auto& collision) + { + auto postrack = v0.template posTrackExtra_as(); + auto negtrack = v0.template negTrackExtra_as(); + + int lambdaTag = 0; + int aLambdaTag = 0; + + if (isSelectedV0Daughter(v0, postrack, 0) && isSelectedV0Daughter(v0, negtrack, 1)) { + lambdaTag = 1; + } + if (isSelectedV0Daughter(v0, negtrack, 0) && isSelectedV0Daughter(v0, postrack, 1)) { + aLambdaTag = 1; + } + + if (!lambdaTag && !aLambdaTag) { + return {0, 0, false}; // No valid tags + } + + if (!selectionV0(collision, v0)) { + return {0, 0, false}; // Fails selection + } + + return {lambdaTag, aLambdaTag, true}; // Valid candidate + } + std::tuple getLambdaTagsMC(const auto& v0, const auto& collision) { auto postrack = v0.template posTrack_as(); @@ -766,6 +795,340 @@ struct LfTaskLambdaSpinCorr { } PROCESS_SWITCH(LfTaskLambdaSpinCorr, processME, "Process data ME", true); + void processDerivedData(soa::Join::iterator const& collision, v0Candidates const& V0s, dauTracks const&) + { + histos.fill(HIST("hEvtSelInfo"), 0.5); + if (rctCut.requireRCTFlagChecker && !rctChecker(collision)) { + return; + } + histos.fill(HIST("hEvtSelInfo"), 1.5); + if (!collision.sel8()) { + return; + } + histos.fill(HIST("hEvtSelInfo"), 2.5); + auto centrality = collision.centFT0C(); + int occupancy = collision.trackOccupancyInTimeRange(); + if (additionalEvSel && (!collision.selection_bit(aod::evsel::kNoSameBunchPileup) || !collision.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV))) { + return; + } + histos.fill(HIST("hEvtSelInfo"), 3.5); + if (additionalEvSel3 && (!collision.selection_bit(aod::evsel::kNoTimeFrameBorder) || !collision.selection_bit(aod::evsel::kNoITSROFrameBorder))) { + return; + } + histos.fill(HIST("hEvtSelInfo"), 4.5); + if (additionalEvSel4 && !collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { + return; + } + histos.fill(HIST("hEvtSelInfo"), 5.5); + if (additionalEvSel5 && !collision.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { + return; + } + histos.fill(HIST("hEvtSelInfo"), 6.5); + if (occupancy > cfgCutOccupancy) { + return; + } + histos.fill(HIST("hEvtSelInfo"), 7.5); + histos.fill(HIST("hCentrality"), centrality); + + for (const auto& v0 : V0s) { + auto [lambdaTag, aLambdaTag, isValid] = getLambdaTagsDD(v0, collision); + if (!isValid) { + continue; + } + + if (lambdaTag && aLambdaTag) { + continue; + } + + if (lambdaTag) { + 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; + } + if (aLambdaTag) { + 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; + } + + if (lambdaTag && (lambda.M() < lbinIM || lambda.M() > hbinIM)) { + continue; + } + if (aLambdaTag && (antiLambda.M() < lbinIM || antiLambda.M() > hbinIM)) { + continue; + } + + // auto postrack1 = v0.template posTrackExtra_as(); + // auto negtrack1 = v0.template negTrackExtra_as(); + + // 2nd loop for combination of lambda lambda + for (const auto& v02 : V0s) { + if (v02.index() <= v0.index()) { + continue; + } + auto [lambdaTag2, aLambdaTag2, isValid2] = getLambdaTagsDD(v02, collision); + if (!isValid2) { + continue; + } + if (lambdaTag2 && aLambdaTag2) { + continue; + } + if (lambdaTag2) { + proton2 = ROOT::Math::PxPyPzMVector(v02.pxpos(), v02.pypos(), v02.pzpos(), o2::constants::physics::MassProton); + antiPion2 = ROOT::Math::PxPyPzMVector(v02.pxneg(), v02.pyneg(), v02.pzneg(), o2::constants::physics::MassPionCharged); + lambda2 = proton2 + antiPion2; + } + if (aLambdaTag2) { + antiProton2 = ROOT::Math::PxPyPzMVector(v02.pxneg(), v02.pyneg(), v02.pzneg(), o2::constants::physics::MassProton); + pion2 = ROOT::Math::PxPyPzMVector(v02.pxpos(), v02.pypos(), v02.pzpos(), o2::constants::physics::MassPionCharged); + antiLambda2 = antiProton2 + pion2; + } + + if (lambdaTag2 && (lambda2.M() < lbinIM || lambda2.M() > hbinIM)) { + continue; + } + if (aLambdaTag2 && (antiLambda2.M() < lbinIM || antiLambda2.M() > hbinIM)) { + continue; + } + + // auto postrack2 = v02.template posTrackExtra_as(); + // auto negtrack2 = v02.template negTrackExtra_as(); + if (v0.posTrackExtraId() == v02.posTrackExtraId() || v0.negTrackExtraId() == v02.negTrackExtraId()) { + continue; + } + + if (lambdaTag && lambdaTag2) { + fillHistograms(1, 0, 1, 0, lambda, lambda2, proton, proton2, centrality, 0); + } + if (aLambdaTag && aLambdaTag2) { + fillHistograms(0, 1, 0, 1, antiLambda, antiLambda2, antiProton, antiProton2, centrality, 0); + } + if (lambdaTag && aLambdaTag2) { + fillHistograms(1, 0, 0, 1, lambda, antiLambda2, proton, antiProton2, centrality, 0); + } + if (aLambdaTag && lambdaTag2) { + fillHistograms(0, 1, 1, 0, antiLambda, lambda2, antiProton, proton2, centrality, 0); + } + } + } + } + PROCESS_SWITCH(LfTaskLambdaSpinCorr, processDerivedData, "Process derived data", true); + + Preslice tracksPerCollisionV0Mixed = o2::aod::v0data::straCollisionId; // for derived data only + void processDerivedDataMixed(soa::Join const& collisions, v0Candidates const& V0s, dauTracks const&) + + { + + for (auto& [collision1, collision2] : selfCombinations(colBinning, nMix, -1, collisions, collisions)) { + // LOGF(info, "Mixed event collisions: (%d, %d)", collision1.index(), collision2.index()); + if (rctCut.requireRCTFlagChecker && !rctChecker(collision1)) { + continue; + } + if (rctCut.requireRCTFlagChecker && !rctChecker(collision2)) { + continue; + } + int occupancy1 = collision1.trackOccupancyInTimeRange(); + int occupancy2 = collision2.trackOccupancyInTimeRange(); + + if (collision1.index() == collision2.index()) { + continue; + } + if (!collision1.sel8() || !collision2.sel8()) { + continue; + } + if (additionalEvSel && (!collision1.selection_bit(aod::evsel::kNoSameBunchPileup) || !collision1.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV))) { + continue; + } + if (occupancy1 > cfgCutOccupancy) { + continue; + } + if (additionalEvSel && (!collision2.selection_bit(aod::evsel::kNoSameBunchPileup) || !collision2.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV))) { + continue; + } + if (occupancy2 > cfgCutOccupancy) { + continue; + } + if (additionalEvSel3 && (!collision1.selection_bit(aod::evsel::kNoTimeFrameBorder) || !collision1.selection_bit(aod::evsel::kNoITSROFrameBorder))) { + continue; + } + if (additionalEvSel4 && !collision1.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { + continue; + } + if (mixingEvSel && additionalEvSel5 && !collision1.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { + continue; + } + + if (additionalEvSel3 && (!collision2.selection_bit(aod::evsel::kNoTimeFrameBorder) || !collision2.selection_bit(aod::evsel::kNoITSROFrameBorder))) { + continue; + } + if (additionalEvSel4 && !collision2.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { + continue; + } + if (mixingEvSel && additionalEvSel5 && !collision2.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { + continue; + } + auto centrality = collision1.centFT0C(); + auto groupV01 = V0s.sliceBy(tracksPerCollisionV0Mixed, collision1.globalIndex()); + auto groupV02 = V0s.sliceBy(tracksPerCollisionV0Mixed, collision1.globalIndex()); + auto groupV03 = V0s.sliceBy(tracksPerCollisionV0Mixed, collision2.globalIndex()); + + size_t rows = groupV03.size() + 20; + size_t cols = groupV01.size() + 20; + std::vector> pairStatus(rows, std::vector(cols, false)); + histos.fill(HIST("hv0Mult"), groupV01.size()); + for (auto& [t1, t2] : soa::combinations(o2::soa::CombinationsFullIndexPolicy(groupV01, groupV02))) { + bool pairfound = false; + if (t2.index() <= t1.index()) { + continue; + } + if (t1.straCollisionId() != t2.straCollisionId()) { + continue; + } + + auto [lambdaTag1, aLambdaTag1, isValid1] = getLambdaTagsDD(t1, collision1); + auto [lambdaTag2, aLambdaTag2, isValid2] = getLambdaTagsDD(t2, collision1); + if (!isValid1) { + continue; + } + if (!isValid2) { + continue; + } + if (lambdaTag1 && aLambdaTag1) { + continue; + } + if (lambdaTag2 && aLambdaTag2) { + continue; + } + // auto postrack1 = t1.template posTrackExtra_as(); + // auto negtrack1 = t1.template negTrackExtra_as(); + // auto postrack2 = t2.template posTrackExtra_as(); + // auto negtrack2 = t2.template negTrackExtra_as(); + if (t1.posTrackExtraId() == t2.posTrackExtraId() || t1.negTrackExtraId() == t2.negTrackExtraId()) { + continue; + } + // auto samePairSumPt = t1.pt() + t2.pt(); + // auto samePairR = TMath::Sqrt(TMath::Power(t1.phi() - t2.phi(), 2.0) + TMath::Power(t1.eta() - t2.eta(), 2.0)); + + double deltaPhiSame = RecoDecay::constrainAngle(t1.phi() - t2.phi(), 0.0); + auto samePairR = TMath::Sqrt(TMath::Power(deltaPhiSame, 2.0) + TMath::Power(t1.eta() - t2.eta(), 2.0)); + + if (lambdaTag1) { + proton0 = ROOT::Math::PxPyPzMVector(t1.pxpos(), t1.pypos(), t1.pzpos(), o2::constants::physics::MassProton); + antiPion0 = ROOT::Math::PxPyPzMVector(t1.pxneg(), t1.pyneg(), t1.pzneg(), o2::constants::physics::MassPionCharged); + lambda0 = proton0 + antiPion0; + } + if (aLambdaTag1) { + antiProton0 = ROOT::Math::PxPyPzMVector(t1.pxneg(), t1.pyneg(), t1.pzneg(), o2::constants::physics::MassProton); + pion0 = ROOT::Math::PxPyPzMVector(t1.pxpos(), t1.pypos(), t1.pzpos(), o2::constants::physics::MassPionCharged); + antiLambda0 = antiProton0 + pion0; + } + if (lambdaTag1 && (lambda0.M() < lbinIM || lambda0.M() > hbinIM)) { + continue; + } + if (aLambdaTag1 && (antiLambda0.M() < lbinIM || antiLambda0.M() > hbinIM)) { + continue; + } + if (lambdaTag2) { + proton = ROOT::Math::PxPyPzMVector(t2.pxpos(), t2.pypos(), t2.pzpos(), o2::constants::physics::MassProton); + antiPion = ROOT::Math::PxPyPzMVector(t2.pxneg(), t2.pyneg(), t2.pzneg(), o2::constants::physics::MassPionCharged); + lambda = proton + antiPion; + } + if (aLambdaTag2) { + antiProton = ROOT::Math::PxPyPzMVector(t2.pxneg(), t2.pyneg(), t2.pzneg(), o2::constants::physics::MassProton); + pion = ROOT::Math::PxPyPzMVector(t2.pxpos(), t2.pypos(), t2.pzpos(), o2::constants::physics::MassPionCharged); + antiLambda = antiProton + pion; + } + if (lambdaTag2 && (lambda.M() < lbinIM || lambda.M() > hbinIM)) { + continue; + } + if (aLambdaTag2 && (antiLambda.M() < lbinIM || antiLambda.M() > hbinIM)) { + continue; + } + + for (const auto& t3 : groupV03) { + if (pairStatus[t3.index()][t2.index()]) { + continue; + } + if (t1.straCollisionId() == t3.straCollisionId()) { + continue; + } + auto [lambdaTag3, aLambdaTag3, isValid3] = getLambdaTagsDD(t3, collision2); + if (!isValid3) { + continue; + } + if (lambdaTag3 && aLambdaTag3) { + continue; + } + if (lambdaTag1 != lambdaTag3 || aLambdaTag1 != aLambdaTag3) { + continue; + } + + if (lambdaTag3) { + proton2 = ROOT::Math::PxPyPzMVector(t3.pxpos(), t3.pypos(), t3.pzpos(), o2::constants::physics::MassProton); + antiPion2 = ROOT::Math::PxPyPzMVector(t3.pxneg(), t3.pyneg(), t3.pzneg(), o2::constants::physics::MassPionCharged); + lambda2 = proton2 + antiPion2; + } + if (aLambdaTag3) { + antiProton2 = ROOT::Math::PxPyPzMVector(t3.pxneg(), t3.pyneg(), t3.pzneg(), o2::constants::physics::MassProton); + pion2 = ROOT::Math::PxPyPzMVector(t3.pxpos(), t3.pypos(), t3.pzpos(), o2::constants::physics::MassPionCharged); + antiLambda2 = antiProton2 + pion2; + } + if (lambdaTag3 && (lambda2.M() < lbinIM || lambda2.M() > hbinIM)) { + continue; + } + + if (aLambdaTag3 && (antiLambda2.M() < lbinIM || antiLambda2.M() > hbinIM)) { + continue; + } + + double deltaPhiMix = RecoDecay::constrainAngle(t3.phi() - t2.phi(), 0.0); + auto mixPairR = TMath::Sqrt(TMath::Power(deltaPhiMix, 2.0) + TMath::Power(t3.eta() - t2.eta(), 2.0)); + + auto etaDiff = t1.eta() - t3.eta(); + auto phiDiff = RecoDecay::constrainAngle(t1.phi() - t3.phi(), 0.0); + + histos.fill(HIST("hPtDiff"), t1.pt() - t3.pt()); + histos.fill(HIST("hPhiDiff"), phiDiff); + histos.fill(HIST("hRDiff"), etaDiff); + + if (mixingCombination == 0 && std::abs(t1.pt() - t3.pt()) > ptMix) { + continue; + } + if (mixingCombination == 0 && t1.eta() * t3.eta() > 0 && std::abs(etaDiff) > etaMix) { + continue; + } + if (mixingCombination == 0 && phiDiff > phiMix) { + continue; + } + if (mixingCombination == 1 && std::abs(t1.pt() - t3.pt()) > ptMix) { + continue; + } + if (mixingCombination == 1 && std::abs(mixPairR - samePairR) > etaMix) { + continue; + } + if (lambdaTag2 && lambdaTag3) { + fillHistograms(1, 0, 1, 0, lambda, lambda2, proton, proton2, centrality, 2); + } else if (aLambdaTag2 && aLambdaTag3) { + fillHistograms(0, 1, 0, 1, antiLambda, antiLambda2, antiProton, antiProton2, centrality, 2); + } else if (lambdaTag2 && aLambdaTag3) { + fillHistograms(1, 0, 0, 1, lambda, antiLambda2, proton, antiProton2, centrality, 2); + } else if (aLambdaTag2 && lambdaTag3) { + fillHistograms(0, 1, 1, 0, antiLambda, lambda2, antiProton, proton2, centrality, 2); + } else { + continue; + } + pairfound = true; + pairStatus[t3.index()][t2.index()] = true; + if (pairfound) { + break; + } + } + } + } + } + + PROCESS_SWITCH(LfTaskLambdaSpinCorr, processDerivedDataMixed, "Process mixed derived data", true); + using CollisionMCRecTableCentFT0C = soa::Join; using TrackMCRecTable = soa::Join; using V0TrackCandidatesMC = soa::Join; From b7c799e477dfe573b3e86eac40e0374c26a1598e Mon Sep 17 00:00:00 2001 From: Daiki Sekihata Date: Tue, 10 Jun 2025 16:03:15 +0200 Subject: [PATCH 018/871] [PWGEM/Dilepton] update in DimuonCut (#11536) --- PWGEM/Dilepton/Core/Dilepton.h | 3 ++- PWGEM/Dilepton/Core/DileptonMC.h | 3 ++- PWGEM/Dilepton/Core/DimuonCut.cxx | 9 ++++++--- PWGEM/Dilepton/Core/DimuonCut.h | 5 +++-- PWGEM/Dilepton/Core/SingleTrackQC.h | 3 ++- PWGEM/Dilepton/Core/SingleTrackQCMC.h | 3 ++- 6 files changed, 17 insertions(+), 9 deletions(-) diff --git a/PWGEM/Dilepton/Core/Dilepton.h b/PWGEM/Dilepton/Core/Dilepton.h index 46cecc81c87..33f0ba99718 100644 --- a/PWGEM/Dilepton/Core/Dilepton.h +++ b/PWGEM/Dilepton/Core/Dilepton.h @@ -284,6 +284,7 @@ struct Dilepton { Configurable cfg_max_relDPt_wrt_matchedMCHMID{"cfg_max_relDPt_wrt_matchedMCHMID", 1e+10f, "max. relative dpt between MFT-MCH-MID and MCH-MID"}; Configurable cfg_max_DEta_wrt_matchedMCHMID{"cfg_max_DEta_wrt_matchedMCHMID", 1e+10f, "max. deta between MFT-MCH-MID and MCH-MID"}; Configurable cfg_max_DPhi_wrt_matchedMCHMID{"cfg_max_DPhi_wrt_matchedMCHMID", 1e+10f, "max. dphi between MFT-MCH-MID and MCH-MID"}; + Configurable requireMFTHitMap{"requireMFTHitMap", false, "flag to apply MFT hit map"}; Configurable> requiredMFTDisks{"requiredMFTDisks", std::vector{0}, "hit map on MFT disks [0,1,2,3,4]. logical-OR of each double-sided disk"}; } dimuoncuts; @@ -754,7 +755,7 @@ struct Dilepton { fDimuonCut.SetRabs(dimuoncuts.cfg_min_rabs, dimuoncuts.cfg_max_rabs); fDimuonCut.SetMaxPDCARabsDep([&](float rabs) { return (rabs < 26.5 ? 594.f : 324.f); }); fDimuonCut.SetMaxdPtdEtadPhiwrtMCHMID(dimuoncuts.cfg_max_relDPt_wrt_matchedMCHMID, dimuoncuts.cfg_max_DEta_wrt_matchedMCHMID, dimuoncuts.cfg_max_DPhi_wrt_matchedMCHMID); // this is relevant for global muons - fDimuonCut.SetMFTHitMap(dimuoncuts.requiredMFTDisks); + fDimuonCut.SetMFTHitMap(dimuoncuts.requireMFTHitMap, dimuoncuts.requiredMFTDisks); } template diff --git a/PWGEM/Dilepton/Core/DileptonMC.h b/PWGEM/Dilepton/Core/DileptonMC.h index 00cec907de5..25ebe949553 100644 --- a/PWGEM/Dilepton/Core/DileptonMC.h +++ b/PWGEM/Dilepton/Core/DileptonMC.h @@ -276,6 +276,7 @@ struct DileptonMC { Configurable cfg_max_relDPt_wrt_matchedMCHMID{"cfg_max_relDPt_wrt_matchedMCHMID", 1e+10f, "max. relative dpt between MFT-MCH-MID and MCH-MID"}; Configurable cfg_max_DEta_wrt_matchedMCHMID{"cfg_max_DEta_wrt_matchedMCHMID", 1e+10f, "max. deta between MFT-MCH-MID and MCH-MID"}; Configurable cfg_max_DPhi_wrt_matchedMCHMID{"cfg_max_DPhi_wrt_matchedMCHMID", 1e+10f, "max. dphi between MFT-MCH-MID and MCH-MID"}; + Configurable requireMFTHitMap{"requireMFTHitMap", false, "flag to apply MFT hit map"}; Configurable> requiredMFTDisks{"requiredMFTDisks", std::vector{0}, "hit map on MFT disks [0,1,2,3,4]. logical-OR of each double-sided disk"}; } dimuoncuts; @@ -720,7 +721,7 @@ struct DileptonMC { fDimuonCut.SetRabs(dimuoncuts.cfg_min_rabs, dimuoncuts.cfg_max_rabs); fDimuonCut.SetMaxPDCARabsDep([&](float rabs) { return (rabs < 26.5 ? 594.f : 324.f); }); fDimuonCut.SetMaxdPtdEtadPhiwrtMCHMID(dimuoncuts.cfg_max_relDPt_wrt_matchedMCHMID, dimuoncuts.cfg_max_DEta_wrt_matchedMCHMID, dimuoncuts.cfg_max_DPhi_wrt_matchedMCHMID); // this is relevant for global muons - fDimuonCut.SetMFTHitMap(dimuoncuts.requiredMFTDisks); + fDimuonCut.SetMFTHitMap(dimuoncuts.requireMFTHitMap, dimuoncuts.requiredMFTDisks); } template diff --git a/PWGEM/Dilepton/Core/DimuonCut.cxx b/PWGEM/Dilepton/Core/DimuonCut.cxx index 5ee3bf3d3bd..96f00f8b7a5 100644 --- a/PWGEM/Dilepton/Core/DimuonCut.cxx +++ b/PWGEM/Dilepton/Core/DimuonCut.cxx @@ -119,11 +119,14 @@ void DimuonCut::SetMaxPDCARabsDep(std::function RabsDepCut) mMaxPDCARabsDep = RabsDepCut; LOG(info) << "Dimuon Cut, set max pDCA as a function of Rabs: " << mMaxPDCARabsDep(10.0); } -void DimuonCut::SetMFTHitMap(std::vector hitMap) +void DimuonCut::SetMFTHitMap(bool flag, std::vector hitMap) { + mApplyMFTHitMap = flag; mRequiredMFTDisks = hitMap; - for (const auto& iDisk : mRequiredMFTDisks) { - LOG(info) << "Dimuon Cut, require MFT hit on Disk: " << iDisk; + if (mApplyMFTHitMap) { + for (const auto& iDisk : mRequiredMFTDisks) { + LOG(info) << "Dimuon Cut, require MFT hit on Disk: " << iDisk; + } } } void DimuonCut::SetMaxdPtdEtadPhiwrtMCHMID(float reldPtMax, float dEtaMax, float dPhiMax) diff --git a/PWGEM/Dilepton/Core/DimuonCut.h b/PWGEM/Dilepton/Core/DimuonCut.h index 34d8364f65b..b96afcd7c28 100644 --- a/PWGEM/Dilepton/Core/DimuonCut.h +++ b/PWGEM/Dilepton/Core/DimuonCut.h @@ -156,7 +156,7 @@ class DimuonCut : public TNamed if (!IsSelectedTrack(track, DimuonCuts::kRabs)) { return false; } - if (track.trackType() == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) && !IsSelectedTrack(track, DimuonCuts::kMFTHitMap)) { + if (mApplyMFTHitMap && track.trackType() == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) && !IsSelectedTrack(track, DimuonCuts::kMFTHitMap)) { return false; } if (track.trackType() == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) && !IsSelectedTrack(track, DimuonCuts::kDPtDEtaDPhiwrtMCHMID)) { @@ -243,7 +243,7 @@ class DimuonCut : public TNamed void SetDCAxy(float min, float max); // in cm void SetRabs(float min, float max); // in cm void SetMaxPDCARabsDep(std::function RabsDepCut); - void SetMFTHitMap(std::vector hitMap); + void SetMFTHitMap(bool flag, std::vector hitMap); void SetMaxdPtdEtadPhiwrtMCHMID(float reldPtMax, float dEtaMax, float dPhiMax); // this is relevant for global muons private: @@ -273,6 +273,7 @@ class DimuonCut : public TNamed float mMinRabs{17.6}, mMaxRabs{89.5}; float mMinDcaXY{0.0f}, mMaxDcaXY{1e10f}; float mMaxReldPtwrtMCHMID{1e10f}, mMaxdEtawrtMCHMID{1e10f}, mMaxdPhiwrtMCHMID{1e10f}; + bool mApplyMFTHitMap{false}; std::vector mRequiredMFTDisks{}; ClassDef(DimuonCut, 1); diff --git a/PWGEM/Dilepton/Core/SingleTrackQC.h b/PWGEM/Dilepton/Core/SingleTrackQC.h index 2fc94a8a91c..561e8a2adee 100644 --- a/PWGEM/Dilepton/Core/SingleTrackQC.h +++ b/PWGEM/Dilepton/Core/SingleTrackQC.h @@ -204,6 +204,7 @@ struct SingleTrackQC { Configurable cfg_max_relDPt_wrt_matchedMCHMID{"cfg_max_relDPt_wrt_matchedMCHMID", 1e+10f, "max. relative dpt between MFT-MCH-MID and MCH-MID"}; Configurable cfg_max_DEta_wrt_matchedMCHMID{"cfg_max_DEta_wrt_matchedMCHMID", 1e+10f, "max. deta between MFT-MCH-MID and MCH-MID"}; Configurable cfg_max_DPhi_wrt_matchedMCHMID{"cfg_max_DPhi_wrt_matchedMCHMID", 1e+10f, "max. dphi between MFT-MCH-MID and MCH-MID"}; + Configurable requireMFTHitMap{"requireMFTHitMap", false, "flag to apply MFT hit map"}; Configurable> requiredMFTDisks{"requiredMFTDisks", std::vector{0}, "hit map on MFT disks [0,1,2,3,4]. logical-OR of each double-sided disk"}; } dimuoncuts; @@ -458,7 +459,7 @@ struct SingleTrackQC { fDimuonCut.SetRabs(dimuoncuts.cfg_min_rabs, dimuoncuts.cfg_max_rabs); fDimuonCut.SetMaxPDCARabsDep([&](float rabs) { return (rabs < 26.5 ? 594.f : 324.f); }); fDimuonCut.SetMaxdPtdEtadPhiwrtMCHMID(dimuoncuts.cfg_max_relDPt_wrt_matchedMCHMID, dimuoncuts.cfg_max_DEta_wrt_matchedMCHMID, dimuoncuts.cfg_max_DPhi_wrt_matchedMCHMID); // this is relevant for global muons - fDimuonCut.SetMFTHitMap(dimuoncuts.requiredMFTDisks); + fDimuonCut.SetMFTHitMap(dimuoncuts.requireMFTHitMap, dimuoncuts.requiredMFTDisks); } template diff --git a/PWGEM/Dilepton/Core/SingleTrackQCMC.h b/PWGEM/Dilepton/Core/SingleTrackQCMC.h index 481bb2e9e5e..5fb15b4ec26 100644 --- a/PWGEM/Dilepton/Core/SingleTrackQCMC.h +++ b/PWGEM/Dilepton/Core/SingleTrackQCMC.h @@ -210,6 +210,7 @@ struct SingleTrackQCMC { Configurable cfg_max_relDPt_wrt_matchedMCHMID{"cfg_max_relDPt_wrt_matchedMCHMID", 1e+10f, "max. relative dpt between MFT-MCH-MID and MCH-MID"}; Configurable cfg_max_DEta_wrt_matchedMCHMID{"cfg_max_DEta_wrt_matchedMCHMID", 1e+10f, "max. deta between MFT-MCH-MID and MCH-MID"}; Configurable cfg_max_DPhi_wrt_matchedMCHMID{"cfg_max_DPhi_wrt_matchedMCHMID", 1e+10f, "max. dphi between MFT-MCH-MID and MCH-MID"}; + Configurable requireMFTHitMap{"requireMFTHitMap", false, "flag to apply MFT hit map"}; Configurable> requiredMFTDisks{"requiredMFTDisks", std::vector{0}, "hit map on MFT disks [0,1,2,3,4]. logical-OR of each double-sided disk"}; } dimuoncuts; @@ -517,7 +518,7 @@ struct SingleTrackQCMC { fDimuonCut.SetRabs(dimuoncuts.cfg_min_rabs, dimuoncuts.cfg_max_rabs); fDimuonCut.SetMaxPDCARabsDep([&](float rabs) { return (rabs < 26.5 ? 594.f : 324.f); }); fDimuonCut.SetMaxdPtdEtadPhiwrtMCHMID(dimuoncuts.cfg_max_relDPt_wrt_matchedMCHMID, dimuoncuts.cfg_max_DEta_wrt_matchedMCHMID, dimuoncuts.cfg_max_DPhi_wrt_matchedMCHMID); // this is relevant for global muons - fDimuonCut.SetMFTHitMap(dimuoncuts.requiredMFTDisks); + fDimuonCut.SetMFTHitMap(dimuoncuts.requireMFTHitMap, dimuoncuts.requiredMFTDisks); } template From 4cc3902a125b35262780f73cfaeabe6ec3a47e5c Mon Sep 17 00:00:00 2001 From: Rrantu <156880782+Rrantu@users.noreply.github.com> Date: Wed, 11 Jun 2025 07:48:54 +0800 Subject: [PATCH 019/871] [PWGHF] Add Xic0 flow task and fix previous O2 linter issues (#11533) --- PWGHF/D2H/Tasks/taskFlowCharmHadrons.cxx | 158 +++++++++++++++++------ 1 file changed, 117 insertions(+), 41 deletions(-) diff --git a/PWGHF/D2H/Tasks/taskFlowCharmHadrons.cxx b/PWGHF/D2H/Tasks/taskFlowCharmHadrons.cxx index 862b4910c72..03e475bc7ed 100644 --- a/PWGHF/D2H/Tasks/taskFlowCharmHadrons.cxx +++ b/PWGHF/D2H/Tasks/taskFlowCharmHadrons.cxx @@ -14,6 +14,7 @@ /// /// \author S. Politanò, INFN Torino, Italy /// \author Wu Chuntai, CUG, China +/// \author Ran Tu, Fudan University, China #include #include @@ -48,7 +49,8 @@ enum DecayChannel { DplusToPiKPi = 0, LcToPKPi, LcToPiKP, XicToPKPi, - XicToPiKP + XicToPiKP, + Xic0ToXiPi }; enum QvecEstimator { FV0A = 0, @@ -75,25 +77,11 @@ struct HfTaskFlowCharmHadrons { Configurable ccdbUrl{"ccdbUrl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; Configurable> classMl{"classMl", {0, 2}, "Indexes of BDT scores to be stored. Two indexes max."}; - ConfigurableAxis thnConfigAxisInvMass{"thnConfigAxisInvMass", {100, 1.78, 2.05}, ""}; - ConfigurableAxis thnConfigAxisPt{"thnConfigAxisPt", {10, 0., 10.}, ""}; - ConfigurableAxis thnConfigAxisCent{"thnConfigAxisCent", {10000, 0., 100.}, ""}; - ConfigurableAxis thnConfigAxisCosNPhi{"thnConfigAxisCosNPhi", {100, -1., 1.}, ""}; - ConfigurableAxis thnConfigAxisPsi{"thnConfigAxisPsi", {6000, 2. * TMath::Pi(), 2. * TMath::Pi()}, ""}; - ConfigurableAxis thnConfigAxisCosDeltaPhi{"thnConfigAxisCosDeltaPhi", {100, -1., 1.}, ""}; - ConfigurableAxis thnConfigAxisScalarProd{"thnConfigAxisScalarProd", {100, 0., 1.}, ""}; - ConfigurableAxis thnConfigAxisMlOne{"thnConfigAxisMlOne", {1000, 0., 1.}, ""}; - ConfigurableAxis thnConfigAxisMlTwo{"thnConfigAxisMlTwo", {1000, 0., 1.}, ""}; - ConfigurableAxis thnConfigAxisOccupancyITS{"thnConfigAxisOccupancyITS", {14, 0, 14000}, ""}; - ConfigurableAxis thnConfigAxisOccupancyFT0C{"thnConfigAxisOccupancyFT0C", {14, 0, 140000}, ""}; - ConfigurableAxis thnConfigAxisNoSameBunchPileup{"thnConfigAxisNoSameBunchPileup", {2, 0, 2}, ""}; - ConfigurableAxis thnConfigAxisOccupancy{"thnConfigAxisOccupancy", {2, 0, 2}, ""}; - ConfigurableAxis thnConfigAxisNoCollInTimeRangeNarrow{"thnConfigAxisNoCollInTimeRangeNarrow", {2, 0, 2}, ""}; - ConfigurableAxis thnConfigAxisNoCollInTimeRangeStandard{"thnConfigAxisNoCollInTimeRangeStandard", {2, 0, 2}, ""}; - ConfigurableAxis thnConfigAxisNoCollInRofStandard{"thnConfigAxisNoCollInRofStandard", {2, 0, 2}, ""}; - ConfigurableAxis thnConfigAxisResoFT0cFV0a{"thnConfigAxisResoFT0cFV0a", {160, -8, 8}, ""}; - ConfigurableAxis thnConfigAxisResoFT0cTPCtot{"thnConfigAxisResoFT0cTPCtot", {160, -8, 8}, ""}; - ConfigurableAxis thnConfigAxisResoFV0aTPCtot{"thnConfigAxisResoFV0aTPCtot", {160, -8, 8}, ""}; + HfHelper hfHelper; + EventPlaneHelper epHelper; + HfEventSelection hfEvSel; // event selection and monitoring + o2::framework::Service ccdb; + SliceCache cache; using CandDsDataWMl = soa::Filtered>; using CandDsData = soa::Filtered>; @@ -103,6 +91,8 @@ struct HfTaskFlowCharmHadrons { using CandLcDataWMl = soa::Filtered>; using CandXicData = soa::Filtered>; using CandXicDataWMl = soa::Filtered>; + using CandXic0Data = soa::Filtered>; + using CandXic0DataWMl = soa::Filtered>; using CandD0DataWMl = soa::Filtered>; using CandD0Data = soa::Filtered>; using CollsWithQvecs = soa::Join; @@ -112,6 +102,7 @@ struct HfTaskFlowCharmHadrons { Filter filterSelectD0Candidates = aod::hf_sel_candidate_d0::isSelD0 >= selectionFlag || aod::hf_sel_candidate_d0::isSelD0bar >= selectionFlag; Filter filterSelectLcCandidates = aod::hf_sel_candidate_lc::isSelLcToPKPi >= selectionFlag || aod::hf_sel_candidate_lc::isSelLcToPiKP >= selectionFlag; Filter filterSelectXicCandidates = aod::hf_sel_candidate_xic::isSelXicToPKPi >= selectionFlag || aod::hf_sel_candidate_xic::isSelXicToPiKP >= selectionFlag; + Filter filterSelectXic0Candidates = aod::hf_sel_toxipi::resultSelections >= selectionFlag; Partition selectedDsToKKPi = aod::hf_sel_candidate_ds::isSelDsToKKPi >= selectionFlag; Partition selectedDsToPiKK = aod::hf_sel_candidate_ds::isSelDsToPiKK >= selectionFlag; @@ -129,12 +120,28 @@ struct HfTaskFlowCharmHadrons { Partition selectedXicToPiKP = aod::hf_sel_candidate_xic::isSelXicToPiKP >= selectionFlag; Partition selectedXicToPKPiWMl = aod::hf_sel_candidate_xic::isSelXicToPKPi >= selectionFlag; Partition selectedXicToPiKPWMl = aod::hf_sel_candidate_xic::isSelXicToPiKP >= selectionFlag; + Partition selectedXic0 = aod::hf_sel_toxipi::resultSelections >= selectionFlag; + Partition selectedXic0WMl = aod::hf_sel_toxipi::resultSelections >= selectionFlag; - SliceCache cache; - HfHelper hfHelper; - EventPlaneHelper epHelper; - HfEventSelection hfEvSel; // event selection and monitoring - o2::framework::Service ccdb; + ConfigurableAxis thnConfigAxisInvMass{"thnConfigAxisInvMass", {100, 1.78, 2.05}, ""}; + ConfigurableAxis thnConfigAxisPt{"thnConfigAxisPt", {10, 0., 10.}, ""}; + ConfigurableAxis thnConfigAxisCent{"thnConfigAxisCent", {10000, 0., 100.}, ""}; + ConfigurableAxis thnConfigAxisCosNPhi{"thnConfigAxisCosNPhi", {100, -1., 1.}, ""}; + ConfigurableAxis thnConfigAxisPsi{"thnConfigAxisPsi", {6000, 0, constants::math::TwoPI}, ""}; + ConfigurableAxis thnConfigAxisCosDeltaPhi{"thnConfigAxisCosDeltaPhi", {100, -1., 1.}, ""}; + ConfigurableAxis thnConfigAxisScalarProd{"thnConfigAxisScalarProd", {100, 0., 1.}, ""}; + ConfigurableAxis thnConfigAxisMlOne{"thnConfigAxisMlOne", {1000, 0., 1.}, ""}; + ConfigurableAxis thnConfigAxisMlTwo{"thnConfigAxisMlTwo", {1000, 0., 1.}, ""}; + ConfigurableAxis thnConfigAxisOccupancyITS{"thnConfigAxisOccupancyITS", {14, 0, 14000}, ""}; + ConfigurableAxis thnConfigAxisOccupancyFT0C{"thnConfigAxisOccupancyFT0C", {14, 0, 140000}, ""}; + ConfigurableAxis thnConfigAxisNoSameBunchPileup{"thnConfigAxisNoSameBunchPileup", {2, 0, 2}, ""}; + ConfigurableAxis thnConfigAxisOccupancy{"thnConfigAxisOccupancy", {2, 0, 2}, ""}; + ConfigurableAxis thnConfigAxisNoCollInTimeRangeNarrow{"thnConfigAxisNoCollInTimeRangeNarrow", {2, 0, 2}, ""}; + ConfigurableAxis thnConfigAxisNoCollInTimeRangeStandard{"thnConfigAxisNoCollInTimeRangeStandard", {2, 0, 2}, ""}; + ConfigurableAxis thnConfigAxisNoCollInRofStandard{"thnConfigAxisNoCollInRofStandard", {2, 0, 2}, ""}; + ConfigurableAxis thnConfigAxisResoFT0cFV0a{"thnConfigAxisResoFT0cFV0a", {160, -8, 8}, ""}; + ConfigurableAxis thnConfigAxisResoFT0cTPCtot{"thnConfigAxisResoFT0cTPCtot", {160, -8, 8}, ""}; + ConfigurableAxis thnConfigAxisResoFV0aTPCtot{"thnConfigAxisResoFV0aTPCtot", {160, -8, 8}, ""}; HistogramRegistry registry{"registry", {}}; @@ -231,15 +238,15 @@ struct HfTaskFlowCharmHadrons { } if (storeResoOccu) { - std::vector axes_reso = {thnAxisCent, thnAxisResoFT0cFV0a, thnAxisResoFT0cTPCtot, thnAxisResoFV0aTPCtot}; + std::vector axesReso = {thnAxisCent, thnAxisResoFT0cFV0a, thnAxisResoFT0cTPCtot, thnAxisResoFV0aTPCtot}; if (occEstimator == 1) { - axes_reso.insert(axes_reso.end(), {thnAxisOccupancyITS, thnAxisNoSameBunchPileup, thnAxisOccupancy, - thnAxisNoCollInTimeRangeNarrow, thnAxisNoCollInTimeRangeStandard, thnAxisNoCollInRofStandard}); + axesReso.insert(axesReso.end(), {thnAxisOccupancyITS, thnAxisNoSameBunchPileup, thnAxisOccupancy, + thnAxisNoCollInTimeRangeNarrow, thnAxisNoCollInTimeRangeStandard, thnAxisNoCollInRofStandard}); } else { - axes_reso.insert(axes_reso.end(), {thnAxisOccupancyFT0C, thnAxisNoSameBunchPileup, thnAxisOccupancy, - thnAxisNoCollInTimeRangeNarrow, thnAxisNoCollInTimeRangeStandard, thnAxisNoCollInRofStandard}); + axesReso.insert(axesReso.end(), {thnAxisOccupancyFT0C, thnAxisNoSameBunchPileup, thnAxisOccupancy, + thnAxisNoCollInTimeRangeNarrow, thnAxisNoCollInTimeRangeStandard, thnAxisNoCollInRofStandard}); } - registry.add("spReso/hSparseReso", "THn for resolution with occupancy", HistType::kTHnSparseF, axes_reso); + registry.add("spReso/hSparseReso", "THn for resolution with occupancy", HistType::kTHnSparseF, axesReso); } hfEvSel.addHistograms(registry); // collision monitoring @@ -285,6 +292,44 @@ struct HfTaskFlowCharmHadrons { } } + /// Compute the Q vector for the candidate's tracks + /// \param cand is the candidate + /// \param tracksQx is the X component of the Q vector for the tracks + /// \param tracksQy is the Y component of the Q vector for the tracks + /// \param channel is the decay channel + template + void getQvecXic0Tracks(const T1& cand, + std::vector& tracksQx, + std::vector& tracksQy, + float ampl) + { + // add possibility to consider different weights for the tracks, at the moment only pT is considered; + float pXTrack0 = cand.pxPosV0Dau(); + float pYTrack0 = cand.pyPosV0Dau(); + float pTTrack0 = std::hypot(pXTrack0, pYTrack0); + float phiTrack0 = std::atan2(pXTrack0, pYTrack0); + float pXTrack1 = cand.pxNegV0Dau(); + float pYTrack1 = cand.pyNegV0Dau(); + float pTTrack1 = std::hypot(pXTrack1, pYTrack1); + float phiTrack1 = std::atan2(pXTrack1, pYTrack1); + float pYTrack2 = cand.pxBachFromCasc(); + float pXTrack2 = cand.pyBachFromCasc(); + float pTTrack2 = std::hypot(pXTrack2, pYTrack2); + float phiTrack2 = std::atan2(pXTrack2, pYTrack2); + float pXTrack3 = cand.pxBachFromCharmBaryon(); + float pYTrack3 = cand.pyBachFromCharmBaryon(); + float pTTrack3 = std::hypot(pXTrack3, pYTrack3); + float phiTrack3 = std::atan2(pXTrack3, pYTrack3); + + tracksQx.push_back(std::cos(harmonic * phiTrack0) * pTTrack0 / ampl); + tracksQy.push_back(std::sin(harmonic * phiTrack0) * pTTrack0 / ampl); + tracksQx.push_back(std::cos(harmonic * phiTrack1) * pTTrack1 / ampl); + tracksQy.push_back(std::sin(harmonic * phiTrack1) * pTTrack1 / ampl); + tracksQx.push_back(std::cos(harmonic * phiTrack2) * pTTrack2 / ampl); + tracksQy.push_back(std::sin(harmonic * phiTrack2) * pTTrack2 / ampl); + tracksQx.push_back(std::cos(harmonic * phiTrack3) * pTTrack3 / ampl); + tracksQy.push_back(std::sin(harmonic * phiTrack3) * pTTrack3 / ampl); + } /// Compute the delta psi in the range [0, pi/harmonic] /// \param psi1 is the first angle /// \param psi2 is the second angle @@ -292,12 +337,7 @@ struct HfTaskFlowCharmHadrons { float getDeltaPsiInRange(float psi1, float psi2) { float deltaPsi = psi1 - psi2; - if (std::abs(deltaPsi) > constants::math::PI / harmonic) { - if (deltaPsi > 0.) - deltaPsi -= constants::math::TwoPI / harmonic; - else - deltaPsi += constants::math::TwoPI / harmonic; - } + deltaPsi = RecoDecay::constrainAngle(deltaPsi, -o2::constants::math::PI / harmonic, harmonic); return deltaPsi; } @@ -552,18 +592,36 @@ struct HfTaskFlowCharmHadrons { default: break; } + } else if constexpr (std::is_same_v || std::is_same_v) { + massCand = candidate.invMassCharmBaryon(); + if constexpr (std::is_same_v) { + for (unsigned int iclass = 0; iclass < classMl->size(); iclass++) + outputMl[iclass] = candidate.mlProbToXiPi()[classMl->at(iclass)]; + } } - float ptCand = candidate.pt(); - float phiCand = candidate.phi(); + float ptCand = 0.; + float phiCand = 0.; + + if constexpr (std::is_same_v || std::is_same_v) { + ptCand = candidate.kfptXic(); + phiCand = std::atan2(candidate.pxCharmBaryon(), candidate.pyCharmBaryon()); + } else { + ptCand = candidate.pt(); + phiCand = candidate.phi(); + } // If TPC is used for the SP estimation, the tracks of the hadron candidate must be removed from the TPC Q vector to avoid double counting if (qvecDetector == QvecEstimator::TPCNeg || qvecDetector == QvecEstimator::TPCPos) { float ampl = amplQVec - static_cast(nProngs); std::vector tracksQx = {}; std::vector tracksQy = {}; - - getQvecDtracks(candidate, tracksQx, tracksQy, ampl); + if constexpr (std::is_same_v || std::is_same_v) { + // std::cout<(candidate, tracksQx, tracksQy, ampl); + } for (auto iTrack{0u}; iTrack < tracksQx.size(); ++iTrack) { xQVec -= tracksQx[iTrack]; yQVec -= tracksQy[iTrack]; @@ -683,6 +741,24 @@ struct HfTaskFlowCharmHadrons { } PROCESS_SWITCH(HfTaskFlowCharmHadrons, processXic, "Process Xic candidates", false); + // Xic0 with ML + void processXic0Ml(CollsWithQvecs::iterator const& collision, + CandXic0DataWMl const&) + { + auto candsXic0WMl = selectedXic0WMl->sliceByCached(aod::hf_cand::collisionId, collision.globalIndex(), cache); + runFlowAnalysis(collision, candsXic0WMl); + } + PROCESS_SWITCH(HfTaskFlowCharmHadrons, processXic0Ml, "Process Xic0 candidates with ML", false); + + // Xic0 + void processXic0(CollsWithQvecs::iterator const& collision, + CandXic0Data const&) + { + auto candsXic0 = selectedXic0->sliceByCached(aod::hf_cand::collisionId, collision.globalIndex(), cache); + runFlowAnalysis(collision, candsXic0); + } + PROCESS_SWITCH(HfTaskFlowCharmHadrons, processXic0, "Process Xic0 candidates", false); + // Resolution void processResolution(CollsWithQvecs::iterator const& collision, aod::BCsWithTimestamps const& bcs) From 06e8c9eb4b632cb73ee21599f0d966c2578a9e52 Mon Sep 17 00:00:00 2001 From: Felix Schlepper Date: Wed, 11 Jun 2025 03:19:37 +0200 Subject: [PATCH 020/871] [ALICE3] do not include internal ITS code (#11539) Co-authored-by: ALICE Action Bot --- ALICE3/TableProducer/OTF/onTheFlyTracker.cxx | 62 +++++++++----------- 1 file changed, 28 insertions(+), 34 deletions(-) diff --git a/ALICE3/TableProducer/OTF/onTheFlyTracker.cxx b/ALICE3/TableProducer/OTF/onTheFlyTracker.cxx index ff804b8485a..c858f5a753e 100644 --- a/ALICE3/TableProducer/OTF/onTheFlyTracker.cxx +++ b/ALICE3/TableProducer/OTF/onTheFlyTracker.cxx @@ -23,48 +23,42 @@ /// \author Roberto Preghenella preghenella@bo.infn.it /// -#include -#include -#include -#include -#include - -#include -#include -#include -#include +#include "ALICE3/Core/DelphesO2TrackSmearer.h" +#include "ALICE3/Core/DetLayer.h" +#include "ALICE3/Core/FastTracker.h" +#include "ALICE3/Core/TrackUtilities.h" +#include "ALICE3/DataModel/OTFStrangeness.h" +#include "ALICE3/DataModel/collisionAlice3.h" +#include "ALICE3/DataModel/tracksAlice3.h" +#include "Common/Core/RecoDecay.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "CommonConstants/MathConstants.h" +#include "DCAFitter/DCAFitterN.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "DetectorsBase/Propagator.h" +#include "DetectorsVertexing/PVertexer.h" +#include "DetectorsVertexing/PVertexerHelpers.h" +#include "Field/MagneticField.h" #include "Framework/AnalysisDataModel.h" #include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" #include "Framework/HistogramRegistry.h" -#include -#include "DCAFitter/DCAFitterN.h" -#include "Common/Core/RecoDecay.h" #include "Framework/O2DatabasePDGPlugin.h" -#include "Common/DataModel/TrackSelectionTables.h" +#include "Framework/runDataProcessing.h" #include "ReconstructionDataFormats/DCA.h" -#include "DetectorsBase/Propagator.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "DetectorsVertexing/PVertexer.h" -#include "DetectorsVertexing/PVertexerHelpers.h" #include "SimulationDataFormat/InteractionSampler.h" -#include "Field/MagneticField.h" -#include "ITSMFTSimulation/Hit.h" -#include "ITStracking/Configuration.h" -#include "ITStracking/IOUtils.h" -#include "ITStracking/Tracker.h" -#include "ITStracking/Vertexer.h" -#include "ITStracking/VertexerTraits.h" +#include +#include +#include +#include +#include -#include "ALICE3/Core/DelphesO2TrackSmearer.h" -#include "ALICE3/Core/FastTracker.h" -#include "ALICE3/Core/DetLayer.h" -#include "ALICE3/Core/TrackUtilities.h" -#include "ALICE3/DataModel/collisionAlice3.h" -#include "ALICE3/DataModel/tracksAlice3.h" -#include "ALICE3/DataModel/OTFStrangeness.h" +#include +#include +#include +#include +#include using namespace o2; using namespace o2::framework; @@ -808,7 +802,7 @@ struct OnTheFlyTracker { std::array posClusterCandidate; trackParCov.getXYZGlo(posClusterCandidate); float r{std::hypot(posClusterCandidate[0], posClusterCandidate[1])}; - float phi{std::atan2(-posClusterCandidate[1], -posClusterCandidate[0]) + o2::its::constants::math::Pi}; + float phi{std::atan2(-posClusterCandidate[1], -posClusterCandidate[0]) + o2::constants::math::PI}; o2::fastsim::DetLayer currentTrackingLayer = fastTracker.GetLayer(i); if (currentTrackingLayer.getResolutionRPhi() > 1e-8 && currentTrackingLayer.getResolutionZ() > 1e-8) { // catch zero (though should not really happen...) From 862bdf2223badc9265b6874a6ea6d81f1a382bc5 Mon Sep 17 00:00:00 2001 From: aimeric-landou <46970521+aimeric-landou@users.noreply.github.com> Date: Wed, 11 Jun 2025 11:13:34 +0200 Subject: [PATCH 021/871] [Common] Common - add trackdcacov table producer for Run2 converted data (#11434) --- Common/TableProducer/CMakeLists.txt | 5 + .../TableProducer/trackDcaCovFillerRun2.cxx | 179 ++++++++++++++++++ 2 files changed, 184 insertions(+) create mode 100644 Common/TableProducer/trackDcaCovFillerRun2.cxx diff --git a/Common/TableProducer/CMakeLists.txt b/Common/TableProducer/CMakeLists.txt index 042bd643d3e..1d6918d6121 100644 --- a/Common/TableProducer/CMakeLists.txt +++ b/Common/TableProducer/CMakeLists.txt @@ -62,6 +62,11 @@ o2physics_add_dpl_workflow(track-propagation PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(track-dca-cov-filler-run2 + SOURCES trackDcaCovFillerRun2.cxx + PUBLIC_LINK_LIBRARIES O2::DetectorsBase O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(track-propagation-tester SOURCES trackPropagationTester.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::trackSelectionRequest diff --git a/Common/TableProducer/trackDcaCovFillerRun2.cxx b/Common/TableProducer/trackDcaCovFillerRun2.cxx new file mode 100644 index 00000000000..d07833ae9e0 --- /dev/null +++ b/Common/TableProducer/trackDcaCovFillerRun2.cxx @@ -0,0 +1,179 @@ +// 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 trackDcaCovFillerRun2.cxx +/// \author Aimeric Landou , CERN +/// \brief Fills DCA and DCA Cov tables for Run 2 tracks +// Run 2 AO2Ds cannot have their dcacov filled by the current track-propagation workflow as the workflow isn't designed for them, given Run 2 tracks are already propagated to the PV. +// This task fills the DCA Cov (and DCA) tables for Run 2 tracks by "propagating" the tracks (though given they are already at the PV it doesn't actually do the propagation) and retrieving the DCA and DCA cov given by the propagateToDCABxByBz function + +#include + +#include "TableHelper.h" +#include "Common/Tools/TrackTuner.h" +#include "DataFormatsParameters/GRPObject.h" + +using namespace o2; +using namespace o2::framework; +// using namespace o2::framework::expressions; + +struct TrackDcaCovFillerRun2 { + Produces tracksDCA; + Produces tracksDCACov; + + // Produces tunertable; + + Service ccdb; + + bool fillTracksDCA = false; + bool fillTracksDCACov = false; + int runNumber = -1; + + o2::base::Propagator::MatCorrType matCorr = o2::base::Propagator::MatCorrType::USEMatCorrNONE; + + const o2::dataformats::MeanVertexObject* mMeanVtx = nullptr; + o2::parameters::GRPMagField* grpmag = nullptr; + o2::base::MatLayerCylSet* lut = nullptr; + + Configurable ccdburl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable ccdbPathGrp{"ccdbPathGrp", "GLO/GRP/GRP", "CCDB path of the grp file (run2)"}; + Configurable mVtxPath{"mVtxPath", "GLO/Calib/MeanVertex", "Path of the mean vertex file"}; + + HistogramRegistry registry{"registry"}; + + void init(o2::framework::InitContext& initContext) + { + // Checking if the tables are requested in the workflow and enabling them + fillTracksDCA = isTableRequiredInWorkflow(initContext, "TracksDCA"); + fillTracksDCACov = isTableRequiredInWorkflow(initContext, "TracksDCACov"); + + ccdb->setURL(ccdburl); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + } + + void initCCDB(aod::BCsWithTimestamps::iterator const& bc) + { + if (runNumber == bc.runNumber()) { + return; + } + + // Run 2 GRP object + o2::parameters::GRPObject* grpo = ccdb->getForTimeStamp(ccdbPathGrp, bc.timestamp()); + if (grpo == nullptr) { + LOGF(fatal, "Run 2 GRP object (type o2::parameters::GRPObject) is not available in CCDB for run=%d at timestamp=%llu", bc.runNumber(), bc.timestamp()); + } + o2::base::Propagator::initFieldFromGRP(grpo); + LOGF(info, "Setting magnetic field to %d kG for run %d from its GRP CCDB object (type o2::parameters::GRPObject)", grpo->getNominalL3Field(), bc.runNumber()); + + mMeanVtx = ccdb->getForTimeStamp(mVtxPath, bc.timestamp()); + runNumber = bc.runNumber(); + } + + // Running variables + std::array mDcaInfo; + o2::dataformats::DCA mDcaInfoCov; + o2::dataformats::VertexBase mVtx; + o2::track::TrackParametrization mTrackPar; + o2::track::TrackParametrizationWithError mTrackParCov; + + template + void fillTrackTables(TTrack const& tracks, + TParticle const&, + aod::Collisions const&, + aod::BCsWithTimestamps const& bcs) + { + if (bcs.size() == 0) { + return; + } + initCCDB(bcs.begin()); + + if constexpr (fillCovMat) { + if (fillTracksDCACov) { + tracksDCACov.reserve(tracks.size()); + } + } else { + if (fillTracksDCA) { + tracksDCA.reserve(tracks.size()); + } + } + + for (auto const& track : tracks) { + if constexpr (fillCovMat) { + if (fillTracksDCA || fillTracksDCACov) { + mDcaInfoCov.set(999, 999, 999, 999, 999); + } + setTrackParCov(track, mTrackParCov); + } else { + if (fillTracksDCA) { + mDcaInfo[0] = 999; + mDcaInfo[1] = 999; + } + setTrackPar(track, mTrackPar); + } + + if (track.has_collision()) { + auto const& collision = track.collision(); + if constexpr (fillCovMat) { + 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, matCorr, &mDcaInfoCov); + } else { + o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, mTrackPar, 2.f, matCorr, &mDcaInfo); + } + } else { + if constexpr (fillCovMat) { + mVtx.setPos({mMeanVtx->getX(), mMeanVtx->getY(), mMeanVtx->getZ()}); + mVtx.setCov(mMeanVtx->getSigmaX() * mMeanVtx->getSigmaX(), 0.0f, mMeanVtx->getSigmaY() * mMeanVtx->getSigmaY(), 0.0f, 0.0f, mMeanVtx->getSigmaZ() * mMeanVtx->getSigmaZ()); + o2::base::Propagator::Instance()->propagateToDCABxByBz(mVtx, mTrackParCov, 2.f, matCorr, &mDcaInfoCov); + } else { + o2::base::Propagator::Instance()->propagateToDCABxByBz({mMeanVtx->getX(), mMeanVtx->getY(), mMeanVtx->getZ()}, mTrackPar, 2.f, matCorr, &mDcaInfo); + } + } + + if constexpr (fillCovMat) { + if (fillTracksDCA) { + tracksDCA(mDcaInfoCov.getY(), mDcaInfoCov.getZ()); + } + if (fillTracksDCACov) { + tracksDCACov(mDcaInfoCov.getSigmaY2(), mDcaInfoCov.getSigmaZ2()); + } + } else { + if (fillTracksDCA) { + tracksDCA(mDcaInfo[0], mDcaInfo[1]); + } + } + } + } + + void processCovariance(soa::Join const& tracks, aod::Collisions const& collisions, aod::BCsWithTimestamps const& bcs) + { + fillTrackTables, /*Particle*/ soa::Join, /*isMc = */ false, /*fillCovMat =*/true>(tracks, tracks, collisions, bcs); + } + PROCESS_SWITCH(TrackDcaCovFillerRun2, processCovariance, "Process with covariance", false); + + void processStandard(soa::Join const& tracks, aod::Collisions const& collisions, aod::BCsWithTimestamps const& bcs) + { + fillTrackTables, /*Particle*/ soa::Join, /*isMc = */ false, /*fillCovMat =*/false>(tracks, tracks, collisions, bcs); + } + PROCESS_SWITCH(TrackDcaCovFillerRun2, processStandard, "Process without covariance", true); +}; + +//**************************************************************************************** +/** + * Workflow definition. + */ +//**************************************************************************************** +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + WorkflowSpec workflow{adaptAnalysisTask(cfgc)}; + return workflow; +} From 64b985131da0d1eb99bc6c2a42fdaff5e86f2a0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Josu=C3=A9=20Mart=C3=ADnez=20Garc=C3=ADa?= Date: Wed, 11 Jun 2025 03:32:37 -0600 Subject: [PATCH 022/871] [PWGUD] : Fixing the runtime overhead (#11532) --- PWGUD/Tasks/upcPhotonuclearAnalysisJMG.cxx | 49 ++++++++++++++-------- 1 file changed, 32 insertions(+), 17 deletions(-) diff --git a/PWGUD/Tasks/upcPhotonuclearAnalysisJMG.cxx b/PWGUD/Tasks/upcPhotonuclearAnalysisJMG.cxx index eb16b83f315..d20a78429dd 100644 --- a/PWGUD/Tasks/upcPhotonuclearAnalysisJMG.cxx +++ b/PWGUD/Tasks/upcPhotonuclearAnalysisJMG.cxx @@ -100,7 +100,8 @@ struct upcPhotonuclearAnalysisJMG { HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; // Declare configurables on events/collisions - Configurable nEvenstMixed{"nEvenstMixed", 3, {"Events to be Mixed"}}; + Configurable nEventsMixed{"nEventsMixed", 3, {"Events to be Mixed"}}; + Configurable factorEventsMixed{"factorEventsMixed", 100, {"factorEventsMixed to events mixed"}}; Configurable myZVtxCut{"myZVtxCut", 10., {"My collision cut"}}; Configurable myTimeZNACut{"myTimeZNACut", 2., {"My collision cut"}}; Configurable myTimeZNCCut{"myTimeZNCCut", 2., {"My collision cut"}}; @@ -275,23 +276,18 @@ struct upcPhotonuclearAnalysisJMG { mixedGapSideC.setObject(new CorrelationContainer("mixedEventGapSideC", "mixedEventGapSideC", corrAxis, effAxis, {})); } - std::vector vtxBinsEdges{VARIABLE_WIDTH, -10.0f, -5.0f, 0.0f, 5.0f, 10.0f}; + std::vector vtxBinsEdges{VARIABLE_WIDTH, -10.0f, -7.0f, -5.0f, -2.5f, 0.0f, 2.5f, 5.0f, 7.0f, 10.0f}; std::vector gapSideBinsEdges{VARIABLE_WIDTH, -0.5, 0.5, 1.5}; SliceCache cache; + int countGapA = 0; + int countGapC = 0; // Binning only on PosZ without multiplicity // using BinningType = ColumnBinningPolicy; using BinningType = ColumnBinningPolicy; - BinningType bindingOnVtx{{vtxBinsEdges, {gapSideBinsEdges}}, true}; - SameKindPair pairs{bindingOnVtx, nEvenstMixed, -1, &cache}; - - // ColumnBinningPolicy bindingOnVtx{{vtxBinsEdges, multBinsEdges}, true}; - - // SameKindPair, - // FullUDTracks, - // ColumnBinningPolicy> - // pair{bindingOnVtx, 5, -1, &cache}; + BinningType bindingOnVtx{{vtxBinsEdges, gapSideBinsEdges}, true}; + SameKindPair pairs{bindingOnVtx, nEventsMixed, -1, &cache}; template bool isCollisionCutSG(CSG const& collision, int SideGap) @@ -584,7 +580,8 @@ struct upcPhotonuclearAnalysisJMG { if (fillCollisionUD(sameGapSideC, multiplicity) == false) { return; } - // LOGF(debug, "Filling sameGapSideC events"); + histos.fill(HIST("eventcount"), -1); + // LOGF(info, "Filling sameGapSideC events"); fillCorrelationsUD(sameGapSideC, reconstructedTracks, reconstructedTracks, multiplicity, reconstructedCollision.posZ()); break; default: @@ -601,18 +598,34 @@ struct upcPhotonuclearAnalysisJMG { // int sgSide = reconstructedCollision.gapSide(); // int sgSide = 0; + int maxCountGapA = 0; + int maxCountGapC = 0; + + if (auto histEventCount = histos.get(HIST("eventcount"))) { + int binA = histEventCount->GetXaxis()->FindBin(-2); // Gap A + int binC = histEventCount->GetXaxis()->FindBin(-1); // Gap C + + maxCountGapA = histEventCount->GetBinContent(binA) * factorEventsMixed; + maxCountGapC = histEventCount->GetBinContent(binC) * factorEventsMixed; + } + for (const auto& [collision1, tracks1, collision2, tracks2] : pairs) { if (collision1.size() == 0 || collision2.size() == 0) { - // LOGF(debug, "One or both collisions are empty."); + // LOGF(info, "One or both collisions are empty."); continue; } + if (countGapA >= maxCountGapA && countGapC >= maxCountGapC) { + break; + } float multiplicity = 0; if (collision1.gapSide() == 0 && collision2.gapSide() == 0) { // gap on side A if (isCollisionCutSG(collision1, 0) == false && isCollisionCutSG(collision2, 0) == false) { continue; } - // LOGF(debug, "In the pairs loop, gap side A"); + // std::cout << "Counts for Gap A: " << countGapA << " Maximum Count for Gap A " << maxCountGapA << std::endl; + ++countGapA; + // LOGF(info, "In the pairs loop, gap side A"); multiplicity = tracks1.size(); if (fillCollisionUD(mixedGapSideA, multiplicity) == false) { return; @@ -620,20 +633,22 @@ struct upcPhotonuclearAnalysisJMG { // histos.fill(HIST("eventcount"), bindingOnVtx.getBin({collision1.posZ()})); histos.fill(HIST("eventcount"), bindingOnVtx.getBin({collision1.posZ(), collision1.gapSide()})); fillCorrelationsUD(mixedGapSideA, tracks1, tracks2, multiplicity, collision1.posZ()); - // LOGF(debug, "Filling mixedGapSideA events, Gap for side A"); + // LOGF(info, "Filling mixedGapSideA events, Gap for side A"); } if (collision1.gapSide() == 1 && collision2.gapSide() == 1) { // gap on side C if (isCollisionCutSG(collision1, 1) == false && isCollisionCutSG(collision2, 1) == false) { continue; } - // LOGF(debug, "In the pairs loop, gap side C"); + // std::cout << "Counts for Gap C: " << countGapC << " Maximum Count for Gap C" << maxCountGapC << std::endl; + ++countGapC; + // LOGF(info, "In the pairs loop, gap side C"); multiplicity = tracks1.size(); if (fillCollisionUD(mixedGapSideC, multiplicity) == false) { return; } fillCorrelationsUD(mixedGapSideC, tracks1, tracks2, multiplicity, collision1.posZ()); - // LOGF(debug, "Filling mixedGapSideC events, Gap for side C"); + // LOGF(info, "Filling mixedGapSideC events, Gap for side C"); } else { continue; } From 9ff5d35e167f4e81115f3e4afcf02378e4fe80f9 Mon Sep 17 00:00:00 2001 From: Maximiliano Puccio Date: Wed, 11 Jun 2025 22:31:36 +0800 Subject: [PATCH 023/871] [Trigger] Add macro to inspect trigger menu per run (#11544) --- EventFiltering/macros/getMenu.C | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 EventFiltering/macros/getMenu.C diff --git a/EventFiltering/macros/getMenu.C b/EventFiltering/macros/getMenu.C new file mode 100644 index 00000000000..692ebe396f3 --- /dev/null +++ b/EventFiltering/macros/getMenu.C @@ -0,0 +1,31 @@ +// 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 "CCDB/BasicCCDBManager.h" + +#include +#include + +#include + +void getMenu(int runNumber, std::string baseCCDBPath = "Users/m/mpuccio/EventFiltering/OTS/Chunked/") +{ + auto& ccdb = o2::ccdb::BasicCCDBManager::instance(); + TH1* counters = ccdb.getForRun(baseCCDBPath + "FilterCounters", runNumber); + TAxis* axis = counters->GetXaxis(); + + std::vector binLabels(axis->GetNbins() - 2); // skip first and last bins + std::cout << "Menu for run " << runNumber << ":\n"; + for (int i = 2; i < axis->GetNbins(); ++i) { + binLabels[i - 1] = axis->GetBinLabel(i); + std::cout << "Id " << i - 2 << ": " << axis->GetBinLabel(i) << "\n"; + } +} From b2a827fad4f5897b7061b9756e9d2d5255a1b380 Mon Sep 17 00:00:00 2001 From: Sandeep Dudi <69388148+sdudi123@users.noreply.github.com> Date: Wed, 11 Jun 2025 16:36:22 +0200 Subject: [PATCH 024/871] [PWGUD] Updated macro for JIT session error Cannot allocate memory issue (#11490) Co-authored-by: sandeep dudi --- PWGUD/Tasks/sginclusivePhiKstarSD.cxx | 219 +++++++++++++++----------- 1 file changed, 124 insertions(+), 95 deletions(-) diff --git a/PWGUD/Tasks/sginclusivePhiKstarSD.cxx b/PWGUD/Tasks/sginclusivePhiKstarSD.cxx index 20d4f08d1d6..628818bd553 100644 --- a/PWGUD/Tasks/sginclusivePhiKstarSD.cxx +++ b/PWGUD/Tasks/sginclusivePhiKstarSD.cxx @@ -59,6 +59,15 @@ struct SginclusivePhiKstarSD { Configurable zdcCut{"zdcCut", 0., "ZDC threshold"}; Configurable vzCut{"vzCut", 10., "Vz position"}; Configurable occCut{"occCut", 1000., "Occupancy cut"}; + Configurable hadronicRate{"hadronicRate", 1000., "hadronicRate cut"}; + Configurable useTrs{"useTrs", -1, "kNoCollInTimeRangeStandard cut"}; + Configurable useTrofs{"useTrofs", -1, "kNoCollInRofStandard cut"}; + Configurable useHmpr{"useHmpr", -1, "kNoHighMultCollInPrevRof cut"}; + Configurable useTfb{"useTfb", -1, "kNoTimeFrameBorder cut"}; + Configurable useItsrofb{"useItsrofb", -1, "kNoITSROFrameBorder cut"}; + Configurable useSbp{"useSbp", -1, "kNoSameBunchPileup cut"}; + Configurable useZvtxftovpv{"useZvtxftovpv", -1, "kIsGoodZvtxFT0vsPV cut"}; + Configurable useVtxItsTpc{"useVtxItsTpc", -1, "kIsVertexITSTPC cut"}; // Track Selections Configurable pvCut{"pvCut", 1.0, "Use Only PV tracks"}; @@ -395,9 +404,9 @@ struct SginclusivePhiKstarSD { } //_____________________________________________________________________________ - double cosThetaCollinsSoperFrame(TLorentzVector pair1, - TLorentzVector pair2, - TLorentzVector fourpion) + double cosThetaCollinsSoperFrame(ROOT::Math::PxPyPzMVector pair1, + ROOT::Math::PxPyPzMVector pair2, + ROOT::Math::PxPyPzMVector fourpion) { double halfSqrtSnn = 2680.; double massOfLead208 = 193.6823; @@ -483,7 +492,7 @@ struct SginclusivePhiKstarSD { } //------------------------------------------------------------------------------------------------------ - double phiCollinsSoperFrame(TLorentzVector pair1, TLorentzVector pair2, TLorentzVector fourpion) + double phiCollinsSoperFrame(ROOT::Math::PxPyPzMVector pair1, ROOT::Math::PxPyPzMVector pair2, ROOT::Math::PxPyPzMVector fourpion) { // Half of the energy per pair of the colliding nucleons. double halfSqrtSnn = 2680.; @@ -518,24 +527,24 @@ struct SginclusivePhiKstarSD { void process(UDCollisionFull const& collision, UDtracksfull const& tracks) { - TLorentzVector v0; - TLorentzVector v1; - TLorentzVector v01; + ROOT::Math::PxPyPzMVector v0; + ROOT::Math::PxPyPzMVector v1; + ROOT::Math::PxPyPzMVector v01; int gapSide = collision.gapSide(); float fitCut[5] = {fv0Cut, ft0aCut, ft0cCut, fddaCut, fddcCut}; std::vector parameters = {pvCut, dcazCut, dcaxyCut, tpcChi2Cut, tpcNClsFindableCut, itsChi2Cut, etaCut, ptCut}; int truegapSide = sgSelector.trueGap(collision, fitCut[0], fitCut[1], fitCut[2], zdcCut); - TLorentzVector phiv; - TLorentzVector phiv1; + ROOT::Math::PxPyPzMVector phiv; + ROOT::Math::PxPyPzMVector phiv1; - std::vector onlyPionTracksp; + std::vector onlyPionTracksp; std::vector rawPionTracksp; - std::vector onlyPionTrackspm; + std::vector onlyPionTrackspm; std::vector rawPionTrackspm; - std::vector onlyPionTracksn; + std::vector onlyPionTracksn; std::vector rawPionTracksn; registry.fill(HIST("GapSide"), gapSide); @@ -547,6 +556,25 @@ struct SginclusivePhiKstarSD { return; if (std::abs(collision.occupancyInTime()) > occCut) return; + if (std::abs(collision.hadronicRate()) > hadronicRate) + return; + + if (useTrs != -1 && collision.trs() != useTrs) + return; + if (useTrofs != -1 && collision.trofs() != useTrofs) + return; + if (useHmpr != -1 && collision.hmpr() != useHmpr) + return; + if (useTfb != -1 && collision.tfb() != useTfb) + return; + if (useItsrofb != -1 && collision.itsROFb() != useItsrofb) + return; + if (useSbp != -1 && collision.sbp() != useSbp) + return; + if (useZvtxftovpv != -1 && collision.zVtxFT0vPV() != useZvtxftovpv) + return; + if (useVtxItsTpc != -1 && collision.vtxITSTPC() != useVtxItsTpc) + return; int mult = collision.numContrib(); if (gapSide == 0) { @@ -569,18 +597,19 @@ struct SginclusivePhiKstarSD { int trackextra = 0; int trackextraDG = 0; - Partition pvContributors1 = aod::udtrack::isPVContributor == true; - pvContributors1.bindTable(tracks); - if (gapSide == 0) { - registry.get(HIST("nPVContributors_data"))->Fill(pvContributors1.size(), 1.); - } - if (gapSide == 1) { - registry.get(HIST("nPVContributors_data_1"))->Fill(pvContributors1.size(), 1.); - } + /* Partition pvContributors1 = aod::udtrack::isPVContributor == true; + pvContributors1.bindTable(tracks); + if (gapSide == 0) { + registry.get(HIST("nPVContributors_data"))->Fill(pvContributors1.size(), 1.); + } + if (gapSide == 1) { + registry.get(HIST("nPVContributors_data_1"))->Fill(pvContributors1.size(), 1.); + } + */ for (const auto& track1 : tracks) { if (!trackselector(track1, parameters)) continue; - v0.SetXYZM(track1.px(), track1.py(), track1.pz(), o2::constants::physics::MassPionCharged); + v0.SetCoordinates(track1.px(), track1.py(), track1.pz(), o2::constants::physics::MassPionCharged); if (selectionPIDPion1(track1)) { onlyPionTrackspm.push_back(v0); rawPionTrackspm.push_back(track1); @@ -719,8 +748,8 @@ struct SginclusivePhiKstarSD { continue; if (phi && selectionPIDKaon1(t0) && selectionPIDKaon1(t1)) { // Apply kaon hypothesis and create pairs - v0.SetXYZM(t0.px(), t0.py(), t0.pz(), o2::constants::physics::MassKaonCharged); - v1.SetXYZM(t1.px(), t1.py(), t1.pz(), o2::constants::physics::MassKaonCharged); + v0.SetCoordinates(t0.px(), t0.py(), t0.pz(), o2::constants::physics::MassKaonCharged); + v1.SetCoordinates(t1.px(), t1.py(), t1.pz(), o2::constants::physics::MassKaonCharged); v01 = v0 + v1; // Opposite sign pairs if (t0.sign() != t1.sign()) { @@ -754,8 +783,8 @@ struct SginclusivePhiKstarSD { continue; if (kstar && selectionPIDKaon1(t0) && selectionPIDPion1(t1)) { // Apply kaon hypothesis and create pairs - v0.SetXYZM(t0.px(), t0.py(), t0.pz(), o2::constants::physics::MassKaonCharged); - v1.SetXYZM(t1.px(), t1.py(), t1.pz(), o2::constants::physics::MassPionCharged); + v0.SetCoordinates(t0.px(), t0.py(), t0.pz(), o2::constants::physics::MassKaonCharged); + v1.SetCoordinates(t1.px(), t1.py(), t1.pz(), o2::constants::physics::MassPionCharged); v01 = v0 + v1; // Opposite sign pairs if (t0.sign() != t1.sign()) { @@ -790,8 +819,8 @@ struct SginclusivePhiKstarSD { continue; if (phi && selectionPIDKaon1(t0) && selectionPIDKaon1(t1)) { // Apply kaon hypothesis and create pairs - v0.SetXYZM(t0.px(), t0.py(), t0.pz(), o2::constants::physics::MassKaonCharged); - v1.SetXYZM(t1.px(), t1.py(), t1.pz(), o2::constants::physics::MassKaonCharged); + v0.SetCoordinates(t0.px(), t0.py(), t0.pz(), o2::constants::physics::MassKaonCharged); + v1.SetCoordinates(t1.px(), t1.py(), t1.pz(), o2::constants::physics::MassKaonCharged); v01 = v0 + v1; // Opposite sign pairs if (t0.sign() != t1.sign()) { @@ -825,8 +854,8 @@ struct SginclusivePhiKstarSD { continue; if (kstar && selectionPIDKaon1(t0) && selectionPIDPion1(t1)) { // Apply kaon hypothesis and create pairs - v0.SetXYZM(t0.px(), t0.py(), t0.pz(), o2::constants::physics::MassKaonCharged); - v1.SetXYZM(t1.px(), t1.py(), t1.pz(), o2::constants::physics::MassPionCharged); + v0.SetCoordinates(t0.px(), t0.py(), t0.pz(), o2::constants::physics::MassKaonCharged); + v1.SetCoordinates(t1.px(), t1.py(), t1.pz(), o2::constants::physics::MassPionCharged); v01 = v0 + v1; // Opposite sign pairs if (t0.sign() != t1.sign()) { @@ -860,8 +889,8 @@ struct SginclusivePhiKstarSD { continue; if (phi && selectionPIDKaon1(t0) && selectionPIDKaon1(t1)) { // Apply kaon hypothesis and create pairs - v0.SetXYZM(t0.px(), t0.py(), t0.pz(), o2::constants::physics::MassKaonCharged); - v1.SetXYZM(t1.px(), t1.py(), t1.pz(), o2::constants::physics::MassKaonCharged); + v0.SetCoordinates(t0.px(), t0.py(), t0.pz(), o2::constants::physics::MassKaonCharged); + v1.SetCoordinates(t1.px(), t1.py(), t1.pz(), o2::constants::physics::MassKaonCharged); v01 = v0 + v1; // Opposite sign pairs if (t0.sign() != t1.sign()) { @@ -895,8 +924,8 @@ struct SginclusivePhiKstarSD { continue; if (kstar && selectionPIDKaon1(t0) && selectionPIDPion1(t1)) { // Apply kaon hypothesis and create pairs - v0.SetXYZM(t0.px(), t0.py(), t0.pz(), o2::constants::physics::MassKaonCharged); - v1.SetXYZM(t1.px(), t1.py(), t1.pz(), o2::constants::physics::MassPionCharged); + v0.SetCoordinates(t0.px(), t0.py(), t0.pz(), o2::constants::physics::MassKaonCharged); + v1.SetCoordinates(t1.px(), t1.py(), t1.pz(), o2::constants::physics::MassPionCharged); v01 = v0 + v1; // Opposite sign pairs if (t0.sign() != t1.sign()) { @@ -932,8 +961,8 @@ struct SginclusivePhiKstarSD { if (phi && selectionPIDKaon1(t0) && selectionPIDKaon1(t1)) { // Apply kaon hypothesis and create pairs - v0.SetXYZM(t0.px(), t0.py(), t0.pz(), o2::constants::physics::MassKaonCharged); - v1.SetXYZM(t1.px(), t1.py(), t1.pz(), o2::constants::physics::MassKaonCharged); + v0.SetCoordinates(t0.px(), t0.py(), t0.pz(), o2::constants::physics::MassKaonCharged); + v1.SetCoordinates(t1.px(), t1.py(), t1.pz(), o2::constants::physics::MassKaonCharged); v01 = v0 + v1; // Opposite sign pairs if (t0.sign() != t1.sign()) { @@ -971,8 +1000,8 @@ struct SginclusivePhiKstarSD { auto rotkaonPx = t0.px() * std::cos(rotangle) - t0.py() * std::sin(rotangle); auto rotkaonPy = t0.px() * std::sin(rotangle) + t0.py() * std::cos(rotangle); - v0.SetXYZM(rotkaonPx, rotkaonPy, t0.pz(), o2::constants::physics::MassKaonCharged); - v1.SetXYZM(t1.px(), t1.py(), t1.pz(), o2::constants::physics::MassKaonCharged); + v0.SetCoordinates(rotkaonPx, rotkaonPy, t0.pz(), o2::constants::physics::MassKaonCharged); + v1.SetCoordinates(t1.px(), t1.py(), t1.pz(), o2::constants::physics::MassKaonCharged); v01 = v0 + v1; if (t0.sign() != t1.sign()) { if (gapSide == 0) { @@ -995,8 +1024,8 @@ struct SginclusivePhiKstarSD { if (t0.globalIndex() == t1.globalIndex()) continue; if (rho && selectionPIDProton(t0, useTof, nsigmaTpcCut, nsigmaTofCut) && selectionPIDPion1(t1)) { - v0.SetXYZM(t0.px(), t0.py(), t0.pz(), o2::constants::physics::MassProton); - v1.SetXYZM(t1.px(), t1.py(), t1.pz(), o2::constants::physics::MassPionCharged); + v0.SetCoordinates(t0.px(), t0.py(), t0.pz(), o2::constants::physics::MassProton); + v1.SetCoordinates(t1.px(), t1.py(), t1.pz(), o2::constants::physics::MassPionCharged); v01 = v0 + v1; // Opposite sign pairs if (t0.sign() != t1.sign()) { @@ -1025,8 +1054,8 @@ struct SginclusivePhiKstarSD { if (kstar && selectionPIDKaon1(t0) && selectionPIDPion1(t1)) { if (kaoncut && t0.tpcNSigmaPi() < pionNsigmaCut) continue; - v0.SetXYZM(t0.px(), t0.py(), t0.pz(), o2::constants::physics::MassKaonCharged); - v1.SetXYZM(t1.px(), t1.py(), t1.pz(), o2::constants::physics::MassPionCharged); + v0.SetCoordinates(t0.px(), t0.py(), t0.pz(), o2::constants::physics::MassKaonCharged); + v1.SetCoordinates(t1.px(), t1.py(), t1.pz(), o2::constants::physics::MassPionCharged); v01 = v0 + v1; // Opposite sign pairs if (t0.sign() != t1.sign()) { @@ -1062,8 +1091,8 @@ struct SginclusivePhiKstarSD { auto rotkaonPx = t0.px() * std::cos(rotangle) - t0.py() * std::sin(rotangle); auto rotkaonPy = t0.px() * std::sin(rotangle) + t0.py() * std::cos(rotangle); - v0.SetXYZM(rotkaonPx, rotkaonPy, t0.pz(), o2::constants::physics::MassKaonCharged); - v1.SetXYZM(t1.px(), t1.py(), t1.pz(), o2::constants::physics::MassPionCharged); + v0.SetCoordinates(rotkaonPx, rotkaonPy, t0.pz(), o2::constants::physics::MassKaonCharged); + v1.SetCoordinates(t1.px(), t1.py(), t1.pz(), o2::constants::physics::MassPionCharged); v01 = v0 + v1; if (t0.sign() != t1.sign()) { if (gapSide == 0) { @@ -1082,12 +1111,12 @@ struct SginclusivePhiKstarSD { } if (fourpion) { if (gapSide == 2 && mult2 == 4) { - TLorentzVector pair1, pair2, pair3, pair4; + ROOT::Math::PxPyPzMVector pair1, pair2, pair3, pair4; if (onlyPionTracksp.size() == 2 && onlyPionTracksn.size() == 2) { - TLorentzVector k1 = onlyPionTracksp.at(0); - TLorentzVector k2 = onlyPionTracksp.at(1); - TLorentzVector k3 = onlyPionTracksn.at(0); - TLorentzVector k4 = onlyPionTracksn.at(1); + ROOT::Math::PxPyPzMVector k1 = onlyPionTracksp.at(0); + ROOT::Math::PxPyPzMVector k2 = onlyPionTracksp.at(1); + ROOT::Math::PxPyPzMVector k3 = onlyPionTracksn.at(0); + ROOT::Math::PxPyPzMVector k4 = onlyPionTracksn.at(1); phiv = k1 + k2 + k3 + k4; pair1 = k1 + k3; pair2 = k2 + k4; @@ -1112,10 +1141,10 @@ struct SginclusivePhiKstarSD { if (onlyPionTracksp.size() != 2 && onlyPionTracksn.size() != 2) { if (onlyPionTracksp.size() + onlyPionTracksn.size() != 4) return; - TLorentzVector l1 = onlyPionTrackspm.at(0); - TLorentzVector l2 = onlyPionTrackspm.at(1); - TLorentzVector l3 = onlyPionTrackspm.at(2); - TLorentzVector l4 = onlyPionTrackspm.at(3); + ROOT::Math::PxPyPzMVector l1 = onlyPionTrackspm.at(0); + ROOT::Math::PxPyPzMVector l2 = onlyPionTrackspm.at(1); + ROOT::Math::PxPyPzMVector l3 = onlyPionTrackspm.at(2); + ROOT::Math::PxPyPzMVector l4 = onlyPionTrackspm.at(3); phiv1 = l1 + l2 + l3 + l4; registry.fill(HIST("os_pppp_pT_2_ls"), phiv1.M(), phiv1.Pt(), phiv1.Rapidity()); } @@ -1134,9 +1163,9 @@ struct SginclusivePhiKstarSD { using BinningTypeVertexContributor = ColumnBinningPolicy; void mixprocess(UDCollisionsFull1 const& collisions, UDtracksfull const& /*track*/) { - TLorentzVector v0; - TLorentzVector v1; - TLorentzVector v01; + ROOT::Math::PxPyPzMVector v0; + ROOT::Math::PxPyPzMVector v1; + ROOT::Math::PxPyPzMVector v01; float fitCut[5] = {fv0Cut, ft0aCut, ft0cCut, fddaCut, fddcCut}; std::vector parameters = {pvCut, dcazCut, dcaxyCut, tpcChi2Cut, tpcNClsFindableCut, itsChi2Cut, etaCut, ptCut}; BinningTypeVertexContributor binningOnPositions{{axisVertex, axisMultiplicityClass}, true}; @@ -1158,8 +1187,8 @@ struct SginclusivePhiKstarSD { if (!trackselector(track1, parameters) || !trackselector(track2, parameters)) continue; if (phi && selectionPIDKaon1(track1) && selectionPIDKaon1(track2)) { - v0.SetXYZM(track1.px(), track1.py(), track1.pz(), o2::constants::physics::MassKaonCharged); - v1.SetXYZM(track2.px(), track2.py(), track2.pz(), o2::constants::physics::MassKaonCharged); + v0.SetCoordinates(track1.px(), track1.py(), track1.pz(), o2::constants::physics::MassKaonCharged); + v1.SetCoordinates(track2.px(), track2.py(), track2.pz(), o2::constants::physics::MassKaonCharged); v01 = v0 + v1; // Opposite sign pairs if (track1.sign() != track2.sign()) { @@ -1181,8 +1210,8 @@ struct SginclusivePhiKstarSD { if (track1.globalIndex() == track2.globalIndex()) continue; if (kstar && selectionPIDKaon1(track1) && selectionPIDPion1(track2)) { - v0.SetXYZM(track1.px(), track1.py(), track1.pz(), o2::constants::physics::MassKaonCharged); - v1.SetXYZM(track2.px(), track2.py(), track2.pz(), o2::constants::physics::MassPionCharged); + v0.SetCoordinates(track1.px(), track1.py(), track1.pz(), o2::constants::physics::MassKaonCharged); + v1.SetCoordinates(track2.px(), track2.py(), track2.pz(), o2::constants::physics::MassPionCharged); v01 = v0 + v1; // Opposite sign pairs if (track1.sign() != track2.sign()) { @@ -1216,11 +1245,11 @@ struct SginclusivePhiKstarSD { void processMCTruth(aod::UDMcCollisions const& mccollisions, CCs const& collisions, aod::UDMcParticles const& McParts, TCs const& tracks) { // number of McCollisions in DF - TLorentzVector v0; - TLorentzVector v1; - TLorentzVector v01; - TLorentzVector vkstar; - TLorentzVector vphi; + ROOT::Math::PxPyPzMVector v0; + ROOT::Math::PxPyPzMVector v1; + ROOT::Math::PxPyPzMVector v01; + ROOT::Math::PxPyPzMVector vkstar; + ROOT::Math::PxPyPzMVector vphi; for (const auto& mccollision : mccollisions) { if (mccollision.generatorsID() != generatedId) continue; @@ -1236,11 +1265,11 @@ struct SginclusivePhiKstarSD { for (const auto& [tr1, tr2] : combinations(partSlice, partSlice)) { if ((tr1.pdgCode() == kKPlus && tr2.pdgCode() == kPiMinus) || (tr1.pdgCode() == kKMinus && tr2.pdgCode() == kPiPlus) || (tr1.pdgCode() == kPiPlus && tr2.pdgCode() == kKMinus) || (tr1.pdgCode() == kPiMinus && tr2.pdgCode() == kKPlus)) { if (std::abs(tr1.pdgCode()) == kKPlus) { - v0.SetXYZM(tr1.px(), tr1.py(), tr1.pz(), o2::constants::physics::MassKaonCharged); - v1.SetXYZM(tr2.px(), tr2.py(), tr2.pz(), o2::constants::physics::MassPionCharged); + v0.SetCoordinates(tr1.px(), tr1.py(), tr1.pz(), o2::constants::physics::MassKaonCharged); + v1.SetCoordinates(tr2.px(), tr2.py(), tr2.pz(), o2::constants::physics::MassPionCharged); } else { - v0.SetXYZM(tr1.px(), tr1.py(), tr1.pz(), o2::constants::physics::MassPionCharged); - v1.SetXYZM(tr2.px(), tr2.py(), tr2.pz(), o2::constants::physics::MassKaonCharged); + v0.SetCoordinates(tr1.px(), tr1.py(), tr1.pz(), o2::constants::physics::MassPionCharged); + v1.SetCoordinates(tr2.px(), tr2.py(), tr2.pz(), o2::constants::physics::MassKaonCharged); } if (!tr1.isPhysicalPrimary() || !tr2.isPhysicalPrimary()) continue; @@ -1255,7 +1284,7 @@ struct SginclusivePhiKstarSD { if (tr1.has_mothers() && tr2.has_mothers()) { for (const auto& mother : tr1.mothers_as()) { if (std::abs(mother.pdgCode()) == o2::constants::physics::Pdg::kK0Star892) { - vkstar.SetXYZM(mother.px(), mother.py(), mother.pz(), o2::constants::physics::MassK0Star892); + vkstar.SetCoordinates(mother.px(), mother.py(), mother.pz(), o2::constants::physics::MassK0Star892); registry.get(HIST("MC/accMPtRap_kstar_G"))->Fill(vkstar.M(), vkstar.Pt(), vkstar.Rapidity(), 1.); flag = true; } @@ -1279,8 +1308,8 @@ struct SginclusivePhiKstarSD { if (std::abs(tr1.pdgCode()) != kKPlus || std::abs(tr2.pdgCode()) != kKPlus) continue; - v0.SetXYZM(tr1.px(), tr1.py(), tr1.pz(), o2::constants::physics::MassKaonCharged); - v1.SetXYZM(tr2.px(), tr2.py(), tr2.pz(), o2::constants::physics::MassKaonCharged); + v0.SetCoordinates(tr1.px(), tr1.py(), tr1.pz(), o2::constants::physics::MassKaonCharged); + v1.SetCoordinates(tr2.px(), tr2.py(), tr2.pz(), o2::constants::physics::MassKaonCharged); if (tr1.pdgCode() == tr2.pdgCode()) continue; v01 = v0 + v1; @@ -1296,7 +1325,7 @@ struct SginclusivePhiKstarSD { if (tr1.has_mothers() && tr2.has_mothers()) { for (const auto& mother : tr1.mothers_as()) { if (std::abs(mother.pdgCode()) == o2::constants::physics::Pdg::kPhi) { - vphi.SetXYZM(mother.px(), mother.py(), mother.pz(), o2::constants::physics::MassPhi); + vphi.SetCoordinates(mother.px(), mother.py(), mother.pz(), o2::constants::physics::MassPhi); registry.get(HIST("MC/accMPtRap_phi_G"))->Fill(vphi.M(), vphi.Pt(), vphi.Rapidity(), 1.); flag = true; } @@ -1349,8 +1378,8 @@ struct SginclusivePhiKstarSD { std::vector parameters = {pvCut, dcazCut, dcaxyCut, tpcChi2Cut, tpcNClsFindableCut, itsChi2Cut, etaCut, ptCut}; int truegapSide = sgSelector.trueGap(collision, fitCut[0], fitCut[1], fitCut[2], zdcCut); registry.get(HIST("Reco/Stat"))->Fill(4.0, 1.); - Partition pvContributors = aod::udtrack::isPVContributor == true; - pvContributors.bindTable(tracks); + // Partition pvContributors = aod::udtrack::isPVContributor == true; + // pvContributors.bindTable(tracks); if (std::abs(collision.posZ()) > vzCut) return; if (std::abs(collision.occupancyInTime()) > occCut) @@ -1358,16 +1387,16 @@ struct SginclusivePhiKstarSD { registry.get(HIST("Reco/Stat"))->Fill(truegapSide, 1.); if (truegapSide != gapsideMC) return; - registry.get(HIST("Reco/nPVContributors"))->Fill(pvContributors.size(), 1.); - TLorentzVector vphi; - TLorentzVector vkstar; - TLorentzVector v0; - TLorentzVector vr0; - TLorentzVector vr1; - TLorentzVector vr01; - TLorentzVector vr0g; - TLorentzVector vr1g; - TLorentzVector vr01g; + // registry.get(HIST("Reco/nPVContributors"))->Fill(pvContributors.size(), 1.); + ROOT::Math::PxPyPzMVector vphi; + ROOT::Math::PxPyPzMVector vkstar; + ROOT::Math::PxPyPzMVector v0; + ROOT::Math::PxPyPzMVector vr0; + ROOT::Math::PxPyPzMVector vr1; + ROOT::Math::PxPyPzMVector vr01; + ROOT::Math::PxPyPzMVector vr0g; + ROOT::Math::PxPyPzMVector vr1g; + ROOT::Math::PxPyPzMVector vr01g; int t1 = 0; if (truegapSide == 0) { registry.fill(HIST("V0A_0_mc"), collision.totalFV0AmplitudeA()); @@ -1401,7 +1430,7 @@ struct SginclusivePhiKstarSD { registry.get(HIST("Reco/tr_chi2ncl_2"))->Fill(tr1.tpcChi2NCl(), 1.); registry.get(HIST("Reco/tr_tpcnclfind_2"))->Fill(tr1.tpcNClsFindable(), 1.); registry.get(HIST("Reco/tr_itsChi2NCl_2"))->Fill(tr1.itsChi2NCl(), 1.); - v0.SetXYZM(tr1.px(), tr1.py(), tr1.pz(), o2::constants::physics::MassPionCharged); + v0.SetCoordinates(tr1.px(), tr1.py(), tr1.pz(), o2::constants::physics::MassPionCharged); registry.fill(HIST("tpc_dedx_mc"), v0.P(), tr1.tpcSignal()); registry.fill(HIST("tof_beta_mc"), v0.P(), tr1.beta()); @@ -1421,7 +1450,7 @@ struct SginclusivePhiKstarSD { } t1++; - vr0.SetXYZM(tr1.px(), tr1.py(), tr1.pz(), o2::constants::physics::MassKaonCharged); + vr0.SetCoordinates(tr1.px(), tr1.py(), tr1.pz(), o2::constants::physics::MassKaonCharged); registry.get(HIST("Reco/trpt"))->Fill(vr0.Pt(), 1.); registry.get(HIST("Reco/treta_k"))->Fill(vr0.Eta(), 1.); if (!selectionPIDKaon1(tr1)) @@ -1437,7 +1466,7 @@ struct SginclusivePhiKstarSD { if (t2 > t1) { if (!selectionPIDKaon1(tr2)) continue; - vr1.SetXYZM(tr2.px(), tr2.py(), tr2.pz(), o2::constants::physics::MassKaonCharged); + vr1.SetCoordinates(tr2.px(), tr2.py(), tr2.pz(), o2::constants::physics::MassKaonCharged); auto mcPart2 = tr2.udMcParticle(); if (std::abs(mcPart2.globalIndex() - mcPart1.globalIndex()) != 1) continue; @@ -1452,7 +1481,7 @@ struct SginclusivePhiKstarSD { if (mcPart1.has_mothers() && mcPart2.has_mothers()) { for (const auto& mother : mcPart1.mothers_as()) { if (std::abs(mother.pdgCode()) == o2::constants::physics::Pdg::kPhi) { - vphi.SetXYZM(mother.px(), mother.py(), mother.pz(), o2::constants::physics::MassPhi); + vphi.SetCoordinates(mother.px(), mother.py(), mother.pz(), o2::constants::physics::MassPhi); registry.get(HIST("MC/accMPtRap_phi_T"))->Fill(vphi.M(), vphi.Pt(), vphi.Rapidity(), 1.); flag = true; } @@ -1463,8 +1492,8 @@ struct SginclusivePhiKstarSD { } } } - vr0g.SetXYZM(mcPart1.px(), mcPart1.py(), mcPart1.pz(), o2::constants::physics::MassKaonCharged); - vr1g.SetXYZM(mcPart2.px(), mcPart2.py(), mcPart2.pz(), o2::constants::physics::MassKaonCharged); + vr0g.SetCoordinates(mcPart1.px(), mcPart1.py(), mcPart1.pz(), o2::constants::physics::MassKaonCharged); + vr1g.SetCoordinates(mcPart2.px(), mcPart2.py(), mcPart2.pz(), o2::constants::physics::MassKaonCharged); vr01g = vr0g + vr1g; vr01 = vr0 + vr1; @@ -1499,10 +1528,10 @@ struct SginclusivePhiKstarSD { if (tr1.sign() * tr2.sign() > 0) continue; - vr0.SetXYZM(tr1.px(), tr1.py(), tr1.pz(), o2::constants::physics::MassPionCharged); - vr1.SetXYZM(tr2.px(), tr2.py(), tr2.pz(), o2::constants::physics::MassKaonCharged); - vr0g.SetXYZM(mcPart1.px(), mcPart1.py(), mcPart1.pz(), o2::constants::physics::MassPionCharged); - vr1g.SetXYZM(mcPart2.px(), mcPart2.py(), mcPart2.pz(), o2::constants::physics::MassKaonCharged); + vr0.SetCoordinates(tr1.px(), tr1.py(), tr1.pz(), o2::constants::physics::MassPionCharged); + vr1.SetCoordinates(tr2.px(), tr2.py(), tr2.pz(), o2::constants::physics::MassKaonCharged); + vr0g.SetCoordinates(mcPart1.px(), mcPart1.py(), mcPart1.pz(), o2::constants::physics::MassPionCharged); + vr1g.SetCoordinates(mcPart2.px(), mcPart2.py(), mcPart2.pz(), o2::constants::physics::MassKaonCharged); vr01g = vr0g + vr1g; vr01 = vr0 + vr1; if (!trackselector(tr1, parameters) || !trackselector(tr2, parameters)) { @@ -1514,7 +1543,7 @@ struct SginclusivePhiKstarSD { if (mcPart1.has_mothers() && mcPart2.has_mothers()) { for (const auto& mother : mcPart1.mothers_as()) { if (std::abs(mother.pdgCode()) == o2::constants::physics::Pdg::kK0Star892) { - vkstar.SetXYZM(mother.px(), mother.py(), mother.pz(), o2::constants::physics::MassK0Star892); + vkstar.SetCoordinates(mother.px(), mother.py(), mother.pz(), o2::constants::physics::MassK0Star892); registry.get(HIST("MC/accMPtRap_kstar_T"))->Fill(vkstar.M(), vkstar.Pt(), vkstar.Rapidity(), 1.); flag = true; } From 66a62b9e06ecb124eb7c0cc202fdd526111ecd21 Mon Sep 17 00:00:00 2001 From: ariedel-cern <85537041+ariedel-cern@users.noreply.github.com> Date: Wed, 11 Jun 2025 18:01:37 +0200 Subject: [PATCH 025/871] [Trigger,PWGCF] Fix order of enums (#11545) --- EventFiltering/PWGCF/CFFilterAll.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/EventFiltering/PWGCF/CFFilterAll.cxx b/EventFiltering/PWGCF/CFFilterAll.cxx index 589228edc5f..efc7625b215 100644 --- a/EventFiltering/PWGCF/CFFilterAll.cxx +++ b/EventFiltering/PWGCF/CFFilterAll.cxx @@ -61,8 +61,8 @@ enum CFTriggers { kPPRho, kPD, kLD, - kRhoD, kPhiD, + kRhoD, kNTriggers }; From bb4736da716c5129e93958af6417f3a32cd95244 Mon Sep 17 00:00:00 2001 From: Felix Schlepper Date: Wed, 11 Jun 2025 20:09:12 +0200 Subject: [PATCH 026/871] [PWGLF] do not include ITS internal code (#11540) --- .../Strangeness/Converters/CMakeLists.txt | 10 +++++----- .../Strangeness/Converters/straevselsconverter2.cxx | 11 ++++++----- .../Strangeness/Converters/straevselsconverter3.cxx | 11 ++++++----- .../Strangeness/Converters/straevselsconverter4.cxx | 8 ++++---- .../Strangeness/Converters/straevselsconverter5.cxx | 10 +++++----- 5 files changed, 26 insertions(+), 24 deletions(-) diff --git a/PWGLF/TableProducer/Strangeness/Converters/CMakeLists.txt b/PWGLF/TableProducer/Strangeness/Converters/CMakeLists.txt index 131672fd384..842137dafe1 100644 --- a/PWGLF/TableProducer/Strangeness/Converters/CMakeLists.txt +++ b/PWGLF/TableProducer/Strangeness/Converters/CMakeLists.txt @@ -41,22 +41,22 @@ o2physics_add_dpl_workflow(straevselsconverter o2physics_add_dpl_workflow(straevselsconverter2 SOURCES straevselsconverter2.cxx - PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::ITStracking + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::ReconstructionDataFormats COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(straevselsconverter3 SOURCES straevselsconverter3.cxx - PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::ITStracking + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::ReconstructionDataFormats COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(straevselsconverter4 SOURCES straevselsconverter4.cxx - PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::ITStracking + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(straevselsconverter5 SOURCES straevselsconverter5.cxx - PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::ITStracking O2Physics::AnalysisCCDB + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::AnalysisCCDB COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(straevselsconverter2rawcents @@ -117,4 +117,4 @@ o2physics_add_dpl_workflow(stramccollisionconverter2 o2physics_add_dpl_workflow(zdcneutronsconverter SOURCES zdcneutronsconverter.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore - COMPONENT_NAME Analysis) \ No newline at end of file + COMPONENT_NAME Analysis) diff --git a/PWGLF/TableProducer/Strangeness/Converters/straevselsconverter2.cxx b/PWGLF/TableProducer/Strangeness/Converters/straevselsconverter2.cxx index 401b04bbc83..fd3ccad4ee4 100644 --- a/PWGLF/TableProducer/Strangeness/Converters/straevselsconverter2.cxx +++ b/PWGLF/TableProducer/Strangeness/Converters/straevselsconverter2.cxx @@ -8,12 +8,13 @@ // 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 "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "ITStracking/Vertexer.h" #include "PWGLF/DataModel/LFStrangenessTables.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" +#include "ReconstructionDataFormats/Vertex.h" + using namespace o2; using namespace o2::framework; @@ -52,7 +53,7 @@ struct straevselsconverter2 { values.totalFDDAmplitudeC(), values.energyCommonZNA(), values.energyCommonZNC(), - o2::its::Vertex::FlagsMask /*dummy flag value*/); + o2::dataformats::Vertex::FlagsMask /*dummy flag value*/); } } }; diff --git a/PWGLF/TableProducer/Strangeness/Converters/straevselsconverter3.cxx b/PWGLF/TableProducer/Strangeness/Converters/straevselsconverter3.cxx index ecbd738f5fa..ac209c26fe7 100644 --- a/PWGLF/TableProducer/Strangeness/Converters/straevselsconverter3.cxx +++ b/PWGLF/TableProducer/Strangeness/Converters/straevselsconverter3.cxx @@ -8,12 +8,13 @@ // 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 "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "ITStracking/Vertexer.h" #include "PWGLF/DataModel/LFStrangenessTables.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" +#include "ReconstructionDataFormats/Vertex.h" + using namespace o2; using namespace o2::framework; @@ -53,7 +54,7 @@ struct straevselsconverter3 { values.totalFDDAmplitudeC(), values.energyCommonZNA(), values.energyCommonZNC(), - o2::its::Vertex::FlagsMask /*dummy flag value*/); + o2::dataformats::Vertex::FlagsMask /*dummy flag value*/); } } }; diff --git a/PWGLF/TableProducer/Strangeness/Converters/straevselsconverter4.cxx b/PWGLF/TableProducer/Strangeness/Converters/straevselsconverter4.cxx index ad988fd93aa..2dc55f365c9 100644 --- a/PWGLF/TableProducer/Strangeness/Converters/straevselsconverter4.cxx +++ b/PWGLF/TableProducer/Strangeness/Converters/straevselsconverter4.cxx @@ -8,12 +8,12 @@ // 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 "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "ITStracking/Vertexer.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; diff --git a/PWGLF/TableProducer/Strangeness/Converters/straevselsconverter5.cxx b/PWGLF/TableProducer/Strangeness/Converters/straevselsconverter5.cxx index f9617c42a0b..0ba066f99b3 100644 --- a/PWGLF/TableProducer/Strangeness/Converters/straevselsconverter5.cxx +++ b/PWGLF/TableProducer/Strangeness/Converters/straevselsconverter5.cxx @@ -8,13 +8,13 @@ // 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 "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" + #include "CCDB/BasicCCDBManager.h" #include "DataFormatsParameters/AggregatedRunInfo.h" -#include "ITStracking/Vertexer.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; From 7d7062b05a6c68b42aac01cf92780fd90c996a7a Mon Sep 17 00:00:00 2001 From: prottayCMT <61418725+prottayCMT@users.noreply.github.com> Date: Wed, 11 Jun 2025 21:43:09 +0200 Subject: [PATCH 027/871] [PWGLF] removed globalindex to index in addition to filters (#11565) Co-authored-by: Prottay Das --- .../Tasks/Strangeness/taskLambdaSpinCorr.cxx | 87 +++++++++++-------- 1 file changed, 50 insertions(+), 37 deletions(-) diff --git a/PWGLF/Tasks/Strangeness/taskLambdaSpinCorr.cxx b/PWGLF/Tasks/Strangeness/taskLambdaSpinCorr.cxx index 00a2d9707f5..33157c327bf 100644 --- a/PWGLF/Tasks/Strangeness/taskLambdaSpinCorr.cxx +++ b/PWGLF/Tasks/Strangeness/taskLambdaSpinCorr.cxx @@ -13,36 +13,41 @@ /// \brief Analysis task for Lambda spin spin correlation /// /// \author prottay.das@cern.ch +/// \author sourav.kundu@cern.ch -#include -#include -#include -#include -#include "Math/Vector2D.h" -#include "Math/Vector3D.h" -#include "Math/Vector4D.h" -#include "Math/GenVector/Boost.h" +#include "PWGLF/DataModel/LFStrangenessPIDTables.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" +#include "PWGMM/Mult/DataModel/Index.h" // for Particles2Tracks table -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/StepTHn.h" -#include "Common/DataModel/PIDResponse.h" -#include "Common/DataModel/Multiplicity.h" +#include "Common/Core/TrackSelection.h" +#include "Common/Core/trackUtilities.h" #include "Common/DataModel/Centrality.h" -#include "Common/DataModel/TrackSelectionTables.h" #include "Common/DataModel/EventSelection.h" -#include "Common/Core/trackUtilities.h" +#include "Common/DataModel/FT0Corrected.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include "CCDB/BasicCCDBManager.h" #include "CommonConstants/PhysicsConstants.h" -#include "Common/Core/TrackSelection.h" #include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/StepTHn.h" +#include "Framework/runDataProcessing.h" #include "ReconstructionDataFormats/Track.h" -#include "CCDB/BasicCCDBManager.h" -#include "PWGLF/DataModel/LFStrangenessTables.h" -#include "PWGLF/DataModel/LFStrangenessPIDTables.h" -#include "Common/DataModel/FT0Corrected.h" -#include "PWGMM/Mult/DataModel/Index.h" // for Particles2Tracks table + +#include "Math/GenVector/Boost.h" +#include "Math/Vector2D.h" +#include "Math/Vector3D.h" +#include "Math/Vector4D.h" + +#include + +#include +#include +#include using namespace o2; using namespace o2::framework; @@ -66,7 +71,6 @@ struct LfTaskLambdaSpinCorr { // mixing Configurable cosCalculation{"cosCalculation", 0, "cos calculation"}; Configurable mixingCombination{"mixingCombination", 0, "mixing Combination"}; - Configurable mixingEvSel{"mixingEvSel", false, "mixingEvSel"}; Configurable cfgCutOccupancy{"cfgCutOccupancy", 2000, "Occupancy cut"}; ConfigurableAxis axisVertex{"axisVertex", {5, -10, 10}, "vertex axis for bin"}; ConfigurableAxis axisMultiplicityClass{"axisMultiplicityClass", {8, 0, 80}, "multiplicity percentile for bin"}; @@ -94,13 +98,13 @@ struct LfTaskLambdaSpinCorr { Configurable confV0PtMin{"confV0PtMin", 0.f, "Minimum transverse momentum of V0"}; Configurable confV0PtMax{"confV0PtMax", 0.f, "Maximum transverse momentum of V0"}; Configurable confV0Rap{"confV0Rap", 0.8f, "Rapidity range of V0"}; - Configurable confV0DCADaughMax{"confV0DCADaughMax", 0.2f, "Maximum DCA between the V0 daughters"}; + Configurable confV0DCADaughMax{"confV0DCADaughMax", 0.2f, "Maximum DCA between the V0 daughters"}; Configurable confV0CPAMin{"confV0CPAMin", 0.9998f, "Minimum CPA of V0"}; Configurable confV0TranRadV0Min{"confV0TranRadV0Min", 1.5f, "Minimum transverse radius"}; Configurable confV0TranRadV0Max{"confV0TranRadV0Max", 100.f, "Maximum transverse radius"}; Configurable cMaxV0DCA{"cMaxV0DCA", 1.2, "Maximum V0 DCA to PV"}; - Configurable cMinV0DCAPr{"cMinV0DCAPr", 0.05, "Minimum V0 daughters DCA to PV for Pr"}; - Configurable cMinV0DCAPi{"cMinV0DCAPi", 0.05, "Minimum V0 daughters DCA to PV for Pi"}; + Configurable cMinV0DCAPr{"cMinV0DCAPr", 0.05, "Minimum V0 daughters DCA to PV for Pr"}; + Configurable cMinV0DCAPi{"cMinV0DCAPi", 0.05, "Minimum V0 daughters DCA to PV for Pi"}; Configurable cMaxV0LifeTime{"cMaxV0LifeTime", 20, "Maximum V0 life time"}; // config for V0 daughters @@ -610,7 +614,7 @@ struct LfTaskLambdaSpinCorr { if (additionalEvSel4 && !collision1.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { continue; } - if (mixingEvSel && additionalEvSel5 && !collision1.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { + if (additionalEvSel5 && !collision1.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { continue; } @@ -620,7 +624,7 @@ struct LfTaskLambdaSpinCorr { if (additionalEvSel4 && !collision2.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { continue; } - if (mixingEvSel && additionalEvSel5 && !collision2.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { + if (additionalEvSel5 && !collision2.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { continue; } @@ -795,7 +799,11 @@ struct LfTaskLambdaSpinCorr { } PROCESS_SWITCH(LfTaskLambdaSpinCorr, processME, "Process data ME", true); - void processDerivedData(soa::Join::iterator const& collision, v0Candidates const& V0s, dauTracks const&) + Filter v0der = (nabs(aod::v0data::dcapostopv) > cMinV0DCAPr && nabs(aod::v0data::dcanegtopv) > cMinV0DCAPi && nabs(aod::v0data::dcaV0daughters) < confV0DCADaughMax); + 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&) { histos.fill(HIST("hEvtSelInfo"), 0.5); if (rctCut.requireRCTFlagChecker && !rctChecker(collision)) { @@ -914,8 +922,10 @@ struct LfTaskLambdaSpinCorr { } PROCESS_SWITCH(LfTaskLambdaSpinCorr, processDerivedData, "Process derived data", true); - Preslice tracksPerCollisionV0Mixed = o2::aod::v0data::straCollisionId; // for derived data only - void processDerivedDataMixed(soa::Join const& collisions, v0Candidates const& V0s, dauTracks const&) + // 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&) { @@ -954,7 +964,7 @@ struct LfTaskLambdaSpinCorr { if (additionalEvSel4 && !collision1.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { continue; } - if (mixingEvSel && additionalEvSel5 && !collision1.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { + if (additionalEvSel5 && !collision1.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { continue; } @@ -964,13 +974,16 @@ struct LfTaskLambdaSpinCorr { if (additionalEvSel4 && !collision2.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { continue; } - if (mixingEvSel && additionalEvSel5 && !collision2.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { + if (additionalEvSel5 && !collision2.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { continue; } auto centrality = collision1.centFT0C(); - auto groupV01 = V0s.sliceBy(tracksPerCollisionV0Mixed, collision1.globalIndex()); - auto groupV02 = V0s.sliceBy(tracksPerCollisionV0Mixed, collision1.globalIndex()); - auto groupV03 = V0s.sliceBy(tracksPerCollisionV0Mixed, collision2.globalIndex()); + // auto groupV01 = V0s.sliceBy(tracksPerCollisionV0Mixed, collision1.globalIndex()); + // auto groupV02 = V0s.sliceBy(tracksPerCollisionV0Mixed, collision1.globalIndex()); + // auto groupV03 = V0s.sliceBy(tracksPerCollisionV0Mixed, collision2.globalIndex()); + auto groupV01 = V0s.sliceBy(tracksPerCollisionV0Mixed, collision1.index()); + auto groupV02 = V0s.sliceBy(tracksPerCollisionV0Mixed, collision1.index()); + auto groupV03 = V0s.sliceBy(tracksPerCollisionV0Mixed, collision2.index()); size_t rows = groupV03.size() + 20; size_t cols = groupV01.size() + 20; From 5bd224bba9ad74f5f86b3b024365c36c03d7eada Mon Sep 17 00:00:00 2001 From: Zhiyong <71517277+Luzhiyongg@users.noreply.github.com> Date: Thu, 12 Jun 2025 07:21:44 +0800 Subject: [PATCH 028/871] [PWGCF] flowtask: ccdb set to now. diHadron: add event weight (#11569) --- PWGCF/Flow/Tasks/flowTask.cxx | 4 +- .../Tasks/diHadronCor.cxx | 155 ++++++++++-------- 2 files changed, 88 insertions(+), 71 deletions(-) diff --git a/PWGCF/Flow/Tasks/flowTask.cxx b/PWGCF/Flow/Tasks/flowTask.cxx index 5431a84bd47..4390131be3a 100644 --- a/PWGCF/Flow/Tasks/flowTask.cxx +++ b/PWGCF/Flow/Tasks/flowTask.cxx @@ -132,7 +132,6 @@ struct FlowTask { // 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", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; // Define output @@ -196,7 +195,8 @@ struct FlowTask { ccdb->setURL(ccdbUrl.value); ccdb->setCaching(true); - ccdb->setCreatedNotAfter(ccdbNoLaterThan.value); + auto now = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); + ccdb->setCreatedNotAfter(now); // Add some output objects to the histogram registry // Event QA diff --git a/PWGCF/TwoParticleCorrelations/Tasks/diHadronCor.cxx b/PWGCF/TwoParticleCorrelations/Tasks/diHadronCor.cxx index 4a944a4fff0..189e201ef68 100644 --- a/PWGCF/TwoParticleCorrelations/Tasks/diHadronCor.cxx +++ b/PWGCF/TwoParticleCorrelations/Tasks/diHadronCor.cxx @@ -78,7 +78,6 @@ struct DiHadronCor { 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(cfgUseTentativeEventCounter, bool, false, "After sel8(), count events regardless of real event selection") O2_DEFINE_CONFIGURABLE(cfgEvSelkNoSameBunchPileup, bool, false, "rejects collisions which are associated with the same found-by-T0 bunch crossing") 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") @@ -93,6 +92,7 @@ struct DiHadronCor { O2_DEFINE_CONFIGURABLE(cfgEfficiency, std::string, "", "CCDB path to efficiency object") O2_DEFINE_CONFIGURABLE(cfgLocalEfficiency, bool, false, "Use local efficiency object") O2_DEFINE_CONFIGURABLE(cfgVerbosity, bool, false, "Verbose output") + O2_DEFINE_CONFIGURABLE(cfgUseEventWeights, bool, false, "Use event weights for mixed event") SliceCache cache; @@ -184,29 +184,18 @@ struct DiHadronCor { LOGF(info, "Starting init"); // Event Counter - registry.add("hEventCountSpecific", "Number of Event;; Count", {HistType::kTH1D, {{10, 0, 10}}}); - registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(1, "after sel8"); - registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(2, "kNoSameBunchPileup"); - registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(3, "kIsGoodZvtxFT0vsPV"); - registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(4, "kNoCollInTimeRangeStandard"); - registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(5, "kIsGoodITSLayersAll"); - registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(6, "kNoCollInRofStandard"); - registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(7, "kNoHighMultCollInPrevRof"); - registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(8, "occupancy"); - registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(9, "MultCorrelation"); - registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(10, "cfgEvSelV0AT0ACut"); - if (cfgUseTentativeEventCounter) { - registry.add("hEventCountTentative", "Number of Event;; Count", {HistType::kTH1D, {{10, 0, 10}}}); - registry.get(HIST("hEventCountTentative"))->GetXaxis()->SetBinLabel(1, "after sel8"); - registry.get(HIST("hEventCountTentative"))->GetXaxis()->SetBinLabel(2, "kNoSameBunchPileup"); - registry.get(HIST("hEventCountTentative"))->GetXaxis()->SetBinLabel(3, "kIsGoodZvtxFT0vsPV"); - registry.get(HIST("hEventCountTentative"))->GetXaxis()->SetBinLabel(4, "kNoCollInTimeRangeStandard"); - registry.get(HIST("hEventCountTentative"))->GetXaxis()->SetBinLabel(5, "kIsGoodITSLayersAll"); - registry.get(HIST("hEventCountTentative"))->GetXaxis()->SetBinLabel(6, "kNoCollInRofStandard"); - registry.get(HIST("hEventCountTentative"))->GetXaxis()->SetBinLabel(7, "kNoHighMultCollInPrevRof"); - registry.get(HIST("hEventCountTentative"))->GetXaxis()->SetBinLabel(8, "occupancy"); - registry.get(HIST("hEventCountTentative"))->GetXaxis()->SetBinLabel(9, "MultCorrelation"); - registry.get(HIST("hEventCountTentative"))->GetXaxis()->SetBinLabel(10, "cfgEvSelV0AT0ACut"); + if (doprocessSame && cfgUseAdditionalEventCut) { + registry.add("hEventCountSpecific", "Number of Event;; Count", {HistType::kTH1D, {{10, 0, 10}}}); + registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(1, "after sel8"); + registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(2, "kNoSameBunchPileup"); + registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(3, "kIsGoodZvtxFT0vsPV"); + registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(4, "kNoCollInTimeRangeStandard"); + registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(5, "kIsGoodITSLayersAll"); + registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(6, "kNoCollInRofStandard"); + registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(7, "kNoHighMultCollInPrevRof"); + registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(8, "occupancy"); + registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(9, "MultCorrelation"); + registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(10, "cfgEvSelV0AT0ACut"); } if (cfgUseAdditionalEventCut) { @@ -226,23 +215,24 @@ struct DiHadronCor { fT0AV0ASigma->SetParameters(463.4144, 6.796509e-02, -9.097136e-07, 7.971088e-12, -2.600581e-17); } - // Make histograms to check the distributions after cuts - registry.add("deltaEta_deltaPhi_same", "", {HistType::kTH2D, {axisDeltaPhi, axisDeltaEta}}); // check to see the delta eta and delta phi distribution - registry.add("deltaEta_deltaPhi_mixed", "", {HistType::kTH2D, {axisDeltaPhi, axisDeltaEta}}); - registry.add("Phi", "Phi", {HistType::kTH1D, {axisPhi}}); - registry.add("Eta", "Eta", {HistType::kTH1D, {axisEta}}); - 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", "N_{ch}", {HistType::kTH1D, {axisMultiplicity}}); // histogram to see how many events are in the same and mixed event std::string hCentTitle = "Centrality distribution, Estimator " + std::to_string(cfgCentEstimator); - registry.add("Centrality", hCentTitle.c_str(), {HistType::kTH1D, {axisCentrality}}); - registry.add("Centrality_used", hCentTitle.c_str(), {HistType::kTH1D, {axisCentrality}}); // histogram to see how many events are in the same and mixed event - registry.add("zVtx", "zVtx", {HistType::kTH1D, {axisVertex}}); - registry.add("zVtx_used", "zVtx_used", {HistType::kTH1D, {axisVertex}}); - - registry.add("Trig_hist", "", {HistType::kTHnSparseF, {{axisSample, axisVertex, axisPtTrigger}}}); + // Make histograms to check the distributions after cuts + if (doprocessSame) { + registry.add("deltaEta_deltaPhi_same", "", {HistType::kTH2D, {axisDeltaPhi, axisDeltaEta}}); // check to see the delta eta and delta phi distribution + registry.add("deltaEta_deltaPhi_mixed", "", {HistType::kTH2D, {axisDeltaPhi, axisDeltaEta}}); + registry.add("Phi", "Phi", {HistType::kTH1D, {axisPhi}}); + registry.add("Eta", "Eta", {HistType::kTH1D, {axisEta}}); + 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", "N_{ch}", {HistType::kTH1D, {axisMultiplicity}}); // histogram to see how many events are in the same and mixed event + registry.add("Centrality", hCentTitle.c_str(), {HistType::kTH1D, {axisCentrality}}); + registry.add("Centrality_used", hCentTitle.c_str(), {HistType::kTH1D, {axisCentrality}}); // histogram to see how many events are in the same and mixed event + registry.add("zVtx", "zVtx", {HistType::kTH1D, {axisVertex}}); + registry.add("zVtx_used", "zVtx_used", {HistType::kTH1D, {axisVertex}}); + registry.add("Trig_hist", "", {HistType::kTHnSparseF, {{axisSample, axisVertex, axisPtTrigger}}}); + } registry.add("eventcount", "bin", {HistType::kTH1F, {{4, 0, 4, "bin"}}}); // histogram to see how many events are in the same and mixed event if (doprocessMCSame && doprocessOntheflySame) { @@ -263,6 +253,13 @@ struct DiHadronCor { registry.add("MCTrue/MCdeltaEta_deltaPhi_same", "", {HistType::kTH2D, {axisDeltaPhi, axisDeltaEta}}); // check to see the delta eta and delta phi distribution registry.add("MCTrue/MCdeltaEta_deltaPhi_mixed", "", {HistType::kTH2D, {axisDeltaPhi, axisDeltaEta}}); } + if (doprocessMCEfficiency) { + registry.add("MCEffeventcount", "bin", {HistType::kTH1F, {{4, 0, 4, "bin"}}}); + registry.get(HIST("MCEffeventcount"))->GetXaxis()->SetBinLabel(1, "MC"); + registry.get(HIST("MCEffeventcount"))->GetXaxis()->SetBinLabel(2, "Reco Primary"); + registry.get(HIST("MCEffeventcount"))->GetXaxis()->SetBinLabel(3, "Reco All"); + registry.get(HIST("MCEffeventcount"))->GetXaxis()->SetBinLabel(4, "Fake"); + } std::vector corrAxis = {{axisSample, "Sample"}, {axisVertex, "z-vtx (cm)"}, @@ -424,7 +421,7 @@ struct DiHadronCor { } template - void fillCorrelations(TTracks tracks1, TTracksAssoc tracks2, float posZ, int system, int magneticField, float cent) // 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 magneticField, float cent, float eventWeight) // function to fill the Output functions (sparse) and the delta eta and delta phi histograms { // Cache efficiency for particles (too many FindBin lookups) if (mEfficiency) { @@ -455,7 +452,7 @@ struct DiHadronCor { if (!getEfficiencyCorrection(triggerWeight, track1.eta(), track1.pt(), posZ)) continue; if (system == SameEvent) { - registry.fill(HIST("Trig_hist"), fSampleIndex, posZ, track1.pt(), triggerWeight); + registry.fill(HIST("Trig_hist"), fSampleIndex, posZ, track1.pt(), eventWeight * triggerWeight); } for (auto const& track2 : tracks2) { @@ -497,18 +494,18 @@ struct DiHadronCor { // fill the right sparse and histograms if (system == SameEvent) { - same->getPairHist()->Fill(step, fSampleIndex, posZ, track1.pt(), track2.pt(), deltaPhi, deltaEta, triggerWeight * associatedWeight); - registry.fill(HIST("deltaEta_deltaPhi_same"), deltaPhi, deltaEta, triggerWeight * associatedWeight); + same->getPairHist()->Fill(step, fSampleIndex, posZ, track1.pt(), track2.pt(), deltaPhi, deltaEta, eventWeight * triggerWeight * associatedWeight); + registry.fill(HIST("deltaEta_deltaPhi_same"), deltaPhi, deltaEta, eventWeight * triggerWeight * associatedWeight); } else if (system == MixedEvent) { - mixed->getPairHist()->Fill(step, fSampleIndex, posZ, track1.pt(), track2.pt(), deltaPhi, deltaEta, triggerWeight * associatedWeight); - registry.fill(HIST("deltaEta_deltaPhi_mixed"), deltaPhi, deltaEta, triggerWeight * associatedWeight); + mixed->getPairHist()->Fill(step, fSampleIndex, posZ, track1.pt(), track2.pt(), deltaPhi, deltaEta, eventWeight * triggerWeight * associatedWeight); + registry.fill(HIST("deltaEta_deltaPhi_mixed"), deltaPhi, deltaEta, eventWeight * triggerWeight * associatedWeight); } } } } template - void fillMCCorrelations(TTracks tracks1, TTracksAssoc tracks2, float posZ, int system) // function to fill the Output functions (sparse) and the delta eta and delta phi histograms + void fillMCCorrelations(TTracks tracks1, TTracksAssoc tracks2, 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); @@ -522,7 +519,7 @@ struct DiHadronCor { continue; if (system == SameEvent && (doprocessMCSame || doprocessOntheflySame)) - registry.fill(HIST("MCTrue/MCTrig_hist"), fSampleIndex, posZ, track1.pt(), triggerWeight); + registry.fill(HIST("MCTrue/MCTrig_hist"), fSampleIndex, posZ, track1.pt(), eventWeight * triggerWeight); for (auto const& track2 : tracks2) { @@ -539,13 +536,13 @@ struct DiHadronCor { // fill the right sparse and histograms if (system == SameEvent) { - same->getPairHist()->Fill(step, fSampleIndex, posZ, track1.pt(), track2.pt(), deltaPhi, deltaEta, triggerWeight * associatedWeight); + same->getPairHist()->Fill(step, fSampleIndex, posZ, track1.pt(), track2.pt(), deltaPhi, deltaEta, eventWeight * triggerWeight * associatedWeight); if (doprocessMCSame || doprocessOntheflySame) - registry.fill(HIST("MCTrue/MCdeltaEta_deltaPhi_same"), deltaPhi, deltaEta, triggerWeight * associatedWeight); + registry.fill(HIST("MCTrue/MCdeltaEta_deltaPhi_same"), deltaPhi, deltaEta, eventWeight * triggerWeight * associatedWeight); } else if (system == MixedEvent) { - mixed->getPairHist()->Fill(step, fSampleIndex, posZ, track1.pt(), track2.pt(), deltaPhi, deltaEta, triggerWeight * associatedWeight); + mixed->getPairHist()->Fill(step, fSampleIndex, posZ, track1.pt(), track2.pt(), deltaPhi, deltaEta, eventWeight * triggerWeight * associatedWeight); if (doprocessMCMixed || doprocessOntheflyMixed) - registry.fill(HIST("MCTrue/MCdeltaEta_deltaPhi_mixed"), deltaPhi, deltaEta, triggerWeight * associatedWeight); + registry.fill(HIST("MCTrue/MCdeltaEta_deltaPhi_mixed"), deltaPhi, deltaEta, eventWeight * triggerWeight * associatedWeight); } } } @@ -652,7 +649,7 @@ struct DiHadronCor { fillYield(collision, tracks); same->fillEvent(tracks.size(), CorrelationContainer::kCFStepReconstructed); - fillCorrelations(tracks, tracks, collision.posZ(), SameEvent, getMagneticField(bc.timestamp()), cent); + fillCorrelations(tracks, tracks, collision.posZ(), SameEvent, getMagneticField(bc.timestamp()), cent, 1.0f); } PROCESS_SWITCH(DiHadronCor, processSame, "Process same event", true); @@ -671,8 +668,9 @@ struct DiHadronCor { MixedBinning binningOnVtxAndMult{{getTracksSize}, {axisVtxMix, axisMultMix}, true}; auto tracksTuple = std::make_tuple(tracks, tracks); - Pair pair{binningOnVtxAndMult, cfgMixEventNumMin, -1, collisions, tracksTuple, &cache}; // -1 is the number of the bin to skip - for (auto const& [collision1, tracks1, collision2, tracks2] : pair) { + Pair pairs{binningOnVtxAndMult, 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; @@ -702,8 +700,12 @@ struct DiHadronCor { registry.fill(HIST("eventcount"), MixedEvent); // fill the mixed event in the 3 bin auto bc = collision1.bc_as(); loadEfficiency(bc.timestamp()); + float eventWeight = 1.0f; + if (cfgUseEventWeights) { + eventWeight = 1.0f / it.currentWindowNeighbours(); + } - fillCorrelations(tracks1, tracks2, collision1.posZ(), MixedEvent, getMagneticField(bc.timestamp()), cent1); + fillCorrelations(tracks1, tracks2, collision1.posZ(), MixedEvent, getMagneticField(bc.timestamp()), cent1, eventWeight); } } @@ -723,7 +725,7 @@ struct DiHadronCor { } } - void processMCEfficiency(FilteredMcCollisions::iterator const& mcCollision, aod::BCsWithTimestamps const&, soa::SmallGroups> const& collisions, FilteredMcParticles const& mcParticles, FilteredTracksWithMCLabels const& tracks) + void processMCEfficiency(FilteredMcCollisions::iterator const& mcCollision, soa::SmallGroups> const& collisions, FilteredMcParticles const& mcParticles, FilteredTracksWithMCLabels const& tracks) { if (cfgSelCollByNch && (tracks.size() < cfgCutMultMin || tracks.size() >= cfgCutMultMax)) { return; @@ -731,6 +733,7 @@ struct DiHadronCor { // Primaries for (const auto& mcParticle : mcParticles) { if (mcParticle.isPhysicalPrimary()) { + registry.fill(HIST("MCEffeventcount"), 0.5); same->getTrackHistEfficiency()->Fill(CorrelationContainer::MC, mcParticle.eta(), mcParticle.pt(), getSpecies(mcParticle.pdgCode()), 0., mcCollision.posZ()); } } @@ -745,11 +748,14 @@ struct DiHadronCor { if (track.has_mcParticle()) { const auto& mcParticle = track.mcParticle(); if (mcParticle.isPhysicalPrimary()) { + registry.fill(HIST("MCEffeventcount"), 1.5); same->getTrackHistEfficiency()->Fill(CorrelationContainer::RecoPrimaries, mcParticle.eta(), mcParticle.pt(), getSpecies(mcParticle.pdgCode()), 0., mcCollision.posZ()); } + registry.fill(HIST("MCEffeventcount"), 2.5); same->getTrackHistEfficiency()->Fill(CorrelationContainer::RecoAll, mcParticle.eta(), mcParticle.pt(), getSpecies(mcParticle.pdgCode()), 0., mcCollision.posZ()); } else { // fake track + registry.fill(HIST("MCEffeventcount"), 3.5); same->getTrackHistEfficiency()->Fill(CorrelationContainer::Fake, track.eta(), track.pt(), 0, 0., mcCollision.posZ()); } } @@ -791,14 +797,15 @@ struct DiHadronCor { } same->fillEvent(mcParticles.size(), CorrelationContainer::kCFStepAll); - fillMCCorrelations(mcParticles, mcParticles, mcCollision.posZ(), SameEvent); + fillMCCorrelations(mcParticles, mcParticles, mcCollision.posZ(), SameEvent, 1.0f); if (collisions.size() == 0) { return; } + registry.fill(HIST("MCTrue/MCeventcount"), 2.5); same->fillEvent(mcParticles.size(), CorrelationContainer::kCFStepTrackedOnlyPrim); - fillMCCorrelations(mcParticles, mcParticles, mcCollision.posZ(), SameEvent); + fillMCCorrelations(mcParticles, mcParticles, mcCollision.posZ(), SameEvent, 1.0f); } PROCESS_SWITCH(DiHadronCor, processMCSame, "Process MC same event", false); @@ -815,8 +822,9 @@ struct DiHadronCor { MixedBinning binningOnVtxAndMult{{getTracksSize}, {axisVtxMix, axisMultMix}, true}; auto tracksTuple = std::make_tuple(mcParticles, mcParticles); - Pair pair{binningOnVtxAndMult, cfgMixEventNumMin, -1, mcCollisions, tracksTuple, &cache}; // -1 is the number of the bin to skip - for (auto const& [collision1, tracks1, collision2, tracks2] : pair) { + Pair pairs{binningOnVtxAndMult, 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 (cfgSelCollByNch && (tracks1.size() < cfgCutMultMin || tracks1.size() >= cfgCutMultMax)) continue; @@ -839,14 +847,18 @@ struct DiHadronCor { continue; registry.fill(HIST("MCTrue/MCeventcount"), MixedEvent); // fill the mixed event in the 3 bin + float eventWeight = 1.0f; + if (cfgUseEventWeights) { + eventWeight = 1.0f / it.currentWindowNeighbours(); + } - fillMCCorrelations(tracks1, tracks2, collision1.posZ(), MixedEvent); + fillMCCorrelations(tracks1, tracks2, collision1.posZ(), MixedEvent, eventWeight); if (groupedCollisions.size() == 0) { continue; } - fillMCCorrelations(tracks1, tracks2, collision1.posZ(), MixedEvent); + fillMCCorrelations(tracks1, tracks2, collision1.posZ(), MixedEvent, eventWeight); } } PROCESS_SWITCH(DiHadronCor, processMCMixed, "Process MC mixed events", false); @@ -873,10 +885,10 @@ struct DiHadronCor { } same->fillEvent(mcParticles.size(), CorrelationContainer::kCFStepAll); - fillMCCorrelations(mcParticles, mcParticles, mcCollision.posZ(), SameEvent); + fillMCCorrelations(mcParticles, mcParticles, mcCollision.posZ(), SameEvent, 1.0f); same->fillEvent(mcParticles.size(), CorrelationContainer::kCFStepTrackedOnlyPrim); - fillMCCorrelations(mcParticles, mcParticles, mcCollision.posZ(), SameEvent); + fillMCCorrelations(mcParticles, mcParticles, mcCollision.posZ(), SameEvent, 1.0f); } PROCESS_SWITCH(DiHadronCor, processOntheflySame, "Process on-the-fly same event", false); @@ -893,8 +905,9 @@ struct DiHadronCor { MixedBinning binningOnVtxAndMult{{getTracksSize}, {axisVtxMix, axisMultMix}, true}; auto tracksTuple = std::make_tuple(mcParticles, mcParticles); - Pair pair{binningOnVtxAndMult, cfgMixEventNumMin, -1, mcCollisions, tracksTuple, &cache}; // -1 is the number of the bin to skip - for (auto const& [collision1, tracks1, collision2, tracks2] : pair) { + Pair pairs{binningOnVtxAndMult, 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 (cfgSelCollByNch && (tracks1.size() < cfgCutMultMin || tracks1.size() >= cfgCutMultMax)) continue; @@ -903,10 +916,14 @@ struct DiHadronCor { continue; registry.fill(HIST("MCTrue/MCeventcount"), MixedEvent); // fill the mixed event in the 3 bin + float eventWeight = 1.0f; + if (cfgUseEventWeights) { + eventWeight = 1.0f / it.currentWindowNeighbours(); + } - fillMCCorrelations(tracks1, tracks2, collision1.posZ(), MixedEvent); + fillMCCorrelations(tracks1, tracks2, collision1.posZ(), MixedEvent, eventWeight); - fillMCCorrelations(tracks1, tracks2, collision1.posZ(), MixedEvent); + fillMCCorrelations(tracks1, tracks2, collision1.posZ(), MixedEvent, eventWeight); } } PROCESS_SWITCH(DiHadronCor, processOntheflyMixed, "Process on-the-fly mixed events", false); From fa73d9137b69f8947d93b0119e0a2c8b9ed8695b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADt=20Ku=C4=8Dera?= Date: Thu, 12 Jun 2025 07:23:03 +0200 Subject: [PATCH 029/871] [PWGHF,Tutorial] Include What You Use (#11553) --- Tutorials/PWGHF/DataModelMini.h | 7 ++++- Tutorials/PWGHF/skimCreatorMini.cxx | 31 +++++++++++++-------- Tutorials/PWGHF/taskMini.cxx | 42 ++++++++++++++++++----------- 3 files changed, 52 insertions(+), 28 deletions(-) diff --git a/Tutorials/PWGHF/DataModelMini.h b/Tutorials/PWGHF/DataModelMini.h index 7a03f1462b7..720b7207676 100644 --- a/Tutorials/PWGHF/DataModelMini.h +++ b/Tutorials/PWGHF/DataModelMini.h @@ -17,7 +17,12 @@ #ifndef TUTORIALS_PWGHF_DATAMODELMINI_H_ #define TUTORIALS_PWGHF_DATAMODELMINI_H_ -#include "Framework/AnalysisDataModel.h" +#include "Common/Core/RecoDecay.h" + +#include +#include + +#include namespace o2::aod { diff --git a/Tutorials/PWGHF/skimCreatorMini.cxx b/Tutorials/PWGHF/skimCreatorMini.cxx index ac6b12e2004..6fba171cfbf 100644 --- a/Tutorials/PWGHF/skimCreatorMini.cxx +++ b/Tutorials/PWGHF/skimCreatorMini.cxx @@ -14,21 +14,30 @@ /// /// \author Vít Kučera , Inha University -// O2 -#include "CommonConstants/PhysicsConstants.h" -#include "DCAFitter/DCAFitterN.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" - -// O2Physics +#include "Tutorials/PWGHF/DataModelMini.h" +// #include "Common/Core/RecoDecay.h" #include "Common/Core/trackUtilities.h" #include "Common/DataModel/TrackSelectionTables.h" -// PWGHF -#include "Tutorials/PWGHF/DataModelMini.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include using namespace o2; using namespace o2::aod; diff --git a/Tutorials/PWGHF/taskMini.cxx b/Tutorials/PWGHF/taskMini.cxx index 871fe710581..1876d6230cc 100644 --- a/Tutorials/PWGHF/taskMini.cxx +++ b/Tutorials/PWGHF/taskMini.cxx @@ -14,23 +14,33 @@ /// /// \author Vít Kučera , Inha University -// O2 -#include "CommonConstants/PhysicsConstants.h" -#include "DCAFitter/DCAFitterN.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" - -// O2Physics +#include "Tutorials/PWGHF/DataModelMini.h" +// +#include "PWGHF/Core/HfHelper.h" +// #include "Common/Core/RecoDecay.h" #include "Common/Core/TrackSelectorPID.h" #include "Common/Core/trackUtilities.h" -#include "Common/DataModel/PIDResponse.h" - -// PWGHF -#include "PWGHF/Core/HfHelper.h" -#include "Tutorials/PWGHF/DataModelMini.h" +#include "Common/DataModel/PIDResponseTOF.h" +#include "Common/DataModel/PIDResponseTPC.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include using namespace o2; using namespace o2::aod; @@ -314,8 +324,8 @@ struct HfTaskMiniD0 { WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{ - adaptAnalysisTask(cfgc, TaskName{"hf-task-mini-candidate-creator-2prong"}), // o2-linter: disable=name/o2-task - adaptAnalysisTask(cfgc, TaskName{"hf-task-mini-candidate-creator-2prong-expressions"}), // o2-linter: disable=name/o2-task + adaptAnalysisTask(cfgc, TaskName{"hf-task-mini-candidate-creator-2prong"}), // o2-linter: disable=name/o2-task (wrong hyphenation) + adaptAnalysisTask(cfgc, TaskName{"hf-task-mini-candidate-creator-2prong-expressions"}), // o2-linter: disable=name/o2-task (wrong hyphenation) adaptAnalysisTask(cfgc), adaptAnalysisTask(cfgc)}; } From af854a45d3d591260e8eefab7816d4a877dcd8dc Mon Sep 17 00:00:00 2001 From: Simone Ragoni <47641042+siragoni@users.noreply.github.com> Date: Thu, 12 Jun 2025 08:34:43 +0200 Subject: [PATCH 030/871] [PWGUD] new task for inclusive MC (#11498) --- PWGUD/Tasks/CMakeLists.txt | 7 +- PWGUD/Tasks/analysisMCDPMJetSGv3.cxx | 412 +++++++++++++++++++++++++++ 2 files changed, 418 insertions(+), 1 deletion(-) create mode 100644 PWGUD/Tasks/analysisMCDPMJetSGv3.cxx diff --git a/PWGUD/Tasks/CMakeLists.txt b/PWGUD/Tasks/CMakeLists.txt index a193e46587e..d828261167c 100644 --- a/PWGUD/Tasks/CMakeLists.txt +++ b/PWGUD/Tasks/CMakeLists.txt @@ -246,5 +246,10 @@ o2physics_add_dpl_workflow(flow-cumulants-upc o2physics_add_dpl_workflow(flow-correlations-upc SOURCES flowCorrelationsUpc.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::AnalysisCCDB O2Physics::PWGCFCore + 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 COMPONENT_NAME Analysis) diff --git a/PWGUD/Tasks/analysisMCDPMJetSGv3.cxx b/PWGUD/Tasks/analysisMCDPMJetSGv3.cxx new file mode 100644 index 00000000000..4347871377a --- /dev/null +++ b/PWGUD/Tasks/analysisMCDPMJetSGv3.cxx @@ -0,0 +1,412 @@ +// 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 AnalysisMCDPMJetSGv3.cxx +/// \brief Process MC DPMJet events for inclusive studies. +/// +/// \author Simone Ragoni + +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "Framework/ASoAHelpers.h" +// #include "TDatabasePDG.h" +#include "PWGUD/Core/UPCHelpers.h" +#include "PWGUD/DataModel/UDTables.h" +// #include "TLorentzVector.h" +// #include "TVector3.h" +#include "Math/LorentzVector.h" // ROOT::Math::LorentzVector +#include "Math/PxPyPzM4D.h" // ROOT::Math::PxPyPzM4D +#include "TMath.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +struct AnalysisMCDPMJetSGv3 { + HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + // TDatabasePDG* fPDG = TDatabasePDG::Instance(); + + Configurable nBinsPt{"nBinsPt", 100, "N bins in pT histo"}; + + // using myCompleteTracks = soa::Join; + // using myFilteredTracks = soa::Filtered; + using BCs = soa::Join; + + Preslice perCollision = aod::track::collisionId; + Preslice perMcCollision = o2::aod::mcparticle::mcCollisionId; + // using MCTCs = soa::Join; + // using MCTC = MCTCs::iterator; + // define abbreviations + using CCs = soa::Join; + using CC = CCs::iterator; + using MCparticles = aod::UDMcParticles::iterator; + using TCs = soa::Join; + // using TCs = soa::Join; + using TC = TCs::iterator; + using LorentzVectorM = ROOT::Math::LorentzVector>; + + double massPion = 0.; + double massKaon = 0.; + double massProton = 0.; + const int codePion = 211; + const int codeKaon = 321; + const int codeProton = 2212; + + void init(InitContext const&) + { + // TParticlePDG* pionPDG = fPDG->GetParticle(codePion); + // if (pionPDG != nullptr) { + // massPion = pionPDG->Mass(); + // } + // TParticlePDG* kaonPDG = fPDG->GetParticle(codeKaon); + // if (kaonPDG != nullptr) { + // massKaon = kaonPDG->Mass(); + // } + // TParticlePDG* protonPDG = fPDG->GetParticle(codeProton); + // if (protonPDG != nullptr) { + // massProton = protonPDG->Mass(); + // } + massPion = o2::constants::physics::MassPionCharged; + massKaon = o2::constants::physics::MassKaonCharged; + massProton = o2::constants::physics::MassProton; + + // define axes you want to use + const AxisSpec axisCounter{10, 0, 10, ""}; + const AxisSpec axisEta{100, -1.5, +1.5, "#eta"}; + const AxisSpec axisPt{5000, 0, 5, "p_{T}"}; + const AxisSpec axisPtSmall{1000, 0, 1, "p_{T}"}; + const AxisSpec axisMass{nBinsPt, 0, 5, "m_{#pi#pi}"}; + const AxisSpec axisMassSmall{nBinsPt, 0, 2, "m_{#pi#pi}"}; + const AxisSpec axisDeltaPt{100, -1.0, +1.0, "#Delta(p_{T})"}; + const AxisSpec axisBC{1000, -10000.0, +10000.0, "BCs"}; + const AxisSpec axisBCext{100000, -10000000.0, +10000000.0, "BCs"}; + const AxisSpec axisCosTheta{100, -1.0, +1.0, "cos#theta"}; + const AxisSpec axisPhi{600, -o2::constants::math::PI, -o2::constants::math::PI, "#varphi"}; + + // create histograms + histos.add("hdEdx", "p vs dE/dx Signal", kTH2F, {{100, 0.0, 3.0}, {1000, 0.0, 2000.0}}); + histos.add("hSigmaPion", "p vs dE/dx sigma pion TPC ", kTH2F, {{300, 0.0, 3.0}, {200, -10.0, 10.0}}); + histos.add("hSigmaPionTruth", "p vs dE/dx sigma pion TPC truth", kTH2F, {{300, 0.0, 3.0}, {200, -10.0, 10.0}}); + histos.add("hSigmaPionTOF", "p vs dE/dx sigma pion TOF ", kTH2F, {{300, 0.0, 3.0}, {200, -10.0, 10.0}}); + histos.add("hSigmaPionTruthTOF", "p vs dE/dx sigma pion TOF truth", kTH2F, {{300, 0.0, 3.0}, {200, -10.0, 10.0}}); + histos.add("hSigmaKaon", "p vs dE/dx sigma kaon TPC ", kTH2F, {{300, 0.0, 3.0}, {200, -10.0, 10.0}}); + histos.add("hSigmaKaonTruth", "p vs dE/dx sigma kaon TPC truth", kTH2F, {{300, 0.0, 3.0}, {200, -10.0, 10.0}}); + histos.add("hSigmaKaonTOF", "p vs dE/dx sigma kaon TOF ", kTH2F, {{300, 0.0, 3.0}, {200, -10.0, 10.0}}); + histos.add("hSigmaKaonTruthTOF", "p vs dE/dx sigma kaon TOF truth", kTH2F, {{300, 0.0, 3.0}, {200, -10.0, 10.0}}); + histos.add("hSigmaProton", "p vs dE/dx sigma proton TPC ", kTH2F, {{300, 0.0, 3.0}, {200, -10.0, 10.0}}); + histos.add("hSigmaProtonTruth", "p vs dE/dx sigma proton TPC truth", kTH2F, {{300, 0.0, 3.0}, {200, -10.0, 10.0}}); + histos.add("hSigmaProtonTOF", "p vs dE/dx sigma proton TOF ", kTH2F, {{300, 0.0, 3.0}, {200, -10.0, 10.0}}); + histos.add("hSigmaProtonTruthTOF", "p vs dE/dx sigma proton TOF truth", kTH2F, {{300, 0.0, 3.0}, {200, -10.0, 10.0}}); + + histos.add("hVisibleMultiVsGeneratedMulti", "Multiplicity correlation", kTH2F, {{10000, -0.5, 9999.5}, {1000, -0.5, 999.5}}); + + histos.add("eventCounter", "eventCounter", kTH1F, {axisCounter}); + histos.add("ptResolution", "ptResolution", kTH2F, {axisPt, axisDeltaPt}); + + histos.add("ptGeneratedPion", "ptGeneratedPion", kTH1F, {axisPt}); + histos.add("ptGeneratedKaon", "ptGeneratedKaon", kTH1F, {axisPt}); + histos.add("ptGeneratedProton", "ptGeneratedProton", kTH1F, {axisPt}); + histos.add("ptGeneratedPionAxE", "ptGeneratedPionAxE", kTH1F, {axisPt}); + histos.add("ptGeneratedKaonAxE", "ptGeneratedKaonAxE", kTH1F, {axisPt}); + histos.add("ptGeneratedProtonAxE", "ptGeneratedProtonAxE", kTH1F, {axisPt}); + histos.add("ptGeneratedProtonAxEPos", "ptGeneratedProtonAxEPos", kTH1F, {axisPt}); + histos.add("ptGeneratedProtonAxENeg", "ptGeneratedProtonAxENeg", kTH1F, {axisPt}); + histos.add("ptReconstructedPion", "ptReconstructedPion", kTH1F, {axisPt}); + histos.add("ptReconstructedKaon", "ptReconstructedKaon", kTH1F, {axisPt}); + histos.add("ptReconstructedProton", "ptReconstructedProton", kTH1F, {axisPt}); + histos.add("ptReconstructedProtonPos", "ptReconstructedProtonPos", kTH1F, {axisPt}); + histos.add("ptReconstructedProtonNeg", "ptReconstructedProtonNeg", kTH1F, {axisPt}); + histos.add("ptReconstructedPionTOF", "ptReconstructedPionTOF", kTH1F, {axisPt}); + histos.add("ptReconstructedKaonTOF", "ptReconstructedKaonTOF", kTH1F, {axisPt}); + histos.add("ptReconstructedProtonTOF", "ptReconstructedProtonTOF", kTH1F, {axisPt}); + + histos.add("allreconstructedPFPion", "allreconstructedPFPion", kTH1F, {axisPt}); + histos.add("allreconstructedPFKaon", "allreconstructedPFKaon", kTH1F, {axisPt}); + histos.add("allreconstructedPFProton", "allreconstructedPFProton", kTH1F, {axisPt}); + histos.add("allreconstructedPFProtonPos", "allreconstructedPFProtonPos", kTH1F, {axisPt}); + histos.add("allreconstructedPFProtonNeg", "allreconstructedPFProtonNeg", kTH1F, {axisPt}); + histos.add("allreconstructedPFPionTOF", "allreconstructedPFPionTOF", kTH1F, {axisPt}); + histos.add("allreconstructedPFKaonTOF", "allreconstructedPFKaonTOF", kTH1F, {axisPt}); + histos.add("allreconstructedPFProtonTOF", "allreconstructedPFProtonTOF", kTH1F, {axisPt}); + + histos.add("numberOfRecoCollisions", "numberOfRecoCollisions", kTH1F, {{100, -0.5f, 99.5f}}); + histos.add("numberOfRecoCollisions2", "numberOfRecoCollisions2", kTH1F, {{100, -0.5f, 99.5f}}); + histos.add("numberOfTracksMC", "numberOfTracksMC", kTH1F, {{100, -0.5f, 99.5f}}); + histos.add("numberOfTracksReco", "numberOfTracksReco", kTH1F, {{100, -0.5f, 99.5f}}); + + histos.add("bcResolution", "bcResolution", kTH1F, {axisBC}); + histos.add("mcbcHistogram", "mcbcHistogram", kTH1F, {axisBCext}); + histos.add("bcHistogram", "bcHistogram", kTH1F, {axisBCext}); + histos.add("mcbcModuloOrbitHistogram", "mcbcModuloOrbitHistogram", kTH1F, {axisBC}); + histos.add("bcModuloOrbitHistogram", "bcModuloOrbitHistogram", kTH1F, {axisBC}); + } + //----------------------------------------------------------------------------------------------------------------------- + void processSim(aod::UDMcCollision const& mcCollision, aod::UDMcParticles const& mcParticles) + { + // histos.fill(HIST("eventCounter"), 0.5); + + // auto massPion = 0.; + // TParticlePDG pionPDG = fPDG->GetParticle(codePion); + // massPion = pionPDG.Mass(); + // auto massKaon = 0.; + // TParticlePDG kaonPDG = fPDG->GetParticle(codeKaon); + // massKaon = kaonPDG.Mass(); + // auto massProton = 0.; + // TParticlePDG protonPDG = fPDG->GetParticle(codeProton); + // massProton = protonPDG.Mass(); + histos.fill(HIST("numberOfTracksMC"), mcParticles.size()); + histos.fill(HIST("eventCounter"), mcCollision.size()); + // LOGF(info, "New event! mcParticles.size() = %d", mcParticles.size()); + + int counterMC = 0; + int counter = 0; + for (const auto& mcParticle : mcParticles) { + if (!mcParticle.isPhysicalPrimary()) + continue; + counterMC += 1; + // if(mcParticle.isPhysicalPrimary()) counterMC += 1; + LorentzVectorM protoMC( + mcParticle.px(), + mcParticle.py(), + mcParticle.pz(), + massPion); + double etaMax = 0.8; + double ptMin = 0.1; + if (std::fabs(protoMC.Eta()) < etaMax && protoMC.Pt() > ptMin) { + counter += 1; + } + if (!mcParticle.isPhysicalPrimary()) + continue; + // if(mcParticle.isPhysicalPrimary() && fabs(mcParticle.eta())<0.9){ // do this in the context of the MC loop ! (context matters!!!) + // LorentzVectorM pMC; + LorentzVectorM pMC(mcParticle.px(), mcParticle.py(), mcParticle.pz(), massPion); + if (std::abs(mcParticle.pdgCode()) == codePion) { + // histos.fill(HIST("ptGeneratedPion"), mcParticle.pt()); + // LorentzVectorM pMC(mcParticle.px(), mcParticle.py(), mcParticle.pz(), massPion); + histos.fill(HIST("ptGeneratedPion"), pMC.Pt()); + } + if (std::abs(mcParticle.pdgCode()) == codeKaon) { + // histos.fill(HIST("ptGenerateKaon"), mcParticle.pt()); + // LorentzVectorM pMC(mcParticle.px(), mcParticle.py(), mcParticle.pz(), massKaon); + pMC.SetM(massKaon); + histos.fill(HIST("ptGeneratedKaon"), pMC.Pt()); + } + if (std::abs(mcParticle.pdgCode()) == codeProton) { + // histos.fill(HIST("ptGeneratedProton"), mcParticle.pt()); + // LorentzVectorM pMC(mcParticle.px(), mcParticle.py(), mcParticle.pz(), massProton); + pMC.SetM(massProton); + histos.fill(HIST("ptGeneratedProton"), pMC.Pt()); + } + double yMax = 0.8; + if (std::abs(pMC.Rapidity()) < yMax) { + if (std::abs(mcParticle.pdgCode()) == codePion) + histos.fill(HIST("ptGeneratedPionAxE"), pMC.Pt()); + if (std::abs(mcParticle.pdgCode()) == codeKaon) + histos.fill(HIST("ptGeneratedKaonAxE"), pMC.Pt()); + if (std::abs(mcParticle.pdgCode()) == codeProton) + histos.fill(HIST("ptGeneratedProtonAxE"), pMC.Pt()); + if (mcParticle.pdgCode() == codeProton) { + histos.fill(HIST("ptGeneratedProtonAxEPos"), pMC.Pt()); + } else { + histos.fill(HIST("ptGeneratedProtonAxENeg"), pMC.Pt()); + } + } + } + histos.fill(HIST("hVisibleMultiVsGeneratedMulti"), counterMC, counter); + } + PROCESS_SWITCH(AnalysisMCDPMJetSGv3, processSim, "processSim", true); + + void processReco(CC const& collision, + TCs const& tracks, + // aod::UDMcCollisions const& /*mccollisions*/, + aod::UDMcParticles const& mcParticles) + { + histos.fill(HIST("numberOfRecoCollisions"), 88.); // number of times coll was reco-ed + histos.fill(HIST("numberOfRecoCollisions"), collision.size()); // number of times coll was reco-ed + histos.fill(HIST("numberOfRecoCollisions2"), mcParticles.size()); + Partition pvContributors = aod::udtrack::isPVContributor == true; + pvContributors.bindTable(tracks); + + // auto massPion = 0.; + // TParticlePDG pionPDG = fPDG->GetParticle(codePion); + // massPion = pionPDG.Mass(); + // auto massKaon = 0.; + // TParticlePDG kaonPDG = fPDG->GetParticle(codeKaon); + // massKaon = kaonPDG.Mass(); + // auto massProton = 0.; + // TParticlePDG protonPDG = fPDG->GetParticle(codeProton); + // massProton = protonPDG.Mass(); + + histos.fill(HIST("numberOfTracksReco"), tracks.size()); + // double etaMax = 0.8; + double yMax = 0.8; + double sigmaMax = 3.; + double ptMin = 0.1; + int nFindableMin = 70; + double dcaZlimit = 2.; + + // int counter = 0; + for (const auto& track : tracks) { + if (track.isPVContributor()) { + int nFindable = track.tpcNClsFindable(); + if (nFindable < nFindableMin) { + continue; + } + // int NMinusFound = track.tpcNClsFindableMinusFound(); + // int NCluster = NFindable - NMinusFound; + // if (NCluster < 70) { + // continue; + // } + if (track.pt() < ptMin) { + continue; + } + if (!(std::abs(track.dcaZ()) < dcaZlimit)) { + continue; + } + double dcaLimit = 0.0105 + 0.035 / std::pow(track.pt(), 1.1); + if (!(std::abs(track.dcaXY()) < dcaLimit)) { + continue; + } + + double momentum = std::sqrt(track.px() * track.px() + track.py() * track.py() + track.pz() * track.pz()); + double dEdx = track.tpcSignal(); + histos.fill(HIST("hdEdx"), momentum, dEdx); + + LorentzVectorM pion(track.px(), track.py(), track.pz(), o2::constants::physics::MassPionCharged); + LorentzVectorM kaon(track.px(), track.py(), track.pz(), o2::constants::physics::MassKaonCharged); + LorentzVectorM proton(track.px(), track.py(), track.pz(), o2::constants::physics::MassProton); + auto nSigmaPi = -999.; + auto nSigmaKa = -999.; + auto nSigmaPr = -999.; + auto nSigmaPiTOF = -999.; + auto nSigmaKaTOF = -999.; + auto nSigmaPrTOF = -999.; + // This section makes templates + if (track.hasTPC()) { + nSigmaPi = track.tpcNSigmaPi(); + nSigmaKa = track.tpcNSigmaKa(); + nSigmaPr = track.tpcNSigmaPr(); + if (std::abs(nSigmaPi) < sigmaMax && std::abs(pion.Rapidity()) < yMax) { + histos.fill(HIST("hSigmaPion"), track.pt(), nSigmaPi); + if (track.has_udMcParticle()) { + auto mcParticle = track.udMcParticle(); + // if(abs(mcParticle.pdgCode())==codePion && mcParticle.isPhysicalPrimary()) howManyPionsHavePionMCandPrimaries += 1; + if (std::abs(mcParticle.pdgCode()) == codePion) { + histos.fill(HIST("hSigmaPionTruth"), track.pt(), nSigmaPi); + histos.fill(HIST("allreconstructedPFPion"), track.pt()); + if (mcParticle.isPhysicalPrimary()) { + histos.fill(HIST("ptReconstructedPion"), track.pt()); + } + } + } + } + if (std::abs(nSigmaKa) < sigmaMax && std::abs(kaon.Rapidity()) < yMax) { + histos.fill(HIST("hSigmaKaon"), track.pt(), nSigmaKa); + if (track.has_udMcParticle()) { + auto mcParticle = track.udMcParticle(); + if (std::abs(mcParticle.pdgCode()) == codeKaon) { + histos.fill(HIST("hSigmaKaonTruth"), track.pt(), nSigmaKa); + histos.fill(HIST("allreconstructedPFKaon"), track.pt()); + if (mcParticle.isPhysicalPrimary()) { + histos.fill(HIST("ptReconstructedKaon"), track.pt()); + } + } + } + } + if (std::abs(nSigmaPr) < sigmaMax && std::abs(proton.Rapidity()) < yMax) { + histos.fill(HIST("hSigmaProton"), track.pt(), nSigmaPr); + if (track.has_udMcParticle()) { + auto mcParticle = track.udMcParticle(); + if (std::abs(mcParticle.pdgCode()) == codeProton) { + histos.fill(HIST("hSigmaProtonTruth"), track.pt(), nSigmaPr); + histos.fill(HIST("allreconstructedPFProton"), track.pt()); + if (mcParticle.pdgCode() == codeProton) { + histos.fill(HIST("allreconstructedPFProtonPos"), track.pt()); + } else { + histos.fill(HIST("allreconstructedPFProtonNeg"), track.pt()); + } + if (mcParticle.isPhysicalPrimary()) { + histos.fill(HIST("ptReconstructedProton"), track.pt()); + if (mcParticle.pdgCode() == codeProton) { + histos.fill(HIST("ptReconstructedProtonPos"), track.pt()); + } else { + histos.fill(HIST("ptReconstructedProtonNeg"), track.pt()); + } + } + } + } + } + } + if (track.hasTPC() && track.hasTOF()) { + // if (track.hasTOF()) { + nSigmaPiTOF = track.tofNSigmaPi(); + nSigmaKaTOF = track.tofNSigmaKa(); + nSigmaPrTOF = track.tofNSigmaPr(); + if (std::abs(nSigmaPiTOF) < sigmaMax && std::abs(pion.Rapidity()) < yMax) { + histos.fill(HIST("hSigmaPionTOF"), track.pt(), nSigmaPiTOF); + if (track.has_udMcParticle()) { + auto mcParticle = track.udMcParticle(); + // if(abs(mcParticle.pdgCode())==codePion && mcParticle.isPhysicalPrimary()) howManyPionsHavePionMCandPrimaries += 1; + if (std::abs(mcParticle.pdgCode()) == codePion) { + histos.fill(HIST("hSigmaPionTruthTOF"), track.pt(), nSigmaPiTOF); + histos.fill(HIST("allreconstructedPFPionTOF"), track.pt()); + if (mcParticle.isPhysicalPrimary()) { + histos.fill(HIST("ptReconstructedPionTOF"), track.pt()); + } + } + } + } + if (std::abs(nSigmaKaTOF) < sigmaMax && std::abs(kaon.Rapidity()) < yMax) { + histos.fill(HIST("hSigmaKaonTOF"), track.pt(), nSigmaKaTOF); + if (track.has_udMcParticle()) { + auto mcParticle = track.udMcParticle(); + if (std::abs(mcParticle.pdgCode()) == codeKaon) { + histos.fill(HIST("hSigmaKaonTruthTOF"), track.pt(), nSigmaKaTOF); + histos.fill(HIST("allreconstructedPFKaonTOF"), track.pt()); + if (mcParticle.isPhysicalPrimary()) { + histos.fill(HIST("ptReconstructedKaonTOF"), track.pt()); + } + } + } + } + if (std::abs(nSigmaPrTOF) < sigmaMax && std::abs(proton.Rapidity()) < yMax) { + histos.fill(HIST("hSigmaProtonTOF"), track.pt(), nSigmaPrTOF); + if (track.has_udMcParticle()) { + auto mcParticle = track.udMcParticle(); + if (std::abs(mcParticle.pdgCode()) == codeProton) { + histos.fill(HIST("hSigmaProtonTruthTOF"), track.pt(), nSigmaPrTOF); + histos.fill(HIST("allreconstructedPFProtonTOF"), track.pt()); + if (mcParticle.isPhysicalPrimary()) { + histos.fill(HIST("ptReconstructedProtonTOF"), track.pt()); + } + } + } + } + } + // counter++; + // histos.fill(HIST("hVisibleMultiVsGeneratedMulti"), counterMC, counter); + // histos.fill(HIST("hVisibleMultiVsGeneratedMulti"), mcParticles.size(), counter); + } + } // track loop + + // } // collision loop + } + PROCESS_SWITCH(AnalysisMCDPMJetSGv3, processReco, "processReco", true); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +} From 844e127fec4262b979c9f8a5e5ff8661ae46353f Mon Sep 17 00:00:00 2001 From: Jesper Gumprecht <113693781+jesgum@users.noreply.github.com> Date: Thu, 12 Jun 2025 08:55:36 +0200 Subject: [PATCH 031/871] [ALICE3] Remove subscription to MCharmIndices (#11557) --- ALICE3/Tasks/alice3-multicharm.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ALICE3/Tasks/alice3-multicharm.cxx b/ALICE3/Tasks/alice3-multicharm.cxx index 34276a800b3..2b6ad804ddf 100644 --- a/ALICE3/Tasks/alice3-multicharm.cxx +++ b/ALICE3/Tasks/alice3-multicharm.cxx @@ -57,7 +57,7 @@ using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; -using multicharmtracks = soa::Join; +// using multicharmtracks = soa::Join; struct alice3multicharm { SliceCache cache; @@ -134,7 +134,7 @@ struct alice3multicharm { histos.add("h3dXicc", "h3dXicc; Xicc pT (GeV/#it(c)); Xicc #eta; Xicc mass (GeV/#it(c)^{2})", kTH3D, {axisPt, axisEta, axisXiccMass}); } - void processXicc(multicharmtracks const& multiCharmTracks) + void processXicc(aod::MCharmCores const& multiCharmTracks) { for (const auto& xiccCand : multiCharmTracks) { if (xiccCand.xicDauDCA() > xicMaxDauDCA || xiccCand.xiccDauDCA() > xiccMaxDauDCA) From e63bb0371138c30616d8e63f19ad803c25004988 Mon Sep 17 00:00:00 2001 From: yuanzhe <90246048+wang-yuanzhe@users.noreply.github.com> Date: Thu, 12 Jun 2025 09:15:28 +0200 Subject: [PATCH 032/871] [PWGLF] Add option to disable SV radius cut for kink (#11541) --- PWGLF/TableProducer/Common/kinkBuilder.cxx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/PWGLF/TableProducer/Common/kinkBuilder.cxx b/PWGLF/TableProducer/Common/kinkBuilder.cxx index d2b25be26a0..51be861741a 100644 --- a/PWGLF/TableProducer/Common/kinkBuilder.cxx +++ b/PWGLF/TableProducer/Common/kinkBuilder.cxx @@ -106,6 +106,7 @@ struct kinkBuilder { Configurable etaMax{"etaMax", 1., "eta daughter"}; Configurable nTPCClusMinDaug{"nTPCClusMinDaug", 80, "daug NTPC clusters cut"}; Configurable askTOFforDaug{"askTOFforDaug", false, "If true, ask for TOF signal"}; + Configurable doSVRadiusCut{"doSVRadiusCut", true, "If true, apply the cut on the radius of the secondary vertex and tracksIU"}; o2::vertexing::DCAFitterN<2> fitter; o2::base::MatLayerCylSet* lut = nullptr; @@ -329,7 +330,7 @@ struct kinkBuilder { // cut on decay radius to 17 cm float decRad2 = kinkCand.decVtx[0] * kinkCand.decVtx[0] + kinkCand.decVtx[1] * kinkCand.decVtx[1]; - if (decRad2 < LayerRadii[3] * LayerRadii[3]) { + if (doSVRadiusCut && decRad2 < LayerRadii[3] * LayerRadii[3]) { continue; } @@ -348,11 +349,11 @@ struct kinkBuilder { } } - if (lastLayerMoth >= firstLayerDaug) { + if (doSVRadiusCut && lastLayerMoth >= firstLayerDaug) { continue; } - if (decRad2 < LayerRadii[lastLayerMoth] * LayerRadii[lastLayerMoth]) { + if (doSVRadiusCut && decRad2 < LayerRadii[lastLayerMoth] * LayerRadii[lastLayerMoth]) { continue; } From 2fd49aab769d64a7dac561cbf607b5f4639a751c Mon Sep 17 00:00:00 2001 From: creetz16 <79141119+creetz16@users.noreply.github.com> Date: Thu, 12 Jun 2025 09:15:44 +0200 Subject: [PATCH 033/871] [PWGLF] Update hypertriton 3body decay analysis (#11512) Co-authored-by: ALICE Action Bot --- PWGLF/DataModel/Reduced3BodyTables.h | 28 +- PWGLF/DataModel/Vtx3BodyTables.h | 783 ++-- PWGLF/TableProducer/Nuspex/CMakeLists.txt | 17 +- .../Nuspex/decay3bodybuilder.cxx | 3334 ++++++----------- .../Nuspex/hypertriton3bodyfinder.cxx | 1197 ------ .../Nuspex/reduced3bodyCreator.cxx | 61 +- .../TableProducer/Nuspex/threebodyKFTask.cxx | 488 --- .../Nuspex/threebodyRecoTask.cxx | 909 ----- PWGLF/Tasks/Nuspex/CMakeLists.txt | 10 - PWGLF/Tasks/Nuspex/hypertriton3bodyMcqa.cxx | 908 ----- .../Tasks/Nuspex/hypertriton3bodyanalysis.cxx | 797 ---- PWGLF/Utils/decay3bodyBuilderHelper.h | 838 +++++ 12 files changed, 2219 insertions(+), 7151 deletions(-) delete mode 100644 PWGLF/TableProducer/Nuspex/hypertriton3bodyfinder.cxx delete mode 100644 PWGLF/TableProducer/Nuspex/threebodyKFTask.cxx delete mode 100644 PWGLF/TableProducer/Nuspex/threebodyRecoTask.cxx delete mode 100644 PWGLF/Tasks/Nuspex/hypertriton3bodyMcqa.cxx delete mode 100644 PWGLF/Tasks/Nuspex/hypertriton3bodyanalysis.cxx create mode 100644 PWGLF/Utils/decay3bodyBuilderHelper.h diff --git a/PWGLF/DataModel/Reduced3BodyTables.h b/PWGLF/DataModel/Reduced3BodyTables.h index 51fff63c81d..aeabfb92c0b 100644 --- a/PWGLF/DataModel/Reduced3BodyTables.h +++ b/PWGLF/DataModel/Reduced3BodyTables.h @@ -83,6 +83,7 @@ DECLARE_SOA_TABLE_FULL(StoredRedIUTracks, "RedIUTracks", "AOD", "REDIUTRACK", // // tracks extra track::PIDForTracking, track::IsPVContributor, + track::HasITS, track::HasTPC, track::HasTOF, track::TPCNClsFound, @@ -120,29 +121,22 @@ DECLARE_SOA_INDEX_COLUMN_FULL(Track0, track0, int, RedIUTracks, "_0"); //! DECLARE_SOA_INDEX_COLUMN_FULL(Track1, track1, int, RedIUTracks, "_1"); //! Track 1 index DECLARE_SOA_INDEX_COLUMN_FULL(Track2, track2, int, RedIUTracks, "_2"); //! Track 2 index DECLARE_SOA_INDEX_COLUMN_FULL(Collision, collision, int, RedCollisions, ""); //! Collision index -DECLARE_SOA_COLUMN(Phi, phi, float); //! decay3body radius -DECLARE_SOA_COLUMN(Radius, radius, float); //! decay3body phi -DECLARE_SOA_COLUMN(PosZ, posz, float); //! decay3body z position +DECLARE_SOA_COLUMN(RadiusKF, radiusKF, float); //! phi of momentum of mother particle calculated by KF +DECLARE_SOA_COLUMN(PhiKF, phiKF, float); //! SV radius in x-y plane calculated by KF +DECLARE_SOA_COLUMN(PosZKF, poszKF, float); //! z position of SV calculated by KF +DECLARE_SOA_COLUMN(RadiusDCA, radiusDCA, float); //! phi of momentum of mother particle calculated by dcaFitter +DECLARE_SOA_COLUMN(PhiDCA, phiDCA, float); //! SV radius in x-y plane calculated by dcaFitter +DECLARE_SOA_COLUMN(PosZDCA, poszDCA, float); //! z position of SV calculated by dcaFitter +DECLARE_SOA_COLUMN(TrackedClSize, trackedClSize, float); //! average ITS cluster size (if tracked) } // namespace reduceddecay3body DECLARE_SOA_TABLE(RedDecay3Bodys, "AOD", "REDDECAY3BODY", //! reduced 3-body decay table o2::soa::Index<>, reduceddecay3body::CollisionId, reduceddecay3body::Track0Id, reduceddecay3body::Track1Id, reduceddecay3body::Track2Id); -using ReducedDecay3BodysLinked = soa::Join; -using ReducedDecay3BodyLinked = ReducedDecay3BodysLinked::iterator; - DECLARE_SOA_TABLE(Red3BodyInfo, "AOD", "RED3BODYINFO", //! joinable with RedDecay3Bodys - reduceddecay3body::Radius, reduceddecay3body::Phi, reduceddecay3body::PosZ); - -namespace dcafittersvinfo -{ -DECLARE_SOA_COLUMN(SVRadius, svRadius, float); //! SV radius in x-y plane calculated by dcaFitter -DECLARE_SOA_COLUMN(MomPhi, momPhi, float); //! phi of momentum of mother particle calculated from dcaFitter -DECLARE_SOA_COLUMN(SVPosZ, svPosZ, float); //! z position of SV calculated by dcaFitter -} // namespace dcafittersvinfo - -DECLARE_SOA_TABLE_FULL(DCAFitterSVInfo, "FitSVInfo", "AOD", "FITSVINFO", //! joinable with RedDecay3Bodys - dcafittersvinfo::SVRadius, dcafittersvinfo::MomPhi, dcafittersvinfo::SVPosZ); + reduceddecay3body::RadiusKF, reduceddecay3body::PhiKF, reduceddecay3body::PosZKF, + reduceddecay3body::RadiusDCA, reduceddecay3body::PhiDCA, reduceddecay3body::PosZDCA, + reduceddecay3body::TrackedClSize); } // namespace o2::aod diff --git a/PWGLF/DataModel/Vtx3BodyTables.h b/PWGLF/DataModel/Vtx3BodyTables.h index 9ae43bb0255..f03dfa8254c 100644 --- a/PWGLF/DataModel/Vtx3BodyTables.h +++ b/PWGLF/DataModel/Vtx3BodyTables.h @@ -10,7 +10,7 @@ // or submit itself to any jurisdiction. /// \file Vtx3BodyTables.h -/// \brief Definitions of reduced tables for 3body decayed hypertriton +/// \brief Definitions of analysis tables for 3body decayed hypertriton /// \author Yuanzhe Wang /// \author Carolina Reetz @@ -26,48 +26,117 @@ namespace o2::aod { namespace vtx3body { -DECLARE_SOA_INDEX_COLUMN_FULL(Track0, track0, int, Tracks, "_0"); //! -DECLARE_SOA_INDEX_COLUMN_FULL(Track1, track1, int, Tracks, "_1"); //! -DECLARE_SOA_INDEX_COLUMN_FULL(Track2, track2, int, Tracks, "_2"); //! +// indices +DECLARE_SOA_INDEX_COLUMN_FULL(TrackPr, trackPr, int, Tracks, "_pr"); //! +DECLARE_SOA_INDEX_COLUMN_FULL(TrackPi, trackPi, int, Tracks, "_pi"); //! +DECLARE_SOA_INDEX_COLUMN_FULL(TrackDe, trackDe, int, Tracks, "_de"); //! DECLARE_SOA_INDEX_COLUMN(Collision, collision); //! DECLARE_SOA_INDEX_COLUMN(Decay3Body, decay3body); //! -// General 3 body Vtx properties: position, momentum -DECLARE_SOA_COLUMN(PxTrack0, pxtrack0, float); //! track0 px at min -DECLARE_SOA_COLUMN(PyTrack0, pytrack0, float); //! track0 py at min -DECLARE_SOA_COLUMN(PzTrack0, pztrack0, float); //! track0 pz at min -DECLARE_SOA_COLUMN(PxTrack1, pxtrack1, float); //! track1 px at min -DECLARE_SOA_COLUMN(PyTrack1, pytrack1, float); //! track1 py at min -DECLARE_SOA_COLUMN(PzTrack1, pztrack1, float); //! track1 pz at min -DECLARE_SOA_COLUMN(PxTrack2, pxtrack2, float); //! track2 px at min -DECLARE_SOA_COLUMN(PyTrack2, pytrack2, float); //! track2 py at min -DECLARE_SOA_COLUMN(PzTrack2, pztrack2, float); //! track2 pz at min -DECLARE_SOA_COLUMN(X, x, float); //! decay position X -DECLARE_SOA_COLUMN(Y, y, float); //! decay position Y -DECLARE_SOA_COLUMN(Z, z, float); //! decay position Z - -// Saved from finding: DCAs -DECLARE_SOA_COLUMN(DCAVtxDaughters, dcaVtxdaughters, float); //! DCA among daughters -DECLARE_SOA_COLUMN(DCAXYTrack0ToPV, dcaXYtrack0topv, float); //! DCAXY of prong0 to PV -DECLARE_SOA_COLUMN(DCAXYTrack1ToPV, dcaXYtrack1topv, float); //! DCAXY of prong1 to PV -DECLARE_SOA_COLUMN(DCAXYTrack2ToPV, dcaXYtrack2topv, float); //! DCAXY of prong2 to PV -DECLARE_SOA_COLUMN(DCATrack0ToPV, dcatrack0topv, float); //! DCA of prong0 to PV -DECLARE_SOA_COLUMN(DCATrack1ToPV, dcatrack1topv, float); //! DCA of prong1 to PV -DECLARE_SOA_COLUMN(DCATrack2ToPV, dcatrack2topv, float); //! DCA of prong2 to PV - -// Recalculated TOF PID information of bachelor -DECLARE_SOA_COLUMN(TOFNSigmaBachDe, tofNSigmaBachDe, float); //! Recalculated Nsigma seperation with TOF for deuteron +// General 3 body Vtx properties +DECLARE_SOA_COLUMN(Mass, mass, float); //! candidate mass (with H3L or Anti-H3L mass hypothesis depending on deuteron charge) +DECLARE_SOA_COLUMN(Sign, sign, float); //! candidate sign +DECLARE_SOA_COLUMN(X, x, float); //! decay position X +DECLARE_SOA_COLUMN(Y, y, float); //! decay position Y +DECLARE_SOA_COLUMN(Z, z, float); //! decay position Z +DECLARE_SOA_COLUMN(Px, px, float); //! momentum X +DECLARE_SOA_COLUMN(Py, py, float); //! momentum Y +DECLARE_SOA_COLUMN(Pz, pz, float); //! momentum Z +DECLARE_SOA_COLUMN(Chi2, chi2, float); //! KFParticle: chi2geo/ndf or chi2topo/ndf of vertex fit, DCA fitter: Chi2AtPCACandidate value + +// daughter properties +DECLARE_SOA_COLUMN(MassV0, massV0, float); //! V0 mass (with H3L or Anti-H3L mass hypothesis depending on deuteron charge) +DECLARE_SOA_COLUMN(PxTrackPr, pxTrackPr, float); //! track0 px at min +DECLARE_SOA_COLUMN(PyTrackPr, pyTrackPr, float); //! track0 py at min +DECLARE_SOA_COLUMN(PzTrackPr, pzTrackPr, float); //! track0 pz at min +DECLARE_SOA_COLUMN(PxTrackPi, pxTrackPi, float); //! track1 px at min +DECLARE_SOA_COLUMN(PyTrackPi, pyTrackPi, float); //! track1 py at min +DECLARE_SOA_COLUMN(PzTrackPi, pzTrackPi, float); //! track1 pz at min +DECLARE_SOA_COLUMN(PxTrackDe, pxTrackDe, float); //! track2 px at min +DECLARE_SOA_COLUMN(PyTrackDe, pyTrackDe, float); //! track2 py at min +DECLARE_SOA_COLUMN(PzTrackDe, pzTrackDe, float); //! track2 pz at min + +// DCAs to PV +DECLARE_SOA_COLUMN(DCAXYTrackPrToPV, dcaXYtrackPrToPv, float); //! DCAXY of proton to PV +DECLARE_SOA_COLUMN(DCAXYTrackPiToPV, dcaXYtrackPiToPv, float); //! DCAXY of pion to PV +DECLARE_SOA_COLUMN(DCAXYTrackDeToPV, dcaXYtrackDeToPv, float); //! DCAXY of deuteron to PV +DECLARE_SOA_COLUMN(DCAZTrackPrToPV, dcaZtrackPrToPv, float); //! DCAZ of proton to PV +DECLARE_SOA_COLUMN(DCAZTrackPiToPV, dcaZtrackPiToPv, float); //! DCAZ of pion to PV +DECLARE_SOA_COLUMN(DCAZTrackDeToPV, dcaZtrackDeToPv, float); //! DCAZ of deuteron to PV + +// DCAs to SV +DECLARE_SOA_COLUMN(DCATrackPrToSV, dcaTrackPrToSv, float); //! DCA of proton to SV +DECLARE_SOA_COLUMN(DCATrackPiToSV, dcaTrackPiToSv, float); //! DCA of pion to SV +DECLARE_SOA_COLUMN(DCATrackDeToSV, dcaTrackDeToSv, float); //! DCA of deuteron to SV +DECLARE_SOA_COLUMN(DCAVtxDaughters, dcaVtxdaughters, float); //! Quadratic sum of DCA between daughters at SV + +// Strangeness tracking +DECLARE_SOA_COLUMN(TrackedClSize, trackedClSize, float); //! Average ITS cluster size of strangeness tracked 3body + +// PID +DECLARE_SOA_COLUMN(TPCNSigmaPr, tpcNSigmaPr, float); //! nsigma proton of TPC PID of the proton daughter +DECLARE_SOA_COLUMN(TPCNSigmaPi, tpcNSigmaPi, float); //! nsigma pion of TPC PID of the pion daughter +DECLARE_SOA_COLUMN(TPCNSigmaDe, tpcNSigmaDe, float); //! nsigma deuteron of TPC PID of the bachelor daughter +DECLARE_SOA_COLUMN(TPCNSigmaPiBach, tpcNSigmaPiBach, float); //! nsigma pion of TPC PID of the bachelor daughter +DECLARE_SOA_COLUMN(TOFNSigmaDe, tofNSigmaDe, float); //! nsigma deuteron of TOF PID of the bachelor daughter +DECLARE_SOA_COLUMN(PIDTrackingDe, pidTrackingDe, uint32_t); //! PID during tracking of bachelor daughter + +// Daughter track quality +DECLARE_SOA_COLUMN(TPCNClTrackPr, tpcNClTrackPr, int); //! Number of TPC clusters of proton daughter +DECLARE_SOA_COLUMN(TPCNClTrackPi, tpcNClTrackPi, int); //! Number of TPC clusters of pion daughter +DECLARE_SOA_COLUMN(TPCNClTrackDe, tpcNClTrackDe, int); //! Number of TPC clusters of deuteron daughter +DECLARE_SOA_COLUMN(ITSClSizePr, itsClsizePr, double); //! average ITS cluster size of proton daughter +DECLARE_SOA_COLUMN(ITSClSizePi, itsClsizePi, double); //! average ITS cluster size of pion daughter +DECLARE_SOA_COLUMN(ITSClSizeDe, itsClsizeDe, double); //! average ITS cluster size of deuteron daughter + +// Covariance matrices +DECLARE_SOA_COLUMN(CovProton, covProton, float[21]); //! covariance matrix elements of proton daughter track +DECLARE_SOA_COLUMN(CovPion, covPion, float[21]); //! covariance matrix elements of pion daughter track +DECLARE_SOA_COLUMN(CovDeuteron, covDeuteron, float[21]); //! covariance matrix elements of deuteron daughter track +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(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 // Derived expressions // Momenta -DECLARE_SOA_DYNAMIC_COLUMN(P, p, //! 3 body p - [](float pxtrack0, float pytrack0, float pztrack0, float pxtrack1, float pytrack1, float pztrack1, float pxtrack2, float pytrack2, float pztrack2) -> float { return RecoDecay::sqrtSumOfSquares(pxtrack0 + pxtrack1 + pxtrack2, pytrack0 + pytrack1 + pytrack2, pztrack0 + pztrack1 + pztrack2); }); -DECLARE_SOA_DYNAMIC_COLUMN(Pt, pt, //! 3 body pT - [](float pxtrack0, float pytrack0, float pxtrack1, float pytrack1, float pxtrack2, float pytrack2) -> float { return RecoDecay::sqrtSumOfSquares(pxtrack0 + pxtrack1 + pxtrack2, pytrack0 + pytrack1 + pytrack2); }); +DECLARE_SOA_DYNAMIC_COLUMN(Pt, pt, //! 3 body pT in GeV/c + [](float px, float py) -> float { return RecoDecay::sqrtSumOfSquares(px, py); }); +DECLARE_SOA_DYNAMIC_COLUMN(P, p, //! 3 body total momentum in GeV/c + [](float px, float py, float pz) -> float { return RecoDecay::sqrtSumOfSquares(px, py, pz); }); +DECLARE_SOA_DYNAMIC_COLUMN(GenPt, genPt, //! 3 body pT in GeV/c + [](float genPx, float genPy) -> float { return RecoDecay::sqrtSumOfSquares(genPx, genPy); }); +DECLARE_SOA_DYNAMIC_COLUMN(GenP, genP, //! 3 body total momentum in GeV/c + [](float genPx, float genPy, float genPz) -> float { return RecoDecay::sqrtSumOfSquares(genPx, genPy, genPz); }); // Length quantities DECLARE_SOA_DYNAMIC_COLUMN(VtxRadius, vtxradius, //! 3 body decay radius (2D, centered at zero) [](float x, float y) -> float { return RecoDecay::sqrtSumOfSquares(x, y); }); +DECLARE_SOA_DYNAMIC_COLUMN(GenRadius, genRadius, //! 3 body decay radius (2D, centered at zero) + [](float genX, float genY) -> float { return RecoDecay::sqrtSumOfSquares(genX, genY); }); // Distance Over To Mom DECLARE_SOA_DYNAMIC_COLUMN(DistOverTotMom, distovertotmom, //! PV to 3 body decay distance over total momentum @@ -79,6 +148,7 @@ DECLARE_SOA_DYNAMIC_COLUMN(DistOverTotMom, distovertotmom, //! PV to 3 body deca // CosPA DECLARE_SOA_DYNAMIC_COLUMN(VtxCosPA, vtxcosPA, //! 3 body vtx CosPA [](float X, float Y, float Z, float Px, float Py, float Pz, float pvX, float pvY, float pvZ) -> float { return RecoDecay::cpa(std::array{pvX, pvY, pvZ}, std::array{X, Y, Z}, std::array{Px, Py, Pz}); }); + // Dca to PV DECLARE_SOA_DYNAMIC_COLUMN(DCAVtxToPV, dcavtxtopv, //! DCA of 3 body vtx to PV [](float X, float Y, float Z, float Px, float Py, float Pz, float pvX, float pvY, float pvZ) -> float { return std::sqrt((std::pow((pvY - Y) * Pz - (pvZ - Z) * Py, 2) + std::pow((pvX - X) * Pz - (pvZ - Z) * Px, 2) + std::pow((pvX - X) * Py - (pvY - Y) * Px, 2)) / (Px * Px + Py * Py + Pz * Pz)); }); @@ -89,532 +159,151 @@ DECLARE_SOA_DYNAMIC_COLUMN(Eta, eta, //! 3 body vtx eta DECLARE_SOA_DYNAMIC_COLUMN(Phi, phi, //! 3 body vtx phi [](float Px, float Py) -> float { return RecoDecay::phi(Px, Py); }); -// Calculated on the fly with mother particle hypothesis -DECLARE_SOA_DYNAMIC_COLUMN(MHypertriton, mHypertriton, //! mass under Hypertriton hypothesis - [](float pxtrack0, float pytrack0, float pztrack0, float pxtrack1, float pytrack1, float pztrack1, float pxtrack2, float pytrack2, float pztrack2) -> float { return RecoDecay::m(std::array{std::array{pxtrack0, pytrack0, pztrack0}, std::array{pxtrack1, pytrack1, pztrack1}, std::array{pxtrack2, pytrack2, pztrack2}}, std::array{o2::constants::physics::MassProton, o2::constants::physics::MassPionCharged, o2::constants::physics::MassDeuteron}); }); -DECLARE_SOA_DYNAMIC_COLUMN(MAntiHypertriton, mAntiHypertriton, //! mass under antiHypertriton hypothesis - [](float pxtrack0, float pytrack0, float pztrack0, float pxtrack1, float pytrack1, float pztrack1, float pxtrack2, float pytrack2, float pztrack2) -> float { return RecoDecay::m(std::array{std::array{pxtrack0, pytrack0, pztrack0}, std::array{pxtrack1, pytrack1, pztrack1}, std::array{pxtrack2, pytrack2, pztrack2}}, std::array{o2::constants::physics::MassPionCharged, o2::constants::physics::MassProton, o2::constants::physics::MassDeuteron}); }); - -DECLARE_SOA_DYNAMIC_COLUMN(MHyperHelium4, mHyperHelium4, //! mass under HyperHelium4 hypothesis - [](float pxtrack0, float pytrack0, float pztrack0, float pxtrack1, float pytrack1, float pztrack1, float pxtrack2, float pytrack2, float pztrack2) -> float { return RecoDecay::m(std::array{std::array{pxtrack0, pytrack0, pztrack0}, std::array{pxtrack1, pytrack1, pztrack1}, std::array{pxtrack2, pytrack2, pztrack2}}, std::array{o2::constants::physics::MassProton, o2::constants::physics::MassPionCharged, o2::constants::physics::MassHelium3}); }); -DECLARE_SOA_DYNAMIC_COLUMN(MAntiHyperHelium4, mAntiHyperHelium4, //! mass under antiHyperHelium4 hypothesis - [](float pxtrack0, float pytrack0, float pztrack0, float pxtrack1, float pytrack1, float pztrack1, float pxtrack2, float pytrack2, float pztrack2) -> float { return RecoDecay::m(std::array{std::array{pxtrack0, pytrack0, pztrack0}, std::array{pxtrack1, pytrack1, pztrack1}, std::array{pxtrack2, pytrack2, pztrack2}}, std::array{o2::constants::physics::MassPionCharged, o2::constants::physics::MassProton, o2::constants::physics::MassHelium3}); }); - -DECLARE_SOA_DYNAMIC_COLUMN(YHypertriton, yHypertriton, //! 3 body vtx y with hypertriton or antihypertriton hypothesis +// Rapidity +DECLARE_SOA_DYNAMIC_COLUMN(Rap, rap, //! 3 body vtx y with hypertriton or antihypertriton hypothesis [](float Px, float Py, float Pz) -> float { return RecoDecay::y(std::array{Px, Py, Pz}, o2::constants::physics::MassHyperTriton); }); -DECLARE_SOA_DYNAMIC_COLUMN(YHyperHelium4, yHyperHelium4, //! 3 body vtx y with hyperhelium4 or antihyperhelium4 hypothesis - [](float Px, float Py, float Pz) -> float { return RecoDecay::y(std::array{Px, Py, Pz}, o2::constants::physics::MassHyperHelium4); }); - -// kinematic information of daughter tracks -DECLARE_SOA_DYNAMIC_COLUMN(Track0Pt, track0pt, //! daughter0 pT - [](float pxtrack0, float pytrack0) -> float { return RecoDecay::sqrtSumOfSquares(pxtrack0, pytrack0); }); -DECLARE_SOA_DYNAMIC_COLUMN(Track1Pt, track1pt, //! daughter1 pT - [](float pxtrack1, float pytrack1) -> float { return RecoDecay::sqrtSumOfSquares(pxtrack1, pytrack1); }); -DECLARE_SOA_DYNAMIC_COLUMN(Track2Pt, track2pt, //! daughter2 pT - [](float pxtrack2, float pytrack2) -> float { return RecoDecay::sqrtSumOfSquares(pxtrack2, pytrack2); }); -DECLARE_SOA_DYNAMIC_COLUMN(Track0Eta, track0eta, //! daughter0 eta - [](float pxtrack0, float pytrack0, float pztrack0) -> float { return RecoDecay::eta(std::array{pxtrack0, pytrack0, pztrack0}); }); -DECLARE_SOA_DYNAMIC_COLUMN(Track0Phi, track0phi, //! daughter0 phi - [](float pxtrack0, float pytrack0) -> float { return RecoDecay::phi(pxtrack0, pytrack0); }); -DECLARE_SOA_DYNAMIC_COLUMN(Track1Eta, track1eta, //! daughter1 eta - [](float pxtrack1, float pytrack1, float pztrack1) -> float { return RecoDecay::eta(std::array{pxtrack1, pytrack1, pztrack1}); }); -DECLARE_SOA_DYNAMIC_COLUMN(Track1Phi, track1phi, //! daughter1 phi - [](float pxtrack1, float pytrack1) -> float { return RecoDecay::phi(pxtrack1, pytrack1); }); -DECLARE_SOA_DYNAMIC_COLUMN(Track2Eta, track2eta, //! daughter2 eta - [](float pxtrack2, float pytrack2, float pztrack2) -> float { return RecoDecay::eta(std::array{pxtrack2, pytrack2, pztrack2}); }); -DECLARE_SOA_DYNAMIC_COLUMN(Track2Phi, track2phi, //! daughter2 phi - [](float pxtrack2, float pytrack2) -> float { return RecoDecay::phi(pxtrack2, pytrack2); }); - -DECLARE_SOA_EXPRESSION_COLUMN(Px, px, //! 3 body vtx px - float, 1.f * aod::vtx3body::pxtrack0 + 1.f * aod::vtx3body::pxtrack1 + 1.f * aod::vtx3body::pxtrack2); -DECLARE_SOA_EXPRESSION_COLUMN(Py, py, //! 3 body vtx py - float, 1.f * aod::vtx3body::pytrack0 + 1.f * aod::vtx3body::pytrack1 + 1.f * aod::vtx3body::pytrack2); -DECLARE_SOA_EXPRESSION_COLUMN(Pz, pz, //! 3 body vtx pz - float, 1.f * aod::vtx3body::pztrack0 + 1.f * aod::vtx3body::pztrack1 + 1.f * aod::vtx3body::pztrack2); -} // namespace vtx3body - -DECLARE_SOA_TABLE_FULL(StoredVtx3BodyDatas, "Vtx3BodyDatas", "AOD", "Vtx3BodyDATA", //! - o2::soa::Index<>, vtx3body::Track0Id, vtx3body::Track1Id, vtx3body::Track2Id, vtx3body::CollisionId, vtx3body::Decay3BodyId, - vtx3body::X, vtx3body::Y, vtx3body::Z, - vtx3body::PxTrack0, vtx3body::PyTrack0, vtx3body::PzTrack0, - vtx3body::PxTrack1, vtx3body::PyTrack1, vtx3body::PzTrack1, - vtx3body::PxTrack2, vtx3body::PyTrack2, vtx3body::PzTrack2, - vtx3body::DCAVtxDaughters, - vtx3body::DCAXYTrack0ToPV, vtx3body::DCAXYTrack1ToPV, vtx3body::DCAXYTrack2ToPV, - vtx3body::DCATrack0ToPV, vtx3body::DCATrack1ToPV, vtx3body::DCATrack2ToPV, - vtx3body::TOFNSigmaBachDe, - - // Dynamic columns - vtx3body::P, - vtx3body::Pt, - vtx3body::VtxRadius, - vtx3body::DistOverTotMom, - vtx3body::VtxCosPA, - vtx3body::DCAVtxToPV, - - // Invariant masses - vtx3body::MHypertriton, - vtx3body::MAntiHypertriton, - vtx3body::MHyperHelium4, - vtx3body::MAntiHyperHelium4, - - // Longitudinal - vtx3body::YHypertriton, - vtx3body::YHyperHelium4, - vtx3body::Eta, - vtx3body::Phi, - vtx3body::Track0Pt, - vtx3body::Track0Eta, - vtx3body::Track0Phi, - vtx3body::Track1Pt, - vtx3body::Track1Eta, - vtx3body::Track1Phi, - vtx3body::Track2Pt, - vtx3body::Track2Eta, - vtx3body::Track2Phi); - -// extended table with expression columns that can be used as arguments of dynamic columns -DECLARE_SOA_EXTENDED_TABLE_USER(Vtx3BodyDatas, StoredVtx3BodyDatas, "Vtx3BodyDATAEXT", //! - vtx3body::Px, vtx3body::Py, vtx3body::Pz); - -using Vtx3BodyData = Vtx3BodyDatas::iterator; -namespace vtx3body -{ -DECLARE_SOA_INDEX_COLUMN(Vtx3BodyData, vtx3BodyData); //! Index to Vtx3BodyData entry -} - -DECLARE_SOA_TABLE(Decay3BodyDataLink, "AOD", "DECAY3BODYLINK", //! Joinable table with Decay3bodys which links to Vtx3BodyData which is not produced for all entries - vtx3body::Vtx3BodyDataId); - -using Decay3BodysLinked = soa::Join; -using Decay3BodyLinked = Decay3BodysLinked::iterator; - -// Definition of labels for Vtx3BodyDatas -namespace mcvtx3bodylabel -{ -DECLARE_SOA_INDEX_COLUMN(McParticle, mcParticle); //! MC particle for Vtx3BodyDatas -} // namespace mcvtx3bodylabel - -DECLARE_SOA_TABLE(McVtx3BodyLabels, "AOD", "MCVTXLABEL", //! Table joinable with Vtx3BodyData containing the MC labels - mcvtx3bodylabel::McParticleId); -using McVtx3BodyLabel = McVtx3BodyLabels::iterator; -// Definition of labels for Decay3Bodys // Full table, joinable with Decay3Bodys (CAUTION: NOT WITH Vtx3BodyDATA) -namespace mcfullvtx3bodylabel -{ -DECLARE_SOA_INDEX_COLUMN(McParticle, mcParticle); //! MC particle for Decay3Bodys -} // namespace mcfullvtx3bodylabel - -DECLARE_SOA_TABLE(McFullVtx3BodyLabels, "AOD", "MCFULLVTXLABEL", //! Table joinable with Decay3Bodys - mcfullvtx3bodylabel::McParticleId); -using McFullVtx3BodyLabel = McFullVtx3BodyLabels::iterator; +// Kinematic information of daughter tracks +DECLARE_SOA_DYNAMIC_COLUMN(TrackPrPt, trackPrPt, //! daughter0 pT + [](float pxTrackPr, float pyTrackPr) -> float { return RecoDecay::sqrtSumOfSquares(pxTrackPr, pyTrackPr); }); +DECLARE_SOA_DYNAMIC_COLUMN(TrackPiPt, trackPiPt, //! daughter1 pT + [](float pxTrackPi, float pyTrackPi) -> float { return RecoDecay::sqrtSumOfSquares(pxTrackPi, pyTrackPi); }); +DECLARE_SOA_DYNAMIC_COLUMN(TrackDePt, trackDePt, //! daughter2 pT + [](float pxTrackDe, float pyTrackDe) -> float { return RecoDecay::sqrtSumOfSquares(pxTrackDe, pyTrackDe); }); +DECLARE_SOA_DYNAMIC_COLUMN(TrackPrEta, trackPrEta, //! daughter0 eta + [](float pxTrackPr, float pyTrackPr, float pzTrackPr) -> float { return RecoDecay::eta(std::array{pxTrackPr, pyTrackPr, pzTrackPr}); }); +DECLARE_SOA_DYNAMIC_COLUMN(TrackPrPhi, trackPrPhi, //! daughter0 phi + [](float pxTrackPr, float pyTrackPr) -> float { return RecoDecay::phi(pxTrackPr, pyTrackPr); }); +DECLARE_SOA_DYNAMIC_COLUMN(TrackPiEta, trackPiEta, //! daughter1 eta + [](float pxTrackPi, float pyTrackPi, float pzTrackPi) -> float { return RecoDecay::eta(std::array{pxTrackPi, pyTrackPi, pzTrackPi}); }); +DECLARE_SOA_DYNAMIC_COLUMN(TrackPiPhi, trackPiPhi, //! daughter1 phi + [](float pxTrackPi, float pyTrackPi) -> float { return RecoDecay::phi(pxTrackPi, pyTrackPi); }); +DECLARE_SOA_DYNAMIC_COLUMN(TrackDeEta, trackDeEta, //! daughter2 eta + [](float pxTrackDe, float pyTrackDe, float pzTrackDe) -> float { return RecoDecay::eta(std::array{pxTrackDe, pyTrackDe, pzTrackDe}); }); +DECLARE_SOA_DYNAMIC_COLUMN(TrackDePhi, trackDePhi, //! daughter2 phi + [](float pxTrackDe, float pyTrackDe) -> float { return RecoDecay::phi(pxTrackDe, pyTrackDe); }); +} // namespace vtx3body -// output table for ML studies -namespace hyp3body -{ -// collision -DECLARE_SOA_COLUMN(Centrality, centrality, float); //! centrality -// reconstruced candidate -DECLARE_SOA_COLUMN(IsMatter, isMatter, bool); //! bool: true for matter -DECLARE_SOA_COLUMN(M, m, float); //! invariant mass -DECLARE_SOA_COLUMN(P, p, float); //! p -DECLARE_SOA_COLUMN(Pt, pt, float); //! pT -DECLARE_SOA_COLUMN(Ct, ct, float); //! ct -DECLARE_SOA_COLUMN(CosPA, cospa, float); -DECLARE_SOA_COLUMN(DCADaughters, dcaDaughters, float); //! DCA among daughters -DECLARE_SOA_COLUMN(DCACandToPV, dcaCandtopv, float); //! DCA of the reconstructed track to pv -DECLARE_SOA_COLUMN(VtxRadius, vtxRadius, float); //! Radius of SV -// kinematic infomation of daughter tracks -DECLARE_SOA_COLUMN(PtProton, ptProton, float); //! pT of the proton daughter -DECLARE_SOA_COLUMN(EtaProton, etaProton, float); //! eta of the proton daughter -DECLARE_SOA_COLUMN(PhiProton, phiProton, float); //! phi of the proton daughter -DECLARE_SOA_COLUMN(RadiusProton, radiusProton, float); //! radius of innermost hit of the proton daughter -DECLARE_SOA_COLUMN(PtPion, ptPion, float); //! pT of the pion daughter -DECLARE_SOA_COLUMN(EtaPion, etaPion, float); //! eta of the pion daughter -DECLARE_SOA_COLUMN(PhiPion, phiPion, float); //! phi of the pion daughter -DECLARE_SOA_COLUMN(RadiusPion, radiusPion, float); //! radius of innermost hit of the pion daughter -DECLARE_SOA_COLUMN(PtBachelor, ptBachelor, float); //! pT of the bachelor daughter -DECLARE_SOA_COLUMN(EtaBachelor, etaBachelor, float); //! eta of the bachelor daughter -DECLARE_SOA_COLUMN(PhiBachelor, phiBachelor, float); //! phi of the bachelor daughter -DECLARE_SOA_COLUMN(RadiusBachelor, radiusBachelor, float); //! radius of innermost hit of the bachelor daughter -// track quality -DECLARE_SOA_COLUMN(TPCNclusProton, tpcNclusProton, uint8_t); //! number of TPC clusters of the proton daughter -DECLARE_SOA_COLUMN(TPCNclusPion, tpcNclusPion, uint8_t); //! number of TPC clusters of the pion daughter -DECLARE_SOA_COLUMN(TPCNclusBachelor, tpcNclusBachelor, uint8_t); //! number of TPC clusters of the bachelor daughter -DECLARE_SOA_COLUMN(ITSNclusSizeProton, itsNclusSizeProton, uint8_t); //! average ITS cluster size of the proton daughter -DECLARE_SOA_COLUMN(ITSNclusSizePion, itsNclusSizePion, uint8_t); //! average ITS cluster size of the pion daughter -DECLARE_SOA_COLUMN(ITSNclusSizeBachelor, itsNclusSizeBachelor, uint8_t); //! average ITS cluster size of the bachelor daughter -// PID -DECLARE_SOA_COLUMN(TPCNSigmaProton, tpcNSigmaProton, float); //! nsigma of TPC PID of the proton daughter -DECLARE_SOA_COLUMN(TPCNSigmaPion, tpcNSigmaPion, float); //! nsigma of TPC PID of the pion daughter -DECLARE_SOA_COLUMN(TPCNSigmaBachelor, tpcNSigmaBachelor, float); //! nsigma of TPC PID of the bachelor daughter -DECLARE_SOA_COLUMN(TOFNSigmaBachelor, tofNSigmaBachelor, float); //! nsigma of TOF PID of the bachelor daughter -// DCA to PV -DECLARE_SOA_COLUMN(DCAXYProtonToPV, dcaxyProtontoPV, float); //! DCAXY of the proton daughter to pv -DECLARE_SOA_COLUMN(DCAXYPionToPV, dcaxyPiontoPV, float); //! DCAXY of the pion daughter to pv -DECLARE_SOA_COLUMN(DCAXYBachelorToPV, dcaxyBachelortoPV, float); //! DCAXY of the bachelor daughter to pv -DECLARE_SOA_COLUMN(DCAProtonToPV, dcaProtontoPV, float); //! DCA of the proton daughter to pv -DECLARE_SOA_COLUMN(DCAPionToPV, dcaPiontoPV, float); //! DCA of the pion daughter to pv -DECLARE_SOA_COLUMN(DCABachelorToPV, dcaBachelortoPV, float); //! DCA of the bachelor daughter to pv -DECLARE_SOA_COLUMN(IsBachPrimary, isbachprimary, bool); //! flag for bachelor daughter primary -// for MC -DECLARE_SOA_COLUMN(GenP, genP, float); // P of the hypertriton -DECLARE_SOA_COLUMN(GenPt, genPt, float); // pT of the hypertriton -DECLARE_SOA_COLUMN(GenCt, genCt, float); // ct of the hypertriton -DECLARE_SOA_COLUMN(GenPhi, genPhi, float); // Phi of the hypertriton -DECLARE_SOA_COLUMN(GenEta, genEta, float); // Eta of the hypertriton -DECLARE_SOA_COLUMN(GenRapidity, genRapidity, float); // Rapidity of the hypertriton -DECLARE_SOA_COLUMN(IsReco, isReco, bool); // bool: true for reco -DECLARE_SOA_COLUMN(IsSignal, isSignal, bool); // bool: true for signal -DECLARE_SOA_COLUMN(PdgCode, pdgCode, int); // pdgCode of the mcparticle, -1 for fake pair -DECLARE_SOA_COLUMN(SurvivedEventSelection, survivedEventSelection, bool); // bool: true for survived event selection -} // namespace hyp3body - -// output table for data -DECLARE_SOA_TABLE(Hyp3BodyCands, "AOD", "HYP3BODYCANDS", - o2::soa::Index<>, - hyp3body::Centrality, - // secondary vertex and reconstruced candidate - hyp3body::IsMatter, - hyp3body::M, - hyp3body::P, - hyp3body::Pt, - hyp3body::Ct, - hyp3body::CosPA, - hyp3body::DCADaughters, - hyp3body::DCACandToPV, - hyp3body::VtxRadius, - // daughter tracks - hyp3body::PtProton, hyp3body::EtaProton, hyp3body::PhiProton, hyp3body::RadiusProton, - hyp3body::PtPion, hyp3body::EtaPion, hyp3body::PhiPion, hyp3body::RadiusPion, - hyp3body::PtBachelor, hyp3body::EtaBachelor, hyp3body::PhiBachelor, hyp3body::RadiusBachelor, - hyp3body::TPCNclusProton, hyp3body::TPCNclusPion, hyp3body::TPCNclusBachelor, - hyp3body::ITSNclusSizeProton, hyp3body::ITSNclusSizePion, hyp3body::ITSNclusSizeBachelor, - hyp3body::TPCNSigmaProton, hyp3body::TPCNSigmaPion, hyp3body::TPCNSigmaBachelor, - hyp3body::TOFNSigmaBachelor, - hyp3body::DCAXYProtonToPV, hyp3body::DCAXYPionToPV, hyp3body::DCAXYBachelorToPV, - hyp3body::DCAProtonToPV, hyp3body::DCAPionToPV, hyp3body::DCABachelorToPV); - -// output table for MC -DECLARE_SOA_TABLE(MCHyp3BodyCands, "AOD", "MCHYP3BODYCANDS", +// index table +DECLARE_SOA_TABLE(Decay3BodyIndices, "AOD", "3BodyINDEX", //! o2::soa::Index<>, - hyp3body::Centrality, - // secondary vertex and reconstruced candidate - hyp3body::IsMatter, - hyp3body::M, - hyp3body::P, - hyp3body::Pt, - hyp3body::Ct, - hyp3body::CosPA, - hyp3body::DCADaughters, - hyp3body::DCACandToPV, - hyp3body::VtxRadius, - // daughter tracks - hyp3body::PtProton, hyp3body::EtaProton, hyp3body::PhiProton, hyp3body::RadiusProton, - hyp3body::PtPion, hyp3body::EtaPion, hyp3body::PhiPion, hyp3body::RadiusPion, - hyp3body::PtBachelor, hyp3body::EtaBachelor, hyp3body::PhiBachelor, hyp3body::RadiusBachelor, - hyp3body::TPCNclusProton, hyp3body::TPCNclusPion, hyp3body::TPCNclusBachelor, - hyp3body::ITSNclusSizeProton, hyp3body::ITSNclusSizePion, hyp3body::ITSNclusSizeBachelor, - hyp3body::TPCNSigmaProton, hyp3body::TPCNSigmaPion, hyp3body::TPCNSigmaBachelor, - hyp3body::TOFNSigmaBachelor, - hyp3body::DCAXYProtonToPV, hyp3body::DCAXYPionToPV, hyp3body::DCAXYBachelorToPV, - hyp3body::DCAProtonToPV, hyp3body::DCAPionToPV, hyp3body::DCABachelorToPV, - hyp3body::IsBachPrimary, - // MC information - hyp3body::GenP, - hyp3body::GenPt, - hyp3body::GenCt, - hyp3body::GenPhi, - hyp3body::GenEta, - hyp3body::GenRapidity, - hyp3body::IsSignal, - hyp3body::IsReco, - hyp3body::PdgCode, - hyp3body::SurvivedEventSelection); - -//______________________________________________________ -// DATAMODEL FOR KFPARTICLE DECAY3BODYS - -namespace kfvtx3body -{ -// General 3 body Vtx properties: mass, momentum, charge -DECLARE_SOA_COLUMN(Mass, mass, float); //! candidate mass (PID hypothesis depending on bachelor charge) -DECLARE_SOA_COLUMN(XErr, xerr, float); //! candidate position x error at decay position -DECLARE_SOA_COLUMN(YErr, yerr, float); //! candidate position y error at decay position -DECLARE_SOA_COLUMN(ZErr, zerr, float); //! candidate position z error at decay position -DECLARE_SOA_COLUMN(Px, px, float); //! candidate px at decay position -DECLARE_SOA_COLUMN(Py, py, float); //! candidate py at decay position -DECLARE_SOA_COLUMN(Pz, pz, float); //! candidate pz at decay position -DECLARE_SOA_COLUMN(Pt, pt, float); //! candidate pt at decay position -DECLARE_SOA_COLUMN(PxErr, pxerr, float); //! candidate px error at decay position -DECLARE_SOA_COLUMN(PyErr, pyerr, float); //! candidate py error at decay position -DECLARE_SOA_COLUMN(PzErr, pzerr, float); //! candidate pz error at decay position -DECLARE_SOA_COLUMN(PtErr, pterr, float); //! candidate pt error at decay position -DECLARE_SOA_COLUMN(Sign, sign, float); //! candidate sign - -// topological properties -DECLARE_SOA_COLUMN(VtxCosPAKF, vtxcospakf, float); //! 3 body vtx CosPA from KFParticle (using kfpPV) -DECLARE_SOA_COLUMN(VtxCosXYPAKF, vtxcosxypakf, float); //! 3 body vtx CosPA from KFParticle (using kfpPV) -DECLARE_SOA_COLUMN(VtxCosPAKFtopo, vtxcospakftopo, float); //! 3 body vtx CosPA from KFParticle after topological constraint (using kfpPV) -DECLARE_SOA_COLUMN(VtxCosXYPAKFtopo, vtxcosxypakftopo, float); //! 3 body vtx CosPA from KFParticle after topological constraint (using kfpPV) -DECLARE_SOA_COLUMN(DCAVtxToPVKF, dcavtxtopvkf, float); //! 3 body vtx DCA to PV from KFParticle (using kfpPV) -DECLARE_SOA_COLUMN(DCAXYVtxToPVKF, dcaxyvtxtopvkf, float); //! 3 body vtx DCAxy to PV from KFParticle (using kfpPV) -DECLARE_SOA_COLUMN(DecayLKF, decaylkf, float); //! 3 body vtx decay length from KFParticle (using kfpPV after topological constraint) -DECLARE_SOA_COLUMN(DecayLXYKF, decaylxykf, float); //! 3 body vtx decay length XY from KFParticle (using kfpPV after topological constraint) -DECLARE_SOA_COLUMN(DecayLDeltaL, decayldeltal, float); //! 3 body vtx l/dl from KFParticle (using kfpPV after topological constraint) -DECLARE_SOA_COLUMN(Chi2geoNDF, chi2geondf, float); //! 3 body vtx chi2geo from geometrical KFParticle fit -DECLARE_SOA_COLUMN(Chi2topoNDF, chi2topondf, float); //! 3 body vtx chi2topo from KFParticle topological constraint to the PV (using kfpPV) -DECLARE_SOA_COLUMN(CTauKFtopo, ctaukftopo, float); //! 3 body vtx ctau from KFParticle after topological constraint - -// Strangeness tracking -DECLARE_SOA_COLUMN(TrackedClSize, trackedclsize, int); //! Cluster size of strangeness tracked 3body - -// daughters -DECLARE_SOA_COLUMN(DCATrack0ToPVKF, dcatrack0topvkf, float); //! DCA of proton prong to PV from KFParticle -DECLARE_SOA_COLUMN(DCATrack1ToPVKF, dcatrack1topvkf, float); //! DCA of pion prong to PV from KFParticle -DECLARE_SOA_COLUMN(DCATrack2ToPVKF, dcatrack2topvkf, float); //! DCA of deuteron prong to PV from KFParticle -DECLARE_SOA_COLUMN(DCAxyTrack0ToPVKF, dcaxytrack0topvkf, float); //! DCAxy of proton prong to PV from KFParticle -DECLARE_SOA_COLUMN(DCAxyTrack1ToPVKF, dcaxytrack1topvkf, float); //! DCAxy of pion prong to PV from KFParticle -DECLARE_SOA_COLUMN(DCAxyTrack2ToPVKF, dcaxytrack2topvkf, float); //! DCAxy of deuteron prong to PV from KFParticle -DECLARE_SOA_COLUMN(DCATrackPosToPV, dcatrackpostopv, float); //! DCA of positive track to PV (propagated before vtx fit) -DECLARE_SOA_COLUMN(DCATrackNegToPV, dcatracknegtopv, float); //! DCA of negative track to PV (propagated before vtx fit) -DECLARE_SOA_COLUMN(DCATrackBachToPV, dcatrackbachtopv, float); //! DCA of bachelor track to PV (propagated before vtx fit) -DECLARE_SOA_COLUMN(DCAxyTrackPosToPV, dcaxytrackpostopv, float); //! DCAxy of positive track to PV (propagated before vtx fit) -DECLARE_SOA_COLUMN(DCAxyTrackNegToPV, dcaxytracknegtopv, float); //! DCAxy of negative track to PV (propagated before vtx fit) -DECLARE_SOA_COLUMN(DCAxyTrackBachToPV, dcaxytrackbachtopv, float); //! DCAxy of bachelor track to PV (propagated before vtx fit) -DECLARE_SOA_COLUMN(DCAxyTrack0ToSVKF, dcaxytrack0tosvkf, float); //! DCAxy of proton prong to SV from KFParticle -DECLARE_SOA_COLUMN(DCAxyTrack1ToSVKF, dcaxytrack1tosvkf, float); //! DCAxy of pion prong to SV from KFParticle -DECLARE_SOA_COLUMN(DCAxyTrack2ToSVKF, dcaxytrack2tosvkf, float); //! DCAxy of deuteron prong to SV from KFParticle -DECLARE_SOA_COLUMN(DCATrack0ToTrack1KF, dcatrack0totrack1kf, float); //! DCAxy of proton prong to pion from KFParticle -DECLARE_SOA_COLUMN(DCATrack0ToTrack2KF, dcatrack0totrack2kf, float); //! DCAxy of proton prong to deuteron from KFParticle -DECLARE_SOA_COLUMN(DCATrack1ToTrack2KF, dcatrack1totrack2kf, float); //! DCAxy of pion prong to deuteron from KFParticle -DECLARE_SOA_COLUMN(DCAVtxDaughtersKF, dcavtxdaughterskf, float); //! sum of DCAs between daughters in 3D from KFParticle -DECLARE_SOA_COLUMN(Track0Sign, track0sign, float); //! sign of proton daughter track -DECLARE_SOA_COLUMN(Track1Sign, track1sign, float); //! sign of pion daughter track -DECLARE_SOA_COLUMN(Track2Sign, track2sign, float); //! sign of deuteron daughter track -DECLARE_SOA_COLUMN(TPCInnerParamTrack0, tpcinnerparamtrack0, float); //! momentum at inner wall of TPC of proton daughter -DECLARE_SOA_COLUMN(TPCInnerParamTrack1, tpcinnerparamtrack1, float); //! momentum at inner wall of TPC of pion daughter -DECLARE_SOA_COLUMN(TPCInnerParamTrack2, tpcinnerparamtrack2, float); //! momentum at inner wall of TPC of deuteron daughter -DECLARE_SOA_COLUMN(TPCNClTrack0, tpcncltrack0, int); //! Number of TPC clusters of proton daughter -DECLARE_SOA_COLUMN(TPCNClTrack1, tpcncltrack1, int); //! Number of TPC clusters of pion daughter -DECLARE_SOA_COLUMN(TPCNClTrack2, tpcncltrack2, int); //! Number of TPC clusters of deuteron daughter -DECLARE_SOA_COLUMN(TPCChi2NClDeuteron, tpcchi2ncldeuteron, float); //! TPC Chi2 / cluster of deuteron daughter -DECLARE_SOA_COLUMN(DeltaPhiDeuteron, deltaphideuteron, float); //! phi before track rotation - phi after track rotation for deuteron track -DECLARE_SOA_COLUMN(DeltaPhiProton, deltaphiproton, float); //! phi before track rotation - phi after track rotation for proton track -// PID -DECLARE_SOA_COLUMN(TPCNSigmaProton, tpcnsigmaproton, float); //! nsigma proton of TPC PID of the proton daughter -DECLARE_SOA_COLUMN(TPCNSigmaPion, tpcnsigmapion, float); //! nsigma pion of TPC PID of the pion daughter -DECLARE_SOA_COLUMN(TPCNSigmaDeuteron, tpcnsigmadeuteron, float); //! nsigma deuteron of TPC PID of the bachelor daughter -DECLARE_SOA_COLUMN(TPCNSigmaPionBach, tpcnsigmapionbach, float); //! nsigma pion of TPC PID of the bachelor daughter -DECLARE_SOA_COLUMN(TPCdEdxProton, tpcdedxproton, float); //! TPC dEdx of the proton daughter -DECLARE_SOA_COLUMN(TPCdEdxPion, tpcdedxpion, float); //! TPC dEdx of the pion daughter -DECLARE_SOA_COLUMN(TPCdEdxDeuteron, tpcdedxdeuteron, float); //! TPC dEdx of the bachelor daughter -DECLARE_SOA_COLUMN(TOFNSigmaDeuteron, tofnsigmadeuteron, float); //! nsigma of TOF PID of the bachelor daughter -DECLARE_SOA_COLUMN(ITSClusSizeDeuteron, itsclussizedeuteron, double); //! average ITS cluster size of bachelor daughter -DECLARE_SOA_COLUMN(PIDTrackingDeuteron, pidtrackingdeuteron, uint32_t); //! PID during tracking of bachelor daughter - -// Monte Carlo -DECLARE_SOA_COLUMN(GenP, genp, float); //! generated momentum -DECLARE_SOA_COLUMN(GenPt, genpt, float); //! generated transverse momentum -DECLARE_SOA_COLUMN(GenDecVtxX, gendecvtxx, double); //! generated decay vertex position x -DECLARE_SOA_COLUMN(GenDecVtxY, gendecvtxy, double); //! generated decay vertex position y -DECLARE_SOA_COLUMN(GenDecVtxZ, gendecvtxz, double); //! generated decay vertex position z -DECLARE_SOA_COLUMN(GenCtau, genctau, double); //! generated ctau -DECLARE_SOA_COLUMN(GenPhi, genphi, float); //! generated phi -DECLARE_SOA_COLUMN(GenEta, geneta, float); //! generated eta -DECLARE_SOA_COLUMN(GenRapidity, genrapidity, float); //! generated rapidity -DECLARE_SOA_COLUMN(GenPosP, genposp, float); //! generated momentum pos daughter particle -DECLARE_SOA_COLUMN(GenPosPt, genpospt, float); //! generated transverse momentum pos daughter particle -DECLARE_SOA_COLUMN(GenNegP, gennegp, float); //! generated momentum neg daughter particle -DECLARE_SOA_COLUMN(GenNegPt, gennegpt, float); //! generated transverse momentum neg daughter particle -DECLARE_SOA_COLUMN(GenBachP, genbachp, float); //! generated momentum bachelor daughter particle -DECLARE_SOA_COLUMN(GenBachPt, genbachpt, float); //! generated transverse momentum bachelor 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(PdgCodeDau0, pdgcodedau0, int); //! MC particle daughter 0 PDG code -DECLARE_SOA_COLUMN(PdgCodeDau1, pdgcodedau1, int); //! MC particle daughter 1 PDG code -DECLARE_SOA_COLUMN(PdgCodeDau2, pdgcodedau2, int); //! MC particle daughter 2 PDG code -DECLARE_SOA_COLUMN(IsBachPrimary, isbachprimary, bool); //! flag for bachelor daughter primary -DECLARE_SOA_COLUMN(SurvEvSel, survevsel, int); //! flag if reco collision survived event selection -DECLARE_SOA_COLUMN(IsReco, isreco, int); //! flag if candidate was reconstructed - -// V0 -DECLARE_SOA_COLUMN(MassV0, massv0, float); //! proton, pion vertex mass -DECLARE_SOA_COLUMN(Chi2MassV0, chi2massv0, float); //! chi2 of proton, pion mass constraint to Lambda mass -DECLARE_SOA_COLUMN(CosPAV0, cospav0, float); //! proton, pion vertex mass - -} // namespace kfvtx3body + vtx3body::Decay3BodyId, + vtx3body::TrackPrId, vtx3body::TrackPiId, vtx3body::TrackDeId, + vtx3body::CollisionId); -DECLARE_SOA_TABLE(KFVtx3BodyDatas, "AOD", "KFVTX3BODYDATA", - o2::soa::Index<>, vtx3body::CollisionId, vtx3body::Track0Id, vtx3body::Track1Id, vtx3body::Track2Id, vtx3body::Decay3BodyId, - - // hypertriton candidate - kfvtx3body::Mass, - vtx3body::X, vtx3body::Y, vtx3body::Z, - kfvtx3body::XErr, kfvtx3body::YErr, kfvtx3body::ZErr, - kfvtx3body::Px, kfvtx3body::Py, kfvtx3body::Pz, kfvtx3body::Pt, - kfvtx3body::PxErr, kfvtx3body::PyErr, kfvtx3body::PzErr, kfvtx3body::PtErr, - kfvtx3body::Sign, - kfvtx3body::DCAVtxToPVKF, kfvtx3body::DCAXYVtxToPVKF, - kfvtx3body::VtxCosPAKF, kfvtx3body::VtxCosXYPAKF, - kfvtx3body::VtxCosPAKFtopo, kfvtx3body::VtxCosXYPAKFtopo, - kfvtx3body::DecayLKF, kfvtx3body::DecayLXYKF, kfvtx3body::DecayLDeltaL, - kfvtx3body::Chi2geoNDF, kfvtx3body::Chi2topoNDF, - kfvtx3body::CTauKFtopo, kfvtx3body::TrackedClSize, - - // V0 - kfvtx3body::MassV0, kfvtx3body::Chi2MassV0, - kfvtx3body::CosPAV0, - - // daughters - vtx3body::PxTrack0, vtx3body::PyTrack0, vtx3body::PzTrack0, // proton - vtx3body::PxTrack1, vtx3body::PyTrack1, vtx3body::PzTrack1, // pion - vtx3body::PxTrack2, vtx3body::PyTrack2, vtx3body::PzTrack2, // deuteron - kfvtx3body::TPCInnerParamTrack0, kfvtx3body::TPCInnerParamTrack1, kfvtx3body::TPCInnerParamTrack2, // proton, pion, deuteron - kfvtx3body::TPCNClTrack0, kfvtx3body::TPCNClTrack1, kfvtx3body::TPCNClTrack2, // proton, pion, deuteron - kfvtx3body::TPCChi2NClDeuteron, - kfvtx3body::DeltaPhiDeuteron, kfvtx3body::DeltaPhiProton, - kfvtx3body::DCATrack0ToPVKF, kfvtx3body::DCATrack1ToPVKF, kfvtx3body::DCATrack2ToPVKF, kfvtx3body::DCAxyTrack0ToPVKF, kfvtx3body::DCAxyTrack1ToPVKF, kfvtx3body::DCAxyTrack2ToPVKF, - kfvtx3body::DCAxyTrack0ToSVKF, kfvtx3body::DCAxyTrack1ToSVKF, kfvtx3body::DCAxyTrack2ToSVKF, - kfvtx3body::DCATrack0ToTrack1KF, kfvtx3body::DCATrack0ToTrack2KF, kfvtx3body::DCATrack1ToTrack2KF, - kfvtx3body::DCAVtxDaughtersKF, - kfvtx3body::DCAxyTrackPosToPV, kfvtx3body::DCAxyTrackNegToPV, kfvtx3body::DCAxyTrackBachToPV, - kfvtx3body::DCATrackPosToPV, kfvtx3body::DCATrackNegToPV, kfvtx3body::DCATrackBachToPV, - kfvtx3body::Track0Sign, kfvtx3body::Track1Sign, kfvtx3body::Track2Sign, // track sing: proton, pion, deuteron - kfvtx3body::TPCNSigmaProton, kfvtx3body::TPCNSigmaPion, kfvtx3body::TPCNSigmaDeuteron, kfvtx3body::TPCNSigmaPionBach, - kfvtx3body::TPCdEdxProton, kfvtx3body::TPCdEdxPion, kfvtx3body::TPCdEdxDeuteron, - kfvtx3body::TOFNSigmaDeuteron, - kfvtx3body::ITSClusSizeDeuteron, - kfvtx3body::PIDTrackingDeuteron); - -using KFVtx3BodyData = KFVtx3BodyDatas::iterator; -namespace kfvtx3body -{ -DECLARE_SOA_INDEX_COLUMN(KFVtx3BodyData, kfvtx3BodyData); //! Index to KFVtx3BodyData entry -} - -DECLARE_SOA_TABLE(KFDecay3BodyDataLink, "AOD", "KF3BODYLINK", //! Joinable table with Decay3bodys which links to KFVtx3BodyData which is not produced for all entries - kfvtx3body::KFVtx3BodyDataId); - -using KFDecay3BodysLinked = soa::Join; -using KFDecay3BodyLinked = KFDecay3BodysLinked::iterator; - -// Lite data candidate table for analysis -DECLARE_SOA_TABLE(KFVtx3BodyDatasLite, "AOD", "KF3BODYLITE", +// reconstructed candidate table for analysis +DECLARE_SOA_TABLE(Vtx3BodyDatas, "AOD", "VTX3BODYDATA", //! o2::soa::Index<>, - // hypertriton candidate - kfvtx3body::Mass, + vtx3body::Sign, + vtx3body::Mass, vtx3body::MassV0, vtx3body::X, vtx3body::Y, vtx3body::Z, - kfvtx3body::Px, kfvtx3body::Py, kfvtx3body::Pz, kfvtx3body::Pt, - kfvtx3body::Sign, - kfvtx3body::DCAVtxToPVKF, kfvtx3body::DCAXYVtxToPVKF, - kfvtx3body::VtxCosPAKF, kfvtx3body::VtxCosXYPAKF, - kfvtx3body::DecayLKF, kfvtx3body::DecayLXYKF, kfvtx3body::DecayLDeltaL, - kfvtx3body::Chi2geoNDF, kfvtx3body::Chi2topoNDF, - kfvtx3body::CTauKFtopo, kfvtx3body::TrackedClSize, - - // V0 - kfvtx3body::MassV0, - kfvtx3body::CosPAV0, - - // daughters - vtx3body::PxTrack0, vtx3body::PyTrack0, vtx3body::PzTrack0, // proton - vtx3body::PxTrack1, vtx3body::PyTrack1, vtx3body::PzTrack1, // pion - vtx3body::PxTrack2, vtx3body::PyTrack2, vtx3body::PzTrack2, // deuteron - kfvtx3body::TPCInnerParamTrack0, kfvtx3body::TPCInnerParamTrack1, kfvtx3body::TPCInnerParamTrack2, // proton, pion, deuteron - kfvtx3body::TPCNClTrack0, kfvtx3body::TPCNClTrack1, kfvtx3body::TPCNClTrack2, // proton, pion, deuteron - kfvtx3body::TPCChi2NClDeuteron, - kfvtx3body::DeltaPhiDeuteron, kfvtx3body::DeltaPhiProton, - kfvtx3body::DCATrack0ToPVKF, kfvtx3body::DCATrack1ToPVKF, kfvtx3body::DCATrack2ToPVKF, kfvtx3body::DCAxyTrack0ToPVKF, kfvtx3body::DCAxyTrack1ToPVKF, kfvtx3body::DCAxyTrack2ToPVKF, - kfvtx3body::DCAxyTrack0ToSVKF, kfvtx3body::DCAxyTrack1ToSVKF, kfvtx3body::DCAxyTrack2ToSVKF, - kfvtx3body::DCATrack0ToTrack1KF, kfvtx3body::DCATrack0ToTrack2KF, kfvtx3body::DCATrack1ToTrack2KF, - kfvtx3body::DCAVtxDaughtersKF, - kfvtx3body::Track0Sign, kfvtx3body::Track1Sign, kfvtx3body::Track2Sign, // track sing: proton, pion, deuteron - kfvtx3body::TPCNSigmaProton, kfvtx3body::TPCNSigmaPion, kfvtx3body::TPCNSigmaDeuteron, kfvtx3body::TPCNSigmaPionBach, - kfvtx3body::TOFNSigmaDeuteron, - kfvtx3body::ITSClusSizeDeuteron, - kfvtx3body::PIDTrackingDeuteron); - -using KFVtx3BodyDataLite = KFVtx3BodyDatasLite::iterator; + vtx3body::Px, vtx3body::Py, vtx3body::Pz, + vtx3body::Chi2, + vtx3body::TrackedClSize, + vtx3body::PxTrackPr, vtx3body::PyTrackPr, vtx3body::PzTrackPr, + vtx3body::PxTrackPi, vtx3body::PyTrackPi, vtx3body::PzTrackPi, + vtx3body::PxTrackDe, vtx3body::PyTrackDe, vtx3body::PzTrackDe, + vtx3body::DCAXYTrackPrToPV, vtx3body::DCAXYTrackPiToPV, vtx3body::DCAXYTrackDeToPV, + vtx3body::DCAZTrackPrToPV, vtx3body::DCAZTrackPiToPV, vtx3body::DCAZTrackDeToPV, + vtx3body::DCATrackPrToSV, vtx3body::DCATrackPiToSV, vtx3body::DCATrackDeToSV, + vtx3body::DCAVtxDaughters, + vtx3body::TPCNSigmaPr, vtx3body::TPCNSigmaPi, vtx3body::TPCNSigmaDe, vtx3body::TPCNSigmaPiBach, + vtx3body::TOFNSigmaDe, + vtx3body::ITSClSizePr, vtx3body::ITSClSizePi, vtx3body::ITSClSizeDe, + vtx3body::TPCNClTrackPr, vtx3body::TPCNClTrackPi, vtx3body::TPCNClTrackDe, + vtx3body::PIDTrackingDe, + + // Dynamic columns + vtx3body::P, + vtx3body::Pt, + vtx3body::VtxRadius, + vtx3body::DistOverTotMom, + vtx3body::VtxCosPA, + vtx3body::DCAVtxToPV, + + // Longitudinal + vtx3body::Rap, + vtx3body::Eta, + vtx3body::Phi, + vtx3body::TrackPrPt, + vtx3body::TrackPrEta, + vtx3body::TrackPrPhi, + vtx3body::TrackPiPt, + vtx3body::TrackPiEta, + vtx3body::TrackPiPhi, + vtx3body::TrackDePt, + vtx3body::TrackDeEta, + vtx3body::TrackDePhi); + +// covariance matrix table +DECLARE_SOA_TABLE(Vtx3BodyCovs, "AOD", "VTX3BODYCOV", //! + vtx3body::CovProton, vtx3body::CovPion, vtx3body::CovDeuteron, + vtx3body::VtxCovMat); // MC candidate table for analysis -DECLARE_SOA_TABLE(McKFVtx3BodyDatas, "AOD", "MCKF3BODYDATAS", +DECLARE_SOA_TABLE(McVtx3BodyDatas, "AOD", "MC3BODYDATA", //! o2::soa::Index<>, - // hypertriton candidate - kfvtx3body::Mass, + vtx3body::Sign, + vtx3body::Mass, vtx3body::MassV0, vtx3body::X, vtx3body::Y, vtx3body::Z, - kfvtx3body::XErr, kfvtx3body::YErr, kfvtx3body::ZErr, - kfvtx3body::Px, kfvtx3body::Py, kfvtx3body::Pz, kfvtx3body::Pt, - kfvtx3body::PxErr, kfvtx3body::PyErr, kfvtx3body::PzErr, kfvtx3body::PtErr, - kfvtx3body::Sign, - kfvtx3body::DCAVtxToPVKF, kfvtx3body::DCAXYVtxToPVKF, - kfvtx3body::VtxCosPAKF, kfvtx3body::VtxCosXYPAKF, - kfvtx3body::VtxCosPAKFtopo, kfvtx3body::VtxCosXYPAKFtopo, - kfvtx3body::DecayLKF, kfvtx3body::DecayLXYKF, kfvtx3body::DecayLDeltaL, - kfvtx3body::Chi2geoNDF, kfvtx3body::Chi2topoNDF, - kfvtx3body::CTauKFtopo, kfvtx3body::TrackedClSize, - - // V0 - kfvtx3body::MassV0, kfvtx3body::Chi2MassV0, - kfvtx3body::CosPAV0, - - // daughters - vtx3body::PxTrack0, vtx3body::PyTrack0, vtx3body::PzTrack0, // proton - vtx3body::PxTrack1, vtx3body::PyTrack1, vtx3body::PzTrack1, // pion - vtx3body::PxTrack2, vtx3body::PyTrack2, vtx3body::PzTrack2, // deuteron - kfvtx3body::TPCInnerParamTrack0, kfvtx3body::TPCInnerParamTrack1, kfvtx3body::TPCInnerParamTrack2, // proton, pion, deuteron - kfvtx3body::TPCNClTrack0, kfvtx3body::TPCNClTrack1, kfvtx3body::TPCNClTrack2, // proton, pion, deuteron - kfvtx3body::TPCChi2NClDeuteron, - kfvtx3body::DeltaPhiDeuteron, kfvtx3body::DeltaPhiProton, - kfvtx3body::DCATrack0ToPVKF, kfvtx3body::DCATrack1ToPVKF, kfvtx3body::DCATrack2ToPVKF, kfvtx3body::DCAxyTrack0ToPVKF, kfvtx3body::DCAxyTrack1ToPVKF, kfvtx3body::DCAxyTrack2ToPVKF, - kfvtx3body::DCAxyTrack0ToSVKF, kfvtx3body::DCAxyTrack1ToSVKF, kfvtx3body::DCAxyTrack2ToSVKF, - kfvtx3body::DCATrack0ToTrack1KF, kfvtx3body::DCATrack0ToTrack2KF, kfvtx3body::DCATrack1ToTrack2KF, - kfvtx3body::DCAVtxDaughtersKF, - kfvtx3body::DCAxyTrackPosToPV, kfvtx3body::DCAxyTrackNegToPV, kfvtx3body::DCAxyTrackBachToPV, - kfvtx3body::DCATrackPosToPV, kfvtx3body::DCATrackNegToPV, kfvtx3body::DCATrackBachToPV, - kfvtx3body::Track0Sign, kfvtx3body::Track1Sign, kfvtx3body::Track2Sign, // track sing: proton, pion, deuteron - kfvtx3body::TPCNSigmaProton, kfvtx3body::TPCNSigmaPion, kfvtx3body::TPCNSigmaDeuteron, kfvtx3body::TPCNSigmaPionBach, - kfvtx3body::TPCdEdxProton, kfvtx3body::TPCdEdxPion, kfvtx3body::TPCdEdxDeuteron, - kfvtx3body::TOFNSigmaDeuteron, - kfvtx3body::ITSClusSizeDeuteron, - kfvtx3body::PIDTrackingDeuteron, - - // MC information - kfvtx3body::GenP, - kfvtx3body::GenPt, - kfvtx3body::GenDecVtxX, kfvtx3body::GenDecVtxY, kfvtx3body::GenDecVtxZ, - kfvtx3body::GenCtau, - kfvtx3body::GenPhi, - kfvtx3body::GenEta, - kfvtx3body::GenRapidity, - kfvtx3body::GenPosP, kfvtx3body::GenPosPt, - kfvtx3body::GenNegP, kfvtx3body::GenNegPt, - kfvtx3body::GenBachP, kfvtx3body::GenBachPt, - kfvtx3body::IsTrueH3L, kfvtx3body::IsTrueAntiH3L, - kfvtx3body::PdgCodeDau0, kfvtx3body::PdgCodeDau1, kfvtx3body::PdgCodeDau2, - kfvtx3body::IsBachPrimary, - kfvtx3body::IsReco, - kfvtx3body::SurvEvSel); - -// Definition of labels for KFVtx3BodyDatas -namespace mckfvtx3bodylabel -{ -DECLARE_SOA_INDEX_COLUMN(McParticle, mcParticle); //! MC particle for KF Vtx3BodyDatas -} // namespace mckfvtx3bodylabel - -DECLARE_SOA_TABLE(McKFVtx3BodyLabels, "AOD", "MCKFVTXLABEL", //! Table joinable with KFVtx3BodyData containing the MC labels - mckfvtx3bodylabel::McParticleId); -using McKFVtx3BodyLabel = McKFVtx3BodyLabels::iterator; - -// Definition of labels for KFDecay3Bodys // Full table, joinable with KFDecay3Bodys (CAUTION: NOT WITH Vtx3BodyDATA) -namespace mcfullkfvtx3bodylabel -{ -DECLARE_SOA_INDEX_COLUMN(McParticle, mcParticle); //! MC particle for Decay3Bodys -} // namespace mcfullkfvtx3bodylabel + vtx3body::Px, vtx3body::Py, vtx3body::Pz, + vtx3body::Chi2, + vtx3body::TrackedClSize, + vtx3body::PxTrackPr, vtx3body::PyTrackPr, vtx3body::PzTrackPr, + vtx3body::PxTrackPi, vtx3body::PyTrackPi, vtx3body::PzTrackPi, + vtx3body::PxTrackDe, vtx3body::PyTrackDe, vtx3body::PzTrackDe, + vtx3body::DCAXYTrackPrToPV, vtx3body::DCAXYTrackPiToPV, vtx3body::DCAXYTrackDeToPV, + vtx3body::DCAZTrackPrToPV, vtx3body::DCAZTrackPiToPV, vtx3body::DCAZTrackDeToPV, + vtx3body::DCATrackPrToSV, vtx3body::DCATrackPiToSV, vtx3body::DCATrackDeToSV, + vtx3body::DCAVtxDaughters, + vtx3body::TPCNSigmaPr, vtx3body::TPCNSigmaPi, vtx3body::TPCNSigmaDe, vtx3body::TPCNSigmaPiBach, + vtx3body::TOFNSigmaDe, + vtx3body::ITSClSizePr, vtx3body::ITSClSizePi, vtx3body::ITSClSizeDe, + vtx3body::TPCNClTrackPr, vtx3body::TPCNClTrackPi, vtx3body::TPCNClTrackDe, + vtx3body::PIDTrackingDe, + + // Monte Carlo information + vtx3body::GenPx, vtx3body::GenPy, vtx3body::GenPz, + vtx3body::GenX, vtx3body::GenY, vtx3body::GenZ, + vtx3body::GenCt, + 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::PrPdgCode, vtx3body::PiPdgCode, vtx3body::DePdgCode, + vtx3body::IsDePrimary, + vtx3body::IsSurvEvSel, + + // Dynamic columns + vtx3body::P, + vtx3body::Pt, + vtx3body::GenP, + vtx3body::GenPt, + vtx3body::VtxRadius, + vtx3body::GenRadius, + vtx3body::DistOverTotMom, + vtx3body::VtxCosPA, + vtx3body::DCAVtxToPV, + + // Longitudinal + vtx3body::Rap, + vtx3body::Eta, + vtx3body::Phi, + vtx3body::TrackPrPt, + vtx3body::TrackPrEta, + vtx3body::TrackPrPhi, + vtx3body::TrackPiPt, + vtx3body::TrackPiEta, + vtx3body::TrackPiPhi, + vtx3body::TrackDePt, + vtx3body::TrackDeEta, + vtx3body::TrackDePhi); + +// Define joins +using Vtx3BodyDatasCovs = soa::Join; +using Vtx3BodyDatasCovsIndexed = soa::Join; -DECLARE_SOA_TABLE(McFullKFVtx3BodyLabels, "AOD", "MCFULLKFLABEL", //! Table joinable with Decay3Bodys (CAUTION: NOT WITH Vtx3BodyDATA) - mcfullkfvtx3bodylabel::McParticleId); -using McFullKFVtx3BodyLabel = McFullKFVtx3BodyLabels::iterator; } // namespace o2::aod #endif // PWGLF_DATAMODEL_VTX3BODYTABLES_H_ diff --git a/PWGLF/TableProducer/Nuspex/CMakeLists.txt b/PWGLF/TableProducer/Nuspex/CMakeLists.txt index f8f62f22925..7138fe9ded7 100644 --- a/PWGLF/TableProducer/Nuspex/CMakeLists.txt +++ b/PWGLF/TableProducer/Nuspex/CMakeLists.txt @@ -11,7 +11,7 @@ o2physics_add_dpl_workflow(decay3bodybuilder SOURCES decay3bodybuilder.cxx - PUBLIC_LINK_LIBRARIES O2::DCAFitter KFParticle::KFParticle O2Physics::AnalysisCore O2::TOFBase O2Physics::EventFilteringUtils O2::DetectorsVertexing + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::DCAFitter KFParticle::KFParticle O2::TOFBase O2Physics::EventFilteringUtils O2::DetectorsVertexing COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(hyhefour-builder @@ -29,11 +29,6 @@ o2physics_add_dpl_workflow(lnn-reco-task PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::DCAFitter COMPONENT_NAME Analysis) -o2physics_add_dpl_workflow(hypertriton3bodyfinder - SOURCES hypertriton3bodyfinder.cxx - PUBLIC_LINK_LIBRARIES O2::DCAFitter O2Physics::AnalysisCore - COMPONENT_NAME Analysis) - o2physics_add_dpl_workflow(nucleustreecreator SOURCES LFTreeCreatorNuclei.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore @@ -59,11 +54,6 @@ o2physics_add_dpl_workflow(threebodymcfinder PUBLIC_LINK_LIBRARIES O2::DCAFitter O2Physics::AnalysisCore COMPONENT_NAME Analysis) -o2physics_add_dpl_workflow(threebody-reco-task - SOURCES threebodyRecoTask.cxx - PUBLIC_LINK_LIBRARIES O2::DCAFitter O2Physics::AnalysisCore O2Physics::EventFilteringUtils - COMPONENT_NAME Analysis) - o2physics_add_dpl_workflow(ebye-maker SOURCES ebyeMaker.cxx PUBLIC_LINK_LIBRARIES O2::DCAFitter O2Physics::AnalysisCore @@ -79,11 +69,6 @@ o2physics_add_dpl_workflow(pidtof-generic PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::TOFBase COMPONENT_NAME Analysis) -o2physics_add_dpl_workflow(threebody-kf-task - SOURCES threebodyKFTask.cxx - PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore - COMPONENT_NAME Analysis) - o2physics_add_dpl_workflow(hypernuclei-kf-reco-task SOURCES hypKfRecoTask.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore KFParticle::KFParticle diff --git a/PWGLF/TableProducer/Nuspex/decay3bodybuilder.cxx b/PWGLF/TableProducer/Nuspex/decay3bodybuilder.cxx index b7b643bca21..77c3e5668a7 100644 --- a/PWGLF/TableProducer/Nuspex/decay3bodybuilder.cxx +++ b/PWGLF/TableProducer/Nuspex/decay3bodybuilder.cxx @@ -9,10 +9,12 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. +// ======================== /// \file decay3bodybuilder.cxx -/// \brief Builder task for 3-body decay reconstruction (p + pion + bachelor) +/// \brief Builder task for 3-body hypertriton decay reconstruction (proton + pion + deuteron) /// \author Yuanzhe Wang -/// \author Carolina Reetz (KFParticle specific part) +/// \author Carolina Reetz +// ======================== #include #include @@ -20,25 +22,20 @@ #include #include #include -#include #include - -#include -#include +#include #include "Framework/runDataProcessing.h" #include "Framework/AnalysisTask.h" #include "Framework/AnalysisDataModel.h" #include "Framework/ASoAHelpers.h" -#include "DCAFitter/DCAFitterN.h" #include "ReconstructionDataFormats/Track.h" -#include "DetectorsVertexing/SVertexHypothesis.h" #include "Common/Core/RecoDecay.h" #include "Common/Core/trackUtilities.h" -#include "PWGLF/DataModel/LFStrangenessTables.h" #include "PWGLF/DataModel/Reduced3BodyTables.h" #include "PWGLF/DataModel/Vtx3BodyTables.h" #include "PWGLF/DataModel/pidTOFGeneric.h" +#include "PWGLF/Utils/decay3bodyBuilderHelper.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/PIDResponse.h" #include "Common/Core/PID/PIDTOF.h" @@ -53,8 +50,6 @@ #include "DataFormatsParameters/GRPObject.h" #include "DataFormatsParameters/GRPMagField.h" #include "CCDB/BasicCCDBManager.h" -#include "DataFormatsTPC/BetheBlochAleph.h" -#include "DataFormatsCalibration/MeanVertexObject.h" #ifndef HomogeneousField #define HomogeneousField @@ -70,308 +65,207 @@ using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; -using std::array; - -using FullTracksExtIU = soa::Join; -using FullTracksExtPIDIU = soa::Join; - -using ColwithEvTimes = o2::soa::Join; -using ColwithEvTimesMults = o2::soa::Join; -using TrackExtIUwithEvTimes = soa::Join; -using TrackExtPIDIUwithEvTimes = soa::Join; - -using MCLabeledTracksIU = soa::Join; - -using ReducedCollisionsMults = soa::Join; -using ReducedCollisionsMultsCents = soa::Join; - -namespace -{ -const float pidCutsLambda[o2::vertexing::SVertexHypothesis::NPIDParams] = {0., 20, 0., 5.0, 0.0, 1.09004e-03, 2.62291e-04, 8.93179e-03, 2.83121}; // Lambda -} // namespace - -struct VtxCandidate { - int track0Id; - int track1Id; - int track2Id; - int collisionId; - int decay3bodyId; - float vtxPos[3]; - float track0P[3]; - float track1P[3]; - float track2P[3]; - float dcadaughters; - float daudcaxytopv[3]; // 0 - proton, 1 - pion, 2 - bachelor - float daudcatopv[3]; // 0 - proton, 1 - pion, 2 - bachelor - float bachelortofNsigma; -}; -struct kfCandidate { - // hypertriton - int collisionID; - int trackPosID; - int trackNegID; - int trackBachID; - int decay3bodyID; - float mass; - float pos[3]; - float posErr[3]; - float mom[4]; - float momErr[4]; - float charge; - float dcaToPV[2]; // 3D, xy - float cpaToPV[2]; // 3D, xy - float cpaToPVtopo[2]; // 3D, xy - float decLen[2]; // 3D, xy - float ldl; - float chi2geoNDF; - float chi2topoNDF; - float ctau; - float trackedClSize; - float DeltaPhiRotDeuteron; - float DeltaPhiRotProton; - // V0 - float massV0; - float chi2massV0; - float cpaV0ToPV; - // daughter momenta - float protonMom[3]; - float pionMom[3]; - float deuteronMom[3]; - float tpcInnerParam[3]; // proton, pion, deuteron - // daughter track quality - int tpcNClDaughters[3]; // proton, pion, deuteron - float tpcChi2NClDeuteron; - // daughter DCAs KF - float DCAdaughterToPV[3]; // proton, pion, deuteron - float DCAdaughterToPVxy[3]; // proton, pion, deuteron - float DCAdaughterToSVxy[3]; // proton, pion, deuteron - float DCAprotonToPion; - float DCAprotonToDeuteron; - float DCApionToDeuteron; - float DCAvtxDaughters3D; - // daughter DCAs to PV propagated with material - float trackDCAxy[3]; // pos, neg, bach - float trackDCA[3]; // pos, neg, bach - // daughter signs - float daughterCharge[3]; // proton, pion, deuteron - // daughter PID - float tpcNsigma[4]; // proton, pion, deuteron, bach with pion hyp - float tpcdEdx[3]; // proton, pion, deuteron - float tofNsigmaDeuteron; - float averageClusterSizeDeuteron; - float pidForTrackingDeuteron; +static constexpr int nParameters = 1; +static const std::vector tableNames{ + "Decay3BodyIndices", + "Vtx3BodyDatas", + "Vtx3BodyCovs", + "McVtx3BodyDatas"}; + +static constexpr int nTablesConst = 4; + +static const std::vector parameterNames{"enable"}; +static const int defaultParameters[nTablesConst][nParameters]{ + {0}, // Decay3BodyIndices + {0}, // Vtx3BodyDatas + {0}, // Vtx3BodyCovs + {0} // McVtx3BodyDatas }; -struct decay3bodyBuilder { - - Produces vtx3bodydata; - Produces kfvtx3bodydata; - Produces kfvtx3bodydatalite; - Service ccdb; - o2::base::Propagator::MatCorrType matCorr = o2::base::Propagator::MatCorrType::USEMatCorrNONE; - std::vector VtxCandidates; +using TracksExtPIDIUwithEvTimes = soa::Join; +using TracksExtPIDIUwithEvTimesLabeled = soa::Join; - std::unordered_map ccdbCache; // Maps runNumber -> d_bz - std::unordered_map> grpMagCache; // Maps runNumber -> grpmap +using ColswithEvTimes = o2::soa::Join; +using ColswithEvTimesLabeled = o2::soa::Join; - Zorro zorro; - OutputObj zorroSummary{"zorroSummary"}; +struct decay3bodyBuilder { - std::vector fTrackedClSizeVector; + // helper object + o2::pwglf::decay3bodyBuilderHelper helper; + + // table index : match order above + enum tableIndex { kDecay3BodyIndices = 0, + kVtx3BodyDatas, + kVtx3BodyCovs, + kMcVtx3BodyDatas, + nTables }; + + struct : ProducesGroup { + Produces decay3bodyindices; + Produces vtx3bodydatas; + Produces vtx3bodycovs; + Produces mcvtx3bodydatas; + } products; + + // enablde tables + Configurable> enabledTables{"enabledTables", + {defaultParameters[0], nTables, nParameters, tableNames, parameterNames}, + "Produce this table: 0 - false, 1 - true"}; + std::vector mEnabledTables; // Vector of enabled tables + + // general options + Configurable useMatCorrType{"useMatCorrType", 0, "0: none, 1: TGeo, 2: LUT"}; + Configurable doTrackQA{"doTrackQA", false, "Flag to fill QA histograms for daughter tracks of (selected) decay3body candidates."}; + Configurable doVertexQA{"doVertexQA", false, "Flag to fill QA histograms for PV of (selected) events."}; + Configurable doSel8selection{"doSel8selection", true, "flag for sel8 event selection"}; + Configurable doPosZselection{"doPosZselection", true, "flag for posZ event selection"}; - // Configurables - Configurable d_UseAbsDCA{"d_UseAbsDCA", true, "Use Abs DCAs"}; - - enum Hyp3Body { kH3L = 0, - kH4L, - kHe4L, - kHe5L, - kNHyp3body }; - - enum VtxStep { kVtxAll = 0, - kVtxTPCNcls, - kVtxPIDCut, - kVtxhasSV, - kVtxDcaDau, - kVtxCosPA, - kNVtxSteps }; - - enum kfvtxstep { kKfVtxAll = 0, - kKfVtxCharge, - kKfVtxEta, - kKfVtxTPCNcls, - kKfVtxTPCRows, - kKfVtxTPCPID, - kKfVtxDCAxyPV, - kKfVtxDCAzPV, - kKfVtxV0MassConst, - kKfVtxhasSV, - kKfVtxDcaDau, - kKfVtxDcaDauVtx, - kKfVtxDauPt, - kKfVtxRap, - kKfVtxPt, - kKfVtxMass, - kKfVtxCosPA, - kKfVtxCosPAXY, - kKfVtxChi2geo, - kKfVtxTopoConstr, - kKfVtxChi2topo, - kKfNVtxSteps }; - - HistogramRegistry registry{"registry", {}}; - - // hypothesis - Configurable motherhyp{"motherhyp", 0, "hypothesis of the 3body decayed particle"}; // corresponds to Hyp3Body - int bachelorcharge = 1; // to be updated in Init base on the hypothesis - o2::aod::pidtofgeneric::TofPidNewCollision bachelorTOFPID; // to be updated in Init base on the hypothesis - - // Selection criteria - Configurable d_bz_input{"d_bz", -999, "bz field, -999 is automatic"}; - Configurable mintpcNCls{"mintpcNCls", 70, "min tpc Nclusters"}; - Configurable minCosPA3body{"minCosPA3body", 0.9, "minCosPA3body"}; - Configurable dcavtxdau{"dcavtxdau", 1.0, "DCA Vtx Daughters"}; - Configurable enablePidCut{"enablePidCut", 0, "enable function checkPIDH3L"}; - Configurable TofPidNsigmaMin{"TofPidNsigmaMin", -5, "TofPidNsigmaMin"}; - Configurable TofPidNsigmaMax{"TofPidNsigmaMax", 5, "TofPidNsigmaMax"}; - Configurable TpcPidNsigmaCut{"TpcPidNsigmaCut", 5, "TpcPidNsigmaCut"}; - Configurable minBachPUseTOF{"minBachPUseTOF", 1, "minBachP Enable TOF PID"}; + // data processing options + Configurable doSkimmedProcessing{"doSkimmedProcessing", false, "Apply Zoroo counting in case of skimmed data input"}; + Configurable triggerList{"triggerList", "fTriggerEventF1Proton, fTrackedOmega, fTrackedXi, fOmegaLargeRadius, fDoubleOmega, fOmegaHighMult, fSingleXiYN, fQuadrupleXi, fDoubleXi, fhadronOmega, fOmegaXi, fTripleXi, fOmega, fGammaVeryLowPtEMCAL, fGammaVeryLowPtDCAL, fGammaHighPtEMCAL, fGammaLowPtEMCAL, fGammaVeryHighPtDCAL, fGammaVeryHighPtEMCAL, fGammaLowPtDCAL, fJetNeutralLowPt, fJetNeutralHighPt, fGammaHighPtDCAL, fJetFullLowPt, fJetFullHighPt, fEMCALReadout, fPCMandEE, fPHOSnbar, fPCMHighPtPhoton, fPHOSPhoton, fLD, fPPPHI, fPD, fLLL, fPLL, fPPL, fPPP, fLeadingPtTrack, fHighFt0cFv0Flat, fHighFt0cFv0Mult, fHighFt0Flat, fHighFt0Mult, fHighMultFv0, fHighTrackMult, fHfSingleNonPromptCharm3P, fHfSingleNonPromptCharm2P, fHfSingleCharm3P, fHfPhotonCharm3P, fHfHighPt2P, fHfSigmaC0K0, fHfDoubleCharm2P, fHfBeauty3P, fHfFemto3P, fHfFemto2P, fHfHighPt3P, fHfSigmaCPPK, fHfDoubleCharm3P, fHfDoubleCharmMix, fHfPhotonCharm2P, fHfV0Charm2P, fHfBeauty4P, fHfV0Charm3P, fHfSingleCharm2P, fHfCharmBarToXiBach, fSingleMuHigh, fSingleMuLow, fLMeeHMR, fDiMuon, fDiElectron, fLMeeIMR, fSingleE, fTrackHighPt, fTrackLowPt, fJetChHighPt, fJetChLowPt, fUDdiffLarge, fUDdiffSmall, fITSextremeIonisation, fITSmildIonisation, fH3L3Body, fHe, fH2", "List of triggers used to select events"}; + Configurable onlyKeepInterestedTrigger{"onlyKeepInterestedTrigger", false, "Flag to keep only interested trigger"}; - Configurable useMatCorrType{"useMatCorrType", 0, "0: none, 1: TGeo, 2: LUT"}; // CCDB options - 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 geoPath{"geoPath", "GLO/Config/GeometryAligned", "Path of the geometry file"}; - // CCDB TOF PID paras - Configurable timestamp{"ccdb-timestamp", -1, "timestamp of the object"}; - 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 passName{"passName", "", "Name of the pass inside of the CCDB parameter collection. If empty, the automatically deceted from metadata (to be implemented!!!)"}; - Configurable timeShiftCCDBPath{"timeShiftCCDBPath", "", "Path of the TOF time shift vs eta. If empty none is taken"}; - Configurable loadResponseFromCCDB{"loadResponseFromCCDB", false, "Flag to load the response from the CCDB"}; - Configurable fatalOnPassNotAvailable{"fatalOnPassNotAvailable", true, "Flag to throw a fatal if the pass is not available in the retrieved CCDB object"}; - // for KFParticle reconstruction struct : ConfigurableGroup { - Configurable cfgSkimmedProcessing{"kfparticleConfigurations.cfgSkimmedProcessing", false, "Flag for skimmed dataset processing"}; - Configurable triggerList{"kfparticleConfigurations.triggerList", "fH3L3Body", "List of triggers used to select events"}; - Configurable cfgOnlyKeepInterestedTrigger{"kfparticleConfigurations.cfgOnlyKeepInterestedTrigger", false, "Flag to keep only interested trigger"}; - Configurable fillCandidateFullTable{"kfparticleConfigurations.fillCandidateFullTable", false, "Switch to fill full table with candidate properties"}; - Configurable doSel8selection{"kfparticleConfigurations.doSel8selection", true, "flag for sel8 event selection"}; - Configurable doPosZselection{"kfparticleConfigurations.doPosZselection", true, "flag for posZ event selection"}; - Configurable doDCAFitterPreMinimum{"kfparticleConfigurations.doDCAFitterPreMinimum", false, "do DCAFitter pre-optimization before KF fit to include material corrections for decay3body vertex"}; - Configurable doTrackQA{"kfparticleConfigurations.doTrackQA", false, "Flag to fill QA histograms for daughter tracks."}; - Configurable doVertexQA{"kfparticleConfigurations.doVertexQA", false, "Flag to fill QA histograms for KFParticle PV."}; - Configurable useLambdaMassConstraint{"kfparticleConfigurations.useLambdaMassConstraint", false, "Apply Lambda mass constraint on proton-pion vertex"}; - Configurable doDCAPreSel{"kfparticleConfigurations.doDCAPreSel", false, "Apply selection on DCA of daughter tracks to PV"}; - Configurable maxEta{"kfparticleConfigurations.maxEta", 1.0, "Maximum eta for proton and pion daughter tracks"}; - Configurable maxEtaDeuteron{"kfparticleConfigurations.maxEtaDeuteron", 0.9, "Maximum eta for deuteron daughter track"}; - Configurable useTPCforPion{"kfparticleConfigurations.useTPCforPion", true, "Flag to ask for TPC info for pion track (PID, nClusters), false: pion track can be ITS only"}; - Configurable mintpcNClsProton{"kfparticleConfigurations.mintpcNClsProton", 70, "Minimum number of TPC clusters for proton track"}; - Configurable mintpcNClsPion{"kfparticleConfigurations.mintpcNClsPion", 70, "Minimum number of TPC clusters for pion track"}; - Configurable mintpcNClsBach{"kfparticleConfigurations.mintpcNClsBach", 70, "Minimum number of TPC clusters for bachelor track"}; - Configurable mintpcCrossedRows{"kfparticleConfigurations.mintpcCrossedRows", 70, "Minimum number of TPC crossed rows for proton and deuteron track"}; - Configurable mintpcCrossedRowsPion{"kfparticleConfigurations.mintpcCrossedRowsPion", 70, "Minimum number of TPC crossed rows for pion track"}; - Configurable minPtProton{"kfparticleConfigurations.minPtProton", 0.1, "Minimum pT of proton track"}; - Configurable maxPtProton{"kfparticleConfigurations.maxPtProton", 10, "Maximum pT of proton track"}; - Configurable minPtPion{"kfparticleConfigurations.minPtPion", 0.1, "Minimum pT of pion track"}; - Configurable maxPtPion{"kfparticleConfigurations.maxPtPion", 10, "Maximum pT of pion track"}; - Configurable minPtDeuteron{"kfparticleConfigurations.minPtDeuteron", 0.1, "Minimum pT of deuteron track"}; - Configurable maxPtDeuteron{"kfparticleConfigurations.maxPtDeuteron", 10, "Maximum pT of deuteron track"}; - Configurable mindcaXYPionPV{"kfparticleConfigurations.mindcaXYPionPV", 0.1, "Minimum DCA XY of the pion daughter track to the PV"}; - Configurable mindcaXYProtonPV{"kfparticleConfigurations.mindcaXYProtonPV", 0.1, "Minimum DCA XY of the proton daughter track to the PV"}; - Configurable mindcaZPionPV{"kfparticleConfigurations.mindcaZPionPV", 0.1, "Minimum DCA Z of the pion daughter track to the PV"}; - Configurable mindcaZProtonPV{"kfparticleConfigurations.mindcaZProtonPV", 0.1, "Minimum DCA Z of the proton daughter track to the PV"}; - Configurable maxtpcnSigma{"kfparticleConfigurations.maxtpcnSigma", 5., "Maximum nSigma TPC for daughter tracks"}; - Configurable maxDcaProDeu{"kfparticleConfigurations.maxDcaProDeu", 1000., "Maximum geometrical distance between proton and deuteron at the SV in 3D with KFParticle"}; - Configurable maxDcaProPi{"kfparticleConfigurations.maxDcaProPi", 1000., "Maximum geometrical distance between proton and pion at the SV in 3D with KFParticle"}; - Configurable maxDcaPiDe{"kfparticleConfigurations.maxDcaPiDe", 1000., "Maximum geometrical distance between pion and deuteron at the SV in 3D with KFParticle"}; - Configurable maxDcaXYSVDau{"kfparticleConfigurations.maxDcaXYSVDau", 1.0, "Maximum geometrical distance of daughter tracks from the SV in XY with KFParticle"}; - Configurable maxRapidityHt{"kfparticleConfigurations.maxRapidityHt", 1., "Maximum rapidity for Hypertriton candidates with KFParticle"}; - Configurable minPtHt{"kfparticleConfigurations.minPtHt", 0.01, "Minimum momentum for Hypertriton candidates with KFParticle (0.01 applied in SVertexer)"}; - Configurable maxPtHt{"kfparticleConfigurations.maxPtHt", 36., "Maximum momentum for Hypertriton candidates with KFParticle"}; - Configurable minMassHt{"kfparticleConfigurations.minMassHt", 2.96, "Minimum candidate mass with KFParticle"}; - Configurable maxMassHt{"kfparticleConfigurations.maxMassHt", 3.05, "Maximum candidate mass with KFParticle"}; - Configurable maxctauHt{"kfparticleConfigurations.maxctauHt", 40., "Maximum candidate ctau with KFParticle before topological constraint"}; - Configurable maxChi2geo{"kfparticleConfigurations.maxChi2geo", 1000., "Maximum chi2 geometrical with KFParticle"}; - Configurable minCosPA{"kfparticleConfigurations.minCosPA", 0.8, "Minimum cosine pointing angle with KFParticle (0.8 applied in SVertexer)"}; - Configurable minCosPAxy{"kfparticleConfigurations.minCosPAxy", 0.8, "Minimum cosine pointing angle in xy with KFParticle"}; - Configurable applyTopoSel{"kfparticleConfigurations.applyTopoSel", false, "Apply selection constraining the mother to the PV with KFParticle"}; - Configurable maxChi2topo{"kfparticleConfigurations.maxChi2topo", 1000., "Maximum chi2 topological with KFParticle"}; - Configurable nEvtMixing{"kfparticleConfigurations.nEvtMixing", 5, "Number of events to mix"}; - ConfigurableAxis binsVtxZ{"kfparticleConfigurations.binsVtxZ", {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 binsMultiplicity{"kfparticleConfigurations.binsMultiplicity", {VARIABLE_WIDTH, 0.0f, 1.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"}; - // 3body mixing - Configurable mixingType{"kfparticleConfigurations.mixingType", 0, "0: mix V0 from one event with bachelor from another, 1: mix pion and bachelor from one event with proton from another "}; - Configurable applySVertexerV0Cuts{"kfparticleConfigurations.applySVertexerV0Cuts", false, "Apply virtual V0 cuts applied in SVertexer in case of proton mixing"}; - ConfigurableAxis bins3BodyRadius{"kfparticleConfigurations.bins3BodyRadius", {VARIABLE_WIDTH, 0.0f, 0.5f, 1.0f, 1.5f, 2.0f, 3.0f, 4.0f, 6.0f, 8.0f, 10.0f, 12.0f, 14.0f, 16.0f, 18.0f, 20.0f, 30.0f, 1000.0}, "Mixing bins - 3body radius"}; - // ConfigurableAxis bins3BodyPhi{"kfparticleConfigurations.bins3BodyPhi", {VARIABLE_WIDTH, -180.0f*TMath::Pi()/180, -170.0f*TMath::Pi()/180, -160.0f*TMath::Pi()/180, -150.0f*TMath::Pi()/180, -140.0f*TMath::Pi()/180, -130.0f*TMath::Pi()/180, -120.0f*TMath::Pi()/180, -110.0f*TMath::Pi()/180, -100.0f*TMath::Pi()/180, -90.0f*TMath::Pi()/180, -80.0f*TMath::Pi()/180, -70.0f*TMath::Pi()/180, -60.0f*TMath::Pi()/180, -50.0f*TMath::Pi()/180, -40.0f*TMath::Pi()/180, -30.0f*TMath::Pi()/180, -20.0f*TMath::Pi()/180, -10.0f*TMath::Pi()/180, 0.0f, 10.0f*TMath::Pi()/180, 20.0f*TMath::Pi()/180, 30.0f*TMath::Pi()/180, 40.0f*TMath::Pi()/180, 50.0f*TMath::Pi()/180, 60.0f*TMath::Pi()/180, 70.0f*TMath::Pi()/180, 80.0f*TMath::Pi()/180, 90.0f*TMath::Pi()/180, 100.0f*TMath::Pi()/180, 110.0f*TMath::Pi()/180, 120.0f*TMath::Pi()/180, 130.0f*TMath::Pi()/180, 140.0f*TMath::Pi()/180, 150.0f*TMath::Pi()/180, 160.0f*TMath::Pi()/180, 170.0f*TMath::Pi()/180, 180.0f*TMath::Pi()/180}, "Mixing bins - 3body phi"}; - ConfigurableAxis bins3BodyPhi{"kfparticleConfigurations.bins3BodyPhi", {VARIABLE_WIDTH, -180.0f * TMath::Pi() / 180, -160.0f * TMath::Pi() / 180, -140.0f * TMath::Pi() / 180, -120.0f * TMath::Pi() / 180, -100.0f * TMath::Pi() / 180, -80.0f * TMath::Pi() / 180, -60.0f * TMath::Pi() / 180, -40.0f * TMath::Pi() / 180, -20.0f * TMath::Pi() / 180, 0.0f, 20.0f * TMath::Pi() / 180, 40.0f * TMath::Pi() / 180, 60.0f * TMath::Pi() / 180, 80.0f * TMath::Pi() / 180, 100.0f * TMath::Pi() / 180, 120.0f * TMath::Pi() / 180, 140.0f * TMath::Pi() / 180, 160.0f * TMath::Pi() / 180, 180.0f * TMath::Pi() / 180}, "Mixing bins - 3body phi"}; - ConfigurableAxis bins3BodyPosZ{"kfparticleConfigurations.bins3BodyPosZ", {VARIABLE_WIDTH, -300.0f, -42.0f, -13.0f, -6.0f, -4.0f, -2.0f, 0.0f, 2.0f, 4.0f, 6.0f, 13.0f, 42.0f, 300.0f}, "Mixing bins - 3body z position"}; - Configurable selectVtxZ3bodyMixing{"kfparticleConfigurations.selectVtxZ3bodyMixing", true, "Select same VtxZ events in case of 3body mixing"}; - Configurable VtxZBin3bodyMixing{"kfparticleConfigurations.VtxZBin3bodyMixing", 1., "Bin width for event vtx z position in case of 3body mixing"}; - } kfparticleConfigurations; - - //------------------------------------------------------------------ - // Sets for DCAFitter event mixing + 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 geoPath{"geoPath", "GLO/Config/GeometryAligned", "Path of the geometry file"}; + } ccdbConfigurations; + + // Decay3body building options struct : ConfigurableGroup { - Configurable nUseMixed{"dcaFitterEMSel.nUseMixed", 5, "nUseMixed"}; - Configurable mMinPt2V0{"dcaFitterEMSel.mMinPt2V0", 0.5, "mMinPt2V0"}; // minimum pT^2 of V0 - Configurable mMaxTgl2V0{"dcaFitterEMSel.mMaxTgl2V0", 4, "mMaxTgl2V0"}; // maximum tgLambda^2 of V0 - Configurable mMaxDCAXY2ToMeanVertex3bodyV0{"dcaFitterEMSel.mMaxDCAXY2ToMeanVertex3bodyV0", 4, "mMaxDCAXY2ToMeanVertex3bodyV0"}; // max DCA^2 of 2 body decay to mean vertex of 3 body decay in XY - Configurable minCosPAXYMeanVertex3bodyV0{"dcaFitterEMSel.minCosPAXYMeanVertex3bodyV0", 0.9, "minCosPAXYMeanVertex3bodyV0"}; // min CosPA of 2 body decay to mean vertex of 3 body decay in XY - Configurable minCosPA3bodyV0{"dcaFitterEMSel.minCosPA3bodyV0", 0.8, "minCosPA3bodyV0"}; // min CosPA of 3 body decay to PV - Configurable maxRDiffV03body{"dcaFitterEMSel.maxRDiffV03body", 3, "maxRDiffV03body"}; // Maximum difference between virtual V0 and 3body radius - Configurable minPt3Body = {"dcaFitterEMSel.minPt3Body", 0.01, ""}; // minimum pT of 3body Vertex - Configurable maxTgl3Body = {"dcaFitterEMSel.maxTgl3Body", 2, ""}; // maximum tgLambda of 3body Vertex - Configurable maxDCAXY3Body{"dcaFitterEMSel.maxDCAXY3Body", 0.5, "DCAXY H3L to PV"}; // max DCA of 3 body decay to PV in XY - Configurable maxDCAZ3Body{"dcaFitterEMSel.maxDCAZ3Body", 1.0, "DCAZ H3L to PV"}; // max DCA of 3 body decay to PV in Z - // Binning for mixing events - ConfigurableAxis binsVtxZ{"dcaFitterEMSel.binsVtxZ", {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 binsMultiplicity{"dcaFitterEMSel.binsMultiplicity", {VARIABLE_WIDTH, 0.0f, 1.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"}; - Configurable maxDeltaRadiusColMixing{"dcaFitterEMSel.maxDeltaRadiusColMixing", 2., "max difference between pv z position in case of collision mixing"}; - Configurable maxDeltaPhiColMixing{"dcaFitterEMSel.maxDeltaPhiColMixing", 30., "max difference between Phi of monther particle in case of collision mixing (degree)"}; - // Configurations for mixing decay3bodys - // Configurable cfgUseDCAFitterInfo{"dcaFitterEMSel.cfgUseDCAFitterInfo", true, ""}; // if use information from dcatFitter while mixing reduced 3bodys - Configurable cfgMix3BodyMethod{"dcaFitterEMSel.cfgMix3BodyMethod", 0, ""}; // 0: bachelor, 1: pion, 2: proton - Configurable cfgApplyV0Cut{"dcaFitterEMSel.cfgApplyV0Cut", true, "if apply V0 cut while performing event-mixing"}; - ConfigurableAxis bins3BodyRadius{"dcaFitterEMSel.bins3BodyRadius", {VARIABLE_WIDTH, 0.0f, 2.0f, 4.0f, 7.0f, 10.0f, 14.0f, 18.0f, 22.0f, 30.0f, 40.0f}, "Mixing bins - 3body radius"}; - ConfigurableAxis bins3BodyPhi{"dcaFitterEMSel.bins3BodyPhi", {VARIABLE_WIDTH, -3.15, -2.15, -1, 0, 1, 2.15, 3.15}, "Mixing bins - 3body phi"}; - ConfigurableAxis bins3BodyPhiDegree{"dcaFitterEMSel.bins3BodyPhiDegree", {VARIABLE_WIDTH, -180, -120, -60, 0, 60, 120, 180}, "Mixing bins - 3body phi"}; - ConfigurableAxis bins3BodyPosZ{"dcaFitterEMSel.bins3BodyPosZ", {VARIABLE_WIDTH, -500.0f, -200.0f, -100.0f, -70.0f, -60.0f, -50.0f, -40.0f, -35.0f, -30.0f, -25.0f, -20.0f, -15.0f, -13.0f, -10.0f, -8.0f, -6.0f, -4.0f, -2.0f, 0.0f, 2.0f, 4.0f, 6.0f, 8.0f, 10.0f, 13.0f, 15.0f, 20.0f, 25.0f, 30.0f, 35.0f, 40.0f, 50.0f, 60.0f, 70.0f, 100.0f, 200.0f, 500.0f}, "3body SV z position"}; - Configurable selectPVPosZ3bodyMixing{"dcaFitterEMSel.selectPVPosZ3bodyMixing", true, "Select same pvPosZ events in case of 3body mixing"}; - Configurable maxDeltaPVPosZ3bodyMixing{"dcaFitterEMSel.maxDeltaPVPosZ3bodyMixing", 1., "max difference between pv z position in case of 3body mixing"}; - } dcaFitterEMSel; - - SliceCache cache; - using BinningTypeColEM = ColumnBinningPolicy; - using Binning3BodyDCAFitter = ColumnBinningPolicy; - using Binning3BodyKFInfo = ColumnBinningPolicy; - - // KF event mixing - using BinningTypeKF = ColumnBinningPolicy; + std::string prefix = "decay3bodyBuilderOpts"; + // building options + Configurable useKFParticle{"useKFParticle", false, "Use KFParticle for decay3body building"}; + Configurable kfSetTopologicalConstraint{"kfSetTopologicalConstraint", false, "Set topological vertex constraint in case of KFParticle reconstruction"}; + Configurable useSelections{"useSelections", true, "Apply selections during decay3body building"}; + Configurable useTPCforPion{"useTPCforPion", false, "Flag to ask for TPC info for pion track (PID, nClusters), false: pion track can be ITS only"}; + Configurable acceptTPCOnly{"acceptTPCOnly", false, "Accept TPC only tracks as daughters"}; + Configurable calculateCovariance{"calculateCovariance", true, "Calculate candidate and daughter covariance matrices"}; + // daughter track selections + Configurable maxEtaDaughters{"maxEtaDaughters", 0.9, "Max eta of daughters"}; + Configurable minTPCNClProton{"minTPCNClProton", 90, "Min TPC NClusters of proton daughter"}; + Configurable minTPCNClPion{"minTPCNClPion", 70, "Min TPC NClusters of pion daughter"}; + Configurable minTPCNClDeuteron{"minTPCNClDeuteron", 100, "Min TPC NClusters of deuteron daughter"}; + Configurable minDCAProtonToPV{"minDCAProtonToPV", 0.1, "Min DCA of proton to PV"}; + Configurable minDCAPionToPV{"minDCAPionToPV", 0.1, "Min DCA of pion to PV"}; + Configurable minDCADeuteronToPV{"minDCADeuteronToPV", 0.1, "Min DCA of deuteron to PV"}; + Configurable minPtProton{"minPtProton", 0.3, "Min Pt of proton daughter"}; + Configurable minPtPion{"minPtPion", 0.1, "Min Pt of pion daughter"}; + Configurable minPtDeuteron{"minPtDeuteron", 0.6, "Min Pt of deuteron daughter"}; + Configurable maxPtProton{"maxPtProton", 5.0, "Max Pt of proton daughter"}; + Configurable maxPtPion{"maxPtPion", 1.2, "Max Pt of pion daughter"}; + Configurable maxPtDeuteron{"maxPtDeuteron", 10.0, "Max Pt of deuteron daughter"}; + Configurable maxTPCnSigma{"maxTPCnSigma", 5.0, "Min/max TPC nSigma of daughter tracks"}; + Configurable minTOFnSigmaDeuteron{"minTOFnSigmaDeuteron", -5.0, "Min TOF nSigma of deuteron daughter"}; + Configurable maxTOFnSigmaDeuteron{"maxTOFnSigmaDeuteron", 5.0, "Max TOF nSigma of deuteron daughter"}; + Configurable minPDeuteronUseTOF{"minPDeuteronUseTOF", 1.0, "Min P of deuteron to use TOF PID"}; + Configurable maxDCADauAtSV{"maxDCADauAtSV", 0.5, "Max DCA of daughters at SV (quadratic sum of daughter DCAs between each other)"}; + // candidate selections + Configurable maxRapidity{"maxRapidity", 1.0, "Max rapidity of decay3body vertex"}; + Configurable minPt{"minPt", 2.0, "Min Pt of decay3body candidate"}; + Configurable maxPt{"maxPt", 5.0, "Max Pt of decay3body candidate"}; + Configurable minMass{"minMass", 2.96, "Min mass of decay3body candidate"}; + Configurable maxMass{"maxMass", 3.04, "Max mass of decay3body candidate"}; + Configurable minCtau{"minCtau", 0.0, "Min ctau of decay3body candidate"}; + Configurable maxCtau{"maxCtau", 100.0, "Max ctau of decay3body candidate"}; + Configurable minCosPA{"minCosPA", 0.9, "Min cosPA of decay3body candidate"}; + Configurable maxChi2{"maxChi2", 100.0, "Max chi2 of decay3body candidate"}; + } decay3bodyBuilderOpts; - // 3body mixing - // using Binning3Body = ColumnBinningPolicy; - using Binning3Body = ColumnBinningPolicy; + struct : ConfigurableGroup { + std::string prefix = "mixingOpts"; + Configurable n3bodyMixing{"n3bodyMixing", 0, "Number of decay3bodys to mix: 0 - value set to maximum bin entry in hDecay3BodyRadiusPhi, > 0 - manual setting"}; + Configurable mixingType{"mixingType", 0, "0: mix V0 from one event with bachelor from another, 1: mix pion and bachelor from one event with proton from another, 1: mix proton and bachelor from one event with pion from another "}; + ConfigurableAxis bins3BodyRadius{"mixingOpts.bins3BodyRadius", {VARIABLE_WIDTH, 0.0f, 2.0f, 4.0f, 7.0f, 10.0f, 14.0f, 18.0f, 22.0f, 30.0f, 40.0f}, "Mixing bins - 3body radius"}; + ConfigurableAxis bins3BodyPhi{"mixingOpts.bins3BodyPhi", {VARIABLE_WIDTH, -180 * TMath::Pi() / 180, -120 * TMath::Pi() / 180, -60 * TMath::Pi() / 180, 0, 60 * TMath::Pi() / 180, 120 * TMath::Pi() / 180, 180 * TMath::Pi() / 180}, "Mixing bins - 3body phi (rad)"}; + ConfigurableAxis bins3BodyPhiDegree{"mixingOpts.bins3BodyPhiDegree", {VARIABLE_WIDTH, -180, -120, -60, 0, 60, 120, 180}, "Mixing bins - 3body phi (degree)"}; + ConfigurableAxis bins3BodyPosZ{"mixingOpts.bins3BodyPosZ", {VARIABLE_WIDTH, -500.0f, -200.0f, -100.0f, -70.0f, -60.0f, -50.0f, -40.0f, -35.0f, -30.0f, -25.0f, -20.0f, -15.0f, -13.0f, -10.0f, -8.0f, -6.0f, -4.0f, -2.0f, 0.0f, 2.0f, 4.0f, 6.0f, 8.0f, 10.0f, 13.0f, 15.0f, 20.0f, 25.0f, 30.0f, 35.0f, 40.0f, 50.0f, 60.0f, 70.0f, 100.0f, 200.0f, 500.0f}, "3body SV z position"}; + Configurable selectPVPosZ3bodyMixing{"selectPVPosZ3bodyMixing", true, "Select same pvPosZ events in case of 3body mixing"}; + Configurable maxDeltaPVPosZ3bodyMixing{"maxDeltaPVPosZ3bodyMixing", 1., "max difference between PV z position in case of 3body mixing"}; + // SVertexer selections + Configurable minPt2V0{"minPt2V0", 0.5, "Min Pt squared of V0"}; + Configurable maxTgl2V0{"maxTgl2V0", 4, "Max tgl squared of V0"}; + Configurable maxDCAXY2ToMeanVertex3bodyV0{"maxDCAXY2ToMeanVertex3bodyV0", 4, "Max DCA XY squared of V0 to mean vertex"}; + Configurable minCosPAXYMeanVertex3bodyV0{"minCosPAXYMeanVertex3bodyV0", 0.9, "Min cosPA XY of V0 to mean vertex"}; + Configurable minCosPA3bodyV0{"minCosPA3bodyV0", 0.8, "Min cosPA of V0"}; + Configurable maxRDiffV03body{"maxRDiffV03body", 3, "Max RDiff of V0 to 3body"}; + Configurable minPt3Body{"minPt3Body", 0.5, "Min Pt of 3body"}; + Configurable maxTgl3Body{"maxTgl3Body", 0.01, "Max tgl of 3body"}; + Configurable maxDCAXY3Body{"maxDCAXY3Body", 0.5, "Max DCA XY of 3body"}; + Configurable maxDCAZ3Body{"maxDCAZ3Body", 1.0, "Max DCA Z of 3body"}; + } mixingOpts; - // Filters and slices - Preslice perCollision = o2::aod::decay3body::collisionId; - Preslice perReducedCollision = o2::aod::reduceddecay3body::collisionId; + struct : ConfigurableGroup { + std::string prefix = "tofPIDOpts"; + Configurable timestamp{"ccdb-timestamp", -1, "timestamp of the object"}; + 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 passName{"passName", "", "Name of the pass inside of the CCDB parameter collection. If empty, the automatically deceted from metadata (to be implemented!!!)"}; + Configurable timeShiftCCDBPath{"timeShiftCCDBPath", "", "Path of the TOF time shift vs eta. If empty none is taken"}; + Configurable loadResponseFromCCDB{"loadResponseFromCCDB", false, "Flag to load the response from the CCDB"}; + Configurable fatalOnPassNotAvailable{"fatalOnPassNotAvailable", true, "Flag to throw a fatal if the pass is not available in the retrieved CCDB object"}; + } tofPIDOpts; + + // Helper struct to contain MC information prior to filling + struct mc3Bodyinfo { + int label; + std::array genDecVtx{0.f}; + std::array genMomentum{0.f}; + float genCt; + float genPhi; + float genEta; + float genRapidity; + float genMomProton; + float genMomPion; + float genMomDeuteron; + float genPtProton; + float genPtPion; + float genPtDeuteron; + bool isTrueH3L; + bool isTrueAntiH3L; + bool isReco; + int daughterPrPdgCode; + int daughterPiPdgCode; + int daughterDePdgCode; + bool isDeuteronPrimary; + bool survivedEventSel; + }; + mc3Bodyinfo this3BodyMCInfo; + // CCDB and magnetic field int mRunNumber; float d_bz; - float maxSnp; // max sine phi for propagation - float maxStep; // max step size (cm) for propagation + Service ccdb; + o2::base::Propagator::MatCorrType matCorr = o2::base::Propagator::MatCorrType::USEMatCorrNONE; + std::unordered_map ccdbCache; // Maps runNumber -> d_bz o2::base::MatLayerCylSet* lut = nullptr; - o2::vertexing::DCAFitterN<2> fitterV0; - o2::vertexing::DCAFitterN<3> fitter3body; + + // histogram registry + HistogramRegistry registry{"Registry", {}, OutputObjHandlingPolicy::AnalysisObject}; + + // bachelor TOF PID + o2::aod::pidtofgeneric::TofPidNewCollision bachelorTOFPID; // to be updated in Init based on the hypothesis + o2::aod::pidtofgeneric::TofPidNewCollision bachelorTOFPIDLabeled; // to be updated in Init based on the hypothesis o2::pid::tof::TOFResoParamsV2 mRespParamsV2; - std::array mV0Hyps; // 0 - Lambda, 1 - AntiLambda - bool doUpdateGRPMagField = false; // if initialize magnetic field for each bc - o2::dataformats::VertexBase mMeanVertex{{0., 0., 0.}, {0.1 * 0.1, 0., 0.1 * 0.1, 0., 0., 6. * 6.}}; + + // 3body mixing + using Binning3BodyKF = ColumnBinningPolicy; + using Binning3BodyDCAfitter = ColumnBinningPolicy; + + // skimmed processing + Zorro zorro; + OutputObj zorroSummary{"zorroSummary"}; + + // tracked cluster size + std::vector fTrackedClSizeVector; + + // MC info + std::vector isGoodCollision; void init(InitContext&) { @@ -379,276 +273,238 @@ struct decay3bodyBuilder { mRunNumber = 0; d_bz = 0; - maxSnp = 0.85f; // could be changed later - maxStep = 2.00f; // could be changed later - - // set hypothesis corresponds to Hyp3Body, tpcpid to be implemented - switch (motherhyp) { - case Hyp3Body::kH3L: - bachelorcharge = 1; - bachelorTOFPID.SetPidType(o2::track::PID::Deuteron); - break; - case Hyp3Body::kH4L: - bachelorcharge = 1; - bachelorTOFPID.SetPidType(o2::track::PID::Triton); - break; - case Hyp3Body::kHe4L: - bachelorcharge = 2; - bachelorTOFPID.SetPidType(o2::track::PID::Helium3); - break; - case Hyp3Body::kHe5L: - bachelorcharge = 2; - bachelorTOFPID.SetPidType(o2::track::PID::Alpha); - break; - default: - LOG(fatal) << "Wrong hypothesis for decay3body"; - return; - } - fitterV0.setPropagateToPCA(true); - fitterV0.setMaxR(200.); - fitterV0.setMinParamChange(1e-3); - fitterV0.setMinRelChi2Change(0.9); - fitterV0.setMaxDZIni(1e9); - fitterV0.setMaxChi2(1e9); - fitterV0.setUseAbsDCA(d_UseAbsDCA); - - fitter3body.setPropagateToPCA(true); - fitter3body.setMaxR(200.); //->maxRIni3body - fitter3body.setMinParamChange(1e-3); - fitter3body.setMinRelChi2Change(0.9); - fitter3body.setMaxDZIni(1e9); - fitter3body.setMaxChi2(1e9); - fitter3body.setUseAbsDCA(d_UseAbsDCA); - - // Material correction in the DCA fitter - ccdb->setURL(ccdburl); + mEnabledTables.resize(nTables, 0); + + // CCDB options + ccdb->setURL(ccdbConfigurations.ccdburl); ccdb->setCaching(true); ccdb->setLocalObjectValidityChecking(); ccdb->setFatalWhenNull(false); + // Set material correction if (useMatCorrType == 1) { LOGF(info, "TGeo correction requested, loading geometry"); if (!o2::base::GeometryManager::isGeometryLoaded()) { - ccdb->get(geoPath); + ccdb->get(ccdbConfigurations.geoPath); } + matCorr = o2::base::Propagator::MatCorrType::USEMatCorrTGeo; } if (useMatCorrType == 2) { LOGF(info, "LUT correction requested, loading LUT"); - lut = o2::base::MatLayerCylSet::rectifyPtrFromFile(ccdb->get(lutPath)); - } - - // Material correction in the DCA fitter - if (useMatCorrType == 1) - matCorr = o2::base::Propagator::MatCorrType::USEMatCorrTGeo; - if (useMatCorrType == 2) + lut = o2::base::MatLayerCylSet::rectifyPtrFromFile(ccdb->get(ccdbConfigurations.lutPath)); matCorr = o2::base::Propagator::MatCorrType::USEMatCorrLUT; - - fitterV0.setMatCorrType(matCorr); - fitter3body.setMatCorrType(matCorr); - - // Add histograms separately for different process functions - if (doprocessRun3 == true || doprocessRun3Reduced) { - registry.add("hEventCounter", "hEventCounter", HistType::kTH1F, {{1, 0.0f, 1.0f}}); - } - - if (doprocessRun3 == true || doprocessRun3Reduced || doprocessRun3ReducedEM == true || doprocessRun3Reduced3bodyMixing == true || doprocessRun3Reduced3bodyMixingKFInfo == true) { - auto hVtx3BodyCounter = registry.add("hVtx3BodyCounter", "hVtx3BodyCounter", HistType::kTH1D, {{6, 0.0f, 6.0f}}); - hVtx3BodyCounter->GetXaxis()->SetBinLabel(1, "Total"); - hVtx3BodyCounter->GetXaxis()->SetBinLabel(2, "TPCNcls"); - hVtx3BodyCounter->GetXaxis()->SetBinLabel(3, "PIDCut"); - hVtx3BodyCounter->GetXaxis()->SetBinLabel(4, "HasSV"); - hVtx3BodyCounter->GetXaxis()->SetBinLabel(5, "DcaDau"); - hVtx3BodyCounter->GetXaxis()->SetBinLabel(6, "CosPA"); - registry.add("hBachelorTOFNSigmaDe", "", HistType::kTH2F, {{40, -10.0f, 10.0f, "p/z (GeV/c)"}, {40, -10.0f, 10.0f, "TOF n#sigma"}}); } - if (doprocessRun3ReducedEM == true) { - registry.add("hEventCount", "hEventCount", HistType::kTH2F, {dcaFitterEMSel.binsVtxZ, dcaFitterEMSel.binsMultiplicity}); - registry.add("hEventPairs", "hEventPairs", HistType::kTH2F, {dcaFitterEMSel.binsVtxZ, dcaFitterEMSel.binsMultiplicity}); - registry.add("hDecay3BodyPairsBeforeCut", "hDecay3BodyPairsBeforeCut", HistType::kTH2F, {dcaFitterEMSel.binsVtxZ, dcaFitterEMSel.binsMultiplicity}); - registry.add("hDecay3BodyPairsAfterCut", "hDecay3BodyPairsAfterCut", HistType::kTH2F, {dcaFitterEMSel.binsVtxZ, dcaFitterEMSel.binsMultiplicity}); - registry.add("hRadius0", "hRadius0", HistType::kTH1F, {{200, 0.0f, 20.0f, "Radius (cm)"}}); - registry.add("hRadius1", "hRadius1", HistType::kTH1F, {{200, 0.0f, 20.0f, "Radius (cm)"}}); - registry.add("hDeltaRadius", "hDeltaRadius", HistType::kTH1F, {{400, -20.0f, 20.0f, "#Delta Radius (cm)"}}); - registry.add("hPhi0", "hPhi0", HistType::kTH1F, {{360, -180.0f, 180.0f, "#phi (degree)"}}); - registry.add("hPhi1", "hPhi1", HistType::kTH1F, {{360, -180.0f, 180.0f, "#phi (degree)"}}); - registry.add("hDeltaPhi", "hDeltaPhi", HistType::kTH1F, {{360, -180.0f, 180.0f, "#Delta #phi (degree)"}}); + helper.fitterV0.setMatCorrType(matCorr); + helper.fitter3body.setMatCorrType(matCorr); + + // set bachelor PID + bachelorTOFPID.SetPidType(o2::track::PID::Deuteron); + bachelorTOFPIDLabeled.SetPidType(o2::track::PID::Deuteron); + + // set decay3body parameters in the helper + helper.decay3bodyselections.maxEtaDaughters = decay3bodyBuilderOpts.maxEtaDaughters; + helper.decay3bodyselections.minTPCNClProton = decay3bodyBuilderOpts.minTPCNClProton; + helper.decay3bodyselections.minTPCNClPion = decay3bodyBuilderOpts.minTPCNClPion; + helper.decay3bodyselections.minTPCNClDeuteron = decay3bodyBuilderOpts.minTPCNClDeuteron; + helper.decay3bodyselections.minDCAProtonToPV = decay3bodyBuilderOpts.minDCAProtonToPV; + helper.decay3bodyselections.minDCAPionToPV = decay3bodyBuilderOpts.minDCAPionToPV; + helper.decay3bodyselections.minDCADeuteronToPV = decay3bodyBuilderOpts.minDCADeuteronToPV; + helper.decay3bodyselections.minPtProton = decay3bodyBuilderOpts.minPtProton; + helper.decay3bodyselections.minPtPion = decay3bodyBuilderOpts.minPtPion; + helper.decay3bodyselections.minPtDeuteron = decay3bodyBuilderOpts.minPtDeuteron; + helper.decay3bodyselections.maxPtProton = decay3bodyBuilderOpts.maxPtProton; + helper.decay3bodyselections.maxPtPion = decay3bodyBuilderOpts.maxPtPion; + helper.decay3bodyselections.maxPtDeuteron = decay3bodyBuilderOpts.maxPtDeuteron; + helper.decay3bodyselections.maxTPCnSigma = decay3bodyBuilderOpts.maxTPCnSigma; + helper.decay3bodyselections.minTOFnSigmaDeuteron = decay3bodyBuilderOpts.minTOFnSigmaDeuteron; + helper.decay3bodyselections.maxTOFnSigmaDeuteron = decay3bodyBuilderOpts.maxTOFnSigmaDeuteron; + helper.decay3bodyselections.minPDeuteronUseTOF = decay3bodyBuilderOpts.minPDeuteronUseTOF; + helper.decay3bodyselections.maxDCADauAtSV = decay3bodyBuilderOpts.maxDCADauAtSV; + helper.decay3bodyselections.maxRapidity = decay3bodyBuilderOpts.maxRapidity; + helper.decay3bodyselections.minPt = decay3bodyBuilderOpts.minPt; + helper.decay3bodyselections.maxPt = decay3bodyBuilderOpts.maxPt; + helper.decay3bodyselections.minMass = decay3bodyBuilderOpts.minMass; + helper.decay3bodyselections.maxMass = decay3bodyBuilderOpts.maxMass; + helper.decay3bodyselections.minCtau = decay3bodyBuilderOpts.minCtau; + helper.decay3bodyselections.maxCtau = decay3bodyBuilderOpts.maxCtau; + helper.decay3bodyselections.minCosPA = decay3bodyBuilderOpts.minCosPA; + helper.decay3bodyselections.maxChi2 = decay3bodyBuilderOpts.maxChi2; + + // set SVertexer selection parameters in the helper + helper.svertexerselections.minPt2V0 = mixingOpts.minPt2V0; + helper.svertexerselections.maxTgl2V0 = mixingOpts.maxTgl2V0; + helper.svertexerselections.maxDCAXY2ToMeanVertex3bodyV0 = mixingOpts.maxDCAXY2ToMeanVertex3bodyV0; + helper.svertexerselections.minCosPAXYMeanVertex3bodyV0 = mixingOpts.minCosPAXYMeanVertex3bodyV0; + helper.svertexerselections.minCosPA3bodyV0 = mixingOpts.minCosPA3bodyV0; + helper.svertexerselections.maxRDiffV03body = mixingOpts.maxRDiffV03body; + helper.svertexerselections.minPt3Body = mixingOpts.minPt3Body; + helper.svertexerselections.maxTgl3Body = mixingOpts.maxTgl3Body; + helper.svertexerselections.maxDCAXY3Body = mixingOpts.maxDCAXY3Body; + helper.svertexerselections.maxDCAZ3Body = mixingOpts.maxDCAZ3Body; + + // list enabled process functions + LOGF(info, "*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*"); + LOGF(info, " Decay3body builder: basic configuration listing"); + LOGF(info, "*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*"); + + if (doprocessRealData) { + LOGF(info, " ===> process function enabled: processRealData"); + } + if (doprocessRealDataReduced) { + LOGF(info, " ===> process function enabled: processRealDataReduced"); + } + if (doprocessRealDataReduced3bodyMixing) { + LOGF(info, " ===> process function enabled: processRealDataReduced3bodyMixing"); + } + if (doprocessMonteCarlo) { + LOGF(info, " ===> process function enabled: processMonteCarlo"); + } + + // list enabled tables + for (int i = 0; i < nTables; i++) { + if (mEnabledTables[i]) { + LOGF(info, " -~> Table enabled: %s", tableNames[i]); + } + } + + // print base cuts + LOGF(info, "*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*"); + LOGF(info, "-~> max daughter eta ..............: %f", decay3bodyBuilderOpts.maxEtaDaughters.value); + LOGF(info, "-~> min TPC ncls proton ...........: %i", decay3bodyBuilderOpts.minTPCNClProton.value); + LOGF(info, "-~> min TPC ncls pion .............: %i", decay3bodyBuilderOpts.minTPCNClPion.value); + LOGF(info, "-~> min TPC ncls bach .............: %i", decay3bodyBuilderOpts.minTPCNClDeuteron.value); + LOGF(info, "-~> min DCA proton to PV ..........: %f", decay3bodyBuilderOpts.minDCAProtonToPV.value); + LOGF(info, "-~> min DCA pion to PV ............: %f", decay3bodyBuilderOpts.minDCAPionToPV.value); + LOGF(info, "-~> min DCA bach to PV ............: %f", decay3bodyBuilderOpts.minDCADeuteronToPV.value); + LOGF(info, "-~> min pT proton .................: %f", decay3bodyBuilderOpts.minPtProton.value); + LOGF(info, "-~> min pT pion ...................: %f", decay3bodyBuilderOpts.minPtPion.value); + LOGF(info, "-~> min pT bach ...................: %f", decay3bodyBuilderOpts.minPtDeuteron.value); + LOGF(info, "-~> max pT proton .................: %f", decay3bodyBuilderOpts.maxPtProton.value); + LOGF(info, "-~> max pT pion ...................: %f", decay3bodyBuilderOpts.maxPtPion.value); + LOGF(info, "-~> max pT bach ...................: %f", decay3bodyBuilderOpts.maxPtDeuteron.value); + LOGF(info, "-~> max TPC nSigma ...............: %f", decay3bodyBuilderOpts.maxTPCnSigma.value); + LOGF(info, "-~> min TOF nSigma deuteron ......: %f", decay3bodyBuilderOpts.minTOFnSigmaDeuteron.value); + LOGF(info, "-~> max TOF nSigma deuteron ......: %f", decay3bodyBuilderOpts.maxTOFnSigmaDeuteron.value); + LOGF(info, "-~> min p bach use TOF ...........: %f", decay3bodyBuilderOpts.minPDeuteronUseTOF.value); + LOGF(info, "-~> max DCA dau at SV ............: %f", decay3bodyBuilderOpts.maxDCADauAtSV.value); + LOGF(info, "-~> max rapidity .................: %f", decay3bodyBuilderOpts.maxRapidity.value); + LOGF(info, "-~> min pT .......................: %f", decay3bodyBuilderOpts.minPt.value); + LOGF(info, "-~> max pT .......................: %f", decay3bodyBuilderOpts.maxPt.value); + LOGF(info, "-~> min mass .....................: %f", decay3bodyBuilderOpts.minMass.value); + LOGF(info, "-~> max mass .....................: %f", decay3bodyBuilderOpts.maxMass.value); + LOGF(info, "-~> min ctau .....................: %f", decay3bodyBuilderOpts.minCtau.value); + LOGF(info, "-~> max ctau .....................: %f", decay3bodyBuilderOpts.maxCtau.value); + LOGF(info, "-~> min cosPA ....................: %f", decay3bodyBuilderOpts.minCosPA.value); + LOGF(info, "-~> max chi2 .....................: %f", decay3bodyBuilderOpts.maxChi2.value); + LOGF(info, "*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*"); + + // bookkeeping histograms + auto h = registry.add("Counters/hTableBuildingStatistics", "hTableBuildingStatistics", kTH1D, {{nTablesConst, -0.5f, static_cast(nTablesConst)}}); + auto h2 = registry.add("Counters/hInputStatistics", "hInputStatistics", kTH1D, {{nTablesConst, -0.5f, static_cast(nTablesConst)}}); + h2->SetTitle("Input table sizes"); + + // configure tables to generate + for (int i = 0; i < nTables; i++) { + h->GetXaxis()->SetBinLabel(i + 1, tableNames[i].c_str()); + h2->GetXaxis()->SetBinLabel(i + 1, tableNames[i].c_str()); + h->SetBinContent(i + 1, 0); // mark all as disabled to start + + int f = enabledTables->get(tableNames[i].c_str(), "enable"); + if (f == 1) { + mEnabledTables[i] = 1; + h->SetBinContent(i + 1, 1); // mark enabled + } + } + + if (mEnabledTables[kVtx3BodyDatas] && mEnabledTables[kMcVtx3BodyDatas]) { + LOG(fatal) << "Tables Vtx3BodyDatas and McVtx3BodyDatas cannot both be enabled at the same time. Choose one!"; } - if (doprocessRun3Reduced3bodyMixing == true || doprocessRun3Reduced3bodyMixingKFInfo == true) { - registry.add("hDecay3BodyRadiusPhi", "hDecay3BodyRadiusPhi", HistType::kTH2F, {dcaFitterEMSel.bins3BodyRadius, dcaFitterEMSel.bins3BodyPhi}); - registry.add("hDecay3BodyPosZ", "hDecay3BodyPosZ", HistType::kTH1F, {dcaFitterEMSel.bins3BodyPosZ}); - auto h3bodyCombinationCounter = registry.add("h3bodyCombinationCounter", "h3bodyCombinationCounter", HistType::kTH1D, {{4, 0.0f, 4.0f}}); - h3bodyCombinationCounter->GetXaxis()->SetBinLabel(1, "total"); - h3bodyCombinationCounter->GetXaxis()->SetBinLabel(2, "bach sign/ID"); - h3bodyCombinationCounter->GetXaxis()->SetBinLabel(3, "not same collision"); - h3bodyCombinationCounter->GetXaxis()->SetBinLabel(4, "collision VtxZ"); - } - - if (doprocessRun3ReducedEM == true || doprocessRun3Reduced3bodyMixing == true || doprocessRun3Reduced3bodyMixingKFInfo == true) { - doUpdateGRPMagField = true; - registry.add("h3bodyEMCutCounter", "h3bodyEMCutCounter", HistType::kTH1D, {{14, 0.0f, 14.0f}}); - } - - if (doprocessRun3withKFParticle == true || doprocessRun3withKFParticleStrangenessTracking == true || doprocessRun3withKFParticleReduced == true || doprocessRun3withKFParticleReducedEM == true || doprocessRun3withKFParticleReduced3bodyMixing == true) { - auto hEventCounterZorro = registry.add("Counters/hEventCounterZorro", "hEventCounterZorro", HistType::kTH1D, {{2, -0.5, 1.5}}); - hEventCounterZorro->GetXaxis()->SetBinLabel(1, "Zorro before evsel"); - hEventCounterZorro->GetXaxis()->SetBinLabel(2, "Zorro after evsel"); - auto hEventCounterKFParticle = registry.add("Counters/hEventCounterKFParticle", "hEventCounterKFParticle", HistType::kTH1D, {{4, 0.0f, 4.0f}}); - hEventCounterKFParticle->GetXaxis()->SetBinLabel(1, "total"); - hEventCounterKFParticle->GetXaxis()->SetBinLabel(2, "sel8"); - hEventCounterKFParticle->GetXaxis()->SetBinLabel(3, "vertexZ"); - hEventCounterKFParticle->GetXaxis()->SetBinLabel(4, "has candidate"); - hEventCounterKFParticle->LabelsOption("v"); - auto hVtx3BodyCounterKFParticle = registry.add("Counters/hVtx3BodyCounterKFParticle", "hVtx3BodyCounterKFParticle", HistType::kTH1D, {{21, 0.0f, 21.0f}}); - hVtx3BodyCounterKFParticle->GetXaxis()->SetBinLabel(1, "Total"); - hVtx3BodyCounterKFParticle->GetXaxis()->SetBinLabel(2, "Charge"); - hVtx3BodyCounterKFParticle->GetXaxis()->SetBinLabel(3, "Eta"); - hVtx3BodyCounterKFParticle->GetXaxis()->SetBinLabel(4, "TPCNcls"); - hVtx3BodyCounterKFParticle->GetXaxis()->SetBinLabel(5, "TPCRows"); - hVtx3BodyCounterKFParticle->GetXaxis()->SetBinLabel(6, "TPCpid"); - hVtx3BodyCounterKFParticle->GetXaxis()->SetBinLabel(7, "DCAxyPV"); - hVtx3BodyCounterKFParticle->GetXaxis()->SetBinLabel(8, "DCAzPV"); - hVtx3BodyCounterKFParticle->GetXaxis()->SetBinLabel(9, "V0MassConst"); - hVtx3BodyCounterKFParticle->GetXaxis()->SetBinLabel(10, "HasSV"); - hVtx3BodyCounterKFParticle->GetXaxis()->SetBinLabel(11, "DcaDau"); - hVtx3BodyCounterKFParticle->GetXaxis()->SetBinLabel(12, "DCADauVtx"); - hVtx3BodyCounterKFParticle->GetXaxis()->SetBinLabel(13, "DauPt"); - hVtx3BodyCounterKFParticle->GetXaxis()->SetBinLabel(14, "Rapidity"); - hVtx3BodyCounterKFParticle->GetXaxis()->SetBinLabel(15, "Pt"); - hVtx3BodyCounterKFParticle->GetXaxis()->SetBinLabel(16, "Mass"); - hVtx3BodyCounterKFParticle->GetXaxis()->SetBinLabel(17, "CosPA"); - hVtx3BodyCounterKFParticle->GetXaxis()->SetBinLabel(18, "CosPAXY"); - hVtx3BodyCounterKFParticle->GetXaxis()->SetBinLabel(19, "Chi2geo"); - hVtx3BodyCounterKFParticle->GetXaxis()->SetBinLabel(20, "TopoConstr"); - hVtx3BodyCounterKFParticle->GetXaxis()->SetBinLabel(21, "Chi2topo"); - hVtx3BodyCounterKFParticle->LabelsOption("v"); - - registry.add("QA/Tracks/hTrackPosTPCNcls", "hTrackPosTPCNcls", HistType::kTH1F, {{152, 0, 152, "# TPC clusters"}}); - registry.add("QA/Tracks/hTrackNegTPCNcls", "hTrackNegTPCNcls", HistType::kTH1F, {{152, 0, 152, "# TPC clusters"}}); - registry.add("QA/Tracks/hTrackBachTPCNcls", "hTrackBachTPCNcls", HistType::kTH1F, {{152, 0, 152, "# TPC clusters"}}); - registry.add("QA/Tracks/hTrackPosHasTPC", "hTrackPosHasTPC", HistType::kTH1F, {{2, -0.5, 1.5, "has TPC"}}); - registry.add("QA/Tracks/hTrackNegHasTPC", "hTrackNegHasTPC", HistType::kTH1F, {{2, -0.5, 1.5, "has TPC"}}); - registry.add("QA/Tracks/hTrackBachHasTPC", "hTrackBachHasTPC", HistType::kTH1F, {{2, -0.5, 1.5, "has TPC"}}); - registry.add("QA/Tracks/hTrackBachITSClusSizes", "hTrackBachITSClusSizes", HistType::kTH1F, {{10, 0., 10., "ITS cluster sizes"}}); - registry.add("QA/Tracks/hTrackProtonTPCPID", "hTrackProtonTPCPID", HistType::kTH2F, {{100, -10.0f, 10.0f, "p/z (GeV/c)"}, {100, -10.0f, 10.0f, "TPC n#sigma"}}); - registry.add("QA/Tracks/hTrackPionTPCPID", "hTrackPionTPCPID", HistType::kTH2F, {{100, -10.0f, 10.0f, "p/z (GeV/c)"}, {100, -10.0f, 10.0f, "TPC n#sigma"}}); - registry.add("QA/Tracks/hTrackBachTPCPID", "hTrackBachTPCPID", HistType::kTH2F, {{100, -10.0f, 10.0f, "p/z (GeV/c)"}, {100, -10.0f, 10.0f, "TPC n#sigma"}}); - registry.add("QA/Tracks/hTrackProtonPt", "hTrackProtonPt", HistType::kTH1F, {{100, 0.0f, 10.0f, "#it{p}_{T} (GeV/c)"}}); - registry.add("QA/Tracks/hTrackPionPt", "hTrackPionPt", HistType::kTH1F, {{100, 0.0f, 10.0f, "#it{p}_{T} (GeV/c)"}}); - registry.add("QA/Tracks/hTrackBachPt", "hTrackBachPt", HistType::kTH1F, {{100, 0.0f, 10.0f, "#it{p}_{T} (GeV/c)"}}); - registry.add("QA/Event/hAllSelEventsVtxZ", "hAllSelEventsVtxZ", HistType::kTH1F, {{500, -15.0f, 15.0f, "PV Z (cm)"}}); - registry.add("QA/Event/hVtxXKF", "hVtxXKF", HistType::kTH1F, {{500, -0.1f, 0.1f, "PV X (cm)"}}); - registry.add("QA/Event/hVtxYKF", "hVtxYKF", HistType::kTH1F, {{500, -0.1f, 0.1f, "PV Y (cm)"}}); - registry.add("QA/Event/hVtxZKF", "hVtxZKF", HistType::kTH1F, {{500, -15.0f, 15.0f, "PV Z (cm)"}}); - registry.add("QA/Event/hVtxCovXXKF", "hVtxCovXXKF", HistType::kTH1F, {{200, -0.0001f, 0.0001f, "PV cov(XX) (cm^{2})"}}); - registry.add("QA/Event/hVtxCovYYKF", "hVtxCovYYKF", HistType::kTH1F, {{200, -0.0001f, 0.0001f, "PV cov(YY) (cm^{2})"}}); - registry.add("QA/Event/hVtxCovZZKF", "hVtxCovZZKF", HistType::kTH1F, {{200, -0.0001f, 0.0001f, "PV cov(ZZ) (cm^{2})"}}); - registry.add("QA/Event/hVtxCovXYKF", "hVtxCovXYKF", HistType::kTH1F, {{200, -0.0001f, 0.0001f, "PV cov(XY) (cm^{2})"}}); - registry.add("QA/Event/hVtxCovXZKF", "hVtxCovXZKF", HistType::kTH1F, {{200, -0.0001f, 0.0001f, "PV cov(XZ) (cm^{2})"}}); - registry.add("QA/Event/hVtxCovYZKF", "hVtxCovYZKF", HistType::kTH1F, {{200, -0.0001f, 0.0001f, "PV cov(YZ) (cm^{2})"}}); - registry.add("QA/Event/hVtxX", "hVtxX", HistType::kTH1F, {{500, -0.1f, 0.1f, "PV X (cm)"}}); - registry.add("QA/Event/hVtxY", "hVtxY", HistType::kTH1F, {{500, -0.1f, 0.1f, "PV Y (cm)"}}); - registry.add("QA/Event/hVtxZ", "hVtxZ", HistType::kTH1F, {{500, -15.0f, 15.0f, "PV Z (cm)"}}); - registry.add("QA/Event/hVtxCovXX", "hVtxCovXX", HistType::kTH1F, {{200, -0.0001f, 0.0001f, "PV cov(XX) (cm^{2})"}}); - registry.add("QA/Event/hVtxCovYY", "hVtxCovYY", HistType::kTH1F, {{200, -0.0001f, 0.0001f, "PV cov(YY) (cm^{2})"}}); - registry.add("QA/Event/hVtxCovZZ", "hVtxCovZZ", HistType::kTH1F, {{200, -0.0001f, 0.0001f, "PV cov(ZZ) (cm^{2})"}}); - registry.add("QA/Event/hVtxCovXY", "hVtxCovXY", HistType::kTH1F, {{200, -0.0001f, 0.0001f, "PV cov(XY) (cm^{2})"}}); - registry.add("QA/Event/hVtxCovXZ", "hVtxCovXZ", HistType::kTH1F, {{200, -0.0001f, 0.0001f, "PV cov(XZ) (cm^{2})"}}); - registry.add("QA/Event/hVtxCovYZ", "hVtxCovYZ", HistType::kTH1F, {{200, -0.0001f, 0.0001f, "PV cov(YZ) (cm^{2})"}}); - } - - if (doprocessRun3withKFParticleReducedEM == true) { - registry.add("QA/EM/hPairCounterMixing", "hPairCounterMixing", HistType::kTH1D, {{1, 0.0f, 1.0f}}); - auto hCombinationCounterMixing = registry.add("QA/EM/hCombinationCounterMixing", "hCombinationCounterMixing", HistType::kTH1D, {{3, 0.0f, 3.0f}}); - hCombinationCounterMixing->GetXaxis()->SetBinLabel(1, "total"); - hCombinationCounterMixing->GetXaxis()->SetBinLabel(2, "bach sign/ID"); - hCombinationCounterMixing->GetXaxis()->SetBinLabel(3, "radius, phi"); - hCombinationCounterMixing->LabelsOption("v"); - - registry.add("QA/EM/hEventBinCounts", "hEventBinCounts", HistType::kTH2D, {{10, 0, 10, "bins VtxZ"}, {13, 0, 13, "bins mult"}}); - registry.add("QA/EM/h3bodyBinCounts", "h3bodyBinCounts", HistType::kTH2D, {{10, 0, 10, "bins VtxZ"}, {13, 0, 13, "bins mult"}}); - registry.add("QA/EM/hPairBinCounts", "hPairBinCounts", HistType::kTH2D, {{10, 0, 10, "bins VtxZ"}, {13, 0, 13, "bins mult"}}); - - registry.add("QA/EM/hRadius1", "hRadius1", HistType::kTH1F, {{200, 0.0f, 20.0f, "Radius (cm)"}}); - registry.add("QA/EM/hRadius2", "hRadius2", HistType::kTH1F, {{200, 0.0f, 20.0f, "Radius (cm)"}}); - registry.add("QA/EM/hPhi1", "hPhi1", HistType::kTH1F, {{360, 0.0f, 360.0f, "#phi (degree)"}}); - registry.add("QA/EM/hPhi2", "hPhi2", HistType::kTH1F, {{360, 0.0f, 360.0f, "#phi (degree)"}}); - registry.add("QA/EM/hDeltaRadius", "hDeltaRadius", HistType::kTH1F, {{200, 0.0f, 10.0f, "#Delta Radius (cm)"}}); - registry.add("QA/EM/hDeltaPhi", "hDeltaPhi", HistType::kTH1F, {{360, 0.0f, 360.0f, "#Delta #phi (degree)"}}); - } - - if (doprocessRun3withKFParticleReduced3bodyMixing == true) { - auto h3bodyCombinationCounter = registry.add("QA/EM/h3bodyCombinationCounter", "h3bodyCombinationCounter", HistType::kTH1D, {{4, 0.0f, 4.0f}}); + // Add histograms separately for different process functions + if (doprocessRealData == true || doprocessMonteCarlo == true) { + auto hEventCounter = registry.add("Counters/hEventCounter", "hEventCounter", HistType::kTH1D, {{3, 0.0f, 3.0f}}); + hEventCounter->GetXaxis()->SetBinLabel(1, "total"); + hEventCounter->GetXaxis()->SetBinLabel(2, "sel8"); + hEventCounter->GetXaxis()->SetBinLabel(3, "vertexZ"); + hEventCounter->LabelsOption("v"); + } + + if (doprocessRealData == true || doprocessRealDataReduced == true || doprocessMonteCarlo == true) { + if (doTrackQA) { // histograms for all daughter tracks of (selected) 3body candidates + registry.add("QA/Tracks/hTrackProtonTPCNcls", "hTrackProtonTPCNcls", HistType::kTH1F, {{152, 0, 152, "# TPC clusters"}}); + registry.add("QA/Tracks/hTrackPionTPCNcls", "hTrackPionTPCNcls", HistType::kTH1F, {{152, 0, 152, "# TPC clusters"}}); + registry.add("QA/Tracks/hTrackDeuteronTPCNcls", "hTrackDeuteronTPCNcls", HistType::kTH1F, {{152, 0, 152, "# TPC clusters"}}); + registry.add("QA/Tracks/hTrackProtonHasTPC", "hTrackProtonHasTPC", HistType::kTH1F, {{2, -0.5, 1.5, "has TPC"}}); + registry.add("QA/Tracks/hTrackPionHasTPC", "hTrackPionHasTPC", HistType::kTH1F, {{2, -0.5, 1.5, "has TPC"}}); + registry.add("QA/Tracks/hTrackDeuteronHasTPC", "hTrackDeuteronHasTPC", HistType::kTH1F, {{2, -0.5, 1.5, "has TPC"}}); + registry.add("QA/Tracks/hTrackDeuteronITSClusSizes", "hTrackDeuteronITSClusSizes", HistType::kTH1F, {{10, 0., 10., "ITS cluster sizes"}}); + registry.add("QA/Tracks/hTrackProtonTPCPID", "hTrackProtonTPCPID", HistType::kTH2F, {{100, -10.0f, 10.0f, "p/z (GeV/c)"}, {100, -10.0f, 10.0f, "TPC n#sigma"}}); + registry.add("QA/Tracks/hTrackPionTPCPID", "hTrackPionTPCPID", HistType::kTH2F, {{100, -10.0f, 10.0f, "p/z (GeV/c)"}, {100, -10.0f, 10.0f, "TPC n#sigma"}}); + registry.add("QA/Tracks/hTrackDeuteronTPCPID", "hTrackDeuteronTPCPID", HistType::kTH2F, {{100, -10.0f, 10.0f, "p/z (GeV/c)"}, {100, -10.0f, 10.0f, "TPC n#sigma"}}); + registry.add("QA/Tracks/hTrackProtonPt", "hTrackProtonPt", HistType::kTH1F, {{100, 0.0f, 10.0f, "#it{p}_{T} (GeV/c)"}}); + registry.add("QA/Tracks/hTrackPionPt", "hTrackPionPt", HistType::kTH1F, {{100, 0.0f, 10.0f, "#it{p}_{T} (GeV/c)"}}); + registry.add("QA/Tracks/hTrackDeuteronPt", "hTrackDeuteronPt", HistType::kTH1F, {{100, 0.0f, 10.0f, "#it{p}_{T} (GeV/c)"}}); + } + if (doVertexQA) { + registry.add("QA/Event/hAllSelEventsVtxZ", "hAllSelEventsVtxZ", HistType::kTH1F, {{500, -15.0f, 15.0f, "PV Z (cm)"}}); + registry.add("QA/Event/hVtxX", "hVtxX", HistType::kTH1F, {{500, -0.1f, 0.1f, "PV X (cm)"}}); + registry.add("QA/Event/hVtxY", "hVtxY", HistType::kTH1F, {{500, -0.1f, 0.1f, "PV Y (cm)"}}); + registry.add("QA/Event/hVtxZ", "hVtxZ", HistType::kTH1F, {{500, -15.0f, 15.0f, "PV Z (cm)"}}); + registry.add("QA/Event/hVtxCovXX", "hVtxCovXX", HistType::kTH1F, {{200, -0.0001f, 0.0001f, "PV cov(XX) (cm^{2})"}}); + registry.add("QA/Event/hVtxCovYY", "hVtxCovYY", HistType::kTH1F, {{200, -0.0001f, 0.0001f, "PV cov(YY) (cm^{2})"}}); + registry.add("QA/Event/hVtxCovZZ", "hVtxCovZZ", HistType::kTH1F, {{200, -0.0001f, 0.0001f, "PV cov(ZZ) (cm^{2})"}}); + registry.add("QA/Event/hVtxCovXY", "hVtxCovXY", HistType::kTH1F, {{200, -0.0001f, 0.0001f, "PV cov(XY) (cm^{2})"}}); + registry.add("QA/Event/hVtxCovXZ", "hVtxCovXZ", HistType::kTH1F, {{200, -0.0001f, 0.0001f, "PV cov(XZ) (cm^{2})"}}); + registry.add("QA/Event/hVtxCovYZ", "hVtxCovYZ", HistType::kTH1F, {{200, -0.0001f, 0.0001f, "PV cov(YZ) (cm^{2})"}}); + } + } + + if (doprocessRealDataReduced3bodyMixing == true) { + auto h3bodyCombinationCounter = registry.add("Mixing/h3bodyCombinationCounter", "h3bodyCombinationCounter", HistType::kTH1D, {{4, 0.0f, 4.0f}}); h3bodyCombinationCounter->GetXaxis()->SetBinLabel(1, "total"); h3bodyCombinationCounter->GetXaxis()->SetBinLabel(2, "not same collision"); h3bodyCombinationCounter->GetXaxis()->SetBinLabel(3, "collision VtxZ"); h3bodyCombinationCounter->GetXaxis()->SetBinLabel(4, "bach sign/ID"); h3bodyCombinationCounter->LabelsOption("v"); - // registry.add("QA/EM/h3bodyBinCounts", "h3bodyBinCounts", HistType::kTH3D, {{16, 0, 16, "bins radius"}, {36, 0, 36, "bins phi"}, {12, 0, 12, "bins pos Z"}}); - registry.add("QA/EM/h3bodyBinCounts", "h3bodyBinCounts", HistType::kTH2D, {{16, 0, 16, "bins radius"}, {18, 0, 18, "bins phi"}}); - - AxisSpec radiusAxis = {kfparticleConfigurations.bins3BodyRadius, "Radius (cm)"}; - AxisSpec phiAxis = {kfparticleConfigurations.bins3BodyPhi, "#phi (degree)"}; - AxisSpec posZAxis = {kfparticleConfigurations.bins3BodyPosZ, "position in z (cm)"}; - - registry.add("QA/EM/hRadius", "hRadius", HistType::kTH1F, {radiusAxis}); - registry.add("QA/EM/hPhi", "hPhi", HistType::kTH1F, {phiAxis}); - registry.add("QA/EM/hPosZ", "hPosZ", HistType::kTH1F, {posZAxis}); + registry.add("Mixing/hDecay3BodyRadiusPhi", "hDecay3BodyRadiusPhi", HistType::kTH2F, {mixingOpts.bins3BodyRadius, mixingOpts.bins3BodyPhi}); + registry.add("Mixing/hDecay3BodyPosZ", "hDecay3BodyPosZ", HistType::kTH1F, {mixingOpts.bins3BodyPosZ}); } } - void initCCDB(aod::BCsWithTimestamps::iterator const& bc) + template + bool initCCDB(aod::BCsWithTimestamps const& bcs, TCollisions const& collisions) { - if (mRunNumber == bc.runNumber()) { - return; + 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 } - if (kfparticleConfigurations.cfgSkimmedProcessing) { - zorro.initCCDB(ccdb.service, bc.runNumber(), bc.timestamp(), kfparticleConfigurations.triggerList); - zorro.populateHistRegistry(registry, bc.runNumber()); + + if (mRunNumber == bc.runNumber()) { + return true; } - // In case override, don't proceed, please - no CCDB access required - if (d_bz_input > -990) { - d_bz = d_bz_input; - fitterV0.setBz(d_bz); - fitter3body.setBz(d_bz); -#ifdef HomogeneousField - KFParticle::SetField(d_bz); -#endif - o2::parameters::GRPMagField grpmag; - if (std::fabs(d_bz) > 1e-5) { - grpmag.setL3Current(30000.f / (d_bz / 5.0f)); - } - o2::base::Propagator::initFieldFromGRP(&grpmag); - mRunNumber = bc.runNumber(); - return; + if (doSkimmedProcessing) { + zorro.initCCDB(ccdb.service, bc.runNumber(), bc.timestamp(), triggerList); + zorro.populateHistRegistry(registry, bc.runNumber()); } - auto run3grp_timestamp = bc.timestamp(); - o2::parameters::GRPObject* grpo = ccdb->getForTimeStamp(grpPath, run3grp_timestamp); + auto timestamp = bc.timestamp(); o2::parameters::GRPMagField* grpmag = 0x0; - if (grpo) { - o2::base::Propagator::initFieldFromGRP(grpo); - // 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(grpmagPath, run3grp_timestamp); - if (!grpmag) { - LOG(fatal) << "Got nullptr from CCDB for path " << grpmagPath << " of object GRPMagField and " << grpPath << " of object GRPObject for timestamp " << run3grp_timestamp; - } - o2::base::Propagator::initFieldFromGRP(grpmag); - // Fetch magnetic field from ccdb for current collision - // d_bz = std::lround(5.f * grpmag->getL3Current() / 30000.f); - d_bz = o2::base::Propagator::Instance()->getNominalBz(); - LOG(info) << "Retrieved GRP for timestamp " << run3grp_timestamp << " with magnetic field of " << d_bz << " kZG"; - } - mRunNumber = bc.runNumber(); - // Set magnetic field value once known - fitterV0.setBz(d_bz); - fitter3body.setBz(d_bz); + grpmag = ccdb->getForTimeStamp(ccdbConfigurations.grpmagPath, timestamp); + if (!grpmag) { + LOG(fatal) << "Got nullptr from CCDB for path " << ccdbConfigurations.grpmagPath << " of object GRPMagField for timestamp " << timestamp; + } + o2::base::Propagator::initFieldFromGRP(grpmag); + // Fetch magnetic field from ccdb for current collision + auto d_bz = o2::base::Propagator::Instance()->getNominalBz(); + LOG(info) << "Retrieved GRP for timestamp " << timestamp << " with magnetic field of " << d_bz << " kG"; + + // set magnetic field value for DCA fitter + helper.fitterV0.setBz(d_bz); + helper.fitter3body.setBz(d_bz); // Set magnetic field for KF vertexing #ifdef HomogeneousField KFParticle::SetField(d_bz); @@ -657,1853 +513,849 @@ struct decay3bodyBuilder { if (useMatCorrType == 2) { // setMatLUT only after magfield has been initalized // (setMatLUT has implicit and problematic init field call if not) + LOG(info) << "Loading material look-up table for timestamp: " << timestamp; + lut = o2::base::MatLayerCylSet::rectifyPtrFromFile(ccdb->getForTimeStamp(ccdbConfigurations.lutPath, timestamp)); o2::base::Propagator::Instance()->setMatLUT(lut); } + // mark run as configured + mRunNumber = bc.runNumber(); + // Initial TOF PID Paras, copied from PIDTOF.h - timestamp.value = bc.timestamp(); - ccdb->setTimestamp(timestamp.value); + tofPIDOpts.timestamp.value = bc.timestamp(); + ccdb->setTimestamp(tofPIDOpts.timestamp.value); // Not later than now objects ccdb->setCreatedNotAfter(std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count()); // TODO: implement the automatic pass name detection from metadata - if (passName.value == "") { - passName.value = "unanchored"; // temporary default - LOG(warning) << "Passed autodetect mode for pass, not implemented yet, waiting for metadata. Taking '" << passName.value << "'"; + if (tofPIDOpts.passName.value == "") { + tofPIDOpts.passName.value = "unanchored"; // temporary default + LOG(warning) << "Passed autodetect mode for pass, not implemented yet, waiting for metadata. Taking '" << tofPIDOpts.passName.value << "'"; } - LOG(info) << "Using parameter collection, starting from pass '" << passName.value << "'"; + LOG(info) << "Using parameter collection, starting from pass '" << tofPIDOpts.passName.value << "'"; - const std::string fname = paramFileName.value; + const std::string fname = tofPIDOpts.paramFileName.value; if (!fname.empty()) { // Loading the parametrization from file - LOG(info) << "Loading exp. sigma parametrization from file " << fname << ", using param: " << parametrizationPath.value; + LOG(info) << "Loading exp. sigma parametrization from file " << fname << ", using param: " << tofPIDOpts.parametrizationPath.value; if (1) { o2::tof::ParameterCollection paramCollection; - paramCollection.loadParamFromFile(fname, parametrizationPath.value); + paramCollection.loadParamFromFile(fname, tofPIDOpts.parametrizationPath.value); LOG(info) << "+++ Loaded parameter collection from file +++"; - if (!paramCollection.retrieveParameters(mRespParamsV2, passName.value)) { - if (fatalOnPassNotAvailable) { - LOGF(fatal, "Pass '%s' not available in the retrieved CCDB object", passName.value.data()); + if (!paramCollection.retrieveParameters(mRespParamsV2, tofPIDOpts.passName.value)) { + if (tofPIDOpts.fatalOnPassNotAvailable) { + LOGF(fatal, "Pass '%s' not available in the retrieved CCDB object", tofPIDOpts.passName.value.data()); } else { - LOGF(warning, "Pass '%s' not available in the retrieved CCDB object", passName.value.data()); + LOGF(warning, "Pass '%s' not available in the retrieved CCDB object", tofPIDOpts.passName.value.data()); } } else { - mRespParamsV2.setShiftParameters(paramCollection.getPars(passName.value)); + mRespParamsV2.setShiftParameters(paramCollection.getPars(tofPIDOpts.passName.value)); mRespParamsV2.printShiftParameters(); } } else { - mRespParamsV2.loadParamFromFile(fname.data(), parametrizationPath.value); + mRespParamsV2.loadParamFromFile(fname.data(), tofPIDOpts.parametrizationPath.value); } - } else if (loadResponseFromCCDB) { // Loading it from CCDB - LOG(info) << "Loading exp. sigma parametrization from CCDB, using path: " << parametrizationPath.value << " for timestamp " << timestamp.value; - o2::tof::ParameterCollection* paramCollection = ccdb->getForTimeStamp(parametrizationPath.value, timestamp.value); + } else if (tofPIDOpts.loadResponseFromCCDB) { // Loading it from CCDB + LOG(info) << "Loading exp. sigma parametrization from CCDB, using path: " << tofPIDOpts.parametrizationPath.value << " for timestamp " << tofPIDOpts.timestamp.value; + o2::tof::ParameterCollection* paramCollection = ccdb->getForTimeStamp(tofPIDOpts.parametrizationPath.value, tofPIDOpts.timestamp.value); paramCollection->print(); - if (!paramCollection->retrieveParameters(mRespParamsV2, passName.value)) { // Attempt at loading the parameters with the pass defined - if (fatalOnPassNotAvailable) { - LOGF(fatal, "Pass '%s' not available in the retrieved CCDB object", passName.value.data()); + if (!paramCollection->retrieveParameters(mRespParamsV2, tofPIDOpts.passName.value)) { // Attempt at loading the parameters with the pass defined + if (tofPIDOpts.fatalOnPassNotAvailable) { + LOGF(fatal, "Pass '%s' not available in the retrieved CCDB object", tofPIDOpts.passName.value.data()); } else { - LOGF(warning, "Pass '%s' not available in the retrieved CCDB object", passName.value.data()); + LOGF(warning, "Pass '%s' not available in the retrieved CCDB object", tofPIDOpts.passName.value.data()); } } else { // Pass is available, load non standard parameters - mRespParamsV2.setShiftParameters(paramCollection->getPars(passName.value)); + mRespParamsV2.setShiftParameters(paramCollection->getPars(tofPIDOpts.passName.value)); mRespParamsV2.printShiftParameters(); } } mRespParamsV2.print(); - if (timeShiftCCDBPath.value != "") { - if (timeShiftCCDBPath.value.find(".root") != std::string::npos) { - mRespParamsV2.setTimeShiftParameters(timeShiftCCDBPath.value, "gmean_Pos", true); - mRespParamsV2.setTimeShiftParameters(timeShiftCCDBPath.value, "gmean_Neg", false); + if (tofPIDOpts.timeShiftCCDBPath.value != "") { + if (tofPIDOpts.timeShiftCCDBPath.value.find(".root") != std::string::npos) { + mRespParamsV2.setTimeShiftParameters(tofPIDOpts.timeShiftCCDBPath.value, "gmean_Pos", true); + mRespParamsV2.setTimeShiftParameters(tofPIDOpts.timeShiftCCDBPath.value, "gmean_Neg", false); } else { - mRespParamsV2.setTimeShiftParameters(ccdb->getForTimeStamp(Form("%s/pos", timeShiftCCDBPath.value.c_str()), timestamp.value), true); - mRespParamsV2.setTimeShiftParameters(ccdb->getForTimeStamp(Form("%s/neg", timeShiftCCDBPath.value.c_str()), timestamp.value), false); + mRespParamsV2.setTimeShiftParameters(ccdb->getForTimeStamp(Form("%s/pos", tofPIDOpts.timeShiftCCDBPath.value.c_str()), tofPIDOpts.timestamp.value), true); + mRespParamsV2.setTimeShiftParameters(ccdb->getForTimeStamp(Form("%s/neg", tofPIDOpts.timeShiftCCDBPath.value.c_str()), tofPIDOpts.timestamp.value), false); } } bachelorTOFPID.SetParams(mRespParamsV2); + bachelorTOFPIDLabeled.SetParams(mRespParamsV2); + + return true; } - void initCCDBfromRunNumber(int runNumber) + float getMagFieldFromRunNumber(int runNumber) { - // set magnetic field only when run number changes - if (mRunNumber == runNumber) { - LOG(debug) << "CCDB initialized for run " << mRunNumber; - return; - } - mRunNumber = runNumber; // Update the last run number - + float magField; // Check if the CCDB data for this run is already cached if (ccdbCache.find(runNumber) != ccdbCache.end()) { LOG(debug) << "CCDB data already cached for run " << runNumber; - d_bz = ccdbCache[runNumber]; - if (doUpdateGRPMagField == true) { - o2::base::Propagator::initFieldFromGRP(grpMagCache[runNumber].get()); - } + magField = ccdbCache[runNumber]; + // if not, retrieve it from CCDB } else { - std::shared_ptr grpmag = std::make_shared(*ccdb->getForRun(grpmagPath, runNumber)); + std::shared_ptr grpmag = std::make_shared(*ccdb->getForRun(ccdbConfigurations.grpmagPath, runNumber)); if (!grpmag) { - LOG(fatal) << "Got nullptr from CCDB for path " << grpmagPath << " of object GRPMagField and " << grpPath << " of object GRPObject for run number " << runNumber; + LOG(fatal) << "Got nullptr from CCDB for path " << ccdbConfigurations.grpmagPath << " of object GRPMagField and " << ccdbConfigurations.grpPath << " of object GRPObject for run number " << runNumber; } o2::base::Propagator::initFieldFromGRP(grpmag.get()); // Fetch magnetic field from ccdb for current collision - d_bz = o2::base::Propagator::Instance()->getNominalBz(); + magField = o2::base::Propagator::Instance()->getNominalBz(); LOG(info) << "Retrieved GRP for run number " << runNumber << " with magnetic field of " << d_bz << " kZG"; - ccdbCache[runNumber] = d_bz; - grpMagCache[runNumber] = grpmag; + // cache magnetic field info + ccdbCache[runNumber] = magField; + } + return magField; + } + + void initFittersWithMagField(int runNumber, float magField) + { + // set magnetic field only when run number changes + if (mRunNumber == runNumber) { + LOG(debug) << "CCDB initialized for run " << mRunNumber; + return; } + mRunNumber = runNumber; // Update the last run number + + // update propagator + o2::base::Propagator::Instance()->setNominalBz(magField); // Set magnetic field for KF vertexing #ifdef HomogeneousField - KFParticle::SetField(d_bz); + KFParticle::SetField(magField); #endif // Set field for DCAfitter - fitterV0.setBz(d_bz); - fitter3body.setBz(d_bz); - - mV0Hyps[0].set(o2::track::PID::Lambda, o2::track::PID::Proton, o2::track::PID::Pion, pidCutsLambda, d_bz); - mV0Hyps[1].set(o2::track::PID::Lambda, o2::track::PID::Pion, o2::track::PID::Proton, pidCutsLambda, d_bz); + helper.fitterV0.setBz(magField); + helper.fitter3body.setBz(magField); if (useMatCorrType == 2) { - // setMatLUT only after magfield has been initalized + // setMatLUT only after magfield has been initalized (setMatLUT has implicit and problematic init field call if not) o2::base::Propagator::Instance()->setMatLUT(lut); } - - // cache magnetic field info - ccdbCache[runNumber] = d_bz; } - //------------------------------------------------------------------ - //-------------------- DCA fitter reconstruction ------------------- - //------------------------------------------------------------------ - // Select decay3body candidate based on daughter track PID - template - bool checkPID(TTrack const& trackProton, TTrack const& trackPion, TTrack const& trackBachelor, const double& tofNSigmaBach) - { - if ((tofNSigmaBach < TofPidNsigmaMin || tofNSigmaBach > TofPidNsigmaMax) && trackBachelor.p() > minBachPUseTOF) { - return false; - } - if (std::abs(trackProton.tpcNSigmaPr()) > TpcPidNsigmaCut) { - return false; - } - if (std::abs(trackPion.tpcNSigmaPi()) > TpcPidNsigmaCut) { - return false; - } - return true; - } - // PID check for H3L - template - bool checkPIDH3L(TTrack const& trackProton, TTrack const& trackPion, TTrack const& trackBachelor, const double& tofNSigmaBach) + // ______________________________________________________________ + // function to build decay3body candidates + template + void buildCandidates(TBCs const&, + TCollisions const& collisions, + T3Bodys const& decay3bodys, + TMCParticles const& mcParticles, + TMCCollisions const& mcCollisions) { - if ((std::abs(trackBachelor.tpcNSigmaDe()) > TpcPidNsigmaCut) || !checkPID(trackProton, trackPion, trackBachelor, tofNSigmaBach)) { - return false; + if (!(mEnabledTables[kVtx3BodyDatas] || mEnabledTables[kMcVtx3BodyDatas])) { + LOG(info) << "No request for candidate analysis table in place, skipping candidate building." << std::endl; + return; // don't do if no request for decay3bodys in place } - return true; - } - //------------------------------------------------------------------ - // 3body candidate builder - template - void fillVtxCand(TCollisionTable const& collision, TTrackTable const& t0, TTrackTable const& t1, TTrackTable const& t2, int64_t decay3bodyId, int bachelorcharge = 1, double tofNSigmaBach = -999, bool saveInTable = true) - { - registry.fill(HIST("hVtx3BodyCounter"), kVtxAll); + // prepare MC container (not necessarily used) + std::vector mcParticleIsReco; - if (t0.tpcNClsFound() < mintpcNCls || t1.tpcNClsFound() < mintpcNCls || t2.tpcNClsFound() < mintpcNCls) { - return; + // clear and reserve size for MC info vectors + if constexpr (soa::is_table) { + isGoodCollision.resize(mcCollisions.size(), false); + mcParticleIsReco.resize(mcParticles.size(), false); } - registry.fill(HIST("hVtx3BodyCounter"), kVtxTPCNcls); - if (enablePidCut) { - if (t2.sign() > 0) { - if (!checkPIDH3L(t0, t1, t2, tofNSigmaBach)) - return; - } else { - if (!checkPIDH3L(t1, t0, t2, tofNSigmaBach)) - return; - } - } + // Loop over collisions for vertex QA + for (const auto& collision : collisions) { + if constexpr (soa::is_table) { // only do if NOT running over reduced data (already done in reducedCreator) + // Zorro event counting + bool isZorroSelected = false; + if (doSkimmedProcessing) { + isZorroSelected = zorro.isSelected(collision.template bc_as().globalBC()); + if (!isZorroSelected && onlyKeepInterestedTrigger) { + continue; + } + } - registry.fill(HIST("hVtx3BodyCounter"), kVtxPIDCut); + // event counting + registry.fill(HIST("Counters/hEventCounter"), 0.5); + if (doSel8selection && !collision.sel8()) { + continue; + } + registry.fill(HIST("Counters/hEventCounter"), 1.5); + if (doPosZselection && (collision.posZ() >= 10.0f || collision.posZ() <= -10.0f)) { + continue; + } + registry.fill(HIST("Counters/hEventCounter"), 2.5); + } + + // vertex QA and counting + if (doVertexQA) { + registry.fill(HIST("QA/Event/hAllSelEventsVtxZ"), collision.posZ()); + registry.fill(HIST("QA/Event/hVtxX"), collision.posX()); + registry.fill(HIST("QA/Event/hVtxY"), collision.posY()); + registry.fill(HIST("QA/Event/hVtxZ"), collision.posZ()); + registry.fill(HIST("QA/Event/hVtxCovXX"), collision.covXX()); + registry.fill(HIST("QA/Event/hVtxCovYY"), collision.covYY()); + registry.fill(HIST("QA/Event/hVtxCovZZ"), collision.covZZ()); + registry.fill(HIST("QA/Event/hVtxCovXY"), collision.covXY()); + registry.fill(HIST("QA/Event/hVtxCovXZ"), collision.covXZ()); + registry.fill(HIST("QA/Event/hVtxCovYZ"), collision.covYZ()); + } + + // In case of MC: reco collision survived event selection filter --> fill value for MC collision if collision is "true" MC collision + if constexpr (soa::is_table) { + if (collision.mcCollisionId() >= 0) { + isGoodCollision[collision.mcCollisionId()] = true; + } + } + } // loop over collisions - // Calculate DCA with respect to the collision associated to the V0, not individual tracks - std::array dcaInfo; + // Loop over all decay3bodys in same time frame + registry.fill(HIST("Counters/hInputStatistics"), kVtx3BodyDatas, decay3bodys.size()); + int lastRunNumber = -1; + for (const auto& decay3body : decay3bodys) { + // skip decay3body without assigned collision + /// TODO: do we want this?? + if (decay3body.collisionId() < 0) { + return; + } - auto Track0Par = getTrackPar(t0); - o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, Track0Par, 2.f, fitter3body.getMatCorrType(), &dcaInfo); - auto Track0dcaXY = dcaInfo[0]; - auto Track0dca = std::sqrt(Track0dcaXY * Track0dcaXY + dcaInfo[1] * dcaInfo[1]); + // aquire collision + auto const& collision = collisions.rawIteratorAt(decay3body.collisionId()); - auto Track1Par = getTrackPar(t1); - o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, Track1Par, 2.f, fitter3body.getMatCorrType(), &dcaInfo); - auto Track1dcaXY = dcaInfo[0]; - auto Track1dca = std::sqrt(Track1dcaXY * Track1dcaXY + dcaInfo[1] * dcaInfo[1]); + // initialise CCDB from run number saved in reduced collisions table when running over reduced data + if constexpr (!soa::is_table) { // only do if running over reduced data (otherwise CCDB is initialised in process function) + if (collision.runNumber() != lastRunNumber) { + initFittersWithMagField(collision.runNumber(), getMagFieldFromRunNumber(collision.runNumber())); + lastRunNumber = collision.runNumber(); // Update the last run number + LOG(debug) << "CCDB initialized for run " << lastRunNumber; + } + } - auto Track2Par = getTrackPar(t2); - o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, Track2Par, 2.f, fitter3body.getMatCorrType(), &dcaInfo); - auto Track2dcaXY = dcaInfo[0]; - auto Track2dca = std::sqrt(Track2dcaXY * Track2dcaXY + dcaInfo[1] * dcaInfo[1]); + // event selection + if constexpr (soa::is_table) { + if (doSel8selection && !collision.sel8()) { // only when NOT running over reduced data + continue; + } + } + if (doPosZselection && (collision.posZ() >= 10.0f || collision.posZ() <= -10.0f)) { + continue; + } - auto Track0 = getTrackParCov(t0); - auto Track1 = getTrackParCov(t1); - auto Track2 = getTrackParCov(t2); - int n3bodyVtx = fitter3body.process(Track0, Track1, Track2); - if (n3bodyVtx == 0) { // discard this pair - return; - } - registry.fill(HIST("hVtx3BodyCounter"), kVtxhasSV); + // aquire tracks + auto trackPos = decay3body.template track0_as(); + auto trackNeg = decay3body.template track1_as(); + auto trackDeuteron = decay3body.template track2_as(); + auto trackProton = trackPos; + auto trackPion = trackNeg; + if (trackDeuteron.sign() < 0) { + trackProton = trackNeg; + trackPion = trackPos; + } + + // get deuteron TOF PID + float tofNSigmaDeuteron; + if constexpr (!soa::is_table) { // running over derived data + tofNSigmaDeuteron = trackDeuteron.tofNSigmaDe(); + } else if constexpr (soa::is_table) { // running over AO2Ds + if constexpr (soa::is_table) { // running over MC (track table with labels) + tofNSigmaDeuteron = getTOFnSigma(collision, trackDeuteron); + } else { // running over real data + tofNSigmaDeuteron = getTOFnSigma(collision, trackDeuteron); + } + } - std::array pos = {0.}; - const auto& vtxXYZ = fitter3body.getPCACandidate(); - for (int i = 0; i < 3; i++) { - pos[i] = vtxXYZ[i]; - } + /// build Decay3body candidate + if (!helper.buildDecay3BodyCandidate(collision, + trackProton, + trackPion, + trackDeuteron, + decay3body.globalIndex(), + tofNSigmaDeuteron, + fTrackedClSizeVector[decay3body.globalIndex()], + decay3bodyBuilderOpts.useKFParticle, + decay3bodyBuilderOpts.kfSetTopologicalConstraint, + decay3bodyBuilderOpts.useSelections, + decay3bodyBuilderOpts.useTPCforPion, + decay3bodyBuilderOpts.acceptTPCOnly, + decay3bodyBuilderOpts.calculateCovariance, + false /*isEventMixing*/)) { + continue; + } - std::array p0 = {0.}, p1 = {0.}, p2{0.}; - const auto& propagatedTrack0 = fitter3body.getTrack(0); - const auto& propagatedTrack1 = fitter3body.getTrack(1); - const auto& propagatedTrack2 = fitter3body.getTrack(2); - propagatedTrack0.getPxPyPzGlo(p0); - propagatedTrack1.getPxPyPzGlo(p1); - propagatedTrack2.getPxPyPzGlo(p2); - for (int i = 0; i < 3; i++) { - p2[i] *= bachelorcharge; - } - std::array p3B = {p0[0] + p1[0] + p2[0], p0[1] + p1[1] + p2[1], p0[2] + p1[2] + p2[2]}; + // fill QA histograms + if (doTrackQA) { // histograms filled for daughter tracks of (selected) 3body candidates + registry.fill(HIST("QA/Tracks/hTrackProtonTPCNcls"), trackProton.tpcNClsFound()); + registry.fill(HIST("QA/Tracks/hTrackPionTPCNcls"), trackPion.tpcNClsFound()); + registry.fill(HIST("QA/Tracks/hTrackDeuteronTPCNcls"), trackDeuteron.tpcNClsFound()); + registry.fill(HIST("QA/Tracks/hTrackProtonHasTPC"), trackProton.hasTPC()); + registry.fill(HIST("QA/Tracks/hTrackPionHasTPC"), trackPion.hasTPC()); + registry.fill(HIST("QA/Tracks/hTrackDeuteronHasTPC"), trackDeuteron.hasTPC()); + registry.fill(HIST("QA/Tracks/hTrackDeuteronITSClusSizes"), trackDeuteron.itsClusterSizes()); + registry.fill(HIST("QA/Tracks/hTrackProtonTPCPID"), trackProton.sign() * trackProton.tpcInnerParam(), trackProton.tpcNSigmaPr()); + registry.fill(HIST("QA/Tracks/hTrackPionTPCPID"), trackPion.sign() * trackPion.tpcInnerParam(), trackPion.tpcNSigmaPi()); + registry.fill(HIST("QA/Tracks/hTrackDeuteronTPCPID"), trackDeuteron.sign() * trackDeuteron.tpcInnerParam(), trackDeuteron.tpcNSigmaDe()); + registry.fill(HIST("QA/Tracks/hTrackProtonPt"), trackProton.pt()); + registry.fill(HIST("QA/Tracks/hTrackPionPt"), trackPion.pt()); + registry.fill(HIST("QA/Tracks/hTrackDeuteronPt"), trackDeuteron.pt()); + } + + // generate analysis tables with current candidate (only Vtx3BodyDatas is filled here, McVtx3BodyDatas table is filled later) + if (!mEnabledTables[kMcVtx3BodyDatas]) { + fillAnalysisTables(); + } + + // ___________________________________________________________ + // MC handling part: matching of reconstructed candidates + // ___________________________________________________________ + // fill MC table with reco MC candidate information and gen information if matched to MC particle + if constexpr (soa::is_table) { + // MC info + resetMCInfo(this3BodyMCInfo); + this3BodyMCInfo.isReco = true; + + // check if daughters have MC particle + if (!trackProton.has_mcParticle() || !trackPion.has_mcParticle() || !trackDeuteron.has_mcParticle()) { + continue; + } - if (fitter3body.getChi2AtPCACandidate() > dcavtxdau) { - return; - } - registry.fill(HIST("hVtx3BodyCounter"), kVtxDcaDau); + // get MC daughter particles + auto mcTrackProton = trackProton.template mcParticle_as(); + auto mcTrackPion = trackPion.template mcParticle_as(); + auto mcTrackDeuteron = trackDeuteron.template mcParticle_as(); + + // set daughter MC info (also for non-matched candidates) + this3BodyMCInfo.daughterPrPdgCode = mcTrackProton.pdgCode(); + this3BodyMCInfo.daughterPiPdgCode = mcTrackPion.pdgCode(); + this3BodyMCInfo.daughterDePdgCode = mcTrackDeuteron.pdgCode(); + this3BodyMCInfo.isDeuteronPrimary = mcTrackDeuteron.isPhysicalPrimary(); + this3BodyMCInfo.genMomProton = mcTrackProton.p(); + this3BodyMCInfo.genMomPion = mcTrackPion.p(); + this3BodyMCInfo.genMomDeuteron = mcTrackDeuteron.p(); + this3BodyMCInfo.genPtProton = mcTrackProton.pt(); + this3BodyMCInfo.genPtPion = mcTrackPion.pt(); + this3BodyMCInfo.genPtDeuteron = mcTrackDeuteron.pt(); + + // check if reco mother is true H3L/Anti-H3l + bool isMuonReco; + int motherID = checkH3LTruth(mcTrackProton, mcTrackPion, mcTrackDeuteron, isMuonReco); + + // get generated mother MC info + if (motherID > 0) { + auto mcTrackH3L = mcParticles.rawIteratorAt(motherID); + int chargeFactor = mcTrackH3L.pdgCode() > 0 ? 1 : -1; + this3BodyMCInfo.label = motherID; + this3BodyMCInfo.genMomentum = {mcTrackH3L.px(), mcTrackH3L.py(), mcTrackH3L.pz()}; + this3BodyMCInfo.genDecVtx = {mcTrackProton.vx(), mcTrackProton.vy(), mcTrackProton.vz()}; + this3BodyMCInfo.genCt = RecoDecay::sqrtSumOfSquares(mcTrackProton.vx() - mcTrackH3L.vx(), mcTrackProton.vy() - mcTrackH3L.vy(), mcTrackProton.vz() - mcTrackH3L.vz()) * o2::constants::physics::MassHyperTriton / mcTrackH3L.p(); + this3BodyMCInfo.genPhi = mcTrackH3L.phi(); + this3BodyMCInfo.genEta = mcTrackH3L.eta(); + this3BodyMCInfo.genRapidity = mcTrackH3L.y(); + this3BodyMCInfo.isTrueH3L = chargeFactor > 0; + this3BodyMCInfo.isTrueAntiH3L = chargeFactor < 0; + } - float VtxcosPA = RecoDecay::cpa(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{pos[0], pos[1], pos[2]}, std::array{p3B[0], p3B[1], p3B[2]}); - if (VtxcosPA < minCosPA3body) { - return; - } - registry.fill(HIST("hVtx3BodyCounter"), kVtxCosPA); - registry.fill(HIST("hBachelorTOFNSigmaDe"), t2.sign() * t2.p(), tofNSigmaBach); - - // additional cut for EM - if (decay3bodyId == -1) { - registry.fill(HIST("h3bodyEMCutCounter"), 0.5); - auto v0Track0 = getTrackParCov(t0); - auto v0Track1 = getTrackParCov(t1); - int nV0 = fitterV0.process(v0Track0, v0Track1); - if (nV0 == 0) { - return; - } - registry.fill(HIST("h3bodyEMCutCounter"), 1.5); + // fill analysis tables (only McVtx3BodyDatas is filled here) + fillAnalysisTables(); - std::array v0pos = {0.}; - const auto& v0vtxXYZ = fitterV0.getPCACandidate(); - for (int i = 0; i < 3; i++) { - v0pos[i] = v0vtxXYZ[i]; - } - const int cand = 0; - if (!fitterV0.isPropagateTracksToVertexDone(cand) && !fitterV0.propagateTracksToVertex(cand)) { - return; - } - registry.fill(HIST("h3bodyEMCutCounter"), 2.5); - - const auto& trPProp = fitterV0.getTrack(0, cand); - const auto& trNProp = fitterV0.getTrack(1, cand); - std::array pP{}, pN{}; - trPProp.getPxPyPzGlo(pP); - trNProp.getPxPyPzGlo(pN); - std::array pV0 = {pP[0] + pN[0], pP[1] + pN[1], pP[2] + pN[2]}; - // Cut for Virtual V0 - float dxv0 = v0pos[0] - mMeanVertex.getX(), dyv0 = v0pos[1] - mMeanVertex.getY(), r2v0 = dxv0 * dxv0 + dyv0 * dyv0; - float rv0 = std::sqrt(r2v0); - float pt2V0 = pV0[0] * pV0[0] + pV0[1] * pV0[1], prodXYv0 = dxv0 * pV0[0] + dyv0 * pV0[1], tDCAXY = prodXYv0 / pt2V0; - if (dcaFitterEMSel.cfgApplyV0Cut && pt2V0 <= dcaFitterEMSel.mMinPt2V0) { - return; - } - registry.fill(HIST("h3bodyEMCutCounter"), 3.5); - if (dcaFitterEMSel.cfgApplyV0Cut && pV0[2] * pV0[2] / pt2V0 > dcaFitterEMSel.mMaxTgl2V0) { // tgLambda cut - return; - } - registry.fill(HIST("h3bodyEMCutCounter"), 4.5); - - float p2V0 = pt2V0 + pV0[2] * pV0[2], ptV0 = std::sqrt(pt2V0); - // apply mass selections - float p2Pos = pP[0] * pP[0] + pP[1] * pP[1] + pP[2] * pP[2], p2Neg = pN[0] * pN[0] + pN[1] * pN[1] + pN[2] * pN[2]; - bool good3bodyV0Hyp = false; - for (int ipid = 0; ipid < 2; ipid++) { - float massForLambdaHyp = mV0Hyps[ipid].calcMass(p2Pos, p2Neg, p2V0); - if (massForLambdaHyp - mV0Hyps[ipid].getMassV0Hyp() < mV0Hyps[ipid].getMargin(ptV0)) { - good3bodyV0Hyp = true; - break; + // mark mcParticle as reconstructed + if (this3BodyMCInfo.label > -1) { + mcParticleIsReco[this3BodyMCInfo.label] = true; + } + } // constexpr requires mcParticles check + } // decay3body loop + + // ____________________________________________________________________ + // MC handling part: generated information of non-reco candidates + // ____________________________________________________________________ + if constexpr (soa::is_table) { + for (auto& mcparticle : mcParticles) { + // MC info + resetMCInfo(this3BodyMCInfo); + this3BodyMCInfo.isReco = false; + + // skip MC particle if reconstructed and already filled previously + if (mcParticleIsReco[mcparticle.globalIndex()] == true) { + continue; } - } - if (dcaFitterEMSel.cfgApplyV0Cut && !good3bodyV0Hyp) { - return; - } - registry.fill(HIST("h3bodyEMCutCounter"), 5.5); - float dcaX = dxv0 - pV0[0] * tDCAXY, dcaY = dyv0 - pV0[1] * tDCAXY, dca2 = dcaX * dcaX + dcaY * dcaY; - float cosPAXY = prodXYv0 / rv0 * ptV0; - if (dcaFitterEMSel.cfgApplyV0Cut && dca2 > dcaFitterEMSel.mMaxDCAXY2ToMeanVertex3bodyV0) { - return; - } - registry.fill(HIST("h3bodyEMCutCounter"), 6.5); - // FIXME: V0 cosPA cut to be investigated - if (dcaFitterEMSel.cfgApplyV0Cut && cosPAXY < dcaFitterEMSel.minCosPAXYMeanVertex3bodyV0) { - return; - } - registry.fill(HIST("h3bodyEMCutCounter"), 7.5); - // Check: CosPA Cut of Virtual V0 may not be used since the V0 may be based on another PV - float dx = v0pos[0] - collision.posX(), dy = v0pos[1] - collision.posY(), dz = v0pos[2] - collision.posZ(), prodXYZv0 = dx * pV0[0] + dy * pV0[1] + dz * pV0[2]; - float v0CosPA = prodXYZv0 / std::sqrt((dx * dx + dy * dy + dz * dz) * p2V0); - if (dcaFitterEMSel.cfgApplyV0Cut && v0CosPA < dcaFitterEMSel.minCosPA3bodyV0) { - return; - } - registry.fill(HIST("h3bodyEMCutCounter"), 8.5); + // set flag if corresponding MC collision has matched reconstructed collision which passed event selection + this3BodyMCInfo.survivedEventSel = isGoodCollision[mcparticle.mcCollisionId()]; - float r3body = std::hypot(pos[0], pos[1]); - if (r3body < 0.5) { - return; - } - registry.fill(HIST("h3bodyEMCutCounter"), 9.5); + // check if MC particle is hypertriton + if (std::abs(mcparticle.pdgCode()) != 1010010030) { + continue; + } - // Cut for the compatibility of V0 and 3body vertex - float deltaR = std::abs(rv0 - r3body); - if (deltaR > dcaFitterEMSel.maxRDiffV03body) { - return; - } - registry.fill(HIST("h3bodyEMCutCounter"), 10.5); + // check daughter identities + bool haveProton = false, havePion = false, haveDeuteron = false; + bool haveAntiProton = false, haveAntiPion = false, haveAntiDeuteron = false; + for (auto& mcparticleDaughter : mcparticle.template daughters_as()) { + if (mcparticleDaughter.pdgCode() == PDG_t::kProton) + haveProton = true; + if (mcparticleDaughter.pdgCode() == PDG_t::kProtonBar) + haveAntiProton = true; + if (mcparticleDaughter.pdgCode() == PDG_t::kPiPlus) + havePion = true; + if (mcparticleDaughter.pdgCode() == PDG_t::kPiMinus) + haveAntiPion = true; + if (mcparticleDaughter.pdgCode() == 1000010020) + haveDeuteron = true; + if (mcparticleDaughter.pdgCode() == -1000010020) + haveAntiDeuteron = true; + } - float pt3B = std::hypot(p3B[0], p3B[1]); - if (pt3B < dcaFitterEMSel.minPt3Body) { // pt cut - return; - } - registry.fill(HIST("h3bodyEMCutCounter"), 11.5); - if (p3B[2] / pt3B > dcaFitterEMSel.maxTgl3Body) { // tgLambda cut - return; - } - registry.fill(HIST("h3bodyEMCutCounter"), 12.5); - - // H3L DCA Check - const auto& vertexXYZ = fitter3body.getPCACandidatePos(); - auto track3B = o2::track::TrackParCov(vertexXYZ, p3B, t2.sign()); - o2::dataformats::DCA dca; - if (!track3B.propagateToDCA({{collision.posX(), collision.posY(), collision.posZ()}, {collision.covXX(), collision.covXY(), collision.covYY(), collision.covXZ(), collision.covYZ(), collision.covZZ()}}, fitter3body.getBz(), &dca, 5.) || - std::abs(dca.getY()) > dcaFitterEMSel.maxDCAXY3Body || std::abs(dca.getZ()) > dcaFitterEMSel.maxDCAZ3Body) { - return; - } - registry.fill(HIST("h3bodyEMCutCounter"), 13.5); - } + // check if hypertriton decayed via 3-body decay and is particle or anti-particle + if ((haveProton && haveAntiPion && haveDeuteron) || (haveAntiProton && havePion && haveAntiDeuteron)) { + if (mcparticle.pdgCode() > 0) { + this3BodyMCInfo.isTrueH3L = true; + } else if (mcparticle.pdgCode() < 0) { + this3BodyMCInfo.isTrueAntiH3L = true; + } + // get daughters + for (auto& mcparticleDaughter : mcparticle.template daughters_as()) { + if (std::abs(mcparticleDaughter.pdgCode()) == PDG_t::kProton) { // proton + this3BodyMCInfo.genMomProton = mcparticleDaughter.p(); + this3BodyMCInfo.genPtProton = mcparticleDaughter.pt(); + this3BodyMCInfo.daughterPrPdgCode = mcparticleDaughter.pdgCode(); + this3BodyMCInfo.genDecVtx = {mcparticleDaughter.vx(), mcparticleDaughter.vy(), mcparticleDaughter.vz()}; + } else if (std::abs(mcparticleDaughter.pdgCode()) == PDG_t::kPiPlus) { // pion + this3BodyMCInfo.genMomPion = mcparticleDaughter.p(); + this3BodyMCInfo.genPtPion = mcparticleDaughter.pt(); + this3BodyMCInfo.daughterPiPdgCode = mcparticleDaughter.pdgCode(); + } else if (std::abs(mcparticleDaughter.pdgCode()) == 1000010020) { // deuteron + this3BodyMCInfo.genMomDeuteron = mcparticleDaughter.p(); + this3BodyMCInfo.genPtDeuteron = mcparticleDaughter.pt(); + this3BodyMCInfo.daughterDePdgCode = mcparticleDaughter.pdgCode(); + this3BodyMCInfo.isDeuteronPrimary = mcparticleDaughter.isPhysicalPrimary(); + } + } + } else { + continue; // stop if particle is not decayed via 3-body decay + } - VtxCandidate candVtx; - candVtx.track0Id = t0.globalIndex(); - candVtx.track1Id = t1.globalIndex(); - candVtx.track2Id = t2.globalIndex(); - candVtx.collisionId = collision.globalIndex(); - candVtx.decay3bodyId = decay3bodyId; - candVtx.vtxPos[0] = pos[0]; - candVtx.vtxPos[1] = pos[1]; - candVtx.vtxPos[2] = pos[2]; - candVtx.track0P[0] = p0[0]; - candVtx.track0P[1] = p0[1]; - candVtx.track0P[2] = p0[2]; - candVtx.track1P[0] = p1[0]; - candVtx.track1P[1] = p1[1]; - candVtx.track1P[2] = p1[2]; - candVtx.track2P[0] = p2[0]; - candVtx.track2P[1] = p2[1]; - candVtx.track2P[2] = p2[2]; - candVtx.dcadaughters = fitter3body.getChi2AtPCACandidate(); - candVtx.daudcaxytopv[0] = Track0dcaXY; - candVtx.daudcaxytopv[1] = Track1dcaXY; - candVtx.daudcaxytopv[2] = Track2dcaXY; - candVtx.daudcatopv[0] = Track0dca; - candVtx.daudcatopv[1] = Track1dca; - candVtx.daudcatopv[2] = Track2dca; - candVtx.bachelortofNsigma = tofNSigmaBach; - if (saveInTable) { - fillVtx3BodyTable(candVtx); - } else { - VtxCandidates.push_back(candVtx); - } + // calculate ctau + this3BodyMCInfo.genCt = RecoDecay::sqrtSumOfSquares(this3BodyMCInfo.genDecVtx[0] - mcparticle.vx(), this3BodyMCInfo.genDecVtx[1] - mcparticle.vy(), this3BodyMCInfo.genDecVtx[2] - mcparticle.vz()) * o2::constants::physics::MassHyperTriton / mcparticle.p(); + + // fill MCDecay3BodyCores table if requested + if (mEnabledTables[kMcVtx3BodyDatas]) { + products.mcvtx3bodydatas(-1, // sign + -1., -1., // mass, massV0 + -1., -1., -1., // position + -1., -1., -1., // momentum + -1., // chi2 + -1., // trackedClSize + -1., -1., -1., // momProton + -1., -1., -1., // momPion + -1., -1., -1., // momDeuteron + -1., -1., -1., // trackDCAxyToPV: 0 - proton, 1 - pion, 2 - deuteron + -1., -1., -1., // trackDCAzToPV: 0 - proton, 1 - pion, 2 - deuteron + -1., -1., -1., // daughterDCAtoSV: 0 - proton, 1 - pion, 2 - deuteron + -1., // daughterDCAatSV + -1., -1., -1., -1., // tpcNsigma: 0 - proton, 1 - pion, 2 - deuteron, 3 - bach with pion hyp + -1., // tofNsigmaDeuteron + -1., -1., -1., // average ITS cluster sizes: proton, pion, deuteron + -1., -1., -1., // TPCNCl: proton, pion, deuteron + -1., // pidForTrackingDeuteron + // MC information + mcparticle.px(), mcparticle.py(), mcparticle.pz(), + this3BodyMCInfo.genDecVtx[0], this3BodyMCInfo.genDecVtx[1], this3BodyMCInfo.genDecVtx[2], + this3BodyMCInfo.genCt, + mcparticle.phi(), mcparticle.eta(), mcparticle.y(), + this3BodyMCInfo.genMomProton, this3BodyMCInfo.genMomPion, this3BodyMCInfo.genMomDeuteron, + this3BodyMCInfo.genPtProton, this3BodyMCInfo.genPtPion, this3BodyMCInfo.genPtDeuteron, + this3BodyMCInfo.isTrueH3L, this3BodyMCInfo.isTrueAntiH3L, + this3BodyMCInfo.isReco, + this3BodyMCInfo.daughterPrPdgCode, this3BodyMCInfo.daughterPiPdgCode, this3BodyMCInfo.daughterDePdgCode, + this3BodyMCInfo.isDeuteronPrimary, + this3BodyMCInfo.survivedEventSel); + } // enabled table check + } // mcParticles loop + } // constexpr requires mcParticles check } - //------------------------------------------------------------------ - // event mixing - template - void doMixed3Body(TMixed3bodys decay3bodys, TBinningType binningType) + + // ______________________________________________________________ + // function to build mixed decay3body candidates + template + void buildMixedCandidates(TRedDecay3Bodys const& decay3bodys, TBinningType const& binningType) { + if (!mEnabledTables[kVtx3BodyDatas]) { + return; // don't do if no request for decay3bodys in place + } + // Strictly upper index policy for decay3body objects binned by radius, phi - for (const auto& [decay3body0, decay3body1] : selfCombinations(binningType, dcaFitterEMSel.nUseMixed, -1, decay3bodys, decay3bodys)) { - auto tpos0 = decay3body0.template track0_as(); - auto tneg0 = decay3body0.template track1_as(); - auto tbach0 = decay3body0.template track2_as(); - auto tpos1 = decay3body1.template track0_as(); - auto tneg1 = decay3body1.template track1_as(); - auto tbach1 = decay3body1.template track2_as(); - - registry.fill(HIST("h3bodyCombinationCounter"), 0.5); - - // ---------- selections ---------- - if ((tbach0.sign() > 0 && !(tbach1.sign() > 0)) || (tbach0.sign() < 0 && !(tbach1.sign() < 0)) || tbach0.globalIndex() == tbach1.globalIndex()) { // only combine if tbach1 has correct sign and is not same as tbach0 + for (const auto& [decay3body0, decay3body1] : selfPairCombinations(binningType, mixingOpts.n3bodyMixing, -1, decay3bodys)) { + auto trackPos0 = decay3body0.template track0_as(); + auto trackNeg0 = decay3body0.template track1_as(); + auto trackDeuteron0 = decay3body0.template track2_as(); + auto trackPos1 = decay3body1.template track0_as(); + auto trackNeg1 = decay3body1.template track1_as(); + auto trackDeuteron1 = decay3body1.template track2_as(); + + // assign tracks + auto trackProton0 = trackPos0; + auto trackPion0 = trackNeg0; + auto trackProton1 = trackPos1; + auto trackPion1 = trackNeg1; + if (trackDeuteron0.sign() < 0) { + trackProton0 = trackNeg0; + trackPion0 = trackPos0; + } + if (trackDeuteron1.sign() < 0) { + trackProton1 = trackNeg1; + trackPion1 = trackPos1; + } + + registry.fill(HIST("Mixing/h3bodyCombinationCounter"), 0.5); + + // only combine if from different event + if (decay3body0.collisionId() == decay3body1.collisionId()) { continue; } - registry.fill(HIST("h3bodyCombinationCounter"), 1.5); + registry.fill(HIST("Mixing/h3bodyCombinationCounter"), 1.5); + + // collision vertex selection + auto collision0 = decay3body0.template collision_as(); + auto collision1 = decay3body1.template collision_as(); + + // get b_z value for each collision (from CCDB or cache) and cache it for that run number + float magFieldCol0 = getMagFieldFromRunNumber(collision0.runNumber()); + float magFieldCol1 = getMagFieldFromRunNumber(collision1.runNumber()); - if (decay3body0.collisionId() == decay3body1.collisionId()) { // only combine if from different event + // only combine if collision similar in VtxZ + if (mixingOpts.selectPVPosZ3bodyMixing && std::abs(collision0.posZ() - collision1.posZ()) > mixingOpts.maxDeltaPVPosZ3bodyMixing) { continue; } - registry.fill(HIST("h3bodyCombinationCounter"), 2.5); + registry.fill(HIST("Mixing/h3bodyCombinationCounter"), 2.5); - auto c0 = decay3body0.template collision_as(); - auto c1 = decay3body1.template collision_as(); + // Charge selections + // same magnetic fields --> mix matter with matter + if ((magFieldCol0 / std::abs(magFieldCol0)) == (magFieldCol1 / std::abs(magFieldCol1))) { + if (trackDeuteron0.sign() != trackDeuteron1.sign()) { + continue; + } + } + // opposite magnetic fields --> mix matter with anti-matter + if ((magFieldCol0 / std::abs(magFieldCol0)) != (magFieldCol1 / std::abs(magFieldCol1))) { + if (trackDeuteron0.sign() == trackDeuteron1.sign()) { + continue; + } + } - if (dcaFitterEMSel.selectPVPosZ3bodyMixing && std::abs(c0.posZ() - c1.posZ()) > dcaFitterEMSel.maxDeltaPVPosZ3bodyMixing) { // only combine if collision similar in PV posZ + // don't mix 3body with itself + if ((trackDeuteron0.globalIndex() == trackDeuteron1.globalIndex()) || (trackProton0.globalIndex() == trackProton1.globalIndex()) || (trackPion0.globalIndex() == trackPion1.globalIndex())) { continue; } - registry.fill(HIST("h3bodyCombinationCounter"), 3.5); - - initCCDBfromRunNumber(c0.runNumber()); - - if (dcaFitterEMSel.cfgMix3BodyMethod == 0) { // mix bachelor (deuteron) - fillVtxCand(c0, tpos0, tneg0, tbach1, -1, bachelorcharge, tbach1.tofNSigmaDe()); - fillVtxCand(c1, tpos1, tneg1, tbach0, -1, bachelorcharge, tbach0.tofNSigmaDe()); - } else if ((dcaFitterEMSel.cfgMix3BodyMethod == 1 && tbach0.sign() > 0) || (dcaFitterEMSel.cfgMix3BodyMethod == 2 && tbach0.sign() < 0)) { // mix piMinus or proton - fillVtxCand(c0, tpos0, tneg1, tbach0, -1, bachelorcharge, tbach0.tofNSigmaDe()); - fillVtxCand(c1, tpos1, tneg0, tbach1, -1, bachelorcharge, tbach1.tofNSigmaDe()); - } else if ((dcaFitterEMSel.cfgMix3BodyMethod == 1 && tbach0.sign() < 0) || (dcaFitterEMSel.cfgMix3BodyMethod == 2 && tbach0.sign() > 0)) { // mix piPlus or anti-proton - fillVtxCand(c0, tpos1, tneg0, tbach0, -1, bachelorcharge, tbach0.tofNSigmaDe()); - fillVtxCand(c1, tpos0, tneg1, tbach1, -1, bachelorcharge, tbach1.tofNSigmaDe()); - } + registry.fill(HIST("Mixing/h3bodyCombinationCounter"), 3.5); - VtxCandidates.clear(); + // candidate analysis + // mix deuteron + if (mixingOpts.mixingType == 0) { + doMixing(collision0, trackProton0, trackPion0, trackDeuteron1, magFieldCol0); + doMixing(collision1, trackProton1, trackPion1, trackDeuteron0, magFieldCol1); + } + // mix proton + if (mixingOpts.mixingType == 1) { + doMixing(collision0, trackProton1, trackPion0, trackDeuteron0, magFieldCol0); + doMixing(collision1, trackProton0, trackPion1, trackDeuteron1, magFieldCol1); + } + // mix pion + if (mixingOpts.mixingType == 2) { + doMixing(collision0, trackProton0, trackPion1, trackDeuteron0, magFieldCol0); + doMixing(collision1, trackProton1, trackPion0, trackDeuteron1, magFieldCol1); + } } // end decay3body combinations loop } - //------------------------------------------------------------------ - // fill the StoredVtx3BodyDatas table - void fillVtx3BodyTable(VtxCandidate const& candVtx) + + // ______________________________________________________________ + // function to calculate correct TOF nSigma for deuteron track + template + double getTOFnSigma(TCollision const& collision, TTrack const& track) { - vtx3bodydata( - candVtx.track0Id, candVtx.track1Id, candVtx.track2Id, candVtx.collisionId, candVtx.decay3bodyId, - candVtx.vtxPos[0], candVtx.vtxPos[1], candVtx.vtxPos[2], - candVtx.track0P[0], candVtx.track0P[1], candVtx.track0P[2], candVtx.track1P[0], candVtx.track1P[1], candVtx.track1P[2], candVtx.track2P[0], candVtx.track2P[1], candVtx.track2P[2], - candVtx.dcadaughters, - candVtx.daudcaxytopv[0], candVtx.daudcaxytopv[1], candVtx.daudcaxytopv[2], - candVtx.daudcatopv[0], candVtx.daudcatopv[1], candVtx.daudcatopv[2], - candVtx.bachelortofNsigma); + // TOF PID of deuteron + if (track.has_collision() && track.hasTOF()) { + auto originalcol = track.template collision_as(); + if constexpr (isMC) { + return bachelorTOFPIDLabeled.GetTOFNSigma(track, originalcol, collision); + } else { + return bachelorTOFPID.GetTOFNSigma(track, originalcol, collision); + } + } + return -999; } - //------------------------------------------------------------------ - //-------------------- KFParticle reconstruction ------------------- - //------------------------------------------------------------------ - // function to select daughter track PID - template - bool selectTPCPID(TTrack const& trackProton, TTrack const& trackPion, TTrack const& trackDeuteron) + // ______________________________________________________________ + // function to fill analysis tables + void fillAnalysisTables() { - if (std::abs(trackProton.tpcNSigmaPr()) > kfparticleConfigurations.maxtpcnSigma) { - return false; - } - if (std::abs(trackDeuteron.tpcNSigmaDe()) > kfparticleConfigurations.maxtpcnSigma) { - return false; + // generate analysis tables + if (mEnabledTables[kDecay3BodyIndices]) { + products.decay3bodyindices(helper.decay3body.decay3bodyID, + helper.decay3body.protonID, helper.decay3body.pionID, helper.decay3body.deuteronID, + helper.decay3body.collisionID); + registry.fill(HIST("Counters/hTableBuildingStatistics"), kDecay3BodyIndices); + } + if (mEnabledTables[kVtx3BodyDatas]) { + products.vtx3bodydatas(helper.decay3body.sign, + helper.decay3body.mass, helper.decay3body.massV0, + helper.decay3body.position[0], helper.decay3body.position[1], helper.decay3body.position[2], + helper.decay3body.momentum[0], helper.decay3body.momentum[1], helper.decay3body.momentum[2], + helper.decay3body.chi2, + helper.decay3body.trackedClSize, + helper.decay3body.momProton[0], helper.decay3body.momProton[1], helper.decay3body.momProton[2], + helper.decay3body.momPion[0], helper.decay3body.momPion[1], helper.decay3body.momPion[2], + helper.decay3body.momDeuteron[0], helper.decay3body.momDeuteron[1], helper.decay3body.momDeuteron[2], + helper.decay3body.trackDCAxyToPV[0], helper.decay3body.trackDCAxyToPV[1], helper.decay3body.trackDCAxyToPV[2], // 0 - proton, 1 - pion, 2 - deuteron + helper.decay3body.trackDCAzToPV[0], helper.decay3body.trackDCAzToPV[1], helper.decay3body.trackDCAzToPV[2], // 0 - proton, 1 - pion, 2 - deuteron + helper.decay3body.daughterDCAtoSV[0], helper.decay3body.daughterDCAtoSV[1], helper.decay3body.daughterDCAtoSV[2], // 0 - proton, 1 - pion, 2 - deuteron + helper.decay3body.daughterDCAatSV, + helper.decay3body.tpcNsigma[0], helper.decay3body.tpcNsigma[1], helper.decay3body.tpcNsigma[2], helper.decay3body.tpcNsigma[2], // 0 - proton, 1 - pion, 2 - deuteron, 3 - bach with pion hyp + helper.decay3body.tofNsigmaDeuteron, + helper.decay3body.averageITSClSize[0], helper.decay3body.averageITSClSize[1], helper.decay3body.averageITSClSize[2], // 0 - proton, 1 - pion, 2 - deuteron + helper.decay3body.tpcNCl[0], helper.decay3body.tpcNCl[1], helper.decay3body.tpcNCl[2], // 0 - proton, 1 - pion, 2 - deuteron + helper.decay3body.pidForTrackingDeuteron); + registry.fill(HIST("Counters/hTableBuildingStatistics"), kVtx3BodyDatas); + } + if (mEnabledTables[kVtx3BodyCovs]) { + products.vtx3bodycovs(helper.decay3body.covProton, + helper.decay3body.covPion, + helper.decay3body.covDeuteron, + helper.decay3body.covariance); + registry.fill(HIST("Counters/hTableBuildingStatistics"), kVtx3BodyCovs); + } + if (mEnabledTables[kMcVtx3BodyDatas]) { + products.mcvtx3bodydatas(helper.decay3body.sign, + helper.decay3body.mass, helper.decay3body.massV0, + helper.decay3body.position[0], helper.decay3body.position[1], helper.decay3body.position[2], + helper.decay3body.momentum[0], helper.decay3body.momentum[1], helper.decay3body.momentum[2], + helper.decay3body.chi2, + helper.decay3body.trackedClSize, + helper.decay3body.momProton[0], helper.decay3body.momProton[1], helper.decay3body.momProton[2], + helper.decay3body.momPion[0], helper.decay3body.momPion[1], helper.decay3body.momPion[2], + helper.decay3body.momDeuteron[0], helper.decay3body.momDeuteron[1], helper.decay3body.momDeuteron[2], + helper.decay3body.trackDCAxyToPV[0], helper.decay3body.trackDCAxyToPV[1], helper.decay3body.trackDCAxyToPV[2], // 0 - proton, 1 - pion, 2 - deuteron + helper.decay3body.trackDCAzToPV[0], helper.decay3body.trackDCAzToPV[1], helper.decay3body.trackDCAzToPV[2], // 0 - proton, 1 - pion, 2 - deuteron + helper.decay3body.daughterDCAtoSV[0], helper.decay3body.daughterDCAtoSV[1], helper.decay3body.daughterDCAtoSV[2], // 0 - proton, 1 - pion, 2 - deuteron + helper.decay3body.daughterDCAatSV, + helper.decay3body.tpcNsigma[0], helper.decay3body.tpcNsigma[1], helper.decay3body.tpcNsigma[2], helper.decay3body.tpcNsigma[2], // 0 - proton, 1 - pion, 2 - deuteron, 3 - bach with pion hyp + helper.decay3body.tofNsigmaDeuteron, + helper.decay3body.averageITSClSize[0], helper.decay3body.averageITSClSize[1], helper.decay3body.averageITSClSize[2], // 0 - proton, 1 - pion, 2 - deuteron + helper.decay3body.tpcNCl[0], helper.decay3body.tpcNCl[1], helper.decay3body.tpcNCl[2], // 0 - proton, 1 - pion, 2 - deuteron + helper.decay3body.pidForTrackingDeuteron, + // MC information + this3BodyMCInfo.genMomentum[0], this3BodyMCInfo.genMomentum[1], this3BodyMCInfo.genMomentum[2], + this3BodyMCInfo.genDecVtx[0], this3BodyMCInfo.genDecVtx[1], this3BodyMCInfo.genDecVtx[2], + this3BodyMCInfo.genCt, + 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.daughterPrPdgCode, this3BodyMCInfo.daughterPiPdgCode, this3BodyMCInfo.daughterDePdgCode, + this3BodyMCInfo.isDeuteronPrimary, + this3BodyMCInfo.survivedEventSel); + registry.fill(HIST("Counters/hTableBuildingStatistics"), kMcVtx3BodyDatas); } - if (kfparticleConfigurations.useTPCforPion && std::abs(trackPion.tpcNSigmaPi()) > kfparticleConfigurations.maxtpcnSigma) { - return false; + } + + // ______________________________________________________________ + // function to build mixed 3body candidate from selected tracks + template + void doMixing(TCollision const& collision, TTrack const& trackProton, TTrack const& trackPion, TTrack const& trackDeuteron, float magField) + { + // set vertexers and propagator with correct mag field of this collision (only if run number changed compared to previous candidate build) + initFittersWithMagField(collision.runNumber(), magField); + if (helper.buildDecay3BodyCandidate(collision, trackProton, trackPion, trackDeuteron, + -1 /*decay3bodyIndex*/, + trackDeuteron.tofNSigmaDe(), + 0 /*trackedClSize*/, + decay3bodyBuilderOpts.useKFParticle, + decay3bodyBuilderOpts.kfSetTopologicalConstraint, + decay3bodyBuilderOpts.useSelections, + decay3bodyBuilderOpts.useTPCforPion, + decay3bodyBuilderOpts.acceptTPCOnly, + decay3bodyBuilderOpts.calculateCovariance, + true /*isEventMixing*/)) { + // fill analysis tables with built candidate + fillAnalysisTables(); + return; + } else { + return; } - return true; } - template - double getTOFnSigma(TCollision const& collision, TTrack const& track, bool isEventMixing) + // ______________________________________________________________ + // function to check if a reconstructed mother is a true H3L/Anti-H3L (returns -1 if not) + template + int checkH3LTruth(MCTrack3B const& mcParticlePr, MCTrack3B const& mcParticlePi, MCTrack3B const& mcParticleDe, bool& isMuonReco) { - // TOF PID of deuteron (set motherhyp correctly) - double tofNSigmaDeuteron = -999; - if (track.has_collision() && track.hasTOF()) { - if (isEventMixing) { - tofNSigmaDeuteron = bachelorTOFPID.GetTOFNSigma(track, collision, collision); - } else { - auto originalcol = track.template collision_as(); - tofNSigmaDeuteron = bachelorTOFPID.GetTOFNSigma(track, originalcol, collision); + if (std::abs(mcParticlePr.pdgCode()) != 2212 || std::abs(mcParticleDe.pdgCode()) != 1000010020) { + return -1; + } + // check proton and deuteron mother + int prDeMomID = -1; + for (const auto& motherPr : mcParticlePr.template mothers_as()) { + for (const auto& motherDe : mcParticleDe.template mothers_as()) { + if (motherPr.globalIndex() == motherDe.globalIndex() && std::abs(motherPr.pdgCode()) == 1010010030) { + prDeMomID = motherPr.globalIndex(); + break; + } + } + } + if (prDeMomID == -1) { + return -1; + } + if (std::abs(mcParticlePi.pdgCode()) != 211 && std::abs(mcParticlePi.pdgCode()) != 13) { + return -1; + } + // check if the pion track is a muon coming from a pi -> mu + vu decay, if yes, take the mother pi + auto mcParticlePiTmp = mcParticlePi; + if (std::abs(mcParticlePiTmp.pdgCode()) == 13) { + for (const auto& motherPi : mcParticlePiTmp.template mothers_as()) { + if (std::abs(motherPi.pdgCode()) == 211) { + mcParticlePiTmp = motherPi; + isMuonReco = true; + break; + } + } + } + // now loop over the pion mother + for (const auto& motherPi : mcParticlePiTmp.template mothers_as()) { + if (motherPi.globalIndex() == prDeMomID) { + return motherPi.globalIndex(); } } - return tofNSigmaDeuteron; + return -1; } - //------------------------------------------------------------------ - // function to fill candidate table - template - void fillCandidateTable(TCandidate const& candidate) + // ______________________________________________________________ + // function to reset MCInfo + void resetMCInfo(mc3Bodyinfo mcInfo) { - kfvtx3bodydatalite( - // hypertriton - candidate.mass, - candidate.pos[0], candidate.pos[1], candidate.pos[2], - candidate.mom[0], candidate.mom[1], candidate.mom[2], candidate.mom[3], - candidate.charge, - candidate.dcaToPV[0], candidate.dcaToPV[1], // 3D, xy - candidate.cpaToPV[0], candidate.cpaToPV[1], // 3D, xy - candidate.decLen[0], candidate.decLen[1], // 3D, xy - candidate.ldl, - candidate.chi2geoNDF, candidate.chi2topoNDF, - candidate.ctau, - candidate.trackedClSize, - // V0 - candidate.massV0, - candidate.cpaV0ToPV, - // daughter momenta at vertex - candidate.protonMom[0], candidate.protonMom[1], candidate.protonMom[2], - candidate.pionMom[0], candidate.pionMom[1], candidate.pionMom[2], - candidate.deuteronMom[0], candidate.deuteronMom[1], candidate.deuteronMom[2], - candidate.tpcInnerParam[0], candidate.tpcInnerParam[1], candidate.tpcInnerParam[2], // proton, pion, deuteron - // daughter track quality - candidate.tpcNClDaughters[0], candidate.tpcNClDaughters[1], candidate.tpcNClDaughters[2], // proton, pion, deuteron - candidate.tpcChi2NClDeuteron, - candidate.DeltaPhiRotDeuteron, candidate.DeltaPhiRotProton, - // daughter DCAs KF - candidate.DCAdaughterToPV[0], candidate.DCAdaughterToPV[1], candidate.DCAdaughterToPV[2], // proton, pion, deuteron - candidate.DCAdaughterToPVxy[0], candidate.DCAdaughterToPVxy[1], candidate.DCAdaughterToPVxy[2], // proton, pion, deuteron - candidate.DCAdaughterToSVxy[0], candidate.DCAdaughterToSVxy[1], candidate.DCAdaughterToSVxy[2], // proton, pion, deuteron - candidate.DCAprotonToPion, candidate.DCAprotonToDeuteron, candidate.DCApionToDeuteron, - candidate.DCAvtxDaughters3D, - // daughter signs - candidate.daughterCharge[0], candidate.daughterCharge[1], candidate.daughterCharge[2], // proton, pion, deuteron - // daughter PID - candidate.tpcNsigma[0], candidate.tpcNsigma[1], candidate.tpcNsigma[2], candidate.tpcNsigma[3], // proton, pion, deuteron, bach with pion hyp - candidate.tofNsigmaDeuteron, - candidate.averageClusterSizeDeuteron, - candidate.pidForTrackingDeuteron); - - if (kfparticleConfigurations.fillCandidateFullTable) { - kfvtx3bodydata( - candidate.collisionID, candidate.trackPosID, candidate.trackNegID, candidate.trackBachID, candidate.decay3bodyID, - // hypertriton - candidate.mass, - candidate.pos[0], candidate.pos[1], candidate.pos[2], - candidate.posErr[0], candidate.posErr[1], candidate.posErr[2], - candidate.mom[0], candidate.mom[1], candidate.mom[2], candidate.mom[3], - candidate.momErr[0], candidate.momErr[1], candidate.momErr[2], candidate.momErr[3], - candidate.charge, - candidate.dcaToPV[0], candidate.dcaToPV[1], // 3D, xy - candidate.cpaToPV[0], candidate.cpaToPV[1], // 3D, xy - candidate.cpaToPVtopo[0], candidate.cpaToPVtopo[1], // 3D, xy - candidate.decLen[0], candidate.decLen[1], // 3D, xy - candidate.ldl, - candidate.chi2geoNDF, candidate.chi2topoNDF, - candidate.ctau, - candidate.trackedClSize, - // V0 - candidate.massV0, candidate.chi2massV0, - candidate.cpaV0ToPV, - // daughter momenta (at vertex and TPC) - candidate.protonMom[0], candidate.protonMom[1], candidate.protonMom[2], - candidate.pionMom[0], candidate.pionMom[1], candidate.pionMom[2], - candidate.deuteronMom[0], candidate.deuteronMom[1], candidate.deuteronMom[2], - candidate.tpcInnerParam[0], candidate.tpcInnerParam[1], candidate.tpcInnerParam[2], // proton, pion, deuteron - // daughter track quality - candidate.tpcNClDaughters[0], candidate.tpcNClDaughters[1], candidate.tpcNClDaughters[2], // proton, pion, deuteron - candidate.tpcChi2NClDeuteron, - candidate.DeltaPhiRotDeuteron, candidate.DeltaPhiRotProton, - // daughter DCAs KF - candidate.DCAdaughterToPV[0], candidate.DCAdaughterToPV[1], candidate.DCAdaughterToPV[2], // proton, pion, deuteron - candidate.DCAdaughterToPVxy[0], candidate.DCAdaughterToPVxy[1], candidate.DCAdaughterToPVxy[2], // proton, pion, deuteron - candidate.DCAdaughterToSVxy[0], candidate.DCAdaughterToSVxy[1], candidate.DCAdaughterToSVxy[2], // proton, pion, deuteron - candidate.DCAprotonToPion, candidate.DCAprotonToDeuteron, candidate.DCApionToDeuteron, - candidate.DCAvtxDaughters3D, - // daughter DCAs to PV propagated with material - candidate.trackDCAxy[0], candidate.trackDCAxy[1], candidate.trackDCAxy[2], // pos, neg, bach - candidate.trackDCA[0], candidate.trackDCA[1], candidate.trackDCA[2], // pos, neg, bach - // daughter signs - candidate.daughterCharge[0], candidate.daughterCharge[1], candidate.daughterCharge[2], // proton, pion, deuteron - // daughter PID - candidate.tpcNsigma[0], candidate.tpcNsigma[1], candidate.tpcNsigma[2], candidate.tpcNsigma[3], // proton, pion, deuteron, bach with pion hyp - candidate.tpcdEdx[0], candidate.tpcdEdx[1], candidate.tpcdEdx[2], // proton, pion, deuteron - candidate.tofNsigmaDeuteron, - candidate.averageClusterSizeDeuteron, - candidate.pidForTrackingDeuteron); - } - LOG(debug) << "Table filled."; + mcInfo.label = -1; + 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.daughterPrPdgCode = -1, mcInfo.daughterPiPdgCode = -1, mcInfo.daughterDePdgCode = -1; + mcInfo.isDeuteronPrimary = false; + mcInfo.survivedEventSel = false; + return; } - //------------------------------------------------------------------ - // function to fit KFParticle 3body vertex - template - void fit3bodyVertex(TKFParticle& kfpProton, TKFParticle& kfpPion, TKFParticle& kfpDeuteron, TKFParticle& KFHt) + // ______________________________________________________________ + // process functions + void processRealData(ColswithEvTimes const& collisions, + aod::Decay3Bodys const& decay3bodys, + aod::Tracked3Bodys const& tracked3bodys, + TracksExtPIDIUwithEvTimes const&, + aod::BCsWithTimestamps const& bcs) { - // Construct 3body vertex - int nDaughters3body = 3; - const KFParticle* Daughters3body[3] = {&kfpProton, &kfpPion, &kfpDeuteron}; - KFHt.SetConstructMethod(2); - try { - KFHt.Construct(Daughters3body, nDaughters3body); - } catch (std::runtime_error& e) { - LOG(debug) << "Failed to create Hyper triton 3-body vertex." << e.what(); + // initialise CCDB from BCs + if (!initCCDB(bcs, collisions)) { + LOG(info) << "CCDB initialisation failed, skipping candidate building." << std::endl; return; } - // transport all daughter tracks to hypertriton vertex - float HtVtx[3] = {0.}; - HtVtx[0] = KFHt.GetX(); - HtVtx[1] = KFHt.GetY(); - HtVtx[2] = KFHt.GetZ(); - kfpProton.TransportToPoint(HtVtx); - kfpPion.TransportToPoint(HtVtx); - kfpDeuteron.TransportToPoint(HtVtx); - LOG(debug) << "Hypertriton vertex constructed."; + + // get tracked cluster size info + fTrackedClSizeVector.clear(); + fTrackedClSizeVector.resize(decay3bodys.size(), 0); + for (const auto& tvtx3body : tracked3bodys) { + fTrackedClSizeVector[tvtx3body.decay3BodyId()] = tvtx3body.itsClsSize(); + } + + // do candidate analysis without MC processing + buildCandidates(bcs, // bc table + collisions, // collision table + decay3bodys, // decay3body table + static_cast(nullptr), // MC particle table + static_cast(nullptr)); // MC collision table } - //------------------------------------------------------------------ - // 3body candidate builder with KFParticle - template - void buildVtx3BodyDataTableKFParticle(TCollision const& collision, TTrack const& trackPos, TTrack const& trackNeg, TTrack const& trackBach, int64_t decay3bodyID, int bachelorcharge, double tofNSigmaDeuteron) + void processRealDataReduced(aod::RedCollisions const& collisions, + soa::Join const& decay3bodys, + aod::RedIUTracks const&) { - gROOT->SetBatch(true); - gRandom->SetSeed(42); - - // initialise KF primary vertex - KFPVertex kfpVertex = createKFPVertexFromCollision(collision); - KFParticle kfpv(kfpVertex); - LOG(debug) << "Created KF PV."; - - // fill event QA histograms --> only for events with a decay3body! - if (kfparticleConfigurations.doVertexQA) { - registry.fill(HIST("QA/Event/hVtxXKF"), kfpv.GetX()); - registry.fill(HIST("QA/Event/hVtxYKF"), kfpv.GetY()); - registry.fill(HIST("QA/Event/hVtxZKF"), kfpv.GetZ()); - registry.fill(HIST("QA/Event/hVtxCovXXKF"), kfpv.GetCovariance(0)); - registry.fill(HIST("QA/Event/hVtxCovYYKF"), kfpv.GetCovariance(2)); - registry.fill(HIST("QA/Event/hVtxCovZZKF"), kfpv.GetCovariance(5)); - registry.fill(HIST("QA/Event/hVtxCovXYKF"), kfpv.GetCovariance(1)); - registry.fill(HIST("QA/Event/hVtxCovXZKF"), kfpv.GetCovariance(3)); - registry.fill(HIST("QA/Event/hVtxCovYZKF"), kfpv.GetCovariance(4)); - registry.fill(HIST("QA/Event/hVtxX"), collision.posX()); - registry.fill(HIST("QA/Event/hVtxY"), collision.posY()); - registry.fill(HIST("QA/Event/hVtxZ"), collision.posZ()); - registry.fill(HIST("QA/Event/hVtxCovXX"), collision.covXX()); - registry.fill(HIST("QA/Event/hVtxCovYY"), collision.covYY()); - registry.fill(HIST("QA/Event/hVtxCovZZ"), collision.covZZ()); - registry.fill(HIST("QA/Event/hVtxCovXY"), collision.covXY()); - registry.fill(HIST("QA/Event/hVtxCovXZ"), collision.covXZ()); - registry.fill(HIST("QA/Event/hVtxCovYZ"), collision.covYZ()); + // get tracked cluster size info (saved in aod::Red3BodyInfo) + fTrackedClSizeVector.clear(); + fTrackedClSizeVector.resize(decay3bodys.size(), 0); + for (const auto& vtx3body : decay3bodys) { + fTrackedClSizeVector[vtx3body.globalIndex()] = vtx3body.trackedClSize(); } - registry.fill(HIST("Counters/hVtx3BodyCounterKFParticle"), kKfVtxAll); - - auto trackParCovPos = getTrackParCov(trackPos); - auto trackParCovNeg = getTrackParCov(trackNeg); - auto trackParCovBach = getTrackParCov(trackBach); - LOG(debug) << "Got all daughter tracks."; - - bool isMatter = trackBach.sign() > 0 ? true : false; - - // ---------- fill track QA histograms ---------- - if (kfparticleConfigurations.doTrackQA) { - registry.fill(HIST("QA/Tracks/hTrackPosTPCNcls"), trackPos.tpcNClsFound()); - registry.fill(HIST("QA/Tracks/hTrackNegTPCNcls"), trackNeg.tpcNClsFound()); - registry.fill(HIST("QA/Tracks/hTrackBachTPCNcls"), trackBach.tpcNClsFound()); - registry.fill(HIST("QA/Tracks/hTrackPosHasTPC"), trackPos.hasTPC()); - registry.fill(HIST("QA/Tracks/hTrackNegHasTPC"), trackNeg.hasTPC()); - registry.fill(HIST("QA/Tracks/hTrackBachHasTPC"), trackBach.hasTPC()); - registry.fill(HIST("QA/Tracks/hTrackBachITSClusSizes"), trackBach.itsClusterSizes()); - if (isMatter) { - registry.fill(HIST("QA/Tracks/hTrackProtonTPCPID"), trackPos.sign() * trackPos.tpcInnerParam(), trackPos.tpcNSigmaPr()); - registry.fill(HIST("QA/Tracks/hTrackPionTPCPID"), trackNeg.sign() * trackNeg.tpcInnerParam(), trackNeg.tpcNSigmaPi()); - registry.fill(HIST("QA/Tracks/hTrackProtonPt"), trackPos.pt()); - registry.fill(HIST("QA/Tracks/hTrackPionPt"), trackNeg.pt()); + // do candidate analysis without MC processing + buildCandidates(static_cast(nullptr), // bc table + collisions, // collision table + decay3bodys, // decay3body table + static_cast(nullptr), // MC particle table + static_cast(nullptr)); // MC collision table + } + + void processRealDataReduced3bodyMixing(aod::RedCollisions const&, + soa::Join const& decay3bodys, + aod::RedIUTracks const&) + { + auto xAxis = registry.get(HIST("Mixing/hDecay3BodyRadiusPhi"))->GetXaxis(); + auto yAxis = registry.get(HIST("Mixing/hDecay3BodyRadiusPhi"))->GetYaxis(); + + for (const auto& decay3body : decay3bodys) { + int bin_Radius, bin_Phi; + if (decay3bodyBuilderOpts.useKFParticle) { + bin_Radius = xAxis->FindBin(decay3body.radiusKF()); + bin_Phi = yAxis->FindBin(decay3body.phiKF()); + registry.fill(HIST("Mixing/hDecay3BodyPosZ"), decay3body.poszKF()); } else { - registry.fill(HIST("QA/Tracks/hTrackProtonTPCPID"), trackNeg.sign() * trackNeg.tpcInnerParam(), trackNeg.tpcNSigmaPr()); - registry.fill(HIST("QA/Tracks/hTrackPionTPCPID"), trackPos.sign() * trackPos.tpcInnerParam(), trackPos.tpcNSigmaPi()); - registry.fill(HIST("QA/Tracks/hTrackProtonPt"), trackNeg.pt()); - registry.fill(HIST("QA/Tracks/hTrackPionPt"), trackPos.pt()); + bin_Radius = xAxis->FindBin(decay3body.radiusDCA()); + bin_Phi = yAxis->FindBin(decay3body.phiDCA()); + registry.fill(HIST("Mixing/hDecay3BodyPosZ"), decay3body.poszDCA()); } - registry.fill(HIST("QA/Tracks/hTrackBachTPCPID"), trackBach.sign() * trackBach.tpcInnerParam(), trackBach.tpcNSigmaDe()); - registry.fill(HIST("QA/Tracks/hTrackBachPt"), trackBach.pt()); + registry.fill(HIST("Mixing/hDecay3BodyRadiusPhi"), xAxis->GetBinCenter(bin_Radius), yAxis->GetBinCenter(bin_Phi)); } - // -------- STEP 1: track selection -------- - // collision ID --> not correct? tracks can have different collisions, but belong to one 3prong vertex! - // if (trackPos.collisionId() != trackNeg.collisionId() || trackPos.collisionId() != trackBach.collisionId() || trackNeg.collisionId() != trackBach.collisionId()) { - // continue; - // } - // track IDs --> already checked in SVertexer! + if (decay3bodyBuilderOpts.useKFParticle) { + Binning3BodyKF binningOnRadPhiKF{{mixingOpts.bins3BodyRadius, mixingOpts.bins3BodyPhi}, true}; + buildMixedCandidates(decay3bodys, binningOnRadPhiKF); + } else { + Binning3BodyDCAfitter binningOnRadPhiDCA{{mixingOpts.bins3BodyRadius, mixingOpts.bins3BodyPhi}, true}; + buildMixedCandidates(decay3bodys, binningOnRadPhiDCA); + } + } - // track signs (pos, neg, bach) --> sanity check, should already be in SVertexer - if (trackPos.sign() != +1 || trackNeg.sign() != -1) { + void processMonteCarlo(ColswithEvTimesLabeled const& collisions, + aod::Decay3Bodys const& decay3bodys, + aod::Tracked3Bodys const& tracked3bodys, + TracksExtPIDIUwithEvTimesLabeled const&, + aod::BCsWithTimestamps const& bcs, + aod::McParticles const& mcParticles, + aod::McCollisions const& mcCollisions) + { + // initialise CCDB from BCs + if (!initCCDB(bcs, collisions)) { + LOG(info) << "CCDB initialisation failed, skipping candidate building." << std::endl; return; } - registry.fill(HIST("Counters/hVtx3BodyCounterKFParticle"), kKfVtxCharge); - // track eta - if (std::abs(trackPos.eta()) > kfparticleConfigurations.maxEta || std::abs(trackNeg.eta()) > kfparticleConfigurations.maxEta || std::abs(trackBach.eta()) > kfparticleConfigurations.maxEtaDeuteron) { - return; - } - registry.fill(HIST("Counters/hVtx3BodyCounterKFParticle"), kKfVtxEta); - - // number of TPC clusters - if (trackBach.tpcNClsFound() <= kfparticleConfigurations.mintpcNClsBach) { - return; - } - if (isMatter && ((kfparticleConfigurations.useTPCforPion && trackNeg.tpcNClsFound() <= kfparticleConfigurations.mintpcNClsPion) || trackPos.tpcNClsFound() <= kfparticleConfigurations.mintpcNClsProton)) { - return; - } else if (!isMatter && ((kfparticleConfigurations.useTPCforPion && trackPos.tpcNClsFound() <= kfparticleConfigurations.mintpcNClsPion) || trackNeg.tpcNClsFound() <= kfparticleConfigurations.mintpcNClsProton)) { - return; - } - registry.fill(HIST("Counters/hVtx3BodyCounterKFParticle"), kKfVtxTPCNcls); - - // number of TPC crossed rows - if (trackBach.tpcNClsCrossedRows() <= kfparticleConfigurations.mintpcCrossedRows) { - return; - } - if (isMatter && ((kfparticleConfigurations.useTPCforPion && trackNeg.tpcNClsCrossedRows() <= kfparticleConfigurations.mintpcCrossedRowsPion) || trackPos.tpcNClsCrossedRows() <= kfparticleConfigurations.mintpcCrossedRows)) { - return; - } else if (!isMatter && ((kfparticleConfigurations.useTPCforPion && trackPos.tpcNClsCrossedRows() <= kfparticleConfigurations.mintpcCrossedRowsPion) || trackNeg.tpcNClsCrossedRows() <= kfparticleConfigurations.mintpcCrossedRows)) { - return; - } - registry.fill(HIST("Counters/hVtx3BodyCounterKFParticle"), kKfVtxTPCRows); - - // TPC PID - float tpcNsigmaProton; - float tpcNsigmaPion; - float dEdxProton; - float dEdxPion; - float tpcNsigmaDeuteron = trackBach.tpcNSigmaDe(); - float tpcNsigmaPionBach = trackBach.tpcNSigmaPi(); - float dEdxDeuteron = trackBach.tpcSignal(); - if (isMatter) { // hypertriton (proton, pi-, deuteron) - tpcNsigmaProton = trackPos.tpcNSigmaPr(); - tpcNsigmaPion = trackNeg.tpcNSigmaPi(); - dEdxProton = trackPos.tpcSignal(); - dEdxPion = trackNeg.tpcSignal(); - if (!selectTPCPID(trackPos, trackNeg, trackBach)) { - return; - } - } else if (!isMatter) { // anti-hypertriton (anti-proton, pi+, deuteron) - tpcNsigmaProton = trackNeg.tpcNSigmaPr(); - tpcNsigmaPion = trackPos.tpcNSigmaPi(); - dEdxProton = trackNeg.tpcSignal(); - dEdxPion = trackPos.tpcSignal(); - if (!selectTPCPID(trackNeg, trackPos, trackBach)) { - return; - } - } - registry.fill(HIST("Counters/hVtx3BodyCounterKFParticle"), kKfVtxTPCPID); - LOG(debug) << "Basic track selections done."; - - // Average ITS cluster size of deuteron track - double averageClusterSizeDeuteron(0); - int nCls(0); - for (int i = 0; i < 7; i++) { - int clusterSize = trackBach.itsClsSizeInLayer(i); - averageClusterSizeDeuteron += static_cast(clusterSize); - if (clusterSize > 0) - nCls++; - } - averageClusterSizeDeuteron = averageClusterSizeDeuteron / static_cast(nCls); - - // track DCAxy and DCAz to PV associated with decay3body - o2::dataformats::VertexBase mPV; - o2::dataformats::DCA mDcaInfoCovPos; - o2::dataformats::DCA mDcaInfoCovNeg; - o2::dataformats::DCA mDcaInfoCovBach; - auto trackParCovPVPos = trackParCovPos; - auto trackParCovPVNeg = trackParCovNeg; - auto trackParCovPVBach = trackParCovBach; - mPV.setPos({collision.posX(), collision.posY(), collision.posZ()}); - mPV.setCov(collision.covXX(), collision.covXY(), collision.covYY(), collision.covXZ(), collision.covYZ(), collision.covZZ()); - o2::base::Propagator::Instance()->propagateToDCABxByBz(mPV, trackParCovPVPos, 2.f, matCorr, &mDcaInfoCovPos); - o2::base::Propagator::Instance()->propagateToDCABxByBz(mPV, trackParCovPVNeg, 2.f, matCorr, &mDcaInfoCovNeg); - o2::base::Propagator::Instance()->propagateToDCABxByBz(mPV, trackParCovPVBach, 2.f, matCorr, &mDcaInfoCovBach); - auto TrackPosDcaXY = mDcaInfoCovPos.getY(); - auto TrackNegDcaXY = mDcaInfoCovNeg.getY(); - auto TrackBachDcaXY = mDcaInfoCovBach.getY(); - auto TrackPosDcaZ = mDcaInfoCovPos.getZ(); - auto TrackNegDcaZ = mDcaInfoCovNeg.getZ(); - auto TrackBachDcaZ = mDcaInfoCovBach.getZ(); - // calculate 3D track DCA - auto TrackPosDca = std::sqrt(TrackPosDcaXY * TrackPosDcaXY + TrackPosDcaZ * TrackPosDcaZ); - auto TrackNegDca = std::sqrt(TrackNegDcaXY * TrackNegDcaXY + TrackNegDcaZ * TrackNegDcaZ); - auto TrackBachDca = std::sqrt(TrackBachDcaXY * TrackBachDcaXY + TrackBachDcaZ * TrackBachDcaZ); - // selection - if (kfparticleConfigurations.doDCAPreSel && isMatter && (std::fabs(TrackNegDcaXY) <= kfparticleConfigurations.mindcaXYPionPV || std::fabs(TrackPosDcaXY) <= kfparticleConfigurations.mindcaXYProtonPV)) { - return; - } else if (kfparticleConfigurations.doDCAPreSel && !isMatter && (std::fabs(TrackPosDcaXY) <= kfparticleConfigurations.mindcaXYPionPV || std::fabs(TrackNegDcaXY) <= kfparticleConfigurations.mindcaXYProtonPV)) { - return; - } - registry.fill(HIST("Counters/hVtx3BodyCounterKFParticle"), kKfVtxDCAxyPV); - if (kfparticleConfigurations.doDCAPreSel && isMatter && (std::fabs(TrackNegDcaZ) <= kfparticleConfigurations.mindcaZPionPV || std::fabs(TrackPosDcaZ) <= kfparticleConfigurations.mindcaZProtonPV)) { - return; - } else if (kfparticleConfigurations.doDCAPreSel && !isMatter && (std::fabs(TrackPosDcaZ) <= kfparticleConfigurations.mindcaZPionPV || std::fabs(TrackNegDcaZ) <= kfparticleConfigurations.mindcaZProtonPV)) { - return; - } - registry.fill(HIST("Counters/hVtx3BodyCounterKFParticle"), kKfVtxDCAzPV); - - // daughter track momentum at inner wall of TPC - float tpcInnerParamProton; - float tpcInnerParamPion; - float tpcInnerParamDeuteron = trackBach.tpcInnerParam(); - if (isMatter) { // hypertriton (proton, pi-, deuteron) - tpcInnerParamProton = trackPos.tpcInnerParam(); - tpcInnerParamPion = trackNeg.tpcInnerParam(); - } else if (!isMatter) { // anti-hypertriton (anti-proton, pi+, deuteron) - tpcInnerParamProton = trackNeg.tpcInnerParam(); - tpcInnerParamPion = trackPos.tpcInnerParam(); - } - - // -------- STEP 2: fit vertex with proton and pion -------- - // Fit vertex with DCA fitter to find minimization point --> uses material corrections implicitly - if (kfparticleConfigurations.doDCAFitterPreMinimum) { - try { - fitter3body.process(trackParCovPos, trackParCovNeg, trackParCovBach); - } catch (std::runtime_error& e) { - LOG(error) << "Exception caught in DCA fitter process call: Not able to fit decay3body vertex!"; - return; - } - // re-acquire tracks at vertex position from DCA fitter - trackParCovPos = fitter3body.getTrack(0); - trackParCovNeg = fitter3body.getTrack(1); - trackParCovBach = fitter3body.getTrack(2); - - LOG(debug) << "Minimum found with DCA fitter for decay3body."; - } - - // create KFParticle objects from tracks - KFParticle kfpProton, kfpPion; - if (isMatter) { - kfpProton = createKFParticleFromTrackParCov(trackParCovPos, trackPos.sign(), constants::physics::MassProton); - kfpPion = createKFParticleFromTrackParCov(trackParCovNeg, trackNeg.sign(), constants::physics::MassPionCharged); - } else if (!isMatter) { - kfpProton = createKFParticleFromTrackParCov(trackParCovNeg, trackNeg.sign(), constants::physics::MassProton); - kfpPion = createKFParticleFromTrackParCov(trackParCovPos, trackPos.sign(), constants::physics::MassPionCharged); - } - LOG(debug) << "KFParticle objects created from daughter tracks."; - - // Construct V0 as intermediate step - KFParticle KFV0; - int nDaughtersV0 = 2; - const KFParticle* DaughtersV0[2] = {&kfpProton, &kfpPion}; - KFV0.SetConstructMethod(2); - try { - KFV0.Construct(DaughtersV0, nDaughtersV0); - } catch (std::runtime_error& e) { - LOG(debug) << "Failed to create V0 vertex from daughter tracks." << e.what(); - return; - } - KFV0.TransportToDecayVertex(); - LOG(debug) << "V0 constructed."; - - // check V0 mass and set mass constraint - float massV0, sigmaMassV0; - KFV0.GetMass(massV0, sigmaMassV0); - KFParticle KFV0Mass = KFV0; - KFV0Mass.SetNonlinearMassConstraint(o2::constants::physics::MassLambda); - float chi2massV0 = KFV0Mass.GetChi2() / KFV0Mass.GetNDF(); - if (kfparticleConfigurations.useLambdaMassConstraint) { - LOG(debug) << "V0 mass constraint applied."; - KFV0 = KFV0Mass; - } - registry.fill(HIST("Counters/hVtx3BodyCounterKFParticle"), kKfVtxV0MassConst); - - // apply virtual V0 cuts used in SVertexer in case of 3body mixing with proton track - if (kfparticleConfigurations.mixingType == 1 && kfparticleConfigurations.applySVertexerV0Cuts) { - // V0 radius - if (std::sqrt(KFV0.GetX() * KFV0.GetX() + KFV0.GetY() * KFV0.GetY()) <= 0.5) { - return; - } - // pT - if (KFV0.GetPt() <= 0.01) { - return; - } - // pz/pT - if (KFV0.GetPz() / KFV0.GetPt() >= 2) { - return; - } - // cos(PA) - if (cpaXYFromKF(KFV0, kfpv) <= 0.9 || cpaFromKF(KFV0, kfpv) <= 0.8) { - return; - } - } - - // -------- STEP 3: fit three body vertex -------- - // Create KFParticle object from deuteron track - KFParticle kfpDeuteron; - kfpDeuteron = createKFParticleFromTrackParCov(trackParCovBach, trackBach.sign() * bachelorcharge, constants::physics::MassDeuteron); - LOG(debug) << "KFParticle created from deuteron track."; - - // Construct vertex - KFParticle KFHt; - fit3bodyVertex(kfpProton, kfpPion, kfpDeuteron, KFHt); - registry.fill(HIST("Counters/hVtx3BodyCounterKFParticle"), kKfVtxhasSV); - - // -------- STEP 4: daughter selections after geometrical vertex fit -------- - // daughter DCAs with KF - if ((kfpProton.GetDistanceFromParticle(kfpPion) >= kfparticleConfigurations.maxDcaProPi) || (kfpProton.GetDistanceFromParticle(kfpDeuteron) >= kfparticleConfigurations.maxDcaProDeu) || (kfpPion.GetDistanceFromParticle(kfpDeuteron) >= kfparticleConfigurations.maxDcaPiDe)) { - return; - } - float DCAvtxDaughters3D = kfpProton.GetDistanceFromParticle(kfpPion) + kfpProton.GetDistanceFromParticle(kfpDeuteron) + kfpPion.GetDistanceFromParticle(kfpDeuteron); - registry.fill(HIST("Counters/hVtx3BodyCounterKFParticle"), kKfVtxDcaDau); - LOG(debug) << "DCA selection after vertex fit applied."; - - // daughter DCAs to vertex - if (kfpProton.GetDistanceFromVertexXY(KFHt) >= kfparticleConfigurations.maxDcaXYSVDau || kfpPion.GetDistanceFromVertexXY(KFHt) >= kfparticleConfigurations.maxDcaXYSVDau || kfpDeuteron.GetDistanceFromVertexXY(KFHt) >= kfparticleConfigurations.maxDcaXYSVDau) { - return; - } - registry.fill(HIST("Counters/hVtx3BodyCounterKFParticle"), kKfVtxDcaDauVtx); - LOG(debug) << "DCA to vertex selection after vertex fit applied."; - - // daughter pT - if (kfpProton.GetPt() < kfparticleConfigurations.minPtProton || kfpProton.GetPt() > kfparticleConfigurations.maxPtProton || kfpPion.GetPt() < kfparticleConfigurations.minPtPion || kfpPion.GetPt() > kfparticleConfigurations.maxPtPion || kfpDeuteron.GetPt() < kfparticleConfigurations.minPtDeuteron || kfpDeuteron.GetPt() > kfparticleConfigurations.maxPtDeuteron) { - return; - } - registry.fill(HIST("Counters/hVtx3BodyCounterKFParticle"), kKfVtxDauPt); - LOG(debug) << "Daughter pT selection applied."; - - // -------- STEP 5: candidate selection and constraint after geometrical vertex fit -------- - // Rapidity - float rapHt = RecoDecay::y(std::array{KFHt.GetPx(), KFHt.GetPy(), KFHt.GetPz()}, o2::constants::physics::MassHyperTriton); - if (std::abs(rapHt) > kfparticleConfigurations.maxRapidityHt) { - return; - } - registry.fill(HIST("Counters/hVtx3BodyCounterKFParticle"), kKfVtxRap); - - // Pt selection - if (KFHt.GetPt() <= kfparticleConfigurations.minPtHt || KFHt.GetPt() >= kfparticleConfigurations.maxPtHt) { - return; - } - registry.fill(HIST("Counters/hVtx3BodyCounterKFParticle"), kKfVtxPt); - - // Mass window - float massHt, sigmaMassHt; - KFHt.GetMass(massHt, sigmaMassHt); - if (massHt <= kfparticleConfigurations.minMassHt || massHt >= kfparticleConfigurations.maxMassHt) { - return; - } - registry.fill(HIST("Counters/hVtx3BodyCounterKFParticle"), kKfVtxMass); - - // cos(PA) to PV - if (std::abs(cpaFromKF(KFHt, kfpv)) <= kfparticleConfigurations.minCosPA) { - return; - } - registry.fill(HIST("Counters/hVtx3BodyCounterKFParticle"), kKfVtxCosPA); - - // cos(PA) xy to PV - if (std::abs(cpaXYFromKF(KFHt, kfpv)) <= kfparticleConfigurations.minCosPAxy) { - return; - } - registry.fill(HIST("Counters/hVtx3BodyCounterKFParticle"), kKfVtxCosPAXY); - - // chi2 geometrical - float chi2geoNDF = KFHt.GetChi2() / KFHt.GetNDF(); - if (kfparticleConfigurations.applyTopoSel && chi2geoNDF >= kfparticleConfigurations.maxChi2geo) { - return; - } - registry.fill(HIST("Counters/hVtx3BodyCounterKFParticle"), kKfVtxChi2geo); - LOG(debug) << "Basic selections after vertex fit done."; - - // ctau before topo constraint - if (KFHt.GetLifeTime() > kfparticleConfigurations.maxctauHt) { - return; - } - - // Set vertex constraint and topological selection - KFParticle KFHtPV = KFHt; - try { - KFHtPV.SetProductionVertex(kfpv); - } catch (std::runtime_error& e) { - LOG(error) << "Exception caught KFParticle process call: Topological constraint failed"; - return; - } - registry.fill(HIST("Counters/hVtx3BodyCounterKFParticle"), kKfVtxTopoConstr); // to check if topo constraint fails - // get topological chi2 - float chi2topoNDF = KFHtPV.GetChi2() / KFHtPV.GetNDF(); - KFHtPV.TransportToDecayVertex(); - if (kfparticleConfigurations.applyTopoSel && chi2topoNDF >= kfparticleConfigurations.maxChi2topo) { - return; - } - registry.fill(HIST("Counters/hVtx3BodyCounterKFParticle"), kKfVtxChi2topo); - - // -------- STEP 6: collect and fill candidate info -------- - // get cluster size of strangeness tracked 3bodies - float trackedClSize; - if (decay3bodyID == -1) { - trackedClSize = 0; - } else { - trackedClSize = !fTrackedClSizeVector.empty() ? fTrackedClSizeVector[decay3bodyID] : 0; - } - - // candidate filling - kfCandidate candidate; - candidate.collisionID = collision.globalIndex(); - candidate.trackPosID = trackPos.globalIndex(); - candidate.trackNegID = trackNeg.globalIndex(); - candidate.trackBachID = trackBach.globalIndex(); - candidate.decay3bodyID = decay3bodyID; - // hypertriton - candidate.mass = massHt; - candidate.pos[0] = KFHt.GetX(); - candidate.pos[1] = KFHt.GetY(); - candidate.pos[2] = KFHt.GetZ(); - candidate.posErr[0] = KFHt.GetErrX(); - candidate.posErr[1] = KFHt.GetErrY(); - candidate.posErr[2] = KFHt.GetErrZ(); - candidate.mom[0] = KFHt.GetPx(); - candidate.mom[1] = KFHt.GetPy(); - candidate.mom[2] = KFHt.GetPz(); - candidate.mom[3] = KFHt.GetPt(); - candidate.momErr[0] = KFHt.GetErrPx(); - candidate.momErr[1] = KFHt.GetErrPy(); - candidate.momErr[2] = KFHt.GetErrPz(); - candidate.momErr[3] = KFHt.GetErrPt(); - candidate.charge = KFHt.GetQ(); - candidate.dcaToPV[0] = KFHt.GetDistanceFromVertex(kfpv); - candidate.dcaToPV[1] = KFHt.GetDistanceFromVertexXY(kfpv); - candidate.cpaToPV[0] = cpaFromKF(KFHt, kfpv); - candidate.cpaToPV[1] = cpaXYFromKF(KFHt, kfpv); - candidate.cpaToPVtopo[0] = cpaFromKF(KFHtPV, kfpv); - candidate.cpaToPVtopo[1] = cpaXYFromKF(KFHtPV, kfpv); - candidate.decLen[0] = KFHtPV.GetDecayLength(); - candidate.decLen[1] = KFHtPV.GetDecayLengthXY(); - candidate.ldl = KFHtPV.GetDecayLength() / KFHtPV.GetErrDecayLength(); - candidate.chi2geoNDF = chi2geoNDF; - candidate.chi2topoNDF = chi2topoNDF; - candidate.ctau = KFHtPV.GetLifeTime(); - candidate.trackedClSize = trackedClSize; - // V0 - candidate.massV0 = massV0; - candidate.chi2massV0 = chi2massV0; - candidate.cpaV0ToPV = cpaFromKF(KFV0, kfpv); - // daughter momenta - candidate.protonMom[0] = kfpProton.GetPx(); - candidate.protonMom[1] = kfpProton.GetPy(); - candidate.protonMom[2] = kfpProton.GetPz(); - candidate.pionMom[0] = kfpPion.GetPx(); - candidate.pionMom[1] = kfpPion.GetPy(); - candidate.pionMom[2] = kfpPion.GetPz(); - candidate.deuteronMom[0] = kfpDeuteron.GetPx(); - candidate.deuteronMom[1] = kfpDeuteron.GetPy(); - candidate.deuteronMom[2] = kfpDeuteron.GetPz(); - candidate.tpcInnerParam[0] = tpcInnerParamProton; - candidate.tpcInnerParam[1] = tpcInnerParamPion; - candidate.tpcInnerParam[2] = tpcInnerParamDeuteron; - // daughter DCAs with KF - candidate.DCAdaughterToPV[0] = kfpProton.GetDistanceFromVertex(kfpv); - candidate.DCAdaughterToPV[1] = kfpPion.GetDistanceFromVertex(kfpv); - candidate.DCAdaughterToPV[2] = kfpDeuteron.GetDistanceFromVertex(kfpv); - candidate.DCAdaughterToPVxy[0] = kfpProton.GetDistanceFromVertexXY(kfpv); - candidate.DCAdaughterToPVxy[1] = kfpPion.GetDistanceFromVertexXY(kfpv); - candidate.DCAdaughterToPVxy[2] = kfpDeuteron.GetDistanceFromVertexXY(kfpv); - candidate.DCAdaughterToSVxy[0] = kfpProton.GetDistanceFromVertexXY(KFHt); - candidate.DCAdaughterToSVxy[1] = kfpPion.GetDistanceFromVertexXY(KFHt); - candidate.DCAdaughterToSVxy[2] = kfpDeuteron.GetDistanceFromVertexXY(KFHt); - candidate.DCAprotonToPion = kfpProton.GetDistanceFromParticle(kfpPion); - candidate.DCAprotonToDeuteron = kfpProton.GetDistanceFromParticle(kfpDeuteron); - candidate.DCApionToDeuteron = kfpPion.GetDistanceFromParticle(kfpDeuteron); - candidate.DCAvtxDaughters3D = DCAvtxDaughters3D; - // daughter DCAs with material corrections - candidate.trackDCAxy[0] = TrackPosDcaXY; - candidate.trackDCAxy[1] = TrackNegDcaXY; - candidate.trackDCAxy[2] = TrackBachDcaXY; - candidate.trackDCA[0] = TrackPosDca; - candidate.trackDCA[1] = TrackNegDca; - candidate.trackDCA[2] = TrackBachDca; - // daughter signs - candidate.daughterCharge[0] = kfpProton.GetQ(); - candidate.daughterCharge[1] = kfpPion.GetQ(); - candidate.daughterCharge[2] = trackBach.sign(); - // daughter PID - candidate.tpcNsigma[0] = tpcNsigmaProton; - candidate.tpcNsigma[1] = tpcNsigmaPion; - candidate.tpcNsigma[2] = tpcNsigmaDeuteron; - candidate.tpcNsigma[3] = tpcNsigmaPionBach; - candidate.tpcdEdx[0] = dEdxProton; - candidate.tpcdEdx[1] = dEdxPion; - candidate.tpcdEdx[2] = dEdxDeuteron; - candidate.tofNsigmaDeuteron = tofNSigmaDeuteron; - candidate.averageClusterSizeDeuteron = averageClusterSizeDeuteron; - candidate.pidForTrackingDeuteron = trackBach.pidForTracking(); - - //------------------------------------------------------------------ - // table filling - fillCandidateTable(candidate); - LOG(debug) << "Table filled."; - - // fill event counter hist (has selected candidate) --> only filled once per vertex - registry.fill(HIST("Counters/hEventCounterKFParticle"), 3.5); - } // end buildVtx3BodyDataTableKFParticle - - //------------------------------------------------------------------ - void processRun3(ColwithEvTimes const& collisions, aod::Decay3Bodys const& decay3bodys, TrackExtPIDIUwithEvTimes const&, aod::BCsWithTimestamps const&) - { - VtxCandidates.clear(); - - registry.fill(HIST("hEventCounter"), 0.5, collisions.size()); - - for (const auto& d3body : decay3bodys) { - auto t0 = d3body.track0_as(); - auto t1 = d3body.track1_as(); - auto t2 = d3body.track2_as(); - auto collision = d3body.collision_as(); - auto bc = collision.bc_as(); - initCCDB(bc); - - // Recalculate the TOF PID - double tofNSigmaBach = -999; - if (t2.has_collision() && t2.hasTOF()) { - auto originalcol = t2.template collision_as(); - tofNSigmaBach = bachelorTOFPID.GetTOFNSigma(t2, originalcol, collision); - } - - fillVtxCand(collision, t0, t1, t2, d3body.globalIndex(), bachelorcharge, tofNSigmaBach); - } - } - PROCESS_SWITCH(decay3bodyBuilder, processRun3, "Produce DCA fitter decay3body tables", true); - - //------------------------------------------------------------------ - void processRun3Reduced(aod::RedCollisions const& collisions, aod::RedDecay3Bodys const& decay3bodys, aod::RedIUTracks const&) - { - VtxCandidates.clear(); - - registry.fill(HIST("hEventCounter"), 0.5, collisions.size()); - - for (const auto& d3body : decay3bodys) { - auto t0 = d3body.track0_as(); - auto t1 = d3body.track1_as(); - auto t2 = d3body.track2_as(); - auto collision = d3body.collision_as(); - - initCCDBfromRunNumber(collision.runNumber()); - fillVtxCand(collision, t0, t1, t2, d3body.globalIndex(), bachelorcharge, t2.tofNSigmaDe()); - } - } - PROCESS_SWITCH(decay3bodyBuilder, processRun3Reduced, "Produce DCA fitter decay3body tables with reduced data", false); - - //------------------------------------------------------------------ - // Event-mixing background - void processRun3ReducedEM(ReducedCollisionsMultsCents const& collisions, aod::RedDecay3Bodys const& decay3bodys, aod::RedIUTracks const&) - { - auto xAxis = registry.get(HIST("hEventPairs"))->GetXaxis(); - auto yAxis = registry.get(HIST("hEventPairs"))->GetYaxis(); - - // fill collisions counter - for (const auto& collision : collisions) { - int bin_PosZ = xAxis->FindBin(collision.posZ()); - int bin_Mult = yAxis->FindBin(collision.multNTracksPV()); - registry.fill(HIST("hEventCount"), xAxis->GetBinCenter(bin_PosZ), yAxis->GetBinCenter(bin_Mult)); - } - VtxCandidates.clear(); - - auto tuple = std::make_tuple(decay3bodys); - BinningTypeColEM binningEvent{{dcaFitterEMSel.binsVtxZ, dcaFitterEMSel.binsMultiplicity}, true}; - SameKindPair pair{binningEvent, dcaFitterEMSel.nUseMixed, -1, collisions, tuple, &cache}; - - for (const auto& [c0, decay3bodys0, c1, decay3bodys1] : pair) { - // LOG(info) << "Processing event mixing with collisions " << c0.globalIndex() << " and " << c1.globalIndex(); - initCCDBfromRunNumber(c0.runNumber()); - - int bin_PosZ = xAxis->FindBin(c0.posZ()); - int bin_Mult = yAxis->FindBin(c0.multNTracksPV()); - registry.fill(HIST("hEventPairs"), xAxis->GetBinCenter(bin_PosZ), yAxis->GetBinCenter(bin_Mult)); - - for (const auto& [d3body0, d3body1] : combinations(soa::CombinationsFullIndexPolicy(decay3bodys0, decay3bodys1))) { - - registry.fill(HIST("hDecay3BodyPairsBeforeCut"), xAxis->GetBinCenter(bin_PosZ), yAxis->GetBinCenter(bin_Mult)); - - auto tpos0 = d3body0.track0_as(); - auto tneg0 = d3body0.track1_as(); - auto tbach0 = d3body0.track2_as(); - auto tpos1 = d3body1.track0_as(); - auto tneg1 = d3body1.track1_as(); - auto tbach1 = d3body1.track2_as(); - - // try to fit the vertex for decay3body0 - auto Trackpos0 = getTrackParCov(tpos0); - auto Trackneg0 = getTrackParCov(tneg0); - auto Trackbach0 = getTrackParCov(tbach0); - int nVtx0 = fitter3body.process(Trackpos0, Trackneg0, Trackbach0); - if (nVtx0 == 0) { - continue; - ; - } - - if ((tbach0.sign() > 0 && !(tbach1.sign() > 0)) || (tbach0.sign() < 0 && !(tbach1.sign() < 0)) || tbach0.globalIndex() == tbach1.globalIndex()) { // only combine if tbach1 has correct sign and is not same as tbach0 - continue; - } - - const auto& vtx0XYZ = fitter3body.getPCACandidate(); - float rVtx0 = std::hypot(vtx0XYZ[0], vtx0XYZ[1]); - registry.fill(HIST("hRadius0"), rVtx0); - - std::array ppos0 = {0.}, pneg0 = {0.}, pbach0{0.}; - const auto& propagatedtpos0 = fitter3body.getTrack(0); - const auto& propagatedtneg0 = fitter3body.getTrack(1); - const auto& propagatedtbach0 = fitter3body.getTrack(2); - propagatedtpos0.getPxPyPzGlo(ppos0); - propagatedtneg0.getPxPyPzGlo(pneg0); - propagatedtbach0.getPxPyPzGlo(pbach0); - for (int i = 0; i < 3; i++) { - pbach0[i] *= bachelorcharge; - } - std::array p3B0 = {ppos0[0] + pneg0[0] + pbach0[0], ppos0[1] + pneg0[1] + pbach0[1], ppos0[2] + pneg0[2] + pbach0[2]}; - float phiVtx0 = std::atan2(p3B0[1], p3B0[0]); - - // try to fit the vertex for decay3body1 - auto Trackpos1 = getTrackParCov(tpos1); - auto Trackneg1 = getTrackParCov(tneg1); - auto Trackbach1 = getTrackParCov(tbach1); - int nVtx1 = fitter3body.process(Trackpos1, Trackneg1, Trackbach1); - if (nVtx1 == 0) { - continue; - } - - const auto& vtx1XYZ = fitter3body.getPCACandidate(); - float rVtx1 = std::hypot(vtx1XYZ[0], vtx1XYZ[1]); - registry.fill(HIST("hRadius1"), rVtx1); - - std::array ppos1 = {0.}, pneg1 = {0.}, pbach1{0.}; - const auto& propagatedtpos1 = fitter3body.getTrack(0); - const auto& propagatedtneg1 = fitter3body.getTrack(1); - const auto& propagatedtbach1 = fitter3body.getTrack(2); - propagatedtpos1.getPxPyPzGlo(ppos1); - propagatedtneg1.getPxPyPzGlo(pneg1); - propagatedtbach1.getPxPyPzGlo(pbach1); - for (int i = 0; i < 3; i++) { - pbach1[i] *= bachelorcharge; - } - std::array p3B1 = {ppos1[0] + pneg1[0] + pbach1[0], ppos1[1] + pneg1[1] + pbach1[1], ppos1[2] + pneg1[2] + pbach1[2]}; - float phiVtx1 = std::atan2(p3B1[1], p3B1[0]); - registry.fill(HIST("hPhi0"), phiVtx0 * o2::constants::math::Rad2Deg); - registry.fill(HIST("hPhi1"), phiVtx1 * o2::constants::math::Rad2Deg); - // convert deltaPhi to range [-pi, pi] - float deltaPhi = RecoDecay::constrainAngle(phiVtx1 - phiVtx0, -o2::constants::math::PI); - // check if radius and phi of the two vertices are compatible - registry.fill(HIST("hDeltaRadius"), rVtx1 - rVtx0); - registry.fill(HIST("hDeltaPhi"), deltaPhi * o2::constants::math::Rad2Deg); - if (std::abs(deltaPhi) * o2::constants::math::Rad2Deg > dcaFitterEMSel.maxDeltaPhiColMixing || std::abs(rVtx1 - rVtx0) > dcaFitterEMSel.maxDeltaRadiusColMixing) { - continue; - } - registry.fill(HIST("hDecay3BodyPairsAfterCut"), xAxis->GetBinCenter(bin_PosZ), yAxis->GetBinCenter(bin_Mult)); - - fillVtxCand(c0, tpos0, tneg0, tbach1, -1, bachelorcharge, tbach1.tofNSigmaDe()); - // initCCDBfromRunNumber(c1.runNumber()); - fillVtxCand(c1, tpos1, tneg1, tbach0, -1, bachelorcharge, tbach0.tofNSigmaDe()); - } - } - - // Aviod break of preslice in following workflow - /*std::sort(VtxCandidates.begin(), VtxCandidates.end(), [](const VtxCandidate a, const VtxCandidate b) { - return a.collisionId < b.collisionId; - });*/ - } - PROCESS_SWITCH(decay3bodyBuilder, processRun3ReducedEM, "Produce event-mixing background", false); - - void processRun3Reduced3bodyMixing(ReducedCollisionsMults const&, aod::RedIUTracks const&, soa::Join const& decay3bodys) - { - VtxCandidates.clear(); - - auto xAxis = registry.get(HIST("hDecay3BodyRadiusPhi"))->GetXaxis(); - auto yAxis = registry.get(HIST("hDecay3BodyRadiusPhi"))->GetYaxis(); - - for (const auto& decay3body : decay3bodys) { - int bin_Radius = xAxis->FindBin(decay3body.svRadius()); - int bin_Phi = yAxis->FindBin(decay3body.momPhi()); - registry.fill(HIST("hDecay3BodyRadiusPhi"), xAxis->GetBinCenter(bin_Radius), yAxis->GetBinCenter(bin_Phi)); - registry.fill(HIST("hDecay3BodyPosZ"), decay3body.svPosZ()); - } - - Binning3BodyDCAFitter binningOnRadiusPhi{{dcaFitterEMSel.bins3BodyRadius, dcaFitterEMSel.bins3BodyPhiDegree}, true}; - doMixed3Body(decay3bodys, binningOnRadiusPhi); - } - PROCESS_SWITCH(decay3bodyBuilder, processRun3Reduced3bodyMixing, "Produce mixing background directly from mixed decay3bodys based on DCAFitter Info", false); - - void processRun3Reduced3bodyMixingKFInfo(ReducedCollisionsMults const&, aod::RedIUTracks const&, soa::Join const& decay3bodys) - { - VtxCandidates.clear(); - - auto xAxis = registry.get(HIST("hDecay3BodyRadiusPhi"))->GetXaxis(); - auto yAxis = registry.get(HIST("hDecay3BodyRadiusPhi"))->GetYaxis(); - - for (const auto& decay3body : decay3bodys) { - int bin_Radius = xAxis->FindBin(decay3body.radius()); - int bin_Phi = yAxis->FindBin(decay3body.phi()); - registry.fill(HIST("hDecay3BodyRadiusPhi"), xAxis->GetBinCenter(bin_Radius), yAxis->GetBinCenter(bin_Phi)); - registry.fill(HIST("hDecay3BodyPosZ"), decay3body.posz()); - } - - Binning3BodyKFInfo binningOnRadiusPhi{{dcaFitterEMSel.bins3BodyRadius, dcaFitterEMSel.bins3BodyPhi}, true}; - doMixed3Body(decay3bodys, binningOnRadiusPhi); - } - PROCESS_SWITCH(decay3bodyBuilder, processRun3Reduced3bodyMixingKFInfo, "Produce mixing background directly from mixed decay3bodys based on KF Info", false); - - //------------------------------------------------------------------ - void processRun3withKFParticle(ColwithEvTimes const& collisions, TrackExtPIDIUwithEvTimes const&, aod::Decay3Bodys const& decay3bodys, aod::BCsWithTimestamps const&) - { - for (const auto& collision : collisions) { - - auto bc = collision.bc_as(); - initCCDB(bc); - LOG(debug) << "CCDB initialised."; - - // Zorro event counting - bool isZorroSelected = false; - if (kfparticleConfigurations.cfgSkimmedProcessing) { - isZorroSelected = zorro.isSelected(collision.template bc_as().globalBC()); - if (isZorroSelected) { - registry.fill(HIST("Counters/hEventCounterZorro"), 0.); - } else { - if (kfparticleConfigurations.cfgOnlyKeepInterestedTrigger) { - continue; - } - } - } - - // event selection - registry.fill(HIST("Counters/hEventCounterKFParticle"), 0.5); - if (kfparticleConfigurations.doSel8selection && !collision.sel8()) { - continue; - } - registry.fill(HIST("Counters/hEventCounterKFParticle"), 1.5); - if (kfparticleConfigurations.doPosZselection && (collision.posZ() >= 10.0f || collision.posZ() <= -10.0f)) { - continue; - } - registry.fill(HIST("Counters/hEventCounterKFParticle"), 2.5); - registry.fill(HIST("QA/Event/hAllSelEventsVtxZ"), collision.posZ()); - - if (isZorroSelected) { - registry.fill(HIST("Counters/hEventCounterZorro"), 1.); - } - - // slice Decay3Body table by collision - const uint64_t collIdx = collision.globalIndex(); - auto Decay3BodyTable_thisCollision = decay3bodys.sliceBy(perCollision, collIdx); - for (auto& vtx3body : Decay3BodyTable_thisCollision) { - auto trackPos = vtx3body.template track0_as(); - auto trackNeg = vtx3body.template track1_as(); - auto trackBach = vtx3body.template track2_as(); - buildVtx3BodyDataTableKFParticle(collision, trackPos, trackNeg, trackBach, vtx3body.globalIndex(), bachelorcharge, getTOFnSigma(collision, trackBach, false /*isEventMixing*/)); - LOG(debug) << "End of processKFParticle."; - } - } - } - PROCESS_SWITCH(decay3bodyBuilder, processRun3withKFParticle, "Produce KFParticle decay3body tables", false); - - void processRun3withKFParticleStrangenessTracking(ColwithEvTimes const& collisions, TrackExtPIDIUwithEvTimes const& tracks, aod::Decay3Bodys const& decay3bodys, aod::Tracked3Bodys const& tracked3bodys, aod::BCsWithTimestamps const& bcs) - { + // get tracked cluster size info fTrackedClSizeVector.clear(); fTrackedClSizeVector.resize(decay3bodys.size(), 0); for (const auto& tvtx3body : tracked3bodys) { fTrackedClSizeVector[tvtx3body.decay3BodyId()] = tvtx3body.itsClsSize(); } - processRun3withKFParticle(collisions, tracks, decay3bodys, bcs); - } - PROCESS_SWITCH(decay3bodyBuilder, processRun3withKFParticleStrangenessTracking, "Produce KFParticle strangeness tracked decay3body tables", false); - - void processRun3withKFParticleReduced(aod::RedCollisions const& collisions, aod::RedIUTracks const&, aod::RedDecay3Bodys const& decay3bodys) - { - int lastRunNumber = -1; - - for (const auto& collision : collisions) { - // set magnetic field only when run number changes - if (collision.runNumber() != lastRunNumber) { - initCCDBfromRunNumber(collision.runNumber()); - lastRunNumber = collision.runNumber(); // Update the last run number - LOG(debug) << "CCDB initialized for run " << lastRunNumber; - } - - // event selection - registry.fill(HIST("Counters/hEventCounterKFParticle"), 2.5); - registry.fill(HIST("QA/Event/hAllSelEventsVtxZ"), collision.posZ()); - - // slice Decay3Body table by collision - const uint64_t collIdx = collision.globalIndex(); - auto Decay3BodyTable_thisCollision = decay3bodys.sliceBy(perReducedCollision, collIdx); - for (auto& vtx3body : Decay3BodyTable_thisCollision) { - auto trackPos = vtx3body.template track0_as(); - auto trackNeg = vtx3body.template track1_as(); - auto trackBach = vtx3body.template track2_as(); - buildVtx3BodyDataTableKFParticle(collision, trackPos, trackNeg, trackBach, vtx3body.globalIndex(), bachelorcharge, trackBach.tofNSigmaDe()); - } - LOG(debug) << "End of processKFParticleDerived."; - } - } - PROCESS_SWITCH(decay3bodyBuilder, processRun3withKFParticleReduced, "Produce KFParticle decay3body tables from derived decay3body data", false); - - void processRun3withKFParticleReducedEM(ReducedCollisionsMults const& collisions, aod::RedIUTracks const&, aod::RedDecay3Bodys const& decay3bodys) - { - // ------------- Check number of events in bins -------------- - // Define a 2D array to count events and pairs per bin - std::vector> binEventCounts(10, std::vector(13, 0)); // 10 vtxZ bins, 13 multiplicity bins - std::vector> binPairCounts(10, std::vector(13, 0)); - - // Function to find bin index (returns -1 if out of range) - auto findBin = [](float value, const std::vector& binEdges) -> int { - for (size_t i = 0; i < binEdges.size() - 1; ++i) { - if (value > binEdges[i] && value <= binEdges[i + 1]) { - return i; - } - } - return -1; // Shouldn't happen if events are within range - }; - // Loop over all collisions to count them in bins - for (auto& collision : collisions) { - float vtxZ = collision.posZ(); - float mult = collision.multNTracksPV(); - - // Determine bin indices - int vtxZBin = findBin(vtxZ, {-10.0f, -8.f, -6.f, -4.f, -2.f, 0.f, 2.f, 4.f, 6.f, 8.f, 10.f}); - int multBin = findBin(mult, {0.0f, 1.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}); - - if (vtxZBin >= 0 && multBin >= 0) { - binEventCounts[vtxZBin][multBin]++; - } - } - // Print out the number of events per bin - LOG(info) << "Event count per bin (vtxZ, mult):"; - for (size_t i = 0; i < binEventCounts.size(); ++i) { - for (size_t j = 0; j < binEventCounts[i].size(); ++j) { - LOG(info) << "Bin (" << i << ", " << j << "): " << binEventCounts[i][j] << " events"; - } - } - // Fill histogram with numbers per bin - for (size_t i = 0; i < binEventCounts.size(); ++i) { - for (size_t j = 0; j < binEventCounts[i].size(); ++j) { - registry.fill(HIST("QA/EM/hEventBinCounts"), i, j, binEventCounts[i][j]); - } - } - LOG(info) << "Integral of hEventBinCounts:" << registry.get(HIST("QA/EM/hEventBinCounts"))->Integral(); - - // ------------- Check number of decay3bodys in bins ------------- - // Define a 2D array to count events and pairs per bin - std::vector> binDecay3BodyCounts(10, std::vector(13, 0)); // 10 vtxZ bins, 13 multiplicity bins - // Loop over all decay3bodys to count them in bins - for (auto& decay3body : decay3bodys) { - auto collision = decay3body.template collision_as(); - float vtx3bodyZ = collision.posZ(); - float mult3body = collision.multNTracksPV(); - - // Determine bin indices - int vtx3bodyZBin = findBin(vtx3bodyZ, {-10.0f, -8.f, -6.f, -4.f, -2.f, 0.f, 2.f, 4.f, 6.f, 8.f, 10.f}); - int mult3bodyBin = findBin(mult3body, {0.0f, 1.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}); - - if (vtx3bodyZBin >= 0 && mult3bodyBin >= 0) { - binDecay3BodyCounts[vtx3bodyZBin][mult3bodyBin]++; - } - } - // Print out the number of events per bin - LOG(debug) << "Event count per bin (vtxZ, mult):"; - for (size_t i = 0; i < binDecay3BodyCounts.size(); ++i) { - for (size_t j = 0; j < binDecay3BodyCounts[i].size(); ++j) { - LOG(debug) << "Bin (" << i << ", " << j << "): " << binDecay3BodyCounts[i][j] << " events"; - } - } - // Fill histogram with numbers per bin - for (size_t i = 0; i < binDecay3BodyCounts.size(); ++i) { - for (size_t j = 0; j < binDecay3BodyCounts[i].size(); ++j) { - registry.fill(HIST("QA/EM/h3bodyBinCounts"), i, j, binDecay3BodyCounts[i][j]); - } - } - LOG(info) << "Integral of h3bodyBinCounts:" << registry.get(HIST("QA/EM/h3bodyBinCounts"))->Integral(); - - // ------------- Do event mixing -------------- - auto tuple = std::make_tuple(decay3bodys); - BinningTypeKF binningOnPosAndMult{{kfparticleConfigurations.binsVtxZ, kfparticleConfigurations.binsMultiplicity}, true}; // ignore over-/underflow - SameKindPair pair{binningOnPosAndMult, kfparticleConfigurations.nEvtMixing, -1, collisions, tuple, &cache}; // indicates that under/overflow (-1) to be ignored - - int lastRunNumber = -1; - - for (auto& [c1, decays3body1, c2, decays3body2] : pair) { - registry.fill(HIST("QA/EM/hPairCounterMixing"), 0.5); - - // event selection already applied in reducer task - - // set magnetic field only when run number changes - if (c1.runNumber() != lastRunNumber) { - initCCDBfromRunNumber(c1.runNumber()); - lastRunNumber = c1.runNumber(); // Update the last run number - LOG(debug) << "CCDB initialized for run " << lastRunNumber; - } - - // Get vtxZ and multiplicity from collision - float vtxZpair = c1.posZ(); - float multpair = c1.multNTracksPV(); - // Find the bin index - int vtxZpairBin = findBin(vtxZpair, {-10.0f, -8.f, -6.f, -4.f, -2.f, 0.f, 2.f, 4.f, 6.f, 8.f, 10.f}); - int multpairBin = findBin(multpair, {0.0f, 1.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}); - if (vtxZpairBin >= 0 && multpairBin >= 0) { - binPairCounts[vtxZpairBin][multpairBin]++; // Count the pair - } - - for (auto& [decay3body1, decay3body2] : soa::combinations(soa::CombinationsFullIndexPolicy(decays3body1, decays3body2))) { - auto trackPos1 = decay3body1.template track0_as(); - auto trackNeg1 = decay3body1.template track1_as(); - auto trackBach1 = decay3body1.template track2_as(); - auto trackPos2 = decay3body2.template track0_as(); - auto trackNeg2 = decay3body2.template track1_as(); - auto trackBach2 = decay3body2.template track2_as(); - - registry.fill(HIST("QA/EM/hCombinationCounterMixing"), 0.5); - - // ---------- selections bachelor track ---------- - if ((trackBach1.sign() > 0 && !(trackBach2.sign() > 0)) || (trackBach1.sign() < 0 && !(trackBach2.sign() < 0)) || trackBach1.globalIndex() == trackBach2.globalIndex()) { // only combine if trackBach2 has correct sign and is not same as trackBach1 - continue; - } - registry.fill(HIST("QA/EM/hCombinationCounterMixing"), 1.5); - - // ---------- check radius and phi of decay3bodys ---------- - auto trackParCovPos1 = getTrackParCov(trackPos1); - auto trackParCovNeg1 = getTrackParCov(trackNeg1); - auto trackParCovBach1 = getTrackParCov(trackBach1); - auto trackParCovPos2 = getTrackParCov(trackPos2); - auto trackParCovNeg2 = getTrackParCov(trackNeg2); - auto trackParCovBach2 = getTrackParCov(trackBach2); - // create KFParticle objects from tracks - KFParticle kfpProton1, kfpPion1, kfpDeuteron1; - if (trackBach1.sign() > 0) { - kfpProton1 = createKFParticleFromTrackParCov(trackParCovPos1, trackPos1.sign(), constants::physics::MassProton); - kfpPion1 = createKFParticleFromTrackParCov(trackParCovNeg1, trackNeg1.sign(), constants::physics::MassPionCharged); - } else if (!(trackBach1.sign() > 0)) { - kfpProton1 = createKFParticleFromTrackParCov(trackParCovNeg1, trackNeg1.sign(), constants::physics::MassProton); - kfpPion1 = createKFParticleFromTrackParCov(trackParCovPos1, trackPos1.sign(), constants::physics::MassPionCharged); - } - kfpDeuteron1 = createKFParticleFromTrackParCov(trackParCovBach1, trackBach1.sign() * bachelorcharge, constants::physics::MassDeuteron); - KFParticle kfpProton2, kfpPion2, kfpDeuteron2; - if (trackBach2.sign() > 0) { - kfpProton2 = createKFParticleFromTrackParCov(trackParCovPos2, trackPos2.sign(), constants::physics::MassProton); - kfpPion2 = createKFParticleFromTrackParCov(trackParCovNeg2, trackNeg2.sign(), constants::physics::MassPionCharged); - } else if (!(trackBach2.sign() > 0)) { - kfpProton2 = createKFParticleFromTrackParCov(trackParCovNeg2, trackNeg2.sign(), constants::physics::MassProton); - kfpPion2 = createKFParticleFromTrackParCov(trackParCovPos2, trackPos2.sign(), constants::physics::MassPionCharged); - } - kfpDeuteron2 = createKFParticleFromTrackParCov(trackParCovBach2, trackBach2.sign() * bachelorcharge, constants::physics::MassDeuteron); - // fit vertices - KFParticle KFHt1, KFHt2; - fit3bodyVertex(kfpProton1, kfpPion1, kfpDeuteron1, KFHt1); - fit3bodyVertex(kfpProton2, kfpPion2, kfpDeuteron2, KFHt2); - - // ---------- select common radius and phi region ---------- - auto radius1 = std::sqrt(KFHt1.GetX() * KFHt1.GetX() + KFHt1.GetY() * KFHt1.GetY()); - auto radius2 = std::sqrt(KFHt2.GetX() * KFHt2.GetX() + KFHt2.GetY() * KFHt2.GetY()); - registry.fill(HIST("QA/EM/hRadius1"), radius1); - registry.fill(HIST("QA/EM/hRadius2"), radius2); - registry.fill(HIST("QA/EM/hPhi1"), KFHt1.GetPhi() * (180.0 / TMath::Pi())); - registry.fill(HIST("QA/EM/hPhi2"), KFHt2.GetPhi() * (180.0 / TMath::Pi())); - registry.fill(HIST("QA/EM/hDeltaRadius"), std::abs(radius1 - radius2)); - registry.fill(HIST("QA/EM/hDeltaPhi"), std::abs(KFHt1.GetPhi() - KFHt2.GetPhi()) * (180.0 / TMath::Pi())); - if (std::abs(KFHt1.GetPhi() - KFHt2.GetPhi()) * (180.0 / TMath::Pi()) > 10 || std::abs(radius1 - radius2) > 2) { - continue; - } - registry.fill(HIST("QA/EM/hCombinationCounterMixing"), 2.5); - - // fill 2D pair counter per bin - registry.fill(HIST("QA/EM/hPairBinCounts"), vtxZpairBin, multpairBin, 1); - - // ---------- do candidate analysis ---------- - buildVtx3BodyDataTableKFParticle(c1, trackPos1, trackNeg1, trackBach2, -1 /*vtx3bodyID*/, bachelorcharge, trackBach2.tofNSigmaDe()); - } // end decay3body combinations loop - } // end pairing loop - } // end process - PROCESS_SWITCH(decay3bodyBuilder, processRun3withKFParticleReducedEM, "Produce KFParticle event mixing decay3body tables from derived decay3body data", false); - - void processRun3withKFParticleReduced3bodyMixing(ReducedCollisionsMults const&, aod::RedIUTracks const&, soa::Join const& decay3bodys) - { - // Define a 2D array to count 3bodies per bin (radius, phi, posZ) - std::vector> bin3bodyCounts(16, std::vector(36, 0)); - - // Function to find bin index (returns -1 if out of range) - auto findBin = [](float value, const std::vector& binEdges) -> int { - for (size_t i = 0; i < binEdges.size() - 1; ++i) { - if (value > binEdges[i] && value <= binEdges[i + 1]) { - return i; - } - } - return -1; // Out of range - }; - - int counter = 0; - // Loop over all collisions to count them in bins - for (auto& decay3body : decay3bodys) { - counter++; - float radius = decay3body.radius(); - float phi = decay3body.phi(); - float posZ = decay3body.posz(); - - registry.fill(HIST("QA/EM/hRadius"), radius); - registry.fill(HIST("QA/EM/hPhi"), phi); - registry.fill(HIST("QA/EM/hPosZ"), posZ); - - // float degToRad = TMath::Pi()/180; - - // Determine bin indices - int radiusBin = findBin(radius, {0.0f, 0.5f, 1.0f, 1.5f, 2.0f, 3.0f, 4.0f, 6.0f, 8.0f, 10.0f, 12.0f, 14.0f, 16.0f, 18.0f, 20.0f, 30.0f, 1000.0}); - int phiBin = findBin(phi, {-180.0f * TMath::Pi() / 180, -160.0f * TMath::Pi() / 180, -140.0f * TMath::Pi() / 180, -120.0f * TMath::Pi() / 180, -100.0f * TMath::Pi() / 180, -80.0f * TMath::Pi() / 180, -60.0f * TMath::Pi() / 180, -40.0f * TMath::Pi() / 180, -20.0f * TMath::Pi() / 180, 0.0f, 20.0f * TMath::Pi() / 180, 40.0f * TMath::Pi() / 180, 60.0f * TMath::Pi() / 180, 80.0f * TMath::Pi() / 180, 100.0f * TMath::Pi() / 180, 120.0f * TMath::Pi() / 180, 140.0f * TMath::Pi() / 180, 160.0f * TMath::Pi() / 180, 180.0f * TMath::Pi() / 180}); - if (radiusBin >= 0 && phiBin >= 0) { // && posZBin >= 0) { - bin3bodyCounts[radiusBin][phiBin]++; //[posZBin]++; - } - } - LOG(info) << "3body counter: " << counter; - - // Print out the number of 3-body decays per bin - LOG(info) << "3body count per bin (radius, phi, posZ):"; - for (size_t i = 0; i < bin3bodyCounts.size(); ++i) { - for (size_t j = 0; j < bin3bodyCounts[i].size(); ++j) { - LOG(info) << "Bin (" << i << ", " << j << "): " << bin3bodyCounts[i][j] << " 3bodies"; - } - } - // Fill 3D histogram with numbers per bin - for (size_t i = 0; i < bin3bodyCounts.size(); ++i) { - for (size_t j = 0; j < bin3bodyCounts[i].size(); ++j) { - registry.fill(HIST("QA/EM/h3bodyBinCounts"), i, j, bin3bodyCounts[i][j]); - } - } - LOG(info) << "Integral of h3bodyBinCounts: " << registry.get(HIST("QA/EM/h3bodyBinCounts"))->Integral(); - - Binning3Body binningOnRadPhi{{kfparticleConfigurations.bins3BodyRadius, kfparticleConfigurations.bins3BodyPhi}, true}; - - // Strictly upper index policy for decay3body objects binned by radius, phi and z position - for (auto& [decay3body1, decay3body2] : selfPairCombinations(binningOnRadPhi, kfparticleConfigurations.nEvtMixing, -1, decay3bodys)) { - auto trackPos1 = decay3body1.template track0_as(); - auto trackNeg1 = decay3body1.template track1_as(); - auto trackBach1 = decay3body1.template track2_as(); - auto trackPos2 = decay3body2.template track0_as(); - auto trackNeg2 = decay3body2.template track1_as(); - auto trackBach2 = decay3body2.template track2_as(); - - registry.fill(HIST("QA/EM/h3bodyCombinationCounter"), 0.5); - - // collision vertex selections - auto collision1 = decay3body1.template collision_as(); - auto collision2 = decay3body2.template collision_as(); - initCCDBfromRunNumber(collision2.runNumber()); - initCCDBfromRunNumber(collision1.runNumber()); - - if (decay3body1.collisionId() == decay3body2.collisionId()) { // only combine if from different event - continue; - } - registry.fill(HIST("QA/EM/h3bodyCombinationCounter"), 1.5); - if (kfparticleConfigurations.selectVtxZ3bodyMixing && std::abs(collision1.posZ() - collision2.posZ()) > kfparticleConfigurations.VtxZBin3bodyMixing) { // only combine if collision similar in VtxZ - continue; - } - registry.fill(HIST("QA/EM/h3bodyCombinationCounter"), 2.5); - - // ---------- selections ---------- - if ((trackBach1.sign() > 0 && !(trackBach2.sign() > 0)) || (trackBach1.sign() < 0 && !(trackBach2.sign() < 0)) || trackBach1.globalIndex() == trackBach2.globalIndex()) { // only combine if trackBach2 has correct sign and is not same as trackBach1 - continue; - } - registry.fill(HIST("QA/EM/h3bodyCombinationCounter"), 3.5); - - // ---------- do candidate analysis ---------- - bool isMatter1 = false; - if (trackBach1.sign() > 0) { - isMatter1 = true; - } - if (kfparticleConfigurations.mixingType == 0) { // mix deuteron - buildVtx3BodyDataTableKFParticle(collision1, trackPos1, trackNeg1, trackBach2, -1 /*vtx3bodyID*/, bachelorcharge, trackBach2.tofNSigmaDe()); - buildVtx3BodyDataTableKFParticle(collision2, trackPos2, trackNeg2, trackBach1, -1 /*vtx3bodyID*/, bachelorcharge, trackBach1.tofNSigmaDe()); - } else if (kfparticleConfigurations.mixingType == 1) { // mix proton - if (isMatter1 == true) { - buildVtx3BodyDataTableKFParticle(collision1, trackPos2, trackNeg1, trackBach1, -1 /*vtx3bodyID*/, bachelorcharge, trackBach1.tofNSigmaDe()); - buildVtx3BodyDataTableKFParticle(collision2, trackPos1, trackNeg2, trackBach2, -1 /*vtx3bodyID*/, bachelorcharge, trackBach2.tofNSigmaDe()); - } else if (isMatter1 == false) { - buildVtx3BodyDataTableKFParticle(collision1, trackPos1, trackNeg2, trackBach1, -1 /*vtx3bodyID*/, bachelorcharge, trackBach1.tofNSigmaDe()); - buildVtx3BodyDataTableKFParticle(collision2, trackPos2, trackNeg1, trackBach2, -1 /*vtx3bodyID*/, bachelorcharge, trackBach2.tofNSigmaDe()); - } - } - } // end decay3body combinations loop - } - PROCESS_SWITCH(decay3bodyBuilder, processRun3withKFParticleReduced3bodyMixing, "Produce KFParticle mixed decay3body tables from derived decay3body data", false); -}; - -// build link from decay3body -> vtx3body -struct decay3bodyDataLinkBuilder { - Produces VtxDataLink; - - void init(InitContext const&) {} - - template - void buildDecay3BodyLabel(TDecay3Bodys const& decay3bodytable, TVtx3BodyDatas const& vtxdatatable) - { - std::vector lIndices; - lIndices.reserve(decay3bodytable.size()); - for (int ii = 0; ii < decay3bodytable.size(); ii++) - lIndices[ii] = -1; - for (const auto& vtxdata : vtxdatatable) { - if (vtxdata.decay3bodyId() != -1) { - lIndices[vtxdata.decay3bodyId()] = vtxdata.globalIndex(); - } - } - for (int ii = 0; ii < decay3bodytable.size(); ii++) { - VtxDataLink(lIndices[ii]); - } - } - - void processStandard(aod::Decay3Bodys const& decay3bodytable, aod::Vtx3BodyDatas const& vtxdatatable) - { - buildDecay3BodyLabel(decay3bodytable, vtxdatatable); - } - PROCESS_SWITCH(decay3bodyDataLinkBuilder, processStandard, "Produce label from decay3body to vtx3body", true); - - void processReduced(aod::RedDecay3Bodys const& decay3bodytable, aod::Vtx3BodyDatas const& vtxdatatable) - { - buildDecay3BodyLabel(decay3bodytable, vtxdatatable); - } - PROCESS_SWITCH(decay3bodyDataLinkBuilder, processReduced, "Produce label from reducedDecay3body to vtx3body", false); -}; - -struct kfdecay3bodyDataLinkBuilder { - Produces kfvtxdataLink; - - void init(InitContext const&) {} - - template - void buildDataLink(TDecay3Bodys const& decay3bodytable, TVtx3BodyDatas const& vtxdatatable) - { - std::vector lIndices; - lIndices.reserve(decay3bodytable.size()); - for (int ii = 0; ii < decay3bodytable.size(); ii++) - lIndices[ii] = -1; - for (auto& vtxdata : vtxdatatable) { - if (vtxdata.decay3bodyId() != -1) { - lIndices[vtxdata.decay3bodyId()] = vtxdata.globalIndex(); - } - } - for (int ii = 0; ii < decay3bodytable.size(); ii++) { - kfvtxdataLink(lIndices[ii]); - } - } - - void processStandard(aod::Decay3Bodys const& decay3bodytable, aod::KFVtx3BodyDatas const& vtxdatatable) - { - buildDataLink(decay3bodytable, vtxdatatable); // build Decay3Body -> KFDecay3BodyData link table - } - PROCESS_SWITCH(kfdecay3bodyDataLinkBuilder, processStandard, "Build data link table.", true); - - void processReduced(aod::RedDecay3Bodys const& decay3bodytable, aod::KFVtx3BodyDatas const& vtxdatatable) - { - buildDataLink(decay3bodytable, vtxdatatable); // build ReducedDecay3Body -> KFDecay3BodyData link table - } - PROCESS_SWITCH(kfdecay3bodyDataLinkBuilder, processReduced, "Build data link table for reduced data.", false); -}; - -struct decay3bodyLabelBuilder { - - Produces vtxlabels; - Produces vtxfulllabels; - - HistogramRegistry registry{"registry", {}}; - - void init(InitContext const&) - { - if (doprocessDoNotBuildLabels == false) { - auto hLabelCounter = registry.add("hLabelCounter", "hLabelCounter", HistType::kTH1D, {{3, 0.0f, 3.0f}}); - hLabelCounter->GetXaxis()->SetBinLabel(1, "Total"); - hLabelCounter->GetXaxis()->SetBinLabel(2, "Have Same MotherTrack"); - hLabelCounter->GetXaxis()->SetBinLabel(3, "True H3L"); - - registry.add("hHypertritonMCPt", "hHypertritonMCPt", HistType::kTH1F, {{100, 0.0f, 10.0f}}); - registry.add("hAntiHypertritonMCPt", "hAntiHypertritonMCPt", HistType::kTH1F, {{100, 0.0f, 10.0f}}); - registry.add("hHypertritonMCMass", "hHypertritonMCMass", HistType::kTH1F, {{40, 2.95f, 3.05f, "Inv. Mass (GeV/c^{2})"}}); - registry.add("hAntiHypertritonMCMass", "hAntiHypertritonMCMass", HistType::kTH1F, {{40, 2.95f, 3.05f, "Inv. Mass (GeV/c^{2})"}}); - registry.add("hHypertritonMCLifetime", "hHypertritonMCLifetime", HistType::kTH1F, {{50, 0.0f, 50.0f, "ct(cm)"}}); - registry.add("hAntiHypertritonMCLifetime", "hAntiHypertritonMCLifetime", HistType::kTH1F, {{50, 0.0f, 50.0f, "ct(cm)"}}); - } - } - - Configurable TpcPidNsigmaCut{"TpcPidNsigmaCut", 5, "TpcPidNsigmaCut"}; - - void processDoNotBuildLabels(aod::Decay3BodyDataLink const&) // is it possible to have none parameter? - { - // dummy process function - should not be required in the future - }; - PROCESS_SWITCH(decay3bodyLabelBuilder, processDoNotBuildLabels, "Do not produce MC label tables", true); - - void processBuildLabels(aod::Decay3BodysLinked const& decay3bodys, aod::Vtx3BodyDatas const& vtx3bodydatas, MCLabeledTracksIU const&, aod::McParticles const&) - { - std::vector lIndices; - lIndices.reserve(vtx3bodydatas.size()); - for (int ii = 0; ii < vtx3bodydatas.size(); ii++) { - lIndices[ii] = -1; - } - for (const auto& decay3body : decay3bodys) { - - int lLabel = -1; - int lPDG = -1; - float lPt = -1; - double MClifetime = -1; - bool is3bodyDecay = false; - int lGlobalIndex = -1; - - auto lTrack0 = decay3body.track0_as(); - auto lTrack1 = decay3body.track1_as(); - auto lTrack2 = decay3body.track2_as(); - registry.fill(HIST("hLabelCounter"), 0.5); - - // Association check - // There might be smarter ways of doing this in the future - if (!lTrack0.has_mcParticle() || !lTrack1.has_mcParticle() || !lTrack2.has_mcParticle()) { - vtxfulllabels(-1); - continue; - } - auto lMCTrack0 = lTrack0.mcParticle_as(); - auto lMCTrack1 = lTrack1.mcParticle_as(); - auto lMCTrack2 = lTrack2.mcParticle_as(); - if (!lMCTrack0.has_mothers() || !lMCTrack1.has_mothers() || !lMCTrack2.has_mothers()) { - vtxfulllabels(-1); - continue; - } - - for (const auto& lMother0 : lMCTrack0.mothers_as()) { - for (const auto& lMother1 : lMCTrack1.mothers_as()) { - for (const auto& lMother2 : lMCTrack2.mothers_as()) { - if (lMother0.globalIndex() == lMother1.globalIndex() && lMother0.globalIndex() == lMother2.globalIndex()) { - lGlobalIndex = lMother1.globalIndex(); - lPt = lMother1.pt(); - lPDG = lMother1.pdgCode(); - MClifetime = RecoDecay::sqrtSumOfSquares(lMCTrack2.vx() - lMother2.vx(), lMCTrack2.vy() - lMother2.vy(), lMCTrack2.vz() - lMother2.vz()) * o2::constants::physics::MassHyperTriton / lMother2.p(); // only for hypertriton - is3bodyDecay = true; // vtxs with the same mother - } - } - } - } // end association check - if (!is3bodyDecay) { - vtxfulllabels(-1); - continue; - } - registry.fill(HIST("hLabelCounter"), 1.5); - - // Intended for hypertriton cross-checks only - if (lPDG == 1010010030 && lMCTrack0.pdgCode() == 2212 && lMCTrack1.pdgCode() == -211 && lMCTrack2.pdgCode() == 1000010020) { - lLabel = lGlobalIndex; - double hypertritonMCMass = RecoDecay::m(std::array{std::array{lMCTrack0.px(), lMCTrack0.py(), lMCTrack0.pz()}, std::array{lMCTrack1.px(), lMCTrack1.py(), lMCTrack1.pz()}, std::array{lMCTrack2.px(), lMCTrack2.py(), lMCTrack2.pz()}}, std::array{o2::constants::physics::MassProton, o2::constants::physics::MassPionCharged, o2::constants::physics::MassDeuteron}); - registry.fill(HIST("hLabelCounter"), 2.5); - registry.fill(HIST("hHypertritonMCPt"), lPt); - registry.fill(HIST("hHypertritonMCLifetime"), MClifetime); - registry.fill(HIST("hHypertritonMCMass"), hypertritonMCMass); - } - if (lPDG == -1010010030 && lMCTrack0.pdgCode() == 211 && lMCTrack1.pdgCode() == -2212 && lMCTrack2.pdgCode() == -1000010020) { - lLabel = lGlobalIndex; - double antiHypertritonMCMass = RecoDecay::m(std::array{std::array{lMCTrack0.px(), lMCTrack0.py(), lMCTrack0.pz()}, std::array{lMCTrack1.px(), lMCTrack1.py(), lMCTrack1.pz()}, std::array{lMCTrack2.px(), lMCTrack2.py(), lMCTrack2.pz()}}, std::array{o2::constants::physics::MassPionCharged, o2::constants::physics::MassProton, o2::constants::physics::MassDeuteron}); - registry.fill(HIST("hLabelCounter"), 2.5); - registry.fill(HIST("hAntiHypertritonMCPt"), lPt); - registry.fill(HIST("hAntiHypertritonMCLifetime"), MClifetime); - registry.fill(HIST("hAntiHypertritonMCMass"), antiHypertritonMCMass); - } - - // Construct label table, only vtx which corresponds to true mother and true daughters with a specified order is labeled - // for matter: track0->p, track1->pi, track2->bachelor - // for antimatter: track0->pi, track1->p, track2->bachelor - vtxfulllabels(lLabel); - if (decay3body.vtx3BodyDataId() != -1) { - lIndices[decay3body.vtx3BodyDataId()] = lLabel; - } - } - for (int ii = 0; ii < vtx3bodydatas.size(); ii++) { - vtxlabels(lIndices[ii]); - } + // do candidate analysis with MC processing + buildCandidates(bcs, // bc table + collisions, // collision table + decay3bodys, // decay3body table + mcParticles, // MC particle table + mcCollisions); // MC collision table } - PROCESS_SWITCH(decay3bodyLabelBuilder, processBuildLabels, "Produce MC label tables", false); -}; -struct decay3bodyInitializer { - Spawns vtx3bodydatas; - void init(InitContext const&) {} + PROCESS_SWITCH(decay3bodyBuilder, processRealData, "process real data", true); + PROCESS_SWITCH(decay3bodyBuilder, processRealDataReduced, "process real reduced data", false); + PROCESS_SWITCH(decay3bodyBuilder, processRealDataReduced3bodyMixing, "process real reduced data", false); + PROCESS_SWITCH(decay3bodyBuilder, processMonteCarlo, "process monte carlo", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{ - adaptAnalysisTask(cfgc), - adaptAnalysisTask(cfgc), - adaptAnalysisTask(cfgc), - adaptAnalysisTask(cfgc), - }; + adaptAnalysisTask(cfgc)}; } diff --git a/PWGLF/TableProducer/Nuspex/hypertriton3bodyfinder.cxx b/PWGLF/TableProducer/Nuspex/hypertriton3bodyfinder.cxx deleted file mode 100644 index bad62accce2..00000000000 --- a/PWGLF/TableProducer/Nuspex/hypertriton3bodyfinder.cxx +++ /dev/null @@ -1,1197 +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. - -// This 3-body method is not recommended due to high cost of computing resources -// author: yuanzhe.wang@cern.ch - -#include -#include -#include -#include - -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.h" -#include "DCAFitter/DCAFitterN.h" -#include "ReconstructionDataFormats/Track.h" -#include "Common/Core/RecoDecay.h" -#include "Common/Core/trackUtilities.h" -#include "PWGLF/DataModel/LFStrangenessTables.h" -#include "PWGLF/DataModel/Vtx3BodyTables.h" -#include "Common/Core/TrackSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/Centrality.h" -#include "Common/DataModel/PIDResponse.h" -#include "EventFiltering/filterTables.h" - -#include "DetectorsBase/Propagator.h" -#include "DetectorsBase/GeometryManager.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "CCDB/BasicCCDBManager.h" - -using namespace o2; -using namespace o2::framework; -using namespace o2::framework::expressions; -using std::array; - -using FullTracksExtIU = soa::Join; -using MCLabeledTracksIU = soa::Join; - -template -bool is3bodyDecayedH3L(TMCParticle const& particle) -{ - if (particle.pdgCode() != 1010010030 && particle.pdgCode() != -1010010030) { - return false; - } - bool haveProton = false, havePionPlus = false, haveDeuteron = false; - bool haveAntiProton = false, havePionMinus = false, haveAntiDeuteron = false; - for (auto& mcparticleDaughter : particle.template daughters_as()) { - if (mcparticleDaughter.pdgCode() == 2212) - haveProton = true; - if (mcparticleDaughter.pdgCode() == -2212) - haveAntiProton = true; - if (mcparticleDaughter.pdgCode() == 211) - havePionPlus = true; - if (mcparticleDaughter.pdgCode() == -211) - havePionMinus = true; - if (mcparticleDaughter.pdgCode() == 1000010020) - haveDeuteron = true; - if (mcparticleDaughter.pdgCode() == -1000010020) - haveAntiDeuteron = true; - } - if (haveProton && havePionMinus && haveDeuteron && particle.pdgCode() == 1010010030) { - return true; - } else if (haveAntiProton && havePionPlus && haveAntiDeuteron && particle.pdgCode() == -1010010030) { - return true; - } - return false; -} - -namespace o2::aod -{ -namespace v0goodpostrack -{ -DECLARE_SOA_INDEX_COLUMN_FULL(GoodTrack, goodTrack, int, Tracks, "_GoodTrack"); -DECLARE_SOA_INDEX_COLUMN(Collision, collision); -} // namespace v0goodpostrack -DECLARE_SOA_TABLE(V0GoodPosTracks, "AOD", "V0GOODPOSTRACKS", o2::soa::Index<>, v0goodpostrack::GoodTrackId, v0goodpostrack::CollisionId); -namespace v0goodnegtrack -{ -DECLARE_SOA_INDEX_COLUMN_FULL(GoodTrack, goodTrack, int, Tracks, "_GoodTrack"); -DECLARE_SOA_INDEX_COLUMN(Collision, collision); -} // namespace v0goodnegtrack -DECLARE_SOA_TABLE(V0GoodNegTracks, "AOD", "V0GOODNEGTRACKS", o2::soa::Index<>, v0goodnegtrack::GoodTrackId, v0goodnegtrack::CollisionId); -namespace v0goodtrack -{ -DECLARE_SOA_INDEX_COLUMN_FULL(GoodTrack, goodTrack, int, Tracks, "_GoodTrack"); -DECLARE_SOA_INDEX_COLUMN(Collision, collision); -} // namespace v0goodtrack -DECLARE_SOA_TABLE(V0GoodTracks, "AOD", "V0GOODTRACKS", o2::soa::Index<>, v0goodtrack::GoodTrackId, v0goodtrack::CollisionId); -} // namespace o2::aod - -struct trackprefilter { - HistogramRegistry registry{ - "registry", - { - {"hCrossedRows", "hCrossedRows", {HistType::kTH1F, {{50, 0.0f, 200.0f}}}}, - {"hGoodTrackCount", "hGoodTrackCount", {HistType::kTH1F, {{4, 0.0f, 4.0f}}}}, - {"hGoodPosTrackCount", "hGoodPosTrackCount", {HistType::kTH1F, {{1, 0.0f, 1.0f}}}}, - {"hGoodNegTrackCount", "hGoodNegTrackCount", {HistType::kTH1F, {{1, 0.0f, 1.0f}}}}, - {"h3bodyCounter", "h3bodyCounter", {HistType::kTH1F, {{6, 0.0f, 6.0f}}}}, - }, - }; - - // change the dca cut for helium3 - Configurable mintpcNCls{"mintpcNCls", 70, "min tpc Nclusters"}; - Configurable tpcrefit{"tpcrefit", 0, "demand TPC refit"}; - - Produces v0GoodPosTracks; - Produces v0GoodNegTracks; - Produces v0GoodTracks; - - // Fix: Add PID and pt cuts to tracks - void processDefault(aod::Collision const& /*collision*/, - FullTracksExtIU const& tracks) - { - for (auto& t0 : tracks) { - registry.fill(HIST("hGoodTrackCount"), 0.5); - registry.fill(HIST("hCrossedRows"), t0.tpcNClsCrossedRows()); - if (tpcrefit) { - if (!(t0.trackType() & o2::aod::track::TPCrefit)) { - continue; // TPC refit - } - } - registry.fill(HIST("hGoodTrackCount"), 1.5); - if (t0.tpcNClsFound() < mintpcNCls) { - continue; - } - registry.fill(HIST("hGoodTrackCount"), 2.5); - if (t0.signed1Pt() > 0.0f) { - v0GoodPosTracks(t0.globalIndex(), t0.collisionId()); - registry.fill(HIST("hGoodPosTrackCount"), 0.5); - registry.fill(HIST("hGoodTrackCount"), 3.5); - } - if (t0.signed1Pt() < 0.0f) { - v0GoodNegTracks(t0.globalIndex(), t0.collisionId()); - registry.fill(HIST("hGoodNegTrackCount"), 0.5); - registry.fill(HIST("hGoodTrackCount"), 3.5); - } - v0GoodTracks(t0.globalIndex(), t0.collisionId()); - } - } - PROCESS_SWITCH(trackprefilter, processDefault, "Default process function", true); - - // process function for MC d3body check - // void processCheck(aod::Collision const& collision, aod::Decay3Bodys const& decay3bodys, - void processCheck(aod::Decay3Bodys const& decay3bodys, - MCLabeledTracksIU const& /*tracks*/, aod::McParticles const& /*particlesMC*/) - { - for (auto& d3body : decay3bodys) { - registry.fill(HIST("h3bodyCounter"), 0.5); - auto lTrack0 = d3body.track0_as(); - auto lTrack1 = d3body.track1_as(); - auto lTrack2 = d3body.track2_as(); - if (!lTrack0.has_mcParticle() || !lTrack1.has_mcParticle() || !lTrack2.has_mcParticle()) { - continue; - } - registry.fill(HIST("h3bodyCounter"), 1.5); - auto lMCTrack0 = lTrack0.mcParticle_as(); - auto lMCTrack1 = lTrack1.mcParticle_as(); - auto lMCTrack2 = lTrack2.mcParticle_as(); - if (!lMCTrack0.has_mothers() || !lMCTrack1.has_mothers() || !lMCTrack2.has_mothers()) { - continue; - } - registry.fill(HIST("h3bodyCounter"), 2.5); - - int lPDG = -1; - bool is3bodyDecay = false; - for (auto& lMother0 : lMCTrack0.mothers_as()) { - for (auto& lMother1 : lMCTrack1.mothers_as()) { - for (auto& lMother2 : lMCTrack2.mothers_as()) { - if (lMother0.globalIndex() == lMother1.globalIndex() && lMother0.globalIndex() == lMother2.globalIndex()) { - lPDG = lMother1.pdgCode(); - if (lPDG == 1010010030 && lMCTrack0.pdgCode() == 2212 && lMCTrack1.pdgCode() == -211 && lMCTrack2.pdgCode() == 1000010020) { - is3bodyDecay = true; // vtxs with the same mother - } - if (lPDG == -1010010030 && lMCTrack0.pdgCode() == 211 && lMCTrack1.pdgCode() == -2212 && lMCTrack2.pdgCode() == -1000010020) { - is3bodyDecay = true; // vtxs with the same mother - } - } - } - } - } // end association check - - if (!is3bodyDecay || std::abs(lPDG) != 1010010030) { - continue; - } - registry.fill(HIST("h3bodyCounter"), 3.5); - if (lTrack0.collisionId() != lTrack1.collisionId() || lTrack0.collisionId() != lTrack2.collisionId()) { - continue; - } - registry.fill(HIST("h3bodyCounter"), 4.5); - - if (lTrack0.collisionId() != d3body.collisionId()) { - continue; - } - registry.fill(HIST("h3bodyCounter"), 5.5); - - // LOG(info) << "; Track0ID: " << lTrack0.globalIndex() << "; Track1ID:" << lTrack1.globalIndex() << "; Track2ID:" << lTrack2.globalIndex(); - v0GoodPosTracks(lTrack0.globalIndex(), lTrack0.collisionId()); - v0GoodNegTracks(lTrack1.globalIndex(), lTrack1.collisionId()); - v0GoodTracks(lTrack2.globalIndex(), lTrack2.collisionId()); - } - } - PROCESS_SWITCH(trackprefilter, processCheck, "Check specific paired tracks", false); -}; - -struct hypertriton3bodyFinder { - - Produces vtx3bodydata; - Service ccdb; - - // Configurables - Configurable UseCFFilter{"UseCFFilter", true, "Reject event without CF LD trigger"}; - Configurable RejectBkgInMC{"RejectBkgInMC", false, "Reject fake 3-body pairs in MC check"}; - - Configurable d_UseAbsDCA{"d_UseAbsDCA", true, "Use Abs DCAs"}; - Configurable d_bz_input{"d_bz", -999, "bz field, -999 is automatic"}; - - // Selection criteria - Configurable minRToMeanVertex = {"minRToMeanVertex", 0.5, ""}; ///< min radial distance of V0 from beam line (mean vertex) - // Configurable causalityRTolerance = {"causalityRTolerance", 1., ""}; ///< V0 radius cannot exceed its contributors minR by more than this value - Configurable maxV0ToProngsRDiff = {"maxV0ToProngsRDiff", 50., ""}; ///< V0 radius cannot be lower than this ammount wrt minR of contributors - Configurable minPtV0 = {"minPtV0", 0.5, ""}; ///< v0 minimum pT - Configurable maxTglV0 = {"maxTglV0", 2., ""}; ///< maximum tgLambda of V0 - Configurable maxDCAXY2ToMeanVertex3bodyV0 = {"maxDCAXY2ToMeanVertex3bodyV0", 2 * 2, ""}; - Configurable minCosPAXYMeanVertex3bodyV0 = {"minCosPAXYMeanVertex3bodyV0", 0.9, ""}; ///< min cos of PA to beam line (mean vertex) in tr. plane for 3body V0 cand. - Configurable minCosPA3bodyV0 = {"minCosPA3bodyV0", 0.8, ""}; // min cos of PA to PV for 3body V0 - - // for 3 body reconstructed Vertex - Configurable minbachPt = {"minbachPt", 0.6, ""}; ///< Minimum bachelor Pt - Configurable maxRDiff3bodyV0 = {"maxRDiff3bodyV0", 3, ""}; ///< Maximum difference between V0 and 3body radii - Configurable minPt3Body = {"minPt3Body", 0.01, ""}; // minimum pT of 3body Vertex - Configurable maxTgl3Body = {"maxTgl3Body", 2, ""}; // maximum tgLambda of 3body Vertex - Configurable minCosPA3body = {"minCosPA3body", 0.8, ""}; // min cos of PA to PV for 3body Vertex - - // for DCA - Configurable dcavtxdau{"dcavtxdau", 2.0, "DCA Vtx Daughters"}; - Configurable d_UseH3LDCACut{"d_UseH3LDCACut", true, "Use Cuts for H3L DCA to PV"}; - Configurable maxDCAXY3Body{"maxDCAXY3Body", 0.5, "DCAXY H3L to PV"}; // max DCA of 3 body decay to PV in XY - Configurable maxDCAZ3Body{"maxDCAZ3Body", 1.0, "DCAZ H3L to PV"}; // max DCA of 3 body decay to PV in Z - - Configurable useMatCorrType{"useMatCorrType", 2, "0: none, 1: TGeo, 2: LUT"}; - // CCDB options - 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 geoPath{"geoPath", "GLO/Config/GeometryAligned", "Path of the geometry file"}; - - Preslice perCollisionGoodPosTracks = o2::aod::v0goodpostrack::collisionId; - Preslice perCollisionGoodNegTracks = o2::aod::v0goodnegtrack::collisionId; - Preslice perCollisionGoodTracks = o2::aod::v0goodtrack::collisionId; - Preslice perCollisionV0s = o2::aod::v0::collisionId; - Preslice perCollisionV0Datas = o2::aod::v0data::collisionId; - - // Helper struct to pass V0 information - HistogramRegistry registry{ - "registry", - { - {"hEventCounter", "hEventCounter", {HistType::kTH1F, {{2, 0.0f, 2.0f}}}}, - {"hDauTrackCounter", "hDauTrackCounter", {HistType::kTH1F, {{3, 0.0f, 3.0f}}}}, - {"hV0Counter", "hV0Counter", {HistType::kTH1F, {{8, -0.5f, 7.5f}}}}, - {"hTrueV0Counter", "hTrueV0Counter", {HistType::kTH1F, {{8, -0.5f, 7.5f}}}}, - {"hVtx3BodyCounter", "hVtx3BodyCounter", {HistType::kTH1F, {{9, -0.5f, 8.5f}}}}, - {"hTrueVtx3BodyCounter", "hTrueVtx3BodyCounter", {HistType::kTH1F, {{9, -0.5f, 8.5f}}}}, - {"hVirtLambaCounter", "hVirtualLambaCounter", {HistType::kTH1F, {{6, -0.5f, 5.5f}}}}, - {"hCFFilteredVirtLambaCounter", "hCFFilteredVirtLambaCounter", {HistType::kTH1F, {{6, -0.5f, 5.5f}}}}, - }, - }; - - //------------------------------------------------------------------ - // Fill stats histograms - enum v0step { kV0All = 0, - kV0hasSV, - kV0Radius, - kV0Pt, - kV0TgLamda, - kV0InvMass, - kV0DcaXY, - kV0CosPA, - kNV0Steps }; - enum vtxstep { kVtxAll = 0, - kVtxbachPt, - kVtxhasSV, - kVtxRadius, - kVtxPt, - kVtxTgLamda, - kVtxCosPA, - kVtxDcaDau, - kVtxDcaH3L, - kNVtxSteps }; - - // Helper struct to do bookkeeping of building parameters - struct { - std::array v0stats; - std::array truev0stats; - std::array vtxstats; - std::array truevtxstats; - std::array virtLambdastats; - } statisticsRegistry; - - void resetHistos() - { - for (Int_t ii = 0; ii < kNV0Steps; ii++) { - statisticsRegistry.v0stats[ii] = 0; - statisticsRegistry.truev0stats[ii] = 0; - } - for (Int_t ii = 0; ii < kNVtxSteps; ii++) { - statisticsRegistry.vtxstats[ii] = 0; - statisticsRegistry.truevtxstats[ii] = 0; - } - for (Int_t ii = 0; ii < 12; ii++) { - statisticsRegistry.virtLambdastats[ii] = 0; - } - } - - void fillHistos() - { - for (Int_t ii = 0; ii < kNV0Steps; ii++) { - registry.fill(HIST("hV0Counter"), ii, statisticsRegistry.v0stats[ii]); - registry.fill(HIST("hTrueV0Counter"), ii, statisticsRegistry.truev0stats[ii]); - } - for (Int_t ii = 0; ii < kNVtxSteps; ii++) { - registry.fill(HIST("hVtx3BodyCounter"), ii, statisticsRegistry.vtxstats[ii]); - registry.fill(HIST("hTrueVtx3BodyCounter"), ii, statisticsRegistry.truevtxstats[ii]); - } - for (Int_t ii = 0; ii < 3; ii++) { - registry.fill(HIST("hVirtLambaCounter"), ii, statisticsRegistry.virtLambdastats[ii]); - registry.fill(HIST("hVirtLambaCounter"), ii + 3, statisticsRegistry.virtLambdastats[ii + 3]); - registry.fill(HIST("hCFFilteredVirtLambaCounter"), ii, statisticsRegistry.virtLambdastats[ii + 6]); - registry.fill(HIST("hCFFilteredVirtLambaCounter"), ii + 3, statisticsRegistry.virtLambdastats[ii + 9]); - } - } - - // v0, vtx, and virtual Lambda statiscs - void FillV0Counter(int kn, bool istrue = false) - { - statisticsRegistry.v0stats[kn]++; - if (istrue) { - statisticsRegistry.truev0stats[kn]++; - } - } - void FillVtxCounter(int kn, bool istrue = false) - { - statisticsRegistry.vtxstats[kn]++; - if (istrue) { - statisticsRegistry.truevtxstats[kn]++; - } - } - //------------------------------------------------------------------ - - int mRunNumber; - float d_bz; - float maxSnp; // max sine phi for propagation - float maxStep; // max step size (cm) for propagation - o2::base::MatLayerCylSet* lut = nullptr; - o2::vertexing::DCAFitterN<2> fitter; - o2::vertexing::DCAFitterN<3> fitter3body; - - void init(InitContext&) - { - resetHistos(); - mRunNumber = 0; - d_bz = 0; - maxSnp = 0.85f; // could be changed later - maxStep = 2.00f; // could be changed later - - TString DauCounterbinLabel[3] = {"Proton", "Pion", "Deuteron"}; - TString V0CounterbinLabel[8] = {"Total", "hasSV", "V0R", "V0Pt", "TgLambda", "V0Mass", "DcaXY", "CosPA"}; - TString VtxCounterbinLabel[9] = {"Total", "bachPt", "hasSV", "VtxR", "VtxPt", "TgLambda", "CosPA", "DcaDau", "DcaH3L"}; - for (int i{0}; i < 3; i++) { - registry.get(HIST("hDauTrackCounter"))->GetXaxis()->SetBinLabel(i + 1, DauCounterbinLabel[i]); - } - for (int i{0}; i < kNV0Steps; i++) { - registry.get(HIST("hV0Counter"))->GetXaxis()->SetBinLabel(i + 1, V0CounterbinLabel[i]); - registry.get(HIST("hTrueV0Counter"))->GetXaxis()->SetBinLabel(i + 1, V0CounterbinLabel[i]); - } - for (int i{0}; i < kNVtxSteps; i++) { - registry.get(HIST("hVtx3BodyCounter"))->GetXaxis()->SetBinLabel(i + 1, VtxCounterbinLabel[i]); - registry.get(HIST("hTrueVtx3BodyCounter"))->GetXaxis()->SetBinLabel(i + 1, VtxCounterbinLabel[i]); - } - - ccdb->setURL(ccdburl); - ccdb->setCaching(true); - ccdb->setLocalObjectValidityChecking(); - ccdb->setFatalWhenNull(false); - - // Set 2-body fitter and 3-body fitter3body - fitter.setPropagateToPCA(true); - fitter.setMaxR(200.); //->maxRIni3body - fitter.setMinParamChange(1e-3); - fitter.setMinRelChi2Change(0.9); - fitter.setMaxDZIni(1e9); - fitter.setMaxChi2(1e9); - fitter.setUseAbsDCA(d_UseAbsDCA); - fitter3body.setPropagateToPCA(true); - fitter3body.setMaxR(200.); //->maxRIni3body - fitter3body.setMinParamChange(1e-3); - fitter3body.setMinRelChi2Change(0.9); - fitter3body.setMaxDZIni(1e9); - fitter3body.setMaxChi2(1e9); - fitter3body.setUseAbsDCA(d_UseAbsDCA); - - // Material correction in the DCA fitter - o2::base::Propagator::MatCorrType matCorr = o2::base::Propagator::MatCorrType::USEMatCorrNONE; - if (useMatCorrType == 1) { - LOGF(info, "TGeo correction requested, loading geometry"); - if (!o2::base::GeometryManager::isGeometryLoaded()) { - ccdb->get(geoPath); - } - matCorr = o2::base::Propagator::MatCorrType::USEMatCorrTGeo; - } - if (useMatCorrType == 2) { - LOGF(info, "LUT correction requested, loading LUT"); - lut = o2::base::MatLayerCylSet::rectifyPtrFromFile(ccdb->get(lutPath)); - matCorr = o2::base::Propagator::MatCorrType::USEMatCorrLUT; - } - fitter.setMatCorrType(matCorr); - fitter3body.setMatCorrType(matCorr); - } - - void initCCDB(aod::BCsWithTimestamps::iterator const& bc) - { - if (mRunNumber == bc.runNumber()) { - return; - } - - // In case override, don't proceed, please - no CCDB access required - if (d_bz_input > -990) { - d_bz = d_bz_input; - fitter.setBz(d_bz); - fitter3body.setBz(d_bz); - o2::parameters::GRPMagField grpmag; - if (fabs(d_bz) > 1e-5) { - grpmag.setL3Current(30000.f / (d_bz / 5.0f)); - } - o2::base::Propagator::initFieldFromGRP(&grpmag); - mRunNumber = bc.runNumber(); - return; - } - - auto run3grp_timestamp = bc.timestamp(); - o2::parameters::GRPObject* grpo = ccdb->getForTimeStamp(grpPath, run3grp_timestamp); - o2::parameters::GRPMagField* grpmag = 0x0; - if (grpo) { - o2::base::Propagator::initFieldFromGRP(grpo); - // 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(grpmagPath, run3grp_timestamp); - if (!grpmag) { - LOG(fatal) << "Got nullptr from CCDB for path " << grpmagPath << " of object GRPMagField and " << grpPath << " of object GRPObject for timestamp " << run3grp_timestamp; - } - o2::base::Propagator::initFieldFromGRP(grpmag); - // 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(); - // Set magnetic field value once known - fitter.setBz(d_bz); - fitter3body.setBz(d_bz); - - if (useMatCorrType == 2) { - // setMatLUT only after magfield has been initalized - // (setMatLUT has implicit and problematic init field call if not) - o2::base::Propagator::Instance()->setMatLUT(lut); - } - } - - //------------------------------------------------------------------ - // Check the info of good tracks - template - void CheckGoodTracks(TGoodTrackTable const& dGoodtracks, aod::McParticles const& /*particlesMC*/) - { - for (auto& goodtrackid : dGoodtracks) { - auto goodtrack = goodtrackid.template goodTrack_as(); - if (!goodtrack.has_mcParticle()) { - continue; - } - auto mcgoodtrack = goodtrack.template mcParticle_as(); - if (!mcgoodtrack.has_mothers()) { - continue; - } - bool flag_H3L = false; - for (auto& mothertrack : mcgoodtrack.template mothers_as()) { - if (is3bodyDecayedH3L(mothertrack)) { - flag_H3L = true; - } - } - if (flag_H3L && std::abs(mcgoodtrack.pdgCode()) == 2212) { - registry.fill(HIST("hDauTrackCounter"), 0.5); - } - if (flag_H3L && std::abs(mcgoodtrack.pdgCode()) == 211) { - registry.fill(HIST("hDauTrackCounter"), 1.5); - } - if (flag_H3L && std::abs(mcgoodtrack.pdgCode()) == 1000010020) { - registry.fill(HIST("hDauTrackCounter"), 2.5); - } - } - } - - o2::dataformats::VertexBase mMeanVertex{{0., 0., 0.}, {0.1 * 0.1, 0., 0.1 * 0.1, 0., 0., 6. * 6.}}; - //------------------------------------------------------------------ - // Virtual Lambda V0 finder - template - bool DecayV0Finder(TCollisionTable const& dCollision, TTrackTable const& dPtrack, TTrackTable const& dNtrack, float& rv0, bool isTrue3bodyV0 = false) - { - if (dPtrack.collisionId() != dNtrack.collisionId()) { - return false; - } - FillV0Counter(kV0All, isTrue3bodyV0); - if (!isTrue3bodyV0 && RejectBkgInMC) { - return false; - } - - auto Track0 = getTrackParCov(dPtrack); - auto Track1 = getTrackParCov(dNtrack); - int nCand = fitter.process(Track0, Track1); - if (nCand == 0) { - return false; - } - FillV0Counter(kV0hasSV, isTrue3bodyV0); - - // validate V0 radial position - // First check closeness to the beam-line as same as SVertexer - const auto& v0XYZ = fitter.getPCACandidate(); - float dxv0 = v0XYZ[0] - mMeanVertex.getX(), dyv0 = v0XYZ[1] - mMeanVertex.getY(), r2v0 = dxv0 * dxv0 + dyv0 * dyv0; - // float rv0 = std::sqrt(r2v0); - rv0 = std::sqrt(r2v0); - if (rv0 < minRToMeanVertex) { - return false; - } - FillV0Counter(kV0Radius, isTrue3bodyV0); - - // Not involved: Get minR with same way in SVertexer - // float drv0P = rv0 - Track0minR, drv0N = rv0 - Track1minR; - - // check: if the process function finish the propagation - if (!fitter.isPropagateTracksToVertexDone() && !fitter.propagateTracksToVertex()) { - return false; - } - - auto& trPProp = fitter.getTrack(0); - auto& trNProp = fitter.getTrack(1); - std::array pP, pN; - trPProp.getPxPyPzGlo(pP); - trNProp.getPxPyPzGlo(pN); - // estimate DCA of neutral V0 track to beamline: straight line with parametric equation - // x = X0 + pV0[0]*t, y = Y0 + pV0[1]*t reaches DCA to beamline (Xv, Yv) at - // t = -[ (x0-Xv)*pV0[0] + (y0-Yv)*pV0[1]) ] / ( pT(pV0)^2 ) - // Similar equation for 3D distance involving pV0[2] - std::array pV0 = {pP[0] + pN[0], pP[1] + pN[1], pP[2] + pN[2]}; - float pt2V0 = pV0[0] * pV0[0] + pV0[1] * pV0[1], prodXYv0 = dxv0 * pV0[0] + dyv0 * pV0[1], tDCAXY = prodXYv0 / pt2V0; - float p2V0 = pt2V0 + pV0[2] * pV0[2], ptV0 = std::sqrt(pt2V0); - if (ptV0 < minPtV0) { // pt cut - return false; - } - FillV0Counter(kV0Pt, isTrue3bodyV0); - - if (pV0[2] / ptV0 > maxTglV0) { // tgLambda cut - return false; - } - FillV0Counter(kV0TgLamda, isTrue3bodyV0); - - // apply mass selections - float massV0LambdaHyp = RecoDecay::m(array{array{pP[0], pP[1], pP[2]}, array{pN[0], pN[1], pN[2]}}, array{o2::constants::physics::MassProton, o2::constants::physics::MassPionCharged}); - float massV0AntiLambdaHyp = RecoDecay::m(array{array{pP[0], pP[1], pP[2]}, array{pN[0], pN[1], pN[2]}}, array{o2::constants::physics::MassPionCharged, o2::constants::physics::MassProton}); - float massMargin = 20 * (0.001 * (1. + 0.5 * ptV0)) + 0.07; - if (massV0LambdaHyp - o2::constants::physics::MassLambda > massMargin && massV0AntiLambdaHyp - o2::constants::physics::MassLambda > massMargin) { - return false; - } - FillV0Counter(kV0InvMass, isTrue3bodyV0); - - float dcaX = dxv0 - pV0[0] * tDCAXY, dcaY = dyv0 - pV0[1] * tDCAXY, dca2 = dcaX * dcaX + dcaY * dcaY; - float cosPAXY = prodXYv0 / std::sqrt(r2v0 * pt2V0); - if (dca2 > maxDCAXY2ToMeanVertex3bodyV0) { - return false; - } - FillV0Counter(kV0DcaXY, isTrue3bodyV0); - - if (cosPAXY < minCosPAXYMeanVertex3bodyV0) { - return false; - } - float dx = v0XYZ[0] - dCollision.posX(), dy = v0XYZ[1] - dCollision.posY(), dz = v0XYZ[2] - dCollision.posZ(), prodXYZv0 = dx * pV0[0] + dy * pV0[1] + dz * pV0[2]; - float cosPA = prodXYZv0 / std::sqrt((dx * dx + dy * dy + dz * dz) * p2V0); - if (cosPA < minCosPA3bodyV0) { - return false; - } - FillV0Counter(kV0CosPA, isTrue3bodyV0); - return true; - } - //------------------------------------------------------------------ - // 3body decay vertex finder - template - void Decay3bodyFinder(TCollisionTable const& dCollision, TTrackTable const& dPtrack, TTrackTable const& dNtrack, TTrackTable const& dBachtrack, float const& rv0, bool isTrue3bodyVtx = false) - { - if (dPtrack.collisionId() != dBachtrack.collisionId()) { - return; - } - if (dPtrack.globalIndex() == dBachtrack.globalIndex()) { - return; // skip the track used by V0 - } - FillVtxCounter(kVtxAll, isTrue3bodyVtx); - if (!isTrue3bodyVtx && RejectBkgInMC) { - return; - } - - auto track0 = getTrackParCov(dPtrack); - auto track1 = getTrackParCov(dNtrack); - auto bach = getTrackParCov(dBachtrack); - - if (bach.getPt() < minbachPt) { - return; - } - FillVtxCounter(kVtxbachPt, isTrue3bodyVtx); - - int n3bodyVtx = fitter3body.process(track0, track1, bach); - if (n3bodyVtx == 0) { // discard this pair - return; - } - FillVtxCounter(kVtxhasSV, isTrue3bodyVtx); - - const auto& vertexXYZ = fitter3body.getPCACandidatePos(); - // make sure the cascade radius is smaller than that of the vertex - float dxc = vertexXYZ[0] - dCollision.posX(), dyc = vertexXYZ[1] - dCollision.posY(), dzc = vertexXYZ[2] - dCollision.posZ(), r2vertex = dxc * dxc + dyc * dyc; - float rvertex = std::sqrt(r2vertex); - if (std::abs(rv0 - rvertex) > maxRDiff3bodyV0 || rvertex < minRToMeanVertex) { - return; - } - FillVtxCounter(kVtxRadius, isTrue3bodyVtx); - - // Not involved: bach.minR - rveretx check - - // check: if the process function finish the propagation - if (!fitter3body.isPropagateTracksToVertexDone() && !fitter3body.propagateTracksToVertex()) { - return; - } - - auto& tr0 = fitter3body.getTrack(0); - auto& tr1 = fitter3body.getTrack(1); - auto& tr2 = fitter3body.getTrack(2); - std::array p0, p1, p2; - tr0.getPxPyPzGlo(p0); - tr1.getPxPyPzGlo(p1); - tr2.getPxPyPzGlo(p2); - std::array p3B = {p0[0] + p1[0] + p2[0], p0[1] + p1[1] + p2[1], p0[2] + p1[2] + p2[2]}; - - float pt2 = p3B[0] * p3B[0] + p3B[1] * p3B[1], p2candidate = pt2 + p3B[2] * p3B[2]; - float pt = std::sqrt(pt2); - if (pt < minPt3Body) { // pt cut - return; - } - FillVtxCounter(kVtxPt, isTrue3bodyVtx); - - if (p3B[2] / pt > maxTgl3Body) { // tgLambda cut - return; - } - FillVtxCounter(kVtxTgLamda, isTrue3bodyVtx); - - float cosPA = (p3B[0] * dxc + p3B[1] * dyc + p3B[2] * dzc) / std::sqrt(p2candidate * (r2vertex + dzc * dzc)); - if (cosPA < minCosPA3body) { - return; - } - FillVtxCounter(kVtxCosPA, isTrue3bodyVtx); - - if (fitter3body.getChi2AtPCACandidate() > dcavtxdau) { - return; - } - FillVtxCounter(kVtxDcaDau, isTrue3bodyVtx); - - // Calculate DCA with respect to the collision associated to the V0, not individual tracks - std::array dcaInfo; - - auto Track0Par = getTrackPar(dPtrack); - o2::base::Propagator::Instance()->propagateToDCABxByBz({dCollision.posX(), dCollision.posY(), dCollision.posZ()}, Track0Par, 2.f, fitter3body.getMatCorrType(), &dcaInfo); - auto Track0dcaXY = dcaInfo[0]; - auto Track0dca = std::sqrt(Track0dcaXY * Track0dcaXY + dcaInfo[1] * dcaInfo[1]); - - auto Track1Par = getTrackPar(dNtrack); - o2::base::Propagator::Instance()->propagateToDCABxByBz({dCollision.posX(), dCollision.posY(), dCollision.posZ()}, Track1Par, 2.f, fitter3body.getMatCorrType(), &dcaInfo); - auto Track1dcaXY = dcaInfo[0]; - auto Track1dca = std::sqrt(Track1dcaXY * Track1dcaXY + dcaInfo[1] * dcaInfo[1]); - - auto Track2Par = getTrackPar(dBachtrack); - o2::base::Propagator::Instance()->propagateToDCABxByBz({dCollision.posX(), dCollision.posY(), dCollision.posZ()}, Track2Par, 2.f, fitter3body.getMatCorrType(), &dcaInfo); - auto Track2dcaXY = dcaInfo[0]; - auto Track2dca = std::sqrt(Track2dcaXY * Track2dcaXY + dcaInfo[1] * dcaInfo[1]); - - // H3L DCA Check - // auto track3B = o2::track::TrackParCov(vertexXYZ, p3B, fitter3body.calcPCACovMatrixFlat(), t2.sign()); - auto track3B = o2::track::TrackParCov(vertexXYZ, p3B, dBachtrack.sign()); - o2::dataformats::DCA dca; - if (d_UseH3LDCACut && (!track3B.propagateToDCA({{dCollision.posX(), dCollision.posY(), dCollision.posZ()}, {dCollision.covXX(), dCollision.covXY(), dCollision.covYY(), dCollision.covXZ(), dCollision.covYZ(), dCollision.covZZ()}}, fitter3body.getBz(), &dca, 5.) || - std::abs(dca.getY()) > maxDCAXY3Body || std::abs(dca.getZ()) > maxDCAZ3Body)) { - return; - } - FillVtxCounter(kVtxDcaH3L, isTrue3bodyVtx); - - vtx3bodydata( - dPtrack.globalIndex(), dNtrack.globalIndex(), dBachtrack.globalIndex(), dCollision.globalIndex(), 0, - vertexXYZ[0], vertexXYZ[1], vertexXYZ[2], - p0[0], p0[1], p0[2], p1[0], p1[1], p1[2], p2[0], p2[1], p2[2], - fitter3body.getChi2AtPCACandidate(), - Track0dcaXY, Track1dcaXY, Track2dcaXY, - Track0dca, Track1dca, Track2dca, - 0); // To be fixed - } - //------------------------------------------------------------------ - // 3body decay finder for a collsion - template - void DecayFinder(TCollisionTable const& dCollision, TPosTrackTable const& dPtracks, TNegTrackTable const& dNtracks, TGoodTrackTable const& dGoodtracks) - { - for (auto& t0id : dPtracks) { // FIXME: turn into combination(...) - auto t0 = t0id.template goodTrack_as(); - - for (auto& t1id : dNtracks) { - auto t1 = t1id.template goodTrack_as(); - float rv0; - if (!DecayV0Finder(dCollision, t0, t1, rv0)) { - continue; - } - - for (auto& t2id : dGoodtracks) { - auto t2 = t2id.template goodTrack_as(); - Decay3bodyFinder(dCollision, t0, t1, t2, rv0); - } - } - } - fillHistos(); - resetHistos(); - } - //------------------------------------------------------------------ - // MC 3body decay vertex finder - template - void DecayFinderMC(TCollisionTable const& dCollision, TPosTrackTable const& dPtracks, TNegTrackTable const& dNtracks, TGoodTrackTable const& dGoodtracks) - { - for (auto& t0id : dPtracks) { // FIXME: turn into combination(...) - auto t0 = t0id.template goodTrack_as(); - for (auto& t1id : dNtracks) { - auto t1 = t1id.template goodTrack_as(); - if (t0.collisionId() != t1.collisionId()) { - continue; - } - - bool isTrue3bodyV0 = false; - if (t0.has_mcParticle() && t1.has_mcParticle()) { - auto t0mc = t0.template mcParticle_as(); - auto t1mc = t1.template mcParticle_as(); - if ((t0mc.pdgCode() == 2212 && t1mc.pdgCode() == -211) || (t0mc.pdgCode() == 211 && t1mc.pdgCode() == -2212)) { - if (t0mc.has_mothers() && t1mc.has_mothers()) { - for (auto& t0mother : t0mc.template mothers_as()) { - for (auto& t1mother : t1mc.template mothers_as()) { - if (t0mother.globalIndex() == t1mother.globalIndex() && std::abs(t0mother.pdgCode()) == 1010010030) { - isTrue3bodyV0 = true; - } - } - } - } - } - } - - float rv0; - if (!DecayV0Finder(dCollision, t0, t1, rv0, isTrue3bodyV0)) { - continue; - } - - for (auto& t2id : dGoodtracks) { - auto t2 = t2id.template goodTrack_as(); - - bool isTrue3bodyVtx = false; - if (t0.has_mcParticle() && t1.has_mcParticle() && t2.has_mcParticle()) { - auto t0mc = t0.template mcParticle_as(); - auto t1mc = t1.template mcParticle_as(); - auto t2mc = t2.template mcParticle_as(); - if ((t0mc.pdgCode() == 2212 && t1mc.pdgCode() == -211 && t2mc.pdgCode() == 1000010020) || (t0mc.pdgCode() == 211 && t1mc.pdgCode() == -2212 && t2mc.pdgCode() == -1000010020)) { - if (t0mc.has_mothers() && t1mc.has_mothers() && t2mc.has_mothers()) { - for (auto& t0mother : t0mc.template mothers_as()) { - for (auto& t1mother : t1mc.template mothers_as()) { - for (auto& t2mother : t2mc.template mothers_as()) { - if (t0mother.globalIndex() == t1mother.globalIndex() && t0mother.globalIndex() == t2mother.globalIndex() && std::abs(t0mother.pdgCode()) == 1010010030) { - isTrue3bodyVtx = true; - } - } - } - } - } - } - } - - Decay3bodyFinder(dCollision, t0, t1, t2, rv0, isTrue3bodyVtx); - } - } - } - fillHistos(); - resetHistos(); - } - //------------------------------------------------------------------ - // MC virtual lambda check - template - void VirtualLambdaCheck(TCollisionTable const& /*dCollision*/, TV0DataTable const& fullV0s, int bin) - { - for (auto& v0 : fullV0s) { - statisticsRegistry.virtLambdastats[bin]++; - auto postrack = v0.template posTrack_as(); - auto negtrack = v0.template negTrack_as(); - if (postrack.has_mcParticle() && negtrack.has_mcParticle()) { - auto postrackmc = postrack.template mcParticle_as(); - auto negtrackmc = negtrack.template mcParticle_as(); - - if ((postrackmc.pdgCode() == 2212 && negtrackmc.pdgCode() == -211) || (postrackmc.pdgCode() == 211 && negtrackmc.pdgCode() == -2212)) { - if (postrackmc.has_mothers() && negtrackmc.has_mothers()) { - for (auto& posmother : postrackmc.template mothers_as()) { - for (auto& negmother : negtrackmc.template mothers_as()) { - if (posmother.globalIndex() == negmother.globalIndex()) { - if (posmother.pdgCode() == 1010010030) - statisticsRegistry.virtLambdastats[bin + 1]++; - else if (posmother.pdgCode() == -1010010030) - statisticsRegistry.virtLambdastats[bin + 2]++; - } - } - } - } - } - } - } - fillHistos(); - resetHistos(); - } - - //------------------------------------------------------------------ - // Process Function - void processData(aod::Collision const& collision, aod::V0GoodPosTracks const& ptracks, aod::V0GoodNegTracks const& ntracks, aod::V0GoodTracks const& goodtracks, FullTracksExtIU const&, aod::BCsWithTimestamps const&) - { - auto bc = collision.bc_as(); - initCCDB(bc); - registry.fill(HIST("hEventCounter"), 0.5); - - DecayFinder(collision, ptracks, ntracks, goodtracks); - } - PROCESS_SWITCH(hypertriton3bodyFinder, processData, "Produce StoredVtx3BodyDatas with data", true); - - void processCFFilteredData(aod::Collisions const& collisions, aod::CFFilters const& cffilters, aod::V0GoodPosTracks const& Ptracks, aod::V0GoodNegTracks const& Ntracks, aod::V0GoodTracks const& Goodtracks, FullTracksExtIU const&, aod::BCsWithTimestamps const&) - { - for (int i{0}; i < collisions.size(); i++) { - auto collision = collisions.iteratorAt(i); - auto cffilter = cffilters.iteratorAt(i); - auto bc = collision.bc_as(); - initCCDB(bc); - registry.fill(HIST("hEventCounter"), 0.5); - - auto ptracks = Ptracks.sliceBy(perCollisionGoodPosTracks, collision.globalIndex()); - auto ntracks = Ntracks.sliceBy(perCollisionGoodNegTracks, collision.globalIndex()); - auto goodtracks = Goodtracks.sliceBy(perCollisionGoodTracks, collision.globalIndex()); - - if (!cffilter.hasLD_LooseKstar() && UseCFFilter) { - continue; - } - registry.fill(HIST("hEventCounter"), 1.5); - - DecayFinder(collision, ptracks, ntracks, goodtracks); - } - } - PROCESS_SWITCH(hypertriton3bodyFinder, processCFFilteredData, "Produce StoredVtx3BodyDatas with data using CFtriggers", false); - - void processMC(aod::Collision const& collision, aod::V0GoodPosTracks const& ptracks, aod::V0GoodNegTracks const& ntracks, aod::V0GoodTracks const& goodtracks, aod::McParticles const& particlesMC, MCLabeledTracksIU const&, aod::BCsWithTimestamps const&) - { - auto bc = collision.bc_as(); - initCCDB(bc); - registry.fill(HIST("hEventCounter"), 0.5); - - CheckGoodTracks(goodtracks, particlesMC); - DecayFinderMC(collision, ptracks, ntracks, goodtracks); - } - PROCESS_SWITCH(hypertriton3bodyFinder, processMC, "Produce StoredVtx3BodyDatas with MC", false); - - void processCFFilteredMC(aod::Collisions const& collisions, aod::CFFilters const& cffilters, aod::V0GoodPosTracks const& Ptracks, aod::V0GoodNegTracks const& Ntracks, aod::V0GoodTracks const& Goodtracks, aod::V0s const& V0s, aod::V0Datas const& fullV0s, aod::McParticles const& particlesMC, MCLabeledTracksIU const&, aod::BCsWithTimestamps const&) - { - for (int i{0}; i < collisions.size(); i++) { - auto collision = collisions.iteratorAt(i); - auto cffilter = cffilters.iteratorAt(i); - auto bc = collision.bc_as(); - initCCDB(bc); - registry.fill(HIST("hEventCounter"), 0.5); - - auto goodtracks = Goodtracks.sliceBy(perCollisionGoodTracks, collision.globalIndex()); - CheckGoodTracks(goodtracks, particlesMC); - auto v0s = V0s.sliceBy(perCollisionV0s, collision.globalIndex()); - auto fullv0s = fullV0s.sliceBy(perCollisionV0Datas, collision.globalIndex()); - VirtualLambdaCheck(collision, v0s, 0); - VirtualLambdaCheck(collision, fullv0s, 3); - - if (!cffilter.hasLD_LooseKstar() && UseCFFilter) { - continue; - } - registry.fill(HIST("hEventCounter"), 1.5); - - auto ptracks = Ptracks.sliceBy(perCollisionGoodPosTracks, collision.globalIndex()); - auto ntracks = Ntracks.sliceBy(perCollisionGoodNegTracks, collision.globalIndex()); - - VirtualLambdaCheck(collision, v0s, 6); - VirtualLambdaCheck(collision, fullv0s, 9); - DecayFinderMC(collision, ptracks, ntracks, goodtracks); - } - } - PROCESS_SWITCH(hypertriton3bodyFinder, processCFFilteredMC, "Produce StoredVtx3BodyDatas with MC using CFtriggers", false); -}; - -struct hypertriton3bodyLabelBuilder { - - Produces vtxlabels; - - // for bookkeeping purposes: how many V0s come from same mother etc - HistogramRegistry registry{ - "registry", - { - {"hLabelCounter", "hLabelCounter", {HistType::kTH1F, {{3, 0.0f, 3.0f}}}}, - {"hHypertritonMCPt", "hHypertritonMCPt", {HistType::kTH1F, {{100, 0.0f, 10.0f}}}}, - {"hAntiHypertritonMCPt", "hAntiHypertritonMCPt", {HistType::kTH1F, {{100, 0.0f, 10.0f}}}}, - {"hHypertritonMCMass", "hHypertritonMCMass", {HistType::kTH1F, {{40, 2.95f, 3.05f, "Inv. Mass (GeV/c^{2})"}}}}, - {"hAntiHypertritonMCMass", "hAntiHypertritonMCMass", {HistType::kTH1F, {{40, 2.95f, 3.05f, "Inv. Mass (GeV/c^{2})"}}}}, - {"hHypertritonMCLifetime", "hHypertritonMCLifetime", {HistType::kTH1F, {{50, 0.0f, 50.0f, "ct(cm)"}}}}, - {"hAntiHypertritonMCLifetime", "hAntiHypertritonMCLifetime", {HistType::kTH1F, {{50, 0.0f, 50.0f, "ct(cm)"}}}}, - }, - }; - - void init(InitContext const&) - { - registry.get(HIST("hLabelCounter"))->GetXaxis()->SetBinLabel(1, "Total"); - registry.get(HIST("hLabelCounter"))->GetXaxis()->SetBinLabel(2, "Same MotherParticle"); - registry.get(HIST("hLabelCounter"))->GetXaxis()->SetBinLabel(3, "True H3L"); - } - - Configurable TpcPidNsigmaCut{"TpcPidNsigmaCut", 5, "TpcPidNsigmaCut"}; - - void processDoNotBuildLabels(aod::Collisions::iterator const&) - { - // dummy process function - should not be required in the future - } - PROCESS_SWITCH(hypertriton3bodyLabelBuilder, processDoNotBuildLabels, "Do not produce MC label tables", true); - - void processBuildLabels(aod::Vtx3BodyDatas const& vtx3bodydatas, MCLabeledTracksIU const&, aod::McParticles const& /*particlesMC*/) - { - std::vector lIndices; - lIndices.reserve(vtx3bodydatas.size()); - for (int ii = 0; ii < vtx3bodydatas.size(); ii++) { - lIndices[ii] = -1; - } - - for (auto& vtx3body : vtx3bodydatas) { - - int lLabel = -1; - int lPDG = -1; - float lPt = -1; - double MClifetime = -1; - bool is3bodyDecay = false; - int lGlobalIndex = -1; - - auto lTrack0 = vtx3body.track0_as(); - auto lTrack1 = vtx3body.track1_as(); - auto lTrack2 = vtx3body.track2_as(); - registry.fill(HIST("hLabelCounter"), 0.5); - - // Association check - // There might be smarter ways of doing this in the future - if (!lTrack0.has_mcParticle() || !lTrack1.has_mcParticle() || !lTrack2.has_mcParticle()) { - vtxlabels(-1); - continue; - } - auto lMCTrack0 = lTrack0.mcParticle_as(); - auto lMCTrack1 = lTrack1.mcParticle_as(); - auto lMCTrack2 = lTrack2.mcParticle_as(); - if (!lMCTrack0.has_mothers() || !lMCTrack1.has_mothers() || !lMCTrack2.has_mothers()) { - vtxlabels(-1); - continue; - } - - for (auto& lMother0 : lMCTrack0.mothers_as()) { - for (auto& lMother1 : lMCTrack1.mothers_as()) { - for (auto& lMother2 : lMCTrack2.mothers_as()) { - if (lMother0.globalIndex() == lMother1.globalIndex() && lMother0.globalIndex() == lMother2.globalIndex()) { - lGlobalIndex = lMother1.globalIndex(); - lPt = lMother1.pt(); - lPDG = lMother1.pdgCode(); - MClifetime = RecoDecay::sqrtSumOfSquares(lMCTrack2.vx() - lMother2.vx(), lMCTrack2.vy() - lMother2.vy(), lMCTrack2.vz() - lMother2.vz()) * o2::constants::physics::MassHyperTriton / lMother2.p(); - is3bodyDecay = true; // vtxs with the same mother - } - } - } - } // end association check - if (!is3bodyDecay) { - vtxlabels(-1); - continue; - } - registry.fill(HIST("hLabelCounter"), 1.5); - - // Intended for cross-checks only - // N.B. no rapidity cut! - if (lPDG == 1010010030 && lMCTrack0.pdgCode() == 2212 && lMCTrack1.pdgCode() == -211 && lMCTrack2.pdgCode() == 1000010020) { - lLabel = lGlobalIndex; - double hypertritonMCMass = RecoDecay::m(array{array{lMCTrack0.px(), lMCTrack0.py(), lMCTrack0.pz()}, array{lMCTrack1.px(), lMCTrack1.py(), lMCTrack1.pz()}, array{lMCTrack2.px(), lMCTrack2.py(), lMCTrack2.pz()}}, array{o2::constants::physics::MassProton, o2::constants::physics::MassPionCharged, o2::constants::physics::MassDeuteron}); - registry.fill(HIST("hLabelCounter"), 2.5); - registry.fill(HIST("hHypertritonMCPt"), lPt); - registry.fill(HIST("hHypertritonMCLifetime"), MClifetime); - registry.fill(HIST("hHypertritonMCMass"), hypertritonMCMass); - } - if (lPDG == -1010010030 && lMCTrack0.pdgCode() == 211 && lMCTrack1.pdgCode() == -2212 && lMCTrack2.pdgCode() == -1000010020) { - lLabel = lGlobalIndex; - double antiHypertritonMCMass = RecoDecay::m(array{array{lMCTrack0.px(), lMCTrack0.py(), lMCTrack0.pz()}, array{lMCTrack1.px(), lMCTrack1.py(), lMCTrack1.pz()}, array{lMCTrack2.px(), lMCTrack2.py(), lMCTrack2.pz()}}, array{o2::constants::physics::MassPionCharged, o2::constants::physics::MassProton, o2::constants::physics::MassDeuteron}); - registry.fill(HIST("hLabelCounter"), 2.5); - registry.fill(HIST("hAntiHypertritonMCPt"), lPt); - registry.fill(HIST("hAntiHypertritonMCLifetime"), MClifetime); - registry.fill(HIST("hAntiHypertritonMCMass"), antiHypertritonMCMass); - } - - // Construct label table, only true hypertriton and true daughters with a specified order is labeled - // for matter: track0->p, track1->pi, track2->d - // for antimatter: track0->pi, track1->p, track2->d - vtxlabels(lLabel); - } - } - PROCESS_SWITCH(hypertriton3bodyLabelBuilder, processBuildLabels, "Produce MC label tables", false); -}; - -struct hypertriton3bodyComparewithDecay3body { - - HistogramRegistry registry{ - "registry", - { - {"hMCInfoCounter", "hMCInfoCounter", {HistType::kTH1F, {{8, 0.0f, 8.0f}}}}, - {"hCheckCounter", "hCheckCounter", {HistType::kTH1F, {{5, 0.0f, 5.0f}}}}, - {"hHypertritonMCPtTotal", "hHypertritonMCPtTotal", {HistType::kTH1F, {{20, 0.0f, 10.0f}}}}, - {"hHypertritonMCPt", "hHypertritonMCPt", {HistType::kTH1F, {{100, 0.0f, 10.0f}}}}, - {"hAntiHypertritonMCPt", "hAntiHypertritonMCPt", {HistType::kTH1F, {{100, 0.0f, 10.0f}}}}, - {"hHypertritonMCMass", "hHypertritonMCMass", {HistType::kTH1F, {{40, 2.95f, 3.05f}}}}, - {"hAntiHypertritonMCMass", "hAntiHypertritonMCMass", {HistType::kTH1F, {{40, 2.95f, 3.05f}}}}, - {"hPairedHypertritonMCPt", "hPairedHypertritonMCPt", {HistType::kTH1F, {{100, 0.0f, 10.0f}}}}, - {"hPairedAntiHypertritonMCPt", "hPairedAntiHypertritonMCPt", {HistType::kTH1F, {{100, 0.0f, 10.0f}}}}, - {"hSameMcIndexCounter", "hSameMcIndexCounter", {HistType::kTH1F, {{2, 0.0f, 2.0f}}}}, - }, - }; - - void init(InitContext const&) - { - registry.get(HIST("hCheckCounter"))->GetXaxis()->SetBinLabel(1, "Total"); - registry.get(HIST("hCheckCounter"))->GetXaxis()->SetBinLabel(2, "Sig in Decay3body"); - registry.get(HIST("hCheckCounter"))->GetXaxis()->SetBinLabel(3, "Sig SameCol"); - registry.get(HIST("hCheckCounter"))->GetXaxis()->SetBinLabel(4, "Sig contained by finder"); - registry.get(HIST("hCheckCounter"))->GetXaxis()->SetBinLabel(5, "Sig SameIndex"); - } - struct Indexdaughters { // check duplicated paired daughters - int64_t index0; - int64_t index1; - int64_t index2; - bool operator==(const Indexdaughters& t) const - { - return (this->index0 == t.index0 && this->index1 == t.index1 && this->index2 == t.index2); - } - }; - - void processDoNotCompare(aod::Collisions::iterator const&) - { - // dummy process function - should not be required in the future - } - PROCESS_SWITCH(hypertriton3bodyComparewithDecay3body, processDoNotCompare, "Do not do comparison", true); - - void processDoComparison(aod::Decay3Bodys const& decay3bodytable, soa::Join const& vtx3bodydatas, MCLabeledTracksIU const&, aod::McParticles const& /*particlesMC*/) - { - std::vector set_pair; - for (auto d3body : decay3bodytable) { - registry.fill(HIST("hCheckCounter"), 0.5); - registry.fill(HIST("hMCInfoCounter"), 0.5); - auto lTrack0 = d3body.track0_as(); - auto lTrack1 = d3body.track1_as(); - auto lTrack2 = d3body.track2_as(); - if (!lTrack0.has_mcParticle() || !lTrack1.has_mcParticle() || !lTrack2.has_mcParticle()) { - continue; - } - registry.fill(HIST("hMCInfoCounter"), 1.5); - auto lMCTrack0 = lTrack0.mcParticle_as(); - auto lMCTrack1 = lTrack1.mcParticle_as(); - auto lMCTrack2 = lTrack2.mcParticle_as(); - if (lMCTrack0.isPhysicalPrimary() || lMCTrack1.isPhysicalPrimary() || lMCTrack2.isPhysicalPrimary()) { - continue; - } - if (lMCTrack0.producedByGenerator() || lMCTrack1.producedByGenerator() || lMCTrack2.producedByGenerator()) { - continue; - } - registry.fill(HIST("hMCInfoCounter"), 2.5); - - if (!lMCTrack0.has_mothers() || !lMCTrack1.has_mothers() || !lMCTrack2.has_mothers()) { - continue; - } - registry.fill(HIST("hMCInfoCounter"), 3.5); - - int lPDG = -1; - float lPt = -1; - bool is3bodyDecayedH3L = false; - int lGlobalIndex = -1; - - for (auto& lMother0 : lMCTrack0.mothers_as()) { - for (auto& lMother1 : lMCTrack1.mothers_as()) { - for (auto& lMother2 : lMCTrack2.mothers_as()) { - registry.fill(HIST("hMCInfoCounter"), 4.5); - if (lMother0.globalIndex() == lMother1.globalIndex() && lMother0.globalIndex() == lMother2.globalIndex()) { // vtxs with the same mother - registry.fill(HIST("hMCInfoCounter"), 7.5); - lGlobalIndex = lMother1.globalIndex(); - lPDG = lMother1.pdgCode(); - lPt = lMother1.pt(); - if (lPDG == 1010010030 && lMCTrack0.pdgCode() == 2212 && lMCTrack1.pdgCode() == -211 && lMCTrack2.pdgCode() == 1000010020) { - is3bodyDecayedH3L = true; - double hypertritonMCMass = RecoDecay::m(array{array{lMCTrack0.px(), lMCTrack0.py(), lMCTrack0.pz()}, array{lMCTrack1.px(), lMCTrack1.py(), lMCTrack1.pz()}, array{lMCTrack2.px(), lMCTrack2.py(), lMCTrack2.pz()}}, array{o2::constants::physics::MassProton, o2::constants::physics::MassPionCharged, o2::constants::physics::MassDeuteron}); - registry.fill(HIST("hHypertritonMCPt"), lPt); - registry.fill(HIST("hHypertritonMCMass"), hypertritonMCMass); - } - if (lPDG == -1010010030 && lMCTrack0.pdgCode() == 211 && lMCTrack1.pdgCode() == -2212 && lMCTrack2.pdgCode() == -1000010020) { - is3bodyDecayedH3L = true; - double antiHypertritonMCMass = RecoDecay::m(array{array{lMCTrack0.px(), lMCTrack0.py(), lMCTrack0.pz()}, array{lMCTrack1.px(), lMCTrack1.py(), lMCTrack1.pz()}, array{lMCTrack2.px(), lMCTrack2.py(), lMCTrack2.pz()}}, array{o2::constants::physics::MassPionCharged, o2::constants::physics::MassProton, o2::constants::physics::MassDeuteron}); - registry.fill(HIST("hAntiHypertritonMCPt"), lPt); - registry.fill(HIST("hAntiHypertritonMCMass"), antiHypertritonMCMass); - } - } - } - } - } // end association check - - if (!is3bodyDecayedH3L) { - continue; - } - - registry.fill(HIST("hCheckCounter"), 1.5); - registry.fill(HIST("hMCInfoCounter"), 5.5); - // for check - registry.fill(HIST("hHypertritonMCPtTotal"), lPt); - - Indexdaughters temp = {lMCTrack0.globalIndex(), lMCTrack1.globalIndex(), lMCTrack2.globalIndex()}; - auto p = std::find(set_pair.begin(), set_pair.end(), temp); - if (p == set_pair.end()) { - set_pair.push_back(temp); - registry.fill(HIST("hMCInfoCounter"), 6.5); - } - - if (lTrack0.collisionId() != lTrack1.collisionId() || lTrack0.collisionId() != lTrack2.collisionId()) { - continue; - } - registry.fill(HIST("hCheckCounter"), 2.5); - - for (auto vtx : vtx3bodydatas) { - if (vtx.mcParticleId() == -1) { - continue; - } - auto mcparticle = vtx.mcParticle_as(); - if (mcparticle.globalIndex() == lGlobalIndex) { - registry.fill(HIST("hCheckCounter"), 4.5); // rare case check: if motherId matches but daughters not - if (lTrack0.globalIndex() == vtx.track0Id() && lTrack1.globalIndex() == vtx.track1Id() && lTrack2.globalIndex() == vtx.track2Id()) { - registry.fill(HIST("hCheckCounter"), 3.5); - if (lPDG > 0) { - registry.fill(HIST("hPairedHypertritonMCPt"), lPt); - } else { - registry.fill(HIST("hPairedAntiHypertritonMCPt"), lPt); - } - break; - } - } - } - } - } - PROCESS_SWITCH(hypertriton3bodyComparewithDecay3body, processDoComparison, "Compare decay3bodys and finder method with MC", false); -}; - -struct hypertriton3bodyInitializer { - Spawns vtx3bodydatas; - void init(InitContext const&) {} -}; - -WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) -{ - return WorkflowSpec{ - adaptAnalysisTask(cfgc), - adaptAnalysisTask(cfgc), - adaptAnalysisTask(cfgc), - adaptAnalysisTask(cfgc), - adaptAnalysisTask(cfgc), - }; -} diff --git a/PWGLF/TableProducer/Nuspex/reduced3bodyCreator.cxx b/PWGLF/TableProducer/Nuspex/reduced3bodyCreator.cxx index f8d3d04856a..4f52fdd8066 100644 --- a/PWGLF/TableProducer/Nuspex/reduced3bodyCreator.cxx +++ b/PWGLF/TableProducer/Nuspex/reduced3bodyCreator.cxx @@ -35,6 +35,7 @@ #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/PIDResponse.h" #include "Common/Core/PID/PIDTOF.h" +#include "Common/Core/RecoDecay.h" #include "TableHelper.h" #include "Tools/KFparticle/KFUtilities.h" @@ -78,7 +79,6 @@ struct reduced3bodyCreator { Produces reducedDecay3Bodys; Produces reduced3BodyInfo; Produces reducedFullTracksPIDIU; - Produces dcaFitterSVInfo; Service ccdb; Zorro zorro; @@ -88,7 +88,6 @@ struct reduced3bodyCreator { o2::aod::pidtofgeneric::TofPidNewCollision bachelorTOFPID; Configurable event_sel8_selection{"event_sel8_selection", true, "event selection count post sel8 cut"}; - Configurable mc_event_selection{"mc_event_selection", true, "mc event selection count post kIsTriggerTVX and kNoTimeFrameBorder"}; Configurable event_posZ_selection{"event_posZ_selection", true, "event selection count post poZ cut"}; // CCDB options Configurable ccdburl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; @@ -114,6 +113,9 @@ struct reduced3bodyCreator { float d_bz; o2::pid::tof::TOFResoParamsV2 mRespParamsV2; + // tracked cluster size + std::vector fTrackedClSizeVector; + HistogramRegistry registry{"registry", {}}; void init(InitContext&) @@ -282,7 +284,7 @@ struct reduced3bodyCreator { //------------------------------------------------------------------ // function to fit KFParticle 3body vertex template - void fit3bodyVertex(TKFParticle& kfpProton, TKFParticle& kfpPion, TKFParticle& kfpDeuteron, TKFParticle& KFHt) + bool fit3bodyVertex(TKFParticle& kfpProton, TKFParticle& kfpPion, TKFParticle& kfpDeuteron, TKFParticle& KFHt) { // Construct 3body vertex int nDaughters3body = 3; @@ -292,12 +294,13 @@ struct reduced3bodyCreator { KFHt.Construct(Daughters3body, nDaughters3body); } catch (std::runtime_error& e) { LOG(debug) << "Failed to create Hyper triton 3-body vertex." << e.what(); - return; + return false; } LOG(debug) << "Hypertriton vertex constructed."; + return true; } - void process(ColwithEvTimesMultsCents const& collisions, TrackExtPIDIUwithEvTimes const&, aod::Decay3Bodys const& decay3bodys, aod::BCsWithTimestamps const&) + void process(ColwithEvTimesMultsCents const& collisions, TrackExtPIDIUwithEvTimes const&, aod::Decay3Bodys const& decay3bodys, aod::Tracked3Bodys const& tracked3bodys, aod::BCsWithTimestamps const&) { std::vector triggeredCollisions(collisions.size(), false); @@ -340,7 +343,14 @@ struct reduced3bodyCreator { int lastCollisionID = -1; // collisionId of last analysed decay3body. Table is sorted. - // Creat reduced table + // get tracked cluster size info + fTrackedClSizeVector.clear(); + fTrackedClSizeVector.resize(decay3bodys.size(), 0); + for (const auto& tvtx3body : tracked3bodys) { + fTrackedClSizeVector[tvtx3body.decay3BodyId()] = tvtx3body.itsClsSize(); + } + + // Create reduced table for (const auto& d3body : decay3bodys) { auto collision = d3body.template collision_as(); @@ -398,7 +408,7 @@ struct reduced3bodyCreator { const auto trackStartIndex = reducedFullTracksPIDIU.lastIndex(); reducedDecay3Bodys(collisionIndex, trackStartIndex - 2, trackStartIndex - 1, trackStartIndex); - // -------- save reduced decay3body info table -------- + // -------- get decay3body info with KF -------- // get trackParCov daughters auto trackParCovPos = getTrackParCov(daughter0); auto trackParCovNeg = getTrackParCov(daughter1); @@ -413,23 +423,29 @@ struct reduced3bodyCreator { kfpPion = createKFParticleFromTrackParCov(trackParCovPos, daughter0.sign(), constants::physics::MassPionCharged); } kfpDeuteron = createKFParticleFromTrackParCov(trackParCovBach, daughter2.sign(), constants::physics::MassDeuteron); - // fit 3body vertex + // fit 3body vertex and caclulate radius, phi, z position + float radius, phi, posZ; KFParticle KFHt; - fit3bodyVertex(kfpProton, kfpPion, kfpDeuteron, KFHt); - // calculate radius and phi - auto radius = std::sqrt(KFHt.GetX() * KFHt.GetX() + KFHt.GetY() * KFHt.GetY()); - float phi, sigma; - KFHt.GetPhi(phi, sigma); - // fill 3body info table - reduced3BodyInfo(radius, phi, KFHt.GetZ()); - - // -------- save dcaFitter secondary vertex info table -------- + if (fit3bodyVertex(kfpProton, kfpPion, kfpDeuteron, KFHt)) { + radius = std::hypot(KFHt.GetX(), KFHt.GetY()); + phi = std::atan2(KFHt.GetPx(), KFHt.GetPy()); + posZ = KFHt.GetZ(); + } else { + radius = -999.; + phi = -999.; + posZ = -999.; + } + + // -------- get decay3body info with DCA fitter -------- auto Track0 = getTrackParCov(daughter0); auto Track1 = getTrackParCov(daughter1); auto Track2 = getTrackParCov(daughter2); int n3bodyVtx = fitter3body.process(Track0, Track1, Track2); + float phiVtx, rVtx, zVtx; if (n3bodyVtx == 0) { // discard this pair - dcaFitterSVInfo(-999, -999, -999); + phiVtx = -999.; + rVtx = -999.; + zVtx = -999.; } else { const auto& vtxXYZ = fitter3body.getPCACandidate(); @@ -441,10 +457,13 @@ struct reduced3bodyCreator { propagatedTrack1.getPxPyPzGlo(p1); propagatedTrack2.getPxPyPzGlo(p2); std::array p3B = {p0[0] + p1[0] + p2[0], p0[1] + p1[1] + p2[1], p0[2] + p1[2] + p2[2]}; - float phiVtx = std::atan2(p3B[1], p3B[0]); - float rVtx = std::hypot(vtxXYZ[0], vtxXYZ[1]); - dcaFitterSVInfo(rVtx, phiVtx, vtxXYZ[2]); + phiVtx = std::atan2(p3B[1], p3B[0]); + rVtx = std::hypot(vtxXYZ[0], vtxXYZ[1]); + zVtx = vtxXYZ[2]; } + + // fill 3body info table (KF and DCA fitter info) + reduced3BodyInfo(radius, phi, posZ, rVtx, phiVtx, zVtx, fTrackedClSizeVector[d3body.globalIndex()]); } // end decay3body loop registry.fill(HIST("hEventCounter"), 3.5, reducedCollisions.lastIndex() + 1); diff --git a/PWGLF/TableProducer/Nuspex/threebodyKFTask.cxx b/PWGLF/TableProducer/Nuspex/threebodyKFTask.cxx deleted file mode 100644 index 1fed55805c2..00000000000 --- a/PWGLF/TableProducer/Nuspex/threebodyKFTask.cxx +++ /dev/null @@ -1,488 +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. -// -/// \brief Analysis task for KFVtx3BodyDatas (3body candidates reconstructed with KF) -/// \author Carolina Reetz --> partly copied from threebodyRecoTask.cxx -// ======================== - -#include -#include -#include -#include -#include - -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.h" -#include "ReconstructionDataFormats/Track.h" -#include "Common/Core/RecoDecay.h" -#include "Common/Core/trackUtilities.h" -#include "PWGLF/DataModel/LFStrangenessTables.h" -#include "PWGLF/DataModel/Vtx3BodyTables.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/Centrality.h" -#include "Common/DataModel/PIDResponse.h" -#include "CommonConstants/PhysicsConstants.h" - -using namespace o2; -using namespace o2::framework; -using namespace o2::framework::expressions; -using std::array; - -using MCLabeledTracksIU = soa::Join; - -struct threebodyKFTask { - - Produces outputMCTable; - std::vector filledMothers; - std::vector isGoodCollision; - - // Configurables - Configurable bachelorPdgCode{"bachelorPdgCode", 1000010020, "pdgCode of bachelor daughter"}; - Configurable motherPdgCode{"motherPdgCode", 1010010030, "pdgCode of mother"}; - - ConfigurableAxis m2PrPiBins{"m2PrPiBins", {60, 1., 3.3}, "Binning for m2(p,pi) axis"}; - ConfigurableAxis m2PiDeBins{"m2PiDeBins", {120, 4.0, 8.0}, "Binning for m2(pi,d) axis"}; - - // collision filter and preslice - Filter collisionFilter = (aod::evsel::sel8 == true && nabs(aod::collision::posZ) < 10.f); - Preslice perCollisionVtx3BodyDatas = o2::aod::vtx3body::collisionId; - - HistogramRegistry registry{"registry", {}, OutputObjHandlingPolicy::AnalysisObject}; - - void init(InitContext const&) - { - const AxisSpec axisM2PrPi{m2PrPiBins, "#it{m}^{2}(p,#pi^{-}) ((GeV/#it{c}^{2})^{2})"}; - const AxisSpec axisM2PiDe{m2PiDeBins, "#it{m}^{2}(#pi^{+},#bar{d}) ((GeV/#it{c}^{2})^{2})"}; - - registry.add("hCentFT0C", "hCentFT0C", HistType::kTH1F, {{100, 0.0f, 100.0f, "FT0C Centrality"}}); - - // mass spectrum of reco candidates - registry.add("hMassHypertriton", "Mass hypertriton", HistType::kTH1F, {{80, 2.96f, 3.04f, "#it{m}(p,#pi^{-},d) (GeV/#it{c}^{2})"}}); - registry.add("hMassAntiHypertriton", "Mass anti-hypertriton", HistType::kTH1F, {{80, 2.96f, 3.04f, "#it{m}(#bar{p},#pi^{+},#bar{d}) (GeV/#it{c}^{2})"}}); - // Dalitz diagrams of reco candidates - registry.add("hDalitzHypertriton", "Dalitz diagram", HistType::kTH2F, {axisM2PrPi, axisM2PiDe})->GetYaxis()->SetTitle("#it{m}^{2}(#pi^{-},d) ((GeV/#it{c}^{2})^{2})"); - registry.add("hDalitzAntiHypertriton", "Dalitz diagram", HistType::kTH2F, {axisM2PrPi, axisM2PiDe})->GetXaxis()->SetTitle("#it{m}^{2}(#bar{p},#pi^{+}) ((GeV/#it{c}^{2})^{2})"); - - // bachelor histgrams - registry.add("hAverageITSClusterSizeBachelor", "Average ITS cluster size bachelor track", HistType::kTH1F, {{15, 0.5, 15.5, "#langle ITS cluster size #rangle"}}); - registry.add("hdEdxBachelor", "TPC dE/dx bachelor track", HistType::kTH1F, {{200, 0.0f, 200.0f, "Average ITS cluster size"}}); - registry.add("hPIDTrackingBachelor", "Tracking PID bachelor track", HistType::kTH1F, {{20, 0.5, 20.5, "Tracking PID identifier"}}); - - // for gen information of reco candidates - auto LabelHist = registry.add("hLabelCounter", "Reco MC candidate counter", HistType::kTH1F, {{3, 0.0f, 3.0f}}); - LabelHist->GetXaxis()->SetBinLabel(1, "Total"); - LabelHist->GetXaxis()->SetBinLabel(2, "Have Same MotherTrack"); - LabelHist->GetXaxis()->SetBinLabel(3, "True H3L/Anti-H3L"); - registry.add("hTrueHypertritonMCPt", "pT gen. of reco. H3L", HistType::kTH1F, {{100, -10.0f, 10.0f, "#it{p}_{T} (GeV/#it{c})"}}); - registry.add("hTrueHypertritonMCMass", "mass gen. of reco. H3L", HistType::kTH1F, {{40, 2.96f, 3.04f, "#it{m}(p,#pi^{-},d) (GeV/#it{c}^{2})"}}); - registry.add("hTrueHypMassWithMuReco", "mass gen. of reco. H3L", HistType::kTH1F, {{40, 2.96f, 3.04f, "#it{m}(p,#pi^{-},d) (GeV/#it{c}^{2})"}}); - registry.add("hTrueHypertritonMCCTau", "#it{c}#tau gen. of reco. H3L", HistType::kTH1F, {{50, 0.0f, 50.0f, "#it{c}#tau(cm)"}}); - registry.add("hTrueHypertritonMCMassPrPi", "inv. mass gen. of reco. V0 pair (H3L)", HistType::kTH1F, {{100, 0.0f, 6.0f, "#it{m}(p,#pi^{-}) (GeV/#it{c}^{2})"}}); - - // for gen information of non reco candidates - registry.add("hTrueHypertritonMCMassPrPi_nonReco", "inv. mass gen. of non-reco. V0 pair (H3L)", HistType::kTH1F, {{100, 0.0f, 6.0f, "#it{m}(p,#pi^{-}) (GeV/#it{c}^{2})"}}); - registry.add("hTrueHypertritonMCPtPion_nonReco", "Pion #it{p}_{T} gen. of non-reco. H3L", HistType::kTH1F, {{100, 0.0f, 6.0f, "#it{p}_{T}(#pi) (GeV/#it{c})"}}); - registry.add("hTrueHypertritonMCPtProton_nonReco", "Proton #it{p}_{T} gen. of non-reco. H3L", HistType::kTH1F, {{100, 0.0f, 6.0f, "#it{p}_{T}(p) (GeV/#it{c})"}}); - } - - // helper function to check if a mother track is a true H3L/Anti-H3L - template - int checkH3LTruth(MCTrack3B const& mcParticlePr, MCTrack3B const& mcParticlePi, MCTrack3B const& mcParticleDe, bool& isMuonReco) - { - if (abs(mcParticlePr.pdgCode()) != 2212 || abs(mcParticleDe.pdgCode()) != 1000010020) { - return -1; - } - // check proton and deuteron mother - int prDeMomID = -1; - for (const auto& motherPr : mcParticlePr.template mothers_as()) { - for (const auto& motherDe : mcParticleDe.template mothers_as()) { - if (motherPr.globalIndex() == motherDe.globalIndex() && std::abs(motherPr.pdgCode()) == 1010010030) { - prDeMomID = motherPr.globalIndex(); - break; - } - } - } - if (prDeMomID == -1) { - return -1; - } - if (std::abs(mcParticlePi.pdgCode()) != 211 && std::abs(mcParticlePi.pdgCode()) != 13) { - return -1; - } - // check if the pion track is a muon coming from a pi -> mu + vu decay, if yes, take the mother pi - auto mcParticlePiTmp = mcParticlePi; - if (std::abs(mcParticlePiTmp.pdgCode()) == 13) { - for (const auto& motherPi : mcParticlePiTmp.template mothers_as()) { - if (std::abs(motherPi.pdgCode()) == 211) { - mcParticlePiTmp = motherPi; - isMuonReco = true; - break; - } - } - } - // now loop over the pion mother - for (const auto& motherPi : mcParticlePiTmp.template mothers_as()) { - if (motherPi.globalIndex() == prDeMomID) { - return motherPi.globalIndex(); - } - } - return -1; - } - - template - void fillQAPlots(TCand const& vtx3body) - { - // Mass plot - if (vtx3body.track2sign() > 0) { // hypertriton - registry.fill(HIST("hMassHypertriton"), vtx3body.mass()); - } else if (vtx3body.track2sign() < 0) { // anti-hypertriton - registry.fill(HIST("hMassAntiHypertriton"), vtx3body.mass()); - } - - // Dalitz plot - auto m2prpi = RecoDecay::m2(array{array{vtx3body.pxtrack0(), vtx3body.pytrack0(), vtx3body.pztrack0()}, array{vtx3body.pxtrack1(), vtx3body.pytrack1(), vtx3body.pztrack1()}}, array{o2::constants::physics::MassProton, o2::constants::physics::MassPionCharged}); - auto m2pide = RecoDecay::m2(array{array{vtx3body.pxtrack1(), vtx3body.pytrack1(), vtx3body.pztrack1()}, array{vtx3body.pxtrack2(), vtx3body.pytrack2(), vtx3body.pztrack2()}}, array{o2::constants::physics::MassPionCharged, o2::constants::physics::MassDeuteron}); - if (std::abs(vtx3body.mass() - o2::constants::physics::MassHyperTriton) <= 0.005) { - if (vtx3body.track2sign() > 0) { // hypertriton - registry.fill(HIST("hDalitzHypertriton"), m2prpi, m2pide); - } else if (vtx3body.track2sign() < 0) { // anti-hypertriton - registry.fill(HIST("hDalitzAntiHypertriton"), m2prpi, m2pide); - } - } - - // ITS cluster sizes - registry.fill(HIST("hAverageITSClusterSizeBachelor"), vtx3body.itsclussizedeuteron()); - registry.fill(HIST("hdEdxBachelor"), vtx3body.tpcdedxdeuteron()); - registry.fill(HIST("hPIDTrackingBachelor"), vtx3body.pidtrackingdeuteron()); - } - - //------------------------------------------------------------------ - // process real data analysis - void processData(soa::Filtered>::iterator const& collision, - aod::KFVtx3BodyDatas const& vtx3bodydatas) - { - registry.fill(HIST("hCentFT0C"), collision.centFT0C()); - - for (auto& vtx3bodydata : vtx3bodydatas) { - // QA histograms - fillQAPlots(vtx3bodydata); - } - } - PROCESS_SWITCH(threebodyKFTask, processData, "Data analysis", true); - - //------------------------------------------------------------------ - // process mc analysis - void processMC(soa::Join const& collisions, - aod::KFVtx3BodyDatas const& vtx3bodydatas, - aod::McParticles const& particlesMC, - MCLabeledTracksIU const&, - aod::McCollisions const& mcCollisions) - { - filledMothers.clear(); - isGoodCollision.resize(mcCollisions.size(), false); - - // loop over collisions - for (const auto& collision : collisions) { - // event selection - if (!collision.sel8() || std::abs(collision.posZ()) > 10.f) { - continue; - } - // reco collision survived event selection filter --> fill value for MC collision if collision is "true" MC collision - if (collision.mcCollisionId() >= 0) { - isGoodCollision[collision.mcCollisionId()] = true; - } - - // fill MC table with reco MC candidate information and gen information if matched to MC particle - auto Decay3BodyTable_thisCollision = vtx3bodydatas.sliceBy(perCollisionVtx3BodyDatas, collision.globalIndex()); - for (auto& vtx3bodydata : Decay3BodyTable_thisCollision) { - registry.fill(HIST("hLabelCounter"), 0.5); - - // fill QA histograms for all reco candidates - fillQAPlots(vtx3bodydata); - - auto track0 = vtx3bodydata.track0_as(); - auto track1 = vtx3bodydata.track1_as(); - auto track2 = vtx3bodydata.track2_as(); - - if (!track0.has_mcParticle() || !track1.has_mcParticle() || !track2.has_mcParticle()) { - continue; - } - - auto mcTrack0 = track0.mcParticle_as(); - auto mcTrack1 = track1.mcParticle_as(); - auto mcTrack2 = track2.mcParticle_as(); - - float genPosPt = mcTrack0.pt(); - float genPosP = mcTrack0.p(); - int daughter0PDGcode = mcTrack0.pdgCode(); - float genNegPt = mcTrack1.pt(); - float genNegP = mcTrack1.p(); - int daughter1PDGcode = mcTrack1.pdgCode(); - float genBachPt = mcTrack2.pt(); - float genBachP = mcTrack2.p(); - int daughter2PDGcode = mcTrack2.pdgCode(); - bool isBachPrimary = mcTrack2.isPhysicalPrimary(); - - double MClifetime = -1.; - bool isTrueH3L = false; - bool isTrueAntiH3L = false; - float genPhi = -1.; - float genEta = -1.; - float genRap = -1.; - float genP = -1.; - float genPt = -1.; - std::array genDecVtx{-1.f}; - bool isMuonReco = false; - auto& mcTrackPr = vtx3bodydata.sign() > 0 ? mcTrack0 : mcTrack1; - auto& mcTrackPi = vtx3bodydata.sign() > 0 ? mcTrack1 : mcTrack0; - auto& mcTrackDe = mcTrack2; - int motherID = checkH3LTruth(mcTrackPr, mcTrackPi, mcTrackDe, isMuonReco); - if (motherID > 0) { - auto mcTrackHyp = particlesMC.rawIteratorAt(motherID); - genPhi = mcTrackHyp.phi(); - genEta = mcTrackHyp.eta(); - genPt = mcTrackHyp.pt(); - int chargeFactor = mcTrackHyp.pdgCode() > 0 ? 1 : -1; - isTrueH3L = chargeFactor > 0; - isTrueAntiH3L = chargeFactor < 0; - MClifetime = RecoDecay::sqrtSumOfSquares(mcTrackPr.vx() - mcTrackHyp.vx(), mcTrackPr.vy() - mcTrackHyp.vy(), mcTrackPr.vz() - mcTrackHyp.vz()) * o2::constants::physics::MassHyperTriton / mcTrackHyp.p(); - double MCMass = RecoDecay::m(array{array{mcTrackPr.px(), mcTrackPr.py(), mcTrackPr.pz()}, array{mcTrackPi.px(), mcTrackPi.py(), mcTrackPi.pz()}, array{mcTrackDe.px(), mcTrackDe.py(), mcTrackDe.pz()}}, array{o2::constants::physics::MassProton, o2::constants::physics::MassPionCharged, o2::constants::physics::MassDeuteron}); - float MCmassPrPi = RecoDecay::m(array{array{mcTrackPr.px(), mcTrackPr.py(), mcTrackPr.pz()}, array{mcTrackPi.px(), mcTrackPi.py(), mcTrackPi.pz()}}, array{o2::constants::physics::MassProton, o2::constants::physics::MassPionCharged}); - registry.fill(HIST("hLabelCounter"), 2.5); - registry.fill(HIST("hTrueHypertritonMCPt"), mcTrackHyp.pt() * chargeFactor); - registry.fill(HIST("hTrueHypertritonMCCTau"), MClifetime); - registry.fill(HIST("hTrueHypertritonMCMass"), MCMass); - registry.fill(HIST("hTrueHypertritonMCMassPrPi"), MCmassPrPi); - if (isMuonReco) { - registry.fill(HIST("hTrueHypMassWithMuReco"), MCMass); - } - filledMothers.push_back(mcTrackHyp.globalIndex()); - } - outputMCTable( // filled for each reconstructed candidate (in KFVtx3BodyDatas) - vtx3bodydata.mass(), - vtx3bodydata.x(), vtx3bodydata.y(), vtx3bodydata.z(), - vtx3bodydata.xerr(), vtx3bodydata.yerr(), vtx3bodydata.zerr(), - vtx3bodydata.px(), vtx3bodydata.py(), vtx3bodydata.pz(), vtx3bodydata.pt(), - vtx3bodydata.pxerr(), vtx3bodydata.pyerr(), vtx3bodydata.pzerr(), vtx3bodydata.pterr(), - vtx3bodydata.sign(), - vtx3bodydata.dcavtxtopvkf(), vtx3bodydata.dcaxyvtxtopvkf(), - vtx3bodydata.vtxcospakf(), vtx3bodydata.vtxcosxypakf(), - vtx3bodydata.vtxcospakftopo(), vtx3bodydata.vtxcosxypakftopo(), - vtx3bodydata.decaylkf(), vtx3bodydata.decaylxykf(), vtx3bodydata.decayldeltal(), - vtx3bodydata.chi2geondf(), vtx3bodydata.chi2topondf(), - vtx3bodydata.ctaukftopo(), - vtx3bodydata.trackedclsize(), - vtx3bodydata.massv0(), vtx3bodydata.chi2massv0(), - vtx3bodydata.cospav0(), - vtx3bodydata.pxtrack0(), vtx3bodydata.pytrack0(), vtx3bodydata.pztrack0(), // proton - vtx3bodydata.pxtrack1(), vtx3bodydata.pytrack1(), vtx3bodydata.pztrack1(), // pion - vtx3bodydata.pxtrack2(), vtx3bodydata.pytrack2(), vtx3bodydata.pztrack2(), // deuteron - vtx3bodydata.tpcinnerparamtrack0(), vtx3bodydata.tpcinnerparamtrack1(), vtx3bodydata.tpcinnerparamtrack2(), // proton, pion, deuteron - vtx3bodydata.tpcncltrack0(), vtx3bodydata.tpcncltrack1(), vtx3bodydata.tpcncltrack1(), // proton, pion, deuteron - vtx3bodydata.tpcchi2ncldeuteron(), - vtx3bodydata.deltaphideuteron(), vtx3bodydata.deltaphiproton(), - vtx3bodydata.dcatrack0topvkf(), vtx3bodydata.dcatrack1topvkf(), vtx3bodydata.dcatrack2topvkf(), // proton, pion, deuteron - vtx3bodydata.dcaxytrack0topvkf(), vtx3bodydata.dcaxytrack1topvkf(), vtx3bodydata.dcaxytrack2topvkf(), // proton, pion, deuteron - vtx3bodydata.dcaxytrack0tosvkf(), vtx3bodydata.dcaxytrack1tosvkf(), vtx3bodydata.dcaxytrack2tosvkf(), // proton, pion, deuteron - vtx3bodydata.dcatrack0totrack1kf(), vtx3bodydata.dcatrack0totrack2kf(), vtx3bodydata.dcatrack1totrack2kf(), - vtx3bodydata.dcavtxdaughterskf(), - vtx3bodydata.dcaxytrackpostopv(), vtx3bodydata.dcaxytracknegtopv(), vtx3bodydata.dcaxytrackbachtopv(), - vtx3bodydata.dcatrackpostopv(), vtx3bodydata.dcatracknegtopv(), vtx3bodydata.dcatrackbachtopv(), - vtx3bodydata.track0sign(), vtx3bodydata.track1sign(), vtx3bodydata.track2sign(), // proton, pion, deuteron - vtx3bodydata.tpcnsigmaproton(), vtx3bodydata.tpcnsigmapion(), vtx3bodydata.tpcnsigmadeuteron(), vtx3bodydata.tpcnsigmapionbach(), - vtx3bodydata.tpcdedxproton(), vtx3bodydata.tpcdedxpion(), vtx3bodydata.tpcdedxdeuteron(), - vtx3bodydata.tofnsigmadeuteron(), - vtx3bodydata.itsclussizedeuteron(), - vtx3bodydata.pidtrackingdeuteron(), - // MC info (-1 if not matched to MC particle) - genP, - genPt, - genDecVtx[0], genDecVtx[1], genDecVtx[2], - MClifetime, - genPhi, - genEta, - genRap, - genPosP, genPosPt, genNegP, genNegPt, genBachP, genBachPt, - isTrueH3L, isTrueAntiH3L, - daughter0PDGcode, daughter1PDGcode, daughter2PDGcode, isBachPrimary, - true, // is reconstructed - true); // reco event passed event selection - } // end vtx3bodydatas loop - } // end collision loop - - // generated MC particle analysis - // fill MC table with gen information for all generated but not reconstructed particles - for (auto& mcparticle : particlesMC) { - - double genMCmassPrPi = -1.; - bool isTrueGenH3L = false; - bool isTrueGenAntiH3L = false; - float genPBach = -1.; - float genPtBach = -1.; - float genPPos = -1.; - float genPtPos = -1.; - float genPNeg = -1.; - float genPtNeg = -1.; - int posDauPdgCode = -1; - int negDauPdgCode = -1; - int bachDauPdgCode = -1; - - // check if mcparticle was reconstructed and already filled in the table - if (std::find(filledMothers.begin(), filledMothers.end(), mcparticle.globalIndex()) != std::end(filledMothers)) { - continue; - } - - // set flag if corresponding reco collision survived event selection - bool survEvSel = isGoodCollision[mcparticle.mcCollisionId()]; - - // check if MC particle is hypertriton with 3-body decay - if (std::abs(mcparticle.pdgCode()) != motherPdgCode) { - continue; - } - bool haveProton = false, havePion = false, haveBachelor = false; - bool haveAntiProton = false, haveAntiPion = false, haveAntiBachelor = false; - for (auto& mcparticleDaughter : mcparticle.template daughters_as()) { - if (mcparticleDaughter.pdgCode() == 2212) - haveProton = true; - if (mcparticleDaughter.pdgCode() == -2212) - haveAntiProton = true; - if (mcparticleDaughter.pdgCode() == 211) - havePion = true; - if (mcparticleDaughter.pdgCode() == -211) - haveAntiPion = true; - if (mcparticleDaughter.pdgCode() == bachelorPdgCode) - haveBachelor = true; - if (mcparticleDaughter.pdgCode() == -bachelorPdgCode) - haveAntiBachelor = true; - } - - // check if particle or anti-particle - if (haveProton && haveAntiPion && haveBachelor && mcparticle.pdgCode() > 0) { - isTrueGenH3L = true; - // get proton and pion daughter - std::array protonMom{0.f}; - std::array piMinusMom{0.f}; - for (auto& mcparticleDaughter : mcparticle.template daughters_as()) { - if (mcparticleDaughter.pdgCode() == 2212) { - protonMom = {mcparticleDaughter.px(), mcparticleDaughter.py(), mcparticleDaughter.pz()}; - genPPos = mcparticleDaughter.p(); - genPtPos = mcparticleDaughter.pt(); - posDauPdgCode = mcparticleDaughter.pdgCode(); - } else if (mcparticleDaughter.pdgCode() == -211) { - piMinusMom = {mcparticleDaughter.px(), mcparticleDaughter.py(), mcparticleDaughter.pz()}; - genPNeg = mcparticleDaughter.p(); - genPtNeg = mcparticleDaughter.pt(); - negDauPdgCode = mcparticleDaughter.pdgCode(); - } - } - genMCmassPrPi = RecoDecay::m(array{protonMom, piMinusMom}, array{o2::constants::physics::MassProton, o2::constants::physics::MassPionCharged}); - registry.fill(HIST("hTrueHypertritonMCMassPrPi_nonReco"), genMCmassPrPi); - registry.fill(HIST("hTrueHypertritonMCPtProton_nonReco"), RecoDecay::sqrtSumOfSquares(protonMom[0], protonMom[1])); - registry.fill(HIST("hTrueHypertritonMCPtPion_nonReco"), RecoDecay::sqrtSumOfSquares(piMinusMom[0], piMinusMom[1])); - } else if (haveAntiProton && havePion && haveAntiBachelor && mcparticle.pdgCode() < 0) { - isTrueGenAntiH3L = true; - // get anti-proton and pion daughter - std::array antiProtonMom{0.f}; - std::array piPlusMom{0.f}; - for (auto& mcparticleDaughter : mcparticle.template daughters_as()) { - if (mcparticleDaughter.pdgCode() == -2212) { - antiProtonMom = {mcparticleDaughter.px(), mcparticleDaughter.py(), mcparticleDaughter.pz()}; - genPNeg = mcparticleDaughter.p(); - genPtNeg = mcparticleDaughter.pt(); - negDauPdgCode = mcparticleDaughter.pdgCode(); - } else if (mcparticleDaughter.pdgCode() == 211) { - piPlusMom = {mcparticleDaughter.px(), mcparticleDaughter.py(), mcparticleDaughter.pz()}; - genPPos = mcparticleDaughter.p(); - genPtPos = mcparticleDaughter.pt(); - posDauPdgCode = mcparticleDaughter.pdgCode(); - } - } - genMCmassPrPi = RecoDecay::m(array{antiProtonMom, piPlusMom}, array{o2::constants::physics::MassProton, o2::constants::physics::MassPionCharged}); - registry.fill(HIST("hTrueHypertritonMCMassPrPi_nonReco"), genMCmassPrPi); - registry.fill(HIST("hTrueHypertritonMCPtProton_nonReco"), RecoDecay::sqrtSumOfSquares(antiProtonMom[0], antiProtonMom[1])); - registry.fill(HIST("hTrueHypertritonMCPtPion_nonReco"), RecoDecay::sqrtSumOfSquares(piPlusMom[0], piPlusMom[1])); - } else { - continue; // stop if particle is no true H3L or Anti-H3L - } - - // get gen decay vertex and calculate ctau - std::array genDecayVtx{0.f}; - for (auto& mcDaughter : mcparticle.daughters_as()) { - if (std::abs(mcDaughter.pdgCode()) == bachelorPdgCode) { - genDecayVtx = {mcDaughter.vx(), mcDaughter.vy(), mcDaughter.vz()}; - genPBach = mcDaughter.p(); - genPtBach = mcDaughter.pt(); - bachDauPdgCode = mcDaughter.pdgCode(); - } - } - double genMClifetime = RecoDecay::sqrtSumOfSquares(genDecayVtx[0] - mcparticle.vx(), genDecayVtx[1] - mcparticle.vy(), genDecayVtx[2] - mcparticle.vz()) * o2::constants::physics::MassHyperTriton / mcparticle.p(); - outputMCTable( // reco information (-1) - -1, - -1, -1, -1, - -1, -1, -1, - -1, -1, -1, -1, - -1, -1, -1, -1, - -1, - -1, -1, - -1, -1, - -1, -1, - -1, -1, -1, - -1, -1, - -1, - -1, - -1, -1, - -1, - -1, -1, -1, - -1, -1, -1, - -1, -1, -1, - -1, -1, -1, - -1, -1, -1, - -1, - -1, -1, - -1, -1, -1, - -1, -1, -1, - -1, -1, -1, - -1, -1, -1, - -1, - -1, -1, -1, - -1, -1, -1, - -1, -1, -1, - -1, -1, -1, -1, - -1, -1, -1, - -1, - -1, - -1, - // gen information - mcparticle.p(), - mcparticle.pt(), - genDecayVtx[0], genDecayVtx[1], genDecayVtx[2], - genMClifetime, - mcparticle.phi(), - mcparticle.eta(), - mcparticle.y(), - genPPos, genPtPos, genPNeg, genPtNeg, genPBach, genPtBach, - isTrueGenH3L, isTrueGenAntiH3L, - posDauPdgCode, negDauPdgCode, bachDauPdgCode, - false, // isBachPrimary - false, // is reconstructed - survEvSel); - } // end mcparticles loop - } - PROCESS_SWITCH(threebodyKFTask, processMC, "MC analysis", false); -}; - -WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) -{ - return WorkflowSpec{ - adaptAnalysisTask(cfgc), - }; -} diff --git a/PWGLF/TableProducer/Nuspex/threebodyRecoTask.cxx b/PWGLF/TableProducer/Nuspex/threebodyRecoTask.cxx deleted file mode 100644 index 36af287f95e..00000000000 --- a/PWGLF/TableProducer/Nuspex/threebodyRecoTask.cxx +++ /dev/null @@ -1,909 +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 threebodyRecoTask.cxx -/// \brief Analysis task for 3-body decay process (now mainly for hypertriton) -/// \author Yuanzhe Wang - -#include -#include -#include -#include -#include -#include -#include - -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.h" -#include "ReconstructionDataFormats/Track.h" -#include "Common/Core/RecoDecay.h" -#include "Common/Core/trackUtilities.h" -#include "PWGLF/DataModel/Vtx3BodyTables.h" -#include "PWGLF/DataModel/Reduced3BodyTables.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/Centrality.h" -#include "Common/DataModel/PIDResponse.h" -#include "CommonConstants/PhysicsConstants.h" -#include "CCDB/BasicCCDBManager.h" - -#include "EventFiltering/Zorro.h" -#include "EventFiltering/ZorroSummary.h" - -using namespace o2; -using namespace o2::framework; -using namespace o2::framework::expressions; - -using ReducedCols = soa::Join; -using FullTracksExtIU = soa::Join; -using MCLabeledTracksIU = soa::Join; - -std::vector triggerLabels = { - "fTriggerEventF1Proton", "fTrackedOmega", "fTrackedXi", "fOmegaLargeRadius", - "fDoubleOmega", "fOmegaHighMult", "fSingleXiYN", "fQuadrupleXi", "fDoubleXi", - "fhadronOmega", "fOmegaXi", "fTripleXi", "fOmega", "fGammaVeryLowPtEMCAL", - "fGammaVeryLowPtDCAL", "fGammaHighPtEMCAL", "fGammaLowPtEMCAL", "fGammaVeryHighPtDCAL", - "fGammaVeryHighPtEMCAL", "fGammaLowPtDCAL", "fJetNeutralLowPt", "fJetNeutralHighPt", - "fGammaHighPtDCAL", "fJetFullLowPt", "fJetFullHighPt", "fEMCALReadout", "fPCMandEE", - "fPHOSnbar", "fPCMHighPtPhoton", "fPHOSPhoton", "fLD", "fPPPHI", "fPD", "fLLL", "fPLL", - "fPPL", "fPPP", "fLeadingPtTrack", "fHighFt0cFv0Flat", "fHighFt0cFv0Mult", "fHighFt0Flat", - "fHighFt0Mult", "fHighMultFv0", "fHighTrackMult", "fHfSingleNonPromptCharm3P", - "fHfSingleNonPromptCharm2P", "fHfSingleCharm3P", "fHfPhotonCharm3P", "fHfHighPt2P", - "fHfSigmaC0K0", "fHfDoubleCharm2P", "fHfBeauty3P", "fHfFemto3P", "fHfFemto2P", - "fHfHighPt3P", "fHfSigmaCPPK", "fHfDoubleCharm3P", "fHfDoubleCharmMix", - "fHfPhotonCharm2P", "fHfV0Charm2P", "fHfBeauty4P", "fHfV0Charm3P", "fHfSingleCharm2P", - "fHfCharmBarToXiBach", "fSingleMuHigh", "fSingleMuLow", "fLMeeHMR", "fDiMuon", - "fDiElectron", "fLMeeIMR", "fSingleE", "fTrackHighPt", "fTrackLowPt", "fJetChHighPt", - "fJetChLowPt", "fUDdiffLarge", "fUDdiffSmall", "fITSextremeIonisation", - "fITSmildIonisation", "fH3L3Body", "fHe", "fH2"}; - -struct Candidate3body { - // Index - int mcmotherId; - int track0Id; - int track1Id; - int track2Id; - // Collision - float colCentFT0C; - // sv and candidate - bool isMatter; - float invmass; - float ct; - float cosPA; - float dcadaughters; - float dcacandtopv; - float vtxradius; - // daughter tracks - TLorentzVector lcand; - TLorentzVector lproton; - TLorentzVector lpion; - TLorentzVector lbachelor; - uint8_t dautpcNclusters[3]; // 0 - proton, 1 - pion, 2 - bachelor - uint32_t dauitsclussize[3]; // 0 - proton, 1 - pion, 2 - bachelor - float daudcaxytopv[3]; // 0 - proton, 1 - pion, 2 - bachelor - float daudcatopv[3]; // 0 - proton, 1 - pion, 2 - bachelor - float dautpcNsigma[3]; // 0 - proton, 1 - pion, 2 - bachelor - float dauinnermostR[3]; // 0 - proton, 1 - pion, 2 - bachelor !!! TracksIU required !!! - float bachelortofNsigma; - bool isBachPrimary = false; - // MC infomartion - TLorentzVector lgencand = {0, 0, 0, 0}; - float genct = -1; - float genrapidity = -999; - bool isSignal = false; - bool isReco = false; - int pdgCode = -1; - bool survivedEventSelection = false; -}; - -struct ThreebodyRecoTask { - - Produces outputDataTable; - Produces outputMCTable; - std::vector candidates3body; - std::vector filledMothers; - std::vector isGoodCollision; - - Service ccdb; - Zorro zorro; - OutputObj zorroSummary{"zorroSummary"}; - - //------------------------------------------------------------------ - PresliceUnsorted perCollisionVtx3BodyDatas = o2::aod::vtx3body::collisionId; - - // Configurable for trigger selection - Configurable triggerList{"triggerList", "fTriggerEventF1Proton, fTrackedOmega, fTrackedXi, fOmegaLargeRadius, fDoubleOmega, fOmegaHighMult, fSingleXiYN, fQuadrupleXi, fDoubleXi, fhadronOmega, fOmegaXi, fTripleXi, fOmega, fGammaVeryLowPtEMCAL, fGammaVeryLowPtDCAL, fGammaHighPtEMCAL, fGammaLowPtEMCAL, fGammaVeryHighPtDCAL, fGammaVeryHighPtEMCAL, fGammaLowPtDCAL, fJetNeutralLowPt, fJetNeutralHighPt, fGammaHighPtDCAL, fJetFullLowPt, fJetFullHighPt, fEMCALReadout, fPCMandEE, fPHOSnbar, fPCMHighPtPhoton, fPHOSPhoton, fLD, fPPPHI, fPD, fLLL, fPLL, fPPL, fPPP, fLeadingPtTrack, fHighFt0cFv0Flat, fHighFt0cFv0Mult, fHighFt0Flat, fHighFt0Mult, fHighMultFv0, fHighTrackMult, fHfSingleNonPromptCharm3P, fHfSingleNonPromptCharm2P, fHfSingleCharm3P, fHfPhotonCharm3P, fHfHighPt2P, fHfSigmaC0K0, fHfDoubleCharm2P, fHfBeauty3P, fHfFemto3P, fHfFemto2P, fHfHighPt3P, fHfSigmaCPPK, fHfDoubleCharm3P, fHfDoubleCharmMix, fHfPhotonCharm2P, fHfV0Charm2P, fHfBeauty4P, fHfV0Charm3P, fHfSingleCharm2P, fHfCharmBarToXiBach, fSingleMuHigh, fSingleMuLow, fLMeeHMR, fDiMuon, fDiElectron, fLMeeIMR, fSingleE, fTrackHighPt, fTrackLowPt, fJetChHighPt, fJetChLowPt, fUDdiffLarge, fUDdiffSmall, fITSextremeIonisation, fITSmildIonisation, fH3L3Body, fHe, fH2", "List of triggers used to select events"}; - Configurable cfgOnlyKeepInterestedTrigger{"cfgOnlyKeepInterestedTrigger", false, "Flag to keep only interested trigger"}; - Configurable bcTolerance{"bcTolerance", 100, "Tolerance for BC in Zorro"}; - // Configuration to enable like-sign analysis - Configurable cfgLikeSignAnalysis{"cfgLikeSignAnalysis", false, "Enable like-sign analysis"}; - // Selection criteria - Configurable vtxcospa{"vtxcospa", 0.99, "Vtx CosPA"}; // double -> N.B. dcos(x)/dx = 0 at x=0) - Configurable dcavtxdau{"dcavtxdau", 1.0, "DCA Vtx Daughters"}; // loose cut - Configurable dcapiontopv{"dcapiontopv", .05, "DCA Pion To PV"}; - Configurable etacut{"etacut", 0.9, "etacut"}; - Configurable rapiditycut{"rapiditycut", 1, "rapiditycut"}; - Configurable tofPIDNSigmaMin{"tofPIDNSigmaMin", -5, "tofPIDNSigmaMin"}; - Configurable tofPIDNSigmaMax{"tofPIDNSigmaMax", 5, "tofPIDNSigmaMax"}; - Configurable tpcPIDNSigmaCut{"tpcPIDNSigmaCut", 5, "tpcPIDNSigmaCut"}; - Configurable eventSel8Cut{"eventSel8Cut", true, "flag to enable event sel8 selection"}; - Configurable mcEventCut{"mcEventCut", true, "flag to enable mc event selection: kIsTriggerTVX and kNoTimeFrameBorder"}; - Configurable eventPosZCut{"eventPosZCut", true, "flag to enable event posZ selection"}; - Configurable lifetimecut{"lifetimecut", 40., "lifetimecut"}; // ct - Configurable minProtonPt{"minProtonPt", 0.3, "minProtonPt"}; - Configurable maxProtonPt{"maxProtonPt", 5, "maxProtonPt"}; - Configurable minPionPt{"minPionPt", 0.1, "minPionPt"}; - Configurable maxPionPt{"maxPionPt", 1.2, "maxPionPt"}; - Configurable minDeuteronPt{"minDeuteronPt", 0.6, "minDeuteronPt"}; - Configurable maxDeuteronPt{"maxDeuteronPt", 10, "maxDeuteronPt"}; - Configurable minDeuteronPUseTOF{"minDeuteronPUseTOF", 1, "minDeuteronPt Enable TOF PID"}; - Configurable h3LMassLowerlimit{"h3LMassLowerlimit", 2.96, "Hypertriton mass lower limit"}; - Configurable h3LMassUpperlimit{"h3LMassUpperlimit", 3.04, "Hypertriton mass upper limit"}; - Configurable mintpcNClsproton{"mintpcNClsproton", 90, "min tpc Nclusters for proton"}; - Configurable mintpcNClspion{"mintpcNClspion", 70, "min tpc Nclusters for pion"}; - Configurable mintpcNClsdeuteron{"mintpcNClsdeuteron", 100, "min tpc Nclusters for deuteron"}; - - Configurable mcsigma{"mcsigma", 0.0015, "sigma of mc invariant mass fit"}; // obtained from MC - Configurable bachelorPdgCode{"bachelorPdgCode", 1000010020, "pdgCode of bachelor daughter"}; - Configurable motherPdgCode{"motherPdgCode", 1010010030, "pdgCode of mother track"}; - - // 3sigma region for Dalitz plot - float lowersignallimit = o2::constants::physics::MassHyperTriton - 3 * mcsigma; - float uppersignallimit = o2::constants::physics::MassHyperTriton + 3 * mcsigma; - - // CCDB options - Configurable ccdbUrl{"ccdbUrl", "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 geoPath{"geoPath", "GLO/Config/GeometryAligned", "Path of the geometry file"}; - Configurable pidPath{"pidPath", "", "Path to the PID response object"}; - - // Zorro counting - Configurable cfgSkimmedProcessing{"cfgSkimmedProcessing", false, "Skimmed dataset processing"}; - - HistogramRegistry registry{ - "registry", - { - {"hEventCounter", "hEventCounter", {HistType::kTH1F, {{5, 0.0f, 5.0f}}}}, - {"hCentFT0C", "hCentFT0C", {HistType::kTH1F, {{100, 0.0f, 100.0f, "FT0C Centrality"}}}}, - {"hCandidatesCounter", "hCandidatesCounter", {HistType::kTH1F, {{12, 0.0f, 12.0f}}}}, - {"hMassHypertriton", "hMassHypertriton", {HistType::kTH1F, {{80, 2.96f, 3.04f}}}}, - {"hMassAntiHypertriton", "hMassAntiHypertriton", {HistType::kTH1F, {{80, 2.96f, 3.04f}}}}, - {"hMassHypertritonTotal", "hMassHypertritonTotal", {HistType::kTH1F, {{300, 2.9f, 3.2f}}}}, - {"hTOFPIDDeuteron", "hTOFPIDDeuteron", {HistType::kTH1F, {{2000, -100.0f, 100.0f}}}}, - {"hProtonTPCBB", "hProtonTPCBB", {HistType::kTH2F, {{160, -8.0f, 8.0f, "p/z(GeV/c)"}, {200, 0.0f, 1000.0f, "TPCSignal"}}}}, - {"hPionTPCBB", "hPionTPCBB", {HistType::kTH2F, {{160, -8.0f, 8.0f, "p/z(GeV/c)"}, {200, 0.0f, 1000.0f, "TPCSignal"}}}}, - {"hDeuteronTPCBB", "hDeuteronTPCBB", {HistType::kTH2F, {{160, -8.0f, 8.0f, "p/z(GeV/c)"}, {200, 0.0f, 1000.0f, "TPCSignal"}}}}, - {"hProtonTPCVsPt", "hProtonTPCVsPt", {HistType::kTH2F, {{50, 0.0f, 5.0f, "#it{p}_{T} (GeV/c)"}, {240, -6.0f, 6.0f, "TPC n#sigma"}}}}, - {"hPionTPCVsPt", "hPionTPCVsPt", {HistType::kTH2F, {{20, 0.0f, 2.0f, "#it{p}_{T} (GeV/c)"}, {240, -6.0f, 6.0f, "TPC n#sigma"}}}}, - {"hDeuteronTPCVsPt", "hDeuteronTPCVsPt", {HistType::kTH2F, {{80, 0.0f, 8.0f, "#it{p}_{T} (GeV/c)"}, {240, -6.0f, 6.0f, "TPC n#sigma"}}}}, - {"hDeuteronTOFVsPBeforeTOFCut", "hDeuteronTOFVsPBeforeTOFCut", {HistType::kTH2F, {{40, -10.0f, 10.0f, "p/z (GeV/c)"}, {40, -10.0f, 10.0f, "TOF n#sigma"}}}}, - {"hDeuteronTOFVsPAtferTOFCut", "hDeuteronTOFVsPAtferTOFCut", {HistType::kTH2F, {{40, -10.0f, 10.0f, "p/z (GeV/c)"}, {40, -10.0f, 10.0f, "TOF n#sigma"}}}}, - - {"hDalitz", "hDalitz", {HistType::kTH2F, {{120, 7.85, 8.45, "M^{2}(dp) (GeV^{2}/c^{4})"}, {60, 1.1, 1.4, "M^{2}(p#pi) (GeV^{2}/c^{4})"}}}}, - }, - }; - - //------------------------------------------------------------------ - // Fill stats histograms - enum Vtxstep { kCandAll = 0, - kCandDauEta, - kCandDauPt, - kCandTPCNcls, - kCandTPCPID, - kCandTOFPID, - kCandDcaToPV, - kCandRapidity, - kCandct, - kCandCosPA, - kCandDcaDau, - kCandInvMass, - kNCandSteps }; - - struct { - std::array candstats; - std::array truecandstats; - } statisticsRegistry; - - void resetHistos() - { - for (int ii = 0; ii < kNCandSteps; ii++) { - statisticsRegistry.candstats[ii] = 0; - statisticsRegistry.truecandstats[ii] = 0; - } - } - void fillCandCounter(int kn, bool istrue = false) - { - statisticsRegistry.candstats[kn]++; - if (istrue) { - statisticsRegistry.truecandstats[kn]++; - } - } - void fillHistos() - { - for (int ii = 0; ii < kNCandSteps; ii++) { - registry.fill(HIST("hCandidatesCounter"), ii, statisticsRegistry.candstats[ii]); - if (doprocessMC == true) { - registry.fill(HIST("hTrueHypertritonCounter"), ii, statisticsRegistry.truecandstats[ii]); - } - } - } - - int mRunNumber; - - void init(InitContext const&) - { - zorroSummary.setObject(zorro.getZorroSummary()); - - mRunNumber = 0; - - ccdb->setURL(ccdbUrl); - ccdb->setCaching(true); - ccdb->setLocalObjectValidityChecking(); - ccdb->setFatalWhenNull(false); - - registry.get(HIST("hEventCounter"))->GetXaxis()->SetBinLabel(1, "total"); - registry.get(HIST("hEventCounter"))->GetXaxis()->SetBinLabel(2, "sel8"); - registry.get(HIST("hEventCounter"))->GetXaxis()->SetBinLabel(3, "vertexZ"); - registry.get(HIST("hEventCounter"))->GetXaxis()->SetBinLabel(4, "Zorro H3L 3body event"); - registry.get(HIST("hEventCounter"))->GetXaxis()->SetBinLabel(5, "has Candidate"); - - // Check for selection criteria !!! TracksIU required !!! - registry.add("hDiffRVtxProton", "hDiffRVtxProton", HistType::kTH1F, {{100, -10, 10}}); // difference between the radius of decay vertex and minR of proton - registry.add("hDiffRVtxPion", "hDiffRVtxPion", HistType::kTH1F, {{100, -10, 10}}); // difference between the radius of decay vertex and minR of pion - registry.add("hDiffRVtxDeuteron", "hDiffRVtxDeuteron", HistType::kTH1F, {{100, -10, 10}}); // difference between the radius of decay vertex and minR of deuteron - registry.add("hDiffDaughterR", "hDiffDaughterR", HistType::kTH1F, {{10000, -100, 100}}); // difference between minR of pion&proton and R of deuteron(bachelor) - - // Check triggers - auto hEventTriggerCount = registry.add("hEventTriggerCount", "hEventTriggerCount", HistType::kTH1F, {{static_cast(triggerLabels.size() + 1), 0, static_cast(triggerLabels.size() + 1)}}); - for (size_t i = 0; i < triggerLabels.size(); i++) { - hEventTriggerCount->GetXaxis()->SetBinLabel(i + 1, triggerLabels[i].c_str()); - } - hEventTriggerCount->GetXaxis()->SetBinLabel(triggerLabels.size() + 1, "NoTrigger"); - - if (cfgLikeSignAnalysis) { - registry.add("hInvMassCorrectSign", "hInvMassCorrectSign", HistType::kTH1F, {{80, 2.96f, 3.04f}}); // check if there are contamination of possible signals which are caused by unexpected PID - } - - if (doprocessMC == true) { - registry.add("hTrueHypertritonCounter", "hTrueHypertritonCounter", HistType::kTH1F, {{12, 0.0f, 12.0f}}); - auto hGeneratedHypertritonCounter = registry.add("hGeneratedHypertritonCounter", "hGeneratedHypertritonCounter", HistType::kTH1F, {{2, 0.0f, 2.0f}}); - hGeneratedHypertritonCounter->GetXaxis()->SetBinLabel(1, "Total"); - hGeneratedHypertritonCounter->GetXaxis()->SetBinLabel(2, "3-body decay"); - registry.add("hPtGeneratedHypertriton", "hPtGeneratedHypertriton", HistType::kTH1F, {{200, 0.0f, 10.0f}}); - registry.add("hctGeneratedHypertriton", "hctGeneratedHypertriton", HistType::kTH1F, {{50, 0, 50, "ct(cm)"}}); - registry.add("hEtaGeneratedHypertriton", "hEtaGeneratedHypertriton", HistType::kTH1F, {{40, -2.0f, 2.0f}}); - registry.add("hRapidityGeneratedHypertriton", "hRapidityGeneratedHypertriton", HistType::kTH1F, {{40, -2.0f, 2.0f}}); - registry.add("hPtGeneratedAntiHypertriton", "hPtGeneratedAntiHypertriton", HistType::kTH1F, {{200, 0.0f, 10.0f}}); - registry.add("hctGeneratedAntiHypertriton", "hctGeneratedAntiHypertriton", HistType::kTH1F, {{50, 0, 50, "ct(cm)"}}); - registry.add("hEtaGeneratedAntiHypertriton", "hEtaGeneratedAntiHypertriton", HistType::kTH1F, {{40, -2.0f, 2.0f}}); - registry.add("hRapidityGeneratedAntiHypertriton", "hRapidityGeneratedAntiHypertriton", HistType::kTH1F, {{40, -2.0f, 2.0f}}); - } - - TString candCounterbinLabel[kNCandSteps] = {"Total", "TrackEta", "DauPt", "TPCNcls", "TPCPID", "d TOFPID", "PionDcatoPV", "MomRapidity", "Lifetime", "VtxCosPA", "VtxDcaDau", "InvMass"}; - for (int i{0}; i < kNCandSteps; i++) { - registry.get(HIST("hCandidatesCounter"))->GetXaxis()->SetBinLabel(i + 1, candCounterbinLabel[i]); - if (doprocessMC == true) { - registry.get(HIST("hTrueHypertritonCounter"))->GetXaxis()->SetBinLabel(i + 1, candCounterbinLabel[i]); - } - } - } - - void initCCDB(aod::BCsWithTimestamps::iterator const& bc) - { - if (mRunNumber == bc.runNumber()) { - return; - } - - if (cfgSkimmedProcessing) { - zorro.initCCDB(ccdb.service, bc.runNumber(), bc.timestamp(), triggerList); - zorro.populateHistRegistry(registry, bc.runNumber()); - } - - LOGF(info, "Initializing CCDB for run %d", bc.runNumber()); - mRunNumber = bc.runNumber(); - } - - //------------------------------------------------------------------ - // Check if the mcparticle is hypertriton which decays into 3 daughters - template - bool is3bodyDecayed(TMCParticle const& particle) - { - if (std::abs(particle.pdgCode()) != motherPdgCode) { - return false; - } - bool haveProton = false, havePion = false, haveBachelor = false; - bool haveAntiProton = false, haveAntiPion = false, haveAntiBachelor = false; - for (const auto& mcparticleDaughter : particle.template daughters_as()) { - if (mcparticleDaughter.pdgCode() == PDG_t::kProton) - haveProton = true; - if (mcparticleDaughter.pdgCode() == PDG_t::kProtonBar) - haveAntiProton = true; - if (mcparticleDaughter.pdgCode() == PDG_t::kPiPlus) - havePion = true; - if (mcparticleDaughter.pdgCode() == PDG_t::kPiMinus) - haveAntiPion = true; - if (mcparticleDaughter.pdgCode() == bachelorPdgCode) - haveBachelor = true; - if (mcparticleDaughter.pdgCode() == -bachelorPdgCode) - haveAntiBachelor = true; - } - if (haveProton && haveAntiPion && haveBachelor && particle.pdgCode() > 0) { - return true; - } else if (haveAntiProton && havePion && haveAntiBachelor && particle.pdgCode() < 0) { - return true; - } - return false; - } - - //------------------------------------------------------------------ - // Event Selection - template - bool eventSelection(TCollision const& collision) - { - auto bc = collision.template bc_as(); - initCCDB(bc); - registry.fill(HIST("hEventCounter"), 0.5); - - if (eventSel8Cut && !collision.sel8()) { - return false; - } - registry.fill(HIST("hEventCounter"), 1.5); - if (eventPosZCut && std::abs(collision.posZ()) > 10.f) { // 10cm - return false; - } - registry.fill(HIST("hEventCounter"), 2.5); - registry.fill(HIST("hCentFT0C"), collision.centFT0C()); - - if (cfgSkimmedProcessing) { - bool zorroSelected = zorro.isSelected(bc.globalBC()); /// Just let Zorro do the accounting - if (zorroSelected) { - registry.fill(HIST("hEventCounter"), 3.5); - } else { - if (cfgOnlyKeepInterestedTrigger) { - return false; - } - } - } - - return true; - } - - //------------------------------------------------------------------ - // Fill candidate table - template - void fillCand(TCollisionTable const& collision, TCandTable const& candData, TTrackTable const& trackProton, TTrackTable const& trackPion, TTrackTable const& trackDeuteron, bool isMatter, bool isTrueCand = false, int lLabel = -1, TLorentzVector lmother = {0, 0, 0, 0}, double mcLifetime = -1, bool isBachPrimary = false) - { - double cospa = candData.vtxcosPA(collision.posX(), collision.posY(), collision.posZ()); - double ct = candData.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassHyperTriton; - - Candidate3body cand3body; - cand3body.isMatter = isMatter; - if (isMatter == true) { - cand3body.lproton.SetXYZM(candData.pxtrack0(), candData.pytrack0(), candData.pztrack0(), o2::constants::physics::MassProton); - cand3body.lpion.SetXYZM(candData.pxtrack1(), candData.pytrack1(), candData.pztrack1(), o2::constants::physics::MassPionCharged); - } else { - cand3body.lproton.SetXYZM(candData.pxtrack1(), candData.pytrack1(), candData.pztrack1(), o2::constants::physics::MassPionCharged); - cand3body.lpion.SetXYZM(candData.pxtrack0(), candData.pytrack0(), candData.pztrack0(), o2::constants::physics::MassProton); - } - - cand3body.mcmotherId = lLabel; - cand3body.track0Id = candData.track0Id(); - cand3body.track1Id = candData.track1Id(); - cand3body.track2Id = candData.track2Id(); - cand3body.colCentFT0C = collision.centFT0C(); - cand3body.invmass = cand3body.isMatter ? candData.mHypertriton() : candData.mAntiHypertriton(); - cand3body.lcand.SetXYZM(candData.px(), candData.py(), candData.pz(), o2::constants::physics::MassHyperTriton); - cand3body.ct = ct; - cand3body.cosPA = cospa; - cand3body.dcadaughters = candData.dcaVtxdaughters(); - cand3body.dcacandtopv = candData.dcavtxtopv(collision.posX(), collision.posY(), collision.posZ()); - cand3body.vtxradius = candData.vtxradius(); - cand3body.lbachelor.SetXYZM(candData.pxtrack2(), candData.pytrack2(), candData.pztrack2(), o2::constants::physics::MassDeuteron); - cand3body.dautpcNclusters[0] = trackProton.tpcNClsFound(); - cand3body.dautpcNclusters[1] = trackPion.tpcNClsFound(); - cand3body.dautpcNclusters[2] = trackDeuteron.tpcNClsFound(); - cand3body.dauitsclussize[0] = trackProton.itsClusterSizes(); - cand3body.dauitsclussize[1] = trackPion.itsClusterSizes(); - cand3body.dauitsclussize[2] = trackDeuteron.itsClusterSizes(); - cand3body.dautpcNsigma[0] = trackProton.tpcNSigmaPr(); - cand3body.dautpcNsigma[1] = trackPion.tpcNSigmaPi(); - cand3body.dautpcNsigma[2] = trackDeuteron.tpcNSigmaDe(); - cand3body.daudcaxytopv[0] = cand3body.isMatter ? candData.dcaXYtrack0topv() : candData.dcaXYtrack1topv(); - cand3body.daudcaxytopv[1] = cand3body.isMatter ? candData.dcaXYtrack1topv() : candData.dcaXYtrack0topv(); - cand3body.daudcaxytopv[2] = candData.dcaXYtrack2topv(); - cand3body.daudcatopv[0] = cand3body.isMatter ? candData.dcatrack0topv() : candData.dcatrack1topv(); - cand3body.daudcatopv[1] = cand3body.isMatter ? candData.dcatrack1topv() : candData.dcatrack0topv(); - cand3body.daudcatopv[2] = candData.dcatrack2topv(); - cand3body.dauinnermostR[0] = trackProton.x(); - cand3body.dauinnermostR[1] = trackPion.x(); - cand3body.dauinnermostR[2] = trackDeuteron.x(); - - cand3body.bachelortofNsigma = candData.tofNSigmaBachDe(); - cand3body.isBachPrimary = isBachPrimary; - if (isTrueCand) { - cand3body.mcmotherId = lLabel; - cand3body.lgencand = lmother; - cand3body.genct = mcLifetime; - cand3body.genrapidity = lmother.Rapidity(); - cand3body.isSignal = true; - cand3body.isReco = true; - cand3body.pdgCode = cand3body.isMatter ? motherPdgCode : -motherPdgCode; - cand3body.survivedEventSelection = true; - filledMothers.push_back(lLabel); - } - - candidates3body.push_back(cand3body); - - registry.fill(HIST("hProtonTPCBB"), trackProton.sign() * trackProton.p(), trackProton.tpcSignal()); - registry.fill(HIST("hPionTPCBB"), trackPion.sign() * trackPion.p(), trackPion.tpcSignal()); - registry.fill(HIST("hDeuteronTPCBB"), trackDeuteron.sign() * trackDeuteron.p(), trackDeuteron.tpcSignal()); - registry.fill(HIST("hProtonTPCVsPt"), trackProton.pt(), trackProton.tpcNSigmaPr()); - registry.fill(HIST("hPionTPCVsPt"), trackProton.pt(), trackPion.tpcNSigmaPi()); - registry.fill(HIST("hDeuteronTPCVsPt"), trackDeuteron.pt(), trackDeuteron.tpcNSigmaDe()); - registry.fill(HIST("hTOFPIDDeuteron"), candData.tofNSigmaBachDe()); - registry.fill(HIST("hDiffRVtxProton"), trackProton.x() - candData.vtxradius()); - registry.fill(HIST("hDiffRVtxPion"), trackPion.x() - candData.vtxradius()); - registry.fill(HIST("hDiffRVtxDeuteron"), trackDeuteron.x() - candData.vtxradius()); - float diffTrackR = trackDeuteron.x() - std::min(trackProton.x(), trackPion.x()); - registry.fill(HIST("hDiffDaughterR"), diffTrackR); - } - - //------------------------------------------------------------------ - // Selections for candidates - template - bool selectCand(TCollisionTable const& collision, TCandTable const& candData, TTrackTable const& trackProton, TTrackTable const& trackPion, TTrackTable const& trackDeuteron, bool isMatter, bool isTrueCand = false) - { - fillCandCounter(kCandAll, isTrueCand); - - // Selection on daughters - if (std::abs(trackProton.eta()) > etacut || std::abs(trackPion.eta()) > etacut || std::abs(trackDeuteron.eta()) > etacut) { - return false; - } - fillCandCounter(kCandDauEta, isTrueCand); - - if (trackProton.pt() < minProtonPt || trackProton.pt() > maxProtonPt || trackPion.pt() < minPionPt || trackPion.pt() > maxPionPt || trackDeuteron.pt() < minDeuteronPt || trackDeuteron.pt() > maxDeuteronPt) { - return false; - } - fillCandCounter(kCandDauPt, isTrueCand); - - if (trackProton.tpcNClsFound() < mintpcNClsproton || trackPion.tpcNClsFound() < mintpcNClspion || trackDeuteron.tpcNClsFound() < mintpcNClsdeuteron) { - return false; - } - fillCandCounter(kCandTPCNcls, isTrueCand); - - if (std::abs(trackProton.tpcNSigmaPr()) > tpcPIDNSigmaCut || std::abs(trackPion.tpcNSigmaPi()) > tpcPIDNSigmaCut || std::abs(trackDeuteron.tpcNSigmaDe()) > tpcPIDNSigmaCut) { - return false; - } - fillCandCounter(kCandTPCPID, isTrueCand); - - registry.fill(HIST("hDeuteronTOFVsPBeforeTOFCut"), trackDeuteron.sign() * trackDeuteron.p(), candData.tofNSigmaBachDe()); - if ((candData.tofNSigmaBachDe() < tofPIDNSigmaMin || candData.tofNSigmaBachDe() > tofPIDNSigmaMax) && trackDeuteron.p() > minDeuteronPUseTOF) { - return false; - } - fillCandCounter(kCandTOFPID, isTrueCand); - registry.fill(HIST("hDeuteronTOFVsPAtferTOFCut"), trackDeuteron.sign() * trackDeuteron.p(), candData.tofNSigmaBachDe()); - - double dcapion = isMatter ? candData.dcatrack1topv() : candData.dcatrack0topv(); - if (std::abs(dcapion) < dcapiontopv) { - return false; - } - fillCandCounter(kCandDcaToPV, isTrueCand); - - // Selection on candidate hypertriton - if (std::abs(candData.yHypertriton()) > rapiditycut) { - return false; - } - fillCandCounter(kCandRapidity, isTrueCand); - - double ct = candData.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassHyperTriton; - if (ct > lifetimecut) { - return false; - } - fillCandCounter(kCandct, isTrueCand); - - double cospa = candData.vtxcosPA(collision.posX(), collision.posY(), collision.posZ()); - if (cospa < vtxcospa) { - return false; - } - fillCandCounter(kCandCosPA, isTrueCand); - - if (candData.dcaVtxdaughters() > dcavtxdau) { - return false; - } - fillCandCounter(kCandDcaDau, isTrueCand); - - if ((isMatter && candData.mHypertriton() > h3LMassLowerlimit && candData.mHypertriton() < h3LMassUpperlimit)) { - // Hypertriton - registry.fill(HIST("hMassHypertriton"), candData.mHypertriton()); - registry.fill(HIST("hMassHypertritonTotal"), candData.mHypertriton()); - if (candData.mHypertriton() > lowersignallimit && candData.mHypertriton() < uppersignallimit) { - registry.fill(HIST("hDalitz"), RecoDecay::m2(std::array{std::array{candData.pxtrack0(), candData.pytrack0(), candData.pztrack0()}, std::array{candData.pxtrack2(), candData.pytrack2(), candData.pztrack2()}}, std::array{o2::constants::physics::MassProton, o2::constants::physics::MassDeuteron}), RecoDecay::m2(std::array{std::array{candData.pxtrack0(), candData.pytrack0(), candData.pztrack0()}, std::array{candData.pxtrack1(), candData.pytrack1(), candData.pztrack1()}}, std::array{o2::constants::physics::MassProton, o2::constants::physics::MassPionCharged})); - } - } else if ((!isMatter && candData.mAntiHypertriton() > h3LMassLowerlimit && candData.mAntiHypertriton() < h3LMassUpperlimit)) { - // AntiHypertriton - registry.fill(HIST("hMassAntiHypertriton"), candData.mAntiHypertriton()); - registry.fill(HIST("hMassHypertritonTotal"), candData.mAntiHypertriton()); - if (candData.mAntiHypertriton() > lowersignallimit && candData.mAntiHypertriton() < uppersignallimit) { - registry.fill(HIST("hDalitz"), RecoDecay::m2(std::array{std::array{candData.pxtrack1(), candData.pytrack1(), candData.pztrack1()}, std::array{candData.pxtrack2(), candData.pytrack2(), candData.pztrack2()}}, std::array{o2::constants::physics::MassProton, o2::constants::physics::MassDeuteron}), RecoDecay::m2(std::array{std::array{candData.pxtrack1(), candData.pytrack1(), candData.pztrack1()}, std::array{candData.pxtrack0(), candData.pytrack0(), candData.pztrack0()}}, std::array{o2::constants::physics::MassProton, o2::constants::physics::MassPionCharged})); - } - } else { - return false; - } - fillCandCounter(kCandInvMass, isTrueCand); - - return true; - } - - //------------------------------------------------------------------ - // Analysis process for a single candidate - template - void candidateAnalysis(TCollisionTable const& collision, TCandTable const& candData, bool& ifHasCandidate, bool isTrueCand = false, int lLabel = -1, TLorentzVector lmother = {0, 0, 0, 0}, double mcLifetime = -1, double isBachPrimary = false) - { - auto track0 = candData.template track0_as(); - auto track1 = candData.template track1_as(); - auto track2 = candData.template track2_as(); - - bool isMatter = track2.sign() > 0; // true if the candidate is hypertriton (p pi- d) - - auto& trackProton = isMatter ? track0 : track1; - auto& trackPion = isMatter ? track1 : track0; - auto& trackDeuteron = track2; - - if (selectCand(collision, candData, trackProton, trackPion, trackDeuteron, isMatter, isTrueCand)) { - ifHasCandidate = true; - fillCand(collision, candData, trackProton, trackPion, trackDeuteron, isMatter, isTrueCand, lLabel, lmother, mcLifetime, isBachPrimary); - } - } - - //------------------------------------------------------------------ - // Analysis process for like-sign candidates : (p pi- anti-d) or (anti-p pi+ d) - template - void likeSignAnalysis(TCollisionTable const& collision, TCandTable const& candData, bool& ifHasCandidate, bool isTrueCand = false, int lLabel = -1, TLorentzVector lmother = {0, 0, 0, 0}, double mcLifetime = -1, double isBachPrimary = false) - { - auto track0 = candData.template track0_as(); - auto track1 = candData.template track1_as(); - auto track2 = candData.template track2_as(); - - bool isMatter = track2.sign() < 0; // true if seach for background consists of (p pi- anti-d) - - // Assume proton has an oppisite charge with deuteron - auto& trackProton = isMatter ? track0 : track1; - auto& trackPion = isMatter ? track1 : track0; - auto& trackDeuteron = track2; - - if (selectCand(collision, candData, trackProton, trackPion, trackDeuteron, isMatter, isTrueCand)) { - ifHasCandidate = true; - fillCand(collision, candData, trackProton, trackPion, trackDeuteron, isMatter, isTrueCand, lLabel, lmother, mcLifetime, isBachPrimary); - // QA for if signals have the possibility to be reconginzed as a like-sign background - if (isMatter) { - registry.fill(HIST("hInvMassCorrectSign"), candData.mHypertriton()); - } else { - registry.fill(HIST("hInvMassCorrectSign"), candData.mAntiHypertriton()); - } - } - } - - //------------------------------------------------------------------ - // Analysis process for reduced data - template - void reducedAnalysis(TCollisionTable const& collision, TCandTable const& candData, TTracks tracks, bool isTrueCand = false, int lLabel = -1, TLorentzVector lmother = {0, 0, 0, 0}, double mcLifetime = -1, double isBachPrimary = false) - { - auto track0 = tracks.rawIteratorAt(candData.track0Id()); - auto track1 = tracks.rawIteratorAt(candData.track1Id()); - auto track2 = tracks.rawIteratorAt(candData.track2Id()); - - bool isMatter = track2.sign() > 0; // true if the candidate is hypertriton (p pi- d) - - auto& trackProton = isMatter ? track0 : track1; - auto& trackPion = isMatter ? track1 : track0; - auto& trackDeuteron = track2; - - if (selectCand(collision, candData, trackProton, trackPion, trackDeuteron, isMatter, isTrueCand)) { - fillCand(collision, candData, trackProton, trackPion, trackDeuteron, isMatter, isTrueCand, lLabel, lmother, mcLifetime, isBachPrimary); - } - } - - //------------------------------------------------------------------ - // Analysis process for reduced data with like-sign candidates - template - void reducedLikeSignAnalysis(TCollisionTable const& collision, TCandTable const& candData, TTracks tracks, bool isTrueCand = false, int lLabel = -1, TLorentzVector lmother = {0, 0, 0, 0}, double mcLifetime = -1, bool isBachPrimary = false) - { - auto track0 = tracks.rawIteratorAt(candData.track0Id()); - auto track1 = tracks.rawIteratorAt(candData.track1Id()); - auto track2 = tracks.rawIteratorAt(candData.track2Id()); - - bool isMatter = track2.sign() < 0; // true if seach for background consists of (p pi- anti-d) - - // Assume proton has an oppisite charge with deuteron - auto& trackProton = isMatter ? track0 : track1; - auto& trackPion = isMatter ? track1 : track0; - auto& trackDeuteron = track2; - - if (selectCand(collision, candData, trackProton, trackPion, trackDeuteron, isMatter, isTrueCand)) { - fillCand(collision, candData, trackProton, trackPion, trackDeuteron, isMatter, isTrueCand, lLabel, lmother, mcLifetime, isBachPrimary); - // QA for if signals have the possibility to be reconginzed as a like-sign background - if (isMatter) { - registry.fill(HIST("hInvMassCorrectSign"), candData.mHypertriton()); - } else { - registry.fill(HIST("hInvMassCorrectSign"), candData.mAntiHypertriton()); - } - } - } - - //------------------------------------------------------------------ - void fillOutputDataTable(Candidate3body const& cand3body) - { - outputDataTable(cand3body.colCentFT0C, - cand3body.isMatter, cand3body.invmass, cand3body.lcand.P(), cand3body.lcand.Pt(), cand3body.ct, - cand3body.cosPA, cand3body.dcadaughters, cand3body.dcacandtopv, cand3body.vtxradius, - cand3body.lproton.Pt(), cand3body.lproton.Eta(), cand3body.lproton.Phi(), cand3body.dauinnermostR[0], - cand3body.lpion.Pt(), cand3body.lpion.Eta(), cand3body.lpion.Phi(), cand3body.dauinnermostR[1], - cand3body.lbachelor.Pt(), cand3body.lbachelor.Eta(), cand3body.lbachelor.Phi(), cand3body.dauinnermostR[2], - cand3body.dautpcNclusters[0], cand3body.dautpcNclusters[1], cand3body.dautpcNclusters[2], - cand3body.dauitsclussize[0], cand3body.dauitsclussize[1], cand3body.dauitsclussize[2], - cand3body.dautpcNsigma[0], cand3body.dautpcNsigma[1], cand3body.dautpcNsigma[2], cand3body.bachelortofNsigma, - cand3body.daudcaxytopv[0], cand3body.daudcaxytopv[1], cand3body.daudcaxytopv[2], - cand3body.daudcatopv[0], cand3body.daudcatopv[1], cand3body.daudcatopv[2]); - } - - //------------------------------------------------------------------ - // collect information for generated hypertriton (should be called after event selection) - void getGeneratedH3LInfo(aod::McParticles const& particlesMC) - { - for (const auto& mcparticle : particlesMC) { - if (std::abs(mcparticle.pdgCode()) != motherPdgCode) { - continue; - } - registry.fill(HIST("hGeneratedHypertritonCounter"), 0.5); - - bool haveProton = false, havePionPlus = false, haveDeuteron = false; - bool haveAntiProton = false, havePionMinus = false, haveAntiDeuteron = false; - double mcLifetime = -1; - for (const auto& mcparticleDaughter : mcparticle.template daughters_as()) { - if (mcparticleDaughter.pdgCode() == PDG_t::kProton) - haveProton = true; - if (mcparticleDaughter.pdgCode() == PDG_t::kProtonBar) - haveAntiProton = true; - if (mcparticleDaughter.pdgCode() == PDG_t::kPiPlus) - havePionPlus = true; - if (mcparticleDaughter.pdgCode() == -PDG_t::kPiPlus) - havePionMinus = true; - if (mcparticleDaughter.pdgCode() == bachelorPdgCode) { - haveDeuteron = true; - mcLifetime = RecoDecay::sqrtSumOfSquares(mcparticleDaughter.vx() - mcparticle.vx(), mcparticleDaughter.vy() - mcparticle.vy(), mcparticleDaughter.vz() - mcparticle.vz()) * o2::constants::physics::MassHyperTriton / mcparticle.p(); - } - if (mcparticleDaughter.pdgCode() == -bachelorPdgCode) { - haveAntiDeuteron = true; - mcLifetime = RecoDecay::sqrtSumOfSquares(mcparticleDaughter.vx() - mcparticle.vx(), mcparticleDaughter.vy() - mcparticle.vy(), mcparticleDaughter.vz() - mcparticle.vz()) * o2::constants::physics::MassHyperTriton / mcparticle.p(); - } - } - if (haveProton && havePionMinus && haveDeuteron && mcparticle.pdgCode() == motherPdgCode) { - registry.fill(HIST("hGeneratedHypertritonCounter"), 1.5); - registry.fill(HIST("hPtGeneratedHypertriton"), mcparticle.pt()); - registry.fill(HIST("hctGeneratedHypertriton"), mcLifetime); - registry.fill(HIST("hEtaGeneratedHypertriton"), mcparticle.eta()); - registry.fill(HIST("hRapidityGeneratedHypertriton"), mcparticle.y()); - } else if (haveAntiProton && havePionPlus && haveAntiDeuteron && mcparticle.pdgCode() == -motherPdgCode) { - registry.fill(HIST("hGeneratedHypertritonCounter"), 1.5); - registry.fill(HIST("hPtGeneratedAntiHypertriton"), mcparticle.pt()); - registry.fill(HIST("hctGeneratedAntiHypertriton"), mcLifetime); - registry.fill(HIST("hEtaGeneratedAntiHypertriton"), mcparticle.eta()); - registry.fill(HIST("hRapidityGeneratedAntiHypertriton"), mcparticle.y()); - } - } - } - - //------------------------------------------------------------------ - // process real data analysis - void processData(soa::Join const& collisions, aod::Vtx3BodyDatas const& vtx3bodydatas, FullTracksExtIU const&, aod::BCsWithTimestamps const&) - { - for (const auto& collision : collisions) { - candidates3body.clear(); - - if (!eventSelection(collision)) { - continue; - } - - bool ifHasCandidate = false; - auto d3BodyCands = vtx3bodydatas.sliceBy(perCollisionVtx3BodyDatas, collision.globalIndex()); - for (const auto& vtx : d3BodyCands) { - if (cfgLikeSignAnalysis) { - likeSignAnalysis(collision, vtx, ifHasCandidate); - } else { - candidateAnalysis(collision, vtx, ifHasCandidate); - } - } - - if (ifHasCandidate) { - auto bc = collision.bc_as(); - auto triggerSelection = zorro.getTriggerOfInterestResults(bc.globalBC(), bcTolerance); - for (size_t i = 0; i < triggerSelection.size(); i++) { - if (triggerSelection[i]) { - registry.fill(HIST("hEventTriggerCount"), i + 0.5); - } - } - if (zorro.isNotSelectedByAny(bc.globalBC(), bcTolerance)) { - registry.fill(HIST("hEventTriggerCount"), triggerLabels.size() + 0.5); - } - registry.fill(HIST("hEventCounter"), 4.5); - } - fillHistos(); - resetHistos(); - - for (const auto& cand3body : candidates3body) { - fillOutputDataTable(cand3body); - } - } - } - PROCESS_SWITCH(ThreebodyRecoTask, processData, "Real data reconstruction", true); - - //------------------------------------------------------------------ - // process reduced data analysis - void processReducedData(ReducedCols const& collisions, aod::Vtx3BodyDatas const& vtx3bodydatas, aod::RedIUTracks const& tracks) - { - candidates3body.clear(); - - registry.fill(HIST("hEventCounter"), 0.5, collisions.size()); - - for (const auto& vtx : vtx3bodydatas) { - const auto& collision = collisions.iteratorAt(vtx.collisionId()); - if (cfgLikeSignAnalysis) { - reducedLikeSignAnalysis(collision, vtx, tracks); - } else { - reducedAnalysis(collision, vtx, tracks); - } - for (const auto& cand3body : candidates3body) { - fillOutputDataTable(cand3body); - } - candidates3body.clear(); - } - fillHistos(); - resetHistos(); - } - PROCESS_SWITCH(ThreebodyRecoTask, processReducedData, "Reduced data reconstruction", false); - - //------------------------------------------------------------------ - // process mc analysis - void processMC(soa::Join const& collisions, aod::Vtx3BodyDatas const& vtx3bodydatas, aod::McParticles const& particlesMC, MCLabeledTracksIU const& /*tracks*/, aod::McCollisions const& mcCollisions) - { - filledMothers.clear(); - getGeneratedH3LInfo(particlesMC); - isGoodCollision.resize(mcCollisions.size(), false); - - for (const auto& collision : collisions) { - candidates3body.clear(); - registry.fill(HIST("hEventCounter"), 0.5); - if (mcEventCut && (!collision.selection_bit(aod::evsel::kIsTriggerTVX) || !collision.selection_bit(aod::evsel::kNoTimeFrameBorder))) { - continue; - } - registry.fill(HIST("hEventCounter"), 1.5); - if (eventPosZCut && std::abs(collision.posZ()) > 10.f) { // 10cm - continue; - } - registry.fill(HIST("hEventCounter"), 2.5); - registry.fill(HIST("hCentFT0C"), collision.centFT0C()); - - if (collision.mcCollisionId() >= 0) { - isGoodCollision[collision.mcCollisionId()] = true; - } - - bool ifHasCandidate = false; - auto vtxsThisCol = vtx3bodydatas.sliceBy(perCollisionVtx3BodyDatas, collision.globalIndex()); - - for (const auto& vtx : vtxsThisCol) { - bool isBachPrimary = false; - int lLabel = -1; - int lPDG = -1; - double mcLifetime = -1; - TLorentzVector lmother; - bool isTrueCand = false; - auto track0 = vtx.track0_as(); - auto track1 = vtx.track1_as(); - auto track2 = vtx.track2_as(); - if (track0.has_mcParticle() && track1.has_mcParticle() && track2.has_mcParticle()) { - auto lMCTrack0 = track0.mcParticle_as(); - auto lMCTrack1 = track1.mcParticle_as(); - auto lMCTrack2 = track2.mcParticle_as(); - - if (lMCTrack2.isPhysicalPrimary()) { - isBachPrimary = true; - } - - if (lMCTrack0.has_mothers() && lMCTrack1.has_mothers() && lMCTrack2.has_mothers()) { - for (const auto& lMother0 : lMCTrack0.mothers_as()) { - for (const auto& lMother1 : lMCTrack1.mothers_as()) { - for (const auto& lMother2 : lMCTrack2.mothers_as()) { - if (lMother0.globalIndex() == lMother1.globalIndex() && lMother0.globalIndex() == lMother2.globalIndex()) { - lLabel = lMother0.globalIndex(); - lPDG = lMother0.pdgCode(); - if ((lPDG == motherPdgCode && lMCTrack0.pdgCode() == PDG_t::kProton && lMCTrack1.pdgCode() == PDG_t::kPiMinus && lMCTrack2.pdgCode() == bachelorPdgCode) || - (lPDG == -motherPdgCode && lMCTrack0.pdgCode() == PDG_t::kPiPlus && lMCTrack1.pdgCode() == PDG_t::kProtonBar && lMCTrack2.pdgCode() == -bachelorPdgCode)) { - isTrueCand = true; - mcLifetime = RecoDecay::sqrtSumOfSquares(lMCTrack2.vx() - lMother2.vx(), lMCTrack2.vy() - lMother2.vy(), lMCTrack2.vz() - lMother2.vz()) * o2::constants::physics::MassHyperTriton / lMother2.p(); - lmother.SetXYZM(lMother0.px(), lMother0.py(), lMother0.pz(), o2::constants::physics::MassHyperTriton); - } - } - } - } - } - } - } - - candidateAnalysis(collision, vtx, ifHasCandidate, isTrueCand, lLabel, lmother, mcLifetime, isBachPrimary); - } - - if (ifHasCandidate) - registry.fill(HIST("hEventCounter"), 4.5); - fillHistos(); - resetHistos(); - - for (const auto& cand3body : candidates3body) { - outputMCTable(cand3body.colCentFT0C, - cand3body.isMatter, cand3body.invmass, cand3body.lcand.P(), cand3body.lcand.Pt(), cand3body.ct, - cand3body.cosPA, cand3body.dcadaughters, cand3body.dcacandtopv, cand3body.vtxradius, - cand3body.lproton.Pt(), cand3body.lproton.Eta(), cand3body.lproton.Phi(), cand3body.dauinnermostR[0], - cand3body.lpion.Pt(), cand3body.lpion.Eta(), cand3body.lpion.Phi(), cand3body.dauinnermostR[1], - cand3body.lbachelor.Pt(), cand3body.lbachelor.Eta(), cand3body.lbachelor.Phi(), cand3body.dauinnermostR[2], - cand3body.dautpcNclusters[0], cand3body.dautpcNclusters[1], cand3body.dautpcNclusters[2], - cand3body.dauitsclussize[0], cand3body.dauitsclussize[1], cand3body.dauitsclussize[2], - cand3body.dautpcNsigma[0], cand3body.dautpcNsigma[1], cand3body.dautpcNsigma[2], cand3body.bachelortofNsigma, - cand3body.daudcaxytopv[0], cand3body.daudcaxytopv[1], cand3body.daudcaxytopv[2], - cand3body.daudcatopv[0], cand3body.daudcatopv[1], cand3body.daudcatopv[2], - cand3body.isBachPrimary, - cand3body.lgencand.P(), cand3body.lgencand.Pt(), cand3body.genct, cand3body.lgencand.Phi(), cand3body.lgencand.Eta(), cand3body.lgencand.Rapidity(), - cand3body.isSignal, cand3body.isReco, cand3body.pdgCode, cand3body.survivedEventSelection); - } - } - - // now we fill only the signal candidates that were not reconstructed - for (const auto& mcparticle : particlesMC) { - if (!is3bodyDecayed(mcparticle)) { - continue; - } - if (std::find(filledMothers.begin(), filledMothers.end(), mcparticle.globalIndex()) != std::end(filledMothers)) { - continue; - } - bool isSurEvSelection = isGoodCollision[mcparticle.mcCollisionId()]; - std::array posSV{0.f}; - for (const auto& mcDaughter : mcparticle.daughters_as()) { - if (std::abs(mcDaughter.pdgCode()) == bachelorPdgCode) { - posSV = {mcDaughter.vx(), mcDaughter.vy(), mcDaughter.vz()}; - } - } - double mcLifetime = RecoDecay::sqrtSumOfSquares(posSV[0] - mcparticle.vx(), posSV[1] - mcparticle.vy(), posSV[2] - mcparticle.vz()) * o2::constants::physics::MassHyperTriton / mcparticle.p(); - outputMCTable(-1, - -1, -1, -1, -1, -1, - -1, -1, -1, -1, - -1, -1, -1, -1, - -1, -1, -1, -1, - -1, -1, -1, -1, - -1, -1, -1, - -1, -1, -1, - -1, -1, -1, -1, - -1, -1, -1, - -1, -1, -1, - false, - mcparticle.p(), mcparticle.pt(), mcLifetime, mcparticle.phi(), mcparticle.eta(), mcparticle.y(), - true, false, mcparticle.pdgCode(), isSurEvSelection); - } - } - PROCESS_SWITCH(ThreebodyRecoTask, processMC, "MC reconstruction", false); -}; - -WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) -{ - return WorkflowSpec{ - adaptAnalysisTask(cfgc), - }; -} diff --git a/PWGLF/Tasks/Nuspex/CMakeLists.txt b/PWGLF/Tasks/Nuspex/CMakeLists.txt index b2af549c871..895e15935fc 100644 --- a/PWGLF/Tasks/Nuspex/CMakeLists.txt +++ b/PWGLF/Tasks/Nuspex/CMakeLists.txt @@ -24,16 +24,6 @@ o2physics_add_dpl_workflow(nuclei-hist PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) -o2physics_add_dpl_workflow(hypertriton3bodyanalysis - SOURCES hypertriton3bodyanalysis.cxx - PUBLIC_LINK_LIBRARIES O2::DCAFitter O2Physics::AnalysisCore - COMPONENT_NAME Analysis) - -o2physics_add_dpl_workflow(hypertriton3bodymcqa - SOURCES hypertriton3bodyMcqa.cxx - PUBLIC_LINK_LIBRARIES O2::DCAFitter O2Physics::AnalysisCore O2::TOFBase - COMPONENT_NAME Analysis) - o2physics_add_dpl_workflow(helium-flow SOURCES helium_flow.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore diff --git a/PWGLF/Tasks/Nuspex/hypertriton3bodyMcqa.cxx b/PWGLF/Tasks/Nuspex/hypertriton3bodyMcqa.cxx deleted file mode 100644 index ef8dfb4b958..00000000000 --- a/PWGLF/Tasks/Nuspex/hypertriton3bodyMcqa.cxx +++ /dev/null @@ -1,908 +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 hypertriton3bodyMcqa.cxx -/// \brief QA for MC productions which contain hypertriton 3body decay process, including special checks for TOF PID -/// \author Yuanzhe Wang - -#include -#include -#include -#include -#include -#include -#include - -#include "CommonDataFormat/InteractionRecord.h" -#include "CommonDataFormat/IRFrame.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.h" -#include "ReconstructionDataFormats/Track.h" -#include "Common/Core/RecoDecay.h" -#include "Common/Core/trackUtilities.h" -#include "PWGLF/DataModel/LFStrangenessTables.h" -#include "PWGLF/DataModel/pidTOFGeneric.h" -#include "Common/Core/TrackSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "Common/TableProducer/PID/pidTOFBase.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/Centrality.h" -#include "Common/DataModel/PIDResponse.h" -#include "CommonConstants/PhysicsConstants.h" -#include "CCDB/BasicCCDBManager.h" - -using namespace o2; -using namespace o2::framework; -using namespace o2::framework::expressions; -using std::array; -using ColwithEvTimes = o2::soa::Join; -using FullTracksExtIU = soa::Join; -using MCLabeledTracksIU = soa::Join; - -template -bool is3bodyDecayedH3L(TMCParticle const& particle) -{ - if (std::abs(particle.pdgCode()) != 1010010030) { - return false; - } - bool haveProton = false, havePion = false, haveDeuteron = false; - bool haveAntiProton = false, haveAntiPion = false, haveAntiDeuteron = false; - for (const auto& mcDaughter : particle.template daughters_as()) { - if (mcDaughter.pdgCode() == 2212) - haveProton = true; - if (mcDaughter.pdgCode() == -2212) - haveAntiProton = true; - if (mcDaughter.pdgCode() == 211) - havePion = true; - if (mcDaughter.pdgCode() == -211) - haveAntiPion = true; - if (mcDaughter.pdgCode() == 1000010020) - haveDeuteron = true; - if (mcDaughter.pdgCode() == -1000010020) - haveAntiDeuteron = true; - } - if (haveProton && haveAntiPion && haveDeuteron && particle.pdgCode() > 0) { - return true; - } else if (haveAntiProton && havePion && haveAntiDeuteron && particle.pdgCode() < 0) { - return true; - } - return false; -} - -template -bool isPairedH3LDaughters(TMCParticle const& mctrack0, TMCParticle const& mctrack1, TMCParticle const& mctrack2) -{ - for (const auto& particleMother : mctrack0.template mothers_as()) { - if (!(particleMother.pdgCode() == 1010010030 && mctrack0.pdgCode() == 2212 && mctrack1.pdgCode() == -211 && mctrack2.pdgCode() == 1000010020) && - !(particleMother.pdgCode() == -1010010030 && mctrack0.pdgCode() == -2212 && mctrack1.pdgCode() == 211 && mctrack2.pdgCode() == -1000010020)) { - continue; - } - bool flag1 = false, flag2 = false; - for (const auto& mcDaughter : particleMother.template daughters_as()) { - if (mcDaughter.globalIndex() == mctrack1.globalIndex()) - flag1 = true; - if (mcDaughter.globalIndex() == mctrack2.globalIndex()) - flag2 = true; - } - if (!flag1 || !flag2) - continue; - // move the requirement in mass region into the loop to draw a histogram - // double hypertritonMCMass = RecoDecay::m(array{array{mctrack0.px(), mctrack0.py(), mctrack0.pz()}, array{mctrack1.px(), mctrack1.py(), mctrack1.pz()}, array{mctrack2.px(), mctrack2.py(), mctrack2.pz()}}, array{o2::constants::physics::MassProton, o2::constants::physics::MassPionCharged, o2::constants::physics::MassDeuteron}); - // if (hypertritonMCMass > 2.990 && hypertritonMCMass < 2.993) - return true; - } - return false; -} - -// check the properties of daughters candidates and true daughters -struct Hypertriton3bodyMcqa { - - Service ccdb; - Preslice perCollisionTracks = aod::track::collisionId; - - int mRunNumber; - - // Basic checks - HistogramRegistry registry{ - "registry", - { - {"hEventCounter", "hEventCounter", {HistType::kTH1F, {{3, 0.0f, 3.0f}}}}, - {"hParticleCounter", "hParticleCounter", {HistType::kTH1F, {{7, 0.0f, 7.0f}}}}, - - {"hTPCNCls", "hTPCNCls", {HistType::kTH1F, {{160, 0.0f, 160.0f}}}}, - {"hTPCNClsCrossedRows", "hTPCNClsCrossedRows", {HistType::kTH1F, {{160, 0.0f, 160.0f}}}}, - {"hTrackEta", "hTrackEta", {HistType::kTH1F, {{200, -10.0f, 10.0f}}}}, - {"hTrackITSNcls", "hTrackITSNcls", {HistType::kTH1F, {{10, 0.0f, 10.0f}}}}, - {"hTrackMcRapidity", "hTrackMcRapidity", {HistType::kTH1F, {{200, -10.0f, 10.0f}}}}, - {"hTrackNsigmaProton", "hTrackNsigmaProton", {HistType::kTH1F, {{120, -6.0f, 6.0f}}}}, - {"hTrackNsigmaPion", "hTrackNsigmaPion", {HistType::kTH1F, {{120, -6.0f, 6.0f}}}}, - {"hTrackNsigmaDeuteron", "hTrackNsigmaDeuteron", {HistType::kTH1F, {{120, -6.0f, 6.0f}}}}, - - {"hHypertritonEta", "hHypertritomEta", {HistType::kTH1F, {{200, -10.0f, 10.0f}}}}, - {"hHypertritonMcRapidity", "hHypertritonMcRapidity", {HistType::kTH1F, {{200, -10.0f, 10.0f}}}}, - {"hHypertritonMcPt", "hHypertritonMcPt", {HistType::kTH1F, {{300, 0.0f, 15.0f}}}}, - - {"hProtonCounter", "hProtonCounter", {HistType::kTH1F, {{2, 0.0f, 2.0f}}}}, - {"hProtonPt", "hProtonPt", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, - {"hProtonP", "hProtonP", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, - {"hProtonMcPt", "hProtonMcPt", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, - {"hProtonMcP", "hProtonMcP", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, - {"hProtonEta", "hProtonEta", {HistType::kTH1F, {{200, -10.0f, 10.0f}}}}, - {"hProtonMcRapidity", "hProtonMcRapidity", {HistType::kTH1F, {{200, -10.0f, 10.0f}}}}, - {"hProtonNsigmaProton", "hProtonNsigmaProton", {HistType::kTH1F, {{120, -6.0f, 6.0f}}}}, - {"hProtonTPCNCls", "hProtonTPCNCls", {HistType::kTH1F, {{120, 0.0f, 120.0f}}}}, - {"hProtonTPCBB", "hProtonTPCBB", {HistType::kTH2F, {{320, -8.0f, 8.0f, "p/z(GeV/c)"}, {200, 0.0f, 1000.0f, "TPCSignal"}}}}, - {"hProtonTPCBBAfterTPCNclsCut", "hProtonTPCBBAfterTPCNclsCut", {HistType::kTH2F, {{320, -8.0f, 8.0f, "p/z(GeV/c)"}, {200, 0.0f, 1000.0f, "TPCSignal"}}}}, - {"hDauProtonPt", "hDauProtonPt", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, - {"hDauProtonMcPt", "hDauProtonMcPt", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, - {"hDauProtonNsigmaProton", "hDauProtonNsigmaProton", {HistType::kTH1F, {{120, -6.0f, 6.0f}}}}, - {"hDauProtonTPCVsPt", "hDauProtonTPCVsPt", {HistType::kTH2F, {{50, 0.0f, 5.0f, "#it{p}_{T} (GeV/c)"}, {120, -6.0f, 6.0f, "TPC n#sigma"}}}}, - - {"hPionCounter", "hPionCounter", {HistType::kTH1F, {{2, 0.0f, 2.0f}}}}, - {"hPionPt", "hPionPt", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, - {"hPionP", "hPionP", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, - {"hPionMcPt", "hPionMcPt", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, - {"hPionMcP", "hPionMcP", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, - {"hPionEta", "hPionEta", {HistType::kTH1F, {{200, -10.0f, 10.0f}}}}, - {"hPionMcRapidity", "hPionMcRapidity", {HistType::kTH1F, {{200, -10.0f, 10.0f}}}}, - {"hPionNsigmaPion", "hPionNsigmaPion", {HistType::kTH1F, {{120, -6.0f, 6.0f}}}}, - {"hPionTPCNCls", "hPionTPCNCls", {HistType::kTH1F, {{160, 0.0f, 160.0f}}}}, - {"hPionTPCBB", "hPionTPCBB", {HistType::kTH2F, {{320, -8.0f, 8.0f, "p/z(GeV/c)"}, {200, 0.0f, 1000.0f, "TPCSignal"}}}}, - {"hPionTPCBBAfterTPCNclsCut", "hPionTPCBBAfterTPCNclsCut", {HistType::kTH2F, {{320, -8.0f, 8.0f, "p/z(GeV/c)"}, {200, 0.0f, 1000.0f, "TPCSignal"}}}}, - {"hDauPionPt", "hDauPionPt", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, - {"hDauPionMcPt", "hDauPionMcPt", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, - {"hDauPionNsigmaPion", "hDauPionNsigmaPion", {HistType::kTH1F, {{120, -6.0f, 6.0f}}}}, - {"hDauPionTPCVsPt", "hDauPionTPCVsPt", {HistType::kTH2F, {{20, 0.0f, 2.0f, "#it{p}_{T} (GeV/c)"}, {120, -6.0f, 6.0f, "TPC n#sigma"}}}}, - {"hDauPionDcaXY", "hDauPionDcaXY", {HistType::kTH1F, {{100, -10.0f, 10.0f}}}}, - - {"hDeuteronCounter", "hDeuteronCounter", {HistType::kTH1F, {{2, 0.0f, 2.0f}}}}, - {"hDeuteronPt", "hDeuteronPt", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, - {"hDeuteronP", "hDeuteronP", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, - {"hDeuteronMcPt", "hDeuteronMcPt", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, - {"hDeuteronMcP", "hDeuteronMcP", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, - {"hDeuteronEta", "hDeuteronEta", {HistType::kTH1F, {{200, -10.0f, 10.0f}}}}, - {"hDeuteronMcRapidity", "hDeuteronMcRapidity", {HistType::kTH1F, {{200, -10.0f, 10.0f}}}}, - {"hDeuteronNsigmaDeuteron", "hDeuteronNsigmaDeuteron", {HistType::kTH1F, {{120, -6.0f, 6.0f}}}}, - {"hDeuteronTPCNCls", "hDeuteronTPCNCls", {HistType::kTH1F, {{120, 0.0f, 120.0f}}}}, - {"hDeuteronTPCBB", "hDeuteronTPCBB", {HistType::kTH2F, {{320, -8.0f, 8.0f, "p/z(GeV/c)"}, {200, 0.0f, 1000.0f, "TPCSignal"}}}}, - {"hDeuteronTPCBBAfterTPCNclsCut", "hDeuteronTPCBBAfterTPCNclsCut", {HistType::kTH2F, {{320, -8.0f, 8.0f, "p/z(GeV/c)"}, {200, 0.0f, 1000.0f, "TPCSignal"}}}}, - {"hDauDeuteronPt", "hDauDeuteronPt", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, - {"hDauDeuteronMcPt", "hDauDeuteronMcPt", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, - {"hDauDeuteronTPCVsPt", "hDauDeuteronTPCVsPt", {HistType::kTH2F, {{80, 0.0f, 8.0f, "#it{p}_{T} (GeV/c)"}, {120, -6.0f, 6.0f, "TPC n#sigma"}}}}, - {"hDauDeuteronTOFNSigmaVsP", "hDauDeuteronTOFNSigmaVsP", {HistType::kTH2F, {{40, -10.0f, 10.0f, "p/z (GeV/c)"}, {600, -300.0f, 300.0f, "TOF n#sigma"}}}}, - {"hDauDeuteronTOFNSigmaVsPHasTOF", "hDauDeuteronTOFNSigmaVsPHasTOF", {HistType::kTH2F, {{40, -10.0f, 10.0f, "p/z (GeV/c)"}, {600, -300.0f, 300.0f, "TOF n#sigma"}}}}, - {"hDauDeuteronMatchCounter", "hDauDeuteronMatchCounter", {HistType::kTH1F, {{4, 0.0f, 4.0f}}}}, - - {"hTPCBB", "hTPCBB", {HistType::kTH2F, {{120, -8.0f, 8.0f, "p/z(GeV/c)"}, {100, 0.0f, 1000.0f, "TPCSignal"}}}}, - - {"hPairedH3LDaughers", "hPairedH3LDaughers", {HistType::kTH1F, {{3, 0.0f, 3.0f}}}}, - {"hPairedH3LDaughersInvMass", "hPairedH3LDaughersInvMass", {HistType::kTH1F, {{300, 2.9f, 3.2f}}}}, - {"hDuplicatedH3LDaughers", "hDuplicatedH3LDaughers", {HistType::kTH1F, {{3, 0.0f, 3.0f}}}}, - - // Diff checks always requir hasTOF - {"hDiffTrackTOFSignal", "hDiffTrackTOFSignal", {HistType::kTH1F, {{200, -1.0f, 1.0f}}}}, - {"hDiffEvTimeForTrack", "hDiffEvTimeForTrack", {HistType::kTH1F, {{200, -1.0f, 1.0f}}}}, - {"hDiffTrackTOFNSigmaDe", "hDiffTrackTOFNSigmaDe", {HistType::kTH1F, {{200, -1.0f, 1.0f}}}}, - {"hDauDeuteronNewTOFNSigmaVsP", "hDauDeuteronNewTOFNSigmaVsP", {HistType::kTH2F, {{40, -10.0f, 10.0f, "p/z (GeV/c)"}, {600, -300.0f, 300.0f, "TOF n#sigma"}}}}, - {"hWrongDeuteronTOFNSigmaVsP", "hWrongDeuteronTOFNSigmaVsP", {HistType::kTH2F, {{40, -10.0f, 10.0f, "p/z (GeV/c)"}, {600, -300.0f, 300.0f, "TOF n#sigma"}}}}, - {"hWrongDeuteronNewTOFNSigmaVsP", "hWrongDeuteronNewTOFNSigmaVsP", {HistType::kTH2F, {{40, -10.0f, 10.0f, "p/z (GeV/c)"}, {600, -300.0f, 300.0f, "TOF n#sigma"}}}}, - {"hDiffColTime", "hDiffColTime", {HistType::kTH1F, {{200, -100.0f, 100.0f}}}}, - {"hDauDeuteronDiffTOFNsigmaDeHasTOF", "hDauDeuteronDiffTOFNsigmaDeHasTOF", {HistType::kTH1F, {{200, -100.0f, 100.0f}}}}, - - // _v2 for using relinked collision - {"hDauDeuteronTOFNSigmaVsP_CorrectCol", "hDauDeuteronTOFNSigmaVsP_CorrectCol", {HistType::kTH2F, {{40, -10.0f, 10.0f, "p/z (GeV/c)"}, {600, -300.0f, 300.0f, "TOF n#sigma"}}}}, - {"hDauDeuteronNewTOFNSigmaVsP_CorrectCol", "hDauDeuteronNewTOFNSigmaVsP_CorrectCol", {HistType::kTH2F, {{40, -10.0f, 10.0f, "p/z (GeV/c)"}, {600, -300.0f, 300.0f, "TOF n#sigma"}}}}, - {"hDauDeuteronTOFNSigmaVsP_v2", "hDauDeuteronTOFNSigmaVsP_v2", {HistType::kTH2F, {{40, -10.0f, 10.0f, "p/z (GeV/c)"}, {600, -300.0f, 300.0f, "TOF n#sigma"}}}}, - {"hDauDeuteronNewTOFNSigmaVsP_v2_AO2D", "hDauDeuteronNewTOFNSigmaVsP_v2 AO2D", {HistType::kTH2F, {{40, -10.0f, 10.0f, "p/z (GeV/c)"}, {600, -300.0f, 300.0f, "TOF n#sigma"}}}}, - {"hDauDeuteronNewTOFNSigmaVsP_v2_EvSel", "hDauDeuteronNewTOFNSigmaVsP_v2 EvSel", {HistType::kTH2F, {{40, -10.0f, 10.0f, "p/z (GeV/c)"}, {600, -300.0f, 300.0f, "TOF n#sigma"}}}}, - {"hDauDeuteronTOFNSigmaVsColTimeRes_v2", "hDauDeuteronTOFNSigmaVsColTimeRes_v2", {HistType::kTH2F, {{100, 0.0f, 400.0f, "CollisionTimeRes(ns)"}, {600, -300.0f, 300.0f, "TOF n#sigma"}}}}, - {"hDauDeuteronTOFNSigmaVsColTimeRes_v2_AO2D", "hDauDeuteronTOFNSigmaVsColTimeRes_v2 AO2D", {HistType::kTH2F, {{100, 0.0f, 400.0f, "CollisionTimeRes(ns)"}, {600, -300.0f, 300.0f, "TOF n#sigma"}}}}, - {"hDauDeuteronTOFNSigmaVsColTimeRes_v2_EvSel", "hDauDeuteronTOFNSigmaVsColTimeRes_v2 EvSel", {HistType::kTH2F, {{100, 0.0f, 400.0f, "CollisionTimeRes(ns)"}, {600, -300.0f, 300.0f, "TOF n#sigma"}}}}, - {"hDauDeuteronTOFPIDCounter", "hDauDeuteronTOFPIDCounter", {HistType::kTH1F, {{5, 0.0f, 5.0f}}}}, - {"hDauDeuteronTOFPIDCounter_CloseBC", "hDauDeuteronTOFPIDCounter CloseBC", {HistType::kTH1F, {{5, 0.0f, 5.0f}}}}, - }, - }; - - void init(InitContext&) - { - registry.get(HIST("hParticleCounter"))->GetXaxis()->SetBinLabel(1, "Readin"); - registry.get(HIST("hParticleCounter"))->GetXaxis()->SetBinLabel(2, "Has_mcparticle"); - registry.get(HIST("hParticleCounter"))->GetXaxis()->SetBinLabel(3, "Rapidity Cut"); - registry.get(HIST("hParticleCounter"))->GetXaxis()->SetBinLabel(4, "McisHypertriton"); - registry.get(HIST("hParticleCounter"))->GetXaxis()->SetBinLabel(5, "McisProton"); - registry.get(HIST("hParticleCounter"))->GetXaxis()->SetBinLabel(6, "McisPion"); - registry.get(HIST("hParticleCounter"))->GetXaxis()->SetBinLabel(7, "McisDeuteron"); - - TString trackCounterbinLabel[2] = {"hasMom", "FromHypertriton"}; - for (int i{0}; i < 2; i++) { - registry.get(HIST("hProtonCounter"))->GetXaxis()->SetBinLabel(i + 1, trackCounterbinLabel[i]); - registry.get(HIST("hPionCounter"))->GetXaxis()->SetBinLabel(i + 1, trackCounterbinLabel[i]); - registry.get(HIST("hDeuteronCounter"))->GetXaxis()->SetBinLabel(i + 1, trackCounterbinLabel[i]); - } - registry.get(HIST("hDuplicatedH3LDaughers"))->GetXaxis()->SetBinLabel(1, "proton"); - registry.get(HIST("hDuplicatedH3LDaughers"))->GetXaxis()->SetBinLabel(2, "pion"); - registry.get(HIST("hDuplicatedH3LDaughers"))->GetXaxis()->SetBinLabel(3, "deuteron"); - - registry.get(HIST("hDauDeuteronMatchCounter"))->GetXaxis()->SetBinLabel(1, "Total"); - registry.get(HIST("hDauDeuteronMatchCounter"))->GetXaxis()->SetBinLabel(2, "correct collision"); - registry.get(HIST("hDauDeuteronMatchCounter"))->GetXaxis()->SetBinLabel(3, "hasTOF"); - registry.get(HIST("hDauDeuteronMatchCounter"))->GetXaxis()->SetBinLabel(4, "hasTOF & correct collsion"); - - registry.get(HIST("hDauDeuteronTOFPIDCounter"))->GetXaxis()->SetBinLabel(1, "Origin |n#sigma| >= 5"); - registry.get(HIST("hDauDeuteronTOFPIDCounter"))->GetXaxis()->SetBinLabel(2, "BothBC work"); - registry.get(HIST("hDauDeuteronTOFPIDCounter"))->GetXaxis()->SetBinLabel(3, "Only BCAO2D work"); - registry.get(HIST("hDauDeuteronTOFPIDCounter"))->GetXaxis()->SetBinLabel(4, "Only BCEvSel work"); - registry.get(HIST("hDauDeuteronTOFPIDCounter"))->GetXaxis()->SetBinLabel(5, "BothBC not work"); - registry.get(HIST("hDauDeuteronTOFPIDCounter_CloseBC"))->GetXaxis()->SetBinLabel(1, "Origin |n#sigma| < 6"); - registry.get(HIST("hDauDeuteronTOFPIDCounter_CloseBC"))->GetXaxis()->SetBinLabel(2, "BothBC work"); - registry.get(HIST("hDauDeuteronTOFPIDCounter_CloseBC"))->GetXaxis()->SetBinLabel(3, "Only BCAO2D work"); - registry.get(HIST("hDauDeuteronTOFPIDCounter_CloseBC"))->GetXaxis()->SetBinLabel(4, "Only BCEvSel work"); - registry.get(HIST("hDauDeuteronTOFPIDCounter_CloseBC"))->GetXaxis()->SetBinLabel(5, "BothBC not work"); - } - - Configurable dcapiontopv{"dcapiontopv", .05, "DCA Pion To PV"}; - Configurable minProtonPt{"minProtonPt", 0.3, "minProtonPt"}; - Configurable maxProtonPt{"maxProtonPt", 5, "maxProtonPt"}; - Configurable minPionPt{"minPionPt", 0.1, "minPionPt"}; - Configurable maxPionPt{"maxPionPt", 1.2, "maxPionPt"}; - Configurable minDeuteronPt{"minDeuteronPt", 0.6, "minDeuteronPt"}; - Configurable maxDeuteronPt{"maxDeuteronPt", 10, "maxDeuteronPt"}; - Configurable mc_event_selection{"mc_event_selection", true, "mc event selection count post kIsTriggerTVX and kNoTimeFrameBorder"}; - Configurable event_posZ_selection{"event_posZ_selection", true, "event selection count post poZ cut"}; - - // CCDB TOF PID paras - Configurable timestamp{"ccdb-timestamp", -1, "timestamp of the object"}; - 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 passName{"passName", "", "Name of the pass inside of the CCDB parameter collection. If empty, the automatically deceted from metadata (to be implemented!!!)"}; - Configurable timeShiftCCDBPath{"timeShiftCCDBPath", "", "Path of the TOF time shift vs eta. If empty none is taken"}; - Configurable loadResponseFromCCDB{"loadResponseFromCCDB", false, "Flag to load the response from the CCDB"}; - Configurable fatalOnPassNotAvailable{"fatalOnPassNotAvailable", true, "Flag to throw a fatal if the pass is not available in the retrieved CCDB object"}; - - o2::aod::pidtofgeneric::TofPidNewCollision bachelorTOFPID; - o2::pid::tof::TOFResoParamsV2 mRespParamsV2; - - void initCCDB(aod::BCsWithTimestamps::iterator const& bc) - { - if (mRunNumber == bc.runNumber()) { - return; - } - mRunNumber = bc.runNumber(); - - // Initial TOF PID Paras, copied from PIDTOF.h - timestamp.value = bc.timestamp(); - ccdb->setTimestamp(timestamp.value); - // Not later than now objects - ccdb->setCreatedNotAfter(std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count()); - // TODO: implement the automatic pass name detection from metadata - if (passName.value == "") { - passName.value = "unanchored"; // temporary default - LOG(warning) << "Passed autodetect mode for pass, not implemented yet, waiting for metadata. Taking '" << passName.value << "'"; - } - LOG(info) << "Using parameter collection, starting from pass '" << passName.value << "'"; - - const std::string fname = paramFileName.value; - if (!fname.empty()) { // Loading the parametrization from file - LOG(info) << "Loading exp. sigma parametrization from file " << fname << ", using param: " << parametrizationPath.value; - if (1) { - o2::tof::ParameterCollection paramCollection; - paramCollection.loadParamFromFile(fname, parametrizationPath.value); - LOG(info) << "+++ Loaded parameter collection from file +++"; - if (!paramCollection.retrieveParameters(mRespParamsV2, passName.value)) { - if (fatalOnPassNotAvailable) { - LOGF(fatal, "Pass '%s' not available in the retrieved CCDB object", passName.value.data()); - } else { - LOGF(warning, "Pass '%s' not available in the retrieved CCDB object", passName.value.data()); - } - } else { - mRespParamsV2.setShiftParameters(paramCollection.getPars(passName.value)); - mRespParamsV2.printShiftParameters(); - } - } else { - mRespParamsV2.loadParamFromFile(fname.data(), parametrizationPath.value); - } - } else if (loadResponseFromCCDB) { // Loading it from CCDB - LOG(info) << "Loading exp. sigma parametrization from CCDB, using path: " << parametrizationPath.value << " for timestamp " << timestamp.value; - o2::tof::ParameterCollection* paramCollection = ccdb->getForTimeStamp(parametrizationPath.value, timestamp.value); - paramCollection->print(); - if (!paramCollection->retrieveParameters(mRespParamsV2, passName.value)) { // Attempt at loading the parameters with the pass defined - if (fatalOnPassNotAvailable) { - LOGF(fatal, "Pass '%s' not available in the retrieved CCDB object", passName.value.data()); - } else { - LOGF(warning, "Pass '%s' not available in the retrieved CCDB object", passName.value.data()); - } - } else { // Pass is available, load non standard parameters - mRespParamsV2.setShiftParameters(paramCollection->getPars(passName.value)); - mRespParamsV2.printShiftParameters(); - } - } - mRespParamsV2.print(); - if (timeShiftCCDBPath.value != "") { - if (timeShiftCCDBPath.value.find(".root") != std::string::npos) { - mRespParamsV2.setTimeShiftParameters(timeShiftCCDBPath.value, "gmean_Pos", true); - mRespParamsV2.setTimeShiftParameters(timeShiftCCDBPath.value, "gmean_Neg", false); - } else { - mRespParamsV2.setTimeShiftParameters(ccdb->getForTimeStamp(Form("%s/pos", timeShiftCCDBPath.value.c_str()), timestamp.value), true); - mRespParamsV2.setTimeShiftParameters(ccdb->getForTimeStamp(Form("%s/neg", timeShiftCCDBPath.value.c_str()), timestamp.value), false); - } - } - - bachelorTOFPID.SetParams(mRespParamsV2); - } - - struct Indexdaughters { // check duplicated paired daughters - int64_t index0; - int64_t index1; - int64_t index2; - bool operator==(const Indexdaughters& t) const - { - return (this->index0 == t.index0 && this->index1 == t.index1 && this->index2 == t.index2); - } - }; - - void process(ColwithEvTimes const& collisions, MCLabeledTracksIU const& tracks, aod::McParticles const& /*particlesMC*/, aod::McCollisions const& /*mcCollisions*/, aod::BCsWithTimestamps const&) - { - for (const auto& collision : collisions) { - auto bc = collision.bc_as(); - initCCDB(bc); - - registry.fill(HIST("hEventCounter"), 0.5); - if (mc_event_selection && (!collision.selection_bit(aod::evsel::kIsTriggerTVX) || !collision.selection_bit(aod::evsel::kNoTimeFrameBorder))) { - continue; - } - registry.fill(HIST("hEventCounter"), 1.5); - if (event_posZ_selection && std::abs(collision.posZ()) > 10.f) { // 10cm - continue; - } - registry.fill(HIST("hEventCounter"), 2.5); - - std::vector protons, pions, deuterons; // index for daughter tracks - std::unordered_set set_proton, set_pion, set_deuteron; // check duplicated daughters - int itrack = -1; - - auto coltracks = tracks.sliceBy(perCollisionTracks, collision.globalIndex()); - - for (const auto& track : coltracks) { - - ++itrack; - registry.fill(HIST("hParticleCounter"), 0.5); - registry.fill(HIST("hTrackITSNcls"), track.itsNCls()); - registry.fill(HIST("hTPCNCls"), track.tpcNClsFound()); - registry.fill(HIST("hTPCNClsCrossedRows"), track.tpcNClsCrossedRows()); - registry.fill(HIST("hTrackNsigmaDeuteron"), track.tpcNSigmaDe()); - registry.fill(HIST("hTrackNsigmaProton"), track.tpcNSigmaPr()); - registry.fill(HIST("hTrackNsigmaPion"), track.tpcNSigmaPi()); - - if (!track.has_mcParticle()) { - continue; - } - auto mcparticle = track.mcParticle_as(); - registry.fill(HIST("hTPCBB"), track.p() * track.sign(), track.tpcSignal()); - - registry.fill(HIST("hParticleCounter"), 1.5); - - // if (TMath::Abs(mcparticle.y()) > 0.9) {continue;} - registry.fill(HIST("hParticleCounter"), 2.5); - registry.fill(HIST("hTrackEta"), track.eta()); - registry.fill(HIST("hTrackMcRapidity"), mcparticle.y()); - - // Hypertriton detected directly - if (mcparticle.pdgCode() == 1010010030 || mcparticle.pdgCode() == -1010010030) { - registry.fill(HIST("hParticleCounter"), 3.5); - registry.fill(HIST("hHypertritonMcPt"), mcparticle.pt()); - registry.fill(HIST("hHypertritonEta"), track.eta()); - registry.fill(HIST("hHypertritonMcRapidity"), mcparticle.y()); - } - - // Proton - if (mcparticle.pdgCode() == 2212 || mcparticle.pdgCode() == -2212) { - registry.fill(HIST("hParticleCounter"), 4.5); - if (track.tpcNClsFound() > 70) { - registry.fill(HIST("hProtonTPCBBAfterTPCNclsCut"), track.p() * track.sign(), track.tpcSignal()); - } - - if (mcparticle.has_mothers()) { - registry.fill(HIST("hProtonCounter"), 0.5); - for (const auto& particleMother : mcparticle.mothers_as()) { - bool flag_H3L = is3bodyDecayedH3L(particleMother); - if (!flag_H3L) { - continue; - } - protons.push_back(itrack); - auto p = set_proton.insert(mcparticle.globalIndex()); - if (p.second == false) - registry.fill(HIST("hDuplicatedH3LDaughers"), 0); - registry.fill(HIST("hProtonCounter"), 1.5); - registry.fill(HIST("hDauProtonPt"), track.pt()); - registry.fill(HIST("hDauProtonMcPt"), mcparticle.pt()); - registry.fill(HIST("hDauProtonNsigmaProton"), track.tpcNSigmaPr()); - registry.fill(HIST("hDauProtonTPCVsPt"), track.pt(), track.tpcNSigmaPr()); - } - } - - registry.fill(HIST("hProtonMcPt"), mcparticle.pt()); - registry.fill(HIST("hProtonMcP"), mcparticle.p()); - registry.fill(HIST("hProtonPt"), track.pt()); - registry.fill(HIST("hProtonP"), track.p()); - - registry.fill(HIST("hProtonNsigmaProton"), track.tpcNSigmaPr()); - registry.fill(HIST("hProtonTPCNCls"), track.tpcNClsFound()); - registry.fill(HIST("hProtonEta"), track.eta()); - registry.fill(HIST("hProtonMcRapidity"), mcparticle.y()); - registry.fill(HIST("hProtonTPCBB"), track.p() * track.sign(), track.tpcSignal()); - } - - // Pion - if (mcparticle.pdgCode() == 211 || mcparticle.pdgCode() == -211) { - registry.fill(HIST("hParticleCounter"), 5.5); - if (track.tpcNClsFound() > 70) { - registry.fill(HIST("hPionTPCBBAfterTPCNclsCut"), track.p() * track.sign(), track.tpcSignal()); - } - - if (mcparticle.has_mothers()) { - registry.fill(HIST("hPionCounter"), 0.5); - for (const auto& particleMother : mcparticle.mothers_as()) { - bool flag_H3L = is3bodyDecayedH3L(particleMother); - if (!flag_H3L) { - continue; - } - pions.push_back(itrack); - auto p = set_pion.insert(mcparticle.globalIndex()); - if (p.second == false) { - registry.fill(HIST("hDuplicatedH3LDaughers"), 1); - } - registry.fill(HIST("hPionCounter"), 1.5); - registry.fill(HIST("hDauPionPt"), track.pt()); - registry.fill(HIST("hDauPionMcPt"), mcparticle.pt()); - registry.fill(HIST("hDauPionTPCVsPt"), track.pt(), track.tpcNSigmaPi()); - registry.fill(HIST("hDauPionDcaXY"), track.dcaXY()); - } - } - - registry.fill(HIST("hPionMcPt"), mcparticle.pt()); - registry.fill(HIST("hPionMcP"), mcparticle.p()); - registry.fill(HIST("hPionPt"), track.pt()); - registry.fill(HIST("hPionP"), track.p()); - - registry.fill(HIST("hPionNsigmaPion"), track.tpcNSigmaPi()); - registry.fill(HIST("hPionTPCNCls"), track.tpcNClsFound()); - registry.fill(HIST("hPionEta"), track.eta()); - registry.fill(HIST("hPionMcRapidity"), mcparticle.y()); - registry.fill(HIST("hPionTPCBB"), track.p() * track.sign(), track.tpcSignal()); - } - - float tofNsigmaDe = -999; - static constexpr float kCSPEED = TMath::C() * 1.0e2f * 1.0e-12f; // c in cm/ps - - if (track.hasTOF() && track.has_collision()) { - auto responseDe = o2::pid::tof::ExpTimes(); - // float bachExpTime = track.length() * sqrt((o2::constants::physics::MassDeuteron * o2::constants::physics::MassDeuteron) + (track.tofExpMom() * track.tofExpMom())) / (kCSPEED * track.tofExpMom()); // L*E/(p*c) = L/v - - float mMassHyp = o2::track::pid_constants::sMasses2Z[track.pidForTracking()]; - float bachExpTime = track.length() * std::sqrt((mMassHyp * mMassHyp) + (track.tofExpMom() * track.tofExpMom())) / (kCSPEED * track.tofExpMom()); // L*E/(p*c) = L/v - float tofsignal = track.trackTime() * 1000 + bachExpTime; // in ps - - float expSigma = responseDe.GetExpectedSigma(mRespParamsV2, track, tofsignal, track.tofEvTimeErr()); - // tofNsigmaDe = (track.tofSignal() - track.tofEvTime() - responseDe.GetCorrectedExpectedSignal(mRespParamsV2, track)) / expSigma; - tofNsigmaDe = (tofsignal - track.tofEvTime() - responseDe.GetCorrectedExpectedSignal(mRespParamsV2, track)) / expSigma; - // tofNsigmaDe = (tofsignal - track.evTimeForTrack() - responseDe.GetCorrectedExpectedSignal(mRespParamsV2, track)) / expSigma; - - if (collision.bcId() == collision.foundBCId()) { - registry.fill(HIST("hDiffColTime"), track.tofEvTime() - collision.collisionTime()); - } - - // Assume deuterons linked to the correct collision, result of new TOF PID should be same as the default one - registry.fill(HIST("hDiffTrackTOFSignal"), track.tofSignal() - tofsignal); - registry.fill(HIST("hDiffEvTimeForTrack"), track.tofEvTime() - track.evTimeForTrack()); - registry.fill(HIST("hDiffTrackTOFNSigmaDe"), track.tofNSigmaDe() - bachelorTOFPID.GetTOFNSigma(o2::track::PID::Deuteron, track, collision, collision)); - // registry.fill(HIST("hDiffTrackTOFNSigmaDe"), track.tofExpSigmaDe() - bachelorTOFPID.GetTOFNSigma(o2::track::PID::Deuteron, track, collision, collision)); - } - - // Deuteron - if (mcparticle.pdgCode() == 1000010020 || mcparticle.pdgCode() == -1000010020) { - registry.fill(HIST("hParticleCounter"), 6.5); - if (track.tpcNClsFound() > 70) { - registry.fill(HIST("hDeuteronTPCBBAfterTPCNclsCut"), track.p() * track.sign(), track.tpcSignal()); - } - - if (mcparticle.has_mothers()) { - registry.fill(HIST("hDeuteronCounter"), 0.5); - for (const auto& particleMother : mcparticle.mothers_as()) { - bool flag_H3L = is3bodyDecayedH3L(particleMother); - if (!flag_H3L) { - continue; - } - deuterons.push_back(itrack); - auto p = set_deuteron.insert(mcparticle.globalIndex()); - if (p.second == false) - registry.fill(HIST("hDuplicatedH3LDaughers"), 2); - registry.fill(HIST("hDeuteronCounter"), 1.5); - registry.fill(HIST("hDauDeuteronPt"), track.pt()); - registry.fill(HIST("hDauDeuteronMcPt"), mcparticle.pt()); - registry.fill(HIST("hDauDeuteronTPCVsPt"), track.pt(), track.tpcNSigmaDe()); - registry.fill(HIST("hDauDeuteronTOFNSigmaVsP"), track.sign() * track.p(), track.tofNSigmaDe()); - - registry.fill(HIST("hDauDeuteronNewTOFNSigmaVsP"), track.sign() * track.p(), tofNsigmaDe); - if (track.hasTOF()) { - registry.fill(HIST("hDauDeuteronTOFNSigmaVsPHasTOF"), track.sign() * track.p(), track.tofNSigmaDe()); - registry.fill(HIST("hDauDeuteronDiffTOFNsigmaDeHasTOF"), track.tofNSigmaDe() - tofNsigmaDe); - } - registry.fill(HIST("hDauDeuteronMatchCounter"), 0.5); - if (mcparticle.mcCollisionId() == collision.mcCollisionId()) { - registry.fill(HIST("hDauDeuteronMatchCounter"), 1.5); - } - if (track.hasTOF()) { - registry.fill(HIST("hDauDeuteronMatchCounter"), 2.5); - if (mcparticle.mcCollisionId() == collision.mcCollisionId()) { - registry.fill(HIST("hDauDeuteronMatchCounter"), 3.5); - } - } - } - } - - registry.fill(HIST("hDeuteronMcPt"), mcparticle.pt()); - registry.fill(HIST("hDeuteronMcP"), mcparticle.p()); - registry.fill(HIST("hDeuteronPt"), track.pt()); - registry.fill(HIST("hDeuteronP"), track.p()); - - registry.fill(HIST("hDeuteronNsigmaDeuteron"), track.tpcNSigmaDe()); - registry.fill(HIST("hDeuteronTPCNCls"), track.tpcNClsFound()); - registry.fill(HIST("hDeuteronEta"), track.eta()); - registry.fill(HIST("hDeuteronMcRapidity"), mcparticle.y()); - registry.fill(HIST("hDeuteronTPCBB"), track.p() * track.sign(), track.tpcSignal()); - } else { - if (track.hasTOF()) { - registry.fill(HIST("hWrongDeuteronTOFNSigmaVsP"), track.sign() * track.p(), track.tofNSigmaDe()); - registry.fill(HIST("hWrongDeuteronNewTOFNSigmaVsP"), track.sign() * track.p(), tofNsigmaDe); - } - } - } - - std::vector set_pair; - for (size_t iproton = 0; iproton < protons.size(); iproton++) { - auto track0 = tracks.iteratorAt(protons[iproton]); - auto mctrack0 = track0.mcParticle_as(); - for (size_t ipion = 0; ipion < pions.size(); ipion++) { - auto track1 = tracks.iteratorAt(pions[ipion]); - auto mctrack1 = track1.mcParticle_as(); - for (size_t ideuteron = 0; ideuteron < deuterons.size(); ideuteron++) { - auto track2 = tracks.iteratorAt(deuterons[ideuteron]); - auto mctrack2 = track2.mcParticle_as(); - if (isPairedH3LDaughters(mctrack0, mctrack1, mctrack2)) { - registry.fill(HIST("hPairedH3LDaughers"), 0); - // MC mass cut, to check if the daughters are from materials - double hypertritonMCMass = RecoDecay::m(std::array{std::array{mctrack0.px(), mctrack0.py(), mctrack0.pz()}, std::array{mctrack1.px(), mctrack1.py(), mctrack1.pz()}, std::array{mctrack2.px(), mctrack2.py(), mctrack2.pz()}}, std::array{o2::constants::physics::MassProton, o2::constants::physics::MassPionCharged, o2::constants::physics::MassDeuteron}); - registry.fill(HIST("hPairedH3LDaughersInvMass"), hypertritonMCMass); - if (hypertritonMCMass < 2.990 || hypertritonMCMass > 2.993) - continue; - registry.fill(HIST("hPairedH3LDaughers"), 1); - // duplicated daughters check - Indexdaughters temp = {mctrack0.globalIndex(), mctrack1.globalIndex(), mctrack2.globalIndex()}; - auto p = std::find(set_pair.begin(), set_pair.end(), temp); - if (p == set_pair.end()) { - set_pair.push_back(temp); - registry.fill(HIST("hPairedH3LDaughers"), 2); - } - } - } - } - } - } - - // Check for recalculated TOF PID for secondary deuterons - - std::vector SelectedEvents(collisions.size()); - int nevts = 0; - for (const auto& collision : collisions) { - SelectedEvents[nevts++] = collision.mcCollision_as().globalIndex(); - } - - for (const auto& track : tracks) { - if (!track.has_mcParticle()) { - continue; - } - auto mcparticle = track.mcParticle_as(); - if (mcparticle.pdgCode() == 1000010020 || mcparticle.pdgCode() == -1000010020) { - if (!mcparticle.has_mothers()) { - continue; - } - const auto evtReconstructed = std::find(SelectedEvents.begin(), SelectedEvents.end(), mcparticle.mcCollision_as().globalIndex()); - if (evtReconstructed == SelectedEvents.end() || !track.has_collision()) { - continue; - } - if (!track.has_collision()) { - continue; - } - auto collision = collisions.iteratorAt(evtReconstructed - SelectedEvents.begin()); - auto originalcollision = track.collision_as(); - - for (const auto& particleMother : mcparticle.mothers_as()) { - bool flag_H3L = is3bodyDecayedH3L(particleMother); - if (!flag_H3L) { - continue; - } - - auto bc = collision.bc_as(); - initCCDB(bc); - float tofNsigmaDeAO2D = -999; - float tofNsigmaDeEvSel = -999; - - if (track.hasTOF()) { - /*auto responseDe = o2::pid::tof::ExpTimes(); - //float bachExpTime = track.length() * sqrt((o2::constants::physics::MassDeuteron * o2::constants::physics::MassDeuteron) + (track.tofExpMom() * track.tofExpMom())) / (kCSPEED * track.tofExpMom()); // L*E/(p*c) = L/v - float mMassHyp = o2::track::pid_constants::sMasses2Z[track.pidForTracking()]; - float bachExpTime = track.length() * std::sqrt((mMassHyp * mMassHyp) + (track.tofExpMom() * track.tofExpMom())) / (kCSPEED * track.tofExpMom()); // L*E/(p*c) = L/v - */ - - tofNsigmaDeAO2D = bachelorTOFPID.GetTOFNSigma(o2::track::PID::Deuteron, track, originalcollision, collision); - tofNsigmaDeEvSel = bachelorTOFPID.GetTOFNSigma(o2::track::PID::Deuteron, track, originalcollision, collision, false); - - if (collision.globalIndex() == originalcollision.globalIndex()) { - registry.fill(HIST("hDauDeuteronTOFNSigmaVsP_CorrectCol"), track.sign() * track.p(), track.tofNSigmaDe()); - registry.fill(HIST("hDauDeuteronNewTOFNSigmaVsP_CorrectCol"), track.sign() * track.p(), tofNsigmaDeAO2D); - continue; - } - - /*if (originalcollision.collisionTimeRes() > 40){ - continue; - }*/ - registry.fill(HIST("hDauDeuteronTOFNSigmaVsP_v2"), track.sign() * track.p(), track.tofNSigmaDe()); - registry.fill(HIST("hDauDeuteronNewTOFNSigmaVsP_v2_AO2D"), track.sign() * track.p(), tofNsigmaDeAO2D); - registry.fill(HIST("hDauDeuteronNewTOFNSigmaVsP_v2_EvSel"), track.sign() * track.p(), tofNsigmaDeEvSel); - registry.fill(HIST("hDauDeuteronTOFNSigmaVsColTimeRes_v2"), collision.collisionTimeRes(), track.tofNSigmaDe()); - registry.fill(HIST("hDauDeuteronTOFNSigmaVsColTimeRes_v2_AO2D"), originalcollision.collisionTimeRes(), tofNsigmaDeAO2D); - registry.fill(HIST("hDauDeuteronTOFNSigmaVsColTimeRes_v2_EvSel"), originalcollision.collisionTimeRes(), tofNsigmaDeEvSel); - - if (std::abs(track.tofNSigmaDe()) >= 5) { - registry.fill(HIST("hDauDeuteronTOFPIDCounter"), 0.5); - if (std::abs(tofNsigmaDeAO2D) < 5 && std::abs(tofNsigmaDeEvSel) < 5) { - registry.fill(HIST("hDauDeuteronTOFPIDCounter"), 1.5); - } else if (std::abs(tofNsigmaDeAO2D) < 5 && std::abs(tofNsigmaDeEvSel) >= 5) { - registry.fill(HIST("hDauDeuteronTOFPIDCounter"), 2.5); - } else if (std::abs(tofNsigmaDeAO2D) >= 5 && std::abs(tofNsigmaDeEvSel) < 5) { - registry.fill(HIST("hDauDeuteronTOFPIDCounter"), 3.5); - } else if (std::abs(tofNsigmaDeAO2D) >= 5 && std::abs(tofNsigmaDeEvSel) >= 5) { - registry.fill(HIST("hDauDeuteronTOFPIDCounter"), 4.5); - } - } else if (std::abs(track.tofNSigmaDe()) < 5) { - registry.fill(HIST("hDauDeuteronTOFPIDCounter_CloseBC"), 0.5); - if (std::abs(tofNsigmaDeAO2D) < 5 && std::abs(tofNsigmaDeEvSel) < 5) { - registry.fill(HIST("hDauDeuteronTOFPIDCounter_CloseBC"), 1.5); - } else if (std::abs(tofNsigmaDeAO2D) < 5 && std::abs(tofNsigmaDeEvSel) >= 5) { - registry.fill(HIST("hDauDeuteronTOFPIDCounter_CloseBC"), 2.5); - } else if (std::abs(tofNsigmaDeAO2D) >= 5 && std::abs(tofNsigmaDeEvSel) < 5) { - registry.fill(HIST("hDauDeuteronTOFPIDCounter_CloseBC"), 3.5); - } else if (std::abs(tofNsigmaDeAO2D) >= 5 && std::abs(tofNsigmaDeEvSel) >= 5) { - registry.fill(HIST("hDauDeuteronTOFPIDCounter_CloseBC"), 4.5); - } - } - } - } - } - } - } -}; - -// check the performance of mcparticle -struct Hypertriton3bodyMcParticleCheck { - // Basic checks - HistogramRegistry registry{ - "registry", - { - {"hMcCollCounter", "hMcCollCounter", {HistType::kTH1F, {{2, 0.0f, 2.0f}}}}, - - {"h3dMCDecayedHypertriton", "h3dMCDecayedHypertriton", {HistType::kTH3F, {{20, -1.0f, 1.0f, "Rapidity"}, {200, 0.0f, 10.0f, "#it{p}_{T} (GeV/c)"}, {50, 0.0f, 50.0f, "ct(cm)"}}}}, - - {"hMcHypertritonCounter", "hMcHypertritonCounter", {HistType::kTH1F, {{9, 0.0f, 9.0f}}}}, - {"hMcHypertritonPt", "hMcHypertritonPt", {HistType::kTH1F, {{300, 0.0f, 15.0f}}}}, - {"hMcProtonPt", "hMcProtonPt", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, - {"hMcPionPt", "hMcPionPt", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, - {"hMcDeuteronPt", "hMcDeuteronPt", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, - - {"hMcRecoInvMass", "hMcRecoInvMass", {HistType::kTH1F, {{100, 2.95, 3.05f}}}}, - - {"hDiffDaughterR", "hDiffDaughterR", {HistType::kTH1F, {{10000, -100, 100}}}}, // difference between minR of pion&proton and R of deuteron(bachelor) - {"hTrackX", "hTrackX", {HistType::kTH1F, {{10000, -100, 100}}}}, - {"hTrackY", "hTrackY", {HistType::kTH1F, {{10000, -100, 100}}}}, - {"hTrackZ", "hTrackZ", {HistType::kTH1F, {{10000, -100, 100}}}}, - }, - }; - - o2::pid::tof::TOFResoParamsV2 mRespParamsV2; - - void init(InitContext&) - { - registry.get(HIST("hMcCollCounter"))->GetXaxis()->SetBinLabel(1, "Total Counter"); - registry.get(HIST("hMcCollCounter"))->GetXaxis()->SetBinLabel(2, "Reconstructed"); - - registry.get(HIST("hMcHypertritonCounter"))->GetXaxis()->SetBinLabel(1, "Hypertriton All"); - registry.get(HIST("hMcHypertritonCounter"))->GetXaxis()->SetBinLabel(2, "Matter All"); - registry.get(HIST("hMcHypertritonCounter"))->GetXaxis()->SetBinLabel(3, "AntiMatter All"); - registry.get(HIST("hMcHypertritonCounter"))->GetXaxis()->SetBinLabel(4, "confirm to 3-body decay"); - registry.get(HIST("hMcHypertritonCounter"))->GetXaxis()->SetBinLabel(5, "Matter"); - registry.get(HIST("hMcHypertritonCounter"))->GetXaxis()->SetBinLabel(6, "AntiMatter"); - registry.get(HIST("hMcHypertritonCounter"))->GetXaxis()->SetBinLabel(7, "Rapidity"); - registry.get(HIST("hMcHypertritonCounter"))->GetXaxis()->SetBinLabel(8, "Lifetime"); - registry.get(HIST("hMcHypertritonCounter"))->GetXaxis()->SetBinLabel(9, "PtCut"); - } - - Configurable mc_event_selection{"mc_event_selection", true, "mc event selection count post kIsTriggerTVX and kNoTimeFrameBorder"}; - Configurable event_posZ_selection{"event_posZ_selection", true, "event selection count post poZ cut"}; - - Preslice permcCollision = o2::aod::mcparticle::mcCollisionId; - - std::vector mcPartIndices; - template - void SetTrackIDForMC(aod::McParticles const& particlesMC, TTrackTable const& tracks) - { - mcPartIndices.clear(); - mcPartIndices.resize(particlesMC.size()); - std::fill(mcPartIndices.begin(), mcPartIndices.end(), -1); - for (const auto& track : tracks) { - if (track.has_mcParticle()) { - auto mcparticle = track.template mcParticle_as(); - if (mcPartIndices[mcparticle.globalIndex()] == -1) { - mcPartIndices[mcparticle.globalIndex()] = track.globalIndex(); - } else { - auto candTrack = tracks.rawIteratorAt(mcPartIndices[mcparticle.globalIndex()]); - // Use the track which has innest information (also best quality? - if (track.x() < candTrack.x()) { - mcPartIndices[mcparticle.globalIndex()] = track.globalIndex(); - } - } - - // Checks for TrackR - registry.fill(HIST("hTrackX"), track.x()); - registry.fill(HIST("hTrackY"), track.y()); - registry.fill(HIST("hTrackZ"), track.z()); - } - } - } - - void process(aod::McCollisions const& mcCollisions, aod::McParticles const& particlesMC, const o2::soa::Join& collisions, MCLabeledTracksIU const& tracks) - { - SetTrackIDForMC(particlesMC, tracks); - std::vector SelectedEvents(collisions.size()); - int nevts = 0; - for (const auto& collision : collisions) { - if (mc_event_selection && (!collision.selection_bit(aod::evsel::kIsTriggerTVX) || !collision.selection_bit(aod::evsel::kNoTimeFrameBorder))) { - continue; - } - if (event_posZ_selection && std::abs(collision.posZ()) > 10.f) { // 10cm - continue; - } - SelectedEvents[nevts++] = collision.mcCollision_as().globalIndex(); - } - SelectedEvents.resize(nevts); - - for (const auto& mcCollision : mcCollisions) { - registry.fill(HIST("hMcCollCounter"), 0.5); - const auto evtReconstructedAndSelected = std::find(SelectedEvents.begin(), SelectedEvents.end(), mcCollision.globalIndex()) != SelectedEvents.end(); - if (!evtReconstructedAndSelected) { // Check that the event is reconstructed and that the reconstructed events pass the selection - continue; - } - registry.fill(HIST("hMcCollCounter"), 1.5); - - const auto& dparticlesMC = particlesMC.sliceBy(permcCollision, mcCollision.globalIndex()); - - for (const auto& mcparticle : dparticlesMC) { - - if (mcparticle.pdgCode() == 2212 || mcparticle.pdgCode() == -2212) { - registry.fill(HIST("hMcProtonPt"), mcparticle.pt()); - } - if (mcparticle.pdgCode() == 211 || mcparticle.pdgCode() == -211) { - registry.fill(HIST("hMcPionPt"), mcparticle.pt()); - } - if (mcparticle.pdgCode() == 1000010020 || mcparticle.pdgCode() == -1000010020) { - registry.fill(HIST("hMcDeuteronPt"), mcparticle.pt()); - } - if (mcparticle.pdgCode() == 1010010030) { - registry.fill(HIST("hMcHypertritonCounter"), 1.5); - } else if (mcparticle.pdgCode() == -1010010030) { - registry.fill(HIST("hMcHypertritonCounter"), 2.5); - } - if (mcparticle.pdgCode() == 1010010030 || mcparticle.pdgCode() == -1010010030) { - registry.fill(HIST("hMcHypertritonCounter"), 0.5); - registry.fill(HIST("hMcHypertritonPt"), mcparticle.pt()); - - double dauDeuteronPos[3] = {-999, -999, -999}; - double dauProtonMom[3] = {-999, -999, -999}; - double dauPionMom[3] = {-999, -999, -999}; - double dauDeuteronMom[3] = {-999, -999, -999}; - double MClifetime = 999; - double dauProtonTrackR = 9999, dauPionTrackR = 99999, dauDeuteronTrackR = 999999; - bool flag_H3L = is3bodyDecayedH3L(mcparticle); - if (!flag_H3L) { - continue; - } - for (const auto& mcparticleDaughter : mcparticle.daughters_as()) { - if (std::abs(mcparticleDaughter.pdgCode()) == 2212) { - dauProtonMom[0] = mcparticleDaughter.px(); - dauProtonMom[1] = mcparticleDaughter.py(); - dauProtonMom[2] = mcparticleDaughter.pz(); - if (mcPartIndices[mcparticleDaughter.globalIndex()] != -1) { - auto trackProton = tracks.rawIteratorAt(mcPartIndices[mcparticleDaughter.globalIndex()]); - dauProtonTrackR = trackProton.x(); - } - } - if (std::abs(mcparticleDaughter.pdgCode()) == 211) { - dauPionMom[0] = mcparticleDaughter.px(); - dauPionMom[1] = mcparticleDaughter.py(); - dauPionMom[2] = mcparticleDaughter.pz(); - if (mcPartIndices[mcparticleDaughter.globalIndex()] != -1) { - auto trackPion = tracks.rawIteratorAt(mcPartIndices[mcparticleDaughter.globalIndex()]); - dauPionTrackR = trackPion.x(); - } - } - if (std::abs(mcparticleDaughter.pdgCode()) == 1000010020) { - dauDeuteronPos[0] = mcparticleDaughter.vx(); - dauDeuteronPos[1] = mcparticleDaughter.vy(); - dauDeuteronPos[2] = mcparticleDaughter.vz(); - dauDeuteronMom[0] = mcparticleDaughter.px(); - dauDeuteronMom[1] = mcparticleDaughter.py(); - dauDeuteronMom[2] = mcparticleDaughter.pz(); - if (mcPartIndices[mcparticleDaughter.globalIndex()] != -1) { - auto trackDeuteron = tracks.rawIteratorAt(mcPartIndices[mcparticleDaughter.globalIndex()]); - dauDeuteronTrackR = trackDeuteron.x(); - } - } - } - if (mcparticle.pdgCode() == 1010010030) { - registry.fill(HIST("hMcHypertritonCounter"), 3.5); - registry.fill(HIST("hMcHypertritonCounter"), 4.5); - } - if (mcparticle.pdgCode() == -1010010030) { - registry.fill(HIST("hMcHypertritonCounter"), 3.5); - registry.fill(HIST("hMcHypertritonCounter"), 5.5); - } - double hypertritonMCMass = RecoDecay::m(std::array{std::array{dauProtonMom[0], dauProtonMom[1], dauProtonMom[2]}, std::array{dauPionMom[0], dauPionMom[1], dauPionMom[2]}, std::array{dauDeuteronMom[0], dauDeuteronMom[1], dauDeuteronMom[2]}}, std::array{o2::constants::physics::MassProton, o2::constants::physics::MassPionCharged, o2::constants::physics::MassDeuteron}); - registry.fill(HIST("hMcRecoInvMass"), hypertritonMCMass); - - if (hypertritonMCMass > 2.990 && hypertritonMCMass < 2.993) { - MClifetime = RecoDecay::sqrtSumOfSquares(dauDeuteronPos[0] - mcparticle.vx(), dauDeuteronPos[1] - mcparticle.vy(), dauDeuteronPos[2] - mcparticle.vz()) * o2::constants::physics::MassHyperTriton / mcparticle.p(); - registry.fill(HIST("h3dMCDecayedHypertriton"), mcparticle.y(), mcparticle.pt(), MClifetime); - - double diffTrackR = dauDeuteronTrackR - std::min(dauPionTrackR, dauProtonTrackR); - registry.fill(HIST("hDiffDaughterR"), diffTrackR); - - // int daughterPionCount = 0; - // for (auto& mcparticleDaughter : mcparticle.daughters_as()) { - // if (std::abs(mcparticleDaughter.pdgCode()) == 211) { - // daughterPionCount++; - // } - // } - - // Counter for hypertriton N_gen - if (std::abs(mcparticle.y()) < 1) { - registry.fill(HIST("hMcHypertritonCounter"), 6.5); - if (MClifetime < 40) { - registry.fill(HIST("hMcHypertritonCounter"), 7.5); - if (mcparticle.pt() > 1 && mcparticle.pt() < 10) { - registry.fill(HIST("hMcHypertritonCounter"), 8.5); - } - } - } - } - } - } - } - } -}; - -WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) -{ - return WorkflowSpec{ - adaptAnalysisTask(cfgc), - adaptAnalysisTask(cfgc), - }; -} diff --git a/PWGLF/Tasks/Nuspex/hypertriton3bodyanalysis.cxx b/PWGLF/Tasks/Nuspex/hypertriton3bodyanalysis.cxx deleted file mode 100644 index b8aeb1d34c3..00000000000 --- a/PWGLF/Tasks/Nuspex/hypertriton3bodyanalysis.cxx +++ /dev/null @@ -1,797 +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 hypertriton3bodyanalysis.cxx -/// \brief Standard analysis workflow for hypertriton 3-body decay -/// \author Yuanzhe Wang - -#include -#include -#include -#include -#include - -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.h" -#include "ReconstructionDataFormats/Track.h" -#include "Common/Core/RecoDecay.h" -#include "Common/Core/trackUtilities.h" -// #include "PWGLF/DataModel/LFStrangenessTables.h" -#include "PWGLF/DataModel/Vtx3BodyTables.h" -#include "Common/Core/TrackSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/Centrality.h" -#include "Common/DataModel/PIDResponse.h" -#include "CommonConstants/PhysicsConstants.h" - -using namespace o2; -using namespace o2::framework; -using namespace o2::framework::expressions; - -using FullTracksExtIU = soa::Join; -// using FullTracksExtIU = soa::Join; // For TOF PID check -using MCLabeledTracksIU = soa::Join; - -struct hypertriton3bodyQa { - // Basic checks - HistogramRegistry registry{ - "registry", - { - {"hVtxRadius", "hVtxRadius", {HistType::kTH1F, {{1000, 0.0f, 100.0f, "cm"}}}}, - {"hVtxCosPA", "hVtxCosPA", {HistType::kTH1F, {{1000, 0.9f, 1.0f}}}}, - {"hPtProton", "hPtProton", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, - {"hPtPionMinus", "hPtPionMinus", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, - {"hPtDeuteron", "hPtDeuteron", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, - {"hPtAntiProton", "hPtAntiProton", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, - {"hPtPionPlus", "hPtPionPlus", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, - {"hPtAntiDeuteron", "hPtAntiDeuteron", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, - {"hDCAXYProtonToPV", "hDCAXYProtonToPV", {HistType::kTH1F, {{1000, -10.0f, 10.0f, "cm"}}}}, - {"hDCAXYPionToPV", "hDCAXYPionToPV", {HistType::kTH1F, {{1000, -10.0f, 10.0f, "cm"}}}}, - {"hDCAXYDeuteronToPV", "hDCAXYDeuteronToPV", {HistType::kTH1F, {{1000, -10.0f, 10.0f, "cm"}}}}, - {"hDCAProtonToPV", "hDCAProtonToPV", {HistType::kTH1F, {{1000, -10.0f, 10.0f, "cm"}}}}, - {"hDCAPionToPV", "hDCAPionToPV", {HistType::kTH1F, {{1000, -10.0f, 10.0f, "cm"}}}}, - {"hDCADeuteronToPV", "hDCADeuteronToPV", {HistType::kTH1F, {{1000, -10.0f, 10.0f, "cm"}}}}, - {"hProtonTPCNcls", "hProtonTPCNcls", {HistType::kTH1F, {{300, 0, 300, "TPC cluster"}}}}, - {"hPionTPCNcls", "hPionTPCNcls", {HistType::kTH1F, {{300, 0, 300, "TPC cluster"}}}}, - {"hDeuteronTPCNcls", "hDeuteronTPCNcls", {HistType::kTH1F, {{300, 0, 300, "TPC cluster"}}}}, - {"hDCAVtxDau", "hDCAVtxDau", {HistType::kTH1F, {{1000, 0.0f, 10.0f, "cm^{2}"}}}}, - {"hVtxPt", "hVtxPt", {HistType::kTH1F, {{200, 0.0f, 10.0f, "p_{T}"}}}}, - {"hTOFPIDDeuteron", "hTOFPIDDeuteron", {HistType::kTH1F, {{2000, -100.0f, 100.0f}}}}, - {"hDeuTOFNsigma", "Deuteron TOF Nsigma distribution", {HistType::kTH2F, {{1200, -6, 6, "#it{p} (GeV/#it{c})"}, {2000, -100, 100, "TOF n#sigma"}}}}, - {"hDeuTOFNsigmaWithTPC", "Deuteron TOF Nsigma distribution", {HistType::kTH2F, {{1200, -6, 6, "#it{p} (GeV/#it{c})"}, {1000, -100, 100, "TOF n#sigma"}}}}, - }, - }; - - void init(InitContext const&) - { - AxisSpec massAxis = {120, 2.9f, 3.2f, "Inv. Mass (GeV/c^{2})"}; - registry.add("hMassHypertriton", "hMassHypertriton", {HistType::kTH1F, {massAxis}}); - registry.add("hMassAntiHypertriton", "hMassAntiHypertriton", {HistType::kTH1F, {massAxis}}); - // Check for selection criteria - registry.add("hDiffRVtxProton", "hDiffRVtxProton", HistType::kTH1F, {{100, -10, 10}}); // difference between the radius of decay vertex and minR of proton - registry.add("hDiffRVtxPion", "hDiffRVtxPion", HistType::kTH1F, {{100, -10, 10}}); // difference between the radius of decay vertex and minR of pion - registry.add("hDiffRVtxDeuteron", "hDiffRVtxDeuteron", HistType::kTH1F, {{100, -10, 10}}); // difference between the radius of decay vertex and minR of deuteron - registry.add("hDiffDaughterR", "hDiffDaughterR", HistType::kTH1F, {{10000, -100, 100}}); // difference between minR of pion&proton and R of deuteron(bachelor) - } - - void process(aod::Collision const& collision, aod::Vtx3BodyDatas const& vtx3bodydatas, FullTracksExtIU const& /*tracks*/) - { - for (const auto& vtx : vtx3bodydatas) { - auto track0 = vtx.track0_as(); - auto track1 = vtx.track1_as(); - auto track2 = vtx.track2_as(); - - registry.fill(HIST("hVtxRadius"), vtx.vtxradius()); - registry.fill(HIST("hVtxCosPA"), vtx.vtxcosPA(collision.posX(), collision.posY(), collision.posZ())); - registry.fill(HIST("hDCAVtxDau"), vtx.dcaVtxdaughters()); - registry.fill(HIST("hVtxPt"), vtx.pt()); - registry.fill(HIST("hMassHypertriton"), vtx.mHypertriton()); - registry.fill(HIST("hMassAntiHypertriton"), vtx.mAntiHypertriton()); - if (std::abs(track2.tpcNSigmaDe()) < 5) { - registry.fill(HIST("hDeuTOFNsigmaWithTPC"), track2.tpcInnerParam() * track2.sign(), vtx.tofNSigmaBachDe()); - } - if (track2.sign() > 0) { - registry.fill(HIST("hPtProton"), track0.pt()); - registry.fill(HIST("hPtPionMinus"), track1.pt()); - registry.fill(HIST("hPtDeuteron"), track2.pt()); - registry.fill(HIST("hDCAXYProtonToPV"), vtx.dcaXYtrack0topv()); - registry.fill(HIST("hDCAXYPionToPV"), vtx.dcaXYtrack1topv()); - registry.fill(HIST("hDCAProtonToPV"), vtx.dcatrack0topv()); - registry.fill(HIST("hDCAPionToPV"), vtx.dcatrack1topv()); - registry.fill(HIST("hProtonTPCNcls"), track0.tpcNClsCrossedRows()); - registry.fill(HIST("hPionTPCNcls"), track1.tpcNClsCrossedRows()); - registry.fill(HIST("hDiffRVtxProton"), track0.x() - vtx.vtxradius()); - registry.fill(HIST("hDiffRVtxPion"), track1.x() - vtx.vtxradius()); - } else { - registry.fill(HIST("hPtPionPlus"), track0.pt()); - registry.fill(HIST("hPtAntiProton"), track1.pt()); - registry.fill(HIST("hPtAntiDeuteron"), track2.pt()); - registry.fill(HIST("hDCAXYProtonToPV"), vtx.dcaXYtrack1topv()); - registry.fill(HIST("hDCAXYPionToPV"), vtx.dcaXYtrack0topv()); - registry.fill(HIST("hDCAProtonToPV"), vtx.dcatrack1topv()); - registry.fill(HIST("hDCAPionToPV"), vtx.dcatrack0topv()); - registry.fill(HIST("hProtonTPCNcls"), track1.tpcNClsCrossedRows()); - registry.fill(HIST("hPionTPCNcls"), track0.tpcNClsCrossedRows()); - registry.fill(HIST("hDiffRVtxProton"), track1.x() - vtx.vtxradius()); - registry.fill(HIST("hDiffRVtxPion"), track0.x() - vtx.vtxradius()); - } - registry.fill(HIST("hDCAXYDeuteronToPV"), vtx.dcaXYtrack2topv()); - registry.fill(HIST("hDCADeuteronToPV"), vtx.dcatrack2topv()); - registry.fill(HIST("hDeuteronTPCNcls"), track2.tpcNClsCrossedRows()); - registry.fill(HIST("hTOFPIDDeuteron"), vtx.tofNSigmaBachDe()); - registry.fill(HIST("hDeuTOFNsigma"), track2.tpcInnerParam() * track2.sign(), vtx.tofNSigmaBachDe()); - registry.fill(HIST("hDiffRVtxDeuteron"), track2.x() - vtx.vtxradius()); - float diffTrackR = track2.x() - std::min(track0.x(), track1.x()); - registry.fill(HIST("hDiffDaughterR"), diffTrackR); - } - } -}; - -struct hypertriton3bodyAnalysis { - - Preslice perCollisionVtx3BodyDatas = o2::aod::vtx3body::collisionId; - - // Selection criteria - Configurable vtxcospa{"vtxcospa", 0.99, "Vtx CosPA"}; // double -> N.B. dcos(x)/dx = 0 at x=0) - Configurable dcavtxdau{"dcavtxdau", 1.0, "DCA Vtx Daughters"}; // loose cut - Configurable dcapiontopv{"dcapiontopv", .05, "DCA Pion To PV"}; - Configurable etacut{"etacut", 0.9, "etacut"}; - Configurable rapiditycut{"rapiditycut", 1, "rapiditycut"}; - Configurable tofPIDNSigmaMin{"tofPIDNSigmaMin", -5, "tofPIDNSigmaMin"}; - Configurable tofPIDNSigmaMax{"tofPIDNSigmaMax", 5, "tofPIDNSigmaMax"}; - Configurable tpcPIDNSigmaCut{"tpcPIDNSigmaCut", 5, "tpcPIDNSigmaCut"}; - Configurable event_sel8_selection{"event_sel8_selection", true, "event selection count post sel8 cut"}; - Configurable mc_event_selection{"mc_event_selection", true, "mc event selection count post kIsTriggerTVX and kNoTimeFrameBorder"}; - Configurable event_posZ_selection{"event_posZ_selection", true, "event selection count post poZ cut"}; - Configurable lifetimecut{"lifetimecut", 40., "lifetimecut"}; // ct - Configurable minProtonPt{"minProtonPt", 0.3, "minProtonPt"}; - Configurable maxProtonPt{"maxProtonPt", 5, "maxProtonPt"}; - Configurable minPionPt{"minPionPt", 0.1, "minPionPt"}; - Configurable maxPionPt{"maxPionPt", 1.2, "maxPionPt"}; - Configurable minDeuteronPt{"minDeuteronPt", 0.6, "minDeuteronPt"}; - Configurable maxDeuteronPt{"maxDeuteronPt", 10, "maxDeuteronPt"}; - Configurable minDeuteronPUseTOF{"minDeuteronPUseTOF", 1, "minDeuteronPt Enable TOF PID"}; - Configurable h3LMassLowerlimit{"h3LMassLowerlimit", 2.96, "Hypertriton mass lower limit"}; - Configurable h3LMassUpperlimit{"h3LMassUpperlimit", 3.04, "Hypertriton mass upper limit"}; - Configurable mintpcNClsproton{"mintpcNClsproton", 90, "min tpc Nclusters for proton"}; - Configurable mintpcNClspion{"mintpcNClspion", 70, "min tpc Nclusters for pion"}; - Configurable mintpcNClsdeuteron{"mintpcNClsdeuteron", 100, "min tpc Nclusters for deuteron"}; - - Configurable mcsigma{"mcsigma", 0.0015, "sigma of mc invariant mass fit"}; // obtained from MC - Configurable bachelorPdgCode{"bachelorPdgCode", 1000010020, "pdgCode of bachelor daughter"}; - Configurable motherPdgCode{"motherPdgCode", 1010010030, "pdgCode of mother track"}; - - // 3sigma region for Dalitz plot - float lowersignallimit = o2::constants::physics::MassHyperTriton - 3 * mcsigma; - float uppersignallimit = o2::constants::physics::MassHyperTriton + 3 * mcsigma; - - HistogramRegistry registry{ - "registry", - { - {"hEventCounter", "hEventCounter", {HistType::kTH1F, {{4, 0.0f, 4.0f}}}}, - {"hCandidatesCounter", "hCandidatesCounter", {HistType::kTH1F, {{12, 0.0f, 12.0f}}}}, - {"hMassHypertriton", "hMassHypertriton", {HistType::kTH1F, {{80, 2.96f, 3.04f, "Inv. Mass (GeV/c^{2})"}}}}, - {"hMassAntiHypertriton", "hMassAntiHypertriton", {HistType::kTH1F, {{80, 2.96f, 3.04f, "Inv. Mass (GeV/c^{2})"}}}}, - {"hMassHypertritonTotal", "hMassHypertritonTotal", {HistType::kTH1F, {{300, 2.9f, 3.2f, "Inv. Mass (GeV/c^{2})"}}}}, - {"hPtProton", "hPtProton", {HistType::kTH1F, {{200, 0.0f, 10.0f, "#it{p}_{T} (GeV/c)"}}}}, - {"hPtPionMinus", "hPtPionMinus", {HistType::kTH1F, {{200, 0.0f, 10.0f, "#it{p}_{T} (GeV/c)"}}}}, - {"hPtDeuteron", "hPtDeuteron", {HistType::kTH1F, {{200, 0.0f, 10.0f, "#it{p}_{T} (GeV/c)"}}}}, - {"hPtAntiProton", "hPtAntiProton", {HistType::kTH1F, {{200, 0.0f, 10.0f, "#it{p}_{T} (GeV/c)"}}}}, - {"hPtPionPlus", "hPtPionPlus", {HistType::kTH1F, {{200, 0.0f, 10.0f, "#it{p}_{T} (GeV/c)"}}}}, - {"hPtAntiDeuteron", "hPtAntiDeuteron", {HistType::kTH1F, {{200, 0.0f, 10.0f, "#it{p}_{T} (GeV/c)"}}}}, - {"hDCAXYProtonToPV", "hDCAXYProtonToPV", {HistType::kTH1F, {{1000, -10.0f, 10.0f, "cm"}}}}, - {"hDCAXYPionToPV", "hDCAXYPionToPV", {HistType::kTH1F, {{1000, -10.0f, 10.0f, "cm"}}}}, - {"hDCAXYDeuteronToPV", "hDCAXYDeuteronToPV", {HistType::kTH1F, {{1000, -10.0f, 10.0f, "cm"}}}}, - {"hDCAProtonToPV", "hDCAProtonToPV", {HistType::kTH1F, {{1000, -10.0f, 10.0f, "cm"}}}}, - {"hDCAPionToPV", "hDCAPionToPV", {HistType::kTH1F, {{1000, -10.0f, 10.0f, "cm"}}}}, - {"hDCADeuteronToPV", "hDCADeuteronToPV", {HistType::kTH1F, {{1000, -10.0f, 10.0f, "cm"}}}}, - {"hProtonTPCNcls", "hProtonTPCNcls", {HistType::kTH1F, {{180, 0, 180, "TPC cluster"}}}}, - {"hPionTPCNcls", "hPionTPCNcls", {HistType::kTH1F, {{180, 0, 180, "TPC cluster"}}}}, - {"hDeuteronTPCNcls", "hDeuteronTPCNcls", {HistType::kTH1F, {{180, 0, 180, "TPC cluster"}}}}, - {"hVtxCosPA", "hVtxCosPA", {HistType::kTH1F, {{1000, 0.9f, 1.0f}}}}, - {"hDCAVtxDau", "hDCAVtxDau", {HistType::kTH1F, {{1000, 0.0f, 10.0f, "cm^{2}"}}}}, - {"hTOFPIDDeuteron", "hTOFPIDDeuteron", {HistType::kTH1F, {{2000, -100.0f, 100.0f}}}}, - {"hTPCPIDProton", "hTPCPIDProton", {HistType::kTH1F, {{120, -6.0f, 6.0f}}}}, - {"hTPCPIDPion", "hTPCPIDPion", {HistType::kTH1F, {{120, -6.0f, 6.0f}}}}, - {"hTPCPIDDeuteron", "hTPCPIDDeuteron", {HistType::kTH1F, {{120, -6.0f, 6.0f}}}}, - {"hProtonTPCBB", "hProtonTPCBB", {HistType::kTH2F, {{160, -8.0f, 8.0f, "p/z(GeV/c)"}, {200, 0.0f, 1000.0f, "TPCSignal"}}}}, - {"hPionTPCBB", "hPionTPCBB", {HistType::kTH2F, {{160, -8.0f, 8.0f, "p/z(GeV/c)"}, {200, 0.0f, 1000.0f, "TPCSignal"}}}}, - {"hDeuteronTPCBB", "hDeuteronTPCBB", {HistType::kTH2F, {{160, -8.0f, 8.0f, "p/z(GeV/c)"}, {200, 0.0f, 1000.0f, "TPCSignal"}}}}, - {"hProtonTPCVsPt", "hProtonTPCVsPt", {HistType::kTH2F, {{50, 0.0f, 5.0f, "#it{p}_{T} (GeV/c)"}, {120, -6.0f, 6.0f, "TPC n#sigma"}}}}, - {"hPionTPCVsPt", "hPionTPCVsPt", {HistType::kTH2F, {{20, 0.0f, 2.0f, "#it{p}_{T} (GeV/c)"}, {120, -6.0f, 6.0f, "TPC n#sigma"}}}}, - {"hDeuteronTPCVsPt", "hDeuteronTPCVsPt", {HistType::kTH2F, {{80, 0.0f, 8.0f, "#it{p}_{T} (GeV/c)"}, {120, -6.0f, 6.0f, "TPC n#sigma"}}}}, - {"hDeuteronTOFVsPBeforeTOFCut", "hDeuteronTOFVsPBeforeTOFCut", {HistType::kTH2F, {{40, -10.0f, 10.0f, "p/z (GeV/c)"}, {40, -10.0f, 10.0f, "TOF n#sigma"}}}}, - {"hDeuteronTOFVsPAfterTOFCut", "hDeuteronTOFVsPAfterTOFCut", {HistType::kTH2F, {{40, -10.0f, 10.0f, "p/z (GeV/c)"}, {40, -10.0f, 10.0f, "TOF n#sigma"}}}}, - - {"hDalitz", "hDalitz", {HistType::kTH2F, {{120, 7.85, 8.45, "M^{2}(dp) (GeV^{2}/c^{4})"}, {60, 1.1, 1.4, "M^{2}(p#pi) (GeV^{2}/c^{4})"}}}}, - {"h3dMassHypertriton", "h3dMassHypertriton", {HistType::kTH3F, {{20, 0.0f, 100.0f, "Cent (%)"}, {100, 0.0f, 10.0f, "#it{p}_{T} (GeV/c)"}, {80, 2.96f, 3.04f, "Inv. Mass (GeV/c^{2})"}}}}, - {"h3dMassAntiHypertriton", "h3dMassAntiHypertriton", {HistType::kTH3F, {{20, 0.0f, 100.0f, "Cent (%)"}, {100, 0.0f, 10.0f, "#it{p}_{T} (GeV/c)"}, {80, 2.96f, 3.04f, "Inv. Mass (GeV/c^{2})"}}}}, - {"h3dTotalHypertriton", "h3dTotalHypertriton", {HistType::kTH3F, {{50, 0, 50, "ct(cm)"}, {100, 0.0f, 10.0f, "#it{p}_{T} (GeV/c)"}, {80, 2.96f, 3.04f, "Inv. Mass (GeV/c^{2})"}}}}, - - {"hDeuteronTOFVsPBeforeTOFCutSig", "hDeuteronTOFVsPBeforeTOFCutSig", {HistType::kTH2F, {{40, -10.0f, 10.0f, "p/z (GeV/c)"}, {40, -10.0f, 10.0f, "TOF n#sigma"}}}}, - {"hDeuteronTOFVsPAfterTOFCutSig", "hDeuteronTOFVsPAfterTOFCutSig", {HistType::kTH2F, {{40, -10.0f, 10.0f, "p/z (GeV/c)"}, {40, -10.0f, 10.0f, "TOF n#sigma"}}}}, - {"h3dTotalTrueHypertriton", "h3dTotalTrueHypertriton", {HistType::kTH3F, {{50, 0, 50, "ct(cm)"}, {100, 0.0f, 10.0f, "#it{p}_{T} (GeV/c)"}, {80, 2.96f, 3.04f, "Inv. Mass (GeV/c^{2})"}}}}, - // For TOF PID check - /*{"hDeuteronDefaultTOFVsPBeforeTOFCut", "hDeuteronDefaultTOFVsPBeforeTOFCut", {HistType::kTH2F, {{40, -10.0f, 10.0f, "p/z (GeV/c)"}, {40, -10.0f, 10.0f, "TOF n#sigma"}}}}, - {"hDeuteronDefaultTOFVsPAtferTOFCut", "hDeuteronDefaultTOFVsPAtferTOFCut", {HistType::kTH2F, {{40, -10.0f, 10.0f, "p/z (GeV/c)"}, {40, -10.0f, 10.0f, "TOF n#sigma"}}}}, - {"hDeuteronDefaultTOFVsPBeforeTOFCutSig", "hDeuteronDefaultTOFVsPBeforeTOFCutSig", {HistType::kTH2F, {{40, -10.0f, 10.0f, "p/z (GeV/c)"}, {40, -10.0f, 10.0f, "TOF n#sigma"}}}}, - {"hDeuteronDefaultTOFVsPAfterTOFCutSig", "hDeuteronDefaultTOFVsPAfterTOFCutSig", {HistType::kTH2F, {{40, -10.0f, 10.0f, "p/z (GeV/c)"}, {40, -10.0f, 10.0f, "TOF n#sigma"}}}},*/ - }, - }; - - //------------------------------------------------------------------ - // Fill stats histograms - enum vtxstep { kCandAll = 0, - kCandDauEta, - kCandDauPt, - kCandTPCNcls, - kCandTPCPID, - kCandTOFPID, - kCandDcaToPV, - kCandRapidity, - kCandct, - kCandCosPA, - kCandDcaDau, - kCandInvMass, - kNCandSteps }; - - struct { - std::array candstats; - std::array truecandstats; - } statisticsRegistry; - - void resetHistos() - { - for (int ii = 0; ii < kNCandSteps; ii++) { - statisticsRegistry.candstats[ii] = 0; - statisticsRegistry.truecandstats[ii] = 0; - } - } - void FillCandCounter(int kn, bool istrue = false) - { - statisticsRegistry.candstats[kn]++; - if (istrue) { - statisticsRegistry.truecandstats[kn]++; - } - } - void fillHistos() - { - for (int ii = 0; ii < kNCandSteps; ii++) { - registry.fill(HIST("hCandidatesCounter"), ii, statisticsRegistry.candstats[ii]); - if (doprocessMC == true) { - registry.fill(HIST("hTrueHypertritonCounter"), ii, statisticsRegistry.truecandstats[ii]); - } - } - } - - ConfigurableAxis dcaBinning{"dca-binning", {200, 0.0f, 1.0f}, ""}; - ConfigurableAxis ptBinning{"pt-binning", {200, 0.0f, 10.0f}, ""}; - - void init(InitContext const&) - { - registry.get(HIST("hEventCounter"))->GetXaxis()->SetBinLabel(1, "total"); - registry.get(HIST("hEventCounter"))->GetXaxis()->SetBinLabel(2, "sel8"); - registry.get(HIST("hEventCounter"))->GetXaxis()->SetBinLabel(3, "vertexZ"); - registry.get(HIST("hEventCounter"))->GetXaxis()->SetBinLabel(4, "has Candidate"); - - if (doprocessMC == true) { - registry.add("hTrueHypertritonCounter", "hTrueHypertritonCounter", HistType::kTH1F, {{12, 0.0f, 12.0f}}); - auto hGeneratedHypertritonCounter = registry.add("hGeneratedHypertritonCounter", "hGeneratedHypertritonCounter", HistType::kTH1F, {{2, 0.0f, 2.0f}}); - hGeneratedHypertritonCounter->GetXaxis()->SetBinLabel(1, "Total"); - hGeneratedHypertritonCounter->GetXaxis()->SetBinLabel(2, "3-body decay"); - registry.add("hPtGeneratedHypertriton", "hPtGeneratedHypertriton", HistType::kTH1F, {{200, 0.0f, 10.0f}}); - registry.add("hctGeneratedHypertriton", "hctGeneratedHypertriton", HistType::kTH1F, {{50, 0, 50, "ct(cm)"}}); - registry.add("hEtaGeneratedHypertriton", "hEtaGeneratedHypertriton", HistType::kTH1F, {{40, -2.0f, 2.0f}}); - registry.add("hRapidityGeneratedHypertriton", "hRapidityGeneratedHypertriton", HistType::kTH1F, {{40, -2.0f, 2.0f}}); - registry.add("hPtGeneratedAntiHypertriton", "hPtGeneratedAntiHypertriton", HistType::kTH1F, {{200, 0.0f, 10.0f}}); - registry.add("hctGeneratedAntiHypertriton", "hctGeneratedAntiHypertriton", HistType::kTH1F, {{50, 0, 50, "ct(cm)"}}); - registry.add("hEtaGeneratedAntiHypertriton", "hEtaGeneratedAntiHypertriton", HistType::kTH1F, {{40, -2.0f, 2.0f}}); - registry.add("hRapidityGeneratedAntiHypertriton", "hRapidityGeneratedAntiHypertriton", HistType::kTH1F, {{40, -2.0f, 2.0f}}); - } - - TString CandCounterbinLabel[kNCandSteps] = {"Total", "TrackEta", "DauPt", "TPCNcls", "TPCPID", "d TOFPID", "PionDcatoPV", "MomRapidity", "Lifetime", "VtxCosPA", "VtxDcaDau", "InvMass"}; - for (int i{0}; i < kNCandSteps; i++) { - registry.get(HIST("hCandidatesCounter"))->GetXaxis()->SetBinLabel(i + 1, CandCounterbinLabel[i]); - if (doprocessMC == true) { - registry.get(HIST("hTrueHypertritonCounter"))->GetXaxis()->SetBinLabel(i + 1, CandCounterbinLabel[i]); - } - } - } - - //------------------------------------------------------------------ - // Selections for candidates - template - bool SelectCand(TCollisionTable const& collision, TCandTable const& candData, TTrackTable const& trackProton, TTrackTable const& trackPion, TTrackTable const& trackDeuteron, bool isMatter, bool isTrueCand = false, double MClifetime = -1, double lPt = -1) - { - FillCandCounter(kCandAll, isTrueCand); - - // Selection on daughters - if (std::abs(trackProton.eta()) > etacut || std::abs(trackPion.eta()) > etacut || std::abs(trackDeuteron.eta()) > etacut) { - return false; - } - FillCandCounter(kCandDauEta, isTrueCand); - - if (trackProton.pt() < minProtonPt || trackProton.pt() > maxProtonPt || trackPion.pt() < minPionPt || trackPion.pt() > maxPionPt || trackDeuteron.pt() < minDeuteronPt || trackDeuteron.pt() > maxDeuteronPt) { - return false; - } - FillCandCounter(kCandDauPt, isTrueCand); - - if (trackProton.tpcNClsFound() < mintpcNClsproton || trackPion.tpcNClsFound() < mintpcNClspion || trackDeuteron.tpcNClsFound() < mintpcNClsdeuteron) { - return false; - } - FillCandCounter(kCandTPCNcls, isTrueCand); - - if (std::abs(trackProton.tpcNSigmaPr()) > tpcPIDNSigmaCut || std::abs(trackPion.tpcNSigmaPi()) > tpcPIDNSigmaCut || std::abs(trackDeuteron.tpcNSigmaDe()) > tpcPIDNSigmaCut) { - return false; - } - FillCandCounter(kCandTPCPID, isTrueCand); - - // registry.fill(HIST("hDeuteronDefaultTOFVsPBeforeTOFCut"), trackDeuteron.sign() * trackDeuteron.p(), trackDeuteron.tofNSigmaDe()); - registry.fill(HIST("hDeuteronTOFVsPBeforeTOFCut"), trackDeuteron.sign() * trackDeuteron.p(), candData.tofNSigmaBachDe()); - if (isTrueCand) { - // registry.fill(HIST("hDeuteronDefaultTOFVsPBeforeTOFCutSig"), trackDeuteron.sign() * trackDeuteron.p(), trackDeuteron.tofNSigmaDe()); - registry.fill(HIST("hDeuteronTOFVsPBeforeTOFCutSig"), trackDeuteron.sign() * trackDeuteron.p(), candData.tofNSigmaBachDe()); - } - if ((candData.tofNSigmaBachDe() < tofPIDNSigmaMin || candData.tofNSigmaBachDe() > tofPIDNSigmaMax) && trackDeuteron.p() > minDeuteronPUseTOF) { - return false; - } - FillCandCounter(kCandTOFPID, isTrueCand); - // registry.fill(HIST("hDeuteronDefaultTOFVsPAtferTOFCut"), trackDeuteron.sign() * trackDeuteron.p(), trackDeuteron.tofNSigmaDe()); - registry.fill(HIST("hDeuteronTOFVsPAfterTOFCut"), trackDeuteron.sign() * trackDeuteron.p(), candData.tofNSigmaBachDe()); - if (isTrueCand) { - // registry.fill(HIST("hDeuteronDefaultTOFVsPAfterTOFCutSig"), trackDeuteron.sign() * trackDeuteron.p(), trackDeuteron.tofNSigmaDe()); - registry.fill(HIST("hDeuteronTOFVsPAfterTOFCutSig"), trackDeuteron.sign() * trackDeuteron.p(), candData.tofNSigmaBachDe()); - } - - double dcapion = isMatter ? candData.dcatrack1topv() : candData.dcatrack0topv(); - if (std::abs(dcapion) < dcapiontopv) { - return false; - } - FillCandCounter(kCandDcaToPV, isTrueCand); - - // Selection on candidate hypertriton - if (std::abs(candData.yHypertriton()) > rapiditycut) { - return false; - } - FillCandCounter(kCandRapidity, isTrueCand); - - double ct = candData.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassHyperTriton; - if (ct > lifetimecut) { - return false; - } - FillCandCounter(kCandct, isTrueCand); - - double cospa = candData.vtxcosPA(collision.posX(), collision.posY(), collision.posZ()); - if (cospa < vtxcospa) { - return false; - } - FillCandCounter(kCandCosPA, isTrueCand); - - if (candData.dcaVtxdaughters() > dcavtxdau) { - return false; - } - FillCandCounter(kCandDcaDau, isTrueCand); - - if ((isMatter && candData.mHypertriton() > h3LMassLowerlimit && candData.mHypertriton() < h3LMassUpperlimit)) { - // Hypertriton - registry.fill(HIST("hPtProton"), trackProton.pt()); - registry.fill(HIST("hPtPionMinus"), trackPion.pt()); - registry.fill(HIST("hPtDeuteron"), trackDeuteron.pt()); - registry.fill(HIST("hDCAXYProtonToPV"), candData.dcaXYtrack0topv()); - registry.fill(HIST("hDCAXYPionToPV"), candData.dcaXYtrack1topv()); - registry.fill(HIST("hDCAProtonToPV"), candData.dcatrack0topv()); - registry.fill(HIST("hDCAPionToPV"), candData.dcatrack1topv()); - - registry.fill(HIST("hMassHypertriton"), candData.mHypertriton()); - registry.fill(HIST("hMassHypertritonTotal"), candData.mHypertriton()); - registry.fill(HIST("h3dMassHypertriton"), 0., candData.pt(), candData.mHypertriton()); // collision.centV0M() instead of 0. once available - registry.fill(HIST("h3dTotalHypertriton"), ct, candData.pt(), candData.mHypertriton()); - if (candData.mHypertriton() > lowersignallimit && candData.mHypertriton() < uppersignallimit) { - registry.fill(HIST("hDalitz"), RecoDecay::m2(std::array{std::array{candData.pxtrack0(), candData.pytrack0(), candData.pztrack0()}, std::array{candData.pxtrack2(), candData.pytrack2(), candData.pztrack2()}}, std::array{o2::constants::physics::MassProton, o2::constants::physics::MassDeuteron}), RecoDecay::m2(std::array{std::array{candData.pxtrack0(), candData.pytrack0(), candData.pztrack0()}, std::array{candData.pxtrack1(), candData.pytrack1(), candData.pztrack1()}}, std::array{o2::constants::physics::MassProton, o2::constants::physics::MassPionCharged})); - } - if (isTrueCand) { - registry.fill(HIST("h3dTotalTrueHypertriton"), MClifetime, lPt, candData.mHypertriton()); - } - } else if ((!isMatter && candData.mAntiHypertriton() > h3LMassLowerlimit && candData.mAntiHypertriton() < h3LMassUpperlimit)) { - // AntiHypertriton - registry.fill(HIST("hPtAntiProton"), trackProton.pt()); - registry.fill(HIST("hPtPionPlus"), trackPion.pt()); - registry.fill(HIST("hPtAntiDeuteron"), trackDeuteron.pt()); - registry.fill(HIST("hDCAXYProtonToPV"), candData.dcaXYtrack1topv()); - registry.fill(HIST("hDCAXYPionToPV"), candData.dcaXYtrack0topv()); - registry.fill(HIST("hDCAProtonToPV"), candData.dcatrack1topv()); - registry.fill(HIST("hDCAPionToPV"), candData.dcatrack0topv()); - - registry.fill(HIST("hMassAntiHypertriton"), candData.mAntiHypertriton()); - registry.fill(HIST("hMassHypertritonTotal"), candData.mAntiHypertriton()); - registry.fill(HIST("h3dMassAntiHypertriton"), 0., candData.pt(), candData.mAntiHypertriton()); // collision.centV0M() instead of 0. once available - registry.fill(HIST("h3dTotalHypertriton"), ct, candData.pt(), candData.mAntiHypertriton()); - if (candData.mAntiHypertriton() > lowersignallimit && candData.mAntiHypertriton() < uppersignallimit) { - registry.fill(HIST("hDalitz"), RecoDecay::m2(std::array{std::array{candData.pxtrack1(), candData.pytrack1(), candData.pztrack1()}, std::array{candData.pxtrack2(), candData.pytrack2(), candData.pztrack2()}}, std::array{o2::constants::physics::MassProton, o2::constants::physics::MassDeuteron}), RecoDecay::m2(std::array{std::array{candData.pxtrack1(), candData.pytrack1(), candData.pztrack1()}, std::array{candData.pxtrack0(), candData.pytrack0(), candData.pztrack0()}}, std::array{o2::constants::physics::MassProton, o2::constants::physics::MassPionCharged})); - } - if (isTrueCand) { - registry.fill(HIST("h3dTotalTrueHypertriton"), MClifetime, lPt, candData.mHypertriton()); - } - } else { - return false; - } - - FillCandCounter(kCandInvMass, isTrueCand); - - registry.fill(HIST("hDCAXYDeuteronToPV"), candData.dcaXYtrack2topv()); - registry.fill(HIST("hDCADeuteronToPV"), candData.dcatrack2topv()); - registry.fill(HIST("hVtxCosPA"), candData.vtxcosPA(collision.posX(), collision.posY(), collision.posZ())); - registry.fill(HIST("hDCAVtxDau"), candData.dcaVtxdaughters()); - registry.fill(HIST("hProtonTPCNcls"), trackProton.tpcNClsCrossedRows()); - registry.fill(HIST("hPionTPCNcls"), trackPion.tpcNClsCrossedRows()); - registry.fill(HIST("hDeuteronTPCNcls"), trackDeuteron.tpcNClsCrossedRows()); - registry.fill(HIST("hTPCPIDProton"), trackProton.tpcNSigmaPr()); - registry.fill(HIST("hTPCPIDPion"), trackPion.tpcNSigmaPi()); - registry.fill(HIST("hTPCPIDDeuteron"), trackDeuteron.tpcNSigmaDe()); - registry.fill(HIST("hProtonTPCBB"), trackProton.sign() * trackProton.p(), trackProton.tpcSignal()); - registry.fill(HIST("hPionTPCBB"), trackPion.sign() * trackPion.p(), trackPion.tpcSignal()); - registry.fill(HIST("hDeuteronTPCBB"), trackDeuteron.sign() * trackDeuteron.p(), trackDeuteron.tpcSignal()); - registry.fill(HIST("hProtonTPCVsPt"), trackProton.pt(), trackProton.tpcNSigmaPr()); - registry.fill(HIST("hPionTPCVsPt"), trackProton.pt(), trackPion.tpcNSigmaPi()); - registry.fill(HIST("hDeuteronTPCVsPt"), trackDeuteron.pt(), trackDeuteron.tpcNSigmaDe()); - registry.fill(HIST("hTOFPIDDeuteron"), candData.tofNSigmaBachDe()); - - return true; - } - - //------------------------------------------------------------------ - // Analysis process for a single candidate - template - void CandidateAnalysis(TCollisionTable const& collision, TCandTable const& candData, bool& if_hasvtx, bool isTrueCand = false, double MClifetime = -1, double lPt = -1) - { - - auto track0 = candData.template track0_as(); - auto track1 = candData.template track1_as(); - auto track2 = candData.template track2_as(); - - bool isMatter = track2.sign() > 0; - - auto& trackProton = isMatter ? track0 : track1; - auto& trackPion = isMatter ? track1 : track0; - auto& trackDeuteron = track2; - - if (SelectCand(collision, candData, trackProton, trackPion, trackDeuteron, isMatter, isTrueCand, MClifetime, lPt)) { - if_hasvtx = true; - } - } - - //------------------------------------------------------------------ - // collect information for generated hypertriton (should be called after event selection) - void GetGeneratedH3LInfo(aod::McParticles const& particlesMC) - { - for (const auto& mcparticle : particlesMC) { - if (std::abs(mcparticle.pdgCode()) != motherPdgCode) { - continue; - } - registry.fill(HIST("hGeneratedHypertritonCounter"), 0.5); - - bool haveProton = false, havePionPlus = false, haveDeuteron = false; - bool haveAntiProton = false, havePionMinus = false, haveAntiDeuteron = false; - double MClifetime = -1; - for (const auto& mcparticleDaughter : mcparticle.template daughters_as()) { - if (mcparticleDaughter.pdgCode() == 2212) - haveProton = true; - if (mcparticleDaughter.pdgCode() == -2212) - haveAntiProton = true; - if (mcparticleDaughter.pdgCode() == 211) - havePionPlus = true; - if (mcparticleDaughter.pdgCode() == -211) - havePionMinus = true; - if (mcparticleDaughter.pdgCode() == bachelorPdgCode) { - haveDeuteron = true; - MClifetime = RecoDecay::sqrtSumOfSquares(mcparticleDaughter.vx() - mcparticle.vx(), mcparticleDaughter.vy() - mcparticle.vy(), mcparticleDaughter.vz() - mcparticle.vz()) * o2::constants::physics::MassHyperTriton / mcparticle.p(); - } - if (mcparticleDaughter.pdgCode() == -bachelorPdgCode) { - haveAntiDeuteron = true; - MClifetime = RecoDecay::sqrtSumOfSquares(mcparticleDaughter.vx() - mcparticle.vx(), mcparticleDaughter.vy() - mcparticle.vy(), mcparticleDaughter.vz() - mcparticle.vz()) * o2::constants::physics::MassHyperTriton / mcparticle.p(); - } - } - if (haveProton && havePionMinus && haveDeuteron && mcparticle.pdgCode() == motherPdgCode) { - registry.fill(HIST("hGeneratedHypertritonCounter"), 1.5); - registry.fill(HIST("hPtGeneratedHypertriton"), mcparticle.pt()); - registry.fill(HIST("hctGeneratedHypertriton"), MClifetime); - registry.fill(HIST("hEtaGeneratedHypertriton"), mcparticle.eta()); - registry.fill(HIST("hRapidityGeneratedHypertriton"), mcparticle.y()); - } else if (haveAntiProton && havePionPlus && haveAntiDeuteron && mcparticle.pdgCode() == -motherPdgCode) { - registry.fill(HIST("hGeneratedHypertritonCounter"), 1.5); - registry.fill(HIST("hPtGeneratedAntiHypertriton"), mcparticle.pt()); - registry.fill(HIST("hctGeneratedAntiHypertriton"), MClifetime); - registry.fill(HIST("hEtaGeneratedAntiHypertriton"), mcparticle.eta()); - registry.fill(HIST("hRapidityGeneratedAntiHypertriton"), mcparticle.y()); - } - } - } - - //------------------------------------------------------------------ - // process real data analysis - void processData(soa::Join::iterator const& collision, aod::Vtx3BodyDatas const& vtx3bodydatas, FullTracksExtIU const& /*tracks*/) - { - registry.fill(HIST("hEventCounter"), 0.5); - if (event_sel8_selection && !collision.sel8()) { - return; - } - registry.fill(HIST("hEventCounter"), 1.5); - if (event_posZ_selection && std::abs(collision.posZ()) > 10.f) { // 10cm - return; - } - registry.fill(HIST("hEventCounter"), 2.5); - - bool if_hasvtx = false; - - for (const auto& vtx : vtx3bodydatas) { - CandidateAnalysis(collision, vtx, if_hasvtx); - } - - if (if_hasvtx) - registry.fill(HIST("hEventCounter"), 3.5); - fillHistos(); - resetHistos(); - } - PROCESS_SWITCH(hypertriton3bodyAnalysis, processData, "Real data analysis", true); - - //------------------------------------------------------------------ - // process mc analysis - void processMC(soa::Join const& collisions, aod::Vtx3BodyDatas const& vtx3bodydatas, aod::McParticles const& particlesMC, MCLabeledTracksIU const& /*tracks*/) - { - GetGeneratedH3LInfo(particlesMC); - - for (const auto& collision : collisions) { - registry.fill(HIST("hEventCounter"), 0.5); - if (mc_event_selection && (!collision.selection_bit(aod::evsel::kIsTriggerTVX) || !collision.selection_bit(aod::evsel::kNoTimeFrameBorder))) { - continue; - } - registry.fill(HIST("hEventCounter"), 1.5); - if (event_posZ_selection && std::abs(collision.posZ()) > 10.f) { // 10cm - continue; - } - registry.fill(HIST("hEventCounter"), 2.5); - - bool if_hasvtx = false; - auto vtxsthiscol = vtx3bodydatas.sliceBy(perCollisionVtx3BodyDatas, collision.globalIndex()); - - for (const auto& vtx : vtxsthiscol) { - // int lLabel = -1; - int lPDG = -1; - float lPt = -1; - double MClifetime = -1; - bool isTrueCand = false; - auto track0 = vtx.track0_as(); - auto track1 = vtx.track1_as(); - auto track2 = vtx.track2_as(); - if (track0.has_mcParticle() && track1.has_mcParticle() && track2.has_mcParticle()) { - auto lMCTrack0 = track0.mcParticle_as(); - auto lMCTrack1 = track1.mcParticle_as(); - auto lMCTrack2 = track2.mcParticle_as(); - if (lMCTrack0.has_mothers() && lMCTrack1.has_mothers() && lMCTrack2.has_mothers()) { - for (const auto& lMother0 : lMCTrack0.mothers_as()) { - for (const auto& lMother1 : lMCTrack1.mothers_as()) { - for (const auto& lMother2 : lMCTrack2.mothers_as()) { - if (lMother0.globalIndex() == lMother1.globalIndex() && lMother0.globalIndex() == lMother2.globalIndex()) { - // lLabel = lMother1.globalIndex(); - lPt = lMother1.pt(); - lPDG = lMother1.pdgCode(); - if ((lPDG == motherPdgCode && lMCTrack0.pdgCode() == 2212 && lMCTrack1.pdgCode() == -211 && lMCTrack2.pdgCode() == bachelorPdgCode) || - (lPDG == -motherPdgCode && lMCTrack0.pdgCode() == 211 && lMCTrack1.pdgCode() == -2212 && lMCTrack2.pdgCode() == -bachelorPdgCode)) { - isTrueCand = true; - MClifetime = RecoDecay::sqrtSumOfSquares(lMCTrack2.vx() - lMother2.vx(), lMCTrack2.vy() - lMother2.vy(), lMCTrack2.vz() - lMother2.vz()) * o2::constants::physics::MassHyperTriton / lMother2.p(); - } - } - } - } - } - } - } - - CandidateAnalysis(collision, vtx, if_hasvtx, isTrueCand, MClifetime, lPt); - } - - if (if_hasvtx) - registry.fill(HIST("hEventCounter"), 3.5); - fillHistos(); - resetHistos(); - } - } - PROCESS_SWITCH(hypertriton3bodyAnalysis, processMC, "MC analysis", false); -}; - -// check vtx3body with mclabels -struct hypertriton3bodyLabelCheck { - - Configurable mc_event_selection{"mc_event_selection", true, "mc event selection count post kIsTriggerTVX and kNoTimeFrameBorder"}; - Configurable event_posZ_selection{"event_posZ_selection", false, "event selection count post poZ cut"}; - Configurable tpcPIDNSigmaCut{"tpcPIDNSigmaCut", 5, "tpcPIDNSigmaCut"}; - Configurable motherPdgCode{"motherPdgCode", 1010010030, "pdgCode of mother track"}; - - HistogramRegistry registry{"registry", {}}; - - void init(InitContext const&) - { - if (doprocessData == false) { - auto hLabeledVtxCounter = registry.add("hLabeledVtxCounter", "hLabeledVtxCounter", HistType::kTH1F, {{3, 0.0f, 3.0f}}); - hLabeledVtxCounter->GetXaxis()->SetBinLabel(1, "Readin"); - hLabeledVtxCounter->GetXaxis()->SetBinLabel(2, "TrueMCH3L"); - hLabeledVtxCounter->GetXaxis()->SetBinLabel(3, "Nonrepetitive"); - registry.add("hMassTrueH3L", "hMassTrueH3L", HistType::kTH1F, {{80, 2.96f, 3.04f}}); - registry.add("hMassTrueH3LMatter", "hMassTrueH3LMatter", HistType::kTH1F, {{80, 2.96f, 3.04f}}); - registry.add("hMassTrueH3LAntiMatter", "hMassTrueH3LAntiMatter", HistType::kTH1F, {{80, 2.96f, 3.04f}}); - auto hPIDCounter = registry.add("hPIDCounter", "hPIDCounter", HistType::kTH1F, {{6, 0.0f, 6.0f}}); - hPIDCounter->GetXaxis()->SetBinLabel(1, "H3L Proton PID > 5"); - hPIDCounter->GetXaxis()->SetBinLabel(2, "H3L Pion PID > 5"); - hPIDCounter->GetXaxis()->SetBinLabel(3, "H3L Deuteron PID > 5"); - hPIDCounter->GetXaxis()->SetBinLabel(4, "#bar{H3L} Proton PID > 5"); - hPIDCounter->GetXaxis()->SetBinLabel(5, "#bar{H3L} Pion PID > 5"); - hPIDCounter->GetXaxis()->SetBinLabel(6, "#bar{H3L} Deuteron PID > 5"); - auto hHypertritonCounter = registry.add("hHypertritonCounter", "hHypertritonCounter", HistType::kTH1F, {{4, 0.0f, 4.0f}}); - hHypertritonCounter->GetXaxis()->SetBinLabel(1, "H3L"); - hHypertritonCounter->GetXaxis()->SetBinLabel(2, "H3L daughters pass PID"); - hHypertritonCounter->GetXaxis()->SetBinLabel(3, "#bar{H3L}"); - hHypertritonCounter->GetXaxis()->SetBinLabel(4, "#bar{H3L} daughters pass PID"); - auto hDecay3BodyCounter = registry.add("hDecay3BodyCounter", "hDecay3BodyCounter", HistType::kTH1F, {{5, 0.0f, 5.0f}}); - hDecay3BodyCounter->GetXaxis()->SetBinLabel(1, "Total"); - hDecay3BodyCounter->GetXaxis()->SetBinLabel(2, "True H3L"); - hDecay3BodyCounter->GetXaxis()->SetBinLabel(3, "Unduplicated H3L"); - hDecay3BodyCounter->GetXaxis()->SetBinLabel(4, "Correct collision"); - hDecay3BodyCounter->GetXaxis()->SetBinLabel(5, "Same ColID for daughters"); - registry.add("hDiffRVtxProton", "hDiffRVtxProton", HistType::kTH1F, {{100, -10, 10}}); // difference between the radius of decay vertex and minR of proton - registry.add("hDiffRVtxPion", "hDiffRVtxPion", HistType::kTH1F, {{100, -10, 10}}); // difference between the radius of decay vertex and minR of pion - registry.add("hDiffRVtxDeuteron", "hDiffRVtxDeuteron", HistType::kTH1F, {{100, -10, 10}}); // difference between the radius of decay vertex and minR of deuteron - } - } - - struct Indexdaughters { // check duplicated paired daughters - int64_t index0; - int64_t index1; - int64_t index2; - bool operator==(const Indexdaughters& t) const - { - return (this->index0 == t.index0 && this->index1 == t.index1 && this->index2 == t.index2); - } - }; - - void processData(soa::Join::iterator const&) - { - // dummy function - } - PROCESS_SWITCH(hypertriton3bodyLabelCheck, processData, "Donot check MC label tables", true); - - void processCheckLabel(soa::Join::iterator const& collision, aod::Decay3Bodys const& decay3bodys, soa::Join const& vtx3bodydatas, MCLabeledTracksIU const& /*tracks*/, aod::McParticles const& /*particlesMC*/, aod::McCollisions const& /*mcCollisions*/) - { - // check the decay3body table - std::vector set_pair; - for (const auto& d3body : decay3bodys) { - registry.fill(HIST("hDecay3BodyCounter"), 0.5); - auto lTrack0 = d3body.track0_as(); - auto lTrack1 = d3body.track1_as(); - auto lTrack2 = d3body.track2_as(); - if (!lTrack0.has_mcParticle() || !lTrack1.has_mcParticle() || !lTrack2.has_mcParticle()) { - continue; - } - auto lMCTrack0 = lTrack0.mcParticle_as(); - auto lMCTrack1 = lTrack1.mcParticle_as(); - auto lMCTrack2 = lTrack2.mcParticle_as(); - if (!lMCTrack0.has_mothers() || !lMCTrack1.has_mothers() || !lMCTrack2.has_mothers()) { - continue; - } - - for (const auto& lMother0 : lMCTrack0.mothers_as()) { - for (const auto& lMother1 : lMCTrack1.mothers_as()) { - for (const auto& lMother2 : lMCTrack2.mothers_as()) { - if (lMother0.globalIndex() == lMother1.globalIndex() && lMother0.globalIndex() == lMother2.globalIndex()) { - registry.fill(HIST("hDecay3BodyCounter"), 1.5); - // duplicated daughters check - Indexdaughters temp = {lMCTrack0.globalIndex(), lMCTrack1.globalIndex(), lMCTrack2.globalIndex()}; - auto p = std::find(set_pair.begin(), set_pair.end(), temp); - if (p == set_pair.end()) { - set_pair.push_back(temp); - registry.fill(HIST("hDecay3BodyCounter"), 2.5); - if (lMother0.mcCollisionId() == collision.mcCollisionId()) { - registry.fill(HIST("hDecay3BodyCounter"), 3.5); - if (lTrack0.collisionId() == lTrack1.collisionId() && lTrack0.collisionId() == lTrack2.collisionId()) { - registry.fill(HIST("hDecay3BodyCounter"), 4.5); - } - } - } - } - } - } - } - } - - if (mc_event_selection && (!collision.selection_bit(aod::evsel::kIsTriggerTVX) || !collision.selection_bit(aod::evsel::kNoTimeFrameBorder))) { - return; - } - - if (event_posZ_selection && std::abs(collision.posZ()) > 10.f) { // 10cm - return; - } - - std::vector set_mothertrack; - for (const auto& vtx : vtx3bodydatas) { - registry.fill(HIST("hLabeledVtxCounter"), 0.5); - if (vtx.mcParticleId() != -1) { - auto mcparticle = vtx.mcParticle_as(); - auto lTrack0 = vtx.track0_as(); - auto lTrack1 = vtx.track1_as(); - auto lTrack2 = vtx.track2_as(); - if (std::abs(mcparticle.pdgCode()) != motherPdgCode) { - continue; - } - registry.fill(HIST("hLabeledVtxCounter"), 1.5); - registry.fill(HIST("hDiffRVtxDeuteron"), lTrack2.x() - vtx.vtxradius()); - if (mcparticle.pdgCode() > 0) { - registry.fill(HIST("hHypertritonCounter"), 0.5); - registry.fill(HIST("hMassTrueH3L"), vtx.mHypertriton()); - registry.fill(HIST("hMassTrueH3LMatter"), vtx.mHypertriton()); - registry.fill(HIST("hDiffRVtxProton"), lTrack0.x() - vtx.vtxradius()); - registry.fill(HIST("hDiffRVtxPion"), lTrack1.x() - vtx.vtxradius()); - auto p = std::find(set_mothertrack.begin(), set_mothertrack.end(), mcparticle.globalIndex()); - if (p == set_mothertrack.end()) { - set_mothertrack.push_back(mcparticle.globalIndex()); - registry.fill(HIST("hLabeledVtxCounter"), 2.5); - } - if (std::abs(lTrack0.tpcNSigmaPr()) > tpcPIDNSigmaCut) { - registry.fill(HIST("hPIDCounter"), 0.5); - } - if (std::abs(lTrack1.tpcNSigmaPi()) > tpcPIDNSigmaCut) { - registry.fill(HIST("hPIDCounter"), 1.5); - } - if (std::abs(lTrack2.tpcNSigmaDe()) > tpcPIDNSigmaCut) { - registry.fill(HIST("hPIDCounter"), 2.5); - } - if (std::abs(lTrack0.tpcNSigmaPr()) < tpcPIDNSigmaCut && std::abs(lTrack1.tpcNSigmaPi()) < tpcPIDNSigmaCut && std::abs(lTrack2.tpcNSigmaDe()) < tpcPIDNSigmaCut) { - registry.fill(HIST("hHypertritonCounter"), 1.5); - } - } else { - registry.fill(HIST("hHypertritonCounter"), 2.5); - registry.fill(HIST("hMassTrueH3L"), vtx.mAntiHypertriton()); - registry.fill(HIST("hMassTrueH3LAntiMatter"), vtx.mAntiHypertriton()); - registry.fill(HIST("hDiffRVtxProton"), lTrack1.x() - vtx.vtxradius()); - registry.fill(HIST("hDiffRVtxPion"), lTrack0.x() - vtx.vtxradius()); - auto p = std::find(set_mothertrack.begin(), set_mothertrack.end(), mcparticle.globalIndex()); - if (p == set_mothertrack.end()) { - set_mothertrack.push_back(mcparticle.globalIndex()); - registry.fill(HIST("hLabeledVtxCounter"), 2.5); - } - if (std::abs(lTrack0.tpcNSigmaPi()) > tpcPIDNSigmaCut) { - registry.fill(HIST("hPIDCounter"), 4.5); - } - if (std::abs(lTrack1.tpcNSigmaPr()) > tpcPIDNSigmaCut) { - registry.fill(HIST("hPIDCounter"), 3.5); - } - if (std::abs(lTrack2.tpcNSigmaDe()) > tpcPIDNSigmaCut) { - registry.fill(HIST("hPIDCounter"), 5.5); - } - if (std::abs(lTrack0.tpcNSigmaPi()) < tpcPIDNSigmaCut && std::abs(lTrack1.tpcNSigmaPr()) < tpcPIDNSigmaCut && std::abs(lTrack2.tpcNSigmaDe()) < tpcPIDNSigmaCut) { - registry.fill(HIST("hHypertritonCounter"), 3.5); - } - } - } - } - } - PROCESS_SWITCH(hypertriton3bodyLabelCheck, processCheckLabel, "Check MC label tables", false); -}; - -WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) -{ - return WorkflowSpec{ - adaptAnalysisTask(cfgc), - adaptAnalysisTask(cfgc), - adaptAnalysisTask(cfgc), - }; -} diff --git a/PWGLF/Utils/decay3bodyBuilderHelper.h b/PWGLF/Utils/decay3bodyBuilderHelper.h new file mode 100644 index 00000000000..550625f2fc6 --- /dev/null +++ b/PWGLF/Utils/decay3bodyBuilderHelper.h @@ -0,0 +1,838 @@ +// 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. + +#ifndef PWGLF_UTILS_DECAY3BODYBUILDERHELPER_H_ +#define PWGLF_UTILS_DECAY3BODYBUILDERHELPER_H_ + +#include +#include +#include +#include "DCAFitter/DCAFitterN.h" +#include "Framework/AnalysisDataModel.h" +#include "ReconstructionDataFormats/Track.h" +#include "DetectorsBase/GeometryManager.h" +#include "DetectorsVertexing/SVertexHypothesis.h" +#include "CommonConstants/PhysicsConstants.h" +#include "Common/Core/trackUtilities.h" +#include "Common/Core/RecoDecay.h" +#include "Tools/KFparticle/KFUtilities.h" + +#ifndef HomogeneousField +#define HomogeneousField +#endif + +/// includes KFParticle +#include "KFParticle.h" +#include "KFPTrack.h" +#include "KFPVertex.h" +#include "KFParticleBase.h" +#include "KFVertex.h" + +namespace o2 +{ +namespace pwglf +{ + +//_______________________________________________________________________ +// Deca3body information storage +struct decay3bodyCandidate { + // indexing + int collisionID = -1; + int decay3bodyID = -1; + int protonID = -1; + int pionID = -1; + int deuteronID = -1; + + // daughter properties + std::array momProton = {0.0f, 0.0f, 0.0f}; + std::array momPion = {0.0f, 0.0f, 0.0f}; + std::array momDeuteron = {0.0f, 0.0f, 0.0f}; + std::array posProton = {0.0f, 0.0f, 0.0f}; + std::array posPion = {0.0f, 0.0f, 0.0f}; + std::array posDeuteron = {0.0f, 0.0f, 0.0f}; + std::array trackDCAxyToPV = {0.0f, 0.0f, 0.0f}; // 0 - proton, 1 - pion, 2 - deuteron + std::array trackDCAzToPV = {0.0f, 0.0f, 0.0f}; // 0 - proton, 1 - pion, 2 - deuteron + std::array tpcNsigma = {0.0f, 0.0f, 0.0f, 0.0f}; // 0 - proton, 1 - pion, 2 - deuteron, 3 - bach with pion hyp + double tofNsigmaDeuteron = 0.0f; + std::array averageITSClSize = {0.0f, 0.0f, 0.0f}; // 0 - proton, 1 - pion, 2 - deuteron + std::array tpcNCl = {0.0f, 0.0f, 0.0f}; // 0 - proton, 1 - pion, 2 - deuteron + int pidForTrackingDeuteron = 0; + + // vertex properties + float mass; + float massV0; + int sign; + float momentum[3]; + float position[3]; + // std::array momentum = {0.0f, 0.0f, 0.0f}; + // std::array position = {0.0f, 0.0f, 0.0f}; + // float dcaToPV = 0.0f; + // float dcaxyToPV = 0.0f; + float chi2 = 0.0f; + float trackedClSize = 0.0f; + float daughterDCAatSV = 0.0f; // quadratic sum of DCA between daughters at SV + std::array daughterDCAtoSV = {0.0f, 0.0f, 0.0f}; // 0 - pos, 1 - neg, 2 - bach + + // covariance matrix + float covProton[21] = {0.0f}; + float covPion[21] = {0.0f}; + float covDeuteron[21] = {0.0f}; + float covariance[21] = {0.0f}; +}; + +//_______________________________________________________________________ +// builder helper class +class decay3bodyBuilderHelper +{ + public: + decay3bodyBuilderHelper() + { + fitter3body.setPropagateToPCA(true); + fitter3body.setMaxR(200.); //->maxRIni3body + fitter3body.setMinParamChange(1e-3); + fitter3body.setMinRelChi2Change(0.9); + fitter3body.setMaxDZIni(1e9); + fitter3body.setMaxDXYIni(4.0f); + fitter3body.setMaxChi2(1e9); + fitter3body.setUseAbsDCA(true); + + fitterV0.setPropagateToPCA(true); + fitterV0.setMaxR(200.); + fitterV0.setMinParamChange(1e-3); + fitterV0.setMinRelChi2Change(0.9); + fitterV0.setMaxDZIni(1e9); + fitterV0.setMaxChi2(1e9); + fitterV0.setUseAbsDCA(true); + + // mag field has to be set later + fitter3body.setBz(-999.9f); // will NOT make sense if not changed + }; + + o2::vertexing::DCAFitterN<2> fitterV0; // 2-prong o2 dca fitter + o2::vertexing::DCAFitterN<3> fitter3body; // 3-prong o2 dca fitter + + decay3bodyCandidate decay3body; // storage for Decay3body candidate properties + + o2::dataformats::VertexBase mMeanVertex{{0., 0., 0.}, {0.1 * 0.1, 0., 0.1 * 0.1, 0., 0., 6. * 6.}}; + o2::vertexing::SVertexHypothesis mV0Hyps; // 0 - Lambda, 1 - AntiLambda + + // decay3body candidate criteria + struct { + // daughter tracks + float maxEtaDaughters; + int minTPCNClProton; + int minTPCNClPion; + int minTPCNClDeuteron; + float minDCAProtonToPV; + float minDCAPionToPV; + float minDCADeuteronToPV; + float minPtProton; + float minPtPion; + float minPtDeuteron; + float maxPtProton; + float maxPtPion; + float maxPtDeuteron; + float maxTPCnSigma; + double minTOFnSigmaDeuteron; + double maxTOFnSigmaDeuteron; + float minPDeuteronUseTOF; + float maxDCADauAtSV; + // candidate + float maxRapidity; + float minPt; + float maxPt; + float minMass; + float maxMass; + float minCtau; + float maxCtau; + float minCosPA; + float maxChi2; + } decay3bodyselections; + + // SVertexer selection criteria + struct { + float minPt2V0; + float maxTgl2V0; + float maxDCAXY2ToMeanVertex3bodyV0; + float minCosPAXYMeanVertex3bodyV0; + float minCosPA3bodyV0; + float maxRDiffV03body; + float minPt3Body; + float maxTgl3Body; + float maxDCAXY3Body; + float maxDCAZ3Body; + } svertexerselections; + + //_______________________________________________________________________ + // build Decay3body from three tracks, including V0 building. + template + bool buildDecay3BodyCandidate(TCollision const& collision, + TTrack const& trackProton, + TTrack const& trackPion, + TTrack const& trackDeuteron, + int decay3bodyIndex, + double tofNsigmaDeuteron, + float trackedClSize, + bool useKFParticle = false, + bool kfSetTopologicalConstraint = false, + bool useSelections = true, + bool useTPCforPion = false, + bool acceptTPCOnly = false, + bool calculateCovariance = true, + bool isEventMixing = false) + { + int collisionIndex = collision.globalIndex(); + float pvX = collision.posX(); + float pvY = collision.posY(); + float pvZ = collision.posZ(); + + auto trackParCovProton = getTrackParCov(trackProton); + auto trackParCovPion = getTrackParCov(trackPion); + auto trackParCovDeuteron = getTrackParCov(trackDeuteron); + + decay3body.collisionID = collisionIndex; + decay3body.decay3bodyID = decay3bodyIndex; + decay3body.protonID = trackProton.globalIndex(); + decay3body.pionID = trackPion.globalIndex(); + decay3body.deuteronID = trackDeuteron.globalIndex(); + + //_______________________________________________________________________ + // track selections + if (useSelections) { + // proton track quality + if (trackProton.tpcNClsFound() < decay3bodyselections.minTPCNClProton) { + decay3body = {}; + return false; + } + // pion track quality + if (useTPCforPion) { + if (trackPion.tpcNClsFound() < decay3bodyselections.minTPCNClPion) { + decay3body = {}; + return false; + } + } + // deuteron track quality + if (trackDeuteron.tpcNClsFound() < decay3bodyselections.minTPCNClDeuteron) { + decay3body = {}; + return false; + } + + // track eta + if (std::fabs(trackProton.eta()) > decay3bodyselections.maxEtaDaughters) { + decay3body = {}; + return false; + } + if (std::fabs(trackPion.eta()) > decay3bodyselections.maxEtaDaughters) { + decay3body = {}; + return false; + } + if (std::fabs(trackDeuteron.eta()) > decay3bodyselections.maxEtaDaughters) { + decay3body = {}; + return false; + } + + // TPC only + if (!acceptTPCOnly && (!trackProton.hasITS() || !trackPion.hasITS() || !trackDeuteron.hasITS())) { + decay3body = {}; + return false; + } + + // daughter TPC PID + if (std::fabs(trackProton.tpcNSigmaPr()) > decay3bodyselections.maxTPCnSigma) { + decay3body = {}; + return false; + } + if (useTPCforPion && std::fabs(trackPion.tpcNSigmaPi()) > decay3bodyselections.maxTPCnSigma) { + decay3body = {}; + return false; + } + if (std::fabs(trackDeuteron.tpcNSigmaDe()) > decay3bodyselections.maxTPCnSigma) { + decay3body = {}; + return false; + } + + // deuteron TOF PID + if ((tofNsigmaDeuteron < decay3bodyselections.minTOFnSigmaDeuteron || tofNsigmaDeuteron > decay3bodyselections.maxTOFnSigmaDeuteron) && trackDeuteron.p() > decay3bodyselections.minPDeuteronUseTOF) { + decay3body = {}; + return false; + } + } // end of selections + + //_______________________________________________________________________ + // daughter track DCA to PV associated with decay3body + o2::dataformats::VertexBase mPV; + o2::dataformats::DCA mDcaInfoCov; + auto trackParCovProtonCopy = trackParCovProton; + auto trackParCovPionCopy = trackParCovPion; + auto trackParCovDeuteronCopy = trackParCovDeuteron; + mPV.setPos({pvX, pvY, pvZ}); + mPV.setCov(collision.covXX(), collision.covXY(), collision.covYY(), collision.covXZ(), collision.covYZ(), collision.covZZ()); + + // proton track + o2::base::Propagator::Instance()->propagateToDCABxByBz(mPV, trackParCovProtonCopy, 2.f, fitter3body.getMatCorrType(), &mDcaInfoCov); + decay3body.trackDCAxyToPV[0] = mDcaInfoCov.getY(); + decay3body.trackDCAzToPV[0] = mDcaInfoCov.getZ(); + auto trackProtonDCAToPV = std::sqrt(decay3body.trackDCAxyToPV[0] * decay3body.trackDCAxyToPV[0] + decay3body.trackDCAzToPV[0] * decay3body.trackDCAzToPV[0]); + if (useSelections) { + if (trackProtonDCAToPV < decay3bodyselections.minDCAProtonToPV) { + decay3body = {}; + return false; + } + } + // pion track + o2::base::Propagator::Instance()->propagateToDCABxByBz(mPV, trackParCovPionCopy, 2.f, fitter3body.getMatCorrType(), &mDcaInfoCov); + decay3body.trackDCAxyToPV[1] = mDcaInfoCov.getY(); + decay3body.trackDCAzToPV[1] = mDcaInfoCov.getZ(); + auto trackPionDCAToPV = std::sqrt(decay3body.trackDCAxyToPV[1] * decay3body.trackDCAxyToPV[1] + decay3body.trackDCAzToPV[1] * decay3body.trackDCAzToPV[1]); + if (useSelections) { + if (trackPionDCAToPV < decay3bodyselections.minDCAPionToPV) { + decay3body = {}; + return false; + } + } + // deuteron track + o2::base::Propagator::Instance()->propagateToDCABxByBz(mPV, trackParCovDeuteronCopy, 2.f, fitter3body.getMatCorrType(), &mDcaInfoCov); + decay3body.trackDCAxyToPV[2] = mDcaInfoCov.getY(); + decay3body.trackDCAzToPV[2] = mDcaInfoCov.getZ(); + auto trackDeuteronDCAToPV = std::sqrt(decay3body.trackDCAxyToPV[2] * decay3body.trackDCAxyToPV[2] + decay3body.trackDCAzToPV[2] * decay3body.trackDCAzToPV[2]); + if (useSelections) { + if (trackDeuteronDCAToPV < decay3bodyselections.minDCADeuteronToPV) { + decay3body = {}; + return false; + } + } + + //_______________________________________________________________________ + // fit 3body vertex + if (!useKFParticle) { + fitVertexWithDCAFitter(trackProton, trackPion, trackDeuteron, calculateCovariance); + } else { + fitVertexWithKF(collision, trackProton, trackPion, trackDeuteron, kfSetTopologicalConstraint, calculateCovariance); + } + + //_______________________________________________________________________ + // get vertex information + // daughter pT + auto trackProtonPt = std::sqrt(decay3body.momProton[0] * decay3body.momProton[0] + decay3body.momProton[1] * decay3body.momProton[1]); + auto trackPionPt = std::sqrt(decay3body.momPion[0] * decay3body.momPion[0] + decay3body.momPion[1] * decay3body.momPion[1]); + auto trackDeuteronPt = std::sqrt(decay3body.momDeuteron[0] * decay3body.momDeuteron[0] + decay3body.momDeuteron[1] * decay3body.momDeuteron[1]); + + // DCA between daughters at SV + decay3body.daughterDCAatSV = std::hypot( + std::hypot(decay3body.posProton[0] - decay3body.posPion[0], + decay3body.posProton[1] - decay3body.posPion[1], + decay3body.posProton[2] - decay3body.posPion[2]), + std::hypot(decay3body.posProton[0] - decay3body.posDeuteron[0], + decay3body.posProton[1] - decay3body.posDeuteron[1], + decay3body.posProton[2] - decay3body.posDeuteron[2]), + std::hypot(decay3body.posPion[0] - decay3body.posProton[0], + decay3body.posPion[1] - decay3body.posProton[1], + decay3body.posPion[2] - decay3body.posProton[2])); + + // daughter DCA to SV + // proton daughter + decay3body.daughterDCAtoSV[0] = std::hypot( + decay3body.posProton[0] - decay3body.position[0], + decay3body.posProton[1] - decay3body.position[1], + decay3body.posProton[2] - decay3body.position[2]); + // pion daughter + decay3body.daughterDCAtoSV[1] = std::hypot( + decay3body.posPion[0] - decay3body.position[0], + decay3body.posPion[1] - decay3body.position[1], + decay3body.posPion[2] - decay3body.position[2]); + // deuteron daughter + decay3body.daughterDCAtoSV[2] = std::hypot( + decay3body.posDeuteron[0] - decay3body.position[0], + decay3body.posDeuteron[1] - decay3body.position[1], + decay3body.posDeuteron[2] - decay3body.position[2]); + + //_____________________________________________________ + // selections after vertex fit + if (useSelections) { + // daughter pT + // proton + if (trackProtonPt < decay3bodyselections.minPtProton || trackProtonPt > decay3bodyselections.maxPtProton) { + decay3body = {}; + return false; + } + // pion + if (trackPionPt < decay3bodyselections.minPtPion || trackPionPt > decay3bodyselections.maxPtPion) { + decay3body = {}; + return false; + } + // deuteron + if (trackDeuteronPt < decay3bodyselections.minPtDeuteron || trackDeuteronPt > decay3bodyselections.maxPtDeuteron) { + decay3body = {}; + return false; + } + + // daughter DCAs at SV + if (decay3body.daughterDCAatSV > decay3bodyselections.maxDCADauAtSV) { + decay3body = {}; + return false; + } + + // rapidity + float rapidity = RecoDecay::y(std::array{decay3body.momentum[0], decay3body.momentum[1], decay3body.momentum[2]}, o2::constants::physics::MassHyperTriton); + if (std::fabs(rapidity) > decay3bodyselections.maxRapidity) { + decay3body = {}; + return false; + } + + // pT + float pT = RecoDecay::pt(std::array{decay3body.momentum[0], decay3body.momentum[1], decay3body.momentum[2]}); + if (pT < decay3bodyselections.minPt || pT > decay3bodyselections.maxPt) { + decay3body = {}; + return false; + } + + // mass window + if (decay3body.mass < decay3bodyselections.minMass || decay3body.mass > decay3bodyselections.maxMass) { + decay3body = {}; + return false; + } + + // pointing angle + float cpa = RecoDecay::cpa(std::array{pvX, pvY, pvZ}, std::array{decay3body.position[0], decay3body.position[1], decay3body.position[2]}, std::array{decay3body.momentum[0], decay3body.momentum[1], decay3body.momentum[2]}); + if (cpa < decay3bodyselections.minCosPA) { + decay3body = {}; + return false; + } + + // vertex chi2 + if (decay3body.chi2 > decay3bodyselections.maxChi2) { + decay3body = {}; + return false; + } + + // ctau + float P = RecoDecay::sqrtSumOfSquares(decay3body.momentum[0], decay3body.momentum[1], decay3body.momentum[2]); + float ctau = std::sqrt(std::pow(decay3body.position[0] - pvX, 2) + std::pow(decay3body.position[1] - pvY, 2) + std::pow(decay3body.position[2] - pvZ, 2)) / (P + 1E-10) * o2::constants::physics::MassHyperTriton; + if (ctau < decay3bodyselections.minCtau || ctau > decay3bodyselections.maxCtau) { + decay3body = {}; + return false; + } + } + + //_______________________________________________________________________ + // SVertexer selections in case of event mixing + if (isEventMixing) { + applySVertexerCuts(collision, trackProton, trackPion, trackDeuteron, /*applyV0Cut = */ true); + } + + //_______________________________________________________________________ + // fill remaining candidate information + // daughter PID + decay3body.tpcNsigma[0] = trackProton.tpcNSigmaPr(); + decay3body.tpcNsigma[1] = trackPion.tpcNSigmaPi(); + decay3body.tpcNsigma[2] = trackDeuteron.tpcNSigmaDe(); + decay3body.tpcNsigma[3] = trackDeuteron.tpcNSigmaPi(); + // recalculated bachelor TOF PID + decay3body.tofNsigmaDeuteron = tofNsigmaDeuteron; + + // average ITS cluster size of daughter tracks + double averageClusterSizeProton(0), averageClusterSizePion(0), averageClusterSizeDeuteron(0); + int nClsProton(0), nClsPion(0), nClsDeuteron(0); + for (int i = 0; i < 7; i++) { + int clusterSizePr = trackProton.itsClsSizeInLayer(i); + int clusterSizePi = trackPion.itsClsSizeInLayer(i); + int clusterSizeDe = trackDeuteron.itsClsSizeInLayer(i); + averageClusterSizeProton += static_cast(clusterSizePr); + averageClusterSizePion += static_cast(clusterSizePi); + averageClusterSizeDeuteron += static_cast(clusterSizeDe); + if (clusterSizePr > 0) + nClsProton++; + if (clusterSizePi > 0) + nClsPion++; + if (clusterSizeDe > 0) + nClsDeuteron++; + } + averageClusterSizeProton = averageClusterSizeProton / static_cast(nClsProton); + averageClusterSizePion = averageClusterSizePion / static_cast(nClsPion); + averageClusterSizeDeuteron = averageClusterSizeDeuteron / static_cast(nClsDeuteron); + decay3body.averageITSClSize[0] = averageClusterSizeProton; + decay3body.averageITSClSize[1] = averageClusterSizePion; + decay3body.averageITSClSize[2] = averageClusterSizeDeuteron; + + // number of TPC clusters + decay3body.tpcNCl[0] = trackProton.tpcNClsFound(); + decay3body.tpcNCl[1] = trackPion.tpcNClsFound(); + decay3body.tpcNCl[2] = trackDeuteron.tpcNClsFound(); + + // PID for tracking of deuteron track + decay3body.pidForTrackingDeuteron = trackDeuteron.pidForTracking(); + + // tracked cluster size + decay3body.trackedClSize = trackedClSize; + + return true; + } + + //___________________________________________________________________________________ + // functionality to fit 3body vertex with KFParticle and fill vertex information + template + void fitVertexWithKF(TCollision const& collision, + TTrack const& trackProton, + TTrack const& trackPion, + TTrack const& trackDeuteron, + bool kfSetTopologicalConstraint = true, + bool calculateCovariance = true) + { + // get TrackParCov daughters + auto trackParCovProton = getTrackParCov(trackProton); + auto trackParCovPion = getTrackParCov(trackPion); + auto trackParCovDeuteron = getTrackParCov(trackDeuteron); + + // initialise KF primary vertex + KFVertex kfpVertex = createKFPVertexFromCollision(collision); + KFParticle kfpv(kfpVertex); + + // create KFParticle objects + KFParticle kfpProton, kfpPion, kfpDeuteron; + kfpProton = createKFParticleFromTrackParCov(trackParCovProton, trackProton.sign(), constants::physics::MassProton); + kfpPion = createKFParticleFromTrackParCov(trackParCovPion, trackPion.sign(), constants::physics::MassPionCharged); + kfpDeuteron = createKFParticleFromTrackParCov(trackParCovDeuteron, trackDeuteron.sign(), constants::physics::MassDeuteron); + + // construct V0 vertex + KFParticle KFV0; + int nDaughtersV0 = 2; + const KFParticle* DaughtersV0[2] = {&kfpProton, &kfpPion}; + KFV0.SetConstructMethod(2); + try { + KFV0.Construct(DaughtersV0, nDaughtersV0); + } catch (std::runtime_error& e) { + LOG(debug) << "Failed to create V0 vertex." << e.what(); + return; + } + + // construct vertex + KFParticle KFH3L; + int nDaughters3body = 3; + const KFParticle* Daughters3body[3] = {&kfpProton, &kfpPion, &kfpDeuteron}; + KFH3L.SetConstructMethod(2); + try { + KFH3L.Construct(Daughters3body, nDaughters3body); + } catch (std::runtime_error& e) { + LOG(debug) << "Failed to create Hyper triton 3-body vertex." << e.what(); + return; + } + + // topological constraint + if (kfSetTopologicalConstraint) { + KFH3L.SetProductionVertex(kfpv); + KFH3L.TransportToDecayVertex(); + } + + // get vertex position and momentum + decay3body.position[0] = KFH3L.GetX(); + decay3body.position[1] = KFH3L.GetY(); + decay3body.position[2] = KFH3L.GetZ(); + decay3body.momentum[0] = KFH3L.GetPx(); + decay3body.momentum[1] = KFH3L.GetPy(); + decay3body.momentum[2] = KFH3L.GetPz(); + + // get sign + decay3body.sign = KFH3L.GetQ() / std::abs(KFH3L.GetQ()); + + // transport all daughter tracks to hypertriton vertex + kfpProton.TransportToPoint(decay3body.position); + kfpPion.TransportToPoint(decay3body.position); + kfpDeuteron.TransportToPoint(decay3body.position); + + // daughter positions + decay3body.posProton[0] = kfpProton.GetX(); + decay3body.posProton[1] = kfpProton.GetY(); + decay3body.posProton[2] = kfpProton.GetZ(); + decay3body.posPion[0] = kfpPion.GetX(); + decay3body.posPion[1] = kfpPion.GetY(); + decay3body.posPion[2] = kfpPion.GetZ(); + decay3body.posDeuteron[0] = kfpDeuteron.GetX(); + decay3body.posDeuteron[1] = kfpDeuteron.GetY(); + decay3body.posDeuteron[2] = kfpDeuteron.GetZ(); + + // daughter momenta + decay3body.momProton[0] = kfpProton.GetPx(); + decay3body.momProton[1] = kfpProton.GetPy(); + decay3body.momProton[2] = kfpProton.GetPz(); + decay3body.momPion[0] = kfpPion.GetPx(); + decay3body.momPion[1] = kfpPion.GetPy(); + decay3body.momPion[2] = kfpPion.GetPz(); + decay3body.momDeuteron[0] = kfpDeuteron.GetPx(); + decay3body.momDeuteron[1] = kfpDeuteron.GetPy(); + decay3body.momDeuteron[2] = kfpDeuteron.GetPz(); + + // candidate mass + float mass, massErr; + KFH3L.GetMass(mass, massErr); + decay3body.mass = mass; + + // V0 mass + float massV0, massV0Err; + KFV0.GetMass(massV0, massV0Err); + decay3body.massV0 = massV0; + + // vertex chi2 + decay3body.chi2 = KFH3L.GetChi2() / KFH3L.GetNDF(); + + // caluclate covariance matrices + if (calculateCovariance) { + // candidate covariance matrix + std::array covKF; + for (int i = 0; i < 21; i++) { // get covariance matrix elements (lower triangle) + covKF[i] = KFH3L.GetCovariance(i); + decay3body.covariance[i] = covKF[i]; + } + // daughter track covariance matrices + for (int i = 0; i < 21; i++) { // get covariance matrix elements (lower triangle) + decay3body.covProton[i] = kfpProton.GetCovariance(i); + decay3body.covPion[i] = kfpPion.GetCovariance(i); + decay3body.covDeuteron[i] = kfpDeuteron.GetCovariance(i); + } + } + + return; + } + + //_______________________________________________________________________ + // functionality to fit 3body vertex with DCAFitter + template + void fitVertexWithDCAFitter(TTrack const& trackProton, + TTrack const& trackPion, + TTrack const& trackDeuteron, + bool calculateCovariance = true) + { + // get TrackParCov daughters + auto trackParCovProton = getTrackParCov(trackProton); + auto trackParCovPion = getTrackParCov(trackPion); + auto trackParCovDeuteron = getTrackParCov(trackDeuteron); + + // fit the vertex + int n3bodyVtx = fitter3body.process(trackParCovProton, trackParCovPion, trackParCovDeuteron); + if (n3bodyVtx == 0) { // discard this pair + return; + } + + // get vertex position + const auto& vtxXYZ = fitter3body.getPCACandidate(); + for (int i = 0; i < 3; i++) { + decay3body.position[i] = vtxXYZ[i]; + } + + // get daughter momenta + const auto& propagatedTrackProton = fitter3body.getTrack(0); + const auto& propagatedTrackPion = fitter3body.getTrack(1); + const auto& propagatedTrackDeuteron = fitter3body.getTrack(2); + propagatedTrackProton.getPxPyPzGlo(decay3body.momProton); + propagatedTrackPion.getPxPyPzGlo(decay3body.momPion); + propagatedTrackDeuteron.getPxPyPzGlo(decay3body.momDeuteron); + propagatedTrackProton.getXYZGlo(decay3body.posProton); + propagatedTrackPion.getXYZGlo(decay3body.posPion); + propagatedTrackDeuteron.getXYZGlo(decay3body.posDeuteron); + + // get daughter positions at vertex + + // calculate candidate momentum + decay3body.momentum[0] = decay3body.momProton[0] + decay3body.momPion[0] + decay3body.momDeuteron[0]; + decay3body.momentum[1] = decay3body.momProton[1] + decay3body.momPion[1] + decay3body.momDeuteron[1]; + decay3body.momentum[2] = decay3body.momProton[2] + decay3body.momPion[2] + decay3body.momDeuteron[2]; + + // candidate and V0 mass + decay3body.mass = RecoDecay::m( + std::array{std::array{decay3body.momProton[0], decay3body.momProton[1], decay3body.momProton[2]}, + std::array{decay3body.momPion[0], decay3body.momPion[1], decay3body.momPion[2]}, + std::array{decay3body.momDeuteron[0], decay3body.momDeuteron[1], decay3body.momDeuteron[2]}}, + std::array{o2::constants::physics::MassProton, o2::constants::physics::MassPionCharged, o2::constants::physics::MassDeuteron}); + decay3body.massV0 = RecoDecay::m( + std::array{std::array{decay3body.momProton[0], decay3body.momProton[1], decay3body.momProton[2]}, + std::array{decay3body.momPion[0], decay3body.momPion[1], decay3body.momPion[2]}}, + std::array{o2::constants::physics::MassProton, o2::constants::physics::MassPionCharged}); + + // vertex chi2 at PCA + decay3body.chi2 = fitter3body.getChi2AtPCACandidate(); + + // candidate sign + decay3body.sign = trackDeuteron.sign(); + + // caluclate covariance matrices + if (calculateCovariance) { + // candidate position covariance matrix + auto covVtxV = fitter3body.calcPCACovMatrix(0); + decay3body.covariance[0] = covVtxV(0, 0); + decay3body.covariance[1] = covVtxV(1, 0); + decay3body.covariance[2] = covVtxV(1, 1); + decay3body.covariance[3] = covVtxV(2, 0); + decay3body.covariance[4] = covVtxV(2, 1); + decay3body.covariance[5] = covVtxV(2, 2); + // daughter covariance matrices + std::array covTproton = {0.}; + std::array covTpion = {0.}; + std::array covTdeuteron = {0.}; + propagatedTrackProton.getCovXYZPxPyPzGlo(covTproton); + propagatedTrackPion.getCovXYZPxPyPzGlo(covTpion); + propagatedTrackDeuteron.getCovXYZPxPyPzGlo(covTdeuteron); + for (int i = 0; i < 21; i++) { + decay3body.covProton[i] = covTproton[i]; + decay3body.covPion[i] = covTpion[i]; + decay3body.covDeuteron[i] = covTdeuteron[i]; + } + // candidate momentum covairance matrix + constexpr int MomInd[6] = {9, 13, 14, 18, 19, 20}; // cov matrix elements for momentum component + for (int i = 0; i < 6; i++) { + decay3body.covariance[MomInd[i]] = covTproton[MomInd[i]] + covTpion[MomInd[i]] + covTdeuteron[MomInd[i]]; + } + /// WARNING: position-momentum covariances are not calculated in the DCAFitter - remain zero + } + + return; + } + + //_______________________________________________________________________ + // functionality to apply SVertexer cuts in case of event mixing + template + void applySVertexerCuts(TCollision const& collision, + TTrack const& trackProton, + TTrack const& trackPion, + TTrack const& trackDeuteron, + bool applyV0Cut = true) + { + // get TrackParCov daughters + auto trackParCovProton = getTrackParCov(trackProton); + auto trackParCovPion = getTrackParCov(trackPion); + auto trackParCovDeuteron = getTrackParCov(trackDeuteron); + + const float pidCutsLambda[o2::vertexing::SVertexHypothesis::NPIDParams] = {0., 20, 0., 5.0, 0.0, 1.09004e-03, 2.62291e-04, 8.93179e-03, 2.83121}; // Lambda + mV0Hyps.set(o2::track::PID::Lambda, o2::track::PID::Proton, o2::track::PID::Pion, pidCutsLambda, fitter3body.getBz()); + + int nV0 = fitterV0.process(trackParCovProton, trackParCovPion); + if (nV0 == 0) { + return; + } + + std::array v0pos = {0.}; + const auto& v0vtxXYZ = fitterV0.getPCACandidate(); + for (int i = 0; i < 3; i++) { + v0pos[i] = v0vtxXYZ[i]; + } + const int cand = 0; + if (!fitterV0.isPropagateTracksToVertexDone(cand) && !fitterV0.propagateTracksToVertex(cand)) { + return; + } + + const auto& trProtonProp = fitterV0.getTrack(0, cand); + const auto& trPionProp = fitterV0.getTrack(1, cand); + std::array pProtonV0{}, pPionV0{}; + trProtonProp.getPxPyPzGlo(pProtonV0); + trPionProp.getPxPyPzGlo(pPionV0); + std::array pV0 = {pProtonV0[0] + pPionV0[0], pProtonV0[1] + pPionV0[1], pProtonV0[2] + pPionV0[2]}; + // Cut for Virtual V0 + float dxv0 = v0pos[0] - mMeanVertex.getX(), dyv0 = v0pos[1] - mMeanVertex.getY(), r2v0 = dxv0 * dxv0 + dyv0 * dyv0; + float rv0 = std::sqrt(r2v0); + float pt2V0 = pV0[0] * pV0[0] + pV0[1] * pV0[1], prodXYv0 = dxv0 * pV0[0] + dyv0 * pV0[1], tDCAXY = prodXYv0 / pt2V0; + if (applyV0Cut && pt2V0 <= svertexerselections.minPt2V0) { + return; + } + if (applyV0Cut && pV0[2] * pV0[2] / pt2V0 > svertexerselections.maxTgl2V0) { // tgLambda cut + return; + } + + float p2V0 = pt2V0 + pV0[2] * pV0[2], ptV0 = std::sqrt(pt2V0); + // apply mass selections + float p2Proton = pProtonV0[0] * pProtonV0[0] + pProtonV0[1] * pProtonV0[1] + pProtonV0[2] * pProtonV0[2], p2Pion = pPionV0[0] * pPionV0[0] + pPionV0[1] * pPionV0[1] + pPionV0[2] * pPionV0[2]; + bool good3bodyV0Hyp = false; + float massForLambdaHyp = mV0Hyps.calcMass(p2Proton, p2Pion, p2V0); + if (massForLambdaHyp - mV0Hyps.getMassV0Hyp() < mV0Hyps.getMargin(ptV0)) { + good3bodyV0Hyp = true; + } + if (applyV0Cut && !good3bodyV0Hyp) { + return; + } + + float dcaX = dxv0 - pV0[0] * tDCAXY, dcaY = dyv0 - pV0[1] * tDCAXY, dca2 = dcaX * dcaX + dcaY * dcaY; + float cosPAXY = prodXYv0 / rv0 * ptV0; + if (applyV0Cut && dca2 > svertexerselections.maxDCAXY2ToMeanVertex3bodyV0) { + return; + } + // FIXME: V0 cosPA cut to be investigated + if (applyV0Cut && cosPAXY < svertexerselections.minCosPAXYMeanVertex3bodyV0) { + return; + } + // Check: CosPA Cut of Virtual V0 may not be used since the V0 may be based on another PV + float dx = v0pos[0] - collision.posX(); + float dy = v0pos[1] - collision.posY(); + float dz = v0pos[2] - collision.posZ(); + float prodXYZv0 = dx * pV0[0] + dy * pV0[1] + dz * pV0[2]; + float v0CosPA = prodXYZv0 / std::sqrt((dx * dx + dy * dy + dz * dz) * p2V0); + if (applyV0Cut && v0CosPA < svertexerselections.minCosPA3bodyV0) { + return; + } + + // 3body vertex + int n3bodyVtx = fitter3body.process(trackParCovProton, trackParCovPion, trackParCovDeuteron); + if (n3bodyVtx == 0) { // discard this pair + return; + } + const auto& vertexXYZ = fitter3body.getPCACandidatePos(); + std::array pos = {0.}; + for (int i = 0; i < 3; i++) { + pos[i] = vertexXYZ[i]; + } + + std::array pProton = {0.}, pPion = {0.}, pDeuteron{0.}; + const auto& propagatedTrackProton = fitter3body.getTrack(0); + const auto& propagatedTrackPion = fitter3body.getTrack(1); + const auto& propagatedTrackDeuteron = fitter3body.getTrack(2); + propagatedTrackProton.getPxPyPzGlo(pProton); + propagatedTrackPion.getPxPyPzGlo(pPion); + propagatedTrackDeuteron.getPxPyPzGlo(pDeuteron); + std::array p3B = {pProton[0] + pPion[0] + pDeuteron[0], pProton[1] + pPion[1] + pDeuteron[1], pProton[2] + pPion[2] + pDeuteron[2]}; + + float r3body = std::hypot(pos[0], pos[1]); + if (r3body < 0.5) { + return; + } + + // Cut for the compatibility of V0 and 3body vertex + float deltaR = std::abs(rv0 - r3body); + if (deltaR > svertexerselections.maxRDiffV03body) { + return; + } + + float pt3B = std::hypot(p3B[0], p3B[1]); + if (pt3B < svertexerselections.minPt3Body) { // pt cut + return; + } + if (p3B[2] / pt3B > svertexerselections.maxTgl3Body) { // tgLambda cut + return; + } + + // H3L DCA Check + auto track3B = o2::track::TrackParCov(vertexXYZ, p3B, trackDeuteron.sign()); + o2::dataformats::DCA dca; + if (!track3B.propagateToDCA({{collision.posX(), collision.posY(), collision.posZ()}, {collision.covXX(), collision.covXY(), collision.covYY(), collision.covXZ(), collision.covYZ(), collision.covZZ()}}, fitter3body.getBz(), &dca, 5.) || + std::abs(dca.getY()) > svertexerselections.maxDCAXY3Body || std::abs(dca.getZ()) > svertexerselections.maxDCAZ3Body) { + return; + } + + return; + } + + private: + // internal helper to calculate DCA (3D) of a straight line to a given PV analytically + float CalculateDCAStraightToPV(float X, float Y, float Z, float Px, float Py, float Pz, float pvX, float pvY, float pvZ) + { + return std::sqrt((std::pow((pvY - Y) * Pz - (pvZ - Z) * Py, 2) + std::pow((pvX - X) * Pz - (pvZ - Z) * Px, 2) + std::pow((pvX - X) * Py - (pvY - Y) * Px, 2)) / (Px * Px + Py * Py + Pz * Pz)); + } +}; + +} // namespace pwglf +} // namespace o2 + +#endif // PWGLF_UTILS_DECAY3BODYBUILDERHELPER_H_ From 55286a01dfcc160df461f4c9779872d5b5e0fb52 Mon Sep 17 00:00:00 2001 From: chengtt0406 <39661669+chengtt0406@users.noreply.github.com> Date: Thu, 12 Jun 2025 15:49:47 +0800 Subject: [PATCH 034/871] [PWGHF] Remove indexRexCharmBaryon=-1 case for MC rec matching (#11556) --- PWGHF/TableProducer/treeCreatorOmegacSt.cxx | 81 +++++++++++---------- 1 file changed, 43 insertions(+), 38 deletions(-) diff --git a/PWGHF/TableProducer/treeCreatorOmegacSt.cxx b/PWGHF/TableProducer/treeCreatorOmegacSt.cxx index 8d2780cd435..4d3c59cfcd1 100644 --- a/PWGHF/TableProducer/treeCreatorOmegacSt.cxx +++ b/PWGHF/TableProducer/treeCreatorOmegacSt.cxx @@ -15,39 +15,41 @@ /// \author Jochen Klein /// \author Tiantian Cheng -#include -#include -#include -#include +#include "PWGHF/Core/SelectorCuts.h" +#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "PWGHF/Utils/utilsTrkCandHf.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" -#include +#include "Common/Core/RecoDecay.h" +#include "Common/Core/TrackSelection.h" +#include "Common/Core/trackUtilities.h" +#include "Common/DataModel/CollisionAssociationTables.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "EventFiltering/Zorro.h" +#include "EventFiltering/ZorroSummary.h" #include "CCDB/BasicCCDBManager.h" #include "CommonConstants/PhysicsConstants.h" +#include "DCAFitter/DCAFitterN.h" #include "DataFormatsParameters/GRPMagField.h" #include "DataFormatsParameters/GRPObject.h" -#include "DCAFitter/DCAFitterN.h" #include "DetectorsBase/Propagator.h" -#include "EventFiltering/Zorro.h" -#include "EventFiltering/ZorroSummary.h" +#include "Framework/ASoA.h" #include "Framework/AnalysisDataModel.h" #include "Framework/AnalysisTask.h" -#include "Framework/ASoA.h" #include "Framework/HistogramRegistry.h" #include "Framework/O2DatabasePDGPlugin.h" #include "Framework/runDataProcessing.h" #include "ReconstructionDataFormats/DCA.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/Core/RecoDecay.h" -#include "Common/Core/trackUtilities.h" -#include "Common/DataModel/PIDResponse.h" -#include "Common/Core/TrackSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "Common/DataModel/CollisionAssociationTables.h" -#include "PWGLF/DataModel/LFStrangenessTables.h" -#include "PWGHF/Core/SelectorCuts.h" -#include "PWGHF/Utils/utilsTrkCandHf.h" -#include "PWGHF/DataModel/CandidateReconstructionTables.h" + +#include + +#include +#include +#include +#include using namespace o2; using namespace o2::framework; @@ -369,8 +371,7 @@ struct HfTreeCreatorOmegacSt { } else if (idxKaonDaughter >= 0 && idxCascDaughter >= 0) { decayChannel = o2::aod::hf_cand_casc_lf::DecayType2Prong::OmegaczeroToOmegaK; // OmegaC -> Omega + K } else { - decayChannel = -1; - LOG(warning) << "Decay channel not recognized!"; + decayChannel = -1; // LOG(warning) << "Decay channel not recognized!"; } if (decayChannel != -1) { int idxDaughter = (decayChannel == o2::aod::hf_cand_casc_lf::DecayType2Prong::OmegaczeroToOmegaPi) ? idxPionDaughter : idxKaonDaughter; @@ -662,32 +663,36 @@ struct HfTreeCreatorOmegacSt { // Match Omegac0 → Omega- + Pi+ indexRec = RecoDecay::getMatchedMCRec(mcParticles->get(), arrayDaughters, o2::constants::physics::kOmegaC0, std::array{+kPiPlus, +kKMinus, +kProton, +kPiMinus}, true, &sign, 3, &nPiToMuOmegac0, &nKaToPiOmegac0); + indexRecCharmBaryon = indexRec; + if (indexRec > -1) { + // Omega- → K pi p (Cascade match) + indexRec = RecoDecay::getMatchedMCRec(mcParticles->get(), arrayDaughtersCasc, +kOmegaMinus, std::array{+kKMinus, +kProton, +kPiMinus}, true, &signCasc, 2, &nPiToMuCasc, &nKaToPiCasc); + if (indexRec > -1) { + // Lambda → p pi (Lambda match) + indexRec = RecoDecay::getMatchedMCRec(mcParticles->get(), arrayDaughtersV0, +kLambda0, std::array{+kProton, +kPiMinus}, true, &signV0, 1, &nPiToMuV0); + if (indexRec > -1) { + isMatched = true; + } + } + } } else if (decayChannel == o2::aod::hf_cand_casc_lf::DecayType2Prong::OmegaczeroToOmegaK) { // Match Omegac0 → Omega- + K+ indexRec = RecoDecay::getMatchedMCRec(mcParticles->get(), arrayDaughters, o2::constants::physics::kOmegaC0, std::array{+kKPlus, +kKMinus, +kProton, +kPiMinus}, true, &sign, 3, &nPiToMuOmegac0, &nKaToPiOmegac0); - } - indexRecCharmBaryon = indexRec; - if (indexRec > -1) { - // Omega- → K pi p (Cascade match) - indexRec = RecoDecay::getMatchedMCRec(mcParticles->get(), arrayDaughtersCasc, +kOmegaMinus, std::array{+kKMinus, +kProton, +kPiMinus}, true, &signCasc, 2, &nPiToMuCasc, &nKaToPiCasc); + indexRecCharmBaryon = indexRec; if (indexRec > -1) { - // Lambda → p pi (Lambda match) - indexRec = RecoDecay::getMatchedMCRec(mcParticles->get(), arrayDaughtersV0, +kLambda0, std::array{+kProton, +kPiMinus}, true, &signV0, 1, &nPiToMuV0); - if (decayChannel == o2::aod::hf_cand_casc_lf::DecayType2Prong::OmegaczeroToOmegaPi) { - if (nPiToMuOmegac0 >= 1 && nKaToPiOmegac0 == 0) { - isMatched = true; - } else if (nPiToMuOmegac0 == 0 && nKaToPiOmegac0 == 0) { - isMatched = true; - } - } else if (decayChannel == o2::aod::hf_cand_casc_lf::DecayType2Prong::OmegaczeroToOmegaK) { - if (nPiToMuOmegac0 == 0 && nKaToPiOmegac0 == 0) { + // Omega- → K pi p (Cascade match) + indexRec = RecoDecay::getMatchedMCRec(mcParticles->get(), arrayDaughtersCasc, +kOmegaMinus, std::array{+kKMinus, +kProton, +kPiMinus}, true, &signCasc, 2, &nPiToMuCasc, &nKaToPiCasc); + if (indexRec > -1) { + // Lambda → p pi (Lambda match) + indexRec = RecoDecay::getMatchedMCRec(mcParticles->get(), arrayDaughtersV0, +kLambda0, std::array{+kProton, +kPiMinus}, true, &signV0, 1, &nPiToMuV0); + if (indexRec > -1) { isMatched = true; } } } } - if (isMatched) { + if (isMatched && indexRecCharmBaryon > -1) { auto particle = mcParticles->get().rawIteratorAt(indexRecCharmBaryon); origin = RecoDecay::getCharmHadronOrigin(mcParticles->get(), particle, false, &idxBhadMothers); } From eac108d1d9d614723c1d2682c168456a3a43b9e4 Mon Sep 17 00:00:00 2001 From: sashingo Date: Thu, 12 Jun 2025 16:50:27 +0900 Subject: [PATCH 035/871] [PWGHF] added some histograms for EMCal (#11554) --- PWGHF/HFL/Tasks/taskElectronWeakBoson.cxx | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/PWGHF/HFL/Tasks/taskElectronWeakBoson.cxx b/PWGHF/HFL/Tasks/taskElectronWeakBoson.cxx index be71ab35a01..72ff0ccdf8d 100644 --- a/PWGHF/HFL/Tasks/taskElectronWeakBoson.cxx +++ b/PWGHF/HFL/Tasks/taskElectronWeakBoson.cxx @@ -160,6 +160,8 @@ struct HfTaskElectronWeakBoson { const AxisSpec axisM02{100, 0, 1, "M02"}; 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"}; + const AxisSpec axisNcell{50, 0.0, 50.0, "Ncell"}; const AxisSpec axisPhi{350, 0, 7, "Phi"}; const AxisSpec axisEop{200, 0, 2, "Eop"}; const AxisSpec axisChi2{250, 0.0, 25.0, "#chi^{2}"}; @@ -184,7 +186,8 @@ struct HfTaskElectronWeakBoson { registry.add("hPt", "track pt", kTH1F, {axisPt}); registry.add("hTPCNsigma", "TPC electron Nsigma", kTH2F, {{axisPt}, {axisNsigma}}); registry.add("hEnergy", "EMC cluster energy", kTH1F, {axisE}); - registry.add("hTrMatch", "Track EMC Match", kTH2F, {{axisdPhi}, {axisdEta}}); + registry.add("hEnergyNcell", "EMC cluster energy and cell", kTH2F, {{axisE}, {axisNcell}}); + registry.add("hTrMatchR", "Track EMC Match in radius", kTH2F, {{axisPt}, {axisdR}}); registry.add("hTrMatch_mim", "Track EMC Match minimu minimumm", kTH2F, {{axisdPhi}, {axisdEta}}); registry.add("hMatchPhi", "Match in Phi", kTH2F, {{axisPhi}, {axisPhi}}); registry.add("hMatchEta", "Match in Eta", kTH2F, {{axisEta}, {axisEta}}); @@ -198,6 +201,7 @@ struct HfTaskElectronWeakBoson { registry.add("hInvMassZeeLs", "invariant mass for Z LS pair", kTH2F, {{axisPt}, {axisInvMassZ}}); registry.add("hInvMassZeeUls", "invariant mass for Z ULS pair", kTH2F, {{axisPt}, {axisInvMassZ}}); registry.add("hTHnElectrons", "electron info", HistType::kTHnSparseF, {axisPt, axisNsigma, axisM02, axisEop, axisIsoEnergy, axisIsoTrack}); + registry.add("hTHnTrMatch", "Track EMC Match", HistType::kTHnSparseF, {axisPt, axisdPhi, axisdEta}); // hisotgram for EMCal trigger registry.add("hEMCalTrigger", "EMCal trigger", kTH1F, {axisTrigger}); @@ -298,7 +302,7 @@ struct HfTaskElectronWeakBoson { registry.fill(HIST("hEMCalTrigger"), isTriggered ? 1 : 0); // Skip event if not triggered and we're processing skimmed data - if (!isTriggered && cfgSkimmedProcessing) { + if (!isTriggered) { return; } } @@ -397,13 +401,16 @@ struct HfTaskElectronWeakBoson { dPhiMin = dPhi; dEtaMin = dEta; } - registry.fill(HIST("hTrMatch"), dPhi, dEta); + registry.fill(HIST("hTHnTrMatch"), match.track_as().pt(), dPhi, dEta); registry.fill(HIST("hEMCtime"), timeEmc); registry.fill(HIST("hEnergy"), energyEmc); - if (r > rMatchMax) + if (std::abs(dPhi) > rMatchMax || std::abs(dEta) > rMatchMax) continue; + registry.fill(HIST("hTrMatchR"), match.track_as().pt(), r); + registry.fill(HIST("hEnergyNcell"), energyEmc, match.emcalcluster_as().nCells()); + const auto& cluster = match.emcalcluster_as(); double eop = energyEmc / match.track_as().p(); From 3ae243858aa626fa27c2c299edc9fe575834ab5a Mon Sep 17 00:00:00 2001 From: Francesco Mazzaschi <43742195+fmazzasc@users.noreply.github.com> Date: Thu, 12 Jun 2025 10:31:21 +0200 Subject: [PATCH 036/871] Add number of PV contributors (#11558) Co-authored-by: Francesco Mazzaschi --- PWGLF/DataModel/LFSlimNucleiTables.h | 8 ++- PWGLF/TableProducer/Nuspex/nucleiFlowTree.cxx | 6 +-- PWGLF/TableProducer/Nuspex/nucleiSpectra.cxx | 54 +++++++++---------- PWGLF/TableProducer/Nuspex/nucleiUtils.h | 1 + 4 files changed, 35 insertions(+), 34 deletions(-) diff --git a/PWGLF/DataModel/LFSlimNucleiTables.h b/PWGLF/DataModel/LFSlimNucleiTables.h index e562c35ddc6..e1c0e0eb364 100644 --- a/PWGLF/DataModel/LFSlimNucleiTables.h +++ b/PWGLF/DataModel/LFSlimNucleiTables.h @@ -14,10 +14,11 @@ /// \brief Slim nuclei tables /// -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.h" #include "Common/DataModel/Centrality.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" + #ifndef PWGLF_DATAMODEL_LFSLIMNUCLEITABLES_H_ #define PWGLF_DATAMODEL_LFSLIMNUCLEITABLES_H_ @@ -31,6 +32,7 @@ DECLARE_SOA_COLUMN(Phi, phi, float); DECLARE_SOA_COLUMN(TPCInnerParam, tpcInnerParam, float); DECLARE_SOA_COLUMN(Beta, beta, float); DECLARE_SOA_COLUMN(Zvertex, zVertex, float); +DECLARE_SOA_COLUMN(NContrib, nContrib, int); DECLARE_SOA_COLUMN(DCAxy, dcaxy, float); DECLARE_SOA_COLUMN(DCAz, dcaz, float); DECLARE_SOA_COLUMN(TPCsignal, tpcSignal, float); @@ -102,6 +104,7 @@ DECLARE_SOA_TABLE(NucleiTable, "AOD", "NUCLEITABLE", NucleiTableNS::TPCInnerParam, NucleiTableNS::Beta, NucleiTableNS::Zvertex, + NucleiTableNS::NContrib, NucleiTableNS::DCAxy, NucleiTableNS::DCAz, NucleiTableNS::TPCsignal, @@ -139,6 +142,7 @@ DECLARE_SOA_TABLE(NucleiTableMC, "AOD", "NUCLEITABLEMC", NucleiTableNS::TPCInnerParam, NucleiTableNS::Beta, NucleiTableNS::Zvertex, + NucleiTableNS::NContrib, NucleiTableNS::DCAxy, NucleiTableNS::DCAz, NucleiTableNS::TPCsignal, diff --git a/PWGLF/TableProducer/Nuspex/nucleiFlowTree.cxx b/PWGLF/TableProducer/Nuspex/nucleiFlowTree.cxx index 68c9b7ac91d..6c15c2a626c 100644 --- a/PWGLF/TableProducer/Nuspex/nucleiFlowTree.cxx +++ b/PWGLF/TableProducer/Nuspex/nucleiFlowTree.cxx @@ -440,7 +440,7 @@ struct nucleiFlowTree { } 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(), dcaInfo[0], dcaInfo[1], track.tpcSignal(), track.itsChi2NCl(), track.tpcChi2NCl(), track.tofChi2(), + 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())}); } @@ -456,7 +456,7 @@ struct nucleiFlowTree { } fillDataInfo(collision, tracks); for (auto& c : nuclei::candidates) { - nucleiTable(c.pt, c.eta, c.phi, c.tpcInnerParam, c.beta, c.zVertex, 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); + nucleiTable(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); } for (auto& c : nuclei::candidates_flow) { nucleiTableFlow(c.centFV0A, c.centFT0M, c.centFT0A, c.centFT0C, c.psiFT0A, c.psiFT0C, c.psiTPC, c.psiTPCl, c.psiTPCr, c.qFT0A, c.qFT0C, c.qTPC, c.qTPCl, c.qTPCr); @@ -473,7 +473,7 @@ struct nucleiFlowTree { } fillDataInfo(collision, tracks); for (auto& c : nuclei::candidates) { - nucleiTable(c.pt, c.eta, c.phi, c.tpcInnerParam, c.beta, c.zVertex, 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); + nucleiTable(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); } for (auto& c : nuclei::candidates_flow) { nucleiTableFlow(c.centFV0A, c.centFT0M, c.centFT0A, c.centFT0C, c.psiFT0A, c.psiFT0C, c.psiTPC, c.psiTPCl, c.psiTPCr, c.qFT0A, c.qFT0C, c.qTPC, c.qTPCl, c.qTPCr); diff --git a/PWGLF/TableProducer/Nuspex/nucleiSpectra.cxx b/PWGLF/TableProducer/Nuspex/nucleiSpectra.cxx index 205c0eda0a4..22945965595 100644 --- a/PWGLF/TableProducer/Nuspex/nucleiSpectra.cxx +++ b/PWGLF/TableProducer/Nuspex/nucleiSpectra.cxx @@ -19,52 +19,47 @@ // o2-analysis-pid-tof-base, o2-analysis-multiplicity-table, o2-analysis-event-selection // (to add flow: o2-analysis-qvector-table, o2-analysis-centrality-table) -#include -#include -#include -#include -#include - -#include "Math/Vector4D.h" - -#include "CCDB/BasicCCDBManager.h" +#include "PWGLF/DataModel/EPCalibrationTables.h" +#include "PWGLF/DataModel/LFSlimNucleiTables.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/trackUtilities.h" #include "Common/DataModel/Centrality.h" -#include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/PIDResponse.h" #include "Common/DataModel/PIDResponseITS.h" +#include "Common/DataModel/Qvectors.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "Common/Core/PID/PIDTOF.h" #include "Common/TableProducer/PID/pidTOFBase.h" -#include "Common/Core/EventPlaneHelper.h" -#include "Common/DataModel/Qvectors.h" -#include "Common/Core/RecoDecay.h" +#include "EventFiltering/Zorro.h" +#include "EventFiltering/ZorroSummary.h" +#include "CCDB/BasicCCDBManager.h" #include "DataFormatsParameters/GRPMagField.h" #include "DataFormatsParameters/GRPObject.h" #include "DataFormatsTPC/BetheBlochAleph.h" #include "DetectorsBase/GeometryManager.h" #include "DetectorsBase/Propagator.h" - -#include "EventFiltering/Zorro.h" -#include "EventFiltering/ZorroSummary.h" - +#include "Framework/ASoAHelpers.h" #include "Framework/AnalysisDataModel.h" #include "Framework/AnalysisTask.h" -#include "Framework/ASoAHelpers.h" #include "Framework/HistogramRegistry.h" #include "Framework/runDataProcessing.h" - #include "ReconstructionDataFormats/Track.h" -#include "PWGLF/DataModel/EPCalibrationTables.h" -#include "PWGLF/DataModel/LFSlimNucleiTables.h" - +#include "Math/Vector4D.h" #include "TRandom3.h" +#include +#include +#include +#include +#include + using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; @@ -79,6 +74,7 @@ struct NucleusCandidate { float tpcInnerParam; float beta; float zVertex; + int nContrib; float DCAxy; float DCAz; float TPCsignal; @@ -793,7 +789,7 @@ struct nucleiSpectra { } 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(), dcaInfo[0], dcaInfo[1], track.tpcSignal(), track.itsChi2NCl(), track.tpcChi2NCl(), track.tofChi2(), + 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())}); } @@ -814,7 +810,7 @@ struct nucleiSpectra { 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.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); + 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 (cfgFillPairTree) { for (size_t i2{i1 + 1}; i2 < nuclei::candidates.size(); ++i2) { auto& c2 = nuclei::candidates[i2]; @@ -849,7 +845,7 @@ struct nucleiSpectra { fillDataInfo(collision, tracks); for (auto& c : nuclei::candidates) { if (c.fillTree) { - nucleiTable(c.pt, c.eta, c.phi, c.tpcInnerParam, c.beta, c.zVertex, 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); + nucleiTable(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); } if (c.fillDCAHist) { for (int iS{0}; iS < nuclei::species; ++iS) { @@ -878,7 +874,7 @@ struct nucleiSpectra { fillDataInfo(collision, tracks); for (auto& c : nuclei::candidates) { if (c.fillTree) { - nucleiTable(c.pt, c.eta, c.phi, c.tpcInnerParam, c.beta, c.zVertex, 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); + nucleiTable(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); } if (c.fillDCAHist) { for (int iS{0}; iS < nuclei::species; ++iS) { @@ -971,7 +967,7 @@ struct nucleiSpectra { isReconstructed[particle.globalIndex()] = true; float absoDecL = computeAbsoDecL(particle); - nucleiTableMC(c.pt, c.eta, c.phi, c.tpcInnerParam, c.beta, c.zVertex, 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); + nucleiTableMC(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); } int index{0}; @@ -1014,7 +1010,7 @@ struct nucleiSpectra { if (!isReconstructed[index] && (cfgTreeConfig->get(iS, 0u) || cfgTreeConfig->get(iS, 1u))) { float absDecL = computeAbsoDecL(particle); - nucleiTableMC(999., 999., 999., 0., 0., 999., 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); + nucleiTableMC(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); } break; } diff --git a/PWGLF/TableProducer/Nuspex/nucleiUtils.h b/PWGLF/TableProducer/Nuspex/nucleiUtils.h index 2a9a64bc4b2..29cd489768d 100644 --- a/PWGLF/TableProducer/Nuspex/nucleiUtils.h +++ b/PWGLF/TableProducer/Nuspex/nucleiUtils.h @@ -29,6 +29,7 @@ struct NucleusCandidate { float tpcInnerParam; float beta; float zVertex; + int nContrib; float DCAxy; float DCAz; float TPCsignal; From c0df1a2d7d19e74bb5a1cf2cb2f15df8509a4af7 Mon Sep 17 00:00:00 2001 From: aimeric-landou <46970521+aimeric-landou@users.noreply.github.com> Date: Thu, 12 Jun 2025 11:23:57 +0200 Subject: [PATCH 037/871] [PWGJE] trackEfficiency: use true track weight for numerator for fake tracks (#11493) --- PWGJE/Tasks/trackEfficiency.cxx | 86 ++++++++++++++++++++++----------- 1 file changed, 57 insertions(+), 29 deletions(-) diff --git a/PWGJE/Tasks/trackEfficiency.cxx b/PWGJE/Tasks/trackEfficiency.cxx index a591c32f958..87e37014ae7 100644 --- a/PWGJE/Tasks/trackEfficiency.cxx +++ b/PWGJE/Tasks/trackEfficiency.cxx @@ -82,6 +82,9 @@ struct TrackEfficiency { Configurable ptHatMin{"ptHatMin", 5, "min pT hat of collisions"}; Configurable ptHatMax{"ptHatMax", 300, "max pT hat of collisions"}; Configurable pTHatExponent{"pTHatExponent", 6.0, "exponent of the event weight for the calculation of pTHat"}; + Configurable pTHatMaxFractionMCD{"pTHatMaxFractionMCD", 999.0, "maximum fraction of hard scattering for reconstructed track acceptance in MC"}; + + Configurable useTrueTrackWeight{"useTrueTrackWeight", 1, "test configurable, to be removed"}; std::vector eventSelectionBits; int trackSelection = -1; @@ -110,6 +113,13 @@ struct TrackEfficiency { if (!(jetderiveddatautilities::selectTrack(track, trackSelection) && jetderiveddatautilities::selectTrackDcaZ(track, trackDcaZmax))) { continue; } + + float simPtRef = 10.; + float pTHat = simPtRef / (std::pow(weight, 1.0 / pTHatExponent)); + if (track.pt() > pTHatMaxFractionMCD * pTHat) { + continue; + } + registry.fill(HIST("h2_centrality_track_pt"), collision.centrality(), track.pt(), weight); registry.fill(HIST("h2_centrality_track_eta"), collision.centrality(), track.eta(), weight); registry.fill(HIST("h2_centrality_track_phi"), collision.centrality(), track.phi(), weight); @@ -164,8 +174,16 @@ struct TrackEfficiency { registry.get(HIST("hTrackCutsCounts"))->GetXaxis()->SetBinLabel(1, "allTracksInSelColl"); registry.get(HIST("hTrackCutsCounts"))->GetXaxis()->SetBinLabel(2, "trackSel"); registry.get(HIST("hTrackCutsCounts"))->GetXaxis()->SetBinLabel(3, "hasMcParticle"); - registry.get(HIST("hTrackCutsCounts"))->GetXaxis()->SetBinLabel(4, "mcPartIsPrimary"); - registry.get(HIST("hTrackCutsCounts"))->GetXaxis()->SetBinLabel(5, "etaAcc"); // not actually applied here but it will give an idea of what will be done in the post processing + + if (doprocessEFficiencyPurity) { + registry.get(HIST("hTrackCutsCounts"))->GetXaxis()->SetBinLabel(4, "mcPartIsPrimary"); + registry.get(HIST("hTrackCutsCounts"))->GetXaxis()->SetBinLabel(5, "etaAcc"); // not actually applied here but it will give an idea of what will be done in the post processing + } + if (doprocessEFficiencyPurityWeighted) { + registry.get(HIST("hTrackCutsCounts"))->GetXaxis()->SetBinLabel(4, "ptHatMaxFraction"); + registry.get(HIST("hTrackCutsCounts"))->GetXaxis()->SetBinLabel(5, "mcPartIsPrimary"); + registry.get(HIST("hTrackCutsCounts"))->GetXaxis()->SetBinLabel(6, "etaAcc"); // not actually applied here but it will give an idea of what will be done in the post processing + } AxisSpec ptAxisEff = {nBinsLowPt, 0., 10., "#it{p}_{T} (GeV/#it{c})"}; AxisSpec ptAxisHighEff = {18, 10., 100., "#it{p}_{T} (GeV/#it{c})"}; @@ -478,8 +496,9 @@ struct TrackEfficiency { } registry.fill(HIST("hMcCollCutsCounts"), 5.5); // at least one of the reconstructed collisions associated with this mcCollision is selected with regard to centrality - float eventWeight = mcCollision.weight(); - float pTHat = 10. / (std::pow(eventWeight, 1.0 / pTHatExponent)); + float simPtRef = 10.; + float mcCollEventWeight = mcCollision.weight(); + float pTHat = simPtRef / (std::pow(mcCollEventWeight, 1.0 / pTHatExponent)); if (pTHat < ptHatMin || pTHat > ptHatMax) { // only allows mcCollisions with weight in between min and max return; } @@ -493,16 +512,16 @@ struct TrackEfficiency { } registry.fill(HIST("hMcPartCutsCounts"), 1.5); // isCharged - registry.fill(HIST("h3_particle_pt_particle_eta_particle_phi_mcpart_nonprimary"), jMcParticle.pt(), jMcParticle.eta(), jMcParticle.phi(), eventWeight); + registry.fill(HIST("h3_particle_pt_particle_eta_particle_phi_mcpart_nonprimary"), jMcParticle.pt(), jMcParticle.eta(), jMcParticle.phi(), mcCollEventWeight); if (checkPrimaryPart && !jMcParticle.isPhysicalPrimary()) { // global tracks should be mostly primaries continue; } registry.fill(HIST("hMcPartCutsCounts"), 2.5); // isPrimary - registry.fill(HIST("h3_particle_pt_particle_eta_particle_phi_mcpartofinterest"), jMcParticle.pt(), jMcParticle.eta(), jMcParticle.phi(), eventWeight); + registry.fill(HIST("h3_particle_pt_particle_eta_particle_phi_mcpartofinterest"), jMcParticle.pt(), jMcParticle.eta(), jMcParticle.phi(), mcCollEventWeight); - registry.fill(HIST("h3_particle_pt_high_particle_eta_particle_phi_mcpartofinterest"), jMcParticle.pt(), jMcParticle.eta(), jMcParticle.phi(), eventWeight); + registry.fill(HIST("h3_particle_pt_high_particle_eta_particle_phi_mcpartofinterest"), jMcParticle.pt(), jMcParticle.eta(), jMcParticle.phi(), mcCollEventWeight); if ((std::abs(jMcParticle.eta()) < trackEtaAcceptanceCountQA)) { // removed from actual cuts for now because all the histograms have an eta axis registry.fill(HIST("hMcPartCutsCounts"), 3.5); // etaAccept // not actually applied here but it will give an idea of what will be done in the post processing @@ -532,27 +551,36 @@ struct TrackEfficiency { registry.fill(HIST("hTrackCutsCounts"), 1.5); if (!track.has_mcParticle()) { - registry.fill(HIST("h3_track_pt_track_eta_track_phi_nonassociatedtrack"), track.pt(), track.eta(), track.phi(), eventWeight); + registry.fill(HIST("h3_track_pt_track_eta_track_phi_nonassociatedtrack"), track.pt(), track.eta(), track.phi(), mcCollEventWeight); // weight attribution here not trivial; I use the one of the current mcCollision, but track belongs to no collision; what should be its weight? could be a moot point but algo has complained about invalid index for mcParticle if I put th etrueTrackCollEventWeight before this cut - registry.fill(HIST("h3_track_pt_high_track_eta_track_phi_nonassociatedtrack"), track.pt(), track.eta(), track.phi(), eventWeight); + registry.fill(HIST("h3_track_pt_high_track_eta_track_phi_nonassociatedtrack"), track.pt(), track.eta(), track.phi(), mcCollEventWeight); continue; } registry.fill(HIST("hTrackCutsCounts"), 2.5); + if (track.pt() > pTHatMaxFractionMCD * pTHat) { + continue; + } + registry.fill(HIST("hTrackCutsCounts"), 3.5); + + auto mcParticle = track.mcParticle_as(); + auto trueTrackMcCollision = mcParticle.mcCollision_as(); + float trueTrackCollEventWeight = useTrueTrackWeight ? trueTrackMcCollision.weight() : mcCollEventWeight; // test1 + auto jMcParticleFromTrack = track.mcParticle_as(); if (!jMcParticleFromTrack.isPhysicalPrimary()) { - registry.fill(HIST("h3_track_pt_track_eta_track_phi_associatedtrack_nonprimary"), track.pt(), track.eta(), track.phi(), eventWeight); - registry.fill(HIST("h3_particle_pt_particle_eta_particle_phi_associatedtrack_nonprimary"), jMcParticleFromTrack.pt(), jMcParticleFromTrack.eta(), jMcParticleFromTrack.phi(), eventWeight); + registry.fill(HIST("h3_track_pt_track_eta_track_phi_associatedtrack_nonprimary"), track.pt(), track.eta(), track.phi(), trueTrackCollEventWeight); + registry.fill(HIST("h3_particle_pt_particle_eta_particle_phi_associatedtrack_nonprimary"), jMcParticleFromTrack.pt(), jMcParticleFromTrack.eta(), jMcParticleFromTrack.phi(), trueTrackCollEventWeight); - registry.fill(HIST("h3_track_pt_high_track_eta_track_phi_associatedtrack_nonprimary"), track.pt(), track.eta(), track.phi(), eventWeight); - registry.fill(HIST("h3_particle_pt_high_particle_eta_particle_phi_associatedtrack_nonprimary"), jMcParticleFromTrack.pt(), jMcParticleFromTrack.eta(), jMcParticleFromTrack.phi(), eventWeight); + registry.fill(HIST("h3_track_pt_high_track_eta_track_phi_associatedtrack_nonprimary"), track.pt(), track.eta(), track.phi(), trueTrackCollEventWeight); + registry.fill(HIST("h3_particle_pt_high_particle_eta_particle_phi_associatedtrack_nonprimary"), jMcParticleFromTrack.pt(), jMcParticleFromTrack.eta(), jMcParticleFromTrack.phi(), trueTrackCollEventWeight); if (std::find(seenMcParticlesVector.begin(), seenMcParticlesVector.end(), jMcParticleFromTrack.globalIndex()) != seenMcParticlesVector.end()) { - registry.fill(HIST("h3_track_pt_track_eta_track_phi_associatedtrack_split_nonprimary"), track.pt(), track.eta(), track.phi(), eventWeight); - registry.fill(HIST("h3_particle_pt_particle_eta_particle_phi_associatedtrack_split_nonprimary"), jMcParticleFromTrack.pt(), jMcParticleFromTrack.eta(), jMcParticleFromTrack.phi(), eventWeight); + registry.fill(HIST("h3_track_pt_track_eta_track_phi_associatedtrack_split_nonprimary"), track.pt(), track.eta(), track.phi(), trueTrackCollEventWeight); + registry.fill(HIST("h3_particle_pt_particle_eta_particle_phi_associatedtrack_split_nonprimary"), jMcParticleFromTrack.pt(), jMcParticleFromTrack.eta(), jMcParticleFromTrack.phi(), trueTrackCollEventWeight); - registry.fill(HIST("h3_track_pt_high_track_eta_track_phi_associatedtrack_split_nonprimary"), track.pt(), track.eta(), track.phi(), eventWeight); - registry.fill(HIST("h3_particle_pt_high_particle_eta_particle_phi_associatedtrack_split_nonprimary"), jMcParticleFromTrack.pt(), jMcParticleFromTrack.eta(), jMcParticleFromTrack.phi(), eventWeight); + registry.fill(HIST("h3_track_pt_high_track_eta_track_phi_associatedtrack_split_nonprimary"), track.pt(), track.eta(), track.phi(), trueTrackCollEventWeight); + registry.fill(HIST("h3_particle_pt_high_particle_eta_particle_phi_associatedtrack_split_nonprimary"), jMcParticleFromTrack.pt(), jMcParticleFromTrack.eta(), jMcParticleFromTrack.phi(), trueTrackCollEventWeight); } else { seenMcParticlesVector.push_back(jMcParticleFromTrack.globalIndex()); } @@ -560,28 +588,28 @@ struct TrackEfficiency { continue; } - registry.fill(HIST("hTrackCutsCounts"), 3.5); + registry.fill(HIST("hTrackCutsCounts"), 4.5); - registry.fill(HIST("h3_track_pt_track_eta_track_phi_associatedtrack_primary"), track.pt(), track.eta(), track.phi(), eventWeight); - registry.fill(HIST("h3_particle_pt_particle_eta_particle_phi_associatedtrack_primary"), jMcParticleFromTrack.pt(), jMcParticleFromTrack.eta(), jMcParticleFromTrack.phi(), eventWeight); - registry.fill(HIST("h2_particle_pt_track_pt_residual_associatedtrack_primary"), jMcParticleFromTrack.pt(), (jMcParticleFromTrack.pt() - track.pt()) / jMcParticleFromTrack.pt(), eventWeight); + registry.fill(HIST("h3_track_pt_track_eta_track_phi_associatedtrack_primary"), track.pt(), track.eta(), track.phi(), trueTrackCollEventWeight); + registry.fill(HIST("h3_particle_pt_particle_eta_particle_phi_associatedtrack_primary"), jMcParticleFromTrack.pt(), jMcParticleFromTrack.eta(), jMcParticleFromTrack.phi(), trueTrackCollEventWeight); + registry.fill(HIST("h2_particle_pt_track_pt_residual_associatedtrack_primary"), jMcParticleFromTrack.pt(), (jMcParticleFromTrack.pt() - track.pt()) / jMcParticleFromTrack.pt(), trueTrackCollEventWeight); - registry.fill(HIST("h3_track_pt_high_track_eta_track_phi_associatedtrack_primary"), track.pt(), track.eta(), track.phi(), eventWeight); - registry.fill(HIST("h3_particle_pt_high_particle_eta_particle_phi_associatedtrack_primary"), jMcParticleFromTrack.pt(), jMcParticleFromTrack.eta(), jMcParticleFromTrack.phi(), eventWeight); - registry.fill(HIST("h2_particle_pt_high_track_pt_high_residual_associatedtrack_primary"), jMcParticleFromTrack.pt(), (jMcParticleFromTrack.pt() - track.pt()) / jMcParticleFromTrack.pt(), eventWeight); + registry.fill(HIST("h3_track_pt_high_track_eta_track_phi_associatedtrack_primary"), track.pt(), track.eta(), track.phi(), trueTrackCollEventWeight); + registry.fill(HIST("h3_particle_pt_high_particle_eta_particle_phi_associatedtrack_primary"), jMcParticleFromTrack.pt(), jMcParticleFromTrack.eta(), jMcParticleFromTrack.phi(), trueTrackCollEventWeight); + registry.fill(HIST("h2_particle_pt_high_track_pt_high_residual_associatedtrack_primary"), jMcParticleFromTrack.pt(), (jMcParticleFromTrack.pt() - track.pt()) / jMcParticleFromTrack.pt(), trueTrackCollEventWeight); if (std::find(seenMcParticlesVector.begin(), seenMcParticlesVector.end(), jMcParticleFromTrack.globalIndex()) != seenMcParticlesVector.end()) { - registry.fill(HIST("h3_track_pt_track_eta_track_phi_associatedtrack_split_primary"), track.pt(), track.eta(), track.phi(), eventWeight); - registry.fill(HIST("h3_particle_pt_particle_eta_particle_phi_associatedtrack_split_primary"), jMcParticleFromTrack.pt(), jMcParticleFromTrack.eta(), jMcParticleFromTrack.phi(), eventWeight); + registry.fill(HIST("h3_track_pt_track_eta_track_phi_associatedtrack_split_primary"), track.pt(), track.eta(), track.phi(), trueTrackCollEventWeight); + registry.fill(HIST("h3_particle_pt_particle_eta_particle_phi_associatedtrack_split_primary"), jMcParticleFromTrack.pt(), jMcParticleFromTrack.eta(), jMcParticleFromTrack.phi(), trueTrackCollEventWeight); - registry.fill(HIST("h3_track_pt_high_track_eta_track_phi_associatedtrack_split_primary"), track.pt(), track.eta(), track.phi(), eventWeight); - registry.fill(HIST("h3_particle_pt_high_particle_eta_particle_phi_associatedtrack_split_primary"), jMcParticleFromTrack.pt(), jMcParticleFromTrack.eta(), jMcParticleFromTrack.phi(), eventWeight); + registry.fill(HIST("h3_track_pt_high_track_eta_track_phi_associatedtrack_split_primary"), track.pt(), track.eta(), track.phi(), trueTrackCollEventWeight); + registry.fill(HIST("h3_particle_pt_high_particle_eta_particle_phi_associatedtrack_split_primary"), jMcParticleFromTrack.pt(), jMcParticleFromTrack.eta(), jMcParticleFromTrack.phi(), trueTrackCollEventWeight); } else { seenMcParticlesVector.push_back(jMcParticleFromTrack.globalIndex()); } if (std::abs(jMcParticleFromTrack.eta()) < trackEtaAcceptanceCountQA) { // not actually applied here but it will give an idea of what will be done in the post processing - registry.fill(HIST("hTrackCutsCounts"), 4.5); + registry.fill(HIST("hTrackCutsCounts"), 5.5); } } } From 51b7ff98384387eb587b09a68df0d57f443b7ce7 Mon Sep 17 00:00:00 2001 From: Archita-Dash <91664849+Archita-Dash@users.noreply.github.com> Date: Thu, 12 Jun 2025 11:26:11 +0200 Subject: [PATCH 038/871] [PWGJE] removal of the redundant outlier cut from Data (#11534) --- PWGJE/Tasks/fullJetSpectra.cxx | 35 ++++++---------------------------- 1 file changed, 6 insertions(+), 29 deletions(-) diff --git a/PWGJE/Tasks/fullJetSpectra.cxx b/PWGJE/Tasks/fullJetSpectra.cxx index 40e233f9a90..5ddcde82ffb 100644 --- a/PWGJE/Tasks/fullJetSpectra.cxx +++ b/PWGJE/Tasks/fullJetSpectra.cxx @@ -674,8 +674,6 @@ struct FullJetSpectra { void processJetsData(soa::Filtered::iterator const& collision, FullJetTableDataJoined const& jets, aod::JetTracks const&, aod::JetClusters const&) { bool eventAccepted = false; - double weight = 1.0; - float pTHat = 10. / (std::pow(weight, 1.0 / pTHatExponent)); registry.fill(HIST("hDetcollisionCounter"), 0.5); // allDetColl if (std::fabs(collision.posZ()) > vertexZCut) { @@ -683,37 +681,24 @@ struct FullJetSpectra { } registry.fill(HIST("hDetcollisionCounter"), 1.5); // DetCollWithVertexZ - // outlier check: for every outlier jet, reject the whole event - for (auto const& jet : jets) { - if (jet.pt() > pTHatMaxMCD * pTHat || pTHat < pTHatAbsoluteMin) { // for MCD jets only to remove outliers; setting pTHatMaxMCD = 1 improves purity - registry.fill(HIST("hDetcollisionCounter"), 2.5); // RejectedDetCollWithOutliers - return; - } - // this cut only to be used for calculating Jet Purity and not for Response Matrix - // this is mainly applied to remove all high weight jets causing big fluctuations - if (jet.pt() > 1 * pTHat) { - registry.fill(HIST("h_full_jet_pt_pTHatcut"), jet.pt(), weight); - } - } - if (doMBGapTrigger && collision.subGeneratorId() == jetderiveddatautilities::JCollisionSubGeneratorId::mbGap) { - registry.fill(HIST("hDetcollisionCounter"), 3.5); // MBRejectedDetEvents + registry.fill(HIST("hDetcollisionCounter"), 2.5); // MBRejectedDetEvents return; } if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, doMBGapTrigger)) { - registry.fill(HIST("hDetcollisionCounter"), 4.5); // EventsNotSatisfyingEventSelection + registry.fill(HIST("hDetcollisionCounter"), 3.5); // EventsNotSatisfyingEventSelection return; } if (doEMCALEventWorkaround) { if (collision.isEmcalReadout() && !collision.isAmbiguous()) { // i.e. EMCAL has a cell content eventAccepted = true; if (collision.alias_bit(kTVXinEMC)) { - registry.fill(HIST("hDetcollisionCounter"), 5.5); // EMCreadoutDetEventsWithkTVXinEMC + registry.fill(HIST("hDetcollisionCounter"), 4.5); // EMCreadoutDetEventsWithkTVXinEMC } } } else { if (!collision.isAmbiguous() && jetderiveddatautilities::eventEMCAL(collision) && collision.alias_bit(kTVXinEMC)) { - registry.fill(HIST("hDetcollisionCounter"), 5.5); // EMCreadoutDetEventsWithkTVXinEMC + registry.fill(HIST("hDetcollisionCounter"), 4.5); // EMCreadoutDetEventsWithkTVXinEMC eventAccepted = true; } } @@ -724,10 +709,10 @@ struct FullJetSpectra { fillRejectedJetHistograms(jet, 1.0); } } - registry.fill(HIST("hDetcollisionCounter"), 6.5); // AllRejectedDetEventsAfterEMCEventSelection + registry.fill(HIST("hDetcollisionCounter"), 5.5); // AllRejectedDetEventsAfterEMCEventSelection return; } - registry.fill(HIST("hDetcollisionCounter"), 7.5); // EMCAcceptedDetColl + registry.fill(HIST("hDetcollisionCounter"), 6.5); // EMCAcceptedDetColl for (auto const& jet : jets) { if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { @@ -1410,8 +1395,6 @@ struct FullJetSpectra { void processDataTracks(soa::Filtered::iterator const& collision, soa::Filtered const& tracks, soa::Filtered const& clusters) { bool eventAccepted = false; - double weight = 1.0; - float pTHat = 10. / (std::pow(weight, 1.0 / pTHatExponent)); registry.fill(HIST("hCollisionsUnweighted"), 0.5); // allDetColl if (std::fabs(collision.posZ()) > vertexZCut) { @@ -1419,12 +1402,6 @@ struct FullJetSpectra { } registry.fill(HIST("hCollisionsUnweighted"), 1.5); // DetCollWithVertexZ - // for (auto const& track : tracks) { - if (pTHat < pTHatAbsoluteMin) { // Track outlier rejection: should this be for every track iteration or for every collision? - return; - } - // } - if (doMBGapTrigger && collision.subGeneratorId() == jetderiveddatautilities::JCollisionSubGeneratorId::mbGap) { registry.fill(HIST("hCollisionsUnweighted"), 2.5); // MBRejectedDetEvents return; From b458464c33f8f5eb9cb7324ea6c8fbca910c57bf Mon Sep 17 00:00:00 2001 From: ynishida-style Date: Thu, 12 Jun 2025 18:26:44 +0900 Subject: [PATCH 039/871] [PWGJE] improvement of the track selection in jetShape.cxx (#11546) --- PWGJE/Tasks/jetShape.cxx | 89 +++++++++++++++++++++------------------- 1 file changed, 46 insertions(+), 43 deletions(-) diff --git a/PWGJE/Tasks/jetShape.cxx b/PWGJE/Tasks/jetShape.cxx index d7e1f2f0557..3c2bfb4c03c 100644 --- a/PWGJE/Tasks/jetShape.cxx +++ b/PWGJE/Tasks/jetShape.cxx @@ -13,14 +13,10 @@ /// \author Yuto Nishida /// \brief Task for measuring the dependence of the jet shape function rho(r) on the distance r from the jet axis. -#include -#include -#include - -#include "Framework/ASoA.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" +#include "PWGJE/Core/FastJetUtilities.h" +#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include "PWGJE/Core/JetUtilities.h" +#include "PWGJE/DataModel/Jet.h" #include "Common/Core/RecoDecay.h" #include "Common/Core/TrackSelection.h" @@ -28,13 +24,16 @@ #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "PWGJE/Core/FastJetUtilities.h" -#include "PWGJE/Core/JetUtilities.h" -#include "PWGJE/Core/JetDerivedDataUtilities.h" -#include "PWGJE/DataModel/Jet.h" - +#include "Framework/ASoA.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" #include "Framework/runDataProcessing.h" +#include +#include +#include + using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; @@ -61,6 +60,7 @@ struct JetShapeTask { {"ptSum", "ptSum", {HistType::kTH2F, {{14, 0, 0.7}, {300, 0, 300}}}}, {"ptSumBg1", "ptSumBg1", {HistType::kTH2F, {{14, 0, 0.7}, {300, 0, 300}}}}, {"ptSumBg2", "ptSumBg2", {HistType::kTH2F, {{14, 0, 0.7}, {300, 0, 300}}}}, + {"event/vertexz", ";Vtx_{z} (cm);Entries", {HistType::kTH1F, {{100, -20, 20}}}}, {"ptVsCentrality", "ptvscentrality", {HistType::kTH2F, {{100, 0, 100}, {300, 0, 300}}}}}}; Configurable vertexZCut{"vertexZCut", 10.0f, "Accepted z-vertex range"}; @@ -79,9 +79,13 @@ 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 maxTpcNClsCrossedRows{"maxTpcNClsCrossedRows", 70, ""}; - Configurable maxDcaXY{"maxDcaXY", 0.2, ""}; - Configurable maxItsNCls{"maxItsNCls", 2, ""}; + Configurable etaTrUp{"etaTrUp", 0.7f, "maximum track eta"}; + Configurable dcaxyMax{"dcaxyMax", 2.0f, "mximum 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 nclcrossTpcMin{"nclcrossTpcMin", 70.0f, "tpc # of crossedRows cut"}; 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"}; @@ -145,18 +149,10 @@ struct JetShapeTask { void processJetShape(soa::Filtered>::iterator const& collision, aod::JetTracks const& tracks, soa::Join const& jets) { - if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits)) { - return; - } - std::vector ptDensity; - std::vector ptDensityBg1; - std::vector ptDensityBg2; - - ptDensity.reserve(distanceCategory->size() - 1); - ptDensityBg1.reserve(distanceCategory->size() - 1); - ptDensityBg2.reserve(distanceCategory->size() - 1); - // std::cout << collision.centrality() << std::endl; + std::vector ptDensity(distanceCategory->size() - 1, 0.f); + std::vector ptDensityBg1(distanceCategory->size() - 1, 0.f); + std::vector ptDensityBg2(distanceCategory->size() - 1, 0.f); for (auto const& jet : jets) { if (!isAcceptedJet(jet)) { @@ -178,12 +174,10 @@ struct JetShapeTask { registry.fill(HIST("ptVsCentrality"), collision.centrality(), track.pt()); // calculate compornents of jetshapefunction rho(r) - std::vector trackPtSum; - std::vector trackPtSumBg1; - std::vector trackPtSumBg2; - trackPtSum.reserve(distanceCategory->size() - 1); - trackPtSumBg1.reserve(distanceCategory->size() - 1); - trackPtSumBg2.reserve(distanceCategory->size() - 1); + std::vector trackPtSum(distanceCategory->size() - 1, 0.f); + std::vector trackPtSumBg1(distanceCategory->size() - 1, 0.f); + std::vector trackPtSumBg2(distanceCategory->size() - 1, 0.f); + float phiBg1 = jet.phi() + (o2::constants::math::PIHalf); float phiBg2 = jet.phi() - (o2::constants::math::PIHalf); @@ -197,11 +191,11 @@ struct JetShapeTask { float distanceBg2 = std::sqrt(deltaEta * deltaEta + deltaPhiBg2 * deltaPhiBg2); for (size_t i = 0; i < distanceCategory->size() - 1; i++) { - if (distance < distanceCategory->at(i + 1)) + if (distanceCategory->at(i) <= distance && distance < distanceCategory->at(i + 1)) trackPtSum[i] += track.pt(); - if (distanceBg1 < distanceCategory->at(i + 1)) + if (distanceCategory->at(i) <= distanceBg1 && distanceBg1 < distanceCategory->at(i + 1)) trackPtSumBg1[i] += track.pt(); - if (distanceBg2 < distanceCategory->at(i + 1)) + if (distanceCategory->at(i) <= distanceBg2 && distanceBg2 < distanceCategory->at(i + 1)) trackPtSumBg2[i] += track.pt(); } @@ -221,9 +215,9 @@ struct JetShapeTask { for (size_t i = 0; i < distanceCategory->size() - 1; i++) { double jetX = (distanceCategory->at(i + 1) - distanceCategory->at(i)) * i + (distanceCategory->at(i + 1) - distanceCategory->at(i)) / 2; - double jetShapeFunction = ptDensity[i + 1]; - double jetShapeFunctionBg1 = ptDensityBg1[i + 1]; - double jetShapeFunctionBg2 = ptDensityBg2[i + 1]; + double jetShapeFunction = ptDensity[i]; + double jetShapeFunctionBg1 = ptDensityBg1[i]; + double jetShapeFunctionBg2 = ptDensityBg2[i]; registry.fill(HIST("ptSum"), jetX, jetShapeFunction); registry.fill(HIST("ptSumBg1"), jetX, jetShapeFunctionBg1); registry.fill(HIST("ptSumBg2"), jetX, jetShapeFunctionBg2); @@ -238,6 +232,8 @@ struct JetShapeTask { return; } + registry.fill(HIST("event/vertexz"), collision.posZ()); + for (auto const& jet : jets) { if (!isAcceptedJet(jet)) { continue; @@ -245,13 +241,20 @@ struct JetShapeTask { // tracks conditions for (const auto& track : tracks) { - if (track.tpcNClsCrossedRows() < maxTpcNClsCrossedRows) + if (std::abs(track.eta()) > etaTrUp) continue; - if (std::fabs(track.dcaXY()) > maxDcaXY) + if (track.tpcNClsCrossedRows() < nclcrossTpcMin) continue; - if (track.itsNCls() < maxItsNCls) { + if (std::abs(track.dcaXY()) > dcaxyMax) + continue; + if (track.itsChi2NCl() > chi2ItsMax) + continue; + if (track.tpcChi2NCl() > chi2TpcMax) + continue; + if (track.tpcNClsFound() < nclTpcMin) + continue; + if (track.itsNCls() < nclItsMin) continue; - } // PID check registry.fill(HIST("tpcDedx"), track.pt(), track.tpcSignal()); From eca9ddb7a2fd9ef04c2e4c63a4f9c92d4be156f0 Mon Sep 17 00:00:00 2001 From: spucillo <93769017+spucillo@users.noreply.github.com> Date: Thu, 12 Jun 2025 12:01:30 +0200 Subject: [PATCH 040/871] [PWGLF] Fix the reweighting for cascades in MC + temporarily disabling histograms for secondary lambdas (#11559) Co-authored-by: ALICE Action Bot --- PWGLF/Tasks/Strangeness/strangenessInJets.cxx | 408 ++++++++++++------ 1 file changed, 267 insertions(+), 141 deletions(-) diff --git a/PWGLF/Tasks/Strangeness/strangenessInJets.cxx b/PWGLF/Tasks/Strangeness/strangenessInJets.cxx index b7e65345661..3cb2ac41f2b 100644 --- a/PWGLF/Tasks/Strangeness/strangenessInJets.cxx +++ b/PWGLF/Tasks/Strangeness/strangenessInJets.cxx @@ -12,7 +12,7 @@ /// \file strangenessInJets.cxx /// /// \brief task for analysis of strangeness in jets -/// \author Alberto Caliva (alberto.caliva@cern.ch), Francesca Ercolessi (francesca.ercolessi@cern.ch), Nicolò Jacazio (nicolo.jacazio@cern.ch) +/// \author Alberto Caliva (alberto.caliva@cern.ch), Francesca Ercolessi (francesca.ercolessi@cern.ch), Nicolò Jacazio (nicolo.jacazio@cern.ch), Sara Pucillo (sara.pucillo@cern.ch) /// \since May 22, 2024 #include @@ -156,9 +156,13 @@ struct StrangenessInJets { Configurable histoNameWeightAntilambdaJet{"histoNameWeightAntilambdaJet", "", "reweighting histogram: antilambda in jet"}; Configurable histoNameWeightAntilambdaUe{"histoNameWeightAntilambdaUe", "", "reweighting histogram: antilambda in ue"}; Configurable histoNameWeightsXiInJet{"histoNameWeightsXiInJet", "", "reweighting histogram: xi in jet"}; - Configurable histoNameWeightsXiInUe{"histoNameWeightsXiInUe", "", "reweighting histogram: xi in ue"}; + Configurable histoNameWeightsXiUe{"histoNameWeightsXiUe", "", "reweighting histogram: xi in ue"}; Configurable histoNameWeightsAntiXiInJet{"histoNameWeightsAntiXiInJet", "", "reweighting histogram: antixi in jet"}; - Configurable histoNameWeightsAntiXiInUe{"histoNameWeightsAntiXiInUe", "", "reweighting histogram: antixi in ue"}; + Configurable histoNameWeightsAntiXiUe{"histoNameWeightsAntiXiUe", "", "reweighting histogram: antixi in ue"}; + Configurable histoNameWeightsOmegaInJet{"histoNameWeightsOmegaInJet", "", "reweighting histogram: omega in jet"}; + Configurable histoNameWeightsOmegaUe{"histoNameWeightsOmegaUe", "", "reweighting histogram: omega in ue"}; + Configurable histoNameWeightsAntiOmegaInJet{"histoNameWeightsAntiOmegaInJet", "", "reweighting histogram: antiomega in jet"}; + Configurable histoNameWeightsAntiOmegaUe{"histoNameWeightsAntiOmegaUe", "", "reweighting histogram: antiomega in ue"}; // Two-dimensional weights TH2F* twodWeightsPiplusJet = nullptr; @@ -171,10 +175,14 @@ struct StrangenessInJets { TH2F* twodWeightsLambdaUe; TH2F* twodWeightsAntilambdaJet; TH2F* twodWeightsAntilambdaUe; - TH1F* weightsXiInJet; - TH1F* weightsXiInUe; - TH1F* weightsAntiXiInJet; - TH1F* weightsAntiXiInUe; + TH2F* twodWeightsXiInJet; + TH2F* twodWeightsXiUe; + TH2F* twodWeightsAntiXiInJet; + TH2F* twodWeightsAntiXiUe; + TH2F* twodWeightsOmegaInJet; + TH2F* twodWeightsOmegaUe; + TH2F* twodWeightsAntiOmegaInJet; + TH2F* twodWeightsAntiOmegaUe; // List of Particles enum Option { KZeroLambda, @@ -214,10 +222,14 @@ struct StrangenessInJets { twodWeightsLambdaUe = nullptr; twodWeightsAntilambdaJet = nullptr; twodWeightsAntilambdaUe = nullptr; - weightsXiInJet = nullptr; - weightsXiInUe = nullptr; - weightsAntiXiInJet = nullptr; - weightsAntiXiInUe = nullptr; + twodWeightsXiInJet = nullptr; + twodWeightsXiUe = nullptr; + twodWeightsAntiXiInJet = nullptr; + twodWeightsAntiXiUe = nullptr; + twodWeightsOmegaInJet = nullptr; + twodWeightsOmegaUe = nullptr; + twodWeightsAntiOmegaInJet = nullptr; + twodWeightsAntiOmegaUe = nullptr; } // Event Counters @@ -241,8 +253,8 @@ struct StrangenessInJets { registryQC.add("sumPtUE", "sumPtUE", HistType::kTH1F, {{500, 0, 50, "#it{p}_{T} (GeV/#it{c})"}}); registryQC.add("nJets_found", "nJets_found", HistType::kTH1F, {{10, 0, 10, "#it{n}_{Jet}"}}); registryQC.add("nJets_selected", "nJets_selected", HistType::kTH1F, {{10, 0, 10, "#it{n}_{Jet}"}}); - registryQC.add("dcaxy_vs_pt", "dcaxy_vs_pt", HistType::kTH2F, {{100, 0.0, 5.0, "#it{p}_{T} (GeV/#it{c})"}, {2000, -0.05, 0.05, "DCA_{xy} (cm)"}}); - registryQC.add("dcaz_vs_pt", "dcaz_vs_pt", HistType::kTH2F, {{100, 0.0, 5.0, "#it{p}_{T} (GeV/#it{c})"}, {2000, -0.05, 0.05, "DCA_{z} (cm)"}}); + // registryQC.add("dcaxy_vs_pt", "dcaxy_vs_pt", HistType::kTH2F, {{100, 0.0, 5.0, "#it{p}_{T} (GeV/#it{c})"}, {2000, -0.05, 0.05, "DCA_{xy} (cm)"}}); + // registryQC.add("dcaz_vs_pt", "dcaz_vs_pt", HistType::kTH2F, {{100, 0.0, 5.0, "#it{p}_{T} (GeV/#it{c})"}, {2000, -0.05, 0.05, "DCA_{z} (cm)"}}); registryQC.add("jet_jet_overlaps", "jet_jet_overlaps", HistType::kTH2F, {{20, 0.0, 20.0, "#it{n}_{jet}"}, {200, 0.0, 200.0, "#it{n}_{overlaps}"}}); registryQC.add("jet_ue_overlaps", "jet_ue_overlaps", HistType::kTH2F, {{20, 0.0, 20.0, "#it{n}_{jet}"}, {200, 0.0, 200.0, "#it{n}_{overlaps}"}}); registryQC.add("ue_ue_overlaps", "ue_ue_overlaps", HistType::kTH2F, {{20, 0.0, 20.0, "#it{n}_{jet}"}, {200, 0.0, 200.0, "#it{n}_{overlaps}"}}); @@ -344,10 +356,14 @@ struct StrangenessInJets { registryMC.add("Lambda_generated_ue", "Lambda_generated_ue", HistType::kTH2F, {multBinning, ptAxis}); registryMC.add("AntiLambda_generated_jet", "AntiLambda_generated_jet", HistType::kTH2F, {multBinning, ptAxis}); registryMC.add("AntiLambda_generated_ue", "AntiLambda_generated_ue", HistType::kTH2F, {multBinning, ptAxis}); - registryMC.add("XiPos_generated", "XiPos_generated", HistType::kTH2F, {multBinning, ptAxis}); - registryMC.add("XiNeg_generated", "XiNeg_generated", HistType::kTH2F, {multBinning, ptAxis}); - registryMC.add("OmegaPos_generated", "OmegaPos_generated", HistType::kTH2F, {multBinning, ptAxis}); - registryMC.add("OmegaNeg_generated", "OmegaNeg_generated", HistType::kTH2F, {multBinning, ptAxis}); + registryMC.add("XiPos_generated_jet", "XiPos_generated_jet", HistType::kTH2F, {multBinning, ptAxis}); + registryMC.add("XiPos_generated_ue", "XiPos_generated_ue", HistType::kTH2F, {multBinning, ptAxis}); + registryMC.add("XiNeg_generated_jet", "XiNeg_generated_jet", HistType::kTH2F, {multBinning, ptAxis}); + registryMC.add("XiNeg_generated_ue", "XiNeg_generated_ue", HistType::kTH2F, {multBinning, ptAxis}); + registryMC.add("OmegaPos_generated_jet", "OmegaPos_generated_jet", HistType::kTH2F, {multBinning, ptAxis}); + registryMC.add("OmegaPos_generated_ue", "OmegaPos_generated_ue", HistType::kTH2F, {multBinning, ptAxis}); + registryMC.add("OmegaNeg_generated_jet", "OmegaNeg_generated_jet", HistType::kTH2F, {multBinning, ptAxis}); + registryMC.add("OmegaNeg_generated_ue", "OmegaNeg_generated_ue", HistType::kTH2F, {multBinning, ptAxis}); // Histograms for efficiency (reconstructed) registryMC.add("K0s_reconstructed_jet", "K0s_reconstructed_jet", HistType::kTH2F, {multBinning, ptAxis}); @@ -356,21 +372,30 @@ struct StrangenessInJets { registryMC.add("Lambda_reconstructed_ue", "Lambda_reconstructed_ue", HistType::kTH2F, {multBinning, ptAxis}); registryMC.add("AntiLambda_reconstructed_jet", "AntiLambda_reconstructed_jet", HistType::kTH2F, {multBinning, ptAxis}); registryMC.add("AntiLambda_reconstructed_ue", "AntiLambda_reconstructed_ue", HistType::kTH2F, {multBinning, ptAxis}); - registryMC.add("XiPos_reconstructed", "XiPos_reconstructed", HistType::kTH2F, {multBinning, ptAxis}); - registryMC.add("XiNeg_reconstructed", "XiNeg_reconstructed", HistType::kTH2F, {multBinning, ptAxis}); - registryMC.add("OmegaPos_reconstructed", "OmegaPos_reconstructed", HistType::kTH2F, {multBinning, ptAxis}); - registryMC.add("OmegaNeg_reconstructed", "OmegaNeg_reconstructed", HistType::kTH2F, {multBinning, ptAxis}); + registryMC.add("XiPos_reconstructed_jet", "XiPos_reconstructed_jet", HistType::kTH2F, {multBinning, ptAxis}); + registryMC.add("XiPos_reconstructed_ue", "XiPos_reconstructed_ue", HistType::kTH2F, {multBinning, ptAxis}); + registryMC.add("XiNeg_reconstructed_jet", "XiNeg_reconstructed_jet", HistType::kTH2F, {multBinning, ptAxis}); + registryMC.add("XiNeg_reconstructed_ue", "XiNeg_reconstructed_ue", HistType::kTH2F, {multBinning, ptAxis}); + registryMC.add("OmegaPos_reconstructed_jet", "OmegaPos_reconstructed_jet", HistType::kTH2F, {multBinning, ptAxis}); + registryMC.add("OmegaPos_reconstructed_ue", "OmegaPos_reconstructed_ue", HistType::kTH2F, {multBinning, ptAxis}); + registryMC.add("OmegaNeg_reconstructed_jet", "OmegaNeg_reconstructed_jet", HistType::kTH2F, {multBinning, ptAxis}); + registryMC.add("OmegaNeg_reconstructed_ue", "OmegaNeg_reconstructed_ue", HistType::kTH2F, {multBinning, ptAxis}); // Histograms for secondary hadrons registryMC.add("K0s_reconstructed_incl", "K0s_reconstructed_incl", HistType::kTH2F, {multBinning, ptAxis}); registryMC.add("Lambda_reconstructed_incl", "Lambda_reconstructed_incl", HistType::kTH2F, {multBinning, ptAxis}); registryMC.add("AntiLambda_reconstructed_incl", "AntiLambda_reconstructed_incl", HistType::kTH2F, {multBinning, ptAxis}); + registryMC.add("XiPos_reconstructed_incl", "XiPos_reconstructed_incl", HistType::kTH2F, {multBinning, ptAxis}); + registryMC.add("XiNeg_reconstructed_incl", "XiNeg_reconstructed_incl", HistType::kTH2F, {multBinning, ptAxis}); + registryMC.add("OmegaPos_reconstructed_incl", "OmegaPos_reconstructed_incl", HistType::kTH2F, {multBinning, ptAxis}); + registryMC.add("OmegaNeg_reconstructed_incl", "OmegaNeg_reconstructed_incl", HistType::kTH2F, {multBinning, ptAxis}); + // Histograms for secondary lambda in jet and UE - registryMC.add("Secondary_Lambda_InJet", "Secondary_Lambda_InJet", HistType::kTH1F, {ptAxis}); - registryMC.add("Secondary_Lambda_InUe", "Secondary_Lambda_InUe", HistType::kTH1F, {ptAxis}); - registryMC.add("Secondary_AntiLambda_InJet", "Secondary_AntiLambda_InJet", HistType::kTH1F, {ptAxis}); - registryMC.add("Secondary_AntiLambda_InUe", "Secondary_AntiLambda_InUe", HistType::kTH1F, {ptAxis}); + // registryMC.add("Secondary_Lambda_InJet", "Secondary_Lambda_InJet", HistType::kTH1F, {ptAxis}); + // registryMC.add("Secondary_Lambda_Ue", "Secondary_Lambda_Ue", HistType::kTH1F, {ptAxis}); + // registryMC.add("Secondary_AntiLambda_InJet", "Secondary_AntiLambda_InJet", HistType::kTH1F, {ptAxis}); + // registryMC.add("Secondary_AntiLambda_Ue", "Secondary_AntiLambda_Ue", HistType::kTH1F, {ptAxis}); // Histograms for 2d reweighting (pion) registryMC.add("mc_pi_plus_eta_pt/jet", "", HistType::kTH2F, {ptAxisPi, etaAxis}); @@ -399,20 +424,20 @@ struct StrangenessInJets { registryMC.add("AntiLambda_eta_pt_pythia", "AntiLambda_eta_pt_pythia", HistType::kTH2F, {ptAxis, etaAxis}); // Histograms for 2d reweighting (Xi) - registryMC.add("Xi_eta_pt_jet", "Xi_eta_pt_jet", HistType::kTH2F, {ptAxis, etaAxis}); - registryMC.add("Xi_eta_pt_ue", "Xi_eta_pt_ue", HistType::kTH2F, {ptAxis, etaAxis}); - registryMC.add("Xi_eta_pt_pythia", "Xi_eta_pt_pythia", HistType::kTH2F, {ptAxis, etaAxis}); - registryMC.add("AntiXi_eta_pt_jet", "AntiXi_eta_pt_jet", HistType::kTH2F, {ptAxis, etaAxis}); - registryMC.add("AntiXi_eta_pt_ue", "AntiXi_eta_pt_ue", HistType::kTH2F, {ptAxis, etaAxis}); - registryMC.add("AntiXi_eta_pt_pythia", "AntiXi_eta_pt_pythia", HistType::kTH2F, {ptAxis, etaAxis}); + registryMC.add("XiNeg_eta_pt_jet", "Xi_eta_pt_jet", HistType::kTH2F, {ptAxis, etaAxis}); + registryMC.add("XiNeg_eta_pt_ue", "Xi_eta_pt_ue", HistType::kTH2F, {ptAxis, etaAxis}); + registryMC.add("XiNeg_eta_pt_pythia", "Xi_eta_pt_pythia", HistType::kTH2F, {ptAxis, etaAxis}); + registryMC.add("XiPos_eta_pt_jet", "AntiXi_eta_pt_jet", HistType::kTH2F, {ptAxis, etaAxis}); + registryMC.add("XiPos_eta_pt_ue", "AntiXi_eta_pt_ue", HistType::kTH2F, {ptAxis, etaAxis}); + registryMC.add("XiPos_eta_pt_pythia", "AntiXi_eta_pt_pythia", HistType::kTH2F, {ptAxis, etaAxis}); // Histograms for 2d reweighting (Omega) - registryMC.add("Omega_eta_pt_jet", "Omega_eta_pt_jet", HistType::kTH2F, {ptAxis, etaAxis}); - registryMC.add("Omega_eta_pt_ue", "Omega_eta_pt_ue", HistType::kTH2F, {ptAxis, etaAxis}); - registryMC.add("Omega_eta_pt_pythia", "Omega_eta_pt_pythia", HistType::kTH2F, {ptAxis, etaAxis}); - registryMC.add("AntiOmega_eta_pt_jet", "AntiOmega_eta_pt_jet", HistType::kTH2F, {ptAxis, etaAxis}); - registryMC.add("AntiOmega_eta_pt_ue", "AntiOmega_eta_pt_ue", HistType::kTH2F, {ptAxis, etaAxis}); - registryMC.add("AntiOmega_eta_pt_pythia", "AntiOmega_eta_pt_pythia", HistType::kTH2F, {ptAxis, etaAxis}); + registryMC.add("OmegaNeg_eta_pt_jet", "Omega_eta_pt_jet", HistType::kTH2F, {ptAxis, etaAxis}); + registryMC.add("OmegaNeg_eta_pt_ue", "Omega_eta_pt_ue", HistType::kTH2F, {ptAxis, etaAxis}); + registryMC.add("OmegaNeg_eta_pt_pythia", "Omega_eta_pt_pythia", HistType::kTH2F, {ptAxis, etaAxis}); + registryMC.add("OmegaPos_eta_pt_jet", "AntiOmega_eta_pt_jet", HistType::kTH2F, {ptAxis, etaAxis}); + registryMC.add("OmegaPos_eta_pt_ue", "AntiOmega_eta_pt_ue", HistType::kTH2F, {ptAxis, etaAxis}); + registryMC.add("OmegaPos_eta_pt_pythia", "AntiOmega_eta_pt_pythia", HistType::kTH2F, {ptAxis, etaAxis}); // Histograms for efficiency (pions) registryMC.add("mc_pi_plus/in_jet/gen", "", HistType::kTH2F, {multBinning, ptAxisPi}); @@ -1017,25 +1042,17 @@ struct StrangenessInJets { get2DWeightHisto(histoNameWeightAntilambdaJet, twodWeightsAntilambdaJet); get2DWeightHisto(histoNameWeightAntilambdaUe, twodWeightsAntilambdaUe); - auto get1DWeightHisto = [&](Configurable name, TH1F*& histo) { - LOG(info) << "Looking for 1D weight histogram '" << name.value << "' for " << name.name; - if (name.value == "") { - LOG(info) << " -> Skipping"; - return; - } - histo = static_cast(l->FindObject(name.value.c_str())); - if (!histo) { - LOG(error) << "Could not open histogram '" << name.value << "'"; - return; - } - LOG(info) << "Opened histogram " << histo->ClassName() << " " << histo->GetName(); - }; - - // Secondary Lambda - get1DWeightHisto(histoNameWeightsXiInJet, weightsXiInJet); - get1DWeightHisto(histoNameWeightsXiInUe, weightsXiInUe); - get1DWeightHisto(histoNameWeightsAntiXiInJet, weightsAntiXiInJet); - get1DWeightHisto(histoNameWeightsAntiXiInUe, weightsAntiXiInUe); + // Xi + get2DWeightHisto(histoNameWeightsXiInJet, twodWeightsXiInJet); + get2DWeightHisto(histoNameWeightsXiUe, twodWeightsXiUe); + get2DWeightHisto(histoNameWeightsAntiXiInJet, twodWeightsAntiXiInJet); + get2DWeightHisto(histoNameWeightsAntiXiUe, twodWeightsAntiXiUe); + + // Omega + get2DWeightHisto(histoNameWeightsOmegaInJet, twodWeightsOmegaInJet); + get2DWeightHisto(histoNameWeightsOmegaUe, twodWeightsOmegaUe); + get2DWeightHisto(histoNameWeightsAntiOmegaInJet, twodWeightsAntiOmegaInJet); + get2DWeightHisto(histoNameWeightsAntiOmegaUe, twodWeightsAntiOmegaUe); } void processData(SelCollisions::iterator const& collision, @@ -1271,22 +1288,22 @@ struct StrangenessInJets { } bool isInJet = false; - bool isInUe = false; + bool isUe = false; if (deltaRjet < rJet) isInJet = true; if (deltaRue1 < rJet || deltaRue2 < rJet) - isInUe = true; + isUe = true; if (isHighPurityPion(track, nsigmaTPC, nsigmaTOF)) { if (track.sign() > 0) { if (isInJet) registryData.fill(HIST("piplus_dcaxy_in_jet"), multiplicity, track.pt(), track.dcaXY()); - if (isInUe) + if (isUe) registryData.fill(HIST("piplus_dcaxy_in_ue"), multiplicity, track.pt(), track.dcaXY()); } else { if (isInJet) registryData.fill(HIST("piminus_dcaxy_in_jet"), multiplicity, track.pt(), track.dcaXY()); - if (isInUe) + if (isUe) registryData.fill(HIST("piminus_dcaxy_in_ue"), multiplicity, track.pt(), track.dcaXY()); } } @@ -1301,7 +1318,7 @@ struct StrangenessInJets { if (isInJet) { registryData.fill(HIST("piplus_tpc_in_jet"), multiplicity, track.pt(), nsigmaTPC); } - if (isInUe) { + if (isUe) { registryData.fill(HIST("piplus_tpc_in_ue"), multiplicity, track.pt(), nsigmaTPC); } break; @@ -1309,7 +1326,7 @@ struct StrangenessInJets { if (isInJet) { registryData.fill(HIST("piminus_tpc_in_jet"), multiplicity, track.pt(), nsigmaTPC); } - if (isInUe) { + if (isUe) { registryData.fill(HIST("piminus_tpc_in_ue"), multiplicity, track.pt(), nsigmaTPC); } break; @@ -1327,7 +1344,7 @@ struct StrangenessInJets { if (isInJet) { registryData.fill(HIST("piplus_tof_in_jet"), multiplicity, track.pt(), nsigmaTOF); } - if (isInUe) { + if (isUe) { registryData.fill(HIST("piplus_tof_in_ue"), multiplicity, track.pt(), nsigmaTOF); } break; @@ -1335,7 +1352,7 @@ struct StrangenessInJets { if (isInJet) { registryData.fill(HIST("piminus_tof_in_jet"), multiplicity, track.pt(), nsigmaTOF); } - if (isInUe) { + if (isUe) { registryData.fill(HIST("piminus_tof_in_ue"), multiplicity, track.pt(), nsigmaTOF); } break; @@ -1504,66 +1521,66 @@ struct StrangenessInJets { TVector3 momentumV0 = momentumPos + momentumNeg; // Feed-down for lambda - if (passedLambdaSelection(v0, pos, neg) && pdgParent == kLambda0) { - if (!isPhysPrim) { - double wSecLambdaInJet(1.0); - double wSecLambdaInUe(1.0); - int idMother = posParticle.mothersIds()[0]; - const auto& mother = mcParticles.iteratorAt(idMother); - int idGrandMother = mother.mothersIds()[0]; - const auto& grandMother = mcParticles.iteratorAt(idGrandMother); - switch (grandMother.pdgCode()) { - case kXiMinus: - case kXiPlusBar: - // case 3322: - // case -3322: - if (weightsXiInJet) { - int ibinXiInJet = weightsXiInJet->GetXaxis()->FindBin(grandMother.pt()); - wSecLambdaInJet = weightsXiInJet->GetBinContent(ibinXiInJet); - } - if (weightsXiInUe) { - int ibinXiInUe = weightsXiInUe->GetXaxis()->FindBin(grandMother.pt()); - wSecLambdaInUe = weightsXiInUe->GetBinContent(ibinXiInUe); - } - break; - default: - break; - } - registryMC.fill(HIST("Secondary_Lambda_InJet"), v0.pt(), wSecLambdaInJet); - registryMC.fill(HIST("Secondary_Lambda_InUe"), v0.pt(), wSecLambdaInUe); - } - } + // if (passedLambdaSelection(v0, pos, neg) && pdgParent == kLambda0) { + // if (!isPhysPrim) { + // double wSecLambdaInJet(1.0); + // double wSecLambdaUe(1.0); + // int idMother = posParticle.mothersIds()[0]; + // const auto& mother = mcParticles.iteratorAt(idMother); + // int idGrandMother = mother.mothersIds()[0]; + // const auto& grandMother = mcParticles.iteratorAt(idGrandMother); + // switch (grandMother.pdgCode()) { + // case kXiMinus: + // case kXiPlusBar: + // // case 3322: + // // case -3322: + // if (weightsXiInJet) { + // int ibinXiInJet = weightsXiInJet->GetXaxis()->FindBin(grandMother.pt()); + // wSecLambdaInJet = weightsXiInJet->GetBinContent(ibinXiInJet); + // } + // if (weightsXiUe) { + // int ibinXiUe = weightsXiUe->GetXaxis()->FindBin(grandMother.pt()); + // wSecLambdaUe = weightsXiUe->GetBinContent(ibinXiUe); + // } + // break; + // default: + // break; + // } + // registryMC.fill(HIST("Secondary_Lambda_InJet"), v0.pt(), wSecLambdaInJet); + // registryMC.fill(HIST("Secondary_Lambda_Ue"), v0.pt(), wSecLambdaUe); + // } + //} // Feed-down for antilambda - if (passedAntiLambdaSelection(v0, pos, neg) && pdgParent == kLambda0Bar) { - if (!isPhysPrim) { - double wSecAntiLambdaInJet(1.0); - double wSecAntiLambdaInUe(1.0); - int idMother = posParticle.mothersIds()[0]; - const auto& mother = mcParticles.iteratorAt(idMother); - int idGrandMother = mother.mothersIds()[0]; - const auto& grandMother = mcParticles.iteratorAt(idGrandMother); - switch (grandMother.pdgCode()) { - case kXiMinus: - case kXiPlusBar: - // case 3322: - // case -3322: - if (weightsAntiXiInJet) { - int ibinAntiXiInJet = weightsAntiXiInJet->GetXaxis()->FindBin(grandMother.pt()); - wSecAntiLambdaInJet = weightsAntiXiInJet->GetBinContent(ibinAntiXiInJet); - } - if (weightsAntiXiInUe) { - int ibinAntiXiInUe = weightsAntiXiInUe->GetXaxis()->FindBin(grandMother.pt()); - wSecAntiLambdaInUe = weightsAntiXiInUe->GetBinContent(ibinAntiXiInUe); - } - break; - default: - break; - } - registryMC.fill(HIST("Secondary_AntiLambda_InJet"), v0.pt(), wSecAntiLambdaInJet); - registryMC.fill(HIST("Secondary_AntiLambda_InUe"), v0.pt(), wSecAntiLambdaInUe); - } - } + // if (passedAntiLambdaSelection(v0, pos, neg) && pdgParent == kLambda0Bar) { + // if (!isPhysPrim) { + // double wSecAntiLambdaInJet(1.0); + // double wSecAntiLambdaUe(1.0); + // int idMother = posParticle.mothersIds()[0]; + // const auto& mother = mcParticles.iteratorAt(idMother); + // int idGrandMother = mother.mothersIds()[0]; + // const auto& grandMother = mcParticles.iteratorAt(idGrandMother); + // switch (grandMother.pdgCode()) { + // case kXiMinus: + // case kXiPlusBar: + // // case 3322: + // // case -3322: + // if (weightsAntiXiInJet) { + // int ibinAntiXiInJet = weightsAntiXiInJet->GetXaxis()->FindBin(grandMother.pt()); + // wSecAntiLambdaInJet = weightsAntiXiInJet->GetBinContent(ibinAntiXiInJet); + // } + // if (weightsAntiXiUe) { + // int ibinAntiXiUe = weightsAntiXiUe->GetXaxis()->FindBin(grandMother.pt()); + // wSecAntiLambdaUe = weightsAntiXiUe->GetBinContent(ibinAntiXiUe); + // } + // break; + // default: + // break; + // } + // registryMC.fill(HIST("Secondary_AntiLambda_InJet"), v0.pt(), wSecAntiLambdaInJet); + // registryMC.fill(HIST("Secondary_AntiLambda_Ue"), v0.pt(), wSecAntiLambdaUe); + // } + //} if (passedK0ShortSelection(v0, pos, neg) && pdgParent == kK0Short) { registryMC.fill(HIST("K0s_reconstructed_incl"), multiplicity, v0.pt()); @@ -1645,6 +1662,7 @@ struct StrangenessInJets { continue; int pdgParent(0); + bool isPhysPrim = false; for (const auto& particleMotherOfNeg : negParticle.mothers_as()) { for (const auto& particleMotherOfPos : posParticle.mothers_as()) { for (const auto& particleMotherOfBach : bachParticle.mothers_as()) { @@ -1656,27 +1674,95 @@ struct StrangenessInJets { continue; pdgParent = particleMotherOfBach.pdgCode(); + isPhysPrim = particleMotherOfBach.isPhysicalPrimary(); } } } if (pdgParent == 0) continue; + // Generated Momentum of casc + TVector3 momentumPos(posParticle.px(), posParticle.py(), posParticle.pz()); + TVector3 momentumNeg(negParticle.px(), negParticle.py(), negParticle.pz()); + TVector3 momentumBach(bachParticle.px(), bachParticle.py(), bachParticle.pz()); + TVector3 momentumV0 = momentumPos + momentumNeg; + TVector3 momentumCasc = momentumV0 + momentumBach; + + // Xi+ + if (passedXiSelection(casc, pos, neg, bach, collision) && pdgParent == kXiPlusBar) { + registryMC.fill(HIST("XiPos_reconstructed_incl"), multiplicity, casc.pt()); + } + // Xi- + if (passedXiSelection(casc, pos, neg, bach, collision) && pdgParent == kXiMinus) { + registryMC.fill(HIST("XiNeg_reconstructed_incl"), multiplicity, casc.pt()); + } + // Omega+ + if (passedOmegaSelection(casc, pos, neg, bach, collision) && pdgParent == kOmegaPlusBar) { + registryMC.fill(HIST("OmegaPos_reconstructed_incl"), multiplicity, casc.pt()); + } + // Omega- + if (passedOmegaSelection(casc, pos, neg, bach, collision) && pdgParent == kOmegaMinus) { + registryMC.fill(HIST("OmegaNeg_reconstructed_incl"), multiplicity, casc.pt()); + } + + if (!isPhysPrim) + continue; + + double wXiPosJet(1.0), wXiPosUe(1.0), wXiNegJet(1.0), wXiNegUe(1.0), wOmegaPosJet(1.0), wOmegaPosUe(1.0), wOmegaNegJet(1.0), wOmegaNegUe(1.0); + if (applyReweighting) { + int ix = twodWeightsXiInJet->GetXaxis()->FindBin(momentumCasc.Pt()); + int iy = twodWeightsXiInJet->GetYaxis()->FindBin(momentumCasc.Eta()); + wXiPosJet = twodWeightsAntiXiInJet->GetBinContent(ix, iy); + wXiPosUe = twodWeightsAntiXiUe->GetBinContent(ix, iy); + wXiNegJet = twodWeightsXiInJet->GetBinContent(ix, iy); + wXiNegUe = twodWeightsXiUe->GetBinContent(ix, iy); + wOmegaPosJet = twodWeightsAntiOmegaInJet->GetBinContent(ix, iy); + wOmegaPosUe = twodWeightsAntiOmegaUe->GetBinContent(ix, iy); + wOmegaNegJet = twodWeightsOmegaInJet->GetBinContent(ix, iy); + wOmegaNegUe = twodWeightsOmegaUe->GetBinContent(ix, iy); + + // protections + if (ix == 0 || ix > twodWeightsXiInJet->GetNbinsX()) { + wXiPosJet = 1.0; + wXiPosUe = 1.0; + wXiNegJet = 1.0; + wXiNegUe = 1.0; + wOmegaPosJet = 1.0; + wOmegaPosUe = 1.0; + wOmegaNegJet = 1.0; + wOmegaNegUe = 1.0; + } + if (iy == 0 || iy > twodWeightsXiInJet->GetNbinsY()) { + wXiPosJet = 1.0; + wXiPosUe = 1.0; + wXiNegJet = 1.0; + wXiNegUe = 1.0; + wOmegaPosJet = 1.0; + wOmegaPosUe = 1.0; + wOmegaNegJet = 1.0; + wOmegaNegUe = 1.0; + } + } + // Xi+ if (passedXiSelection(casc, pos, neg, bach, collision) && pdgParent == kXiPlusBar) { - registryMC.fill(HIST("XiPos_reconstructed"), multiplicity, casc.pt()); + registryMC.fill(HIST("XiPos_reconstructed_jet"), multiplicity, casc.pt(), wXiPosJet); + registryMC.fill(HIST("XiPos_reconstructed_ue"), multiplicity, casc.pt(), wXiPosUe); } // Xi- if (passedXiSelection(casc, pos, neg, bach, collision) && pdgParent == kXiMinus) { - registryMC.fill(HIST("XiNeg_reconstructed"), multiplicity, casc.pt()); + registryMC.fill(HIST("XiNeg_reconstructed_jet"), multiplicity, casc.pt(), wXiNegJet); + registryMC.fill(HIST("XiNeg_reconstructed_ue"), multiplicity, casc.pt(), wXiNegUe); } // Omega+ if (passedOmegaSelection(casc, pos, neg, bach, collision) && pdgParent == kOmegaPlusBar) { - registryMC.fill(HIST("OmegaPos_reconstructed"), multiplicity, casc.pt()); + registryMC.fill(HIST("OmegaPos_reconstructed_jet"), multiplicity, casc.pt(), wOmegaPosJet); + registryMC.fill(HIST("OmegaPos_reconstructed_ue"), multiplicity, casc.pt(), wOmegaPosUe); } // Omega- if (passedOmegaSelection(casc, pos, neg, bach, collision) && pdgParent == kOmegaMinus) { - registryMC.fill(HIST("OmegaNeg_reconstructed"), multiplicity, casc.pt()); + registryMC.fill(HIST("OmegaNeg_reconstructed_jet"), multiplicity, casc.pt(), wOmegaNegJet); + registryMC.fill(HIST("OmegaNeg_reconstructed_ue"), multiplicity, casc.pt(), wOmegaNegUe); } } @@ -1854,6 +1940,42 @@ struct StrangenessInJets { } } + double wXiPosJet(1.0), wXiPosUe(1.0), wXiNegJet(1.0), wXiNegUe(1.0), wOmegaPosJet(1.0), wOmegaPosUe(1.0), wOmegaNegJet(1.0), wOmegaNegUe(1.0); + if (applyReweighting) { + int ix = twodWeightsXiInJet->GetXaxis()->FindBin(mcParticle.pt()); + int iy = twodWeightsXiInJet->GetYaxis()->FindBin(mcParticle.eta()); + wXiPosJet = twodWeightsAntiXiInJet->GetBinContent(ix, iy); + wXiPosUe = twodWeightsAntiXiUe->GetBinContent(ix, iy); + wXiNegJet = twodWeightsXiInJet->GetBinContent(ix, iy); + wXiNegUe = twodWeightsXiUe->GetBinContent(ix, iy); + wOmegaPosJet = twodWeightsAntiOmegaInJet->GetBinContent(ix, iy); + wOmegaPosUe = twodWeightsAntiOmegaUe->GetBinContent(ix, iy); + wOmegaNegJet = twodWeightsOmegaInJet->GetBinContent(ix, iy); + wOmegaNegUe = twodWeightsOmegaUe->GetBinContent(ix, iy); + + // protections + if (ix == 0 || ix > twodWeightsXiInJet->GetNbinsX()) { + wXiPosJet = 1.0; + wXiPosUe = 1.0; + wXiNegJet = 1.0; + wXiNegUe = 1.0; + wOmegaPosJet = 1.0; + wOmegaPosUe = 1.0; + wOmegaNegJet = 1.0; + wOmegaNegUe = 1.0; + } + if (iy == 0 || iy > twodWeightsXiInJet->GetNbinsY()) { + wXiPosJet = 1.0; + wXiPosUe = 1.0; + wXiNegJet = 1.0; + wXiNegUe = 1.0; + wOmegaPosJet = 1.0; + wOmegaPosUe = 1.0; + wOmegaNegJet = 1.0; + wOmegaNegUe = 1.0; + } + } + switch (mcParticle.pdgCode()) { /* case kPiPlus: // Pi+ @@ -1903,20 +2025,24 @@ struct StrangenessInJets { registryMC.fill(HIST("AntiLambda_eta_pt_pythia"), mcParticle.pt(), mcParticle.eta()); break; case kXiPlusBar: // Xi Pos - registryMC.fill(HIST("XiPos_generated"), multiplicity, mcParticle.pt()); + registryMC.fill(HIST("XiPos_generated_jet"), multiplicity, mcParticle.pt(), wXiPosJet); + registryMC.fill(HIST("XiPos_generated_ue"), multiplicity, mcParticle.pt(), wXiPosUe); registryMC.fill(HIST("Xi_eta_pt_pythia"), mcParticle.pt(), mcParticle.eta()); break; case kXiMinus: // Xi Neg - registryMC.fill(HIST("XiNeg_generated"), multiplicity, mcParticle.pt()); - registryMC.fill(HIST("AntiXi_eta_pt_pythia"), mcParticle.pt(), mcParticle.eta()); + registryMC.fill(HIST("XiNeg_generated_jet"), multiplicity, mcParticle.pt(), wXiNegJet); + registryMC.fill(HIST("XiNeg_generated_ue"), multiplicity, mcParticle.pt(), wXiNegUe); + registryMC.fill(HIST("XiNeg_eta_pt_pythia"), mcParticle.pt(), mcParticle.eta()); break; case kOmegaPlusBar: // Omega Pos - registryMC.fill(HIST("OmegaPos_generated"), multiplicity, mcParticle.pt()); - registryMC.fill(HIST("Omega_eta_pt_pythia"), mcParticle.pt(), mcParticle.eta()); + registryMC.fill(HIST("OmegaPos_generated_jet"), multiplicity, mcParticle.pt(), wOmegaPosJet); + registryMC.fill(HIST("OmegaPos_generated_ue"), multiplicity, mcParticle.pt(), wOmegaPosUe); + registryMC.fill(HIST("OmegaPos_eta_pt_pythia"), mcParticle.pt(), mcParticle.eta()); break; case kOmegaMinus: // Omega Neg - registryMC.fill(HIST("OmegaNeg_generated"), multiplicity, mcParticle.pt()); - registryMC.fill(HIST("AntiOmega_eta_pt_pythia"), mcParticle.pt(), mcParticle.eta()); + registryMC.fill(HIST("OmegaNeg_generated_jet"), multiplicity, mcParticle.pt(), wOmegaNegJet); + registryMC.fill(HIST("OmegaNeg_generated_ue"), multiplicity, mcParticle.pt(), wOmegaNegUe); + registryMC.fill(HIST("OmegaNeg_eta_pt_pythia"), mcParticle.pt(), mcParticle.eta()); break; } } @@ -2038,16 +2164,16 @@ struct StrangenessInJets { registryMC.fill(HIST("AntiLambda_eta_pt_jet"), particle.pt(), particle.eta()); break; case kXiMinus: - registryMC.fill(HIST("Xi_eta_pt_jet"), particle.pt(), particle.eta()); + registryMC.fill(HIST("XiNeg_eta_pt_jet"), particle.pt(), particle.eta()); break; case kXiPlusBar: - registryMC.fill(HIST("AntiXi_eta_pt_jet"), particle.pt(), particle.eta()); + registryMC.fill(HIST("XiPos_eta_pt_jet"), particle.pt(), particle.eta()); break; case kOmegaMinus: - registryMC.fill(HIST("Omega_eta_pt_jet"), particle.pt(), particle.eta()); + registryMC.fill(HIST("OmegaNeg_eta_pt_jet"), particle.pt(), particle.eta()); break; case kOmegaPlusBar: - registryMC.fill(HIST("AntiOmega_eta_pt_jet"), particle.pt(), particle.eta()); + registryMC.fill(HIST("OmegaPos_eta_pt_jet"), particle.pt(), particle.eta()); break; default: continue; @@ -2074,16 +2200,16 @@ struct StrangenessInJets { registryMC.fill(HIST("AntiLambda_eta_pt_ue"), particle.pt(), particle.eta()); break; case kXiMinus: - registryMC.fill(HIST("Xi_eta_pt_ue"), particle.pt(), particle.eta()); + registryMC.fill(HIST("XiNeg_eta_pt_ue"), particle.pt(), particle.eta()); break; case kXiPlusBar: - registryMC.fill(HIST("AntiXi_eta_pt_ue"), particle.pt(), particle.eta()); + registryMC.fill(HIST("XiPos_eta_pt_ue"), particle.pt(), particle.eta()); break; case kOmegaMinus: - registryMC.fill(HIST("Omega_eta_pt_ue"), particle.pt(), particle.eta()); + registryMC.fill(HIST("OmegaNeg_eta_pt_ue"), particle.pt(), particle.eta()); break; case kOmegaPlusBar: - registryMC.fill(HIST("AntiOmega_eta_pt_ue"), particle.pt(), particle.eta()); + registryMC.fill(HIST("OmegaPos_eta_pt_ue"), particle.pt(), particle.eta()); break; default: continue; From bbd15bff2815ce21d7396bb8f3524ba1745f8b2a Mon Sep 17 00:00:00 2001 From: Javier Castillo Castellanos Date: Thu, 12 Jun 2025 13:31:32 +0200 Subject: [PATCH 041/871] [Common] Use MCH track counterpart of global muon (#11542) --- Common/Tasks/qaMuon.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Common/Tasks/qaMuon.cxx b/Common/Tasks/qaMuon.cxx index 1f210249089..7c854935930 100644 --- a/Common/Tasks/qaMuon.cxx +++ b/Common/Tasks/qaMuon.cxx @@ -2399,7 +2399,7 @@ struct muonQa { mch::Track mchrealigned1, mchrealigned2; VarClusters fgValuesCls1, fgValuesCls2; - if (!FillClusters(muonTrack1, clusters, fgValuesCls1, mchrealigned1) || !FillClusters(muonTrack2, clusters, fgValuesCls2, mchrealigned2)) { + if (!FillClusters(mchTrack1, clusters, fgValuesCls1, mchrealigned1) || !FillClusters(mchTrack2, clusters, fgValuesCls2, mchrealigned2)) { continue; // Refit is not valid } From 5e3822f8a791aafd15b83dc8bf7189f4878e5d87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Jacazio?= Date: Thu, 12 Jun 2025 13:47:59 +0200 Subject: [PATCH 042/871] [ALICE3] Update FastTracker (#11570) Co-authored-by: ALICE Action Bot --- ALICE3/Core/FastTracker.cxx | 198 ++++++++++++++++-------------------- ALICE3/Core/FastTracker.h | 87 +++++++++------- 2 files changed, 139 insertions(+), 146 deletions(-) diff --git a/ALICE3/Core/FastTracker.cxx b/ALICE3/Core/FastTracker.cxx index 1d06958504b..fe89fcd80fd 100644 --- a/ALICE3/Core/FastTracker.cxx +++ b/ALICE3/Core/FastTracker.cxx @@ -9,13 +9,17 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#include -#include +#include "FastTracker.h" + +#include "ReconstructionDataFormats/TrackParametrization.h" + #include "TMath.h" #include "TMatrixD.h" -#include "TRandom.h" #include "TMatrixDSymEigen.h" -#include "FastTracker.h" +#include "TRandom.h" + +#include +#include namespace o2 { @@ -24,36 +28,6 @@ namespace fastsim // +-~-<*>-~-+-~-<*>-~-+-~-<*>-~-+-~-<*>-~-+-~-<*>-~-+-~-<*>-~-+-~-<*>-~-+-~-<*>-~-+ -FastTracker::FastTracker() -{ - // base constructor - magneticField = 20; // in kiloGauss - applyZacceptance = false; - applyMSCorrection = true; - applyElossCorrection = true; - applyEffCorrection = true; - covMatFactor = 0.99f; - verboseLevel = 0; - - // last fast-tracked track properties - covMatOK = 0; - covMatNotOK = 0; - nIntercepts = 0; - nSiliconPoints = 0; - nGasPoints = 0; - - maxRadiusSlowDet = 10; - integrationTime = 0.02; // ms - crossSectionMinB = 8; - dNdEtaCent = 2200; - dNdEtaMinB = 1; - avgRapidity = 0.45; - sigmaD = 6.0; - luminosity = 1.e27; - otherBackground = 0.0; // [0, 1] - upcBackgroundMultiplier = 1.0; -} - void FastTracker::AddLayer(TString name, float r, float z, float x0, float xrho, float resRPhi, float resZ, float eff, int type) { DetLayer newLayer(name, r, z, x0, xrho, resRPhi, resZ, eff, type); @@ -61,6 +35,17 @@ void FastTracker::AddLayer(TString name, float r, float z, float x0, float xrho, if (newLayer.getEfficiency() > 0.0f && newLayer.isInert()) { LOG(error) << "Layer " << name << " with efficiency > 0.0 should not be inert"; } + // Layers should be ordered by increasing radius, check this + if (!layers.empty() && newLayer.getRadius() < layers.back().getRadius()) { + LOG(fatal) << "Layer " << newLayer << " is not ordered correctly, it should be after layer " << layers.back(); + } + // Layers should all have different names + for (const auto& layer : layers) { + if (layer.getName() == newLayer.getName()) { + LOG(fatal) << "Layer with name " << newLayer.getName() << " already exists in FastTracker layers"; + } + } + // Add the new layer to the layers vector layers.push_back(newLayer); } @@ -78,7 +63,7 @@ DetLayer FastTracker::GetLayer(int layer, bool ignoreBarrelLayers) const return layers[layerIdx]; } -int FastTracker::GetLayerIndex(std::string name) const +int FastTracker::GetLayerIndex(const std::string& name) const { int i = 0; for (const auto& layer : layers) { @@ -211,9 +196,9 @@ float FastTracker::Dist(float z, float r) // https://github.com/AliceO2Group/DelphesO2/blob/master/src/DetectorK/DetectorK.cxx#L743 int index = 1; int nSteps = 301; - double dist = 0.0; - double dz0 = (4 * sigmaD - (-4) * sigmaD / (nSteps = 1)); - double z0 = 0.0; + float dist = 0.0; + float dz0 = (4 * sigmaD - (-4) * sigmaD / (nSteps = 1)); + float z0 = 0.0; for (int i = 0; i < nSteps; i++) { if (i == nSteps - 1) index = 1; @@ -243,7 +228,7 @@ float FastTracker::IntegratedHitDensity(float multiplicity, float radius) // porting of DetektorK::IntegratedHitDensity // see here: // https://github.com/AliceO2Group/DelphesO2/blob/master/src/DetectorK/DetectorK.cxx#L712 - float zdcHz = luminosity * 1.e24 * crossSectionMinB; + float zdcHz = luminosity * 1.e24 * mCrossSectionMinB; float den = zdcHz * integrationTime / 1000. * multiplicity * Dist(0., radius) / (o2::constants::math::TwoPI * radius); if (den < OneEventHitDensity(multiplicity, radius)) den = OneEventHitDensity(multiplicity, radius); @@ -301,6 +286,7 @@ float FastTracker::ProbGoodChiSqHit(float radius, float searchRadiusRPhi, float // returns number of intercepts (generic for now) int FastTracker::FastTrack(o2::track::TrackParCov inputTrack, o2::track::TrackParCov& outputTrack, const float nch) { + dNdEtaCent = nch; // set the number of charged particles per unit rapidity hits.clear(); nIntercepts = 0; nSiliconPoints = 0; @@ -310,38 +296,54 @@ int FastTracker::FastTrack(o2::track::TrackParCov inputTrack, o2::track::TrackPa const float initialRadius = std::hypot(posIni[0], posIni[1]); const float kTrackingMargin = 0.1; const int kMaxNumberOfDetectors = 20; + if (kMaxNumberOfDetectors < layers.size()) { + LOG(fatal) << "Too many layers in FastTracker, increase kMaxNumberOfDetectors"; + return -1; // too many layers + } + int firstActiveLayer = -1; // first layer that is not inert + for (size_t i = 0; i < layers.size(); ++i) { + if (!layers[i].isInert()) { + firstActiveLayer = i; + break; + } + } + if (firstActiveLayer <= 0) { + LOG(fatal) << "No active layers found in FastTracker, check layer setup"; + return -2; // no active layers + } const int xrhosteps = 100; const bool applyAngularCorrection = true; goodHitProbability.clear(); - for (int i = 0; i < kMaxNumberOfDetectors; ++i) + for (int i = 0; i < kMaxNumberOfDetectors; ++i) { goodHitProbability.push_back(-1.); - goodHitProbability[0] = 1.; + } + goodHitProbability[0] = 1.; // we use layer zero to accumulate // +-~-<*>-~-+-~-<*>-~-+-~-<*>-~-+-~-<*>-~-+-~-<*>-~-+ // Outward pass to find intercepts int firstLayerReached = -1; int lastLayerReached = -1; new (&outputTrack)(o2::track::TrackParCov)(inputTrack); - for (uint32_t il = 0; il < layers.size(); il++) { + for (size_t il = 0; il < layers.size(); il++) { // check if layer is doable - if (layers[il].getRadius() < initialRadius) + if (layers[il].getRadius() < initialRadius) { continue; // this layer should not be attempted, but go ahead + } // check if layer is reached float targetX = 1e+3; - bool ok = true; inputTrack.getXatLabR(layers[il].getRadius(), targetX, magneticField); if (targetX > 999.f) { LOGF(debug, "Failed to find intercept for layer %d at radius %.2f cm", il, layers[il].getRadius()); break; // failed to find intercept } - ok = inputTrack.propagateTo(targetX, magneticField); - if (ok && applyMSCorrection && layers[il].getRadiationLength() > 0) { + bool ok = inputTrack.propagateTo(targetX, magneticField); + if (ok && mApplyMSCorrection && layers[il].getRadiationLength() > 0) { ok = inputTrack.correctForMaterial(layers[il].getRadiationLength(), 0, applyAngularCorrection); } - if (ok && applyElossCorrection && layers[il].getDensity() > 0) { // correct in small steps + if (ok && mApplyElossCorrection && layers[il].getDensity() > 0) { // correct in small steps for (int ise = xrhosteps; ise--;) { ok = inputTrack.correctForMaterial(0, -layers[il].getDensity() / xrhosteps, applyAngularCorrection); if (!ok) @@ -361,7 +363,7 @@ int FastTracker::FastTrack(o2::track::TrackParCov inputTrack, o2::track::TrackPa break; } } - if (std::abs(inputTrack.getZ()) > layers[il].getZ() && applyZacceptance) { + if (std::abs(inputTrack.getZ()) > layers[il].getZ() && mApplyZacceptance) { break; // out of acceptance bounds } @@ -384,39 +386,19 @@ int FastTracker::FastTrack(o2::track::TrackParCov inputTrack, o2::track::TrackPa o2::track::TrackParCov inwardTrack(inputTrack); // Enlarge covariance matrix - std::array trPars = {0.}; - for (int ip = 0; ip < 5; ip++) { + std::array trPars = {0.}; + for (int ip = 0; ip < o2::track::kNParams; ip++) { trPars[ip] = outputTrack.getParam(ip); } - std::array largeCov = {0.}; - enum { kY, - kZ, - kSnp, - kTgl, - kPtI }; // track parameter aliases - enum { kY2, - kYZ, - kZ2, - kYSnp, - kZSnp, - kSnp2, - kYTgl, - kZTgl, - kSnpTgl, - kTgl2, - kYPtI, - kZPtI, - kSnpPtI, - kTglPtI, - kPtI2 }; // cov.matrix aliases - const double kLargeErr2Coord = 5 * 5; - const double kLargeErr2Dir = 0.7 * 0.7; - const double kLargeErr2PtI = 30.5 * 30.5; - for (int ic = 15; ic--;) + static constexpr float kLargeErr2Coord = 5 * 5; + static constexpr float kLargeErr2Dir = 0.7 * 0.7; + static constexpr float kLargeErr2PtI = 30.5 * 30.5; + std::array largeCov = {0.}; + for (int ic = o2::track::kCovMatSize; ic--;) largeCov[ic] = 0.; - largeCov[kY2] = largeCov[kZ2] = kLargeErr2Coord; - largeCov[kSnp2] = largeCov[kTgl2] = kLargeErr2Dir; - largeCov[kPtI2] = kLargeErr2PtI * trPars[kPtI] * trPars[kPtI]; + largeCov[o2::track::CovLabels::kSigY2] = largeCov[o2::track::CovLabels::kSigZ2] = kLargeErr2Coord; + largeCov[o2::track::CovLabels::kSigSnp2] = largeCov[o2::track::CovLabels::kSigTgl2] = kLargeErr2Dir; + largeCov[o2::track::CovLabels::kSigQ2Pt2] = kLargeErr2PtI * trPars[o2::track::ParLabels::kQ2Pt] * trPars[o2::track::ParLabels::kQ2Pt]; inwardTrack.setCov(largeCov); inwardTrack.checkCovariance(); @@ -434,7 +416,7 @@ int FastTracker::FastTrack(o2::track::TrackParCov inputTrack, o2::track::TrackPa continue; // failed to propagate } - if (std::abs(inputTrack.getZ()) > layers[il].getZ() && applyZacceptance) { + if (std::abs(inputTrack.getZ()) > layers[il].getZ() && mApplyZacceptance) { continue; // out of acceptance bounds but continue inwards } @@ -444,10 +426,10 @@ int FastTracker::FastTrack(o2::track::TrackParCov inputTrack, o2::track::TrackPa std::vector thisHit = {spacePoint[0], spacePoint[1], spacePoint[2]}; // towards adding cluster: move to track alpha - double alpha = inwardTrack.getAlpha(); - double xyz1[3]{ - TMath::Cos(alpha) * spacePoint[0] + TMath::Sin(alpha) * spacePoint[1], - -TMath::Sin(alpha) * spacePoint[0] + TMath::Cos(alpha) * spacePoint[1], + float alpha = inwardTrack.getAlpha(); + float xyz1[3]{ + std::cos(alpha) * spacePoint[0] + std::sin(alpha) * spacePoint[1], + -std::sin(alpha) * spacePoint[0] + std::cos(alpha) * spacePoint[1], spacePoint[2]}; if (!inwardTrack.propagateTo(xyz1[0], magneticField)) continue; @@ -462,7 +444,7 @@ int FastTracker::FastTrack(o2::track::TrackParCov inputTrack, o2::track::TrackPa inwardTrack.checkCovariance(); } - if (applyMSCorrection && layers[il].getRadiationLength() > 0) { + if (mApplyMSCorrection && layers[il].getRadiationLength() > 0) { if (!inputTrack.correctForMaterial(layers[il].getRadiationLength(), 0, applyAngularCorrection)) { return -6; } @@ -470,7 +452,7 @@ int FastTracker::FastTrack(o2::track::TrackParCov inputTrack, o2::track::TrackPa return -6; } } - if (applyElossCorrection && layers[il].getDensity() > 0) { + if (mApplyElossCorrection && layers[il].getDensity() > 0) { for (int ise = xrhosteps; ise--;) { // correct in small steps if (!inputTrack.correctForMaterial(0, layers[il].getDensity() / xrhosteps, applyAngularCorrection)) { return -7; @@ -488,9 +470,9 @@ int FastTracker::FastTrack(o2::track::TrackParCov inputTrack, o2::track::TrackPa hits.push_back(thisHit); - if (applyEffCorrection && !layers[il].isInert()) { // good hit probability calculation - double sigYCmb = o2::math_utils::sqrt(inwardTrack.getSigmaY2() + layers[il].getResolutionRPhi() * layers[il].getResolutionRPhi()); - double sigZCmb = o2::math_utils::sqrt(inwardTrack.getSigmaZ2() + layers[il].getResolutionZ() * layers[il].getResolutionZ()); + if (!layers[il].isInert()) { // good hit probability calculation + float sigYCmb = o2::math_utils::sqrt(inwardTrack.getSigmaY2() + layers[il].getResolutionRPhi() * layers[il].getResolutionRPhi()); + float sigZCmb = o2::math_utils::sqrt(inwardTrack.getSigmaZ2() + layers[il].getResolutionZ() * layers[il].getResolutionZ()); goodHitProbability[il] = ProbGoodChiSqHit(layers[il].getRadius() * 100, sigYCmb * 100, sigZCmb * 100); goodHitProbability[0] *= goodHitProbability[il]; } @@ -498,9 +480,11 @@ int FastTracker::FastTrack(o2::track::TrackParCov inputTrack, o2::track::TrackPa // backpropagate to original radius float finalX = 1e+3; - inwardTrack.getXatLabR(initialRadius, finalX, magneticField); - if (finalX > 999) + bool inPropStatus = inwardTrack.getXatLabR(initialRadius, finalX, magneticField); + if (finalX > 999) { + LOG(debug) << "Failed to find intercept for initial radius " << initialRadius << " cm, x = " << finalX << " and status " << inPropStatus << " and sn = " << inwardTrack.getSnp() << " r = " << inwardTrack.getY() * inwardTrack.getY(); return -3; // failed to find intercept + } if (!inwardTrack.propagateTo(finalX, magneticField)) { return -4; // failed to propagate @@ -511,17 +495,15 @@ int FastTracker::FastTrack(o2::track::TrackParCov inputTrack, o2::track::TrackPa return nIntercepts; // generate efficiency - if (applyEffCorrection) { - dNdEtaCent = nch; - float eff = 1.; - for (int i = 0; i < kMaxNumberOfDetectors; i++) { - float iGoodHit = goodHitProbability[i]; - if (iGoodHit <= 0) - continue; - - eff *= iGoodHit; - } + float eff = 1.; + for (int i = 0; i < kMaxNumberOfDetectors; i++) { + float iGoodHit = goodHitProbability[i]; + if (iGoodHit <= 0) + continue; + eff *= iGoodHit; + } + if (mApplyEffCorrection) { if (gRandom->Uniform() > eff) return -8; } @@ -530,11 +512,11 @@ int FastTracker::FastTrack(o2::track::TrackParCov inputTrack, o2::track::TrackPa outputTrack.checkCovariance(); // Use covariance matrix based smearing - std::array covMat = {0.}; - for (int ii = 0; ii < 15; ii++) + std::array covMat = {0.}; + for (int ii = 0; ii < o2::track::kCovMatSize; ii++) covMat[ii] = outputTrack.getCov()[ii]; TMatrixDSym m(5); - double fcovm[5][5]; + float fcovm[5][5]; for (int ii = 0, k = 0; ii < 5; ++ii) { for (int j = 0; j < ii + 1; ++j, ++k) { @@ -544,7 +526,7 @@ int FastTracker::FastTrack(o2::track::TrackParCov inputTrack, o2::track::TrackPa } // evaluate ruben's conditional, regularise - bool makePositiveDefinite = (covMatFactor > -1e-5); // apply fix + const bool makePositiveDefinite = (covMatFactor > -1e-5); // apply fix bool rubenConditional = false; for (int ii = 0; ii < 5; ii++) { for (int jj = 0; jj < 5; jj++) { @@ -571,7 +553,7 @@ int FastTracker::FastTrack(o2::track::TrackParCov inputTrack, o2::track::TrackPa } if (negEigVal && rubenConditional && makePositiveDefinite) { - if (verboseLevel > 0) { + if (mVerboseLevel > 0) { LOG(info) << "WARNING: this diagonalization (at pt = " << inputTrack.getPt() << ") has negative eigenvalues despite Ruben's fix! Please be careful!"; LOG(info) << "Printing info:"; LOG(info) << "Kalman updates: " << nIntercepts; @@ -585,9 +567,9 @@ int FastTracker::FastTrack(o2::track::TrackParCov inputTrack, o2::track::TrackPa covMatOK++; // transform parameter vector and smear - double params_[5]; + float params_[5]; for (int ii = 0; ii < 5; ++ii) { - double val = 0.; + float val = 0.; for (int j = 0; j < 5; ++j) val += eigVec[j][ii] * outputTrack.getParam(j); // smear parameters according to eigenvalues @@ -598,7 +580,7 @@ int FastTracker::FastTrack(o2::track::TrackParCov inputTrack, o2::track::TrackPa eigVec.Invert(); // transform back params vector for (int ii = 0; ii < 5; ++ii) { - double val = 0.; + float val = 0.; for (int j = 0; j < 5; ++j) val += eigVec[j][ii] * params_[j]; outputTrack.setParam(val, ii); diff --git a/ALICE3/Core/FastTracker.h b/ALICE3/Core/FastTracker.h index 702caa9e84b..a0dba5d7ec5 100644 --- a/ALICE3/Core/FastTracker.h +++ b/ALICE3/Core/FastTracker.h @@ -12,12 +12,15 @@ #ifndef ALICE3_CORE_FASTTRACKER_H_ #define ALICE3_CORE_FASTTRACKER_H_ -#include // not a system header but megalinter thinks so -#include -#include #include "DetLayer.h" + #include "ReconstructionDataFormats/Track.h" +#include // not a system header but megalinter thinks so + +#include +#include + namespace o2 { namespace fastsim @@ -32,13 +35,16 @@ class FastTracker { public: // Constructor/destructor - FastTracker(); + FastTracker() = default; + // Destructor virtual ~FastTracker() {} // Layer and layer configuration void AddLayer(TString name, float r, float z, float x0, float xrho, float resRPhi = 0.0f, float resZ = 0.0f, float eff = 0.0f, int type = 0); DetLayer GetLayer(const int layer, bool ignoreBarrelLayers = true) const; - int GetLayerIndex(const std::string name) const; + int GetLayerIndex(const std::string& name) const; + size_t GetNLayers() const { return layers.size(); } + bool IsLayerInert(const int layer) const { return layers[layer].isInert(); } void SetRadiationLength(const std::string layerName, float x0) { layers[GetLayerIndex(layerName)].setRadiationLength(x0); } void SetRadius(const std::string layerName, float r) { layers[GetLayerIndex(layerName)].setRadius(r); } void SetResolutionRPhi(const std::string layerName, float resRPhi) { layers[GetLayerIndex(layerName)].setResolutionRPhi(resRPhi); } @@ -80,20 +86,24 @@ class FastTracker void SetIntegrationTime(float t) { integrationTime = t; } void SetMaxRadiusOfSlowDetectors(float r) { maxRadiusSlowDet = r; } void SetAvgRapidity(float y) { avgRapidity = y; } - void SetdNdEtaCent(float d) { dNdEtaCent = d; } + void SetdNdEtaCent(int d) { dNdEtaCent = d; } void SetLhcUPCscale(float s) { lhcUPCScale = s; } void SetBField(float b) { magneticField = b; } void SetMinRadTrack(float r) { fMinRadTrack = r; } void SetMagneticField(float b) { magneticField = b; } - void SetApplyZacceptance(bool b) { applyZacceptance = b; } - void SetApplyMSCorrection(bool b) { applyMSCorrection = b; } - void SetApplyElossCorrection(bool b) { applyElossCorrection = b; } + void SetApplyZacceptance(bool b) { mApplyZacceptance = b; } + void SetApplyMSCorrection(bool b) { mApplyMSCorrection = b; } + void SetApplyElossCorrection(bool b) { mApplyElossCorrection = b; } + void SetApplyEffCorrection(bool b) { mApplyEffCorrection = b; } // Getters for the last track int GetNIntercepts() const { return nIntercepts; } int GetNSiliconPoints() const { return nSiliconPoints; } int GetNGasPoints() const { return nGasPoints; } - float GetGoodHitProb(int layer) const { return goodHitProbability[layer]; } + float GetGoodHitProb(int layer) const + { + return (layer >= 0 && static_cast(layer) < goodHitProbability.size()) ? goodHitProbability[layer] : 0.0f; + } std::size_t GetNHits() const { return hits.size(); } float GetHitX(const int i) const { return hits[i][0]; } float GetHitY(const int i) const { return hits[i][1]; } @@ -106,34 +116,35 @@ class FastTracker std::vector layers; std::vector> hits; // bookkeep last added hits - // operational - bool applyZacceptance; // check z acceptance or not - bool applyMSCorrection; // Apply correction for multiple scattering - bool applyElossCorrection; // Apply correction for eloss (requires MS correction) - bool applyEffCorrection; // Apply correction for hit efficiency - int verboseLevel; // 0: not verbose, >0 more verbose - int crossSectionMinB; - int dNdEtaCent; - int dNdEtaMinB; - float integrationTime; - float magneticField; // in kiloGauss (5 = 0.5T, etc) - float covMatFactor; // covmat off-diagonal factor to use for covmat fix (negative: no factor) - float sigmaD; - float luminosity; - float otherBackground; - float maxRadiusSlowDet; - float avgRapidity; - float lhcUPCScale; - float upcBackgroundMultiplier; - float fMinRadTrack = 132.; - - uint64_t covMatOK; // cov mat has negative eigenvals - uint64_t covMatNotOK; // cov mat has negative eigenvals - - // last track information - int nIntercepts; // found in first outward propagation - int nSiliconPoints; // silicon-based space points added to track - int nGasPoints; // tpc-based space points added to track + /// configuration parameters + bool mApplyZacceptance = false; /// check z acceptance or not + bool mApplyMSCorrection = true; /// Apply correction for multiple scattering + bool mApplyElossCorrection = true; /// Apply correction for eloss (requires MS correction) + bool mApplyEffCorrection = true; /// Apply correction for hit efficiency + int mVerboseLevel = 0; /// 0: not verbose, >0 more verbose + const float mCrossSectionMinB = 8; /// Minimum bias Cross section for event under study (PbPb MinBias ~ 8 Barns) + int dNdEtaCent = 2200; /// dN/deta e.g. at centrality 0-5% (for 5 TeV PbPb) + int dNdEtaMinB = 1; /// dN/deta for minimum bias events + float integrationTime = 0.02f; /// Integration time in ms + float magneticField = 20.f; /// Magnetic field in kiloGauss (5 = 0.5T, 20 = 2T, etc) + float covMatFactor = 0.99f; /// covmat off-diagonal factor to use for covmat fix (negative: no factor) + float sigmaD = 6.0f; /// sigma for the detector resolution in cm + float luminosity = 1.e27f; /// luminosity in cm^-2 s^-1 (e.g. 1.e27 for PbPb at 5 TeV) + float otherBackground = 0.0f; /// background from other sources, e.g. pileup, in [0, 1] + float maxRadiusSlowDet = 10.f; /// maximum radius of slow detectors in cm + float avgRapidity = 0.45f; /// average rapidity for hit density calculation + float lhcUPCScale = 1.0f; /// scale factor for LHC UPC events + float upcBackgroundMultiplier = 1.0f; /// multiplier for UPC background + float fMinRadTrack = 132.f; /// minimum radius for track propagation in cm + + /// counters for covariance matrix statuses + uint64_t covMatOK = 0; /// cov mat has positive eigenvals + uint64_t covMatNotOK = 0; /// cov mat has negative eigenvals + + /// last track information + int nIntercepts = 0; /// found in first outward propagation + int nSiliconPoints = 0; /// silicon-based space points added to track + int nGasPoints = 0; /// tpc-based space points added to track std::vector goodHitProbability; ClassDef(FastTracker, 1); From cd56de7443ab03dec8ad124f5e7c2d39ee949045 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADt=20Ku=C4=8Dera?= Date: Thu, 12 Jun 2025 14:32:16 +0200 Subject: [PATCH 043/871] [Common] Include What You Use (#11547) --- Common/Core/fwdtrackUtilities.h | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/Common/Core/fwdtrackUtilities.h b/Common/Core/fwdtrackUtilities.h index 13fb27c5862..74fe125c2f0 100644 --- a/Common/Core/fwdtrackUtilities.h +++ b/Common/Core/fwdtrackUtilities.h @@ -18,10 +18,18 @@ #ifndef COMMON_CORE_FWDTRACKUTILITIES_H_ #define COMMON_CORE_FWDTRACKUTILITIES_H_ +#include +#include +#include +#include +#include +#include + +#include +#include +#include + #include -#include -#include "Math/SMatrix.h" -#include "TGeoGlobalMagField.h" namespace o2::aod { From 19e218734db13541c89ff9164b37705a9be9fc05 Mon Sep 17 00:00:00 2001 From: marcobianchi463 <121625445+marcobianchi463@users.noreply.github.com> Date: Thu, 12 Jun 2025 16:13:33 +0200 Subject: [PATCH 044/871] [PWGLF] Harmonics configurable and amplitude definition (#11555) --- PWGLF/TableProducer/Nuspex/nucleiFlowTree.cxx | 10 ++--- PWGLF/TableProducer/QC/flowQC.cxx | 42 ++++++++++--------- 2 files changed, 27 insertions(+), 25 deletions(-) diff --git a/PWGLF/TableProducer/Nuspex/nucleiFlowTree.cxx b/PWGLF/TableProducer/Nuspex/nucleiFlowTree.cxx index 6c15c2a626c..14192166fae 100644 --- a/PWGLF/TableProducer/Nuspex/nucleiFlowTree.cxx +++ b/PWGLF/TableProducer/Nuspex/nucleiFlowTree.cxx @@ -428,11 +428,11 @@ struct nucleiFlowTree { computeEventPlane(collision.qvecTPCallImVec()[cfgHarmonics - 2], collision.qvecTPCallReVec()[cfgHarmonics - 2]), computeEventPlane(collision.qvecTPCnegImVec()[cfgHarmonics - 2], collision.qvecTPCnegReVec()[cfgHarmonics - 2]), computeEventPlane(collision.qvecTPCposImVec()[cfgHarmonics - 2], collision.qvecTPCposReVec()[cfgHarmonics - 2]), - collision.sumAmplFT0A(), - collision.sumAmplFT0C(), - static_cast(collision.nTrkTPCall()), - static_cast(collision.nTrkTPCneg()), - static_cast(collision.nTrkTPCpos())}); + std::hypot(collision.qvecFT0AImVec()[cfgHarmonics - 2], collision.qvecFT0AReVec()[cfgHarmonics - 2]), + std::hypot(collision.qvecFT0CImVec()[cfgHarmonics - 2], collision.qvecFT0CReVec()[cfgHarmonics - 2]), + std::hypot(collision.qvecTPCallImVec()[cfgHarmonics - 2], collision.qvecTPCallReVec()[cfgHarmonics - 2]), + std::hypot(collision.qvecTPCnegImVec()[cfgHarmonics - 2], collision.qvecTPCnegReVec()[cfgHarmonics - 2]), + std::hypot(collision.qvecTPCposImVec()[cfgHarmonics - 2], collision.qvecTPCposReVec()[cfgHarmonics - 2])}); } if (flag & kTriton) { if (track.pt() < cfgCutPtMinTree || track.pt() > cfgCutPtMaxTree || track.sign() > 0) diff --git a/PWGLF/TableProducer/QC/flowQC.cxx b/PWGLF/TableProducer/QC/flowQC.cxx index f5dfa06f9d7..1e32b954120 100644 --- a/PWGLF/TableProducer/QC/flowQC.cxx +++ b/PWGLF/TableProducer/QC/flowQC.cxx @@ -111,9 +111,11 @@ struct flowQC { int mRunNumber = 0; float mBz = 0.f; + Configurable cfgHarmonics{"cfgHarmonics", 2, "Harmonics for flow analysis"}; + // Flow analysis using CollWithEPandQvec = soa::Join::iterator; + aod::EvSels, aod::CentFT0As, aod::CentFT0Cs, aod::CentFT0Ms, aod::CentFV0As, aod::FT0Mults, aod::FV0Mults, aod::TPCMults, aod::EPCalibrationTables, aod::QvectorFT0CVecs, aod::QvectorFT0AVecs, aod::QvectorFT0MVecs, aod::QvectorFV0AVecs, aod::QvectorTPCallVecs, aod::QvectorTPCposVecs, aod::QvectorTPCnegVecs>::iterator; HistogramRegistry general{"general", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; HistogramRegistry flow_ep{"flow_ep", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; @@ -171,15 +173,15 @@ struct flowQC { const AxisSpec centAxis{cfgCentralityBins, fmt::format("{} percentile", (std::string)centDetectorNames[cfgCentralityEstimator])}; - const AxisSpec QxAxis{cfgQvecBins, "Q_{2,x}"}; - const AxisSpec QyAxis{cfgQvecBins, "Q_{2,y}"}; + const AxisSpec QxAxis{cfgQvecBins, Form("Q_{%d,x}", cfgHarmonics.value)}; + const AxisSpec QyAxis{cfgQvecBins, Form("Q_{%d,y}", cfgHarmonics.value)}; - const AxisSpec NormQxAxis{cfgQvecBins, "#frac{Q_{2,x}}{||#vec{Q_{2}}||}"}; - const AxisSpec NormQyAxis{cfgQvecBins, "#frac{Q_{2,y}}{||#vec{Q_{2}}||}"}; + const AxisSpec NormQxAxis{cfgQvecBins, Form("#frac{Q_{%d,x}}{||#vec{Q_{%d}}||}", cfgHarmonics.value, cfgHarmonics.value)}; + const AxisSpec NormQyAxis{cfgQvecBins, Form("#frac{Q_{%d,y}}{||#vec{Q_{%d}}||}", cfgHarmonics.value, cfgHarmonics.value)}; - const AxisSpec psiAxis{cfgPhiBins, "#psi_{2}"}; - const AxisSpec psiCompAxis{cfgPhiBins, "#psi_{2}^{EP} - #psi_{2}^{Qvec}"}; - const AxisSpec cosPsiCompAxis{cfgCosPhiBins, "cos[2(#psi_{2}^{EP} - #psi_{2}^{Qvec})]"}; + const AxisSpec psiAxis{cfgPhiBins, Form("#psi_{%d}", cfgHarmonics.value)}; + const AxisSpec psiCompAxis{cfgPhiBins, Form("#psi_{%d}^{EP} - #psi_{%d}^{Qvec}", cfgHarmonics.value, cfgHarmonics.value)}; + const AxisSpec cosPsiCompAxis{cfgCosPhiBins, Form("cos[2(#psi_{%d}^{EP} - #psi_{%d}^{Qvec})]", cfgHarmonics.value, cfgHarmonics.value)}; // z vertex histogram general.add("hRecVtxZData", "collision z position", HistType::kTH1F, {{200, -20., +20., "z position (cm)"}}); @@ -203,12 +205,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}_{2}^{%s} #upoint #vec{Q}_{2}^{%s}", qVecDetectorNames[iQvecDet].c_str(), qVecDetectorNames[jQvecDet].c_str()); + auto spLabel = Form("#vec{Q}_{%d}^{%s} #upoint #vec{Q}_{%d}^{%s}", cfgHarmonics.value, qVecDetectorNames[iQvecDet].c_str(), cfgHarmonics.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}_{2}^{%s} #upoint #vec{Q}_{2}^{%s}}{||#vec{Q}_{2}^{%s}|| ||#vec{Q}_{2}^{%s}||}", qVecDetectorNames[iQvecDet].c_str(), qVecDetectorNames[jQvecDet].c_str(), qVecDetectorNames[iQvecDet].c_str(), qVecDetectorNames[jQvecDet].c_str()); + auto normSpLabel = Form("#frac{#vec{Q}_{%d}^{%s} #upoint #vec{Q}_{%d}^{%s}}{||#vec{Q}_{%d}^{%s}|| ||#vec{Q}_{%d}^{%s}||}", cfgHarmonics.value, qVecDetectorNames[iQvecDet].c_str(), cfgHarmonics.value, qVecDetectorNames[jQvecDet].c_str(), cfgHarmonics.value, qVecDetectorNames[iQvecDet].c_str(), cfgHarmonics.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}}); } @@ -285,28 +287,28 @@ struct flowQC { float QyTPC_EP = QmodTPC_EP * std::sin(2 * psiTPC_EP); // Qvec method - float QxFT0A_Qvec = collision.qvecFT0ARe(); - float QyFT0A_Qvec = collision.qvecFT0AIm(); + float QxFT0A_Qvec = collision.qvecFT0AReVec()[cfgHarmonics - 2]; + float QyFT0A_Qvec = collision.qvecFT0AImVec()[cfgHarmonics - 2]; float QmodFT0A_Qvec = std::hypot(QxFT0A_Qvec, QyFT0A_Qvec); float psiFT0A_Qvec = computeEventPlane(QyFT0A_Qvec, QxFT0A_Qvec); - float QxFT0C_Qvec = collision.qvecFT0CRe(); - float QyFT0C_Qvec = collision.qvecFT0CIm(); + float QxFT0C_Qvec = collision.qvecFT0CReVec()[cfgHarmonics - 2]; + float QyFT0C_Qvec = collision.qvecFT0CImVec()[cfgHarmonics - 2]; float QmodFT0C_Qvec = std::hypot(QxFT0C_Qvec, QyFT0C_Qvec); float psiFT0C_Qvec = computeEventPlane(QyFT0C_Qvec, QxFT0C_Qvec); - float QxTPCl_Qvec = collision.qvecBNegRe(); - float QyTPCl_Qvec = collision.qvecBNegIm(); + float QxTPCl_Qvec = collision.qvecTPCnegReVec()[cfgHarmonics - 2]; + float QyTPCl_Qvec = collision.qvecTPCnegImVec()[cfgHarmonics - 2]; float QmodTPCl_Qvec = std::hypot(QxTPCl_Qvec, QyTPCl_Qvec); float psiTPCl_Qvec = computeEventPlane(QyTPCl_Qvec, QxTPCl_Qvec); - float QxTPCr_Qvec = collision.qvecBPosRe(); - float QyTPCr_Qvec = collision.qvecBPosIm(); + float QxTPCr_Qvec = collision.qvecTPCposReVec()[cfgHarmonics - 2]; + float QyTPCr_Qvec = collision.qvecTPCposImVec()[cfgHarmonics - 2]; float QmodTPCr_Qvec = std::hypot(QxTPCr_Qvec, QyTPCr_Qvec); float psiTPCr_Qvec = computeEventPlane(QyTPCr_Qvec, QxTPCr_Qvec); - float QxTPC_Qvec = collision.qvecBTotRe(); - float QyTPC_Qvec = collision.qvecBTotIm(); + float QxTPC_Qvec = collision.qvecTPCallReVec()[cfgHarmonics - 2]; + float QyTPC_Qvec = collision.qvecTPCallImVec()[cfgHarmonics - 2]; float QmodTPC_Qvec = std::hypot(QxTPC_Qvec, QyTPC_Qvec); float psiTPC_Qvec = computeEventPlane(QyTPC_Qvec, QxTPC_Qvec); From e6cfe892884a612f63144e1da17726cd92793d31 Mon Sep 17 00:00:00 2001 From: hernasab Date: Thu, 12 Jun 2025 09:31:25 -0500 Subject: [PATCH 045/871] [PWGCF] added ccdb objects (#11568) Co-authored-by: Sabrina Hernandez --- PWGCF/Flow/Tasks/flowZdcTask.cxx | 131 +++++++++++++++++++++++-------- 1 file changed, 97 insertions(+), 34 deletions(-) diff --git a/PWGCF/Flow/Tasks/flowZdcTask.cxx b/PWGCF/Flow/Tasks/flowZdcTask.cxx index 3bad6691449..18b92bbfff8 100644 --- a/PWGCF/Flow/Tasks/flowZdcTask.cxx +++ b/PWGCF/Flow/Tasks/flowZdcTask.cxx @@ -14,30 +14,34 @@ /// \since 10/01/2024 /// \brief task to evaluate flow and neutron skin with information from ZDC -#include -#include -#include -#include -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/RunningWorkflowInfo.h" -#include "Framework/HistogramRegistry.h" - -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" +#include "Common/CCDB/EventSelectionParams.h" +#include "Common/CCDB/TriggerAliases.h" #include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" #include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/RunningWorkflowInfo.h" +#include "Framework/runDataProcessing.h" +#include #include "TList.h" -#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; @@ -98,7 +102,10 @@ struct FlowZdcTask { Configurable isApplyFT0CbasedOccupancy{"isApplyFT0CbasedOccupancy", false, "T0C Occu cut?"}; Configurable isTDCcut{"isTDCcut", false, "Use TDC cut?"}; Configurable isZEMcut{"isZEMcut", true, "Use ZEM cut?"}; + Configurable useMidRapNchSel{"useMidRapNchSel", true, "Use mid-rapidit Nch selection"}; + Configurable applyEff{"applyEff", true, "Apply track-by-track efficiency correction"}; + Configurable nSigmaNchCut{"nSigmaNchCut", 1., "nSigma Nch selection"}; Configurable minNchSel{"minNchSel", 5., "min Nch Selection"}; Configurable znBasedCut{"znBasedCut", 100, "ZN-based cut"}; Configurable zemCut{"zemCut", 1000., "ZEM cut"}; @@ -106,6 +113,11 @@ struct FlowZdcTask { Configurable minOccCut{"minOccCut", 0, "min Occu cut"}; Configurable maxOccCut{"maxOccCut", 500, "max Occu cut"}; Configurable minITSnCls{"minITSnCls", 5, "min ITSnCls"}; + Configurable minPt{"minPt", 0.1, "minimum pt of the tracks"}; + Configurable maxPt{"maxPt", 3., "maximum pt of the tracks"}; + Configurable maxPtSpectra{"maxPtSpectra", 50., "maximum pt of the tracks"}; + Configurable minEta{"minEta", -0.8, "minimum eta"}; + Configurable maxEta{"maxEta", +0.8, "maximum eta"}; // axis configs ConfigurableAxis axisVertex{"axisVertex", {20, -10, 10}, "vertex axis for histograms"}; ConfigurableAxis axisPhi{"axisPhi", {60, 0.0, constants::math::TwoPI}, "phi axis for histograms"}; @@ -138,9 +150,12 @@ struct FlowZdcTask { using CollisionDataTable = soa::Join; using TrackDataTable = soa::Join; using FilTrackDataTable = soa::Filtered; - std::complex qTPC; // init q TPC - std::complex qZNA{0, 0}; // init qZNA - std::complex qZNC{0, 0}; // init qZNC + + // CCDB paths + Configurable paTH{"paTH", "Users/s/sahernan/test", "base path to the ccdb object"}; + Configurable paTHmeanNch{"paTHmeanNch", "Users/s/shernan/test", "base path to the ccdb object"}; + Configurable paTHsigmaNch{"paTHsigmaNch", "Users/s/shernan/testSigma", "base path to the ccdb object"}; + Configurable ccdbNoLaterThan{"ccdbNoLaterThan", std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(), "latest acceptable timestamp of creation for the object"}; enum EvCutLabel { All = 1, @@ -164,8 +179,7 @@ struct FlowZdcTask { // Begin Histogram Registry HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; - OutputObj pCosPsiDifferences{TProfile("pCosPsiDifferences", "Differences in cos(psi) vs Centrality;Centrality;Mean cos(psi) Difference", 200, 0, 100, -1, 1)}; - OutputObj pSinPsiDifferences{TProfile("pSinPsiDifferences", "Differences in sin(psi) vs Centrality;Centrality;Mean sin(psi) Difference", 200, 0, 100, -1, 1)}; + Service ccdb; OutputObj pZNvsFT0Ccent{TProfile("pZNvsFT0Ccent", "ZN Energy vs FT0C Centrality", 100, 0, 100, 0, 500)}; OutputObj pZPvsFT0Ccent{TProfile("pZPvsFT0Ccent", "ZP Energy vs FT0C Centrality", 100, 0, 100, 0, 500)}; OutputObj pZNratiovscent{TProfile("pZNratiovscent", "Ratio ZNC/ZNA vs FT0C Centrality", 100, 0, 100, 0, 5)}; @@ -337,6 +351,24 @@ struct FlowZdcTask { histos.add("ZNVsNch", ";#it{N}_{ch} (|#eta|<0.8);ZNA+ZNC;", kTH2F, {{{nBinsNch, minNch, maxNch}, {nBinsZDC, minNch, maxZn}}}); histos.add("ZNDifVsNch", ";#it{N}_{ch} (|#eta|<0.8);ZNA-ZNC;", kTH2F, {{{nBinsNch, minNch, maxNch}, {100, -50., 50.}}}); } + LOG(info) << "\tccdbNoLaterThan=" << ccdbNoLaterThan.value; + LOG(info) << "\tapplyEff=" << applyEff.value; + LOG(info) << "\tpaTH=" << paTH.value; + LOG(info) << "\tuseMidRapNchSel=" << useMidRapNchSel.value; + LOG(info) << "\tpaTHmeanNch=" << paTHmeanNch.value; + LOG(info) << "\tpaTHsigmaNch=" << paTHsigmaNch.value; + LOG(info) << "\tminPt=" << minPt.value; + LOG(info) << "\tmaxPt=" << maxPt.value; + LOG(info) << "\tmaxPtSpectra=" << maxPtSpectra.value; + + ccdb->setURL("http://alice-ccdb.cern.ch"); + // Enabling object caching, otherwise each call goes to the CCDB server + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + ccdb->setFatalWhenNull(false); + // Not later than now, will be replaced by the value of the train creation + // This avoids that users can replace objects **while** a train is running + ccdb->setCreatedNotAfter(ccdbNoLaterThan.value); } template bool isEventSelected(EventCuts const& col) @@ -480,6 +512,7 @@ struct FlowZdcTask { histos.fill(HIST("hEventCounter"), EvCutLabel::Zem); } + const double normT0M{(aT0A + aT0C) / 100.}; float znA = zdc.amplitudeZNA() / cfgCollisionEnergy; float znC = zdc.amplitudeZNC() / cfgCollisionEnergy; float zpA = zdc.amplitudeZPA() / cfgCollisionEnergy; @@ -506,7 +539,50 @@ struct FlowZdcTask { } glbTracks++; } + bool skipEvent{false}; + if (useMidRapNchSel) { + auto hMeanNch = ccdb->getForTimeStamp(paTHmeanNch.value, foundBC.timestamp()); + auto hSigmaNch = ccdb->getForTimeStamp(paTHsigmaNch.value, foundBC.timestamp()); + if (!hMeanNch) { + LOGF(info, "hMeanNch NOT LOADED!"); + return; + } + if (!hSigmaNch) { + LOGF(info, "hSigmaNch NOT LOADED!"); + return; + } + const int binT0M{hMeanNch->FindBin(normT0M)}; + const double meanNch{hMeanNch->GetBinContent(binT0M)}; + const double sigmaNch{hSigmaNch->GetBinContent(binT0M)}; + const double nSigmaSelection{nSigmaNchCut * sigmaNch}; + const double diffMeanNch{meanNch - glbTracks}; + + if (!(std::abs(diffMeanNch) < nSigmaSelection)) { + histos.fill(HIST("ExcludedEvtVsNch"), glbTracks); + } else { + skipEvent = true; + } + } + if (!skipEvent) { + return; + } + + for (const auto& track : tracks) { + // Track Selection + if (!track.isGlobalTrack()) { + continue; + } + if ((track.pt() < minPt) || (track.pt() > maxPtSpectra)) { + continue; + } + + histos.fill(HIST("ZposVsEta"), collision.posZ(), track.eta()); + histos.fill(HIST("EtaVsPhi"), track.eta(), track.phi()); + histos.fill(HIST("dcaXYvspT"), track.dcaXY(), track.pt()); + et += std::sqrt(std::pow(track.pt(), 2.) + std::pow(o2::constants::physics::MassPionCharged, 2.)); + meanpt += track.pt(); + } histos.fill(HIST("zPos"), collision.posZ()); histos.fill(HIST("T0Ccent"), collision.centFT0C()); @@ -574,18 +650,12 @@ struct FlowZdcTask { int globalTracks = tracks.size(); if (globalTracks < 1) return; - // this is the q vector for the TPC data. it is a complex function - double qTpcReal = 0.0; // Initialize qTPC_real - double qTpcIm = 0.0; // init qTPC_imaginary - std::complex qTPC(0, 0); // Starting with a q-vector of zero int nTot{0}; // Tracks are already filtered with GlobalTrack || GlobalTrackSDD for (const auto& track : tracks) { - double phi = track.phi(); nTot++; histos.fill(HIST("etaHistogram"), track.eta()); histos.fill(HIST("phiHistogram"), track.phi()); histos.fill(HIST("ptHistogram"), track.pt()); - qTPC += std::complex(std::cos(2.0 * phi), std::sin(2.0 * phi)); } // end track loop 1 double pT{0}; for (const auto& track : tracks) { @@ -599,16 +669,9 @@ struct FlowZdcTask { histos.fill(HIST("multvsCent"), cent, nTot); histos.fill(HIST("hYield"), nTot, pT); histos.fill(HIST("multHistogram"), nTot); - qTpcReal = qTPC.real() / nTot; // normalize these vectors by the total number of particles - qTpcIm = qTPC.imag() / nTot; - - histos.fill(HIST("REqHistogram"), qTpcReal); - histos.fill(HIST("IMqHistogram"), qTpcIm); histos.fill(HIST("TPCmultiplicity"), multTPC); histos.fill(HIST("hGlobalTracks"), globalTracks); - - histos.fill(HIST("revsimag"), qTpcReal, qTpcIm); } void processZdcCollAssoc( AodCollisions::iterator const& collision, From 831f016ec46069d59e34c51293b1ff24fbbb29da Mon Sep 17 00:00:00 2001 From: Noor Koster <82090643+cnkoster@users.noreply.github.com> Date: Thu, 12 Jun 2025 16:55:59 +0200 Subject: [PATCH 046/871] [Common] Add timestamp, centrality and evSelection to inter-calib table (#11457) Co-authored-by: ALICE Action Bot --- Common/DataModel/ZDCInterCalib.h | 35 +++--- Common/TableProducer/CMakeLists.txt | 4 +- ...k-intercalib.cxx => zdcTaskInterCalib.cxx} | 116 ++++++++++++++++-- 3 files changed, 129 insertions(+), 26 deletions(-) rename Common/TableProducer/{zdc-task-intercalib.cxx => zdcTaskInterCalib.cxx} (53%) diff --git a/Common/DataModel/ZDCInterCalib.h b/Common/DataModel/ZDCInterCalib.h index 290a3ac61fe..d7b66575340 100644 --- a/Common/DataModel/ZDCInterCalib.h +++ b/Common/DataModel/ZDCInterCalib.h @@ -20,21 +20,23 @@ namespace o2::aod { -namespace znoutput +namespace znoutput // o2-linter: disable=name/workflow-file { -DECLARE_SOA_COLUMN(ZNApmc, commonPMZNA, float); //! PMC ZNA // o2-linter: disable=name/o2-column -DECLARE_SOA_COLUMN(ZNApm1, ZNAPM1, float); //! PM1 ZNA // o2-linter: disable=name/o2-column -DECLARE_SOA_COLUMN(ZNApm2, ZNAPM2, float); //! PM2 ZNA // o2-linter: disable=name/o2-column -DECLARE_SOA_COLUMN(ZNApm3, ZNAPM3, float); //! PM3 ZNA // o2-linter: disable=name/o2-column -DECLARE_SOA_COLUMN(ZNApm4, ZNAPM4, float); //! PM4 ZNA // o2-linter: disable=name/o2-column -DECLARE_SOA_COLUMN(ZNAtdc, ZNATDC, float); //! TDC ZNA // o2-linter: disable=name/o2-column -DECLARE_SOA_COLUMN(ZNCpmc, commonPMZNC, float); //! PMC ZNC // o2-linter: disable=name/o2-column -DECLARE_SOA_COLUMN(ZNCpm1, ZNCPM1, float); //! PM1 ZNC // o2-linter: disable=name/o2-column -DECLARE_SOA_COLUMN(ZNCpm2, ZNCPM2, float); //! PM2 ZNC // o2-linter: disable=name/o2-column -DECLARE_SOA_COLUMN(ZNCpm3, ZNCPM3, float); //! PM3 ZNC // o2-linter: disable=name/o2-column -DECLARE_SOA_COLUMN(ZNCpm4, ZNCPM4, float); //! PM4 ZNC // o2-linter: disable=name/o2-column -DECLARE_SOA_COLUMN(ZNCtdc, ZNCTDC, float); //! TDC ZNC // o2-linter: disable=name/o2-column - +DECLARE_SOA_COLUMN(ZNApmc, commonPMZNA, float); //! PMC ZNA // o2-linter: disable=name/o2-column +DECLARE_SOA_COLUMN(ZNApm1, ZNAPM1, float); //! PM1 ZNA // o2-linter: disable=name/o2-column +DECLARE_SOA_COLUMN(ZNApm2, ZNAPM2, float); //! PM2 ZNA // o2-linter: disable=name/o2-column +DECLARE_SOA_COLUMN(ZNApm3, ZNAPM3, float); //! PM3 ZNA // o2-linter: disable=name/o2-column +DECLARE_SOA_COLUMN(ZNApm4, ZNAPM4, float); //! PM4 ZNA // o2-linter: disable=name/o2-column +DECLARE_SOA_COLUMN(ZNAtdc, ZNATDC, float); //! TDC ZNA // o2-linter: disable=name/o2-column +DECLARE_SOA_COLUMN(ZNCpmc, commonPMZNC, float); //! PMC ZNC // o2-linter: disable=name/o2-column +DECLARE_SOA_COLUMN(ZNCpm1, ZNCPM1, float); //! PM1 ZNC // o2-linter: disable=name/o2-column +DECLARE_SOA_COLUMN(ZNCpm2, ZNCPM2, float); //! PM2 ZNC // o2-linter: disable=name/o2-column +DECLARE_SOA_COLUMN(ZNCpm3, ZNCPM3, float); //! PM3 ZNC // o2-linter: disable=name/o2-column +DECLARE_SOA_COLUMN(ZNCpm4, ZNCPM4, float); //! PM4 ZNC // o2-linter: disable=name/o2-column +DECLARE_SOA_COLUMN(ZNCtdc, ZNCTDC, float); //! TDC ZNC // o2-linter: disable=name/o2-column +DECLARE_SOA_COLUMN(Centrality, centrality, float); //! Centrality +DECLARE_SOA_COLUMN(Timestamp, timestamp, uint64_t); //! Timestamp +DECLARE_SOA_COLUMN(SelectionBits, selectionBits, uint8_t); //! Selection Flags } // namespace znoutput DECLARE_SOA_TABLE(ZDCInterCalib, "AOD", "ZDCIC", o2::soa::Index<>, @@ -49,7 +51,10 @@ DECLARE_SOA_TABLE(ZDCInterCalib, "AOD", "ZDCIC", o2::soa::Index<>, znoutput::ZNCpm2, znoutput::ZNCpm3, znoutput::ZNCpm4, - znoutput::ZNCtdc); + znoutput::ZNCtdc, + znoutput::Centrality, + znoutput::Timestamp, + znoutput::SelectionBits); } // namespace o2::aod #endif // COMMON_DATAMODEL_ZDCINTERCALIB_H_ diff --git a/Common/TableProducer/CMakeLists.txt b/Common/TableProducer/CMakeLists.txt index 1d6918d6121..d2d59ea2506 100644 --- a/Common/TableProducer/CMakeLists.txt +++ b/Common/TableProducer/CMakeLists.txt @@ -125,8 +125,8 @@ o2physics_add_dpl_workflow(match-mft-ft0 O2::DetectorsBase O2::DetectorsCommonDataFormats COMPONENT_NAME Analysis) -o2physics_add_dpl_workflow(zdc-task-intercalib - SOURCES zdc-task-intercalib.cxx +o2physics_add_dpl_workflow(zdc-task-inter-calib + SOURCES zdcTaskInterCalib.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore COMPONENT_NAME Analysis) diff --git a/Common/TableProducer/zdc-task-intercalib.cxx b/Common/TableProducer/zdcTaskInterCalib.cxx similarity index 53% rename from Common/TableProducer/zdc-task-intercalib.cxx rename to Common/TableProducer/zdcTaskInterCalib.cxx index 77b590bde57..78054580b81 100644 --- a/Common/TableProducer/zdc-task-intercalib.cxx +++ b/Common/TableProducer/zdcTaskInterCalib.cxx @@ -9,12 +9,10 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -/// \file zdc-task-intercalib.cxx +/// \file zdcTaskInterCalib.cxx /// \brief Task for ZDC tower inter-calibration /// \author chiara.oppedisano@cern.ch -// o2-linter: disable=name/workflow-file -// o2-linter: disable=name/file-cpp #include "Framework/AnalysisTask.h" #include "Framework/AnalysisDataModel.h" #include "Framework/HistogramRegistry.h" @@ -35,9 +33,9 @@ using namespace o2::framework::expressions; using namespace o2::aod::evsel; using BCsRun3 = soa::Join; -using ColEvSels = soa::Join; +using ColEvSels = soa::Join; -struct ZDCCalibTower { +struct ZdcTaskInterCalib { Produces zTab; @@ -48,9 +46,32 @@ struct ZDCCalibTower { Configurable tdcCut{"tdcCut", false, "Flag for TDC cut"}; Configurable tdcZNmincut{"tdcZNmincut", -2.5, "Min ZN TDC cut"}; Configurable tdcZNmaxcut{"tdcZNmaxcut", -2.5, "Max ZN TDC cut"}; + // Event selections + Configurable cfgEvSelSel8{"cfgEvSelSel8", true, "Event selection: sel8"}; + Configurable cfgEvSelVtxZ{"cfgEvSelVtxZ", 10, "Event selection: zVtx"}; + Configurable cfgEvSelsDoOccupancySel{"cfgEvSelsDoOccupancySel", true, "Event selection: do occupancy selection"}; + Configurable cfgEvSelsMaxOccupancy{"cfgEvSelsMaxOccupancy", 10000, "Event selection: set max occupancy"}; + Configurable cfgEvSelsNoSameBunchPileupCut{"cfgEvSelsNoSameBunchPileupCut", true, "Event selection: no same bunch pileup cut"}; + Configurable cfgEvSelsIsGoodZvtxFT0vsPV{"cfgEvSelsIsGoodZvtxFT0vsPV", true, "Event selection: is good ZVTX FT0 vs PV"}; + Configurable cfgEvSelsNoCollInTimeRangeStandard{"cfgEvSelsNoCollInTimeRangeStandard", true, "Event selection: no collision in time range standard"}; + Configurable cfgEvSelsIsVertexITSTPC{"cfgEvSelsIsVertexITSTPC", true, "Event selection: is vertex ITSTPC"}; + Configurable cfgEvSelsIsGoodITSLayersAll{"cfgEvSelsIsGoodITSLayersAll", true, "Event selection: is good ITS layers all"}; // HistogramRegistry registry{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + enum SelectionCriteria { + evSel_zvtx, + evSel_sel8, + evSel_occupancy, + evSel_kNoSameBunchPileup, + evSel_kIsGoodZvtxFT0vsPV, + evSel_kNoCollInTimeRangeStandard, + evSel_kIsVertexITSTPC, + evSel_kIsGoodITSLayersAll, + evSel_allEvents, + nEventSelections + }; + void init(InitContext const&) { registry.add("ZNApmc", "ZNApmc; ZNA PMC; Entries", {HistType::kTH1F, {{nBins, -0.5, maxZN}}}); @@ -65,16 +86,93 @@ struct ZDCCalibTower { registry.add("ZNCpm4", "ZNCpm4; ZNC PM4; Entries", {HistType::kTH1F, {{nBins, -0.5, maxZN}}}); registry.add("ZNAsumq", "ZNAsumq; ZNA uncalib. sum PMQ; Entries", {HistType::kTH1F, {{nBins, -0.5, maxZN}}}); registry.add("ZNCsumq", "ZNCsumq; ZNC uncalib. sum PMQ; Entries", {HistType::kTH1F, {{nBins, -0.5, maxZN}}}); + + 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, "kkIsGoodITSLayersAll"); + } + + template + uint8_t eventSelected(TCollision collision) + { + uint8_t selectionBits = 0; + bool selected; + + registry.fill(HIST("hEventCount"), evSel_allEvents); + + selected = std::fabs(collision.posZ()) < cfgEvSelVtxZ; + if (selected) { + selectionBits |= (uint8_t)(0x1u << evSel_zvtx); + registry.fill(HIST("hEventCount"), evSel_zvtx); + } + + selected = collision.sel8(); + if (selected) { + selectionBits |= (uint8_t)(0x1u << evSel_sel8); + registry.fill(HIST("hEventCount"), evSel_sel8); + } + + auto occupancy = collision.trackOccupancyInTimeRange(); + selected = occupancy <= cfgEvSelsMaxOccupancy; + if (selected) { + selectionBits |= (uint8_t)(0x1u << evSel_occupancy); + registry.fill(HIST("hEventCount"), evSel_occupancy); + } + + selected = collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup); + if (selected) { + selectionBits |= (uint8_t)(0x1u << evSel_kNoSameBunchPileup); + registry.fill(HIST("hEventCount"), evSel_kNoSameBunchPileup); + } + + selected = collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV); + if (selected) { + selectionBits |= (uint8_t)(0x1u << evSel_kIsGoodZvtxFT0vsPV); + registry.fill(HIST("hEventCount"), evSel_kIsGoodZvtxFT0vsPV); + } + + selected = collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard); + if (selected) { + selectionBits |= (uint8_t)(0x1u << evSel_kNoCollInTimeRangeStandard); + registry.fill(HIST("hEventCount"), evSel_kNoCollInTimeRangeStandard); + } + + selected = collision.selection_bit(o2::aod::evsel::kIsVertexITSTPC); + if (selected) { + selectionBits |= (uint8_t)(0x1u << evSel_kIsVertexITSTPC); + registry.fill(HIST("hEventCount"), evSel_kIsVertexITSTPC); + } + + selected = collision.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll); + if (selected) { + selectionBits |= (uint8_t)(0x1u << evSel_kIsGoodITSLayersAll); + registry.fill(HIST("hEventCount"), evSel_kIsGoodITSLayersAll); + } + + return selectionBits; } void process(ColEvSels const& cols, BCsRun3 const& /*bcs*/, aod::Zdcs const& /*zdcs*/) { // collision-based event selection + int nTowers = 4; // number of ZDC towers + for (auto const& collision : cols) { const auto& foundBC = collision.foundBC_as(); if (foundBC.has_zdc()) { const auto& zdc = foundBC.zdc(); + uint8_t evSelection = eventSelected(collision); + + float centrality = collision.centFT0C(); + // To assure that ZN have a genuine signal (tagged by the relative TDC) // we can check that the amplitude is >0 or that ADC is NOT very negative (-inf) @@ -117,7 +215,7 @@ struct ZDCCalibTower { }; // if (isZNChit) { - for (int it = 0; it < 4; it++) { + for (int it = 0; it < nTowers; it++) { pmqZNC[it] = (zdc.energySectorZNC())[it]; sumZNC += pmqZNC[it]; } @@ -129,7 +227,7 @@ struct ZDCCalibTower { registry.get(HIST("ZNCsumq"))->Fill(sumZNC); } if (isZNAhit) { - for (int it = 0; it < 4; it++) { + for (int it = 0; it < nTowers; it++) { pmqZNA[it] = (zdc.energySectorZNA())[it]; sumZNA += pmqZNA[it]; } @@ -142,7 +240,7 @@ struct ZDCCalibTower { registry.get(HIST("ZNAsumq"))->Fill(sumZNA); } if (isZNAhit || isZNChit) - zTab(pmcZNA, pmqZNA[0], pmqZNA[1], pmqZNA[2], pmqZNA[3], tdcZNC, pmcZNC, pmqZNC[0], pmqZNC[1], pmqZNC[2], pmqZNC[3], tdcZNA); + zTab(pmcZNA, pmqZNA[0], pmqZNA[1], pmqZNA[2], pmqZNA[3], tdcZNC, pmcZNC, pmqZNC[0], pmqZNC[1], pmqZNC[2], pmqZNC[3], tdcZNA, centrality, foundBC.timestamp(), evSelection); } } } @@ -151,5 +249,5 @@ struct ZDCCalibTower { WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) // o2-linter: disable=name/file-cpp { return WorkflowSpec{ - adaptAnalysisTask(cfgc)}; + adaptAnalysisTask(cfgc)}; } From 04295d717f1f52ab2414494e5b388e9fa7de9d42 Mon Sep 17 00:00:00 2001 From: Francesco Mazzaschi <43742195+fmazzasc@users.noreply.github.com> Date: Thu, 12 Jun 2025 18:02:14 +0200 Subject: [PATCH 047/871] Add flag to disable its rof cut (#11572) Co-authored-by: Francesco Mazzaschi --- PWGLF/TableProducer/Nuspex/hyperRecoTask.cxx | 51 ++++++++++---------- 1 file changed, 26 insertions(+), 25 deletions(-) diff --git a/PWGLF/TableProducer/Nuspex/hyperRecoTask.cxx b/PWGLF/TableProducer/Nuspex/hyperRecoTask.cxx index 09ed3ec07b8..5a8624e50e1 100644 --- a/PWGLF/TableProducer/Nuspex/hyperRecoTask.cxx +++ b/PWGLF/TableProducer/Nuspex/hyperRecoTask.cxx @@ -11,39 +11,39 @@ // // Build hypertriton candidates from V0s and tracks -#include -#include -#include -#include -#include +#include "PWGLF/DataModel/EPCalibrationTables.h" +#include "PWGLF/DataModel/LFHypernucleiTables.h" +#include "PWGLF/Utils/svPoolCreator.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.h" -#include "ReconstructionDataFormats/Track.h" +#include "Common/Core/PID/PIDTOF.h" +#include "Common/Core/PID/TPCPIDResponse.h" #include "Common/Core/RecoDecay.h" #include "Common/Core/trackUtilities.h" +#include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/Centrality.h" -#include "PWGLF/DataModel/EPCalibrationTables.h" -#include "DetectorsBase/Propagator.h" -#include "DetectorsBase/GeometryManager.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "CCDB/BasicCCDBManager.h" - +#include "Common/TableProducer/PID/pidTOFBase.h" #include "EventFiltering/Zorro.h" #include "EventFiltering/ZorroSummary.h" -#include "Common/Core/PID/TPCPIDResponse.h" -#include "Common/Core/PID/PIDTOF.h" -#include "Common/TableProducer/PID/pidTOFBase.h" -#include "DataFormatsTPC/BetheBlochAleph.h" +#include "CCDB/BasicCCDBManager.h" #include "DCAFitter/DCAFitterN.h" -#include "PWGLF/Utils/svPoolCreator.h" -#include "PWGLF/DataModel/LFHypernucleiTables.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "DataFormatsParameters/GRPObject.h" +#include "DataFormatsTPC/BetheBlochAleph.h" +#include "DetectorsBase/GeometryManager.h" +#include "DetectorsBase/Propagator.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" +#include "ReconstructionDataFormats/Track.h" + +#include +#include +#include +#include +#include using namespace o2; using namespace o2::framework; @@ -168,6 +168,7 @@ struct hyperRecoTask { Configurable useCustomVertexer{"useCustomVertexer", false, "Use custom vertexer"}; Configurable skipAmbiTracks{"skipAmbiTracks", false, "Skip ambiguous tracks"}; + Configurable disableITSROFCut{"disableITSROFCut", false, "Disable ITS ROC cut for event selection"}; Configurable customVertexerTimeMargin{"customVertexerTimeMargin", 800, "Time margin for custom vertexer (ns)"}; Configurable> cfgBetheBlochParams{"cfgBetheBlochParams", {betheBlochDefault[0], 1, 6, particleName, betheBlochParNames}, "TPC Bethe-Bloch parameterisation for He3"}; Configurable cfgCompensatePIDinTracking{"cfgCompensatePIDinTracking", true, "If true, divide tpcInnerParam by the electric charge"}; @@ -341,7 +342,7 @@ struct hyperRecoTask { initCCDB(bc); hEvents->Fill(0.); - if (!collision.selection_bit(aod::evsel::kNoITSROFrameBorder)) { + if (!collision.selection_bit(aod::evsel::kNoITSROFrameBorder) && !disableITSROFCut) { continue; } From 40a494d560189e38a91304dd1b90bf6e9bd6bb05 Mon Sep 17 00:00:00 2001 From: Artem Kotliarov <71133985+KotliarovAr@users.noreply.github.com> Date: Thu, 12 Jun 2025 18:44:43 +0200 Subject: [PATCH 048/871] [PWGJE] PWGJE Change scheme for outlier removal (#11577) --- PWGJE/Tasks/recoilJets.cxx | 117 +++++++++++++++++++++---------------- 1 file changed, 67 insertions(+), 50 deletions(-) diff --git a/PWGJE/Tasks/recoilJets.cxx b/PWGJE/Tasks/recoilJets.cxx index f39d1c9fe25..26abd49517a 100644 --- a/PWGJE/Tasks/recoilJets.cxx +++ b/PWGJE/Tasks/recoilJets.cxx @@ -13,35 +13,33 @@ /// \file recoilJets.cxx /// \brief hadron-jet correlation analysis -#include -#include -#include +#include "PWGJE/Core/FastJetUtilities.h" +#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include "PWGJE/Core/JetFinder.h" +#include "PWGJE/Core/JetFindingUtilities.h" +#include "PWGJE/DataModel/Jet.h" -#include "TRandom3.h" -#include "TVector2.h" +#include "Common/Core/RecoDecay.h" +#include "Common/Core/TrackSelection.h" +#include "Common/Core/TrackSelectionDefaults.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "EventFiltering/filterTables.h" +#include "CommonConstants/MathConstants.h" #include "Framework/ASoA.h" #include "Framework/AnalysisDataModel.h" #include "Framework/AnalysisTask.h" -#include "Framework/O2DatabasePDGPlugin.h" #include "Framework/HistogramRegistry.h" +#include "Framework/O2DatabasePDGPlugin.h" #include "Framework/runDataProcessing.h" -#include "CommonConstants/MathConstants.h" -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectionDefaults.h" -#include "Common/Core/RecoDecay.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" - -#include "PWGJE/Core/FastJetUtilities.h" -#include "PWGJE/Core/JetFinder.h" -#include "PWGJE/Core/JetFindingUtilities.h" -#include "PWGJE/DataModel/Jet.h" - -#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include "TRandom3.h" +#include "TVector2.h" -#include "EventFiltering/filterTables.h" +#include +#include +#include using namespace o2; using namespace o2::framework; @@ -82,7 +80,6 @@ struct RecoilJets { // List of configurable parameters for MC Configurable pTHatExponent{"pTHatExponent", 4.0, "Exponent of the event weight for the calculation of pTHat"}; Configurable pTHatMax{"pTHatMax", 999.0, "Maximum fraction of hard scattering for jet acceptance in MC"}; - Configurable pTHatMaxTrack{"pTHatMaxTrack", 999.0, "Maximum fraction of hard scattering for track acceptance in MC"}; // Parameters for recoil jet selection Configurable ptTTrefMin{"ptTTrefMin", 5., "Minimum pT of reference TT"}; @@ -130,17 +127,29 @@ struct RecoilJets { void init(InitContext const&) { - eventSelectionBits = jetderiveddatautilities::initialiseEventSelectionBits(static_cast(evSel)); - trackSelection = jetderiveddatautilities::initialiseTrackSelection(static_cast(trkSel)); + std::string evSelToString = static_cast(evSel); + std::string trkSelToString = static_cast(trkSel); + + eventSelectionBits = jetderiveddatautilities::initialiseEventSelectionBits(evSelToString); + trackSelection = jetderiveddatautilities::initialiseTrackSelection(trkSelToString); triggerMaskBits = jetderiveddatautilities::initialiseTriggerMaskBits(triggerMasks); // List of raw and MC det. distributions if (doprocessData || doprocessMCDetLevel || doprocessMCDetLevelWeighted) { + spectra.add("hEventSelectionCount", "Count # of events in the analysis", kTH1F, {{3, 0.0, 3.}}); + spectra.get(HIST("hEventSelectionCount"))->GetXaxis()->SetBinLabel(1, "Total # of events"); + spectra.get(HIST("hEventSelectionCount"))->GetXaxis()->SetBinLabel(2, Form("# of events after sel. %s", evSelToString.data())); + spectra.get(HIST("hEventSelectionCount"))->GetXaxis()->SetBinLabel(3, "# of events w. outlier"); + spectra.add("vertexZ", "Z vertex of collisions", kTH1F, {{60, -12., 12.}}); spectra.add("hHasAssocMcCollision", "Has det. level coll. associat. MC coll.", kTH1F, {{2, 0.0, 2.}}); spectra.get(HIST("hHasAssocMcCollision"))->GetXaxis()->SetBinLabel(1, "Yes"); spectra.get(HIST("hHasAssocMcCollision"))->GetXaxis()->SetBinLabel(2, "No"); + spectra.add("hTrackSelectionCount", "Count # of tracks in the analysis", kTH1F, {{2, 0.0, 2.}}); + spectra.get(HIST("hTrackSelectionCount"))->GetXaxis()->SetBinLabel(1, "Total # of tracks"); + spectra.get(HIST("hTrackSelectionCount"))->GetXaxis()->SetBinLabel(2, Form("# of tracks after sel. %s", trkSelToString.data())); + spectra.add("hTrackPtEtaPhi", "Charact. of tracks", kTH3F, {pT, pseudorap, phiAngle}); spectra.add("hTTSig_pT", "pT spectrum of all found TT_{Sig} cand.", kTH1F, {{40, 10., 50.}}); // needed to distinguish merged data from diff. wagons @@ -228,28 +237,33 @@ struct RecoilJets { // Fill histograms with raw or MC det. level data template - void fillHistograms(Collision const& collision, Jets const& jets, Tracks const& tracks, bool bIsMC = false, float weight = 1.) + void fillHistograms(Collision const& collision, Jets const& jets, Tracks const& tracks, float weight = 1.) { - bool bSigEv = false; std::vector vPhiOfTT; double phiTT = 0.; int nTT = 0; - float pTHat = 0.; - if (bIsMC) - pTHat = getPtHat(weight); + float pTHat = getPtHat(weight); auto dice = rand->Rndm(); if (dice < fracSig) bSigEv = true; + // Remove whole event if jet passes the outlier removal condition + for (const auto& jet : jets) { + if (jet.pt() > pTHatMax * pTHat) { + spectra.fill(HIST("hEventSelectionCount"), 2.5); + return; + } + } + for (const auto& track : tracks) { - if (skipTrack(track)) - continue; + spectra.fill(HIST("hTrackSelectionCount"), 0.5); - if (bIsMC && (track.pt() > pTHatMaxTrack * pTHat)) + if (skipTrack(track)) continue; + spectra.fill(HIST("hTrackSelectionCount"), 1.5); spectra.fill(HIST("hTrackPtEtaPhi"), track.pt(), track.eta(), track.phi(), weight); // Search for TT candidate @@ -279,10 +293,6 @@ struct RecoilJets { } for (const auto& jet : jets) { - - if (bIsMC && (jet.pt() > pTHatMax * pTHat)) - continue; - spectra.fill(HIST("hJetPtEtaPhiRhoArea"), jet.pt(), jet.eta(), jet.phi(), collision.rho(), jet.area(), weight); if (nTT > 0) { @@ -327,6 +337,11 @@ struct RecoilJets { if (dice < fracSig) bSigEv = true; + for (const auto& jet : jets) { + if (jet.pt() > pTHatMax * pTHat) + return; + } + for (const auto& particle : particles) { auto pdgParticle = pdg->GetParticle(particle.pdgCode()); if (!pdgParticle) @@ -337,9 +352,6 @@ struct RecoilJets { if (bParticleNeutral || !particle.isPhysicalPrimary()) continue; - if (particle.pt() > pTHatMaxTrack * pTHat) - continue; - spectra.fill(HIST("hPartPtEtaPhi"), particle.pt(), particle.eta(), particle.phi(), weight); if (bSigEv && (particle.pt() > ptTTsigMin && particle.pt() < ptTTsigMax)) { @@ -367,10 +379,6 @@ struct RecoilJets { } for (const auto& jet : jets) { - - if (jet.pt() > pTHatMax * pTHat) - continue; - spectra.fill(HIST("hJetPtEtaPhiRhoArea_Part"), jet.pt(), jet.eta(), jet.phi(), collision.rho(), jet.area(), weight); if (nTT > 0) { @@ -410,13 +418,15 @@ struct RecoilJets { double phiTTSig = 0.; float pTHat = getPtHat(weight); + for (const auto& jetBase : jetsBase) { + if (jetBase.pt() > pTHatMax * pTHat) + return; + } + for (const auto& track : tracks) { if (skipTrack(track)) continue; - if (track.pt() > pTHatMaxTrack * pTHat) - continue; - if (track.pt() > ptTTsigMin && track.pt() < ptTTsigMax) { vPhiOfTT.push_back(track.phi()); } @@ -428,9 +438,6 @@ struct RecoilJets { phiTTSig = getPhiTT(vPhiOfTT); for (const auto& jetBase : jetsBase) { - if (jetBase.pt() > pTHatMax * pTHat) - continue; - bool bIsBaseJetRecoil = get<1>(isRecoilJet(jetBase, phiTTSig)) && bIsThereTTSig; dataForUnfolding(jetBase, jetsTag, bIsBaseJetRecoil, weight); } @@ -440,9 +447,13 @@ struct RecoilJets { FilteredTracks const& tracks, FilteredJets const& jets) { + spectra.fill(HIST("hEventSelectionCount"), 0.5); + if (skipEvent(collision)) return; + spectra.fill(HIST("hEventSelectionCount"), 1.5); + spectra.fill(HIST("vertexZ"), collision.posZ()); fillHistograms(collision, jets, tracks); } @@ -452,11 +463,14 @@ struct RecoilJets { FilteredTracks const& tracks, FilteredJetsDetLevel const& jets) { + spectra.fill(HIST("hEventSelectionCount"), 0.5); if (skipEvent(collision) || skipMBGapEvent(collision)) return; + spectra.fill(HIST("hEventSelectionCount"), 1.5); + spectra.fill(HIST("vertexZ"), collision.posZ()); - fillHistograms(collision, jets, tracks, true); + fillHistograms(collision, jets, tracks); } PROCESS_SWITCH(RecoilJets, processMCDetLevel, "process MC detector level", false); @@ -465,9 +479,12 @@ struct RecoilJets { FilteredTracks const& tracks, FilteredJetsDetLevel const& jets) { + spectra.fill(HIST("hEventSelectionCount"), 0.5); if (skipEvent(collision) || skipMBGapEvent(collision)) return; + spectra.fill(HIST("hEventSelectionCount"), 1.5); + auto weight = collision.mcCollision().weight(); spectra.fill(HIST("vertexZ"), collision.posZ(), weight); @@ -477,7 +494,7 @@ struct RecoilJets { spectra.fill(HIST("hHasAssocMcCollision"), 1.5, weight); } - fillHistograms(collision, jets, tracks, true, weight); + fillHistograms(collision, jets, tracks, weight); } PROCESS_SWITCH(RecoilJets, processMCDetLevelWeighted, "process MC detector level with event weight", false); From 457296919c8401eda53e0623efce4e9600b66e74 Mon Sep 17 00:00:00 2001 From: prottayCMT <61418725+prottayCMT@users.noreply.github.com> Date: Thu, 12 Jun 2025 20:17:27 +0200 Subject: [PATCH 049/871] [PWGLF] adjusted size of 2D array for mixing in derived data (#11583) Co-authored-by: Prottay Das --- PWGLF/Tasks/Strangeness/taskLambdaSpinCorr.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/PWGLF/Tasks/Strangeness/taskLambdaSpinCorr.cxx b/PWGLF/Tasks/Strangeness/taskLambdaSpinCorr.cxx index 33157c327bf..be85c214406 100644 --- a/PWGLF/Tasks/Strangeness/taskLambdaSpinCorr.cxx +++ b/PWGLF/Tasks/Strangeness/taskLambdaSpinCorr.cxx @@ -985,8 +985,8 @@ struct LfTaskLambdaSpinCorr { auto groupV02 = V0s.sliceBy(tracksPerCollisionV0Mixed, collision1.index()); auto groupV03 = V0s.sliceBy(tracksPerCollisionV0Mixed, collision2.index()); - size_t rows = groupV03.size() + 20; - size_t cols = groupV01.size() + 20; + size_t rows = groupV03.size() + 1600; + size_t cols = groupV01.size() + 1600; std::vector> pairStatus(rows, std::vector(cols, false)); histos.fill(HIST("hv0Mult"), groupV01.size()); for (auto& [t1, t2] : soa::combinations(o2::soa::CombinationsFullIndexPolicy(groupV01, groupV02))) { From 85e9628eb14097938a991480d75aa4f84ad1f5ef Mon Sep 17 00:00:00 2001 From: Zhiyong <71517277+Luzhiyongg@users.noreply.github.com> Date: Fri, 13 Jun 2025 03:20:06 +0800 Subject: [PATCH 050/871] [PWGCF] add TPC cross row (#11574) --- PWGCF/Flow/Tasks/flowTask.cxx | 6 ++- .../Tasks/diHadronCor.cxx | 39 ++++++++++++------- 2 files changed, 29 insertions(+), 16 deletions(-) diff --git a/PWGCF/Flow/Tasks/flowTask.cxx b/PWGCF/Flow/Tasks/flowTask.cxx index 4390131be3a..7477aa90aed 100644 --- a/PWGCF/Flow/Tasks/flowTask.cxx +++ b/PWGCF/Flow/Tasks/flowTask.cxx @@ -65,7 +65,8 @@ struct FlowTask { O2_DEFINE_CONFIGURABLE(cfgCutPtMax, float, 10.0f, "Maximal pT for all tracks") O2_DEFINE_CONFIGURABLE(cfgCutEta, float, 0.8f, "Eta range for tracks") O2_DEFINE_CONFIGURABLE(cfgCutChi2prTPCcls, float, 2.5f, "max chi2 per TPC clusters") - O2_DEFINE_CONFIGURABLE(cfgCutTPCclu, float, 70.0f, "minimum 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(cfgCutDCAxyppPass3Enabled, bool, false, "switch of ppPass3 DCAxy pt dependent cut") @@ -477,6 +478,7 @@ struct FlowTask { myTrackSel = getGlobalTrackSelectionRun3ITSMatch(TrackSelection::GlobalTrackRun3ITSMatching::Run3ITSibAny, TrackSelection::GlobalTrackRun3DCAxyCut::Default); myTrackSel.SetMinNClustersTPC(cfgCutTPCclu); + myTrackSel.SetMinNCrossedRowsTPC(cfgCutTPCCrossedRows); myTrackSel.SetMinNClustersITS(cfgCutITSclu); if (cfgCutDCAxyppPass3Enabled) myTrackSel.SetMaxDcaXYPtDep([](float pt) { return 0.004f + 0.013f / pt; }); // Tuned on the LHC22f anchored MC LHC23d1d on primary pions. 7 Sigmas of the resolution @@ -686,7 +688,7 @@ struct FlowTask { if (cfgTrkSelSwitch) { return myTrackSel.IsSelected(track); } else { - return ((track.tpcNClsFound() >= cfgCutTPCclu) && (track.itsNCls() >= cfgCutITSclu)); + return ((track.tpcNClsFound() >= cfgCutTPCclu) && (track.tpcNClsCrossedRows() >= cfgCutTPCCrossedRows) && (track.itsNCls() >= cfgCutITSclu)); } } diff --git a/PWGCF/TwoParticleCorrelations/Tasks/diHadronCor.cxx b/PWGCF/TwoParticleCorrelations/Tasks/diHadronCor.cxx index 189e201ef68..e79c61b3096 100644 --- a/PWGCF/TwoParticleCorrelations/Tasks/diHadronCor.cxx +++ b/PWGCF/TwoParticleCorrelations/Tasks/diHadronCor.cxx @@ -62,7 +62,8 @@ struct DiHadronCor { 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, 70.0f, "minimum 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(cfgCutMerging, float, 0.0, "Merging cut on track merge") @@ -242,7 +243,11 @@ struct DiHadronCor { LOGF(fatal, "Full simulation and on-the-fly processing of mixed event not supported"); } if (doprocessMCSame || doprocessOntheflySame) { - registry.add("MCTrue/MCeventcount", "MCeventcount", {HistType::kTH1F, {{4, 0, 4, "bin"}}}); // histogram to see how many events are in the same and mixed event + 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", hCentTitle.c_str(), {HistType::kTH1D, {axisCentrality}}); registry.add("MCTrue/MCNch", "N_{ch}", {HistType::kTH1D, {axisMultiplicity}}); registry.add("MCTrue/MCzVtx", "MCzVtx", {HistType::kTH1D, {axisVertex}}); @@ -254,13 +259,15 @@ struct DiHadronCor { registry.add("MCTrue/MCdeltaEta_deltaPhi_mixed", "", {HistType::kTH2D, {axisDeltaPhi, axisDeltaEta}}); } if (doprocessMCEfficiency) { - registry.add("MCEffeventcount", "bin", {HistType::kTH1F, {{4, 0, 4, "bin"}}}); - registry.get(HIST("MCEffeventcount"))->GetXaxis()->SetBinLabel(1, "MC"); - registry.get(HIST("MCEffeventcount"))->GetXaxis()->SetBinLabel(2, "Reco Primary"); - registry.get(HIST("MCEffeventcount"))->GetXaxis()->SetBinLabel(3, "Reco All"); - registry.get(HIST("MCEffeventcount"))->GetXaxis()->SetBinLabel(4, "Fake"); + registry.add("MCEffeventcount", "bin", {HistType::kTH1F, {{5, 0, 5, "bin"}}}); + registry.get(HIST("MCEffeventcount"))->GetXaxis()->SetBinLabel(1, "All"); + registry.get(HIST("MCEffeventcount"))->GetXaxis()->SetBinLabel(2, "MC"); + registry.get(HIST("MCEffeventcount"))->GetXaxis()->SetBinLabel(3, "Reco Primary"); + registry.get(HIST("MCEffeventcount"))->GetXaxis()->SetBinLabel(4, "Reco All"); + registry.get(HIST("MCEffeventcount"))->GetXaxis()->SetBinLabel(5, "Fake"); } + LOGF(info, "Initializing correlation container"); std::vector corrAxis = {{axisSample, "Sample"}, {axisVertex, "z-vtx (cm)"}, {axisPtTrigger, "p_{T} (GeV/c)"}, @@ -276,6 +283,8 @@ struct DiHadronCor { same.setObject(new CorrelationContainer("sameEvent", "sameEvent", corrAxis, effAxis, userAxis)); mixed.setObject(new CorrelationContainer("mixedEvent", "mixedEvent", corrAxis, effAxis, userAxis)); + + LOGF(info, "End of init"); } int getMagneticField(uint64_t timestamp) @@ -319,7 +328,7 @@ struct DiHadronCor { template bool trackSelected(TTrack track) { - return ((track.tpcNClsFound() >= cfgCutTPCclu) && (track.itsNCls() >= cfgCutITSclu)); + return ((track.tpcNClsFound() >= cfgCutTPCclu) && (track.tpcNClsCrossedRows() >= cfgCutTPCCrossedRows) && (track.itsNCls() >= cfgCutITSclu)); } template @@ -727,13 +736,14 @@ struct DiHadronCor { void processMCEfficiency(FilteredMcCollisions::iterator const& mcCollision, soa::SmallGroups> const& collisions, FilteredMcParticles const& mcParticles, FilteredTracksWithMCLabels const& tracks) { - if (cfgSelCollByNch && (tracks.size() < cfgCutMultMin || tracks.size() >= cfgCutMultMax)) { + registry.fill(HIST("MCEffeventcount"), 0.5); + if (cfgSelCollByNch && (mcParticles.size() < cfgCutMultMin || mcParticles.size() >= cfgCutMultMax)) { return; } // Primaries for (const auto& mcParticle : mcParticles) { if (mcParticle.isPhysicalPrimary()) { - registry.fill(HIST("MCEffeventcount"), 0.5); + registry.fill(HIST("MCEffeventcount"), 1.5); same->getTrackHistEfficiency()->Fill(CorrelationContainer::MC, mcParticle.eta(), mcParticle.pt(), getSpecies(mcParticle.pdgCode()), 0., mcCollision.posZ()); } } @@ -746,16 +756,16 @@ struct DiHadronCor { for (const auto& track : groupedTracks) { if (track.has_mcParticle()) { - const auto& mcParticle = track.mcParticle(); + auto mcParticle = track.mcParticle(); if (mcParticle.isPhysicalPrimary()) { - registry.fill(HIST("MCEffeventcount"), 1.5); + registry.fill(HIST("MCEffeventcount"), 2.5); same->getTrackHistEfficiency()->Fill(CorrelationContainer::RecoPrimaries, mcParticle.eta(), mcParticle.pt(), getSpecies(mcParticle.pdgCode()), 0., mcCollision.posZ()); } - registry.fill(HIST("MCEffeventcount"), 2.5); + registry.fill(HIST("MCEffeventcount"), 3.5); same->getTrackHistEfficiency()->Fill(CorrelationContainer::RecoAll, mcParticle.eta(), mcParticle.pt(), getSpecies(mcParticle.pdgCode()), 0., mcCollision.posZ()); } else { // fake track - registry.fill(HIST("MCEffeventcount"), 3.5); + registry.fill(HIST("MCEffeventcount"), 4.5); same->getTrackHistEfficiency()->Fill(CorrelationContainer::Fake, track.eta(), track.pt(), 0, 0., mcCollision.posZ()); } } @@ -858,6 +868,7 @@ struct DiHadronCor { continue; } + registry.fill(HIST("MCTrue/MCeventcount"), 4.5); fillMCCorrelations(tracks1, tracks2, collision1.posZ(), MixedEvent, eventWeight); } } From fd1043542ebcdfd15a4d051810ac04d03620cc26 Mon Sep 17 00:00:00 2001 From: dajones2 <140733426+dajones2@users.noreply.github.com> Date: Thu, 12 Jun 2025 21:20:09 +0100 Subject: [PATCH 051/871] [PWGJE] Fixing recoil jet response to fill with delta phi (#11578) --- PWGJE/Tasks/jetHadronRecoil.cxx | 108 ++++++++++++++++++++++---------- 1 file changed, 75 insertions(+), 33 deletions(-) diff --git a/PWGJE/Tasks/jetHadronRecoil.cxx b/PWGJE/Tasks/jetHadronRecoil.cxx index 71946c49aee..97cd31cfb5c 100644 --- a/PWGJE/Tasks/jetHadronRecoil.cxx +++ b/PWGJE/Tasks/jetHadronRecoil.cxx @@ -446,17 +446,6 @@ struct JetHadronRecoil { return; } - for (const auto& mcdjetWTA : mcdjetsWTA) { - double djet = RecoDecay::sqrtSumOfSquares(RecoDecay::constrainAngle(jetBase.phi() - mcdjetWTA.phi(), -o2::constants::math::PI), jetBase.eta() - mcdjetWTA.eta()); - if (mcdjetWTA.pt() > pTHatMaxMCD * pTHat) { - continue; - } - if (djet < 0.6 * jetR) { - dR = djet; - break; - } - } - dR = getWTAaxisDifference(jetBase, mcdjetsWTA, tracks, true); if (jetBase.has_matchedJetGeo()) { @@ -481,6 +470,77 @@ struct JetHadronRecoil { } } + template + void fillRecoilJetMatchedHistograms(T const& jetsBase, V const& mcdjetsWTA, W const& mcpjetsWTA, U const&, X const& tracks, Y const& particles, float weight = 1.0, float rho = 0.0) + { + std::vector phiTTAr; + std::vector phiTTArPart; + double phiTT = 0; + double phiTTPart = 0; + int trigNumber = 0; + int nTT = 0; + float pTHat = 10. / (std::pow(weight, 1.0 / pTHatExponent)); + + for (const auto& track : tracks) { + if (!track.has_mcParticle()) { + continue; + } + if (!jetderiveddatautilities::selectTrack(track, trackSelection)) { + continue; + } + if (track.pt() > pTHatTrackMaxMCD * pTHat) { + return; + } + if (track.pt() < ptTTsigMax && track.pt() > ptTTsigMin) { + phiTTAr.push_back(track.phi()); + nTT++; + auto particle = track.template mcParticle_as(); + phiTTArPart.push_back(particle.phi()); + } + } + + if (nTT > 0) { + trigNumber = rand->Integer(nTT); + phiTT = phiTTAr[trigNumber]; + phiTTPart = phiTTAr[trigNumber]; + } else { + return; + } + + for (const auto& jetBase : jetsBase) { + double dR = 0; + double dRp = 0; + + if (jetBase.pt() > pTHatMaxMCD * pTHat) { + return; + } + + float dphi = RecoDecay::constrainAngle(jetBase.phi() - phiTT); + dR = getWTAaxisDifference(jetBase, mcdjetsWTA, tracks, true); + + if (jetBase.has_matchedJetGeo()) { + for (const auto& jetTag : jetBase.template matchedJetGeo_as>()) { + if (jetTag.pt() > pTHatMaxMCP * pTHat) { + return; + } + + float dphip = RecoDecay::constrainAngle(jetTag.phi() - phiTTPart); + dRp = getWTAaxisDifference(jetTag, mcpjetsWTA, particles, true); + + registry.fill(HIST("hPtMatched"), jetBase.pt() - (rho * jetBase.area()), jetTag.pt(), weight); + registry.fill(HIST("hPhiMatched"), dphi, dphip, weight); + registry.fill(HIST("hPtResolution"), jetTag.pt(), (jetTag.pt() - (jetBase.pt() - (rho * jetBase.area()))) / jetTag.pt(), weight); + registry.fill(HIST("hPhiResolution"), dphip, dphip - dphi, weight); + registry.fill(HIST("hDeltaRMatched"), dR, dRp, weight); + registry.fill(HIST("hDeltaRResolution"), jetTag.pt(), dRp - dR, weight); + registry.fill(HIST("hFullMatching"), jetBase.pt() - (rho * jetBase.area()), jetTag.pt(), dphi, dphip, dR, dRp, weight); + registry.fill(HIST("hPtMatched1d"), jetTag.pt(), weight); + registry.fill(HIST("hDeltaRMatched1d"), dRp, weight); + } + } + } + } + void processData(soa::Filtered::iterator const& collision, soa::Filtered> const& jets, soa::Filtered> const& jetsWTA, @@ -711,7 +771,7 @@ struct JetHadronRecoil { soa::Filtered> const& mcdjets, soa::Filtered> const& mcdjetsWTA, soa::Filtered> const& mcpjetsWTA, - soa::Filtered const& tracks, + soa::Filtered const& tracks, soa::Filtered const& particles, aod::JetMcCollisions const&, soa::Filtered> const& mcpjets) @@ -724,16 +784,7 @@ struct JetHadronRecoil { } registry.fill(HIST("hZvtxSelected"), collision.posZ()); const auto& mcpjetsWTACut = mcpjetsWTA.sliceBy(partJetsPerCollision, collision.mcCollisionId()); - bool ishJetEvent = false; - for (const auto& track : tracks) { - if (track.pt() < ptTTsigMax && track.pt() > ptTTsigMin) { - ishJetEvent = true; - break; - } - } - if (ishJetEvent) { - fillMatchedHistograms(mcdjets, mcdjetsWTA, mcpjetsWTACut, mcpjets, tracks, particles); - } + fillRecoilJetMatchedHistograms(mcdjets, mcdjetsWTA, mcpjetsWTACut, mcpjets, tracks, particles); } PROCESS_SWITCH(JetHadronRecoil, processRecoilJetsMCPMCDMatched, "process MC matched (recoil jets)", false); @@ -741,7 +792,7 @@ struct JetHadronRecoil { soa::Filtered> const& mcdjets, soa::Filtered> const& mcdjetsWTA, soa::Filtered> const& mcpjetsWTA, - soa::Filtered const& tracks, + soa::Filtered const& tracks, soa::Filtered const& particles, aod::JetMcCollisions const&, soa::Filtered> const& mcpjets) @@ -754,16 +805,7 @@ struct JetHadronRecoil { } registry.fill(HIST("hZvtxSelected"), collision.posZ()); const auto& mcpjetsWTACut = mcpjetsWTA.sliceBy(partJetsPerCollision, collision.mcCollisionId()); - bool ishJetEvent = false; - for (const auto& track : tracks) { - if (track.pt() < ptTTsigMax && track.pt() > ptTTsigMin) { - ishJetEvent = true; - break; - } - } - if (ishJetEvent) { - fillMatchedHistograms(mcdjets, mcdjetsWTA, mcpjetsWTACut, mcpjets, tracks, particles, collision.mcCollision().weight()); - } + fillRecoilJetMatchedHistograms(mcdjets, mcdjetsWTA, mcpjetsWTACut, mcpjets, tracks, particles, collision.mcCollision().weight()); } PROCESS_SWITCH(JetHadronRecoil, processRecoilJetsMCPMCDMatchedWeighted, "process MC matched with event weights (recoil jets)", false); From f730ae09aa0174a9b00687be4d45d4552a657366 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Jacazio?= Date: Thu, 12 Jun 2025 22:35:43 +0200 Subject: [PATCH 052/871] [PWGLF] Update inelGt.h (#11579) Co-authored-by: ALICE Builder --- PWGLF/Utils/inelGt.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/PWGLF/Utils/inelGt.h b/PWGLF/Utils/inelGt.h index 2ed513a902c..70c3de8ab4f 100644 --- a/PWGLF/Utils/inelGt.h +++ b/PWGLF/Utils/inelGt.h @@ -19,6 +19,10 @@ #ifndef PWGLF_UTILS_INELGT_H_ #define PWGLF_UTILS_INELGT_H_ +#include "Framework/O2DatabasePDGPlugin.h" + +#include "TParticlePDG.h" + #include namespace o2 From b908e2055dcdfa3c7aa1ef0fab451bfcf7511f50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADt=20Ku=C4=8Dera?= Date: Thu, 12 Jun 2025 22:40:10 +0200 Subject: [PATCH 053/871] [PWGHF,Tutorial] Include What You Use (#11589) --- Tutorials/PWGHF/skimCreatorMini.cxx | 2 -- Tutorials/PWGHF/taskMini.cxx | 1 - 2 files changed, 3 deletions(-) diff --git a/Tutorials/PWGHF/skimCreatorMini.cxx b/Tutorials/PWGHF/skimCreatorMini.cxx index 6fba171cfbf..e3aae5bbaf4 100644 --- a/Tutorials/PWGHF/skimCreatorMini.cxx +++ b/Tutorials/PWGHF/skimCreatorMini.cxx @@ -27,11 +27,9 @@ #include #include #include -#include #include #include #include -#include #include #include diff --git a/Tutorials/PWGHF/taskMini.cxx b/Tutorials/PWGHF/taskMini.cxx index 1876d6230cc..813e9879ce4 100644 --- a/Tutorials/PWGHF/taskMini.cxx +++ b/Tutorials/PWGHF/taskMini.cxx @@ -34,7 +34,6 @@ #include #include #include -#include #include #include From c858688a9fd0046b7b17487bb23a5b407a55c326 Mon Sep 17 00:00:00 2001 From: EmilGorm <50658075+EmilGorm@users.noreply.github.com> Date: Fri, 13 Jun 2025 00:12:51 +0200 Subject: [PATCH 054/871] [PWGCF] Add flag to disable ITS based track selection cuts (#11576) --- PWGCF/Flow/Tasks/flowPtEfficiency.cxx | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/PWGCF/Flow/Tasks/flowPtEfficiency.cxx b/PWGCF/Flow/Tasks/flowPtEfficiency.cxx index 78dbc0fc731..217b6f7fb36 100644 --- a/PWGCF/Flow/Tasks/flowPtEfficiency.cxx +++ b/PWGCF/Flow/Tasks/flowPtEfficiency.cxx @@ -60,6 +60,7 @@ struct FlowPtEfficiency { O2_DEFINE_CONFIGURABLE(cfgCutDCAz, float, 2.0f, "DCAz cut for tracks") O2_DEFINE_CONFIGURABLE(cfgCutDCAxyppPass3Enabled, bool, false, "switch of ppPass3 DCAxy pt dependent cut") O2_DEFINE_CONFIGURABLE(cfgCutDCAzPtDepEnabled, bool, false, "switch of DCAz pt dependent cut") + O2_DEFINE_CONFIGURABLE(cfgEnableITSCuts, bool, true, "switch of enabling ITS based track selection cuts") O2_DEFINE_CONFIGURABLE(cfgSelRunNumberEnabled, bool, false, "switch of run number selection") O2_DEFINE_CONFIGURABLE(cfgFlowEnabled, bool, false, "switch of calculating flow") O2_DEFINE_CONFIGURABLE(cfgFlowNbootstrap, int, 30, "Number of subsamples") @@ -219,10 +220,12 @@ struct FlowPtEfficiency { fGFWReco->CreateRegions(); } - if (cfgTrkSelRun3ITSMatch) { - myTrackSel = getGlobalTrackSelectionRun3ITSMatch(TrackSelection::GlobalTrackRun3ITSMatching::Run3ITSall7Layers, TrackSelection::GlobalTrackRun3DCAxyCut::Default); - } else { - myTrackSel = getGlobalTrackSelectionRun3ITSMatch(TrackSelection::GlobalTrackRun3ITSMatching::Run3ITSibAny, TrackSelection::GlobalTrackRun3DCAxyCut::Default); + if (cfgEnableITSCuts) { + if (cfgTrkSelRun3ITSMatch) { + myTrackSel = getGlobalTrackSelectionRun3ITSMatch(TrackSelection::GlobalTrackRun3ITSMatching::Run3ITSall7Layers, TrackSelection::GlobalTrackRun3DCAxyCut::Default); + } else { + myTrackSel = getGlobalTrackSelectionRun3ITSMatch(TrackSelection::GlobalTrackRun3ITSMatching::Run3ITSibAny, TrackSelection::GlobalTrackRun3DCAxyCut::Default); + } } if (cfgCutDCAxyppPass3Enabled) { myTrackSel.SetMaxDcaXYPtDep([](float pt) { return 0.004f + 0.013f / pt; }); @@ -230,8 +233,9 @@ struct FlowPtEfficiency { myTrackSel.SetMaxDcaXY(cfgCutDCAxy); } myTrackSel.SetMinNClustersTPC(cfgCutTPCclu); - myTrackSel.SetMinNClustersITS(cfgCutITSclu); myTrackSel.SetMinNCrossedRowsTPC(cfgCutTPCcrossedrows); + if (cfgEnableITSCuts) + myTrackSel.SetMinNClustersITS(cfgCutITSclu); if (!cfgCutDCAzPtDepEnabled) myTrackSel.SetMaxDcaZ(cfgCutDCAz); } @@ -358,10 +362,12 @@ struct FlowPtEfficiency { template bool trackSelected(TTrack track) { - if (cfgkIsTrackGlobal && !track.isGlobalTrack()) + if (cfgkIsTrackGlobal && !track.isGlobalTrack()) { return false; - if (cfgCutDCAzPtDepEnabled && (track.dcaZ() > (0.004f + 0.013f / track.pt()))) + } + if (cfgCutDCAzPtDepEnabled && (track.dcaZ() > (0.004f + 0.013f / track.pt()))) { return false; + } return myTrackSel.IsSelected(track); } @@ -378,7 +384,6 @@ struct FlowPtEfficiency { if (!std::count(cfgRunNumberList.value.begin(), cfgRunNumberList.value.end(), runNumber)) return; } - float imp = 0; bool impFetched = false; float evPhi = 0; @@ -393,7 +398,6 @@ struct FlowPtEfficiency { fGFWReco->Clear(); } - for (const auto& track : tracks) { if (!trackSelected(track)) continue; From 46cc605b0e14d5f015a1ec8d401b0aa62ff6df7a Mon Sep 17 00:00:00 2001 From: Pritam Chakraborty <47203359+prchakra@users.noreply.github.com> Date: Fri, 13 Jun 2025 01:27:43 +0200 Subject: [PATCH 055/871] [PWGCF] FemtoUniverse: Addidng 3D histo of qLCMS vs deta vs deta (#11594) --- .../Core/FemtoUniverseDetaDphiStar.h | 37 ++++++++++++++++--- 1 file changed, 31 insertions(+), 6 deletions(-) diff --git a/PWGCF/FemtoUniverse/Core/FemtoUniverseDetaDphiStar.h b/PWGCF/FemtoUniverse/Core/FemtoUniverseDetaDphiStar.h index 0a06b3513e8..bc4c6f1ea4e 100644 --- a/PWGCF/FemtoUniverse/Core/FemtoUniverseDetaDphiStar.h +++ b/PWGCF/FemtoUniverse/Core/FemtoUniverseDetaDphiStar.h @@ -68,6 +68,9 @@ class FemtoUniverseDetaDphiStar histdetadpimixed[0][0] = mHistogramRegistry->add((dirName + static_cast(HistNamesMixed[0][0])).c_str(), "; #Delta #eta; #Delta #phi", kTH2F, {{100, -0.15, 0.15}, {100, -0.15, 0.15}}); histdetadpimixed[0][1] = mHistogramRegistry->add((dirName + static_cast(HistNamesMixed[1][0])).c_str(), "; #Delta #eta; #Delta #phi", kTH2F, {{100, -0.15, 0.15}, {100, -0.15, 0.15}}); + histdetadpiqlcmssame = mHistogramRegistry->add((dirName + static_cast(HistNamesSame[1][7])).c_str(), "; #it{q}_{LCMS}; #Delta #eta; #Delta #phi", kTH3F, {{100, 0.0, 0.5}, {100, -0.15, 0.15}, {100, -0.15, 0.15}}); + histdetadpiqlcmsmixed = mHistogramRegistry->add((dirName + static_cast(HistNamesMixed[1][7])).c_str(), "; #it{q}_{LCMS}; #Delta #eta; #Delta #phi", kTH3F, {{100, 0.0, 0.5}, {100, -0.15, 0.15}, {100, -0.15, 0.15}}); + if (plotForEveryRadii) { for (int i = 0; i < 9; i++) { histdetadpiRadii[0][i] = mHistogramRegistryQA->add((dirName + static_cast(HistNamesRadii[0][i])).c_str(), "; #Delta #eta; #Delta #phi", kTH2F, {{100, -0.15, 0.15}, {100, -0.15, 0.15}}); @@ -407,23 +410,42 @@ class FemtoUniverseDetaDphiStar } } + /// Check if pair is close or not + template + void ClosePairqLCMS(Part const& part1, Part const& part2, float lmagfield, uint8_t ChosenEventType, double qlcms) // add typename Parts and variable parts for adding MClabels + { + magfield = lmagfield; + if constexpr (kPartOneType == o2::aod::femtouniverseparticle::ParticleType::kTrack && kPartTwoType == o2::aod::femtouniverseparticle::ParticleType::kTrack) { + auto deta = part1.eta() - part2.eta(); + auto dphiAvg = averagePhiStar(part1, part2, 0); + + if (ChosenEventType == femto_universe_container::EventType::same) { + histdetadpiqlcmssame->Fill(qlcms, deta, dphiAvg); + } else if (ChosenEventType == femto_universe_container::EventType::mixed) { + histdetadpiqlcmsmixed->Fill(qlcms, deta, dphiAvg); + } else { + LOG(fatal) << "FemtoUniverseDetaDphiStar: passed arguments don't agree with FemtoUniverseDetaDphiStar's type of events! Please provide same or mixed."; + } + } + } + private: HistogramRegistry* mHistogramRegistry = nullptr; ///< For main output HistogramRegistry* mHistogramRegistryQA = nullptr; ///< For QA output static constexpr std::string_view DirNames[6] = {"kTrack_kTrack/", "kTrack_kV0/", "kV0_kV0/", "kTrack_kPhi/", "kTrack_kD0/", "kCascade_kCascade/"}; - static constexpr std::string_view HistNamesSame[2][7] = {{"detadphidetadphi0BeforeSame_0", "detadphidetadphi0BeforeSame_1", "detadphidetadphi0BeforeSame_2", + static constexpr std::string_view HistNamesSame[2][8] = {{"detadphidetadphi0BeforeSame_0", "detadphidetadphi0BeforeSame_1", "detadphidetadphi0BeforeSame_2", "detadphidetadphi0BeforeSame_3", "detadphidetadphi0BeforeSame_4", "detadphidetadphi0BeforeSame_5", - "detadphidetadphi0BeforeSame_6"}, + "detadphidetadphi0BeforeSame_6", "detadphidetadphi0BeforeSameqLCMS"}, {"detadphidetadphi0AfterSame_0", "detadphidetadphi0AfterSame_1", "detadphidetadphi0AfterSame_2", "detadphidetadphi0AfterSame_3", "detadphidetadphi0AfterSame_4", "detadphidetadphi0AfterSame_5", - "detadphidetadphi0AfterSame_6"}}; - static constexpr std::string_view HistNamesMixed[2][7] = {{"detadphidetadphi0BeforeMixed_0", "detadphidetadphi0BeforeMixed_1", "detadphidetadphi0BeforeMixed_2", + "detadphidetadphi0AfterSame_6", "detadphidetadphi0AfterSameqLCMS"}}; + static constexpr std::string_view HistNamesMixed[2][8] = {{"detadphidetadphi0BeforeMixed_0", "detadphidetadphi0BeforeMixed_1", "detadphidetadphi0BeforeMixed_2", "detadphidetadphi0BeforeMixed_3", "detadphidetadphi0BeforeMixed_4", "detadphidetadphi0BeforeMixed_5", - "detadphidetadphi0BeforeMixed_6"}, + "detadphidetadphi0BeforeMixed_6", "detadphidetadphi0BeforeMixedqLCMS"}, {"detadphidetadphi0AfterMixed_0", "detadphidetadphi0AfterMixed_1", "detadphidetadphi0AfterMixed_2", "detadphidetadphi0AfterMixed_3", "detadphidetadphi0AfterMixed_4", "detadphidetadphi0AfterMixed_5", - "detadphidetadphi0AfterMixed_6"}}; + "detadphidetadphi0AfterMixed_6", "detadphidetadphi0AfterMixedqLCMS"}}; static constexpr std::string_view HistNamesRadii[7][9] = {{"detadphidetadphi0Before_0_0", "detadphidetadphi0Before_0_1", "detadphidetadphi0Before_0_2", "detadphidetadphi0Before_0_3", "detadphidetadphi0Before_0_4", "detadphidetadphi0Before_0_5", @@ -471,6 +493,9 @@ class FemtoUniverseDetaDphiStar std::array, 2>, 7> histdetadpimixed{}; std::array, 9>, 7> histdetadpiRadii{}; + std::shared_ptr histdetadpiqlcmssame{}; + std::shared_ptr histdetadpiqlcmsmixed{}; + /// Calculate phi at all required radii stored in TmpRadiiTPC /// Magnetic field to be provided in Tesla template From 05d68bc75024e512f1ed7eae49e672635f659876 Mon Sep 17 00:00:00 2001 From: Preet-Bhanjan Date: Fri, 13 Jun 2025 01:39:22 +0200 Subject: [PATCH 056/871] [PWGCF] Addition New PID function (#11582) Co-authored-by: Preet Pati Co-authored-by: ALICE Action Bot --- PWGCF/Flow/Tasks/flowPbpbPikp.cxx | 127 ++++++++++++++++++++++++++---- 1 file changed, 113 insertions(+), 14 deletions(-) diff --git a/PWGCF/Flow/Tasks/flowPbpbPikp.cxx b/PWGCF/Flow/Tasks/flowPbpbPikp.cxx index dfcf5fb42fc..1d979488da3 100644 --- a/PWGCF/Flow/Tasks/flowPbpbPikp.cxx +++ b/PWGCF/Flow/Tasks/flowPbpbPikp.cxx @@ -36,6 +36,7 @@ #include "Common/DataModel/TrackSelectionTables.h" #include "Common/DataModel/Centrality.h" #include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/PIDResponseITS.h" #include "Common/Core/trackUtilities.h" #include "Common/DataModel/Multiplicity.h" #include "CommonConstants/PhysicsConstants.h" @@ -82,13 +83,14 @@ struct FlowPbpbPikp { O2_DEFINE_CONFIGURABLE(cfgCutPtMax, float, 3.0f, "Maximal pT for ref tracks") O2_DEFINE_CONFIGURABLE(cfgCutEta, float, 0.8f, "Eta range for tracks") O2_DEFINE_CONFIGURABLE(cfgTpcCluster, int, 70, "Number of TPC clusters") + O2_DEFINE_CONFIGURABLE(cfgTpcCrossRows, int, 70, "Number of TPC clusters") O2_DEFINE_CONFIGURABLE(cfgCutChi2prTPCcls, float, 2.5, "Chi2 per TPC clusters") O2_DEFINE_CONFIGURABLE(cfgNbootstrap, int, 10, "Number of subsamples") O2_DEFINE_CONFIGURABLE(cfgOutputNUAWeights, bool, true, "Fill and output NUA weights") O2_DEFINE_CONFIGURABLE(cfgOutputRunByRun, bool, true, "Fill and output NUA weights run by run") O2_DEFINE_CONFIGURABLE(cfgEfficiency, std::string, "", "CCDB path to efficiency object") O2_DEFINE_CONFIGURABLE(cfgAcceptance, std::string, "", "CCDB path to acceptance object") - O2_DEFINE_CONFIGURABLE(cfgTpcNsigmaCut, float, 2.0f, "TPC N-sigma cut for pions, kaons, protons") + O2_DEFINE_CONFIGURABLE(cfgTpcCut, float, 2.0f, "TPC N-sigma cut for pions, kaons, protons") O2_DEFINE_CONFIGURABLE(cfgTofPtCut, float, 0.5f, "Minimum pt to use TOF N-sigma") O2_DEFINE_CONFIGURABLE(cfgCutDCAxy, float, 2.0f, "DCAxy range for tracks") O2_DEFINE_CONFIGURABLE(cfgCutDCAz, float, 2.0f, "DCAz range for tracks") @@ -97,18 +99,20 @@ struct FlowPbpbPikp { O2_DEFINE_CONFIGURABLE(cfgCutOccupancyMax, int, 2000, "Maximum occupancy cut") O2_DEFINE_CONFIGURABLE(cfgUseGlobalTrack, bool, true, "use Global track") O2_DEFINE_CONFIGURABLE(cfgITScluster, int, 5, "Number of ITS cluster") - O2_DEFINE_CONFIGURABLE(cfgTrackDensityCorrUse, bool, true, "Use track density efficiency correction") + O2_DEFINE_CONFIGURABLE(cfgTrackDensityCorrUse, bool, false, "Use track density efficiency correction") O2_DEFINE_CONFIGURABLE(cfgUseWeightPhiEtaVtxz, bool, false, "Use Phi, Eta, VertexZ dependent NUA weights") O2_DEFINE_CONFIGURABLE(cfgUseWeightPhiPtCent, bool, false, "Use Phi, Pt, Centrality dependent NUA weights") O2_DEFINE_CONFIGURABLE(cfgUseWeightPhiEtaPt, bool, true, "Use Phi, Eta, Pt dependent NUA weights") O2_DEFINE_CONFIGURABLE(cfgUseStrictPID, bool, true, "Use strict PID cuts for TPC") O2_DEFINE_CONFIGURABLE(cfgV0AT0Acut, int, 5, "V0AT0A cut") + O2_DEFINE_CONFIGURABLE(cfgUseAsymmetricPID, bool, false, "Use asymmetric PID cuts"); Configurable> cfgTrackDensityP0{"cfgTrackDensityP0", std::vector{0.7217476707, 0.7384792571, 0.7542625668, 0.7640680200, 0.7701951667, 0.7755299053, 0.7805901710, 0.7849446786, 0.7957356586, 0.8113039262, 0.8211968966, 0.8280558878, 0.8329342135}, "parameter 0 for track density efficiency correction"}; Configurable> cfgTrackDensityP1{"cfgTrackDensityP1", std::vector{-2.169488e-05, -2.191913e-05, -2.295484e-05, -2.556538e-05, -2.754463e-05, -2.816832e-05, -2.846502e-05, -2.843857e-05, -2.705974e-05, -2.477018e-05, -2.321730e-05, -2.203315e-05, -2.109474e-05}, "parameter 1 for track density efficiency correction"}; - Configurable> cfgTofNsigmaCut{"cfgTofNsigmaCut", std::vector{1.5, 1.5, 1.5}, "TOF n-sigma cut for pions, kaons, protons"}; - Configurable> cfgItsNsigmaCut{"cfgItsNsigmaCut", std::vector{3, 2.5, 2}, "ITS n-sigma cut for pions, kaons, protons"}; + Configurable> cfgTofNsigmaCut{"cfgTofNsigmaCut", 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"}; + Configurable> cfgItsNsigmaCut{"cfgItsNsigmaCut", 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> cfgTpcNsigmaCut{"cfgTpcNsigmaCut", 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"}; Configurable> cfgUseEventCuts{"cfgUseEventCuts", std::vector{1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0}, "Switch for various event cuts [kNoTimeFrameBorder, kNoITSROFrameBorder, kNoSameBunchPileup, kIsGoodZvtxFT0vsPV, kNoCollInTimeRangeStandard, kIsGoodITSLayersAll, kNoCollInRofStandard, kNoHighMultCollInPrevRof, Occupancy, Multiplicity correlation, T0AV0A 3 sigma cut, kIsVertexITSTPC, kTVXinTRD]"}; Configurable cfgRegions{"cfgRegions", {{"refN08", "refP08", "full", "poiN", "olN", "poiP", "olP", "poi", "ol", "poiNpi", "olNpi", "poiPpi", "olPpi", "poifullpi", "olfullpi", "poiNka", "olNka", "poiPka", "olPka", "poifullka", "olfullka", "poiNpr", "olNpr", "poiPpr", "olPpr", "poifullpr", "olfullpr"}, {-0.8, 0.4, -0.8, -0.8, -0.8, 0.4, 0.4, -0.8, -0.8, -0.8, -0.8, 0.4, 0.4, -0.8, -0.8, -0.8, -0.8, 0.4, 0.4, -0.8, -0.8, -0.8, -0.8, 0.4, 0.4, -0.8, -0.8}, {-0.4, 0.8, 0.8, -0.4, -0.4, 0.8, 0.8, 0.8, 0.8, -0.4, -0.4, 0.8, 0.8, 0.8, 0.8, -0.4, -0.4, 0.8, 0.8, 0.8, 0.8, -0.4, -0.4, 0.8, 0.8, 0.8, 0.8}, {0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, {1, 1, 1, 128, 256, 128, 256, 128, 256, 2, 16, 2, 16, 2, 16, 4, 32, 4, 32, 4, 32, 8, 64, 8, 64, 8, 64}}, "Configurations for GFW regions"}; @@ -123,9 +127,11 @@ struct FlowPbpbPikp { ConfigurableAxis axisNsigmaTOF{"axisNsigmaTOF", {80, -5, 5}, "nsigmaTOF axis"}; ConfigurableAxis axisParticles{"axisParticles", {3, 0, 3}, "axis for different hadrons"}; ConfigurableAxis axisTPCsignal{"axisTPCsignal", {10000, 0, 1000}, "axis for TPC signal"}; + ConfigurableAxis axisTOFbeta{"axisTOFbeta", {200, 0, 2}, "axis for TOF beta"}; std::vector tofNsigmaCut = cfgTofNsigmaCut; std::vector itsNsigmaCut = cfgItsNsigmaCut; + std::vector tpcNsigmaCut = cfgTofNsigmaCut; Filter collisionFilter = nabs(aod::collision::posZ) < cfgCutVertex; Filter trackFilter = (nabs(aod::track::dcaXY) < cfgCutDCAxy) && (nabs(aod::track::dcaZ) < cfgCutDCAz) && (nabs(aod::track::eta) < cfgCutEta) && (aod::track::pt > cfgCutPtPOIMin) && (aod::track::pt < cfgCutPtPOIMax) && ((requireGlobalTrackInFilter()) || (aod::track::isGlobalTrackSDD == (uint8_t) true)) && (aod::track::tpcChi2NCl < cfgCutChi2prTPCcls); @@ -238,11 +244,15 @@ struct FlowPbpbPikp { histos.add("c24_full_pi", "", {HistType::kTProfile, {axisMultiplicity}}); histos.add("c24_full_ka", "", {HistType::kTProfile, {axisMultiplicity}}); histos.add("c24_full_pr", "", {HistType::kTProfile, {axisMultiplicity}}); + + histos.add("TpcdEdx", "", {HistType::kTH2D, {axisPt, axisTPCsignal}}); + histos.add("TofBeta", "", {HistType::kTH2D, {axisPt, axisTOFbeta}}); + histos.add("TofTpcNsigma_before", "", {HistType::kTHnSparseD, {{axisParticles, axisNsigmaTPC, axisNsigmaTOF, axisPt}}}); histos.add("TofTpcNsigma_after", "", {HistType::kTHnSparseD, {{axisParticles, axisNsigmaTPC, axisNsigmaTOF, axisPt}}}); histos.add("partCount", "", {HistType::kTHnSparseD, {{axisParticles, axisMultiplicity, axisPt}}}); - histos.add("hEventCount", "Number of Event;; Count", {HistType::kTH1D, {{15, 0, 15}}}); + histos.add("hEventCount", "Number of Events;; Count", {HistType::kTH1D, {{15, 0, 15}}}); histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(1, "Filtered event"); histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(2, "After sel8"); histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(3, "kNoTimeFrameBorder"); @@ -259,6 +269,18 @@ struct FlowPbpbPikp { histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(14, "kIsVertexITSTPC"); histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(15, "kTVXinTRD"); + histos.add("hTrackCount", "Number of Tracks;; Count", {HistType::kTH1D, {{10, 0, 10}}}); + histos.get(HIST("hTrackCount"))->GetXaxis()->SetBinLabel(1, "Filtered track"); + histos.get(HIST("hTrackCount"))->GetXaxis()->SetBinLabel(2, "Global tracks"); + histos.get(HIST("hTrackCount"))->GetXaxis()->SetBinLabel(3, "PV contributor"); + histos.get(HIST("hTrackCount"))->GetXaxis()->SetBinLabel(4, "ITS clusters"); + histos.get(HIST("hTrackCount"))->GetXaxis()->SetBinLabel(5, "TPC signal"); + histos.get(HIST("hTrackCount"))->GetXaxis()->SetBinLabel(6, "TPC clusters"); + histos.get(HIST("hTrackCount"))->GetXaxis()->SetBinLabel(7, "TPC crossed rows"); + histos.get(HIST("hTrackCount"))->GetXaxis()->SetBinLabel(8, "Pions"); + histos.get(HIST("hTrackCount"))->GetXaxis()->SetBinLabel(9, "Kaons"); + histos.get(HIST("hTrackCount"))->GetXaxis()->SetBinLabel(10, "Protons"); + if (cfgOutputNUAWeights && !cfgOutputRunByRun) { histos.add("NUA/hPhiEtaVtxz_ref", ";#varphi;#eta;v_{z}", {HistType::kTH3D, {axisPhi, axisEta, axisVertex}}); histos.add("NUA/hPhiEtaVtxz_ch", ";#varphi;#eta;v_{z}", {HistType::kTH3D, {axisPhi, axisEta, axisVertex}}); @@ -386,13 +408,38 @@ struct FlowPbpbPikp { template bool selectionTrack(const TTrack& track) { - if (cfgUseGlobalTrack && !(track.isGlobalTrack() && track.isPVContributor() && track.itsNCls() > cfgITScluster && track.tpcNClsFound() > cfgTpcCluster && track.hasTPC())) { - return false; + histos.fill(HIST("hTrackCount"), 0.5); // Filtered tracks + if (cfgUseGlobalTrack && !(track.isGlobalTrack())) { + return 0; } - if (!cfgUseGlobalTrack && !(track.isPVContributor() && track.itsNCls() > cfgITScluster && track.hasTPC())) { - return false; + if (cfgUseGlobalTrack) + histos.fill(HIST("hTrackCount"), 1.5); // After global track selection + + if (!(track.isPVContributor())) { + return 0; } - return true; + histos.fill(HIST("hTrackCount"), 2.5); // After PV contributor selection + + if (!(track.itsNCls() > cfgITScluster)) { + return 0; + } + histos.fill(HIST("hTrackCount"), 3.5); // After ITS cluster selection + + if (!(track.hasTPC())) { + return 0; + } + histos.fill(HIST("hTrackCount"), 4.5); // If track has TPC signal + + if (!(track.tpcNClsFound() > cfgTpcCluster)) { + return 0; + } + histos.fill(HIST("hTrackCount"), 5.5); // After TPC cluster selection + + if (!(track.tpcNClsCrossedRows() > cfgTpcCrossRows)) { + return 0; + } + histos.fill(HIST("hTrackCount"), 6.5); // After TPC crossed rows selection + return 1; } template @@ -402,6 +449,7 @@ struct FlowPbpbPikp { switch (pidIndex) { case 1: histos.fill(HIST("TofTpcNsigma_after"), pidIndex - 1, track.tpcNSigmaPi(), track.tofNSigmaPi(), track.pt()); + histos.fill(HIST("hTrackCount"), 7.5); // Pion count if (!cfgAcceptance.value.empty() && cfgUseWeightPhiEtaVtxz) histos.fill(HIST("PhiCorrected/hPhiEtaVtxz_pi_corrd"), track.phi(), track.eta(), collision.posZ(), wacc); // pion weights if (!cfgAcceptance.value.empty() && cfgUseWeightPhiPtCent) @@ -411,6 +459,7 @@ struct FlowPbpbPikp { break; case 2: histos.fill(HIST("TofTpcNsigma_after"), pidIndex - 1, track.tpcNSigmaKa(), track.tofNSigmaKa(), track.pt()); + histos.fill(HIST("hTrackCount"), 8.5); // Kaon count if (!cfgAcceptance.value.empty() && cfgUseWeightPhiEtaVtxz) histos.fill(HIST("PhiCorrected/hPhiEtaVtxz_ka_corrd"), track.phi(), track.eta(), collision.posZ(), wacc); // kaon weights if (!cfgAcceptance.value.empty() && cfgUseWeightPhiPtCent) @@ -420,6 +469,7 @@ struct FlowPbpbPikp { break; case 3: histos.fill(HIST("TofTpcNsigma_after"), pidIndex - 1, track.tpcNSigmaPr(), track.tofNSigmaPr(), track.pt()); + histos.fill(HIST("hTrackCount"), 9.5); // Proton count if (!cfgAcceptance.value.empty() && cfgUseWeightPhiEtaVtxz) histos.fill(HIST("PhiCorrected/hPhiEtaVtxz_pr_corrd"), track.phi(), track.eta(), collision.posZ(), wacc); // proton weights if (!cfgAcceptance.value.empty() && cfgUseWeightPhiPtCent) @@ -437,12 +487,12 @@ struct FlowPbpbPikp { std::array nSigmaTPC = {track.tpcNSigmaPi(), track.tpcNSigmaKa(), track.tpcNSigmaPr()}; std::array nSigmaCombined = {std::hypot(track.tpcNSigmaPi(), track.tofNSigmaPi()), std::hypot(track.tpcNSigmaKa(), track.tofNSigmaKa()), std::hypot(track.tpcNSigmaPr(), track.tofNSigmaPr())}; int pid = -1; - float nsigma = cfgTpcNsigmaCut; + float nsigma = cfgTpcCut; // Choose which nSigma to use std::array nSigmaToUse = (track.pt() > cfgTofPtCut && track.hasTOF()) ? nSigmaCombined : nSigmaTPC; if (track.pt() > cfgTofPtCut && !track.hasTOF()) - return -1; + return 0; const int numSpecies = 3; int pidCount = 0; @@ -450,7 +500,7 @@ struct FlowPbpbPikp { for (int i = 0; i < numSpecies; ++i) { if (std::abs(nSigmaToUse[i]) < nsigma) { if (pidCount > 0 && cfgUseStrictPID) - return -1; // more than one particle with low nsigma + return 0; // more than one particle with low nsigma pidCount++; pid = i; @@ -461,6 +511,52 @@ struct FlowPbpbPikp { return pid + 1; // shift the pid by 1, 1 = pion, 2 = kaon, 3 = proton } + template + int getNsigmaPIDTpcTofAssymmetric(TTrack track) + { + // Computing Nsigma arrays for pion, kaon, and protons + std::array nSigmaTPC = {track.tpcNSigmaPi(), track.tpcNSigmaKa(), track.tpcNSigmaPr()}; + std::array nSigmaTOF = {track.tofNSigmaPi(), track.tofNSigmaKa(), track.tofNSigmaPr()}; + int pid = -1; + + bool isPion, isKaon, isProton; + bool isTpcPion = nSigmaTPC[0] < tpcNsigmaCut[0] && nSigmaTPC[0] > tpcNsigmaCut[0 + 3]; + bool isTpcKaon = nSigmaTPC[1] < tpcNsigmaCut[1] && nSigmaTPC[1] > tpcNsigmaCut[1 + 3]; + bool isTpcProton = nSigmaTPC[2] < tpcNsigmaCut[2] && nSigmaTPC[2] > tpcNsigmaCut[2 + 3]; + + bool isTofPion = nSigmaTOF[0] < tofNsigmaCut[0] && nSigmaTOF[0] > tofNsigmaCut[0 + 3]; + bool isTofKaon = nSigmaTOF[1] < tofNsigmaCut[1] && nSigmaTOF[1] > tofNsigmaCut[1 + 3]; + bool isTofProton = nSigmaTOF[2] < tofNsigmaCut[2] && nSigmaTOF[2] > tofNsigmaCut[2 + 3]; + + if (track.pt() > cfgTofPtCut && !track.hasTOF()) { + return 0; + } else if (track.pt() > cfgTofPtCut && track.hasTOF()) { + isPion = isTofPion && isTpcPion; + isKaon = isTofKaon && isTpcKaon; + isProton = isTofProton && isTpcProton; + } else { + isPion = isTpcPion; + isKaon = isTpcKaon; + isProton = isTpcProton; + } + + if ((isPion && isKaon) || (isPion && isProton) || (isKaon && isProton)) { + return 0; // more than one particle satisfy the criteria + } + + if (isPion) { + pid = PIONS; + } else if (isKaon) { + pid = KAONS; + } else if (isProton) { + pid = PROTONS; + } else { + return 0; // no particle satisfies the criteria + } + + return pid + 1; // shift the pid by 1, 1 = pion, 2 = kaon, 3 = proton + } + template void fillProfile(const GFW::CorrConfig& corrconf, const ConstStr& tarName, const double& cent) { @@ -814,6 +910,9 @@ struct FlowPbpbPikp { histos.fill(HIST("hEta"), track.eta()); histos.fill(HIST("hPt"), pt); + histos.fill(HIST("TpcdEdx"), pt, track.tpcSignal()); + histos.fill(HIST("TofBeta"), pt, track.beta()); + histos.fill(HIST("TofTpcNsigma_before"), PIONS, track.tpcNSigmaPi(), track.tofNSigmaPi(), pt); histos.fill(HIST("TofTpcNsigma_before"), KAONS, track.tpcNSigmaKa(), track.tofNSigmaKa(), pt); histos.fill(HIST("TofTpcNsigma_before"), PROTONS, track.tpcNSigmaPr(), track.tofNSigmaPr(), pt); @@ -821,7 +920,7 @@ struct FlowPbpbPikp { bool withinPtPOI = (cfgCutPtPOIMin < pt) && (pt < cfgCutPtPOIMax); // within POI pT range bool withinPtRef = (cfgCutPtMin < pt) && (pt < cfgCutPtMax); // within RF pT range - pidIndex = getNsigmaPIDTpcTof(track); + pidIndex = cfgUseAsymmetricPID ? getNsigmaPIDTpcTofAssymmetric(track) : getNsigmaPIDTpcTof(track); weff = 1; // Initializing weff for each track // NUA weights From ac790757978633c85887aefee4357d48e4e90eac Mon Sep 17 00:00:00 2001 From: ddobrigk Date: Fri, 13 Jun 2025 07:10:26 +0200 Subject: [PATCH 057/871] [Common] Unified, simple, fully self-configuring mult/cent provider (#11495) Co-authored-by: David Dobrigkeit Chinellato Co-authored-by: ALICE Builder Co-authored-by: romainschotter Co-authored-by: SCHOTTER Romain <47983209+romainschotter@users.noreply.github.com> --- Common/DataModel/Centrality.h | 9 + Common/TableProducer/CMakeLists.txt | 5 + Common/TableProducer/multCentTable.cxx | 204 ++++ Common/Tools/MultModule.h | 1336 ++++++++++++++++++++++++ 4 files changed, 1554 insertions(+) create mode 100644 Common/TableProducer/multCentTable.cxx create mode 100644 Common/Tools/MultModule.h diff --git a/Common/DataModel/Centrality.h b/Common/DataModel/Centrality.h index c3074a63c67..fa7e2ec51bc 100644 --- a/Common/DataModel/Centrality.h +++ b/Common/DataModel/Centrality.h @@ -60,6 +60,11 @@ DECLARE_SOA_TABLE(CentMFTs, "AOD", "CENTMFT", cent::CentMFT); //! Ru // Run 3 variant tables DECLARE_SOA_TABLE(CentFT0CVariant1s, "AOD", "CENTFT0Cvar1", cent::CentFT0CVariant1); //! Run 3 FT0C variant 1 +// Run 3 centrality per BC (joinable with BC) +DECLARE_SOA_TABLE(BCCentFT0Ms, "AOD", "BCCENTFT0M", cent::CentFT0M, o2::soa::Marker<1>); //! Run 3 FT0M BC centrality table +DECLARE_SOA_TABLE(BCCentFT0As, "AOD", "BCCENTFT0A", cent::CentFT0A, o2::soa::Marker<1>); //! Run 3 FT0A BC centrality table +DECLARE_SOA_TABLE(BCCentFT0Cs, "AOD", "BCCENTFT0C", cent::CentFT0C, o2::soa::Marker<1>); //! Run 3 FT0C BC centrality table + using CentRun2V0M = CentRun2V0Ms::iterator; using CentRun2V0A = CentRun2V0As::iterator; using CentRun2SPDTrk = CentRun2SPDTrks::iterator; @@ -77,6 +82,10 @@ using CentNTPV = CentNTPVs::iterator; using CentNGlobal = CentNGlobals::iterator; using CentMFT = CentMFTs::iterator; +using BCCentFT0M = BCCentFT0Ms::iterator; +using BCCentFT0A = BCCentFT0As::iterator; +using BCCentFT0C = BCCentFT0Cs::iterator; + template concept HasRun2Centrality = requires(T&& t) { { t.centRun2V0M() }; diff --git a/Common/TableProducer/CMakeLists.txt b/Common/TableProducer/CMakeLists.txt index d2d59ea2506..62211406807 100644 --- a/Common/TableProducer/CMakeLists.txt +++ b/Common/TableProducer/CMakeLists.txt @@ -32,6 +32,11 @@ o2physics_add_dpl_workflow(multiplicity-table PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(multcenttable + SOURCES multCentTable.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(multiplicity-extra-table SOURCES multiplicityExtraTable.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore diff --git a/Common/TableProducer/multCentTable.cxx b/Common/TableProducer/multCentTable.cxx new file mode 100644 index 00000000000..421e813bad4 --- /dev/null +++ b/Common/TableProducer/multCentTable.cxx @@ -0,0 +1,204 @@ +// 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 multCentTable.cxx +/// \brief unified, self-configuring mult/cent provider +/// \author ALICE + +//=============================================================== +// +// Unified, self-configuring multiplicity+centrality task +// still work in progress: use at your own discretion +// +//=============================================================== + +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" +#include "Framework/RunningWorkflowInfo.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "Common/Core/trackUtilities.h" +#include "ReconstructionDataFormats/DCA.h" +#include "DetectorsBase/Propagator.h" +#include "DetectorsBase/GeometryManager.h" +#include "CommonUtils/NameConf.h" +#include "CCDB/CcdbApi.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "CCDB/BasicCCDBManager.h" +#include "Framework/HistogramRegistry.h" +#include "DataFormatsCalibration/MeanVertexObject.h" +#include "CommonConstants/GeomConstants.h" +#include "Common/Tools/TrackPropagationModule.h" +#include "Common/Tools/StandardCCDBLoader.h" +#include "Framework/O2DatabasePDGPlugin.h" +#include "MetadataHelper.h" +#include "Common/Tools/MultModule.h" + +using namespace o2; +using namespace o2::framework; +// using namespace o2::framework::expressions; + +MetadataHelper metadataInfo; // Metadata helper + +struct MultCentTable { + o2::common::multiplicity::standardConfigurables opts; + o2::common::multiplicity::products products; + o2::common::multiplicity::MultModule module; + + // CCDB boilerplate declarations + o2::framework::Configurable ccdburl{"ccdburl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Service ccdb; + Service pdg; + + // hold multiplicity values for layover to centrality calculation + std::vector mults; + + // slicers + Preslice> slicerTracksIU = o2::aod::track::collisionId; + Preslice> slicerTracksIUwithSelections = o2::aod::track::collisionId; + Preslice> slicerTrackRun2 = o2::aod::track::collisionId; + + void init(o2::framework::InitContext& initContext) + { + // CCDB boilerplate init + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + ccdb->setURL(ccdburl.value); + + // task-specific + module.init(opts, initContext); + } + + void processRun2(soa::Join const& collisions, + soa::Join const& tracks, + soa::Join const& bcs, + aod::Zdcs const&, + aod::FV0As const&, + aod::FV0Cs const&, + aod::FT0s const&) + { + mults.clear(); + for (auto const& collision : collisions) { + o2::common::multiplicity::multEntry mult; + const auto& bc = bcs.rawIteratorAt(collision.getId()); + const uint64_t collIdx = collision.globalIndex(); + auto tracksThisCollision = tracks.sliceBy(slicerTrackRun2, collIdx); + mult = module.collisionProcessRun2(collision, tracksThisCollision, bc, products); + mults.push_back(mult); + } + } + + void processRun3(soa::Join const& collisions, + soa::Join const& tracks, + soa::Join const&, + aod::Zdcs const&, + aod::FV0As const&, + aod::FT0s const&, + aod::FDDs const&) + { + mults.clear(); + for (auto const& collision : collisions) { + o2::common::multiplicity::multEntry mult; + const auto& bc = collision.bc_as>(); + const uint64_t collIdx = collision.globalIndex(); + auto tracksThisCollision = tracks.sliceBy(slicerTracksIU, collIdx); + mult = module.collisionProcessRun3(ccdb, metadataInfo, collision, tracksThisCollision, bc, products); + mults.push_back(mult); + } + } + + void processRun3WithGlobalCounters(soa::Join const& collisions, + soa::Join const& tracks, + soa::Join const&, + aod::Zdcs const&, + aod::FV0As const&, + aod::FT0s const&, + aod::FDDs const&) + { + mults.clear(); + for (auto const& collision : collisions) { + o2::common::multiplicity::multEntry mult; + const auto& bc = collision.bc_as>(); + const uint64_t collIdx = collision.globalIndex(); + auto tracksThisCollision = tracks.sliceBy(slicerTracksIUwithSelections, collIdx); + mult = module.collisionProcessRun3(ccdb, metadataInfo, collision, tracksThisCollision, bc, products); + mults.push_back(mult); + } + } + void processMFT(soa::Join::iterator const& collision, + o2::aod::MFTTracks const& mfttracks, + soa::SmallGroups const& retracks) + { + if (opts.mEnabledTables[o2::common::multiplicity::kMFTMults]) { + // populates MFT information in the mults buffer (in addition to filling table) + module.collisionProcessMFT(collision, mfttracks, retracks, mults, products); + } + } + void processMonteCarlo(aod::McCollision const& mcCollision, aod::McParticles const& mcParticles) + { + if (opts.mEnabledTables[o2::common::multiplicity::kMultMCExtras]) { + module.collisionProcessMonteCarlo(mcCollision, mcParticles, pdg, products); + } + } + void processMonteCarlo2Mults(soa::Join::iterator const& collision) + { + if (opts.mEnabledTables[o2::common::multiplicity::kMult2MCExtras]) { + // establish simple interlink for posterior analysis (derived data) + products.tableExtraMult2MCExtras(collision.mcCollisionId()); + } + } + void processCentralityRun2(aod::Collisions const& collisions, soa::Join const& bcs) + { + // it is important that this function is at the end of the other process functions. + // it requires `mults` to be properly set, which will only happen after the other process + // functions have been called. + + // internally, the function below will do nothing if no centrality is requested. + // it is thus safer to always keep the actual process function for centrality + // generation to true, since the requisites for being in this context are + // always fulfilled + if (collisions.size() != static_cast(mults.size())) { + LOGF(fatal, "Size of collisions doesn't match size of multiplicity buffer!"); + } + module.generateCentralitiesRun2(ccdb, metadataInfo, bcs, mults, products); + } + void processCentralityRun3(aod::Collisions const& collisions, soa::Join const& bcs, aod::FT0s const&) + { + // it is important that this function is at the end of the other process functions. + // it requires `mults` to be properly set, which will only happen after the other process + // functions have been called. + + // internally, the function below will do nothing if no centrality is requested. + // it is thus safer to always keep the actual process function for centrality + // generation to true, since the requisites for being in this context are + // always fulfilled + if (collisions.size() != static_cast(mults.size())) { + LOGF(fatal, "Size of collisions doesn't match size of multiplicity buffer!"); + } + module.generateCentralitiesRun3(ccdb, metadataInfo, bcs, mults, products); + } + + PROCESS_SWITCH(MultCentTable, processRun2, "Process Run 2", false); + PROCESS_SWITCH(MultCentTable, processRun3, "Process Run 3", true); + PROCESS_SWITCH(MultCentTable, processRun3WithGlobalCounters, "Process Run 3 + global tracking counters", false); + PROCESS_SWITCH(MultCentTable, processMFT, "Process MFT info", false); + PROCESS_SWITCH(MultCentTable, processMonteCarlo, "Process Monte Carlo information", false); + PROCESS_SWITCH(MultCentTable, processMonteCarlo2Mults, "Process Monte Carlo information", false); + PROCESS_SWITCH(MultCentTable, processCentralityRun2, "Generate Run 2 centralities", false); + PROCESS_SWITCH(MultCentTable, processCentralityRun3, "Generate Run 3 centralities", true); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + metadataInfo.initMetadata(cfgc); + WorkflowSpec workflow{adaptAnalysisTask(cfgc)}; + return workflow; +} diff --git a/Common/Tools/MultModule.h b/Common/Tools/MultModule.h new file mode 100644 index 00000000000..07397131b68 --- /dev/null +++ b/Common/Tools/MultModule.h @@ -0,0 +1,1336 @@ +// 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 MultModule.h +/// \brief combined multiplicity + centrality module with autodetect features +/// \author ALICE + +#ifndef COMMON_TOOLS_MULTMODULE_H_ +#define COMMON_TOOLS_MULTMODULE_H_ + +#include +#include +#include +#include +#include +#include +#include +#include "Framework/AnalysisDataModel.h" +#include "Framework/Configurable.h" +#include "Framework/HistogramSpec.h" +#include "TableHelper.h" +#include "Common/Core/TPCVDriftManager.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/Centrality.h" +#include "PWGMM/Mult/DataModel/bestCollisionTable.h" +#include "TFormula.h" + +//__________________________________________ +// MultModule + +namespace o2 +{ +namespace common +{ +namespace multiplicity +{ + +// statics necessary for the configurables in this namespace +static constexpr int nParameters = 1; +static const std::vector tableNames{ + // multiplicity subcomponent + "FV0Mults", + "FV0AOuterMults", + "FT0Mults", + "FDDMults", + "ZDCMults", + "TrackletMults", + "TPCMults", + "PVMults", + "MultsExtra", + "MultSelections", + "FV0MultZeqs", + "FT0MultZeqs", + "FDDMultZeqs", + "PVMultZeqs", + "MultMCExtras", + "kMult2MCExtras", + "kMFTMults", + "kMultsGlobal", + + // centrality subcomponent + "CentRun2V0Ms", + "CentRun2V0As", + "CentRun2SPDTrks", + "CentRun2SPDClss", + "CentRun2CL0s", + "CentRun2CL1s", + "CentFV0As", + "CentFT0Ms", + "CentFT0As", + "CentFT0Cs", + "CentFT0CVariant1s", + "CentFDDMs", + "CentNTPVs", + "CentNGlobals", + "CentMFTs", + "BCCentFT0Ms", + "BCCentFT0As", + "BCCentFT0Cs"}; + +static constexpr int nTablesConst = 36; + +static const std::vector parameterNames{"enable"}; +static const int defaultParameters[nTablesConst][nParameters]{ + {-1}, + {-1}, + {-1}, + {-1}, + {-1}, + {-1}, + {-1}, + {-1}, + {-1}, + {-1}, + {-1}, + {-1}, + {-1}, + {-1}, + {-1}, + {-1}, + {-1}, + {-1}, + {-1}, + {-1}, + {-1}, + {-1}, + {-1}, + {-1}, + {-1}, + {-1}, + {-1}, + {-1}, + {-1}, + {-1}, + {-1}, + {-1}, + {-1}, + {-1}, + {-1}, + {-1}}; + +// table index : match order above +enum tableIndex { kFV0Mults, // standard + kFV0AOuterMults, // standard + kFT0Mults, // standard + kFDDMults, // standard + kZDCMults, // standard + kTrackletMults, // Run 2 + kTPCMults, // standard + kPVMults, // standard + kMultsExtra, // standard + kMultSelections, // event selection + kFV0MultZeqs, // zeq calib, standard + kFT0MultZeqs, // zeq calib, standard + kFDDMultZeqs, // zeq calib, standard + kPVMultZeqs, // zeq calib, standard + kMultMCExtras, // MC exclusive + kMult2MCExtras, // MC exclusive + kMFTMults, // requires MFT task + kMultsGlobal, // requires track selection task + + // centrality subcomponent + kCentRun2V0Ms, // Run 2 + kCentRun2V0As, // Run 2 + kCentRun2SPDTrks, // Run 2 + kCentRun2SPDClss, // Run 2 + kCentRun2CL0s, // Run 2 + kCentRun2CL1s, // Run 2 + kCentFV0As, // standard Run 3 + kCentFT0Ms, // standard Run 3 + kCentFT0As, // standard Run 3 + kCentFT0Cs, // standard Run 3 + kCentFT0CVariant1s, // standard Run 3 + kCentFDDMs, // standard Run 3 + kCentNTPVs, // standard Run 3 + kCentNGlobals, // requires track selection task + kCentMFTs, // requires MFT task + kBCCentFT0Ms, // bc centrality + kBCCentFT0As, // bc centrality + kBCCentFT0Cs, // bc centrality + kNTables }; + +struct products : o2::framework::ProducesGroup { + //__________________________________________________ + // multiplicity tables + o2::framework::Produces tableFV0; + o2::framework::Produces tableFV0AOuter; + o2::framework::Produces tableFT0; + o2::framework::Produces tableFDD; + o2::framework::Produces tableZDC; + o2::framework::Produces tableTracklet; + o2::framework::Produces tableTpc; + o2::framework::Produces tablePv; + o2::framework::Produces tableExtra; + o2::framework::Produces multSelections; + o2::framework::Produces tableFV0Zeqs; + o2::framework::Produces tableFT0Zeqs; + o2::framework::Produces tableFDDZeqs; + o2::framework::Produces tablePVZeqs; + o2::framework::Produces tableExtraMc; + o2::framework::Produces tableExtraMult2MCExtras; + o2::framework::Produces mftMults; + o2::framework::Produces multsGlobal; + + //__________________________________________________ + // centrality tables (per collision / default) + o2::framework::Produces centRun2V0M; + o2::framework::Produces centRun2V0A; + o2::framework::Produces centRun2SPDTracklets; + o2::framework::Produces centRun2SPDClusters; + o2::framework::Produces centRun2CL0; + o2::framework::Produces centRun2CL1; + o2::framework::Produces centFV0A; + o2::framework::Produces centFT0M; + o2::framework::Produces centFT0A; + o2::framework::Produces centFT0C; + o2::framework::Produces centFT0CVariant1; + o2::framework::Produces centFDDM; + o2::framework::Produces centNTPV; + o2::framework::Produces centNGlobals; + o2::framework::Produces centMFTs; + o2::framework::Produces bcCentFT0A; + o2::framework::Produces bcCentFT0C; + o2::framework::Produces bcCentFT0M; + + //__________________________________________________ + // centrality tables per BC + // FIXME - future development +}; + +// for providing temporary buffer +// FIXME ideally cursors could be readable +// to avoid duplicate memory allocation but ok +struct multEntry { + float multFV0A = 0.0f; + float multFV0C = 0.0f; + float multFV0AOuter = 0.0f; + float multFT0A = 0.0f; + float multFT0C = 0.0f; + float multFDDA = 0.0f; + float multFDDC = 0.0f; + float multZNA = 0.0f; + float multZNC = 0.0f; + float multZEM1 = 0.0f; + float multZEM2 = 0.0f; + float multZPA = 0.0f; + float multZPC = 0.0f; + int multTracklets = 0; + + int multNContribs = 0; // PVMult 0.8 + int multNContribsEta1 = 0; // PVMult 1.0 + int multNContribsEtaHalf = 0; // PVMult 0.5 + int multTPC = 0; // all TPC (PV contrib unchecked) + int multHasTPC = 0; // extras + int multHasITS = 0; // extras + int multHasTOF = 0; // extras + int multHasTRD = 0; // extras + int multITSOnly = 0; // extras + int multTPCOnly = 0; // extras + int multITSTPC = 0; // extras + int multAllTracksTPCOnly = 0; // extras + int multAllTracksITSTPC = 0; // extras + + float multFV0AZeq = -999.0f; + float multFV0CZeq = -999.0f; + float multFT0AZeq = -999.0f; + float multFT0CZeq = -999.0f; + float multFDDAZeq = -999.0f; + float multFDDCZeq = -999.0f; + float multNContribsZeq = 0; + + int multGlobalTracks = 0; // multsGlobal + int multNbrContribsEta05GlobalTrackWoDCA = 0; // multsGlobal + int multNbrContribsEta08GlobalTrackWoDCA = 0; // multsGlobal + int multNbrContribsEta10GlobalTrackWoDCA = 0; // multsGlobal + + int multMFTAllTracks = 0; // mft + int multMFTTracks = 0; // mft + + // For Run2 only + float posZ = -999.0f; + uint16_t spdClustersL0 = 0; + uint16_t spdClustersL1 = 0; +}; + +// strangenessBuilder: 1st-order configurables +struct standardConfigurables : o2::framework::ConfigurableGroup { + // self-configuration configurables + o2::framework::Configurable> enabledTables{"enabledTables", + {defaultParameters[0], nTablesConst, nParameters, tableNames, parameterNames}, + "Produce this table: -1 for autodetect; otherwise, 0/1 is false/true"}; + std::vector mEnabledTables; // Vector of enabled tables + + // Autoconfigure process functions + o2::framework::Configurable autoConfigureProcess{"autoConfigureProcess", false, "if true, will configure process function switches based on metadata"}; + + // do vertex-Z equalized or not + o2::framework::Configurable doVertexZeq{"doVertexZeq", 1, "if 1: do vertex Z eq mult table"}; + + // global track counter configurables + o2::framework::Configurable minPtGlobalTrack{"minPtGlobalTrack", 0.15, "min. pT for global tracks"}; + o2::framework::Configurable maxPtGlobalTrack{"maxPtGlobalTrack", 1e+10, "max. pT for global tracks"}; + 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"}; + + // 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"}; + o2::framework::Configurable reconstructionPass{"reconstructionPass", "", {"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."}}; + + // centrality operation + o2::framework::Configurable generatorName{"generatorName", "", {"Specify if and only if this is MC. Typical: PYTHIA"}}; + o2::framework::Configurable embedINELgtZEROselection{"embedINELgtZEROselection", false, {"Option to do percentile 100.5 if not INELgtZERO"}}; +}; + +class MultModule +{ + public: + MultModule() + { + // constructor + mRunNumber = 0; + mRunNumberCentrality = 0; + lCalibLoaded = false; + lCalibObjects = nullptr; + hVtxZFV0A = nullptr; + hVtxZFT0A = nullptr; + hVtxZFT0C = nullptr; + hVtxZFDDA = nullptr; + hVtxZFDDC = nullptr; + hVtxZNTracks = nullptr; + } + + // internal: calib related, vtx-z profiles + int mRunNumber; + int mRunNumberCentrality; + bool lCalibLoaded; + TList* lCalibObjects; + TProfile* hVtxZFV0A; + TProfile* hVtxZFT0A; + TProfile* hVtxZFT0C; + TProfile* hVtxZFDDA; + TProfile* hVtxZFDDC; + TProfile* hVtxZNTracks; + + // declaration of structs here + // (N.B.: will be invisible to the outside, create your own copies) + o2::common::multiplicity::standardConfigurables internalOpts; + + //_________________________________________________ + // centrality-related objects + struct TagRun2V0MCalibration { + bool mCalibrationStored = false; + TFormula* mMCScale = nullptr; + float mMCScalePars[6] = {0.0}; + TH1* mhVtxAmpCorrV0A = nullptr; + TH1* mhVtxAmpCorrV0C = nullptr; + TH1* mhMultSelCalib = nullptr; + } Run2V0MInfo; + struct TagRun2V0ACalibration { + bool mCalibrationStored = false; + TH1* mhVtxAmpCorrV0A = nullptr; + TH1* mhMultSelCalib = nullptr; + } Run2V0AInfo; + struct TagRun2SPDTrackletsCalibration { + bool mCalibrationStored = false; + TH1* mhVtxAmpCorr = nullptr; + TH1* mhMultSelCalib = nullptr; + } Run2SPDTksInfo; + struct TagRun2SPDClustersCalibration { + bool mCalibrationStored = false; + TH1* mhVtxAmpCorrCL0 = nullptr; + TH1* mhVtxAmpCorrCL1 = nullptr; + TH1* mhMultSelCalib = nullptr; + } Run2SPDClsInfo; + struct TagRun2CL0Calibration { + bool mCalibrationStored = false; + TH1* mhVtxAmpCorr = nullptr; + TH1* mhMultSelCalib = nullptr; + } Run2CL0Info; + struct TagRun2CL1Calibration { + bool mCalibrationStored = false; + TH1* mhVtxAmpCorr = nullptr; + TH1* mhMultSelCalib = nullptr; + } Run2CL1Info; + struct CalibrationInfo { + std::string name = ""; + bool mCalibrationStored = false; + TH1* mhMultSelCalib = nullptr; + float mMCScalePars[6] = {0.0}; + TFormula* mMCScale = nullptr; + explicit CalibrationInfo(std::string name) + : name(name), + mCalibrationStored(false), + mhMultSelCalib(nullptr), + mMCScalePars{0.0}, + mMCScale(nullptr) + { + } + bool isSane(bool fatalize = false) + { + if (!mhMultSelCalib) { + return true; + } + for (int i = 1; i < mhMultSelCalib->GetNbinsX() + 1; i++) { + if (mhMultSelCalib->GetXaxis()->GetBinLowEdge(i) > mhMultSelCalib->GetXaxis()->GetBinUpEdge(i)) { + if (fatalize) { + LOG(fatal) << "Centrality calibration table " << name << " has bins with low edge > up edge"; + } + LOG(warning) << "Centrality calibration table " << name << " has bins with low edge > up edge"; + return false; + } + } + return true; + } + }; + + CalibrationInfo fv0aInfo = CalibrationInfo("FV0"); + CalibrationInfo ft0mInfo = CalibrationInfo("FT0"); + CalibrationInfo ft0aInfo = CalibrationInfo("FT0A"); + CalibrationInfo ft0cInfo = CalibrationInfo("FT0C"); + CalibrationInfo ft0cVariant1Info = CalibrationInfo("FT0Cvar1"); + CalibrationInfo fddmInfo = CalibrationInfo("FDD"); + CalibrationInfo ntpvInfo = CalibrationInfo("NTracksPV"); + CalibrationInfo nGlobalInfo = CalibrationInfo("NGlobal"); + CalibrationInfo mftInfo = CalibrationInfo("MFT"); + + template + void init(TConfigurables& opts, TInitContext& context) + { + // read in configurations from the task where it's used + internalOpts = opts; + internalOpts.mEnabledTables.resize(nTablesConst, 0); + + LOGF(info, "Configuring tables to generate"); + auto& workflows = context.services().template get(); + + TString listOfRequestors[nTablesConst]; + for (int i = 0; i < nTablesConst; i++) { + int f = internalOpts.enabledTables->get(tableNames[i].c_str(), "enable"); + if (f == 1) { + internalOpts.mEnabledTables[i] = 1; + listOfRequestors[i] = "manual enabling"; + } + if (f == -1) { + // autodetect this table in other devices + for (o2::framework::DeviceSpec const& device : workflows.devices) { + // Step 1: check if this device subscribed to the V0data table + for (auto const& input : device.inputs) { + if (o2::framework::DataSpecUtils::partialMatch(input.matcher, o2::header::DataOrigin("AOD"))) { + auto&& [origin, description, version] = o2::framework::DataSpecUtils::asConcreteDataMatcher(input.matcher); + std::string tableNameWithVersion = tableNames[i]; + if (version > 0) { + tableNameWithVersion += Form("_%03d", version); + } + if (input.matcher.binding == tableNameWithVersion) { + LOGF(info, "Device %s has subscribed to %s (version %i)", device.name, tableNames[i], version); + listOfRequestors[i].Append(Form("%s ", device.name.c_str())); + internalOpts.mEnabledTables[i] = 1; + } + } + } + } + } + } + + opts = internalOpts; + + // list enabled tables + for (int i = 0; i < nTablesConst; i++) { + // printout to be improved in the future + if (internalOpts.mEnabledTables[i]) { + LOGF(info, " -~> Table enabled: %s, requested by %s", tableNames[i], listOfRequestors[i].Data()); + } + } + + // dependency checker + if (internalOpts.mEnabledTables[kCentFV0As] && !internalOpts.mEnabledTables[kFV0MultZeqs]) { + internalOpts.mEnabledTables[kFV0MultZeqs] = 1; + listOfRequestors[kFV0MultZeqs].Append(Form("%s ", "dependency check")); + } + if ((internalOpts.mEnabledTables[kCentFT0As] || internalOpts.mEnabledTables[kCentFT0Cs] || internalOpts.mEnabledTables[kCentFT0Ms] || internalOpts.mEnabledTables[kCentFT0CVariant1s]) && !internalOpts.mEnabledTables[kFT0MultZeqs]) { + internalOpts.mEnabledTables[kFT0MultZeqs] = 1; + listOfRequestors[kFT0MultZeqs].Append(Form("%s ", "dependency check")); + } + if (internalOpts.mEnabledTables[kCentFDDMs] && !internalOpts.mEnabledTables[kFDDMultZeqs]) { + internalOpts.mEnabledTables[kFDDMultZeqs] = 1; + listOfRequestors[kFDDMultZeqs].Append(Form("%s ", "dependency check")); + } + + mRunNumber = 0; + mRunNumberCentrality = 0; + lCalibLoaded = false; + hVtxZFV0A = nullptr; + hVtxZFT0A = nullptr; + hVtxZFT0C = nullptr; + hVtxZFDDA = nullptr; + hVtxZFDDC = nullptr; + hVtxZNTracks = nullptr; + } + + //__________________________________________________ + template + o2::common::multiplicity::multEntry collisionProcessRun2(TCollision const& collision, TTracks const& tracks, TBC const& bc, TOutputGroup& cursors) + { + // initialize properties + o2::common::multiplicity::multEntry mults; + + mults.posZ = collision.posZ(); + mults.spdClustersL0 = bc.spdClustersL0(); + mults.spdClustersL1 = bc.spdClustersL1(); + //_______________________________________________________________________ + // forward detector signals, raw + if (collision.has_fv0a()) { + for (const auto& amplitude : collision.fv0a().amplitude()) { + mults.multFV0A += amplitude; + } + } + if (collision.has_fv0c()) { + for (const auto& amplitude : collision.fv0c().amplitude()) { + mults.multFV0C += amplitude; + } + } + if (collision.has_ft0()) { + auto ft0 = collision.ft0(); + for (const auto& amplitude : ft0.amplitudeA()) { + mults.multFT0A += amplitude; + } + for (const auto& amplitude : ft0.amplitudeC()) { + mults.multFT0C += amplitude; + } + } + if (collision.has_zdc()) { + auto zdc = collision.zdc(); + mults.multZNA = zdc.energyCommonZNA(); + mults.multZNC = zdc.energyCommonZNC(); + } + + //_______________________________________________________________________ + // determine if barrel track loop is required, do it (once!) if so but save CPU if not + if (internalOpts.mEnabledTables[kPVMults] || internalOpts.mEnabledTables[kTPCMults] || internalOpts.mEnabledTables[kTrackletMults]) { + // Try to do something Similar to https://github.com/alisw/AliPhysics/blob/22862a945004f719f8e9664c0264db46e7186a48/OADB/AliPPVsMultUtils.cxx#L541C26-L541C37 + for (const auto& track : tracks) { + // check whether the track is a tracklet + if (track.trackType() == o2::aod::track::Run2Tracklet) { + if (internalOpts.mEnabledTables[kTrackletMults]) { + mults.multTracklets++; + } + if (internalOpts.mEnabledTables[kPVMults]) { + if (std::abs(track.eta()) < 1.0) { + mults.multNContribsEta1++; // pvmults + if (std::abs(track.eta()) < 0.8) { + mults.multNContribs++; // pvmults + if (std::abs(track.eta()) < 0.5) { + mults.multNContribsEtaHalf++; // pvmults + } + } + } + } + } + // check whether the track is a global ITS-TPC track + if (track.tpcNClsFindable() > 0) { + if (internalOpts.mEnabledTables[kTPCMults]) { + mults.multTPC++; + } + } + } + } + + // fill standard cursors if required + if (internalOpts.mEnabledTables[kFV0Mults]) { + cursors.tableFV0(mults.multFV0A, mults.multFV0C); + } + if (internalOpts.mEnabledTables[kFT0Mults]) { + cursors.tableFT0(mults.multFT0A, mults.multFT0C); + } + if (internalOpts.mEnabledTables[kFDDMults]) { + cursors.tableFDD(mults.multFDDA, mults.multFDDC); + } + if (internalOpts.mEnabledTables[kZDCMults]) { + cursors.tableZDC(mults.multZNA, mults.multZNC, 0.0f, 0.0f, 0.0f, 0.0f); + } + if (internalOpts.mEnabledTables[kTrackletMults]) { // Tracklets only Run2 + cursors.tableTracklet(mults.multTracklets); + } + if (internalOpts.mEnabledTables[kTPCMults]) { + cursors.tableTpc(mults.multTPC); + } + if (internalOpts.mEnabledTables[kPVMults]) { + cursors.tablePv(mults.multNContribs, mults.multNContribsEta1, mults.multNContribsEtaHalf); + } + + return mults; + } + + //__________________________________________________ + template + o2::common::multiplicity::multEntry collisionProcessRun3(TCCDB const& ccdb, TMetadataInfo const& metadataInfo, TCollision const& collision, TTracks const& tracks, TBC const& bc, TOutputGroup& cursors) + { + // initialize properties + o2::common::multiplicity::multEntry mults; + + //_______________________________________________________________________ + // preparatory steps + if (internalOpts.doVertexZeq > 0) { + if (bc.runNumber() != mRunNumber) { + mRunNumber = bc.runNumber(); // mark this run as at least tried + if (internalOpts.reconstructionPass.value == "") { + lCalibObjects = ccdb->template getForRun(internalOpts.ccdbPathVtxZ, mRunNumber); + } else if (internalOpts.reconstructionPass.value == "metadata") { + std::map metadata; + metadata["RecoPassName"] = metadataInfo.get("RecoPassName"); + LOGF(info, "Loading CCDB for reconstruction pass (from metadata): %s", metadataInfo.get("RecoPassName")); + lCalibObjects = ccdb->template getSpecificForRun(internalOpts.ccdbPathVtxZ, mRunNumber, metadata); + } else { + std::map metadata; + metadata["RecoPassName"] = internalOpts.reconstructionPass.value; + LOGF(info, "Loading CCDB for reconstruction pass (from provided argument): %s", internalOpts.reconstructionPass.value); + lCalibObjects = ccdb->template getSpecificForRun(internalOpts.ccdbPathVtxZ, mRunNumber, metadata); + } + + if (lCalibObjects) { + hVtxZFV0A = static_cast(lCalibObjects->FindObject("hVtxZFV0A")); + hVtxZFT0A = static_cast(lCalibObjects->FindObject("hVtxZFT0A")); + hVtxZFT0C = static_cast(lCalibObjects->FindObject("hVtxZFT0C")); + hVtxZFDDA = static_cast(lCalibObjects->FindObject("hVtxZFDDA")); + hVtxZFDDC = static_cast(lCalibObjects->FindObject("hVtxZFDDC")); + hVtxZNTracks = static_cast(lCalibObjects->FindObject("hVtxZNTracksPV")); + lCalibLoaded = true; + // Capture error + if (!hVtxZFV0A || !hVtxZFT0A || !hVtxZFT0C || !hVtxZFDDA || !hVtxZFDDC || !hVtxZNTracks) { + LOGF(error, "Problem loading CCDB objects! Please check"); + lCalibLoaded = false; + } + } else { + LOGF(error, "Problem loading CCDB object! Please check"); + lCalibLoaded = false; + } + } + } + + //_______________________________________________________________________ + // forward detector signals, raw + if (collision.has_foundFV0()) { + const auto& fv0 = collision.foundFV0(); + for (size_t ii = 0; ii < fv0.amplitude().size(); ii++) { + auto amplitude = fv0.amplitude()[ii]; + auto channel = fv0.channel()[ii]; + mults.multFV0A += amplitude; + if (channel > 7) { + mults.multFV0AOuter += amplitude; + } + } + } else { + mults.multFV0A = -999.f; + mults.multFV0AOuter = -999.f; + } + if (collision.has_foundFT0()) { + const auto& ft0 = collision.foundFT0(); + for (const auto& amplitude : ft0.amplitudeA()) { + mults.multFT0A += amplitude; + } + for (const auto& amplitude : ft0.amplitudeC()) { + mults.multFT0C += amplitude; + } + } else { + mults.multFT0A = -999.f; + mults.multFT0C = -999.f; + } + if (collision.has_foundFDD()) { + const auto& fdd = collision.foundFDD(); + for (const auto& amplitude : fdd.chargeA()) { + mults.multFDDA += amplitude; + } + for (const auto& amplitude : fdd.chargeC()) { + mults.multFDDC += amplitude; + } + } else { + mults.multFDDA = -999.f; + mults.multFDDC = -999.f; + } + if (bc.has_zdc()) { + mults.multZNA = bc.zdc().amplitudeZNA(); + mults.multZNC = bc.zdc().amplitudeZNC(); + mults.multZEM1 = bc.zdc().amplitudeZEM1(); + mults.multZEM2 = bc.zdc().amplitudeZEM2(); + mults.multZPA = bc.zdc().amplitudeZPA(); + mults.multZPC = bc.zdc().amplitudeZPC(); + } else { + mults.multZNA = -999.f; + mults.multZNC = -999.f; + mults.multZEM1 = -999.f; + mults.multZEM2 = -999.f; + mults.multZPA = -999.f; + mults.multZPC = -999.f; + } + + // fill standard cursors if required + if (internalOpts.mEnabledTables[kTrackletMults]) { // Tracklets (only Run2) nothing to do (to be removed!) + cursors.tableTracklet(0); + } + if (internalOpts.mEnabledTables[kFV0Mults]) { + cursors.tableFV0(mults.multFV0A, mults.multFV0C); + } + if (internalOpts.mEnabledTables[kFV0AOuterMults]) { + cursors.tableFV0AOuter(mults.multFV0AOuter); + } + if (internalOpts.mEnabledTables[kFT0Mults]) { + cursors.tableFT0(mults.multFT0A, mults.multFT0C); + } + if (internalOpts.mEnabledTables[kFDDMults]) { + cursors.tableFDD(mults.multFDDA, mults.multFDDC); + } + if (internalOpts.mEnabledTables[kZDCMults]) { + cursors.tableZDC(mults.multZNA, mults.multZNC, mults.multZEM1, mults.multZEM2, mults.multZPA, mults.multZPC); + } + + //_______________________________________________________________________ + // forward detector signals, vertex-Z equalized + if (internalOpts.mEnabledTables[kFV0MultZeqs]) { + if (std::fabs(collision.posZ() && lCalibLoaded)) { + mults.multFV0AZeq = hVtxZFV0A->Interpolate(0.0) * mults.multFV0A / hVtxZFV0A->Interpolate(collision.posZ()); + } else { + mults.multFV0AZeq = 0.0f; + } + cursors.tableFV0Zeqs(mults.multFV0AZeq); + } + if (internalOpts.mEnabledTables[kFT0MultZeqs]) { + if (std::fabs(collision.posZ() && lCalibLoaded)) { + mults.multFT0AZeq = hVtxZFT0A->Interpolate(0.0) * mults.multFT0A / hVtxZFT0A->Interpolate(collision.posZ()); + mults.multFT0CZeq = hVtxZFT0C->Interpolate(0.0) * mults.multFT0C / hVtxZFT0C->Interpolate(collision.posZ()); + } else { + mults.multFT0AZeq = 0.0f; + mults.multFT0CZeq = 0.0f; + } + cursors.tableFT0Zeqs(mults.multFT0AZeq, mults.multFT0CZeq); + } + if (internalOpts.mEnabledTables[kFDDMultZeqs]) { + if (std::fabs(collision.posZ() && lCalibLoaded)) { + mults.multFDDAZeq = hVtxZFDDA->Interpolate(0.0) * mults.multFDDA / hVtxZFDDA->Interpolate(collision.posZ()); + mults.multFDDCZeq = hVtxZFDDC->Interpolate(0.0) * mults.multFDDC / hVtxZFDDC->Interpolate(collision.posZ()); + } else { + mults.multFDDAZeq = 0.0f; + mults.multFDDCZeq = 0.0f; + } + cursors.tableFDDZeqs(mults.multFDDAZeq, mults.multFDDCZeq); + } + + //_______________________________________________________________________ + // determine if barrel track loop is required, do it (once!) if so but save CPU if not + if (internalOpts.mEnabledTables[kTPCMults] || internalOpts.mEnabledTables[kPVMults] || internalOpts.mEnabledTables[kMultsExtra] || internalOpts.mEnabledTables[kPVMultZeqs] || internalOpts.mEnabledTables[kMultsGlobal]) { + // single loop to calculate all + for (const auto& track : tracks) { + if (track.hasTPC()) { + mults.multTPC++; + if (track.hasITS()) { + mults.multAllTracksITSTPC++; // multsextra + } else { + mults.multAllTracksTPCOnly++; // multsextra + } + } + // PV contributor checked explicitly + if (track.isPVContributor()) { + if (std::abs(track.eta()) < 1.0) { + mults.multNContribsEta1++; // pvmults + if (std::abs(track.eta()) < 0.8) { + mults.multNContribs++; // pvmults + if (std::abs(track.eta()) < 0.5) { + mults.multNContribsEtaHalf++; // pvmults + } + } + } + if (track.hasITS()) { + mults.multHasITS++; // multsextra + if (track.hasTPC()) + mults.multITSTPC++; // multsextra + if (!track.hasTPC() && !track.hasTOF() && !track.hasTRD()) { + mults.multITSOnly++; // multsextra + } + } + if (track.hasTPC()) { + mults.multHasTPC++; // multsextra + if (!track.hasITS() && !track.hasTOF() && !track.hasTRD()) { + mults.multTPCOnly++; // multsextra + } + } + if (track.hasTOF()) { + mults.multHasTOF++; // multsextra + } + if (track.hasTRD()) { + mults.multHasTRD++; // multsextra + } + } + + // global counters: do them only in case information is provided in tracks table + if constexpr (requires { tracks.isQualityTrack(); }) { + if (track.pt() < internalOpts.maxPtGlobalTrack.value && track.pt() > internalOpts.minPtGlobalTrack.value && std::fabs(track.eta()) < 1.0f && track.isPVContributor() && tracks.isQualityTrack()) { + if (track.itsNCls() < internalOpts.minNclsITSGlobalTrack || track.itsNClsInnerBarrel() < internalOpts.minNclsITSibGlobalTrack) { + continue; + } + mults.multNbrContribsEta10GlobalTrackWoDCA++; + + if (std::abs(track.eta()) < 0.8) { + mults.multNbrContribsEta08GlobalTrackWoDCA++; + } + if (std::abs(track.eta()) < 0.5) { + mults.multNbrContribsEta05GlobalTrackWoDCA++; + } + } + if (std::fabs(track.eta()) < 0.8 && track.tpcNClsFound() >= 80 && track.tpcNClsCrossedRows() >= 100) { + if (track.isGlobalTrack()) { + mults.multGlobalTracks++; + } + } + } // end constexpr requires track selection stuff + } + + cursors.multsGlobal(mults.multGlobalTracks, mults.multNbrContribsEta08GlobalTrackWoDCA, mults.multNbrContribsEta10GlobalTrackWoDCA, mults.multNbrContribsEta05GlobalTrackWoDCA); + } + + // fill track counters at this stage if requested + if (internalOpts.mEnabledTables[kTPCMults]) { + cursors.tableTpc(mults.multTPC); + } + if (internalOpts.mEnabledTables[kPVMults]) { + cursors.tablePv(mults.multNContribs, mults.multNContribsEta1, mults.multNContribsEtaHalf); + } + if (internalOpts.mEnabledTables[kMultsExtra]) { + cursors.tableExtra(collision.numContrib(), collision.chi2(), collision.collisionTimeRes(), + bc.runNumber(), collision.posZ(), collision.sel8(), + mults.multHasITS, mults.multHasTPC, mults.multHasTOF, mults.multHasTRD, + mults.multITSOnly, mults.multTPCOnly, mults.multITSTPC, + mults.multAllTracksTPCOnly, mults.multAllTracksITSTPC, + collision.trackOccupancyInTimeRange(), + collision.ft0cOccupancyInTimeRange(), + collision.flags()); + } + if (internalOpts.mEnabledTables[kPVMultZeqs]) { + if (std::fabs(collision.posZ()) && lCalibLoaded) { + mults.multNContribsZeq = hVtxZNTracks->Interpolate(0.0) * mults.multNContribs / hVtxZNTracks->Interpolate(collision.posZ()); + } else { + mults.multNContribsZeq = 0.0f; + } + cursors.tablePVZeqs(mults.multNContribsZeq); + } + + // return multiplicity object such that it is handled properly when computing centrality + return mults; + } + + //__________________________________________________ + template + void collisionProcessMonteCarlo(TMCCollision const& mccollision, TMCParticles const& mcparticles, TPDGService const& pdg, TOutputGroup& cursors) + { + int multFT0A = 0; + int multFV0A = 0; + int multFT0C = 0; + int multFDDA = 0; + int multFDDC = 0; + int multBarrelEta05 = 0; + int multBarrelEta08 = 0; + int multBarrelEta10 = 0; + for (auto const& mcPart : mcparticles) { + if (!mcPart.isPhysicalPrimary()) { + continue; + } + + auto charge = 0.; + auto* p = pdg->GetParticle(mcPart.pdgCode()); + if (p != nullptr) { + charge = p->Charge(); + } + if (std::abs(charge) < 1e-3) { + continue; // reject neutral particles in counters + } + + if (std::abs(mcPart.eta()) < 1.0) { + multBarrelEta10++; + if (std::abs(mcPart.eta()) < 0.8) { + multBarrelEta08++; + if (std::abs(mcPart.eta()) < 0.5) { + multBarrelEta05++; + } + } + } + if (-3.3 < mcPart.eta() && mcPart.eta() < -2.1) + multFT0C++; + if (3.5 < mcPart.eta() && mcPart.eta() < 4.9) + multFT0A++; + if (2.2 < mcPart.eta() && mcPart.eta() < 5.0) + multFV0A++; + if (-6.9 < mcPart.eta() && mcPart.eta() < -4.9) + multFDDC++; + if (4.7 < mcPart.eta() && mcPart.eta() < 6.3) + multFDDA++; + } + cursors.tableExtraMc(multFT0A, multFT0C, multFV0A, multFDDA, multFDDC, multBarrelEta05, multBarrelEta08, multBarrelEta10, mccollision.posZ()); + } + + //__________________________________________________ + template + void collisionProcessMFT(TCollision const& collision, TMFTTracks const& mfttracks, TBestCollisionsFwd const& retracks, TMultBuffer& mults, TOutputGroup& cursors) + { + int nAllTracks = 0; + int nTracks = 0; + + for (const auto& track : mfttracks) { + if (track.nClusters() >= 5) { // hardcoded for now + nAllTracks++; + } + } + + if (retracks.size() > 0) { + for (const auto& retrack : retracks) { + auto track = retrack.mfttrack(); + if (track.nClusters() < 5) { + continue; // min cluster requirement + } + if ((track.eta() > -2.0f) && (track.eta() < -3.9f)) { + continue; // too far to be of true interest + } + if (std::abs(retrack.bestDCAXY()) > 2.0f) { + continue; // does not point to PV properly + } + nTracks++; + } + } + cursors.mftMults(nAllTracks, nTracks); + mults[collision.globalIndex()].multMFTAllTracks = nAllTracks; + mults[collision.globalIndex()].multMFTTracks = nTracks; + } + + //__________________________________________________ + template + void ConfigureCentralityRun2(TCCDB& ccdb, TMetadata const& metadataInfo, TBC const& bc) + { + if (bc.runNumber() != mRunNumberCentrality) { + mRunNumberCentrality = bc.runNumber(); // mark that this run has been attempted already regardless of outcome + LOGF(info, "centrality loading procedure for timestamp=%llu, run number=%d", bc.timestamp(), bc.runNumber()); + TList* callst = nullptr; + // Check if the ccdb path is a root file + if (internalOpts.ccdbPathCentrality.value.find(".root") != std::string::npos) { + TFile f(internalOpts.ccdbPathCentrality.value.c_str(), "READ"); + f.GetObject(internalOpts.reconstructionPass.value.c_str(), callst); + if (!callst) { + f.ls(); + LOG(fatal) << "No calibration list " << internalOpts.reconstructionPass.value << " found."; + } + } else { + if (internalOpts.reconstructionPass.value == "") { + callst = ccdb->template getForRun(internalOpts.ccdbPathCentrality, bc.runNumber()); + } else if (internalOpts.reconstructionPass.value == "metadata") { + std::map metadata; + metadata["RecoPassName"] = metadataInfo.get("RecoPassName"); + LOGF(info, "Loading CCDB for reconstruction pass (from metadata): %s", metadataInfo.get("RecoPassName")); + callst = ccdb->template getSpecificForRun(internalOpts.ccdbPathCentrality, bc.runNumber(), metadata); + } else { + std::map metadata; + metadata["RecoPassName"] = internalOpts.reconstructionPass.value; + LOGF(info, "Loading CCDB for reconstruction pass (from provided argument): %s", internalOpts.reconstructionPass.value); + callst = ccdb->template getSpecificForRun(internalOpts.ccdbPathCentrality, bc.runNumber(), metadata); + } + } + + Run2V0MInfo.mCalibrationStored = false; + Run2V0AInfo.mCalibrationStored = false; + Run2SPDTksInfo.mCalibrationStored = false; + Run2SPDClsInfo.mCalibrationStored = false; + Run2CL0Info.mCalibrationStored = false; + Run2CL1Info.mCalibrationStored = false; + if (callst != nullptr) { + auto getccdb = [callst](const char* ccdbhname) { + TH1* h = reinterpret_cast(callst->FindObject(ccdbhname)); + return h; + }; + auto getformulaccdb = [callst](const char* ccdbhname) { + TFormula* f = reinterpret_cast(callst->FindObject(ccdbhname)); + return f; + }; + + if (internalOpts.mEnabledTables[kCentRun2V0Ms]) { + LOGF(debug, "Getting new histograms with %d run number for %d run number", mRunNumber, bc.runNumber()); + Run2V0MInfo.mhVtxAmpCorrV0A = getccdb("hVtx_fAmplitude_V0A_Normalized"); + Run2V0MInfo.mhVtxAmpCorrV0C = getccdb("hVtx_fAmplitude_V0C_Normalized"); + Run2V0MInfo.mhMultSelCalib = getccdb("hMultSelCalib_V0M"); + Run2V0MInfo.mMCScale = getformulaccdb(TString::Format("%s-V0M", internalOpts.generatorName->c_str()).Data()); + if ((Run2V0MInfo.mhVtxAmpCorrV0A != nullptr) && (Run2V0MInfo.mhVtxAmpCorrV0C != nullptr) && (Run2V0MInfo.mhMultSelCalib != nullptr)) { + if (internalOpts.generatorName->length() != 0) { + if (Run2V0MInfo.mMCScale != nullptr) { + for (int ixpar = 0; ixpar < 6; ++ixpar) { + Run2V0MInfo.mMCScalePars[ixpar] = Run2V0MInfo.mMCScale->GetParameter(ixpar); + } + } else { + // continue filling with non-valid values (105) + LOGF(info, "MC Scale information from V0M for run %d not available", bc.runNumber()); + } + } + Run2V0MInfo.mCalibrationStored = true; + } else { + // continue filling with non-valid values (105) + LOGF(info, "Calibration information from V0M for run %d corrupted, will fill V0M tables with dummy values", bc.runNumber()); + } + } + if (internalOpts.mEnabledTables[kCentRun2V0As]) { + LOGF(debug, "Getting new histograms with %d run number for %d run number", mRunNumber, bc.runNumber()); + Run2V0AInfo.mhVtxAmpCorrV0A = getccdb("hVtx_fAmplitude_V0A_Normalized"); + Run2V0AInfo.mhMultSelCalib = getccdb("hMultSelCalib_V0A"); + if ((Run2V0AInfo.mhVtxAmpCorrV0A != nullptr) && (Run2V0AInfo.mhMultSelCalib != nullptr)) { + Run2V0AInfo.mCalibrationStored = true; + } else { + // continue filling with non-valid values (105) + LOGF(info, "Calibration information from V0A for run %d corrupted, will fill V0A tables with dummy values", bc.runNumber()); + } + } + if (internalOpts.mEnabledTables[kCentRun2SPDTrks]) { + LOGF(debug, "Getting new histograms with %d run number for %d run number", mRunNumber, bc.runNumber()); + Run2SPDTksInfo.mhVtxAmpCorr = getccdb("hVtx_fnTracklets_Normalized"); + Run2SPDTksInfo.mhMultSelCalib = getccdb("hMultSelCalib_SPDTracklets"); + if ((Run2SPDTksInfo.mhVtxAmpCorr != nullptr) && (Run2SPDTksInfo.mhMultSelCalib != nullptr)) { + Run2SPDTksInfo.mCalibrationStored = true; + } else { + // continue filling with non-valid values (105) + LOGF(info, "Calibration information from SPD tracklets for run %d corrupted, will fill SPD tracklets tables with dummy values", bc.runNumber()); + } + } + if (internalOpts.mEnabledTables[kCentRun2SPDClss]) { + LOGF(debug, "Getting new histograms with %d run number for %d run number", mRunNumber, bc.runNumber()); + Run2SPDClsInfo.mhVtxAmpCorrCL0 = getccdb("hVtx_fnSPDClusters0_Normalized"); + Run2SPDClsInfo.mhVtxAmpCorrCL1 = getccdb("hVtx_fnSPDClusters1_Normalized"); + Run2SPDClsInfo.mhMultSelCalib = getccdb("hMultSelCalib_SPDClusters"); + if ((Run2SPDClsInfo.mhVtxAmpCorrCL0 != nullptr) && (Run2SPDClsInfo.mhVtxAmpCorrCL1 != nullptr) && (Run2SPDClsInfo.mhMultSelCalib != nullptr)) { + Run2SPDClsInfo.mCalibrationStored = true; + } else { + // continue filling with non-valid values (105) + LOGF(info, "Calibration information from SPD clusters for run %d corrupted, will fill SPD clusters tables with dummy values", bc.runNumber()); + } + } + if (internalOpts.mEnabledTables[kCentRun2CL0s]) { + LOGF(debug, "Getting new histograms with %d run number for %d run number", mRunNumber, bc.runNumber()); + Run2CL0Info.mhVtxAmpCorr = getccdb("hVtx_fnSPDClusters0_Normalized"); + Run2CL0Info.mhMultSelCalib = getccdb("hMultSelCalib_CL0"); + if ((Run2CL0Info.mhVtxAmpCorr != nullptr) && (Run2CL0Info.mhMultSelCalib != nullptr)) { + Run2CL0Info.mCalibrationStored = true; + } else { + // continue filling with non-valid values (105) + LOGF(info, "Calibration information from CL0 multiplicity for run %d corrupted, will fill CL0 multiplicity tables with dummy values", bc.runNumber()); + } + } + if (internalOpts.mEnabledTables[kCentRun2CL1s]) { + LOGF(debug, "Getting new histograms with %d run number for %d run number", mRunNumber, bc.runNumber()); + Run2CL1Info.mhVtxAmpCorr = getccdb("hVtx_fnSPDClusters1_Normalized"); + Run2CL1Info.mhMultSelCalib = getccdb("hMultSelCalib_CL1"); + if ((Run2CL1Info.mhVtxAmpCorr != nullptr) && (Run2CL1Info.mhMultSelCalib != nullptr)) { + Run2CL1Info.mCalibrationStored = true; + } else { + // continue filling with non-valid values (105) + LOGF(info, "Calibration information from CL1 multiplicity for run %d corrupted, will fill CL1 multiplicity tables with dummy values", bc.runNumber()); + } + } + } else { + LOGF(info, "Centrality calibration is not available in CCDB for run=%d at timestamp=%llu, will fill tables with dummy values", bc.runNumber(), bc.timestamp()); + } + } + } + + //__________________________________________________ + template + void ConfigureCentralityRun3(TCCDB& ccdb, TMetadata const& metadataInfo, TBC const& bc) + { + if (bc.runNumber() != mRunNumberCentrality) { + mRunNumberCentrality = bc.runNumber(); // mark that this run has been attempted already regardless of outcome + LOGF(info, "centrality loading procedure for timestamp=%llu, run number=%d", bc.timestamp(), bc.runNumber()); + TList* callst = nullptr; + // Check if the ccdb path is a root file + if (internalOpts.ccdbPathCentrality.value.find(".root") != std::string::npos) { + TFile f(internalOpts.ccdbPathCentrality.value.c_str(), "READ"); + f.GetObject(internalOpts.reconstructionPass.value.c_str(), callst); + if (!callst) { + f.ls(); + LOG(fatal) << "No calibration list " << internalOpts.reconstructionPass.value << " found."; + } + } else { + if (internalOpts.reconstructionPass.value == "") { + callst = ccdb->template getForRun(internalOpts.ccdbPathCentrality, bc.runNumber()); + } else if (internalOpts.reconstructionPass.value == "metadata") { + std::map metadata; + metadata["RecoPassName"] = metadataInfo.get("RecoPassName"); + LOGF(info, "Loading CCDB for reconstruction pass (from metadata): %s", metadataInfo.get("RecoPassName")); + callst = ccdb->template getSpecificForRun(internalOpts.ccdbPathCentrality, bc.runNumber(), metadata); + } else { + std::map metadata; + metadata["RecoPassName"] = internalOpts.reconstructionPass.value; + LOGF(info, "Loading CCDB for reconstruction pass (from provided argument): %s", internalOpts.reconstructionPass.value); + callst = ccdb->template getSpecificForRun(internalOpts.ccdbPathCentrality, bc.runNumber(), metadata); + } + } + + fv0aInfo.mCalibrationStored = false; + ft0mInfo.mCalibrationStored = false; + ft0aInfo.mCalibrationStored = false; + ft0cInfo.mCalibrationStored = false; + ft0cVariant1Info.mCalibrationStored = false; + fddmInfo.mCalibrationStored = false; + ntpvInfo.mCalibrationStored = false; + nGlobalInfo.mCalibrationStored = false; + mftInfo.mCalibrationStored = false; + if (callst != nullptr) { + LOGF(info, "Getting new histograms with %d run number for %d run number", mRunNumber, bc.runNumber()); + auto getccdb = [callst, bc](struct CalibrationInfo& estimator, const o2::framework::Configurable generatorName) { // TODO: to consider the name inside the estimator structure + estimator.mhMultSelCalib = reinterpret_cast(callst->FindObject(TString::Format("hCalibZeq%s", estimator.name.c_str()).Data())); + estimator.mMCScale = reinterpret_cast(callst->FindObject(TString::Format("%s-%s", generatorName->c_str(), estimator.name.c_str()).Data())); + if (estimator.mhMultSelCalib != nullptr) { + if (generatorName->length() != 0) { + LOGF(info, "Retrieving MC calibration for %d, generator name: %s", bc.runNumber(), generatorName->c_str()); + if (estimator.mMCScale != nullptr) { + for (int ixpar = 0; ixpar < 6; ++ixpar) { + estimator.mMCScalePars[ixpar] = estimator.mMCScale->GetParameter(ixpar); + LOGF(info, "Parameter index %i value %.5f", ixpar, estimator.mMCScalePars[ixpar]); + } + } else { + LOGF(warning, "MC Scale information from %s for run %d not available", estimator.name.c_str(), bc.runNumber()); + } + } + estimator.mCalibrationStored = true; + estimator.isSane(); + } else { + LOGF(info, "Calibration information from %s for run %d not available, will fill this estimator with invalid values and continue (no crash).", estimator.name.c_str(), bc.runNumber()); + } + }; + + // invoke loading only for requested centralities + if (internalOpts.mEnabledTables[kCentFV0As]) + getccdb(fv0aInfo, internalOpts.generatorName); + if (internalOpts.mEnabledTables[kCentFT0Ms]) + getccdb(ft0mInfo, internalOpts.generatorName); + if (internalOpts.mEnabledTables[kCentFT0As]) + getccdb(ft0aInfo, internalOpts.generatorName); + if (internalOpts.mEnabledTables[kCentFT0Cs]) + getccdb(ft0cInfo, internalOpts.generatorName); + if (internalOpts.mEnabledTables[kCentFT0CVariant1s]) + getccdb(ft0cVariant1Info, internalOpts.generatorName); + if (internalOpts.mEnabledTables[kCentFDDMs]) + getccdb(fddmInfo, internalOpts.generatorName); + if (internalOpts.mEnabledTables[kCentNTPVs]) + getccdb(ntpvInfo, internalOpts.generatorName); + if (internalOpts.mEnabledTables[kCentNGlobals]) + getccdb(nGlobalInfo, internalOpts.generatorName); + if (internalOpts.mEnabledTables[kCentMFTs]) + getccdb(mftInfo, internalOpts.generatorName); + } else { + LOGF(info, "Centrality calibration is not available in CCDB for run=%d at timestamp=%llu, will fill tables with dummy values", bc.runNumber(), bc.timestamp()); + } + } + } + + //__________________________________________________ + template + void generateCentralitiesRun3(TCCDB& ccdb, TMetadata const& metadataInfo, TBCs const& bcs, TMultBuffer const& mults, TOutputGroup& cursors) + { + // takes multiplicity buffer and generates the desirable centrality values (if any) + + // first step: did someone actually ask for it? Otherwise, go home + if ( + internalOpts.mEnabledTables[kCentFV0As] || internalOpts.mEnabledTables[kCentFT0Ms] || + internalOpts.mEnabledTables[kCentFT0As] || internalOpts.mEnabledTables[kCentFT0Cs] || + internalOpts.mEnabledTables[kCentFT0CVariant1s] || internalOpts.mEnabledTables[kCentFDDMs] || + internalOpts.mEnabledTables[kCentNTPVs] || internalOpts.mEnabledTables[kCentNGlobals] || + internalOpts.mEnabledTables[kCentMFTs] || internalOpts.mEnabledTables[kBCCentFT0Ms] || + internalOpts.mEnabledTables[kBCCentFT0As] || internalOpts.mEnabledTables[kBCCentFT0Cs]) { + // check and update centrality calibration objects for Run 3 + const auto& firstbc = bcs.begin(); + ConfigureCentralityRun3(ccdb, metadataInfo, firstbc); + + /************************************************************ + * @brief Populates a table with data based on the given calibration information and multiplicity. + * + * @param table The table to populate. + * @param estimator The calibration information. + * @param multiplicity The multiplicity value. + *************************************************************/ + + auto populateTable = [&](auto& table, struct CalibrationInfo& estimator, float multiplicity, bool isInelGt0) { + const bool assignOutOfRange = internalOpts.embedINELgtZEROselection && !isInelGt0; + auto scaleMC = [](float x, float pars[6]) { + return std::pow(((pars[0] + pars[1] * std::pow(x, pars[2])) - pars[3]) / pars[4], 1.0f / pars[5]); + }; + + float percentile = 105.0f; + float scaledMultiplicity = multiplicity; + if (estimator.mCalibrationStored) { + if (estimator.mMCScale != nullptr) { + scaledMultiplicity = scaleMC(multiplicity, estimator.mMCScalePars); + LOGF(debug, "Unscaled %s multiplicity: %f, scaled %s multiplicity: %f", estimator.name.c_str(), multiplicity, estimator.name.c_str(), scaledMultiplicity); + } + percentile = estimator.mhMultSelCalib->GetBinContent(estimator.mhMultSelCalib->FindFixBin(scaledMultiplicity)); + if (assignOutOfRange) + percentile = 100.5f; + } + LOGF(debug, "%s centrality/multiplicity percentile = %.0f for a zvtx eq %s value %.0f", estimator.name.c_str(), percentile, estimator.name.c_str(), scaledMultiplicity); + table(percentile); + return percentile; + }; + + // populate centralities per event + for (size_t iEv = 0; iEv < mults.size(); iEv++) { + bool isInelGt0 = (mults[iEv].multNContribsEta1 > 0); + if (internalOpts.mEnabledTables[kCentFV0As]) + populateTable(cursors.centFV0A, fv0aInfo, mults[iEv].multFV0AZeq, isInelGt0); + if (internalOpts.mEnabledTables[kCentFT0Ms]) + populateTable(cursors.centFT0M, ft0mInfo, mults[iEv].multFT0AZeq + mults[iEv].multFT0CZeq, isInelGt0); + if (internalOpts.mEnabledTables[kCentFT0As]) + populateTable(cursors.centFT0A, ft0aInfo, mults[iEv].multFT0AZeq, isInelGt0); + if (internalOpts.mEnabledTables[kCentFT0Cs]) + populateTable(cursors.centFT0C, ft0cInfo, mults[iEv].multFT0CZeq, isInelGt0); + if (internalOpts.mEnabledTables[kCentFT0CVariant1s]) + populateTable(cursors.centFT0CVariant1, ft0cVariant1Info, mults[iEv].multFT0CZeq, isInelGt0); + if (internalOpts.mEnabledTables[kCentFDDMs]) + populateTable(cursors.centFDDM, fddmInfo, mults[iEv].multFDDAZeq + mults[iEv].multFDDCZeq, isInelGt0); + if (internalOpts.mEnabledTables[kCentNTPVs]) + populateTable(cursors.centNTPV, ntpvInfo, mults[iEv].multNContribs, isInelGt0); + if (internalOpts.mEnabledTables[kCentNGlobals]) + populateTable(cursors.centNGlobals, nGlobalInfo, mults[iEv].multGlobalTracks, isInelGt0); + if (internalOpts.mEnabledTables[kCentMFTs]) + populateTable(cursors.centMFTs, mftInfo, mults[iEv].multMFTTracks, isInelGt0); + } + + // populate centralities per BC + for (size_t ibc = 0; ibc < static_cast(bcs.size()); ibc++) { + float bcMultFT0A = 0; + float bcMultFT0C = 0; + + const auto& bc = bcs.rawIteratorAt(ibc); + if (bc.has_foundFT0()) { + const auto& ft0 = bc.foundFT0(); + for (const auto& amplitude : ft0.amplitudeA()) { + bcMultFT0A += amplitude; + } + for (const auto& amplitude : ft0.amplitudeC()) { + bcMultFT0C += amplitude; + } + } else { + bcMultFT0A = -999.f; + bcMultFT0C = -999.f; + } + + if (internalOpts.mEnabledTables[kBCCentFT0Ms]) + populateTable(cursors.bcCentFT0M, ft0mInfo, bcMultFT0A + bcMultFT0C, true); + if (internalOpts.mEnabledTables[kBCCentFT0As]) + populateTable(cursors.bcCentFT0A, ft0aInfo, bcMultFT0A, true); + if (internalOpts.mEnabledTables[kBCCentFT0Cs]) + populateTable(cursors.bcCentFT0C, ft0cInfo, bcMultFT0C, true); + } + } + } + //__________________________________________________ + template + void generateCentralitiesRun2(TCCDB& ccdb, TMetadata const& metadataInfo, TBCs const& bcs, TMultBuffer const& mults, TOutputGroup& cursors) + { + // takes multiplicity buffer and generates the desirable centrality values (if any) + // For Run 2 + if ( + internalOpts.mEnabledTables[kCentRun2V0Ms] || internalOpts.mEnabledTables[kCentRun2V0As] || + internalOpts.mEnabledTables[kCentRun2SPDTrks] || internalOpts.mEnabledTables[kCentRun2SPDClss] || + internalOpts.mEnabledTables[kCentRun2CL0s] || internalOpts.mEnabledTables[kCentRun2CL1s]) { + // check and update centrality calibration objects for Run 3 + const auto& firstbc = bcs.begin(); + ConfigureCentralityRun2(ccdb, metadataInfo, firstbc); + + auto scaleMC = [](float x, float pars[6]) { + return std::pow(((pars[0] + pars[1] * std::pow(x, pars[2])) - pars[3]) / pars[4], 1.0f / pars[5]); + }; + + // populate centralities per event + for (size_t iEv = 0; iEv < mults.size(); iEv++) { + if (internalOpts.mEnabledTables[kCentRun2V0Ms]) { + float cV0M = 105.0f; + if (Run2V0MInfo.mCalibrationStored) { + float v0m; + if (Run2V0MInfo.mMCScale != nullptr) { + v0m = scaleMC(mults[iEv].multFV0A + mults[iEv].multFV0C, Run2V0MInfo.mMCScalePars); + LOGF(debug, "Unscaled v0m: %f, scaled v0m: %f", mults[iEv].multFV0A + mults[iEv].multFV0C, v0m); + } else { + v0m = mults[iEv].multFV0A * Run2V0MInfo.mhVtxAmpCorrV0A->GetBinContent(Run2V0MInfo.mhVtxAmpCorrV0A->FindFixBin(mults[iEv].posZ)) + + mults[iEv].multFV0C * Run2V0MInfo.mhVtxAmpCorrV0C->GetBinContent(Run2V0MInfo.mhVtxAmpCorrV0C->FindFixBin(mults[iEv].posZ)); + } + cV0M = Run2V0MInfo.mhMultSelCalib->GetBinContent(Run2V0MInfo.mhMultSelCalib->FindFixBin(v0m)); + } + LOGF(debug, "centRun2V0M=%.0f", cV0M); + // fill centrality columns + cursors.centRun2V0M(cV0M); + } + if (internalOpts.mEnabledTables[kCentRun2V0As]) { + float cV0A = 105.0f; + if (Run2V0AInfo.mCalibrationStored) { + float v0a = mults[iEv].multFV0A * Run2V0AInfo.mhVtxAmpCorrV0A->GetBinContent(Run2V0AInfo.mhVtxAmpCorrV0A->FindFixBin(mults[iEv].posZ)); + cV0A = Run2V0AInfo.mhMultSelCalib->GetBinContent(Run2V0AInfo.mhMultSelCalib->FindFixBin(v0a)); + } + LOGF(debug, "centRun2V0A=%.0f", cV0A); + // fill centrality columns + cursors.centRun2V0A(cV0A); + } + if (internalOpts.mEnabledTables[kCentRun2SPDTrks]) { + float cSPD = 105.0f; + if (Run2SPDTksInfo.mCalibrationStored) { + float spdm = mults[iEv].multTracklets * Run2SPDTksInfo.mhVtxAmpCorr->GetBinContent(Run2SPDTksInfo.mhVtxAmpCorr->FindFixBin(mults[iEv].posZ)); + cSPD = Run2SPDTksInfo.mhMultSelCalib->GetBinContent(Run2SPDTksInfo.mhMultSelCalib->FindFixBin(spdm)); + } + LOGF(debug, "centSPDTracklets=%.0f", cSPD); + cursors.centRun2SPDTracklets(cSPD); + } + if (internalOpts.mEnabledTables[kCentRun2SPDClss]) { + float cSPD = 105.0f; + if (Run2SPDClsInfo.mCalibrationStored) { + float spdm = mults[iEv].spdClustersL0 * Run2SPDClsInfo.mhVtxAmpCorrCL0->GetBinContent(Run2SPDClsInfo.mhVtxAmpCorrCL0->FindFixBin(mults[iEv].posZ)) + + mults[iEv].spdClustersL1 * Run2SPDClsInfo.mhVtxAmpCorrCL1->GetBinContent(Run2SPDClsInfo.mhVtxAmpCorrCL1->FindFixBin(mults[iEv].posZ)); + cSPD = Run2SPDClsInfo.mhMultSelCalib->GetBinContent(Run2SPDClsInfo.mhMultSelCalib->FindFixBin(spdm)); + } + LOGF(debug, "centSPDClusters=%.0f", cSPD); + cursors.centRun2SPDClusters(cSPD); + } + if (internalOpts.mEnabledTables[kCentRun2CL0s]) { + float cCL0 = 105.0f; + if (Run2CL0Info.mCalibrationStored) { + float cl0m = mults[iEv].spdClustersL0 * Run2CL0Info.mhVtxAmpCorr->GetBinContent(Run2CL0Info.mhVtxAmpCorr->FindFixBin(mults[iEv].posZ)); + cCL0 = Run2CL0Info.mhMultSelCalib->GetBinContent(Run2CL0Info.mhMultSelCalib->FindFixBin(cl0m)); + } + LOGF(debug, "centCL0=%.0f", cCL0); + cursors.centRun2CL0(cCL0); + } + if (internalOpts.mEnabledTables[kCentRun2CL1s]) { + float cCL1 = 105.0f; + if (Run2CL1Info.mCalibrationStored) { + float cl1m = mults[iEv].spdClustersL1 * Run2CL1Info.mhVtxAmpCorr->GetBinContent(Run2CL1Info.mhVtxAmpCorr->FindFixBin(mults[iEv].posZ)); + cCL1 = Run2CL1Info.mhMultSelCalib->GetBinContent(Run2CL1Info.mhMultSelCalib->FindFixBin(cl1m)); + } + LOGF(debug, "centCL1=%.0f", cCL1); + cursors.centRun2CL1(cCL1); + } + } + } + } +}; // end BuilderModule + +} // namespace multiplicity +} // namespace common +} // namespace o2 + +#endif // COMMON_TOOLS_MULTMODULE_H_ From 517903c596a3c3bd875094980d817ad7a344d527 Mon Sep 17 00:00:00 2001 From: spucillo <93769017+spucillo@users.noreply.github.com> Date: Fri, 13 Jun 2025 10:09:50 +0200 Subject: [PATCH 058/871] [PWGLF] Update reweighting for cascades in MC (#11597) Co-authored-by: ALICE Action Bot --- PWGLF/Tasks/Strangeness/strangenessInJets.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PWGLF/Tasks/Strangeness/strangenessInJets.cxx b/PWGLF/Tasks/Strangeness/strangenessInJets.cxx index 3cb2ac41f2b..a783c324687 100644 --- a/PWGLF/Tasks/Strangeness/strangenessInJets.cxx +++ b/PWGLF/Tasks/Strangeness/strangenessInJets.cxx @@ -2027,7 +2027,7 @@ struct StrangenessInJets { case kXiPlusBar: // Xi Pos registryMC.fill(HIST("XiPos_generated_jet"), multiplicity, mcParticle.pt(), wXiPosJet); registryMC.fill(HIST("XiPos_generated_ue"), multiplicity, mcParticle.pt(), wXiPosUe); - registryMC.fill(HIST("Xi_eta_pt_pythia"), mcParticle.pt(), mcParticle.eta()); + registryMC.fill(HIST("XiPos_eta_pt_pythia"), mcParticle.pt(), mcParticle.eta()); break; case kXiMinus: // Xi Neg registryMC.fill(HIST("XiNeg_generated_jet"), multiplicity, mcParticle.pt(), wXiNegJet); From 401d3bab557e7e99eae720ee40fae2ba7baab31f Mon Sep 17 00:00:00 2001 From: omvazque Date: Fri, 13 Jun 2025 03:11:25 -0500 Subject: [PATCH 059/871] [PWGLF] Updated the MC correction procedure (#11590) --- PWGLF/Tasks/GlobalEventProperties/uccZdc.cxx | 191 ++++++++++++------- 1 file changed, 124 insertions(+), 67 deletions(-) diff --git a/PWGLF/Tasks/GlobalEventProperties/uccZdc.cxx b/PWGLF/Tasks/GlobalEventProperties/uccZdc.cxx index 7da02f51416..478c49fae87 100644 --- a/PWGLF/Tasks/GlobalEventProperties/uccZdc.cxx +++ b/PWGLF/Tasks/GlobalEventProperties/uccZdc.cxx @@ -15,18 +15,6 @@ /// \author Omar Vazquez (omar.vazquez.rueda@cern.ch) /// \since January 29, 2025 -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - #include "Common/CCDB/EventSelectionParams.h" #include "Common/CCDB/TriggerAliases.h" #include "Common/Core/TrackSelection.h" @@ -34,6 +22,7 @@ #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/TrackSelectionTables.h" + #include "CommonConstants/MathConstants.h" #include "CommonConstants/ZDCConstants.h" #include "Framework/ASoAHelpers.h" // required for Filter op. @@ -44,7 +33,20 @@ #include "Framework/runDataProcessing.h" #include "ReconstructionDataFormats/GlobalTrackID.h" #include "ReconstructionDataFormats/Track.h" +#include + #include "TPDGCode.h" +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include using namespace std; using namespace o2; @@ -81,6 +83,7 @@ struct UccZdc { Configurable isZEMcut{"isZEMcut", true, "Use ZEM cut"}; Configurable useMidRapNchSel{"useMidRapNchSel", true, "Use mid-rapidit Nch selection"}; Configurable applyEff{"applyEff", true, "Apply track-by-track efficiency correction"}; + Configurable correctNch{"correctNch", true, "Correct also Nch"}; // Event selection Configurable posZcut{"posZcut", +10.0, "z-vertex position cut"}; @@ -126,7 +129,8 @@ struct UccZdc { ConfigurableAxis binsCent{"binsCent", {VARIABLE_WIDTH, 0., 10., 20., 30., 40., 50., 60., 70., 80., 90., 100.}, "T0C binning"}; // CCDB paths - Configurable paTH{"paTH", "Users/o/omvazque/TrackingEfficiency", "base path to the ccdb object"}; + Configurable paTHEff{"paTHEff", "Users/o/omvazque/MCcorrection/perTimeStamp/TrackingEff", "base path to the ccdb object"}; + Configurable paTHFD{"paTHFD", "Users/o/omvazque/MCcorrection/perTimeStamp/FeedDown", "base path to the ccdb object"}; Configurable paTHmeanNch{"paTHmeanNch", "Users/o/omvazque/FitMeanNch_9May2025", "base path to the ccdb object"}; Configurable paTHsigmaNch{"paTHsigmaNch", "Users/o/omvazque/FitSigmaNch_9May2025", "base path to the ccdb object"}; Configurable ccdbNoLaterThan{"ccdbNoLaterThan", std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(), "latest acceptable timestamp of creation for the object"}; @@ -238,6 +242,9 @@ struct UccZdc { registry.add("NchVsThreeParCorr", "MC closure;#it{N}_{ch} (|#eta| < 0.8, Corrected);#LT[#it{p}_{T}^{(3)}]#GT", kTProfile, {{nBinsNch, minNch, maxNch}}); registry.add("NchVsFourParCorr", "MC closure;#it{N}_{ch} (|#eta| < 0.8, Corrected);#LT[#it{p}_{T}^{(4)}]#GT", kTProfile, {{nBinsNch, minNch, maxNch}}); // Corrections + registry.add("NchRec", "Corrections;#it{N}_{ch} (|#eta| < 0.8);Entries;", kTH1F, {{nBinsNch, minNch, maxNch}}); + registry.add("NchTrue", "Corrections;#it{N}_{ch} (|#eta| < 0.8);Entries;", kTH1F, {{nBinsNch, minNch, maxNch}}); + registry.add("zPosMC", "Filled at MC closure + Corrections;;Entries;", kTH1F, {axisZpos}); registry.add("hEventCounterMC", "Event counter", kTH1F, {axisEvent}); registry.add("nRecColvsCent", "", kTH2F, {{6, -0.5, 5.5}, {{axisCent}}}); @@ -292,8 +299,11 @@ struct UccZdc { LOG(info) << "\tccdbNoLaterThan=" << ccdbNoLaterThan.value; LOG(info) << "\tapplyEff=" << applyEff.value; - LOG(info) << "\tpaTH=" << paTH.value; + LOG(info) << "\tcorrectNch=" << correctNch.value; + LOG(info) << "\tpaTHEff=" << paTHEff.value; + LOG(info) << "\tpaTHFD=" << paTHFD.value; LOG(info) << "\tuseMidRapNchSel=" << useMidRapNchSel.value; + LOG(info) << "\tnSigmaNchCut=" << nSigmaNchCut.value; LOG(info) << "\tpaTHmeanNch=" << paTHmeanNch.value; LOG(info) << "\tpaTHsigmaNch=" << paTHsigmaNch.value; LOG(info) << "\tminPt=" << minPt.value; @@ -681,48 +691,55 @@ struct UccZdc { } } + // Skip event based on number of Nch sigmas if (!skipEvent) { return; } - auto efficiency = ccdb->getForTimeStamp(paTH.value, foundBC.timestamp()); - // auto efficiency = ccdb->getForRun(paTH.value, foundBC.runNumber()); - if (!efficiency) { + auto efficiency = ccdb->getForTimeStamp(paTHEff.value, foundBC.timestamp()); + auto fd = ccdb->getForTimeStamp(paTHFD.value, foundBC.timestamp()); + if (!efficiency || !fd) { return; } std::vector pTs; - std::vector wIs; - // Calculates the event weight, W_k + std::vector vecFD; + std::vector vecOneOverEff; + + // Calculates the Nch multiplicity for (const auto& track : tracks) { // Track Selection if (!track.isGlobalTrack()) { continue; } - if ((track.pt() < minPt) || (track.pt() > maxPtSpectra)) { + if ((track.pt() < minPt) || (track.pt() > maxPt)) { continue; } float pt{track.pt()}; - double weight{1.}; + float effValue{1.0}; if (applyEff) { - weight = efficiency->GetBinContent(efficiency->FindBin(pt)); + effValue = efficiency->GetBinContent(efficiency->FindBin(pt)); } - if (weight > 0.) { - pTs.emplace_back(pt); - wIs.emplace_back(weight); + if (effValue > 0.) { + vecOneOverEff.emplace_back(1. / effValue); } } - double p1, p2, p3, p4, w1, w2, w3, w4; - p1 = p2 = p3 = p4 = w1 = w2 = w3 = w4 = 0.0; - getPTpowers(pTs, wIs, p1, w1, p2, w2, p3, w3, p4, w4); - const double nch{static_cast(pTs.size())}; - if (nch < minNchSel) { + double nchMult{0.}; + nchMult = std::accumulate(vecOneOverEff.begin(), vecOneOverEff.end(), 0); + if (!applyEff) + nchMult = static_cast(glbTracks); + if (applyEff && !correctNch) + nchMult = static_cast(glbTracks); + if (nchMult < minNchSel) { return; } - // To calculate event-averaged + // Fill vectors for [pT] measurement + pTs.clear(); + vecFD.clear(); + vecOneOverEff.clear(); for (const auto& track : tracks) { // Track Selection if (!track.isGlobalTrack()) { @@ -731,9 +748,27 @@ struct UccZdc { if ((track.pt() < minPt) || (track.pt() > maxPtSpectra)) { continue; } - registry.fill(HIST("NchVsZNVsPt"), w1, sumZNs, track.pt()); + + float pt{track.pt()}; + float effValue{1.}; + float fdValue{1.}; + if (applyEff) { + effValue = efficiency->GetBinContent(efficiency->FindBin(pt)); + fdValue = fd->GetBinContent(fd->FindBin(pt)); + } + if ((effValue > 0.) && (fdValue > 0.)) { + pTs.emplace_back(pt); + vecOneOverEff.emplace_back(1. / effValue); + vecFD.emplace_back(fdValue); + } + // To calculate event-averaged + registry.fill(HIST("NchVsZNVsPt"), nchMult, sumZNs, track.pt()); } + double p1, p2, p3, p4, w1, w2, w3, w4; + p1 = p2 = p3 = p4 = w1 = w2 = w3 = w4 = 0.0; + getPTpowers(pTs, vecOneOverEff, vecFD, p1, w1, p2, w2, p3, w3, p4, w4); + // EbE one-particle pT correlation double oneParCorr{p1 / w1}; @@ -752,20 +787,20 @@ struct UccZdc { double numFourParCorr{std::pow(p1, 4.) - 6. * p2 * std::pow(p1, 2.) + 3. * std::pow(p2, 2.) + 8 * p3 * p1 - 6. * p4}; double fourParCorr{numFourParCorr / denFourParCorr}; - registry.fill(HIST("Nch"), w1); + registry.fill(HIST("Nch"), nchMult); registry.fill(HIST("ZNamp"), sumZNs); - registry.fill(HIST("NchVsZN"), w1, sumZNs); - registry.fill(HIST("NchVsZP"), w1, sumZPs); + registry.fill(HIST("NchVsZN"), nchMult, sumZNs); + registry.fill(HIST("NchVsZP"), nchMult, sumZPs); registry.fill(HIST("NITSTacksVsZN"), itsTracks, sumZNs); registry.fill(HIST("NITSTacksVsZP"), itsTracks, sumZPs); registry.fill(HIST("T0MVsZN"), normT0M, sumZNs); registry.fill(HIST("T0MVsZP"), normT0M, sumZPs); registry.fill(HIST("NchUncorrected"), glbTracks); - registry.fill(HIST("NchVsOneParCorr"), w1, oneParCorr, w1); - registry.fill(HIST("NchVsOneParCorrVsZN"), w1, sumZNs, oneParCorr, w1); - registry.fill(HIST("NchVsTwoParCorrVsZN"), w1, sumZNs, twoParCorr, denTwoParCorr); - registry.fill(HIST("NchVsThreeParCorrVsZN"), w1, sumZNs, threeParCorr, denThreeParCorr); - registry.fill(HIST("NchVsFourParCorrVsZN"), w1, sumZNs, fourParCorr, denFourParCorr); + registry.fill(HIST("NchVsOneParCorr"), nchMult, oneParCorr, w1); + registry.fill(HIST("NchVsOneParCorrVsZN"), nchMult, sumZNs, oneParCorr, w1); + registry.fill(HIST("NchVsTwoParCorrVsZN"), nchMult, sumZNs, twoParCorr, denTwoParCorr); + registry.fill(HIST("NchVsThreeParCorrVsZN"), nchMult, sumZNs, threeParCorr, denThreeParCorr); + registry.fill(HIST("NchVsFourParCorrVsZN"), nchMult, sumZNs, fourParCorr, denFourParCorr); } PROCESS_SWITCH(UccZdc, processZdcCollAss, "Process ZDC W/Coll Ass.", true); @@ -774,7 +809,6 @@ struct UccZdc { TRandom* randPointer = new TRandom(); void processMCclosure(aod::McCollisions::iterator const& mccollision, soa::SmallGroups const& collisions, o2::aod::BCsRun3 const& /*bcs*/, aod::McParticles const& mcParticles, TheFilteredSimTracks const& simTracks) { - float rndNum = randPointer->Uniform(0.0, 1.0); registry.fill(HIST("RandomNumber"), rndNum); @@ -809,14 +843,17 @@ struct UccZdc { // To use run-by-run efficiency const auto& foundBC = collision.foundBC_as(); - // auto efficiency = ccdb->getForTimeStamp(paTH.value, foundBC.timestamp()); - auto efficiency = ccdb->getForRun(paTH.value, foundBC.runNumber()); - if (!efficiency) { - continue; + auto efficiency = ccdb->getForTimeStamp(paTHEff.value, foundBC.timestamp()); + auto fd = ccdb->getForTimeStamp(paTHFD.value, foundBC.timestamp()); + if (!efficiency || !fd) { + return; } + int nchRaw{0}; std::vector pTs; - std::vector wIs; + std::vector vecFD; + std::vector vecOneOverEff; + // std::vector wIs; const auto& groupedTracks{simTracks.sliceBy(perCollision, collision.globalIndex())}; // Calculates the event weight, W_k for (const auto& track : groupedTracks) { @@ -826,22 +863,29 @@ struct UccZdc { } float pt{track.pt()}; - double weight{efficiency->GetBinContent(efficiency->FindBin(pt))}; - if (!(weight > 0.)) { - continue; + float effValue{1.}; + float fdValue{1.}; + nchRaw++; + if (applyEff) { + effValue = efficiency->GetBinContent(efficiency->FindBin(pt)); + fdValue = fd->GetBinContent(fd->FindBin(pt)); + } + if ((effValue > 0.) && (fdValue > 0.)) { + pTs.emplace_back(pt); + vecOneOverEff.emplace_back(1. / effValue); + vecFD.emplace_back(fdValue); } - pTs.emplace_back(pt); - wIs.emplace_back(weight); } - const double nch{static_cast(pTs.size())}; - if (nch < minNchSel) { - continue; + double nchMult{0.}; + nchMult = std::accumulate(vecOneOverEff.begin(), vecOneOverEff.end(), 0); + if (nchMult < minNchSel) { + return; } double p1, p2, p3, p4, w1, w2, w3, w4; p1 = p2 = p3 = p4 = w1 = w2 = w3 = w4 = 0.0; - getPTpowers(pTs, wIs, p1, w1, p2, w2, p3, w3, p4, w4); + getPTpowers(pTs, vecOneOverEff, vecFD, p1, w1, p2, w2, p3, w3, p4, w4); const double denTwoParCorr{std::pow(w1, 2.) - w2}; const double numTwoParCorr{std::pow(p1, 2.) - p2}; @@ -855,16 +899,18 @@ struct UccZdc { const double threeParCorr{numThreeParCorr / denThreeParCorr}; const double fourParCorr{numFourParCorr / denFourParCorr}; - registry.fill(HIST("Nch"), w1); - registry.fill(HIST("NchUncorrected"), nch); - registry.fill(HIST("NchVsOneParCorr"), w1, oneParCorr, w1); - registry.fill(HIST("NchVsTwoParCorr"), w1, twoParCorr, denTwoParCorr); - registry.fill(HIST("NchVsThreeParCorr"), w1, threeParCorr, denThreeParCorr); - registry.fill(HIST("NchVsFourParCorr"), w1, fourParCorr, denFourParCorr); + registry.fill(HIST("Nch"), nchMult); + registry.fill(HIST("NchUncorrected"), nchRaw); + registry.fill(HIST("NchVsOneParCorr"), nchMult, oneParCorr, w1); + registry.fill(HIST("NchVsTwoParCorr"), nchMult, twoParCorr, denTwoParCorr); + registry.fill(HIST("NchVsThreeParCorr"), nchMult, threeParCorr, denThreeParCorr); + registry.fill(HIST("NchVsFourParCorr"), nchMult, fourParCorr, denFourParCorr); //--------------------------- Generated MC --------------------------- std::vector pTsMC; - std::vector wIsMC; + std::vector vecFullEff; + std::vector vecFDEqualOne; + // Calculates the event weight, W_k for (const auto& particle : mcParticles) { if (particle.eta() < minEta || particle.eta() > maxEta) { @@ -879,17 +925,19 @@ struct UccZdc { float pt{particle.pt()}; pTsMC.emplace_back(pt); - wIsMC.emplace_back(1.); + vecFullEff.emplace_back(1.); + vecFDEqualOne.emplace_back(1.); } - const double nchMC{static_cast(pTsMC.size())}; + double nchMC{0}; + nchMult = std::accumulate(vecFullEff.begin(), vecFullEff.end(), 0); if (nchMC < minNchSel) { continue; } double p1MC, p2MC, p3MC, p4MC, w1MC, w2MC, w3MC, w4MC; p1MC = p2MC = p3MC = p4MC = w1MC = w2MC = w3MC = w4MC = 0.0; - getPTpowers(pTsMC, wIsMC, p1MC, w1MC, p2MC, w2MC, p3MC, w3MC, p4MC, w4MC); + getPTpowers(pTsMC, vecFullEff, vecFDEqualOne, p1MC, w1MC, p2MC, w2MC, p3MC, w3MC, p4MC, w4MC); const double denTwoParCorrMC{std::pow(w1MC, 2.) - w2MC}; const double numTwoParCorrMC{std::pow(p1MC, 2.) - p2MC}; @@ -911,6 +959,8 @@ struct UccZdc { } else { // Correction with the remaining half of the sample registry.fill(HIST("EvtsDivided"), 1); //----- MC reconstructed -----// + int nchTrue{0}; + int nchRec{0}; const auto& groupedTracks{simTracks.sliceBy(perCollision, collision.globalIndex())}; for (const auto& track : groupedTracks) { // Track Selection @@ -932,6 +982,7 @@ struct UccZdc { continue; } + nchRec++; registry.fill(HIST("Pt_ch"), cent, track.pt()); if (particle.pdgCode() == PDG_t::kPiPlus || particle.pdgCode() == PDG_t::kPiMinus) { registry.fill(HIST("Pt_pi"), cent, track.pt()); @@ -960,6 +1011,7 @@ struct UccZdc { continue; } + nchTrue++; registry.fill(HIST("PtMC_ch"), cent, particle.pt()); if (particle.pdgCode() == PDG_t::kPiPlus || particle.pdgCode() == PDG_t::kPiMinus) { // pion registry.fill(HIST("PtMC_pi"), cent, particle.pt()); @@ -975,18 +1027,23 @@ struct UccZdc { registry.fill(HIST("PtMC_re"), cent, particle.pt()); } } + + registry.fill(HIST("NchRec"), nchRec); + registry.fill(HIST("NchTrue"), nchTrue); } // Half of statistics for corrections } // Collisions } PROCESS_SWITCH(UccZdc, processMCclosure, "Process MC closure", false); template - void getPTpowers(const T& pTs, const T& wIs, U& pOne, U& wOne, U& pTwo, U& wTwo, U& pThree, U& wThree, U& pFour, U& wFour) + void getPTpowers(const T& pTs, const T& vecOneOverEff, const T& vecFD, U& pOne, U& wOne, U& pTwo, U& wTwo, U& pThree, U& wThree, U& pFour, U& wFour) { pOne = wOne = pTwo = wTwo = pThree = wThree = pFour = wFour = 0.; for (std::size_t i = 0; i < pTs.size(); ++i) { const float pTi{pTs.at(i)}; - const float wEighti{wIs.at(i)}; + const float eFFi{vecOneOverEff.at(i)}; + const float fDi{vecFD.at(i)}; + const float wEighti{eFFi * fDi}; pOne += wEighti * pTi; wOne += wEighti; pTwo += std::pow(wEighti * pTi, 2.); From 8b56b4963714623d8b950f87f65251c22c995a78 Mon Sep 17 00:00:00 2001 From: jaelpark Date: Fri, 13 Jun 2025 14:07:09 +0200 Subject: [PATCH 060/871] [PWGCF] Fix 2prong filter MC particle indexing (#11585) --- PWGCF/TableProducer/filter2Prong.cxx | 28 +++++++------- PWGCF/Tasks/correlations.cxx | 57 +++++++++++++++------------- 2 files changed, 44 insertions(+), 41 deletions(-) diff --git a/PWGCF/TableProducer/filter2Prong.cxx b/PWGCF/TableProducer/filter2Prong.cxx index 25bee387660..4d86c4deda5 100644 --- a/PWGCF/TableProducer/filter2Prong.cxx +++ b/PWGCF/TableProducer/filter2Prong.cxx @@ -11,26 +11,24 @@ /// \author Jasper Parkkila -#include -#include -#include -#include - -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.h" - -#include "MathUtils/detail/TypeTruncation.h" - #include "PWGCF/DataModel/CorrelationsDerived.h" - #include "PWGHF/Core/HfHelper.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" +#include "MathUtils/detail/TypeTruncation.h" + #include +#include +#include +#include +#include + using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; @@ -143,11 +141,11 @@ struct Filter2Prong { } PROCESS_SWITCH(Filter2Prong, processData, "Process data D0 candidates", true); - void processMC(aod::McCollisions::iterator const&, aod::CFMcParticleRefs const& cfmcparticles, aod::McParticles const& mcparticles) + void processMC(aod::McCollisions::iterator const&, aod::CFMcParticleRefs const& cfmcparticles, [[maybe_unused]] aod::McParticles const& mcparticles) { // The main filter outputs the primary MC particles. Here we just resolve the daughter indices that are needed for the efficiency matching. for (const auto& r : cfmcparticles) { - const auto& mcParticle = mcparticles.iteratorAt(r.mcParticleId()); + const auto& mcParticle = r.mcParticle(); if (mcParticle.daughtersIds().size() != 2) { output2ProngMcParts(-1, -1); continue; diff --git a/PWGCF/Tasks/correlations.cxx b/PWGCF/Tasks/correlations.cxx index 7461cc4b671..1e079482284 100644 --- a/PWGCF/Tasks/correlations.cxx +++ b/PWGCF/Tasks/correlations.cxx @@ -13,36 +13,37 @@ /// \brief task for the correlation calculations with CF-filtered tracks for O2 analysis /// \author Jan Fiete Grosse-Oetringhaus , Jasper Parkkila -#include -#include -#include +#include "PWGCF/Core/CorrelationContainer.h" +#include "PWGCF/Core/PairCuts.h" +#include "PWGCF/DataModel/CorrelationsDerived.h" -#include -#include -#include -#include -#include -#include +#include "Common/Core/RecoDecay.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/TrackSelectionTables.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.h" #include "CCDB/BasicCCDBManager.h" -#include "Framework/StepTHn.h" +#include "CommonConstants/MathConstants.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "DataFormatsParameters/GRPObject.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" #include "Framework/RunningWorkflowInfo.h" -#include "CommonConstants/MathConstants.h" -#include "Common/Core/RecoDecay.h" +#include "Framework/StepTHn.h" +#include "Framework/runDataProcessing.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "Common/DataModel/Centrality.h" -#include "PWGCF/DataModel/CorrelationsDerived.h" -#include "PWGCF/Core/CorrelationContainer.h" -#include "PWGCF/Core/PairCuts.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DataFormatsParameters/GRPMagField.h" +#include +#include +#include +#include +#include + +#include +#include +#include +#include using namespace o2; using namespace o2::framework; @@ -1065,17 +1066,21 @@ struct CorrelationTask { for (const auto& p2track : grouped2ProngTracks) { // Check if the mc particles of the prongs are found. + if (p2track.cfTrackProng0Id() < 0 || p2track.cfTrackProng1Id() < 0) { + // fake track + same->getTrackHistEfficiency()->Fill(CorrelationContainer::Fake, p2track.eta(), p2track.pt(), 0, multiplicity, mcCollision.posZ()); + } const auto& p0 = p2track.cfTrackProng0_as(); const auto& p1 = p2track.cfTrackProng1_as(); if (p0.has_cfMCParticle() && p1.has_cfMCParticle()) { // find the 2-prong MC particle by the daughter MC particle IDs auto m = std::find_if(p2indexCache.begin(), p2indexCache.end(), [&](const auto& t) -> bool { - const auto& mcParticle = mcParticles.iteratorAt(t); + const auto& mcParticle = mcParticles.iteratorAt(t - mcParticles.begin().globalIndex()); return p0.cfMCParticleId() == mcParticle.cfParticleDaugh0Id() && p1.cfMCParticleId() == mcParticle.cfParticleDaugh1Id(); }); if (m == p2indexCache.end()) continue; - const auto& mcParticle = mcParticles.iteratorAt(*m); + const auto& mcParticle = mcParticles.iteratorAt(*m - mcParticles.begin().globalIndex()); if (mcParticle.isPhysicalPrimary()) { same->getTrackHistEfficiency()->Fill(CorrelationContainer::RecoPrimaries, mcParticle.eta(), mcParticle.pt(), getSpecies(mcParticle.pdgCode()), multiplicity, mcCollision.posZ()); } From c45e5ec5e9a1edc422232283272f3e84f32393e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADt=20Ku=C4=8Dera?= Date: Fri, 13 Jun 2025 15:00:03 +0200 Subject: [PATCH 061/871] [PWGHF,Trigger] Include What You Use (#11548) --- EventFiltering/PWGHF/HFFilter.cxx | 75 ++++++++++++------- .../PWGHF/HFFilterCharmHadronSignals.cxx | 58 ++++++++------ EventFiltering/PWGHF/HFFilterHelpers.h | 63 +++++++++------- .../PWGHF/HFFilterPrepareMLSamples.cxx | 53 ++++++++----- 4 files changed, 151 insertions(+), 98 deletions(-) diff --git a/EventFiltering/PWGHF/HFFilter.cxx b/EventFiltering/PWGHF/HFFilter.cxx index 4c0d2d891de..7a538f53f27 100644 --- a/EventFiltering/PWGHF/HFFilter.cxx +++ b/EventFiltering/PWGHF/HFFilter.cxx @@ -8,7 +8,6 @@ // 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. -// O2 includes /// \file HFFilter.cxx /// \brief task for selection of events with HF signals @@ -20,40 +19,60 @@ /// \author Federica Zanone , Heidelberg University /// \author Antonio Palasciano , INFN Bari -#include -#include -#include -#include - -#include "TRandom3.h" - -#include "CommonConstants/PhysicsConstants.h" -#include "CCDB/BasicCCDBManager.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DCAFitter/DCAFitterN.h" -#include "DetectorsBase/Propagator.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/DCA.h" +#include "EventFiltering/PWGHF/HFFilterHelpers.h" +#include "EventFiltering/filterTables.h" +// +#include "PWGHF/Core/SelectorCuts.h" +#include "PWGHF/DataModel/CandidateReconstructionTables.h" +// +#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" #include "Common/Core/RecoDecay.h" #include "Common/Core/trackUtilities.h" #include "Common/DataModel/CollisionAssociationTables.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/PIDResponseITS.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 +#include + +#include -#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" - -#include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" -#include "PWGHF/Utils/utilsTrkCandHf.h" - -#include "EventFiltering/filterTables.h" -#include "EventFiltering/PWGHF/HFFilterHelpers.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include using namespace o2; using namespace o2::soa; diff --git a/EventFiltering/PWGHF/HFFilterCharmHadronSignals.cxx b/EventFiltering/PWGHF/HFFilterCharmHadronSignals.cxx index ab46a5e2504..3cd5a047bb9 100644 --- a/EventFiltering/PWGHF/HFFilterCharmHadronSignals.cxx +++ b/EventFiltering/PWGHF/HFFilterCharmHadronSignals.cxx @@ -8,37 +8,53 @@ // 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. -// O2 includes /// \file HFFilterCharmHadronSignals.cxx /// \brief task for the quality control of the signals of D0, D+, Ds+, Lc+, and D*+ selected in the HFFilter.cxx task /// /// \author Fabrizio Grosa , CERN -#include -#include - -#include "CCDB/BasicCCDBManager.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DetectorsBase/Propagator.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" - +#include "EventFiltering/PWGHF/HFFilterHelpers.h" +// +#include "PWGHF/Core/SelectorCuts.h" +#include "PWGHF/DataModel/CandidateReconstructionTables.h" +// +#include "Common/CCDB/EventSelectionParams.h" +#include "Common/Core/RecoDecay.h" #include "Common/Core/trackUtilities.h" #include "Common/DataModel/CollisionAssociationTables.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/Multiplicity.h" - -#include "PWGHF/Core/SelectorCuts.h" -#include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" - -#include "EventFiltering/filterTables.h" -#include "EventFiltering/PWGHF/HFFilterHelpers.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 +#include using namespace o2; using namespace o2::analysis; diff --git a/EventFiltering/PWGHF/HFFilterHelpers.h b/EventFiltering/PWGHF/HFFilterHelpers.h index 72b2f71cae4..af70e4c05fa 100644 --- a/EventFiltering/PWGHF/HFFilterHelpers.h +++ b/EventFiltering/PWGHF/HFFilterHelpers.h @@ -8,7 +8,6 @@ // 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. -// O2 includes /// \file HFFilterHelpers.h /// \brief Header file with definition of variables, methods, and tables used in the HFFilter.cxx task @@ -23,41 +22,47 @@ #ifndef EVENTFILTERING_PWGHF_HFFILTERHELPERS_H_ #define EVENTFILTERING_PWGHF_HFFILTERHELPERS_H_ +#include "EventFiltering/filterTables.h" +// +#include "PWGHF/Core/SelectorCuts.h" +// +#include "Common/Core/RecoDecay.h" +#include "Common/Core/trackUtilities.h" + +#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 #include +#include #include -#include "Math/GenVector/Boost.h" -#include "Math/Vector3D.h" -#include "Math/Vector4D.h" - -#include "CCDB/CcdbApi.h" -#include "CCDB/BasicCCDBManager.h" -#include "CommonConstants/MathConstants.h" -#include "CommonConstants/PhysicsConstants.h" -#include "DataFormatsTPC/BetheBlochAleph.h" -#include "DCAFitter/DCAFitterN.h" -#include "DetectorsBase/Propagator.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/DataTypes.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/AnalysisHelpers.h" -#include "Framework/O2DatabasePDGPlugin.h" - -#include "Common/Core/RecoDecay.h" -#include "Common/Core/trackUtilities.h" - -#include "PWGHF/Core/SelectorCuts.h" -#include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" - -#include "EventFiltering/filterTables.h" - namespace o2::aod { diff --git a/EventFiltering/PWGHF/HFFilterPrepareMLSamples.cxx b/EventFiltering/PWGHF/HFFilterPrepareMLSamples.cxx index 2a5dda41464..6a5f50eb158 100644 --- a/EventFiltering/PWGHF/HFFilterPrepareMLSamples.cxx +++ b/EventFiltering/PWGHF/HFFilterPrepareMLSamples.cxx @@ -8,7 +8,6 @@ // 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. -// O2 includes /// \file HFFilterPrepareMLSamples.cxx /// \brief task for trainings of ML models to be used in the HFFilter.cxx task @@ -19,31 +18,45 @@ /// \author Biao Zhang , CCNU /// \author Antonio Palasciano , INFN Bari -#include +#include "EventFiltering/PWGHF/HFFilterHelpers.h" +// +#include "PWGHF/DataModel/CandidateReconstructionTables.h" +// +#include "Common/Core/RecoDecay.h" +#include "Common/Core/trackUtilities.h" +#include "Common/DataModel/PIDResponseTOF.h" +#include "Common/DataModel/PIDResponseTPC.h" +#include "Common/DataModel/TrackSelectionTables.h" + #if __has_include() #include // needed for HFFilterHelpers, to be fixed #else #include #endif -#include "CommonConstants/PhysicsConstants.h" -#include "CCDB/BasicCCDBManager.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DetectorsBase/Propagator.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" - -#include "Common/Core/trackUtilities.h" - -#include "PWGHF/Core/SelectorCuts.h" -#include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" - -#include "EventFiltering/PWGHF/HFFilterHelpers.h" +#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::analysis; From 2fa94e55772815922c3f2f3aa37edb0eb8d24609 Mon Sep 17 00:00:00 2001 From: Francesca Ercolessi Date: Fri, 13 Jun 2025 15:15:07 +0200 Subject: [PATCH 062/871] [PWGLF] nuclei-proton angular correlations: Add dp and pp correlation (#11605) --- .../Tasks/Nuspex/hadronnucleicorrelation.cxx | 433 ++++++++++++++---- 1 file changed, 350 insertions(+), 83 deletions(-) diff --git a/PWGLF/Tasks/Nuspex/hadronnucleicorrelation.cxx b/PWGLF/Tasks/Nuspex/hadronnucleicorrelation.cxx index 6407e12a3c9..f90d12d75b1 100644 --- a/PWGLF/Tasks/Nuspex/hadronnucleicorrelation.cxx +++ b/PWGLF/Tasks/Nuspex/hadronnucleicorrelation.cxx @@ -13,36 +13,38 @@ /// \author Francesca Ercolessi /// \since 21 April 2024 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "TGrid.h" +#include "PWGCF/Femto3D/Core/femto3dPairTask.h" +#include "PWGCF/Femto3D/DataModel/singletrackselector.h" + +#include "Common/Core/RecoDecay.h" +#include "Common/DataModel/Multiplicity.h" #include "CCDB/BasicCCDBManager.h" #include "CCDB/CcdbApi.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" - #include "Framework/ASoA.h" -#include "MathUtils/Utils.h" -#include "Framework/DataTypes.h" -#include "Common/DataModel/Multiplicity.h" #include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/DataTypes.h" #include "Framework/Expressions.h" - +#include "Framework/HistogramRegistry.h" #include "Framework/StaticFor.h" -#include "PWGCF/Femto3D/DataModel/singletrackselector.h" -#include "PWGCF/Femto3D/Core/femto3dPairTask.h" +#include "Framework/runDataProcessing.h" +#include "MathUtils/Utils.h" + +#include "TGrid.h" +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include using namespace o2; using namespace o2::soa; @@ -56,6 +58,8 @@ struct hadronnucleicorrelation { static constexpr int pdgProton = 2212; static constexpr int pdgDeuteron = 1000010020; + Configurable mode{"mode", 0, "0: antid-antip, 1: d-p, 2: antid-p, 3: d-antip, 4: antip-p, 5: antip-antip, 6: p-p"}; + Configurable doQA{"doQA", true, "save QA histograms"}; Configurable doMCQA{"doMCQA", false, "save MC QA histograms"}; Configurable isMC{"isMC", false, "is MC"}; @@ -143,16 +147,21 @@ struct hadronnucleicorrelation { // key: pair of an integer and a float - value: vector of colType objects // for each key I have a vector of collisions - std::map, std::vector> mixbins_antidantip; + std::map, std::vector> mixbins_antid; + std::map, std::vector> mixbins_d; + std::map, std::vector> mixbins_antip; + std::map, std::vector> mixbins_p; std::map, std::vector> mixbinsPID_antidantip; std::map> mixbinsMC_antidantip; std::map> mixbinsMC_dp; - std::vector> hEtaPhi_AntiDeAntiPr_SE; - std::vector> hEtaPhi_AntiDeAntiPr_ME; - std::vector> hCorrEtaPhi_AntiDeAntiPr_SE; - std::vector> hCorrEtaPhi_AntiDeAntiPr_ME; + // Data histograms + std::vector> hEtaPhi_SE; + std::vector> hEtaPhi_ME; + std::vector> hCorrEtaPhi_SE; + std::vector> hCorrEtaPhi_ME; + // MC histograms std::vector> hEtaPhiRec_AntiDeAntiPr_SE; std::vector> hEtaPhiGen_AntiDeAntiPr_SE; std::vector> hEtaPhiRec_AntiDeAntiPr_ME; @@ -161,7 +170,6 @@ struct hadronnucleicorrelation { std::vector> hPIDEtaPhiGen_AntiDeAntiPr_SE; std::vector> hPIDEtaPhiRec_AntiDeAntiPr_ME; std::vector> hPIDEtaPhiGen_AntiDeAntiPr_ME; - std::vector> hEtaPhiGen_AntiPrAntiPr_SE; std::vector> hEtaPhiGen_AntiPrAntiPr_ME; @@ -193,19 +201,21 @@ struct hadronnucleicorrelation { AxisSpec ptBinnedAxis = {pTBins, "#it{p}_{T} of #bar{p} (GeV/c)"}; AxisSpec etaAxis = {100, -1., 1., "#eta"}; - AxisSpec phiAxis = {157, 0., 2 * o2::constants::math::PI, "#phi (rad)"}; + AxisSpec phiAxis = {157, 0., o2::constants::math::TwoPI, "#phi (rad)"}; AxisSpec pTAxis = {200, -10.f, 10.f, "p_{T} GeV/c"}; AxisSpec pTAxis_small = {100, -5.f, 5.f, "p_{T} GeV/c"}; AxisSpec DeltaEtaAxis = {100, -1.5, 1.5, "#Delta#eta"}; - AxisSpec DeltaPhiAxis = {60, -o2::constants::math::PI / 2, 1.5 * o2::constants::math::PI, "#Delta#phi (rad)"}; + AxisSpec DeltaPhiAxis = {60, -1 * o2::constants::math::PIHalf, 3 * o2::constants::math::PIHalf, "#Delta#phi (rad)"}; - registry.add("hNEvents", "hNEvents", {HistType::kTH1D, {{5, 0.f, 5.f}}}); + registry.add("hNEvents", "hNEvents", {HistType::kTH1D, {{7, 0.f, 7.f}}}); registry.get(HIST("hNEvents"))->GetXaxis()->SetBinLabel(1, "Selected"); registry.get(HIST("hNEvents"))->GetXaxis()->SetBinLabel(2, "events with #bar{d}-#bar{p}"); registry.get(HIST("hNEvents"))->GetXaxis()->SetBinLabel(3, "events with d-p"); registry.get(HIST("hNEvents"))->GetXaxis()->SetBinLabel(4, "events with #bar{d}"); registry.get(HIST("hNEvents"))->GetXaxis()->SetBinLabel(5, "events with d"); + registry.get(HIST("hNEvents"))->GetXaxis()->SetBinLabel(6, "events with #bar{p}"); + registry.get(HIST("hNEvents"))->GetXaxis()->SetBinLabel(7, "events with p"); nBinspT = pTBins.value.size() - 1; @@ -251,17 +261,40 @@ struct hadronnucleicorrelation { } } + TString name = "AntiDeAntiPr"; + switch (mode) { + case 1: + name = "DePr"; + break; + case 2: + name = "AntiDePr"; + break; + case 3: + name = "DeAntiPr"; + break; + case 4: + name = "AntiPrPr"; + break; + case 5: + name = "AntiPrAntiPr"; + break; + case 6: + name = "PrPr"; + break; + } + if (!isMC) { for (int i = 0; i < nBinspT; i++) { - auto htempSE_AntiDeAntiPr = registry.add(Form("hEtaPhi_AntiDeAntiPr_SE_pt%02.0f%02.0f", pTBins.value.at(i) * 10, pTBins.value.at(i + 1) * 10), Form("Raw #Delta#eta#Delta#phi (%.1f(Form("hEtaPhi_AntiDeAntiPr_ME_pt%02.0f%02.0f", pTBins.value.at(i) * 10, pTBins.value.at(i + 1) * 10), Form("Raw #Delta#eta#Delta#phi (%.1f(Form("hCorrEtaPhi_AntiDeAntiPr_SE_pt%02.0f%02.0f", pTBins.value.at(i) * 10, pTBins.value.at(i + 1) * 10), Form("#Delta#eta#Delta#phi (%.1f(Form("hCorrEtaPhi_AntiDeAntiPr_ME_pt%02.0f%02.0f", pTBins.value.at(i) * 10, pTBins.value.at(i + 1) * 10), Form("#Delta#eta#Delta#phi (%.1f(Form("hEtaPhi_%s_SE_pt%02.0f%02.0f", name.Data(), pTBins.value.at(i) * 10, pTBins.value.at(i + 1) * 10), Form("Raw #Delta#eta#Delta#phi (%.1f(Form("hEtaPhi_%s_ME_pt%02.0f%02.0f", name.Data(), pTBins.value.at(i) * 10, pTBins.value.at(i + 1) * 10), Form("Raw #Delta#eta#Delta#phi (%.1f(Form("hCorrEtaPhi_%s_SE_pt%02.0f%02.0f", name.Data(), pTBins.value.at(i) * 10, pTBins.value.at(i + 1) * 10), Form("#Delta#eta#Delta#phi (%.1f(Form("hCorrEtaPhi_%s_ME_pt%02.0f%02.0f", name.Data(), pTBins.value.at(i) * 10, pTBins.value.at(i + 1) * 10), Form("#Delta#eta#Delta#phi (%.1f - void mixTracks(Type const& tracks1, Type const& tracks2, bool isMCPID) + void mixTracks(Type const& tracks1, Type const& tracks2, bool isIdentical, bool isMCPID) { // last value: 0 -- SE; 1 -- ME for (auto it1 : tracks1) { for (auto it2 : tracks2) { @@ -529,7 +562,7 @@ struct hadronnucleicorrelation { // Calculate Delta-eta Delta-phi (reco) float deltaEta = it2->eta() - it1->eta(); float deltaPhi = it2->phi() - it1->phi(); - deltaPhi = getDeltaPhi(deltaPhi); + deltaPhi = RecoDecay::constrainAngle(deltaPhi, -1 * o2::constants::math::PIHalf); // Calculate Delta-eta Delta-phi (gen) float deltaEtaGen = -999.; @@ -537,24 +570,52 @@ struct hadronnucleicorrelation { if constexpr (doMC) { deltaEtaGen = it2->eta_MC() - it1->eta_MC(); deltaPhiGen = it2->phi_MC() - it1->phi_MC(); - deltaPhiGen = getDeltaPhi(deltaPhiGen); + deltaPhiGen = RecoDecay::constrainAngle(deltaPhiGen, -1 * o2::constants::math::PIHalf); } - float antipcorr = 1, antidcorr = 1; - for (int k = 0; k < nBinspT; k++) { if (it1->pt() >= pTBins.value.at(k) && it1->pt() < pTBins.value.at(k + 1)) { + float corr1 = 1, corr2 = 1; + if (docorrection) { // Apply corrections - antipcorr = hEffpTEta_antiproton->Interpolate(it2->pt(), it2->eta()); - antidcorr = hEffpTEta_antideuteron->Interpolate(it1->pt(), it1->eta()); + switch (mode) { + case 0: + corr1 = hEffpTEta_antideuteron->Interpolate(it1->pt(), it1->eta()); + corr2 = hEffpTEta_antiproton->Interpolate(it2->pt(), it2->eta()); + break; + case 1: + corr1 = hEffpTEta_deuteron->Interpolate(it1->pt(), it1->eta()); + corr2 = hEffpTEta_proton->Interpolate(it2->pt(), it2->eta()); + break; + case 2: + corr1 = hEffpTEta_antideuteron->Interpolate(it1->pt(), it1->eta()); + corr2 = hEffpTEta_proton->Interpolate(it2->pt(), it2->eta()); + break; + case 3: + corr1 = hEffpTEta_deuteron->Interpolate(it1->pt(), it1->eta()); + corr2 = hEffpTEta_antiproton->Interpolate(it2->pt(), it2->eta()); + break; + case 4: + corr1 = hEffpTEta_antiproton->Interpolate(it1->pt(), it1->eta()); + corr2 = hEffpTEta_proton->Interpolate(it2->pt(), it2->eta()); + break; + case 5: + corr1 = hEffpTEta_antiproton->Interpolate(it1->pt(), it1->eta()); + corr2 = hEffpTEta_antiproton->Interpolate(it2->pt(), it2->eta()); + break; + case 6: + corr1 = hEffpTEta_proton->Interpolate(it1->pt(), it1->eta()); + corr2 = hEffpTEta_proton->Interpolate(it2->pt(), it2->eta()); + break; + } } if (ME) { if constexpr (!doMC) { // Data - hEtaPhi_AntiDeAntiPr_ME[k]->Fill(deltaEta, deltaPhi, it2->pt()); - hCorrEtaPhi_AntiDeAntiPr_ME[k]->Fill(deltaEta, deltaPhi, it2->pt(), 1. / (antipcorr * antidcorr)); + hEtaPhi_ME[k]->Fill(deltaEta, deltaPhi, it2->pt()); + hCorrEtaPhi_ME[k]->Fill(deltaEta, deltaPhi, it2->pt(), 1. / (corr1 * corr2)); } else { // MC if (isMCPID) { hPIDEtaPhiRec_AntiDeAntiPr_ME[k]->Fill(deltaEta, deltaPhi, it2->pt()); @@ -566,8 +627,12 @@ struct hadronnucleicorrelation { } } else { if constexpr (!doMC) { // Data - hEtaPhi_AntiDeAntiPr_SE[k]->Fill(deltaEta, deltaPhi, it2->pt()); - hCorrEtaPhi_AntiDeAntiPr_SE[k]->Fill(deltaEta, deltaPhi, it2->pt(), 1. / (antipcorr * antidcorr)); + // is Identical (pp and antip-antip)? + if (isIdentical && std::abs(deltaPhi) < 0.001 && std::abs(deltaEta) < 0.001) { + continue; + } + hEtaPhi_SE[k]->Fill(deltaEta, deltaPhi, it2->pt()); + hCorrEtaPhi_SE[k]->Fill(deltaEta, deltaPhi, it2->pt(), 1. / (corr1 * corr2)); } else { // MC if (isMCPID) { hPIDEtaPhiRec_AntiDeAntiPr_SE[k]->Fill(deltaEta, deltaPhi, it2->pt()); @@ -591,7 +656,7 @@ struct hadronnucleicorrelation { for (auto it2 : particles2) { // Calculate Delta-eta Delta-phi (gen) float deltaEtaGen = it2->eta() - it1->eta(); - float deltaPhiGen = getDeltaPhi(it2->phi() - it1->phi()); + float deltaPhiGen = RecoDecay::constrainAngle(it2->phi() - it1->phi(), -1 * o2::constants::math::PIHalf); // Loop over pT bins for (int k = 0; k < nBinspT; k++) { @@ -615,7 +680,7 @@ struct hadronnucleicorrelation { for (auto it2 : particles2) { // Calculate Delta-eta Delta-phi (gen) float deltaEtaGen = it2->eta() - it1->eta(); - float deltaPhiGen = getDeltaPhi(it2->phi() - it1->phi()); + float deltaPhiGen = RecoDecay::constrainAngle(it2->phi() - it1->phi(), -1 * o2::constants::math::PIHalf); if (!ME && std::abs(deltaPhiGen) < 0.001 && std::abs(deltaEtaGen) < 0.001) { continue; @@ -636,16 +701,6 @@ struct hadronnucleicorrelation { } } - float getDeltaPhi(float deltaPhi) - { - if (deltaPhi < -o2::constants::math::PI / 2) { - return deltaPhi += 2 * o2::constants::math::PI; - } else if (deltaPhi >= 3 * o2::constants::math::PI / 2) { - return deltaPhi -= 2 * o2::constants::math::PI; - } - return deltaPhi; - } - void GetCorrection(o2::framework::Service const& ccdbObj, TString filepath, TString histname) { TList* l = ccdbObj->get(filepath.Data()); @@ -793,14 +848,180 @@ struct hadronnucleicorrelation { if (selectedtracks_antid.find(collision.globalIndex()) != selectedtracks_antid.end()) { registry.fill(HIST("hNEvents"), 3.5); + mixbins_antid[std::pair{vertexBinToMix, centBinToMix}].push_back(std::make_shared(collision)); + } + if (selectedtracks_d.find(collision.globalIndex()) != selectedtracks_d.end()) { + registry.fill(HIST("hNEvents"), 4.5); + mixbins_d[std::pair{vertexBinToMix, centBinToMix}].push_back(std::make_shared(collision)); + } + if (selectedtracks_antip.find(collision.globalIndex()) != selectedtracks_antip.end()) { + registry.fill(HIST("hNEvents"), 5.5); + mixbins_antip[std::pair{vertexBinToMix, centBinToMix}].push_back(std::make_shared(collision)); + } + if (selectedtracks_p.find(collision.globalIndex()) != selectedtracks_p.end()) { + registry.fill(HIST("hNEvents"), 6.5); + mixbins_p[std::pair{vertexBinToMix, centBinToMix}].push_back(std::make_shared(collision)); + } + } + + if (mode == 0 && !mixbins_antid.empty()) { + + for (auto i = mixbins_antid.begin(); i != mixbins_antid.end(); i++) { // iterating over all vertex&mult bins + + std::vector value = i->second; + int EvPerBin = value.size(); // number of collisions in each vertex&mult bin + + for (int indx1 = 0; indx1 < EvPerBin; indx1++) { // loop over all the events in each vertex&mult bin + + auto col1 = value[indx1]; + + if (selectedtracks_antip.find(col1->index()) != selectedtracks_antip.end()) { + mixTracks<0, 0>(selectedtracks_antid[col1->index()], selectedtracks_antip[col1->index()], 0, 0); // mixing SE + } + + for (int indx2 = 0; indx2 < EvPerBin; indx2++) { // nested loop for all the combinations of collisions in a chosen mult/vertex bin + + auto col2 = value[indx2]; + + if (col1 == col2) { + continue; + } - mixbins_antidantip[std::pair{vertexBinToMix, centBinToMix}].push_back(std::make_shared(collision)); + if (selectedtracks_antip.find(col2->index()) != selectedtracks_antip.end()) { + mixTracks<1, 0>(selectedtracks_antid[col1->index()], selectedtracks_antip[col2->index()], 0, 0); // mixing ME + } + } + } } } - if (!mixbins_antidantip.empty()) { + if (mode == 1 && !mixbins_d.empty()) { - for (auto i = mixbins_antidantip.begin(); i != mixbins_antidantip.end(); i++) { // iterating over all vertex&mult bins + for (auto i = mixbins_d.begin(); i != mixbins_d.end(); i++) { // iterating over all vertex&mult bins + + std::vector value = i->second; + int EvPerBin = value.size(); // number of collisions in each vertex&mult bin + + for (int indx1 = 0; indx1 < EvPerBin; indx1++) { // loop over all the events in each vertex&mult bin + + auto col1 = value[indx1]; + + if (selectedtracks_p.find(col1->index()) != selectedtracks_p.end()) { + mixTracks<0, 0>(selectedtracks_d[col1->index()], selectedtracks_p[col1->index()], 0, 0); // mixing SE + } + + for (int indx2 = 0; indx2 < EvPerBin; indx2++) { // nested loop for all the combinations of collisions in a chosen mult/vertex bin + + auto col2 = value[indx2]; + + if (col1 == col2) { + continue; + } + + if (selectedtracks_p.find(col2->index()) != selectedtracks_p.end()) { + mixTracks<1, 0>(selectedtracks_d[col1->index()], selectedtracks_p[col2->index()], 0, 0); // mixing ME + } + } + } + } + } + + if (mode == 2 && !mixbins_antid.empty()) { + + for (auto i = mixbins_antid.begin(); i != mixbins_antid.end(); i++) { // iterating over all vertex&mult bins + + std::vector value = i->second; + int EvPerBin = value.size(); // number of collisions in each vertex&mult bin + + for (int indx1 = 0; indx1 < EvPerBin; indx1++) { // loop over all the events in each vertex&mult bin + + auto col1 = value[indx1]; + + if (selectedtracks_p.find(col1->index()) != selectedtracks_p.end()) { + mixTracks<0, 0>(selectedtracks_antid[col1->index()], selectedtracks_p[col1->index()], 0, 0); // mixing SE + } + + for (int indx2 = 0; indx2 < EvPerBin; indx2++) { // nested loop for all the combinations of collisions in a chosen mult/vertex bin + + auto col2 = value[indx2]; + + if (col1 == col2) { + continue; + } + + if (selectedtracks_p.find(col2->index()) != selectedtracks_p.end()) { + mixTracks<1, 0>(selectedtracks_antid[col1->index()], selectedtracks_p[col2->index()], 0, 0); // mixing ME + } + } + } + } + } + + if (mode == 3 && !mixbins_d.empty()) { + + for (auto i = mixbins_d.begin(); i != mixbins_d.end(); i++) { // iterating over all vertex&mult bins + + std::vector value = i->second; + int EvPerBin = value.size(); // number of collisions in each vertex&mult bin + + for (int indx1 = 0; indx1 < EvPerBin; indx1++) { // loop over all the events in each vertex&mult bin + + auto col1 = value[indx1]; + + if (selectedtracks_antip.find(col1->index()) != selectedtracks_antip.end()) { + mixTracks<0, 0>(selectedtracks_d[col1->index()], selectedtracks_antip[col1->index()], 0, 0); // mixing SE + } + + for (int indx2 = 0; indx2 < EvPerBin; indx2++) { // nested loop for all the combinations of collisions in a chosen mult/vertex bin + + auto col2 = value[indx2]; + + if (col1 == col2) { + continue; + } + + if (selectedtracks_antip.find(col2->index()) != selectedtracks_antip.end()) { + mixTracks<1, 0>(selectedtracks_d[col1->index()], selectedtracks_antip[col2->index()], 0, 0); // mixing ME + } + } + } + } + } + + if (mode == 4 && !mixbins_antip.empty()) { + + for (auto i = mixbins_antip.begin(); i != mixbins_antip.end(); i++) { // iterating over all vertex&mult bins + + std::vector value = i->second; + int EvPerBin = value.size(); // number of collisions in each vertex&mult bin + + for (int indx1 = 0; indx1 < EvPerBin; indx1++) { // loop over all the events in each vertex&mult bin + + auto col1 = value[indx1]; + + if (selectedtracks_p.find(col1->index()) != selectedtracks_p.end()) { + mixTracks<0, 0>(selectedtracks_antip[col1->index()], selectedtracks_p[col1->index()], 0, 0); // mixing SE + } + + for (int indx2 = 0; indx2 < EvPerBin; indx2++) { // nested loop for all the combinations of collisions in a chosen mult/vertex bin + + auto col2 = value[indx2]; + + if (col1 == col2) { + continue; + } + + if (selectedtracks_p.find(col2->index()) != selectedtracks_p.end()) { + mixTracks<1, 0>(selectedtracks_antip[col1->index()], selectedtracks_p[col2->index()], 0, 0); // mixing ME + } + } + } + } + } + + if (mode == 5 && !mixbins_antip.empty()) { + + for (auto i = mixbins_antip.begin(); i != mixbins_antip.end(); i++) { // iterating over all vertex&mult bins std::vector value = i->second; int EvPerBin = value.size(); // number of collisions in each vertex&mult bin @@ -810,7 +1031,7 @@ struct hadronnucleicorrelation { auto col1 = value[indx1]; if (selectedtracks_antip.find(col1->index()) != selectedtracks_antip.end()) { - mixTracks<0, 0>(selectedtracks_antid[col1->index()], selectedtracks_antip[col1->index()], 0); // mixing SE + mixTracks<0, 0>(selectedtracks_antip[col1->index()], selectedtracks_antip[col1->index()], 1, 0); // mixing SE } for (int indx2 = 0; indx2 < EvPerBin; indx2++) { // nested loop for all the combinations of collisions in a chosen mult/vertex bin @@ -822,7 +1043,38 @@ struct hadronnucleicorrelation { } if (selectedtracks_antip.find(col2->index()) != selectedtracks_antip.end()) { - mixTracks<1, 0>(selectedtracks_antid[col1->index()], selectedtracks_antip[col2->index()], 0); // mixing ME + mixTracks<1, 0>(selectedtracks_antip[col1->index()], selectedtracks_antip[col2->index()], 1, 0); // mixing ME + } + } + } + } + } + + if (mode == 6 && !mixbins_p.empty()) { + + for (auto i = mixbins_p.begin(); i != mixbins_p.end(); i++) { // iterating over all vertex&mult bins + + std::vector value = i->second; + int EvPerBin = value.size(); // number of collisions in each vertex&mult bin + + for (int indx1 = 0; indx1 < EvPerBin; indx1++) { // loop over all the events in each vertex&mult bin + + auto col1 = value[indx1]; + + if (selectedtracks_p.find(col1->index()) != selectedtracks_p.end()) { + mixTracks<0, 0>(selectedtracks_p[col1->index()], selectedtracks_p[col1->index()], 1, 0); // mixing SE + } + + for (int indx2 = 0; indx2 < EvPerBin; indx2++) { // nested loop for all the combinations of collisions in a chosen mult/vertex bin + + auto col2 = value[indx2]; + + if (col1 == col2) { + continue; + } + + if (selectedtracks_p.find(col2->index()) != selectedtracks_p.end()) { + mixTracks<1, 0>(selectedtracks_p[col1->index()], selectedtracks_p[col2->index()], 1, 0); // mixing ME } } } @@ -846,10 +1098,25 @@ struct hadronnucleicorrelation { (i->second).clear(); selectedtracks_d.clear(); - for (auto& pair : mixbins_antidantip) { + for (auto& pair : mixbins_antid) { + pair.second.clear(); // Clear the vector associated with the key + } + mixbins_antid.clear(); // Then clear the map itself + + for (auto& pair : mixbins_d) { + pair.second.clear(); // Clear the vector associated with the key + } + mixbins_d.clear(); // Then clear the map itself + + for (auto& pair : mixbins_antip) { + pair.second.clear(); // Clear the vector associated with the key + } + mixbins_antip.clear(); // Then clear the map itself + + for (auto& pair : mixbins_p) { pair.second.clear(); // Clear the vector associated with the key } - mixbins_antidantip.clear(); // Then clear the map itself + mixbins_p.clear(); // Then clear the map itself } PROCESS_SWITCH(hadronnucleicorrelation, processData, "processData", true); @@ -1222,7 +1489,7 @@ struct hadronnucleicorrelation { int centBinToMix = std::floor(collision.multPerc() / (100.0 / _multNsubBins)); if (selectedtracksMC_antid.find(collision.globalIndex()) != selectedtracksMC_antid.end()) { - mixbins_antidantip[std::pair{vertexBinToMix, centBinToMix}].push_back(std::make_shared(collision)); + mixbins_antid[std::pair{vertexBinToMix, centBinToMix}].push_back(std::make_shared(collision)); } if (selectedtracksPIDMC_antid.find(collision.globalIndex()) != selectedtracksPIDMC_antid.end()) { @@ -1230,9 +1497,9 @@ struct hadronnucleicorrelation { } } // coll - if (!mixbins_antidantip.empty()) { + if (!mixbins_antid.empty()) { - for (auto i = mixbins_antidantip.begin(); i != mixbins_antidantip.end(); i++) { // iterating over all vertex&mult bins + for (auto i = mixbins_antid.begin(); i != mixbins_antid.end(); i++) { // iterating over all vertex&mult bins std::vector value = i->second; int EvPerBin = value.size(); // number of collisions in each vertex&mult bin @@ -1242,7 +1509,7 @@ struct hadronnucleicorrelation { auto col1 = value[indx1]; if (selectedtracksMC_antip.find(col1->index()) != selectedtracksMC_antip.end()) { - mixTracks<0, 1>(selectedtracksMC_antid[col1->index()], selectedtracksMC_antip[col1->index()], 0); // mixing SE + mixTracks<0, 1>(selectedtracksMC_antid[col1->index()], selectedtracksMC_antip[col1->index()], 0, 0); // mixing SE } for (int indx2 = indx1 + 1; indx2 < EvPerBin; indx2++) { // nested loop for all the combinations of collisions in a chosen mult/vertex bin @@ -1254,7 +1521,7 @@ struct hadronnucleicorrelation { } if (selectedtracksMC_antip.find(col2->index()) != selectedtracksMC_antip.end()) { - mixTracks<1, 1>(selectedtracksMC_antid[col1->index()], selectedtracksMC_antip[col2->index()], 0); // mixing ME + mixTracks<1, 1>(selectedtracksMC_antid[col1->index()], selectedtracksMC_antip[col2->index()], 0, 0); // mixing ME } } } @@ -1273,7 +1540,7 @@ struct hadronnucleicorrelation { auto col1 = value[indx1]; if (selectedtracksPIDMC_antip.find(col1->index()) != selectedtracksPIDMC_antip.end()) { - mixTracks<0, 1>(selectedtracksPIDMC_antid[col1->index()], selectedtracksPIDMC_antip[col1->index()], 1); // mixing SE + mixTracks<0, 1>(selectedtracksPIDMC_antid[col1->index()], selectedtracksPIDMC_antip[col1->index()], 0, 1); // mixing SE } for (int indx2 = indx1 + 1; indx2 < EvPerBin; indx2++) { // nested loop for all the combinations of collisions in a chosen mult/vertex bin @@ -1285,7 +1552,7 @@ struct hadronnucleicorrelation { } if (selectedtracksPIDMC_antip.find(col2->index()) != selectedtracksPIDMC_antip.end()) { - mixTracks<1, 1>(selectedtracksPIDMC_antid[col1->index()], selectedtracksPIDMC_antip[col2->index()], 1); // mixing ME + mixTracks<1, 1>(selectedtracksPIDMC_antid[col1->index()], selectedtracksPIDMC_antip[col2->index()], 0, 1); // mixing ME } } } @@ -1330,10 +1597,10 @@ struct hadronnucleicorrelation { } mixbinsPID_antidantip.clear(); // clear the map - for (auto& pair : mixbins_antidantip) { + for (auto& pair : mixbins_antid) { pair.second.clear(); // clear the vector associated with the key } - mixbins_antidantip.clear(); // clear the map + mixbins_antid.clear(); // clear the map } PROCESS_SWITCH(hadronnucleicorrelation, processMC, "processMC", false); From b901a1f7df85dbecc08a4dfbaa05e0be61af916b Mon Sep 17 00:00:00 2001 From: YubiaoWang Date: Fri, 13 Jun 2025 21:19:00 +0800 Subject: [PATCH 063/871] [PWGJE] Add MCD and MCP in jet v2 task, Updated Data and MC fitting check plots (#11596) --- PWGJE/Tasks/jetChargedV2.cxx | 1287 +++++++++++++++++++++++++++------- 1 file changed, 1028 insertions(+), 259 deletions(-) diff --git a/PWGJE/Tasks/jetChargedV2.cxx b/PWGJE/Tasks/jetChargedV2.cxx index 6133cc19a27..20ea7907a75 100644 --- a/PWGJE/Tasks/jetChargedV2.cxx +++ b/PWGJE/Tasks/jetChargedV2.cxx @@ -13,70 +13,60 @@ /// \file jetChargedV2.cxx /// \brief This file contains the implementation for the Charged Jet v2 analysis in the ALICE experiment -#include -#include -#include -#include -#include -#include -#include -#include -#include -// o2Physics includes. -#include "CommonConstants/MathConstants.h" -#include "CCDB/BasicCCDBManager.h" -#include "DataFormatsParameters/GRPMagField.h" - -#include "Framework/runDataProcessing.h" - -#include "Common/DataModel/FT0Corrected.h" -#include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/Centrality.h" -#include "Common/CCDB/ctpRateFetcher.h" - -//< evt pln .h >// -#include "Framework/ASoAHelpers.h" -#include "Framework/RunningWorkflowInfo.h" -#include "Framework/StaticFor.h" +#include "PWGJE/Core/FastJetUtilities.h" +#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include "PWGJE/Core/JetFinder.h" +#include "PWGJE/Core/JetFindingUtilities.h" +#include "PWGJE/DataModel/Jet.h" -#include "Common/DataModel/Qvectors.h" #include "Common/Core/EventPlaneHelper.h" -//< evt pln .h | end >// - -// o2 includes. -#include "DetectorsCommonDataFormats/AlignParam.h" +#include "Common/Core/TrackSelection.h" +#include "Common/Core/TrackSelectionDefaults.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Qvectors.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "EventFiltering/filterTables.h" +#include "CommonConstants/PhysicsConstants.h" #include "Framework/ASoA.h" +#include "Framework/ASoAHelpers.h" #include "Framework/AnalysisDataModel.h" #include "Framework/AnalysisTask.h" -#include "Framework/O2DatabasePDGPlugin.h" #include "Framework/HistogramRegistry.h" +#include "Framework/O2DatabasePDGPlugin.h" +#include "Framework/RunningWorkflowInfo.h" +#include "Framework/StaticFor.h" +#include "Framework/runDataProcessing.h" -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectionDefaults.h" - -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" - -#include "PWGJE/Core/FastJetUtilities.h" -#include "PWGJE/Core/JetFinder.h" -#include "PWGJE/Core/JetFindingUtilities.h" -#include "PWGJE/DataModel/Jet.h" +#include +#include +#include +#include +#include +#include +#include +#include -#include "PWGJE/Core/JetDerivedDataUtilities.h" -#include "EventFiltering/filterTables.h" +#include +#include +#include +#include +#include using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; struct JetChargedV2 { + using McParticleCollision = soa::Join; + using ChargedMCDMatchedJets = soa::Join; + using ChargedMCPMatchedJets = soa::Join; + HistogramRegistry registry; HistogramRegistry histosQA{"histosQA", {}, OutputObjHandlingPolicy::AnalysisObject, false, false}; Configurable eventSelections{"eventSelections", "sel8", "choose event selection"}; Configurable trackSelections{"trackSelections", "globalTracks", "set track selections"}; - Configurable> jetRadii{"jetRadii", std::vector{0.4}, "jet resolution parameters"}; Configurable vertexZCut{"vertexZCut", 10.0f, "Accepted z-vertex range"}; @@ -95,6 +85,7 @@ struct JetChargedV2 { Configurable jetPtMax{"jetPtMax", 200.0, "maximum pT acceptance for jets"}; Configurable jetEtaMin{"jetEtaMin", -0.9, "minimum eta acceptance for jets"}; Configurable jetEtaMax{"jetEtaMax", 0.9, "maximum eta acceptance for jets"}; + Configurable nBinsEta{"nBinsEta", 200, "number of bins for eta axes"}; Configurable jetRadius{"jetRadius", 0.2, "jet resolution parameters"}; Configurable randomConeLeadJetDeltaR{"randomConeLeadJetDeltaR", -99.0, "min distance between leading jet axis and random cone (RC) axis; if negative, min distance is set to automatic value of R_leadJet+R_RC "}; @@ -104,6 +95,7 @@ struct JetChargedV2 { Configurable randomConeR{"randomConeR", 0.4, "size of random Cone for estimating background fluctuations"}; 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)"}; + //=====================< evt pln >=====================// Configurable cfgAddEvtSel{"cfgAddEvtSel", true, "event selection"}; Configurable> cfgnMods{"cfgnMods", {2}, "Modulation of interest"}; @@ -124,6 +116,16 @@ struct JetChargedV2 { int refAId; int refBId; + //=====================< jetSpectraConfig to this analysis >=====================// + Configurable pTHatExponent{"pTHatExponent", 6.0, "exponent of the event weight for the calculation of pTHat"}; + 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 pTHatAbsoluteMin{"pTHatAbsoluteMin", -99.0, "minimum value of pTHat"}; + 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 checkMcCollisionIsMatched{"checkMcCollisionIsMatched", false, "0: count whole MCcollisions, 1: select MCcollisions which only have their correspond collisions"}; + 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 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"}; + template int getDetId(const T& name) { @@ -148,7 +150,7 @@ struct JetChargedV2 { return 0; } } - //=====================< evt pln | end >=====================// + //=====================< evt p615ln | end >=====================// Configurable selectedJetsRadius{"selectedJetsRadius", 0.2, "resolution parameter for histograms without radius"}; @@ -160,7 +162,12 @@ struct JetChargedV2 { double evtnum = 0; double accptTrack = 0; double fitTrack = 0; + float collQvecAmpDetId = 1e-8; TH1F* hPtsumSumptFit = nullptr; + TH1F* hPtsumSumptFitMCP = nullptr; + TF1* fFitModulationV2v3 = 0x0; + TH1F* hPtsumSumptFitP = nullptr; + TF1* fFitModulationV2v3P = 0x0; void init(o2::framework::InitContext&) { @@ -173,6 +180,12 @@ struct JetChargedV2 { refAId = 4; refBId = 5; } + auto jetRadiiBins = (std::vector)jetRadii; + if (jetRadiiBins.size() > 1) { + jetRadiiBins.push_back(jetRadiiBins[jetRadiiBins.size() - 1] + (std::abs(jetRadiiBins[jetRadiiBins.size() - 1] - jetRadiiBins[jetRadiiBins.size() - 2]))); + } else { + jetRadiiBins.push_back(jetRadiiBins[jetRadiiBins.size() - 1] + 0.1); + } auto jetPtTemp = 0.0; jetPtBins.push_back(jetPtTemp); @@ -200,8 +213,14 @@ struct JetChargedV2 { } std::sort(jetPtBinsRhoAreaSub.begin(), jetPtBinsRhoAreaSub.end()); - AxisSpec jetPtAxis = {jetPtBins, "#it{p}_{T} (GeV/#it{c})"}; - AxisSpec jetPtAxisRhoAreaSub = {jetPtBinsRhoAreaSub, "#it{p}_{T} (GeV/#it{c})"}; + //< MCAxis >// + AxisSpec centralityAxis = {1200, -10., 110., "Centrality"}; + AxisSpec trackPtAxis = {200, -0.5, 199.5, "#it{p}_{T} (GeV/#it{c})"}; + AxisSpec trackEtaAxis = {nBinsEta, -1.0, 1.0, "#eta"}; + AxisSpec phiAxis = {160, -1.0, 7.0, "#varphi"}; + AxisSpec jetPtAxis = {200, 0., 200., "#it{p}_{T} (GeV/#it{c})"}; + AxisSpec jetPtAxisRhoAreaSub = {400, -200., 200., "#it{p}_{T} (GeV/#it{c})"}; + AxisSpec jetEtaAxis = {nBinsEta, -1.0, 1.0, "#eta"}; AxisSpec axisPt = {40, 0.0, 4.0}; AxisSpec axisEta = {32, -0.8, 0.8}; @@ -211,102 +230,177 @@ struct JetChargedV2 { eventSelectionBits = jetderiveddatautilities::initialiseEventSelectionBits(static_cast(eventSelections)); trackSelection = jetderiveddatautilities::initialiseTrackSelection(static_cast(trackSelections)); - //< Track efficiency plots >// - registry.add("h_collisions", "event status;event status;entries", {HistType::kTH1F, {{4, 0.0, 4.0}}}); - registry.add("h2_centrality_collisions", "centrality vs collisions; centrality; collisions", {HistType::kTH2F, {{120, -10., 110.}, {4, 0.0, 4.0}}}); - registry.add("h2_centrality_track_pt", "centrality vs track pT; centrality; #it{p}_{T,track} (GeV/#it{c})", {HistType::kTH2F, {{1200, -10.0, 110.0}, {200, 0., 200.}}}); - registry.add("h2_centrality_track_eta", "centrality vs track #eta; centrality; #eta_{track}", {HistType::kTH2F, {{1200, -10.0, 110.0}, {100, -1.0, 1.0}}}); - registry.add("h2_centrality_track_phi", "centrality vs track #varphi; centrality; #varphi_{track}", {HistType::kTH2F, {{1200, -10.0, 110.0}, {160, -1.0, 7.}}}); - registry.add("h2_centrality_track_energy", "centrality vs track energy; centrality; Energy GeV", {HistType::kTH2F, {{120, -10., 110.}, {100, 0.0, 100.0}}}); - registry.add("h2_track_pt_track_sigmapt", "#sigma(#it{p}_{T})/#it{p}_{T}; #it{p}_{T,track} (GeV/#it{c})", {HistType::kTH2F, {{100, 0., 10.}, {100000, 0.0, 100.0}}}); - registry.add("h2_track_pt_high_track_sigmapt", "#sigma(#it{p}_{T})/#it{p}_{T}; #it{p}_{T,track} (GeV/#it{c})", {HistType::kTH2F, {{90, 10., 100.}, {100000, 0.0, 100.0}}}); - registry.add("h2_track_pt_track_sigma1overpt", "#sigma(1/#it{p}_{T}); #it{p}_{T,track} (GeV/#it{c})", {HistType::kTH2F, {{100, 0., 10.}, {1000, 0.0, 10.0}}}); - registry.add("h2_track_pt_high_track_sigma1overpt", "#sigma(1/#it{p}_{T}); #it{p}_{T,track} (GeV/#it{c})", {HistType::kTH2F, {{90, 10., 100.}, {1000, 0.0, 10.0}}}); - - //< \sigma p_T at local rho test plot > - registry.add("h_accept_Track", "all and accept track;Track;entries", {HistType::kTH1F, {{10, 0.0, 10.0}}}); - registry.add("h_accept_Track_init", "all and accept track;Track;entries", {HistType::kTH1F, {{10, 0.0, 10.0}}}); - registry.add("h_accept_Track_Fit", "all and accept track;Track;entries", {HistType::kTH1F, {{10, 0.0, 10.0}}}); - - registry.add("h_ptsum_collnum", "ptsum collnum;collnum;entries", {HistType::kTH1F, {{40, 0.0, 40}}}); - registry.add("h_ptsum_sumpt", "jet sumpt;sum p_{T};entries", {HistType::kTH1F, {{40, 0., o2::constants::math::TwoPI}}}); - registry.add("h2_phi_track_eta", "phi vs track eta; #eta (GeV/#it{c}); #varphi", {HistType::kTH2F, {{100, -1.0, 1.0}, {40, 0., o2::constants::math::TwoPI}}}); - registry.add("h2_centrality_phi_w_pt", "centrality vs jet #varphi; centrality; entries", {HistType::kTH2F, {{100, 0.0, 100.0}, {40, 0., o2::constants::math::TwoPI}}}); - registry.add("h2_evtnum_phi_w_pt", "eventNumber vs jet #varphi; #eventNumber; entries", {HistType::kTH2F, {{1000, 0.0, 1000}, {40, 0., o2::constants::math::TwoPI}}}); - - //< fit quality >// - registry.add("h_PvalueCDF_CombinFit", "cDF #chi^{2}; entries", {HistType::kTH1F, {{50, 0, 1}}}); - registry.add("h2_PvalueCDFCent_CombinFit", "p-value cDF vs centrality; centrality; p-value", {HistType::kTH2F, {{100, 0, 100}, {40, 0, 1}}}); - registry.add("h2_Chi2Cent_CombinFit", "Chi2 vs centrality; centrality; #tilde{#chi^{2}}", {HistType::kTH2F, {{100, 0, 100}, {100, 0, 5}}}); - registry.add("h2_PChi2_CombinFit", "p-value vs #tilde{#chi^{2}}; p-value; #tilde{#chi^{2}}", {HistType::kTH2F, {{100, 0, 1}, {100, 0, 5}}}); - - registry.add("Thn_PChi2_CombinFitCent", "p-value vs #tilde{#chi^{2}}; p-value; #tilde{#chi^{2}}", {HistType::kTHnSparseF, {{100, 0.0, 100.0}, {100, 0, 1}, {100, 0, 5}}}); - registry.add("h2_PChi2_CombinFitA", "p-value vs #tilde{#chi^{2}}; p-value; #tilde{#chi^{2}}", {HistType::kTH2F, {{100, 0, 1}, {100, 0, 5}}}); - registry.add("h2_PChi2_CombinFitB", "p-value vs #tilde{#chi^{2}}; p-value; #tilde{#chi^{2}}", {HistType::kTH2F, {{100, 0, 1}, {100, 0, 5}}}); - - registry.add("h_evtnum_centrlity", "eventNumber vs centrality ; #eventNumber", {HistType::kTH1F, {{1000, 0.0, 1000}}}); - registry.add("h_evtnum_NTrk", "eventNumber vs Number of Track ; #eventNumber", {HistType::kTH1F, {{1000, 0.0, 1000}}}); - - registry.add("Thn_evtnum_phi_centrality", "eventNumber vs jet #varphi; #eventNumber; entries", {HistType::kTHnSparseF, {{1000, 0.0, 1000}, {40, 0., o2::constants::math::TwoPI}, {100, 0.0, 100.0}}}); - - registry.add("h2_evt_fitpara", "event vs fit parameter; evtnum; parameter", {HistType::kTH2F, {cfgAxisEvtfit, {5, 0., 5}}}); - - registry.add("h_v2obs_centrality", "fitparameter v2obs vs centrality ; #centrality", {HistType::kTProfile, {cfgAxisVnCent}}); - registry.add("h_v3obs_centrality", "fitparameter v3obs vs centrality ; #centrality", {HistType::kTProfile, {cfgAxisVnCent}}); - - registry.add("h_fitparaRho_evtnum", "fitparameter #rho_{0} vs evtnum ; #eventnumber", {HistType::kTH1F, {{1000, 0.0, 1000}}}); - registry.add("h_fitparaPsi2_evtnum", "fitparameter #Psi_{2} vs evtnum ; #eventnumber", {HistType::kTH1F, {{1000, 0.0, 1000}}}); - registry.add("h_fitparaPsi3_evtnum", "fitparameter #Psi_{3} vs evtnum ; #eventnumber", {HistType::kTH1F, {{1000, 0.0, 1000}}}); - registry.add("h_fitparav2obs_evtnum", "fitparameter v2obs vs evtnum ; #eventnumber", {HistType::kTH1F, {{1000, 0.0, 1000}}}); - registry.add("h_fitparav3obs_evtnum", "fitparameter v3obs vs evtnum ; #eventnumber", {HistType::kTH1F, {{1000, 0.0, 1000}}}); - - registry.add("h2_fitParaZero_cent", "#varphi vs #rho(#varphi); #cent; #fitParameter[0] ", {HistType::kTH2F, {{100, 0., 100}, {210, -10.0, 200.0}}}); - registry.add("h2_phi_rhophi", "#varphi vs #rho(#varphi); #varphi - #Psi_{EP,2}; #rho_{ch}(#varphi) ", {HistType::kTH2F, {{40, 0., o2::constants::math::TwoPI}, {210, -10.0, 200.0}}}); - registry.add("h2_phi_rholocal", "#varphi vs #rho(#varphi); #varphi - #Psi_{EP,2}; #rho(#varphi) ", {HistType::kTH2F, {{40, 0., o2::constants::math::TwoPI}, {210, -10.0, 200.0}}}); - registry.add("h2_phi_rholocal_cent", "#varphi vs #rho(#varphi); #cent; #rho(#varphi) ", {HistType::kTH2F, {{100, 0., 100}, {210, -10.0, 200.0}}}); - registry.add("h3_centrality_localrho_phi", "centrality; #rho_{local}; #Delta#varphi_{jet}", {HistType::kTH3F, {{120, -10.0, 110.0}, {200, 0.0, 200.0}, {40, 0., o2::constants::math::TwoPI}}}); - - registry.add("h3_centrality_rhovsphi_phi", "centrality; #rho(#varphi); #Delta#varphi_{jet}", {HistType::kTH3F, {{120, -10.0, 110.0}, {200, 0.0, 200.0}, {40, 0., o2::constants::math::TwoPI}}}); - //< \sigma p_T at local rho test plot | end > - - registry.add("h_jet_pt_rhoareasubtracted", "jet pT rhoareasubtracted;#it{p}_{T,jet} (GeV/#it{c}); entries", {HistType::kTH1F, {jetPtAxisRhoAreaSub}}); - registry.add("h_jet_pt_rholocal", "jet pT rholocal;#it{p}_{T,jet} (GeV/#it{c});entries", {HistType::kTH1F, {jetPtAxisRhoAreaSub}}); - - registry.add("h2_centrality_jet_pt_rhoareasubtracted", "centrality vs #it{p}_{T,jet}; centrality; #it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH2F, {{1200, -10.0, 110.0}, jetPtAxisRhoAreaSub}}); - - registry.add("leadJetPt", "leadJet Pt ", {HistType::kTH1F, {{200, 0., 200.0}}}); - registry.add("leadJetPhi", "leadJet constituent #phi ", {HistType::kTH1F, {{80, -1.0, 7.}}}); - registry.add("leadJetEta", "leadJet constituent #eta ", {HistType::kTH1F, {{100, -1.0, 1.0}}}); - - //< RC test plots >// - registry.add("h3_centrality_deltapT_RandomCornPhi_rhorandomconewithoutleadingjet", "centrality; #it{p}_{T,random cone} - #it{area, random cone} * #it{rho}; #Delta#varphi_{jet}", {HistType::kTH3F, {{100, 0.0, 100.0}, {400, -200.0, 200.0}, {100, 0., o2::constants::math::TwoPI}}}); - registry.add("h3_centrality_deltapT_RandomCornPhi_localrhovsphi", "centrality; #it{p}_{T,random cone} - #it{area, random cone} * #it{rho}; #Delta#varphi_{jet}", {HistType::kTH3F, {{100, 0.0, 100.0}, {400, -200.0, 200.0}, {100, 0., o2::constants::math::TwoPI}}}); - registry.add("h2_centrality_deltapT_RandomCornPhi_RCprocess_rhorandomconewithoutleadingjet", "#it{p}_{T,random cone} - #it{area, random cone} * #it{rho}; #Delta#varphi_{jet}", {HistType::kTH2F, {{400, -200.0, 200.0}, {100, 0., o2::constants::math::TwoPI}}}); - - registry.add("h3_centrality_deltapT_RandomCornPhi_localrhovsphiwithoutleadingjet", "centrality; #it{p}_{T,random cone} - #it{area, random cone} * #it{rho}(#varphi); #Delta#varphi_{jet}", {HistType::kTH3F, {{100, 0.0, 100.0}, {400, -200.0, 200.0}, {100, 0., o2::constants::math::TwoPI}}}); - //< bkg sub plot | end >// - //< median rho >// - registry.add("h_jet_pt_in_plane_v2", "jet pT;#it{p}^{in-plane}_{T,jet} (GeV/#it{c});entries", {HistType::kTH1F, {jetPtAxisRhoAreaSub}}); - registry.add("h_jet_pt_out_of_plane_v2", "jet pT;#it{p}^{out-of-plane}_{T,jet} (GeV/#it{c});entries", {HistType::kTH1F, {jetPtAxisRhoAreaSub}}); - registry.add("h_jet_pt_in_plane_v3", "jet pT;#it{p}^{in-plane}_{T,jet} (GeV/#it{c});entries", {HistType::kTH1F, {jetPtAxisRhoAreaSub}}); - registry.add("h_jet_pt_out_of_plane_v3", "jet pT;#it{p}^{out-of-plane}_{T,jet} (GeV/#it{c});entries", {HistType::kTH1F, {jetPtAxisRhoAreaSub}}); - - registry.add("h2_centrality_jet_pt_in_plane_v2", "centrality vs #it{p}^{in-plane}_{T,jet}; centrality; #it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH2F, {{120, -10.0, 110.0}, jetPtAxisRhoAreaSub}}); - registry.add("h2_centrality_jet_pt_out_of_plane_v2", "centrality vs #it{p}^{out-of-plane}_{T,jet}; centrality; #it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH2F, {{120, -10.0, 110.0}, jetPtAxisRhoAreaSub}}); - registry.add("h2_centrality_jet_pt_in_plane_v3", "centrality vs #it{p}^{in-plane}_{T,jet}; centrality; #it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH2F, {{120, -10.0, 110.0}, jetPtAxisRhoAreaSub}}); - registry.add("h2_centrality_jet_pt_out_of_plane_v3", "centrality vs #it{p}^{out-of-plane}_{T,jet}; centrality; #it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH2F, {{120, -10.0, 110.0}, jetPtAxisRhoAreaSub}}); - //< rho(phi) >// - registry.add("h_jet_pt_inclusive_v2_rho", "jet pT;#it{p}_{T,jet} (GeV/#it{c});entries", {HistType::kTH1F, {jetPtAxisRhoAreaSub}}); - registry.add("h_jet_pt_in_plane_v2_rho", "jet pT;#it{p}^{in-plane}_{T,jet} (GeV/#it{c});entries", {HistType::kTH1F, {jetPtAxisRhoAreaSub}}); - registry.add("h_jet_pt_out_of_plane_v2_rho", "jet pT;#it{p}^{out-of-plane}_{T,jet} (GeV/#it{c});entries", {HistType::kTH1F, {jetPtAxisRhoAreaSub}}); - registry.add("h_jet_pt_in_plane_v3_rho", "jet pT;#it{p}^{in-plane}_{T,jet} (GeV/#it{c});entries", {HistType::kTH1F, {jetPtAxisRhoAreaSub}}); - registry.add("h_jet_pt_out_of_plane_v3_rho", "jet pT;#it{p}^{out-of-plane}_{T,jet} (GeV/#it{c});entries", {HistType::kTH1F, {jetPtAxisRhoAreaSub}}); - - registry.add("h2_centrality_jet_pt_in_plane_v2_rho", "centrality vs #it{p}^{in-plane}_{T,jet}; centrality; #it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH2F, {{120, -10.0, 110.0}, jetPtAxisRhoAreaSub}}); - registry.add("h2_centrality_jet_pt_out_of_plane_v2_rho", "centrality vs #it{p}^{out-of-plane}_{T,jet}; centrality; #it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH2F, {{120, -10.0, 110.0}, jetPtAxisRhoAreaSub}}); - registry.add("h2_centrality_jet_pt_in_plane_v3_rho", "centrality vs #it{p}^{in-plane}_{T,jet}; centrality; #it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH2F, {{120, -10.0, 110.0}, jetPtAxisRhoAreaSub}}); - registry.add("h2_centrality_jet_pt_out_of_plane_v3_rho", "centrality vs #it{p}^{out-of-plane}_{T,jet}; centrality; #it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH2F, {{120, -10.0, 110.0}, jetPtAxisRhoAreaSub}}); + registry.add("h_jet_phat", "jet #hat{p};#hat{p} (GeV/#it{c});entries", {HistType::kTH1F, {{1000, 0, 1000}}}); + registry.add("h_jet_phat_weighted", "jet #hat{p};#hat{p} (GeV/#it{c});entries", {HistType::kTH1F, {{1000, 0, 1000}}}); + + if (doprocessSigmaPtMCP) { + registry.add("h_jet_eta_part_rhoareasubtracted", "part jet #eta;#eta^{part}; counts", {HistType::kTH1F, {jetEtaAxis}}); + registry.add("h_jet_phi_part_rhoareasubtracted", "part jet #varphi;#varphi^{part}; counts", {HistType::kTH1F, {phiAxis}}); + registry.add("h2_jet_pt_part_jet_area_part_rhoareasubtracted", "part jet #it{p}_{T,jet} vs. Area_{jet}; #it{p}_{T,jet}^{part} (GeV/#it{c}); Area_{jet}^{part}", {HistType::kTH2F, {jetPtAxisRhoAreaSub, {150, 0., 1.5}}}); + registry.add("h3_jet_pt_jet_eta_jet_phi_part_rhoareasubtracted", "part jet pt vs. eta vs.phi", {HistType::kTH3F, {jetPtAxisRhoAreaSub, jetEtaAxis, phiAxis}}); + registry.add("leadJetPtMCP", "MCP leadJet Pt ", {HistType::kTH1F, {{200, 0., 200.0}}}); + registry.add("leadJetPhiMCP", "MCP leadJet constituent #phi ", {HistType::kTH1F, {{80, -1.0, 7.}}}); + registry.add("leadJetEtaMCP", "MCP leadJet constituent #eta ", {HistType::kTH1F, {{100, -1.0, 1.0}}}); + registry.add("h_mcp_evtnum_NTrk", "MCP eventNumber vs Number of Track ; #eventNumber", {HistType::kTH1F, {{1000, 0.0, 1000}}}); + registry.add("h3_mcp_centrality_localrho_phi", "MCP centrality; #rho_{local}; #Delta#varphi_{jet}", {HistType::kTH3F, {{120, -10.0, 110.0}, {200, 0.0, 200.0}, {40, 0., o2::constants::math::TwoPI}}}); + registry.add("h_mcp_jet_pt_rholocal", "jet pT rholocal;#it{p}_{T,jet} (GeV/#it{c});entries", {HistType::kTH1F, {jetPtAxisRhoAreaSub}}); + registry.add("h2_mcp_phi_rholocal", "#varphi vs #rho(#varphi); #varphi - #Psi_{EP,2}; #rho(#varphi) ", {HistType::kTH2F, {{40, 0., o2::constants::math::TwoPI}, {210, -10.0, 200.0}}}); + //< MCP fit test >// + registry.add("h_mcp_ptsum_sumpt", "jet sumpt;sum p_{T};entries", {HistType::kTH1F, {{40, 0., o2::constants::math::TwoPI}}}); + registry.add("h2_mcp_phi_track_eta", "phi vs track eta; #eta (GeV/#it{c}); #varphi", {HistType::kTH2F, {{100, -1.0, 1.0}, {40, 0., o2::constants::math::TwoPI}}}); + registry.add("h_mcp_evtnum_centrlity", "eventNumber vs centrality ; #eventNumber", {HistType::kTH1F, {{1000, 0.0, 1000}}}); + registry.add("h_mcp_v2obs_centrality", "fitparameter v2obs vs centrality ; #centrality", {HistType::kTProfile, {cfgAxisVnCent}}); + registry.add("h_mcp_v3obs_centrality", "fitparameter v3obs vs centrality ; #centrality", {HistType::kTProfile, {cfgAxisVnCent}}); + registry.add("h_mcp_fitparaRho_evtnum", "fitparameter #rho_{0} vs evtnum ; #eventnumber", {HistType::kTH1F, {{1000, 0.0, 1000}}}); + registry.add("h_mcp_fitparaPsi2_evtnum", "fitparameter #Psi_{2} vs evtnum ; #eventnumber", {HistType::kTH1F, {{1000, 0.0, 1000}}}); + registry.add("h_mcp_fitparaPsi3_evtnum", "fitparameter #Psi_{3} vs evtnum ; #eventnumber", {HistType::kTH1F, {{1000, 0.0, 1000}}}); + registry.add("h_mcp_fitparav2obs_evtnum", "fitparameter v2obs vs evtnum ; #eventnumber", {HistType::kTH1F, {{1000, 0.0, 1000}}}); + registry.add("h_mcp_fitparav3obs_evtnum", "fitparameter v3obs vs evtnum ; #eventnumber", {HistType::kTH1F, {{1000, 0.0, 1000}}}); + + registry.add("h_mcp_jet_pt_in_plane_v2_rho", "jet pT;#it{p}^{in-plane}_{T,jet} (GeV/#it{c});entries", {HistType::kTH1F, {jetPtAxisRhoAreaSub}}); + registry.add("h_mcp_jet_pt_out_of_plane_v2_rho", "jet pT;#it{p}^{out-of-plane}_{T,jet} (GeV/#it{c});entries", {HistType::kTH1F, {jetPtAxisRhoAreaSub}}); + registry.add("h_mcp_jet_pt_in_plane_v3_rho", "jet pT;#it{p}^{in-plane}_{T,jet} (GeV/#it{c});entries", {HistType::kTH1F, {jetPtAxisRhoAreaSub}}); + registry.add("h_mcp_jet_pt_out_of_plane_v3_rho", "jet pT;#it{p}^{out-of-plane}_{T,jet} (GeV/#it{c});entries", {HistType::kTH1F, {jetPtAxisRhoAreaSub}}); + + registry.add("h2_mcp_centrality_jet_pt_in_plane_v2_rho", "centrality vs #it{p}^{in-plane}_{T,jet}; centrality; #it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH2F, {{120, -10.0, 110.0}, jetPtAxisRhoAreaSub}}); + registry.add("h2_mcp_centrality_jet_pt_out_of_plane_v2_rho", "centrality vs #it{p}^{out-of-plane}_{T,jet}; centrality; #it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH2F, {{120, -10.0, 110.0}, jetPtAxisRhoAreaSub}}); + registry.add("h2_mcp_centrality_jet_pt_in_plane_v3_rho", "centrality vs #it{p}^{in-plane}_{T,jet}; centrality; #it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH2F, {{120, -10.0, 110.0}, jetPtAxisRhoAreaSub}}); + registry.add("h2_mcp_centrality_jet_pt_out_of_plane_v3_rho", "centrality vs #it{p}^{out-of-plane}_{T,jet}; centrality; #it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH2F, {{120, -10.0, 110.0}, jetPtAxisRhoAreaSub}}); + + registry.add("h3_mcp_centrality_deltapT_RandomCornPhi_localrhovsphi", "centrality; #it{p}_{T,random cone} - #it{area, random cone} * #it{rho}; #Delta#varphi_{jet}", {HistType::kTH3F, {{100, 0.0, 100.0}, {400, -200.0, 200.0}, {100, 0., o2::constants::math::TwoPI}}}); + registry.add("h3_mcp_centrality_deltapT_RandomCornPhi_rhorandomconewithoutleadingjet", "centrality; #it{p}_{T,random cone} - #it{area, random cone} * #it{rho}; #Delta#varphi_{jet}", {HistType::kTH3F, {{100, 0.0, 100.0}, {400, -200.0, 200.0}, {100, 0., o2::constants::math::TwoPI}}}); + registry.add("h3_mcp_centrality_deltapT_RandomCornPhi_localrhovsphiwithoutleadingjet", "centrality; #it{p}_{T,random cone} - #it{area, random cone} * #it{rho}(#varphi); #Delta#varphi_{jet}", {HistType::kTH3F, {{100, 0.0, 100.0}, {400, -200.0, 200.0}, {100, 0., o2::constants::math::TwoPI}}}); + + registry.add("h_mcColl_counts_areasub", " number of mc events; event status; entries", {HistType::kTH1F, {{10, 0, 10}}}); + registry.get(HIST("h_mcColl_counts_areasub"))->GetXaxis()->SetBinLabel(1, "allMcColl"); + registry.get(HIST("h_mcColl_counts_areasub"))->GetXaxis()->SetBinLabel(2, "vertexZ"); + registry.get(HIST("h_mcColl_counts_areasub"))->GetXaxis()->SetBinLabel(3, "noRecoColl"); + registry.get(HIST("h_mcColl_counts_areasub"))->GetXaxis()->SetBinLabel(4, "splitColl"); + registry.get(HIST("h_mcColl_counts_areasub"))->GetXaxis()->SetBinLabel(5, "recoEvtSel"); + registry.get(HIST("h_mcColl_counts_areasub"))->GetXaxis()->SetBinLabel(6, "centralitycut"); + registry.get(HIST("h_mcColl_counts_areasub"))->GetXaxis()->SetBinLabel(7, "occupancycut"); + registry.add("h_mcColl_rho", "mc collision rho;#rho (GeV/#it{c}); counts", {HistType::kTH1F, {{500, 0.0, 500.0}}}); + + //< \sigma p_T at local rho test plot > + registry.add("h_accept_Track", "all and accept track;Track;entries", {HistType::kTH1F, {{10, 0.0, 10.0}}}); + registry.get(HIST("h_accept_Track"))->GetXaxis()->SetBinLabel(1, "acceptTrk"); + registry.get(HIST("h_accept_Track"))->GetXaxis()->SetBinLabel(2, "acceptTrkInFit"); + registry.get(HIST("h_accept_Track"))->GetXaxis()->SetBinLabel(3, "beforeSumptFit"); + registry.get(HIST("h_accept_Track"))->GetXaxis()->SetBinLabel(4, "afterSumptFit"); + registry.get(HIST("h_accept_Track"))->GetXaxis()->SetBinLabel(5, "getNtrk"); + registry.get(HIST("h_accept_Track"))->GetXaxis()->SetBinLabel(6, "getNtrkMCP"); + //< fit test >// + registry.add("h_ptsum_collnum", "ptsum collnum;collnum;entries", {HistType::kTH1F, {{40, 0.0, 40}}}); + registry.add("h_ptsum_sumpt", "jet sumpt;sum p_{T};entries", {HistType::kTH1F, {{40, 0., o2::constants::math::TwoPI}}}); + } + if (doprocessInOutJetV2 || doprocessInOutJetV2MCD || doprocessSigmaPt || doprocessSigmaPtMCD) { + //< Track efficiency plots >// + registry.add("h_collisions", "event status;event status;entries", {HistType::kTH1F, {{4, 0.0, 4.0}}}); + registry.add("h2_centrality_collisions", "centrality vs collisions; centrality; collisions", {HistType::kTH2F, {{120, -10., 110.}, {4, 0.0, 4.0}}}); + registry.add("h2_centrality_track_pt", "centrality vs track pT; centrality; #it{p}_{T,track} (GeV/#it{c})", {HistType::kTH2F, {{1200, -10.0, 110.0}, {200, 0., 200.}}}); + registry.add("h2_centrality_track_eta", "centrality vs track #eta; centrality; #eta_{track}", {HistType::kTH2F, {{1200, -10.0, 110.0}, {100, -1.0, 1.0}}}); + registry.add("h2_centrality_track_phi", "centrality vs track #varphi; centrality; #varphi_{track}", {HistType::kTH2F, {{1200, -10.0, 110.0}, {160, -1.0, 7.}}}); + registry.add("h2_centrality_track_energy", "centrality vs track energy; centrality; Energy GeV", {HistType::kTH2F, {{120, -10., 110.}, {100, 0.0, 100.0}}}); + registry.add("h2_track_pt_track_sigmapt", "#sigma(#it{p}_{T})/#it{p}_{T}; #it{p}_{T,track} (GeV/#it{c})", {HistType::kTH2F, {{100, 0., 10.}, {100000, 0.0, 100.0}}}); + registry.add("h2_track_pt_high_track_sigmapt", "#sigma(#it{p}_{T})/#it{p}_{T}; #it{p}_{T,track} (GeV/#it{c})", {HistType::kTH2F, {{90, 10., 100.}, {100000, 0.0, 100.0}}}); + registry.add("h2_track_pt_track_sigma1overpt", "#sigma(1/#it{p}_{T}); #it{p}_{T,track} (GeV/#it{c})", {HistType::kTH2F, {{100, 0., 10.}, {1000, 0.0, 10.0}}}); + registry.add("h2_track_pt_high_track_sigma1overpt", "#sigma(1/#it{p}_{T}); #it{p}_{T,track} (GeV/#it{c})", {HistType::kTH2F, {{90, 10., 100.}, {1000, 0.0, 10.0}}}); + + //< \sigma p_T at local rho test plot > + registry.add("h_accept_Track", "all and accept track;Track;entries", {HistType::kTH1F, {{10, 0.0, 10.0}}}); + registry.get(HIST("h_accept_Track"))->GetXaxis()->SetBinLabel(1, "acceptTrk"); + registry.get(HIST("h_accept_Track"))->GetXaxis()->SetBinLabel(2, "acceptTrkInFit"); + registry.get(HIST("h_accept_Track"))->GetXaxis()->SetBinLabel(3, "beforeSumptFit"); + registry.get(HIST("h_accept_Track"))->GetXaxis()->SetBinLabel(4, "afterSumptFit"); + registry.get(HIST("h_accept_Track"))->GetXaxis()->SetBinLabel(5, "getNtrk"); + registry.get(HIST("h_accept_Track"))->GetXaxis()->SetBinLabel(6, "getNtrkMCP"); + + registry.add("h_ptsum_collnum", "ptsum collnum;collnum;entries", {HistType::kTH1F, {{40, 0.0, 40}}}); + registry.add("h_ptsum_sumpt", "jet sumpt;sum p_{T};entries", {HistType::kTH1F, {{40, 0., o2::constants::math::TwoPI}}}); + registry.add("h2_phi_track_eta", "phi vs track eta; #eta (GeV/#it{c}); #varphi", {HistType::kTH2F, {{100, -1.0, 1.0}, {40, 0., o2::constants::math::TwoPI}}}); + registry.add("h2_centrality_phi_w_pt", "centrality vs jet #varphi; centrality; entries", {HistType::kTH2F, {{100, 0.0, 100.0}, {40, 0., o2::constants::math::TwoPI}}}); + registry.add("h2_evtnum_phi_w_pt", "eventNumber vs jet #varphi; #eventNumber; entries", {HistType::kTH2F, {{1000, 0.0, 1000}, {40, 0., o2::constants::math::TwoPI}}}); + + //< fit quality >// + registry.add("h_PvalueCDF_CombinFit", "cDF #chi^{2}; entries", {HistType::kTH1F, {{50, 0, 1}}}); + registry.add("h2_PvalueCDFCent_CombinFit", "p-value cDF vs centrality; centrality; p-value", {HistType::kTH2F, {{100, 0, 100}, {40, 0, 1}}}); + registry.add("h2_Chi2Cent_CombinFit", "Chi2 vs centrality; centrality; #tilde{#chi^{2}}", {HistType::kTH2F, {{100, 0, 100}, {100, 0, 5}}}); + registry.add("h2_PChi2_CombinFit", "p-value vs #tilde{#chi^{2}}; p-value; #tilde{#chi^{2}}", {HistType::kTH2F, {{100, 0, 1}, {100, 0, 5}}}); + + registry.add("Thn_PChi2_CombinFitCent", "p-value vs #tilde{#chi^{2}}; p-value; #tilde{#chi^{2}}", {HistType::kTHnSparseF, {{100, 0.0, 100.0}, {100, 0, 1}, {100, 0, 5}}}); + registry.add("h2_PChi2_CombinFitA", "p-value vs #tilde{#chi^{2}}; p-value; #tilde{#chi^{2}}", {HistType::kTH2F, {{100, 0, 1}, {100, 0, 5}}}); + registry.add("h2_PChi2_CombinFitB", "p-value vs #tilde{#chi^{2}}; p-value; #tilde{#chi^{2}}", {HistType::kTH2F, {{100, 0, 1}, {100, 0, 5}}}); + + registry.add("h_evtnum_centrlity", "eventNumber vs centrality ; #eventNumber", {HistType::kTH1F, {{1000, 0.0, 1000}}}); + registry.add("h_evtnum_NTrk", "eventNumber vs Number of Track ; #eventNumber", {HistType::kTH1F, {{1000, 0.0, 1000}}}); + + registry.add("Thn_evtnum_phi_centrality", "eventNumber vs jet #varphi; #eventNumber; entries", {HistType::kTHnSparseF, {{1000, 0.0, 1000}, {40, 0., o2::constants::math::TwoPI}, {100, 0.0, 100.0}}}); + + registry.add("h2_evt_fitpara", "event vs fit parameter; evtnum; parameter", {HistType::kTH2F, {cfgAxisEvtfit, {5, 0., 5}}}); + registry.add("h_v2obs_centrality", "fitparameter v2obs vs centrality ; #centrality", {HistType::kTProfile, {cfgAxisVnCent}}); + registry.add("h_v3obs_centrality", "fitparameter v3obs vs centrality ; #centrality", {HistType::kTProfile, {cfgAxisVnCent}}); + + registry.add("h_fitparaRho_evtnum", "fitparameter #rho_{0} vs evtnum ; #eventnumber", {HistType::kTH1F, {{1000, 0.0, 1000}}}); + registry.add("h_fitparaPsi2_evtnum", "fitparameter #Psi_{2} vs evtnum ; #eventnumber", {HistType::kTH1F, {{1000, 0.0, 1000}}}); + registry.add("h_fitparaPsi3_evtnum", "fitparameter #Psi_{3} vs evtnum ; #eventnumber", {HistType::kTH1F, {{1000, 0.0, 1000}}}); + registry.add("h_fitparav2obs_evtnum", "fitparameter v2obs vs evtnum ; #eventnumber", {HistType::kTH1F, {{1000, 0.0, 1000}}}); + registry.add("h_fitparav3obs_evtnum", "fitparameter v3obs vs evtnum ; #eventnumber", {HistType::kTH1F, {{1000, 0.0, 1000}}}); + + registry.add("h2_fitParaZero_cent", "#varphi vs #rho(#varphi); #cent; #fitParameter[0] ", {HistType::kTH2F, {{100, 0., 100}, {210, -10.0, 200.0}}}); + registry.add("h2_phi_rhophi", "#varphi vs #rho(#varphi); #varphi - #Psi_{EP,2}; #rho_{ch}(#varphi) ", {HistType::kTH2F, {{40, 0., o2::constants::math::TwoPI}, {210, -10.0, 200.0}}}); + registry.add("h2_phi_rholocal", "#varphi vs #rho(#varphi); #varphi - #Psi_{EP,2}; #rho(#varphi) ", {HistType::kTH2F, {{40, 0., o2::constants::math::TwoPI}, {210, -10.0, 200.0}}}); + registry.add("h2_phi_rholocal_cent", "#varphi vs #rho(#varphi); #cent; #rho(#varphi) ", {HistType::kTH2F, {{100, 0., 100}, {210, -10.0, 200.0}}}); + registry.add("h3_centrality_localrho_phi", "centrality; #rho_{local}; #Delta#varphi_{jet}", {HistType::kTH3F, {{120, -10.0, 110.0}, {200, 0.0, 200.0}, {40, 0., o2::constants::math::TwoPI}}}); + + registry.add("h3_centrality_rhovsphi_phi", "centrality; #rho(#varphi); #Delta#varphi_{jet}", {HistType::kTH3F, {{120, -10.0, 110.0}, {200, 0.0, 200.0}, {40, 0., o2::constants::math::TwoPI}}}); + //< \sigma p_T at local rho test plot | end > + + registry.add("h_jet_pt_rhoareasubtracted", "jet pT rhoareasubtracted;#it{p}_{T,jet} (GeV/#it{c}); entries", {HistType::kTH1F, {jetPtAxisRhoAreaSub}}); + registry.add("h_jet_pt_rholocal", "jet pT rholocal;#it{p}_{T,jet} (GeV/#it{c});entries", {HistType::kTH1F, {jetPtAxisRhoAreaSub}}); + + registry.add("leadJetPt", "leadJet Pt ", {HistType::kTH1F, {{200, 0., 200.0}}}); + registry.add("leadJetPhi", "leadJet constituent #phi ", {HistType::kTH1F, {{80, -1.0, 7.}}}); + registry.add("leadJetEta", "leadJet constituent #eta ", {HistType::kTH1F, {{100, -1.0, 1.0}}}); + + //< RC test plots >// + registry.add("h3_centrality_deltapT_RandomCornPhi_rhorandomconewithoutleadingjet", "centrality; #it{p}_{T,random cone} - #it{area, random cone} * #it{rho}; #Delta#varphi_{jet}", {HistType::kTH3F, {{100, 0.0, 100.0}, {400, -200.0, 200.0}, {100, 0., o2::constants::math::TwoPI}}}); + registry.add("h3_centrality_deltapT_RandomCornPhi_localrhovsphi", "centrality; #it{p}_{T,random cone} - #it{area, random cone} * #it{rho}; #Delta#varphi_{jet}", {HistType::kTH3F, {{100, 0.0, 100.0}, {400, -200.0, 200.0}, {100, 0., o2::constants::math::TwoPI}}}); + + registry.add("h3_centrality_deltapT_RandomCornPhi_localrhovsphiwithoutleadingjet", "centrality; #it{p}_{T,random cone} - #it{area, random cone} * #it{rho}(#varphi); #Delta#varphi_{jet}", {HistType::kTH3F, {{100, 0.0, 100.0}, {400, -200.0, 200.0}, {100, 0., o2::constants::math::TwoPI}}}); + //< bkg sub plot | end >// + //< median rho >// + registry.add("h_jet_pt_in_plane_v2", "jet pT;#it{p}^{in-plane}_{T,jet} (GeV/#it{c});entries", {HistType::kTH1F, {jetPtAxisRhoAreaSub}}); + registry.add("h_jet_pt_out_of_plane_v2", "jet pT;#it{p}^{out-of-plane}_{T,jet} (GeV/#it{c});entries", {HistType::kTH1F, {jetPtAxisRhoAreaSub}}); + registry.add("h_jet_pt_in_plane_v3", "jet pT;#it{p}^{in-plane}_{T,jet} (GeV/#it{c});entries", {HistType::kTH1F, {jetPtAxisRhoAreaSub}}); + registry.add("h_jet_pt_out_of_plane_v3", "jet pT;#it{p}^{out-of-plane}_{T,jet} (GeV/#it{c});entries", {HistType::kTH1F, {jetPtAxisRhoAreaSub}}); + + registry.add("h2_centrality_jet_pt_in_plane_v2", "centrality vs #it{p}^{in-plane}_{T,jet}; centrality; #it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH2F, {{120, -10.0, 110.0}, jetPtAxisRhoAreaSub}}); + registry.add("h2_centrality_jet_pt_out_of_plane_v2", "centrality vs #it{p}^{out-of-plane}_{T,jet}; centrality; #it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH2F, {{120, -10.0, 110.0}, jetPtAxisRhoAreaSub}}); + registry.add("h2_centrality_jet_pt_in_plane_v3", "centrality vs #it{p}^{in-plane}_{T,jet}; centrality; #it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH2F, {{120, -10.0, 110.0}, jetPtAxisRhoAreaSub}}); + registry.add("h2_centrality_jet_pt_out_of_plane_v3", "centrality vs #it{p}^{out-of-plane}_{T,jet}; centrality; #it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH2F, {{120, -10.0, 110.0}, jetPtAxisRhoAreaSub}}); + //< rho(phi) >// + registry.add("h_jet_pt_inclusive_v2_rho", "jet pT;#it{p}_{T,jet} (GeV/#it{c});entries", {HistType::kTH1F, {jetPtAxisRhoAreaSub}}); + registry.add("h_jet_pt_in_plane_v2_rho", "jet pT;#it{p}^{in-plane}_{T,jet} (GeV/#it{c});entries", {HistType::kTH1F, {jetPtAxisRhoAreaSub}}); + registry.add("h_jet_pt_out_of_plane_v2_rho", "jet pT;#it{p}^{out-of-plane}_{T,jet} (GeV/#it{c});entries", {HistType::kTH1F, {jetPtAxisRhoAreaSub}}); + registry.add("h_jet_pt_in_plane_v3_rho", "jet pT;#it{p}^{in-plane}_{T,jet} (GeV/#it{c});entries", {HistType::kTH1F, {jetPtAxisRhoAreaSub}}); + registry.add("h_jet_pt_out_of_plane_v3_rho", "jet pT;#it{p}^{out-of-plane}_{T,jet} (GeV/#it{c});entries", {HistType::kTH1F, {jetPtAxisRhoAreaSub}}); + + registry.add("h2_centrality_jet_pt_in_plane_v2_rho", "centrality vs #it{p}^{in-plane}_{T,jet}; centrality; #it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH2F, {{120, -10.0, 110.0}, jetPtAxisRhoAreaSub}}); + registry.add("h2_centrality_jet_pt_out_of_plane_v2_rho", "centrality vs #it{p}^{out-of-plane}_{T,jet}; centrality; #it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH2F, {{120, -10.0, 110.0}, jetPtAxisRhoAreaSub}}); + registry.add("h2_centrality_jet_pt_in_plane_v3_rho", "centrality vs #it{p}^{in-plane}_{T,jet}; centrality; #it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH2F, {{120, -10.0, 110.0}, jetPtAxisRhoAreaSub}}); + registry.add("h2_centrality_jet_pt_out_of_plane_v3_rho", "centrality vs #it{p}^{out-of-plane}_{T,jet}; centrality; #it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH2F, {{120, -10.0, 110.0}, jetPtAxisRhoAreaSub}}); + + registry.add("h2_centrality_jet_pt_rhoareasubtracted", "centrality vs. jet pT;centrality; #it{p}_{T,jet} (GeV/#it{c}); counts", {HistType::kTH2F, {centralityAxis, jetPtAxisRhoAreaSub}}); + registry.add("h2_centrality_jet_eta_rhoareasubtracted", "centrality vs. jet eta;centrality; #eta; counts", {HistType::kTH2F, {centralityAxis, jetEtaAxis}}); + registry.add("h2_centrality_jet_phi_rhoareasubtracted", "centrality vs. jet phi;centrality; #varphi; counts", {HistType::kTH2F, {centralityAxis, phiAxis}}); + registry.add("h2_jet_pt_jet_area_rhoareasubtracted", "jet #it{p}_{T,jet} vs. Area_{jet}; #it{p}_{T,jet} (GeV/#it{c}); Area_{jet}", {HistType::kTH2F, {jetPtAxis, {150, 0., 1.5}}}); + registry.add("h3_jet_pt_jet_eta_jet_phi_rhoareasubtracted", "jet_pt_eta_phi_rhoareasubtracted", {HistType::kTH3F, {jetPtAxisRhoAreaSub, jetEtaAxis, phiAxis}}); + 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}}); + } + //< track test >// + registry.add("h_track_pt", "track #it{p}_{T} ; #it{p}_{T,track} (GeV/#it{c})", {HistType::kTH1F, {trackPtAxis}}); + registry.add("h2_track_eta_track_phi", "track eta vs. track phi; #eta; #phi; counts", {HistType::kTH2F, {trackEtaAxis, phiAxis}}); //=====================< evt pln plot >=====================// AxisSpec axisCent{cfgAxisCent, "centrality"}; AxisSpec axisQvec{cfgAxisQvec, "Q"}; @@ -334,34 +428,37 @@ struct JetChargedV2 { //=====================< evt pln plot | end >=====================// } - Preslice jetsPerJCollision = o2::aod::jet::collisionId; - Preslice tracksPerJCollision = o2::aod::jtrack::collisionId; - + Preslice tracksPerJCollision = o2::aod::jtrack::collisionId; Filter trackCuts = (aod::jtrack::pt >= trackPtMin && aod::jtrack::pt < trackPtMax && aod::jtrack::eta > trackEtaMin && aod::jtrack::eta < trackEtaMax); Filter eventCuts = (nabs(aod::jcollision::posZ) < vertexZCut && aod::jcollision::centrality >= centralityMin && aod::jcollision::centrality < centralityMax); + PresliceUnsorted> collisionsPerMCPCollision = aod::jmccollisionlb::mcCollisionId; - template - bool isAcceptedJet(U const& jet) + template + bool isAcceptedJet(TJets const& jet, bool mcLevelIsParticleLevel = false) { - double jetAreaFractionMinCfgMin = -98.0; - double jetAreaFractionMinCfgMax = 9998.0; - if (jetAreaFractionMin > jetAreaFractionMinCfgMin) { + double jetAreaFractionMinAcc = -98.0; + double leadingConstituentPtMinAcc = -98.0; + double leadingConstituentPtMaxAcc = 9998.0; + if (jetAreaFractionMin > jetAreaFractionMinAcc) { if (jet.area() < jetAreaFractionMin * o2::constants::math::PI * (jet.r() / 100.0) * (jet.r() / 100.0)) { return false; } } bool checkConstituentPt = true; - bool checkConstituentMinPt = (leadingConstituentPtMin > jetAreaFractionMinCfgMin); - bool checkConstituentMaxPt = (leadingConstituentPtMax < jetAreaFractionMinCfgMax); + bool checkConstituentMinPt = (leadingConstituentPtMin > leadingConstituentPtMinAcc); + bool checkConstituentMaxPt = (leadingConstituentPtMax < leadingConstituentPtMaxAcc); if (!checkConstituentMinPt && !checkConstituentMaxPt) { checkConstituentPt = false; } + if (mcLevelIsParticleLevel && !checkLeadConstituentPtForMcpJets) { + checkConstituentPt = false; + } if (checkConstituentPt) { bool isMinLeadingConstituent = !checkConstituentMinPt; bool isMaxLeadingConstituent = true; - for (const auto& constituent : jet.template tracks_as()) { + for (const auto& constituent : jet.template tracks_as()) { double pt = constituent.pt(); if (checkConstituentMinPt && pt >= leadingConstituentPtMin) { @@ -373,51 +470,322 @@ struct JetChargedV2 { } return isMinLeadingConstituent && isMaxLeadingConstituent; } - return true; } - template - bool trackIsInJet(T const& track, U const& jet) + double chiSquareCDF(int nDF, double x) { - for (auto const& constituentId : jet.tracksIds()) { - if (constituentId == track.globalIndex()) { - return true; + return TMath::Gamma(nDF / 2., x / 2.); + } + + // leading jet fill + template + void fillLeadingJetQA(T const& jets, double& leadingJetPt, double& leadingJetPhi, double& leadingJetEta) + { + for (const auto& jet : jets) { + if (jet.pt() > leadingJetPt) { + leadingJetPt = jet.pt(); + leadingJetEta = jet.eta(); + leadingJetPhi = jet.phi(); } } - return false; + registry.fill(HIST("leadJetPt"), leadingJetPt); + registry.fill(HIST("leadJetPhi"), leadingJetPhi); + registry.fill(HIST("leadJetEta"), leadingJetEta); } + // create h_ptsum_sumpt_fit, with number of Track template - void fillTrackHistograms(T const& collision, U const& tracks, float weight = 1.0) + void getNtrk(T const& tracks, U const& jets, int& nTrk, double& evtnum, double& leadingJetEta) { - for (auto const& track : tracks) { - if (!(jetderiveddatautilities::selectTrack(track, trackSelection) && jetderiveddatautilities::selectTrackDcaZ(track, trackDcaZmax))) { + if (jets.size() > 0) { + for (auto const& track : tracks) { + if (jetderiveddatautilities::selectTrack(track, trackSelection) && (std::fabs(track.eta() - leadingJetEta) > jetRadius) && track.pt() >= localRhoFitPtMin && track.pt() <= localRhoFitPtMax) { + registry.fill(HIST("h_accept_Track"), 4.5); + nTrk += 1; + } + } + registry.fill(HIST("h_evtnum_NTrk"), evtnum, nTrk); + } + } + + // fill nTrk plot for fit rho(varphi) + template + void fillNtrkCheck(T const& collision, U const& tracks, J const& jets, TH1F* hPtsumSumptFit, double& leadingJetEta, double& evtnum) + { + if (jets.size() > 0) { + for (auto const& trackfit : tracks) { + registry.fill(HIST("h_accept_Track"), 0.5); + if (jetderiveddatautilities::selectTrack(trackfit, trackSelection) && (std::fabs(trackfit.eta() - leadingJetEta) > jetRadius) && trackfit.pt() >= localRhoFitPtMin && trackfit.pt() <= localRhoFitPtMax) { + registry.fill(HIST("h_accept_Track"), 1.5); + } + } + + for (auto const& track : tracks) { + registry.fill(HIST("h_accept_Track"), 2.5); + if (jetderiveddatautilities::selectTrack(track, trackSelection) && (std::fabs(track.eta() - leadingJetEta) > jetRadius) && track.pt() >= localRhoFitPtMin && track.pt() <= localRhoFitPtMax) { + registry.fill(HIST("h_accept_Track"), 3.5); + hPtsumSumptFit->Fill(track.phi(), track.pt()); + registry.fill(HIST("h2_phi_track_eta"), track.eta(), track.phi()); + registry.fill(HIST("h_ptsum_sumpt"), track.phi(), track.pt()); + registry.fill(HIST("h2_centrality_phi_w_pt"), collision.centrality(), track.phi(), track.pt()); + registry.fill(HIST("h2_evtnum_phi_w_pt"), evtnum, track.phi(), track.pt()); + registry.fill(HIST("Thn_evtnum_phi_centrality"), evtnum, track.phi(), collision.centrality()); + } + } + } + } + + // MCP leading jet fill + template + void fillLeadingJetQAMCP(T const& jets, double& leadingJetPt, double& leadingJetPhi, double& leadingJetEta) + { + for (const auto& jet : jets) { + if (jet.pt() > leadingJetPt) { + leadingJetPt = jet.pt(); + leadingJetEta = jet.eta(); + leadingJetPhi = jet.phi(); + } + } + registry.fill(HIST("leadJetPtMCP"), leadingJetPt); + registry.fill(HIST("leadJetPhiMCP"), leadingJetPhi); + registry.fill(HIST("leadJetEtaMCP"), leadingJetEta); + } + + template + void fitFncMCP(U const& collision, T const& tracks, J const& jets, TH1F* hPtsumSumptFitMCP, double leadingJetEta, bool mcLevelIsParticleLevel, float weight = 1.0) + { + double ep2 = 0.; + double ep3 = 0.; + int cfgNmodA = 2; + int cfgNmodB = 3; + int evtPlnAngleA = 7; + int evtPlnAngleB = 3; + int evtPlnAngleC = 5; + for (uint i = 0; i < cfgnMods->size(); i++) { + int nmode = cfgnMods->at(i); + int detInd = detId * 4 + cfgnTotalSystem * 4 * (nmode - 2); + if (nmode == cfgNmodA) { + if (collision.qvecAmp()[detId] > collQvecAmpDetId) { + ep2 = helperEP.GetEventPlane(collision.qvecRe()[detInd + 3], collision.qvecIm()[detInd + 3], nmode); + } + } else if (nmode == cfgNmodB) { + if (collision.qvecAmp()[detId] > collQvecAmpDetId) { + ep3 = helperEP.GetEventPlane(collision.qvecRe()[detInd + 3], collision.qvecIm()[detInd + 3], nmode); + } + } + } + + const char* fitFunctionV2v3P = "[0] * (1. + 2. * ([1] * std::cos(2. * (x - [2])) + [3] * std::cos(3. * (x - [4]))))"; + fFitModulationV2v3P = new TF1("fit_kV3", fitFunctionV2v3P, 0, o2::constants::math::TwoPI); + //=========================< set parameter >=========================// + fFitModulationV2v3P->SetParameter(0, 1.); + fFitModulationV2v3P->SetParameter(1, 0.01); + fFitModulationV2v3P->SetParameter(3, 0.01); + + double ep2fix = 0.; + double ep3fix = 0.; + + if (ep2 < 0) { + ep2fix = RecoDecay::constrainAngle(ep2); + fFitModulationV2v3P->FixParameter(2, ep2fix); + } else { + fFitModulationV2v3P->FixParameter(2, ep2); + } + if (ep3 < 0) { + ep3fix = RecoDecay::constrainAngle(ep3); + fFitModulationV2v3P->FixParameter(4, ep3fix); + } else { + fFitModulationV2v3P->FixParameter(4, ep3); + } + + hPtsumSumptFitMCP->Fit(fFitModulationV2v3P, "Q", "ep", 0, o2::constants::math::TwoPI); + + // int paraNum = 5; + double temppara[5]; + temppara[0] = fFitModulationV2v3P->GetParameter(0); + temppara[1] = fFitModulationV2v3P->GetParameter(1); + temppara[2] = fFitModulationV2v3P->GetParameter(2); + temppara[3] = fFitModulationV2v3P->GetParameter(3); + temppara[4] = fFitModulationV2v3P->GetParameter(4); + if (temppara[0] == 0) { + return; + } + registry.fill(HIST("h_mcp_fitparaRho_evtnum"), evtnum, temppara[0]); + registry.fill(HIST("h_mcp_fitparav2obs_evtnum"), evtnum, temppara[1]); + registry.fill(HIST("h_mcp_fitparaPsi2_evtnum"), evtnum, temppara[2]); + registry.fill(HIST("h_mcp_fitparav3obs_evtnum"), evtnum, temppara[3]); + registry.fill(HIST("h_mcp_fitparaPsi3_evtnum"), evtnum, temppara[4]); + + registry.fill(HIST("h_mcp_v2obs_centrality"), collision.centrality(), temppara[1]); + registry.fill(HIST("h_mcp_v3obs_centrality"), collision.centrality(), temppara[3]); + registry.fill(HIST("h_mcp_evtnum_centrlity"), evtnum, collision.centrality()); + + for (uint i = 0; i < cfgnMods->size(); i++) { + int nmode = cfgnMods->at(i); + int detInd = detId * 4 + cfgnTotalSystem * 4 * (nmode - 2); + + for (auto const& jet : jets) { + if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { + continue; + } + if (!isAcceptedJet(jet, mcLevelIsParticleLevel)) { + continue; + } + if (jet.r() != round(selectedJetsRadius * 100.0f)) { + continue; + } + + double integralValue = fFitModulationV2v3P->Integral(jet.phi() - jetRadius, jet.phi() + jetRadius); + double rholocal = collision.rho() / (2 * jetRadius * temppara[0]) * integralValue; + registry.fill(HIST("h3_mcp_centrality_localrho_phi"), collision.centrality(), rholocal, jet.phi() - ep2, weight); + + if (nmode == cfgNmodA) { + registry.fill(HIST("h_mcp_jet_pt_rholocal"), jet.pt() - (rholocal * jet.area()), weight); + + double phiMinusPsi2; + if (collision.qvecAmp()[detId] < collQvecAmpDetId) { + continue; + } + phiMinusPsi2 = jet.phi() - ep2; + + registry.fill(HIST("h2_mcp_phi_rholocal"), jet.phi() - ep2, rholocal, weight); + + if ((phiMinusPsi2 < o2::constants::math::PIQuarter) || (phiMinusPsi2 >= evtPlnAngleA * o2::constants::math::PIQuarter) || (phiMinusPsi2 >= evtPlnAngleB * o2::constants::math::PIQuarter && phiMinusPsi2 < evtPlnAngleC * o2::constants::math::PIQuarter)) { + registry.fill(HIST("h_mcp_jet_pt_in_plane_v2_rho"), jet.pt() - (rholocal * jet.area()), weight); + registry.fill(HIST("h2_mcp_centrality_jet_pt_in_plane_v2_rho"), collision.centrality(), jet.pt() - (rholocal * jet.area()), weight); + } else { + registry.fill(HIST("h_mcp_jet_pt_out_of_plane_v2_rho"), jet.pt() - (rholocal * jet.area()), weight); + registry.fill(HIST("h2_mcp_centrality_jet_pt_out_of_plane_v2_rho"), collision.centrality(), jet.pt() - (rholocal * jet.area()), weight); + } + } else if (nmode == cfgNmodB) { + double phiMinusPsi3; + if (collision.qvecAmp()[detId] < collQvecAmpDetId) { + continue; + } + ep3 = helperEP.GetEventPlane(collision.qvecRe()[detInd], collision.qvecIm()[detInd], nmode); + phiMinusPsi3 = jet.phi() - ep3; + + if ((phiMinusPsi3 < o2::constants::math::PIQuarter) || (phiMinusPsi3 >= evtPlnAngleA * o2::constants::math::PIQuarter) || (phiMinusPsi3 >= evtPlnAngleB * o2::constants::math::PIQuarter && phiMinusPsi3 < evtPlnAngleC * o2::constants::math::PIQuarter)) { + registry.fill(HIST("h_mcp_jet_pt_in_plane_v3_rho"), jet.pt() - (rholocal * jet.area()), weight); + registry.fill(HIST("h2_mcp_centrality_jet_pt_in_plane_v3_rho"), collision.centrality(), jet.pt() - (rholocal * jet.area()), weight); + } else { + registry.fill(HIST("h_mcp_jet_pt_out_of_plane_v3_rho"), jet.pt() - (rholocal * jet.area()), weight); + registry.fill(HIST("h2_mcp_centrality_jet_pt_out_of_plane_v3_rho"), collision.centrality(), jet.pt() - (rholocal * jet.area()), weight); + } + } + } + } + // RCpT + for (uint i = 0; i < cfgnMods->size(); i++) { + TRandom3 randomNumber(0); + float randomConeEta = randomNumber.Uniform(trackEtaMin + randomConeR, trackEtaMax - randomConeR); + float randomConePhi = randomNumber.Uniform(0.0, o2::constants::math::TwoPI); + float randomConePt = 0; + double integralValueRC = fFitModulationV2v3P->Integral(randomConePhi - randomConeR, randomConePhi + randomConeR); + double rholocalRC = collision.rho() / (2 * randomConeR * temppara[0]) * integralValueRC; + + int nmode = cfgnMods->at(i); + if (nmode == cfgNmodA) { + double rcPhiPsi2; + rcPhiPsi2 = randomConePhi - ep2; + + for (auto const& track : tracks) { + if (jetderiveddatautilities::selectTrack(track, trackSelection)) { + float dPhi = RecoDecay::constrainAngle(track.phi() - randomConePhi, static_cast(-o2::constants::math::PI)); + float dEta = track.eta() - randomConeEta; + if (std::sqrt(dEta * dEta + dPhi * dPhi) < randomConeR) { + randomConePt += track.pt(); + } + } + } + registry.fill(HIST("h3_mcp_centrality_deltapT_RandomCornPhi_localrhovsphi"), collision.centrality(), randomConePt - o2::constants::math::PI * randomConeR * randomConeR * rholocalRC, rcPhiPsi2, weight); + + // removing the leading jet from the random cone + if (jets.size() > 0) { // if there are no jets in the acceptance (from the jetfinder cuts) then there can be no leading jet + float dPhiLeadingJet = RecoDecay::constrainAngle(jets.iteratorAt(0).phi() - randomConePhi, static_cast(-o2::constants::math::PI)); + float dEtaLeadingJet = jets.iteratorAt(0).eta() - randomConeEta; + + bool jetWasInCone = false; + while ((randomConeLeadJetDeltaR <= 0 && (std::sqrt(dEtaLeadingJet * dEtaLeadingJet + dPhiLeadingJet * dPhiLeadingJet) < jets.iteratorAt(0).r() / 100.0 + randomConeR)) || (randomConeLeadJetDeltaR > 0 && (std::sqrt(dEtaLeadingJet * dEtaLeadingJet + dPhiLeadingJet * dPhiLeadingJet) < randomConeLeadJetDeltaR))) { + jetWasInCone = true; + randomConeEta = randomNumber.Uniform(trackEtaMin + randomConeR, trackEtaMax - randomConeR); + randomConePhi = randomNumber.Uniform(0.0, o2::constants::math::TwoPI); + dPhiLeadingJet = RecoDecay::constrainAngle(jets.iteratorAt(0).phi() - randomConePhi, static_cast(-o2::constants::math::PI)); + dEtaLeadingJet = jets.iteratorAt(0).eta() - randomConeEta; + } + if (jetWasInCone) { + randomConePt = 0.0; + for (auto const& track : tracks) { + if (jetderiveddatautilities::selectTrack(track, trackSelection) && (std::fabs(track.eta() - leadingJetEta) > randomConeR)) { // if track selection is uniformTrack, dcaXY and dcaZ cuts need to be added as they aren't in the selection so that they can be studied here + float dPhi = RecoDecay::constrainAngle(track.phi() - randomConePhi, static_cast(-o2::constants::math::PI)); + float dEta = track.eta() - randomConeEta; + if (std::sqrt(dEta * dEta + dPhi * dPhi) < randomConeR) { + randomConePt += track.pt(); + } + } + } + } + } + registry.fill(HIST("h3_mcp_centrality_deltapT_RandomCornPhi_localrhovsphiwithoutleadingjet"), collision.centrality(), randomConePt - o2::constants::math::PI * randomConeR * randomConeR * rholocalRC, rcPhiPsi2, weight); + registry.fill(HIST("h3_mcp_centrality_deltapT_RandomCornPhi_rhorandomconewithoutleadingjet"), collision.centrality(), randomConePt - o2::constants::math::PI * randomConeR * randomConeR * collision.rho(), rcPhiPsi2, weight); + } else if (nmode == cfgNmodB) { continue; } - registry.fill(HIST("h2_centrality_track_pt"), collision.centrality(), track.pt(), weight); - registry.fill(HIST("h2_centrality_track_eta"), collision.centrality(), track.eta(), weight); - registry.fill(HIST("h2_centrality_track_phi"), collision.centrality(), track.phi(), weight); - registry.fill(HIST("h2_centrality_track_energy"), collision.centrality(), track.energy(), weight); - registry.fill(HIST("h2_track_pt_track_sigma1overpt"), track.pt(), track.sigma1Pt(), weight); - registry.fill(HIST("h2_track_pt_track_sigmapt"), track.pt(), track.sigma1Pt() * track.pt(), weight); - registry.fill(HIST("h2_track_pt_high_track_sigma1overpt"), track.pt(), track.sigma1Pt(), weight); - registry.fill(HIST("h2_track_pt_high_track_sigmapt"), track.pt(), track.sigma1Pt() * track.pt(), weight); } } - void fillLeadingJetQA(double leadingJetPt, double leadingJetPhi, double leadingJetEta) + template + void fillJetAreaSubHistograms(TJets const& jet, float centrality, float rho, float weight = 1.0) { - registry.fill(HIST("leadJetPt"), leadingJetPt); - registry.fill(HIST("leadJetPhi"), leadingJetPhi); - registry.fill(HIST("leadJetEta"), leadingJetEta); + float pTHat = 10. / (std::pow(weight, 1.0 / pTHatExponent)); + if (jet.pt() > pTHatMaxMCD * pTHat || pTHat < pTHatAbsoluteMin) { + return; + } + double jetcorrpt = jet.pt() - (rho * jet.area()); + if (jet.r() == round(selectedJetsRadius * 100.0f)) { + // fill jet histograms after area-based subtraction + registry.fill(HIST("h2_centrality_jet_pt_rhoareasubtracted"), centrality, jetcorrpt, weight); + registry.fill(HIST("h3_jet_pt_jet_eta_jet_phi_rhoareasubtracted"), jetcorrpt, jet.eta(), jet.phi(), weight); + if (jetcorrpt > 0) { + registry.fill(HIST("h2_centrality_jet_eta_rhoareasubtracted"), centrality, jet.eta(), weight); + registry.fill(HIST("h2_centrality_jet_phi_rhoareasubtracted"), centrality, jet.phi(), weight); + registry.fill(HIST("h2_jet_pt_jet_area_rhoareasubtracted"), jetcorrpt, jet.area(), weight); + } + } + + for (const auto& constituent : jet.template tracks_as()) { + registry.fill(HIST("h2_jet_pt_track_pt_rhoareasubtracted"), jetcorrpt, constituent.pt(), weight); + } } - double chiSquareCDF(int nDF, double x) + template + void fillMCPAreaSubHistograms(TJets const& jet, float rho = 0.0, float weight = 1.0) { - return TMath::Gamma(nDF / 2., x / 2.); + float pTHat = 10. / (std::pow(weight, 1.0 / pTHatExponent)); + if (jet.pt() > pTHatMaxMCP * pTHat || pTHat < pTHatAbsoluteMin) { + return; + } + if (jet.r() == round(selectedJetsRadius * 100.0f)) { + // fill mcp jet histograms + double jetcorrpt = jet.pt() - (rho * jet.area()); + registry.fill(HIST("h3_jet_pt_jet_eta_jet_phi_part_rhoareasubtracted"), jetcorrpt, jet.eta(), jet.phi(), weight); + if (jetcorrpt > 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"), jetcorrpt, jet.area(), weight); + } + } + } + + template + void fillTrackHistograms(TTracks const& track, float weight = 1.0) + { + registry.fill(HIST("h_track_pt"), track.pt(), weight); + registry.fill(HIST("h2_track_eta_track_phi"), track.eta(), track.phi(), weight); } + //=======================================[ process area ]=============================================// void processInOutJetV2(soa::Filtered>::iterator const& collision, soa::Join const& jets, aod::JetTracks const&) @@ -430,18 +798,18 @@ struct JetChargedV2 { } //=====================< evt pln [n=2->\Psi_2, n=3->\Psi_3] >=====================// histosQA.fill(HIST("histCent"), collision.cent()); + + //=====================< evt pln [n=2->\Psi_2, n=3->\Psi_3] >=====================// + int cfgNmodA = 2; + int cfgNmodB = 3; for (uint i = 0; i < cfgnMods->size(); i++) { int nmode = cfgnMods->at(i); int detInd = detId * 4 + cfgnTotalSystem * 4 * (nmode - 2); int refAInd = refAId * 4 + cfgnTotalSystem * 4 * (nmode - 2); int refBInd = refBId * 4 + cfgnTotalSystem * 4 * (nmode - 2); - int cfgNmodA = 2; - int cfgNmodB = 3; - int evtPlnAngleA = 7; - int evtPlnAngleB = 3; - int evtPlnAngleC = 5; + if (nmode == cfgNmodA) { - if (collision.qvecAmp()[detId] > 1e-8 || collision.qvecAmp()[refAId] < 1e-8 || collision.qvecAmp()[refBId] < 1e-8) { + if (collision.qvecAmp()[detId] > collQvecAmpDetId || collision.qvecAmp()[refAId] < collQvecAmpDetId || collision.qvecAmp()[refBId] < collQvecAmpDetId) { histosQA.fill(HIST("histQvecUncorV2"), collision.qvecRe()[detInd], collision.qvecIm()[detInd], collision.cent()); histosQA.fill(HIST("histQvecRectrV2"), collision.qvecRe()[detInd + 1], collision.qvecIm()[detInd + 1], collision.cent()); histosQA.fill(HIST("histQvecTwistV2"), collision.qvecRe()[detInd + 2], collision.qvecIm()[detInd + 2], collision.cent()); @@ -471,10 +839,18 @@ struct JetChargedV2 { histosQA.fill(HIST("histEvtPlRes_SigRefBV3"), helperEP.GetResolution(helperEP.GetEventPlane(collision.qvecRe()[detInd + 3], collision.qvecIm()[detInd + 3], nmode), helperEP.GetEventPlane(collision.qvecRe()[refBInd + 3], collision.qvecIm()[refBInd + 3], nmode), nmode), collision.cent()); histosQA.fill(HIST("histEvtPlRes_RefARefBV3"), helperEP.GetResolution(helperEP.GetEventPlane(collision.qvecRe()[refAInd + 3], collision.qvecIm()[refAInd + 3], nmode), helperEP.GetEventPlane(collision.qvecRe()[refBInd + 3], collision.qvecIm()[refBInd + 3], nmode), nmode), collision.cent()); } + } + + int evtPlnAngleA = 7; + int evtPlnAngleB = 3; + int evtPlnAngleC = 5; + for (uint i = 0; i < cfgnMods->size(); i++) { + int nmode = cfgnMods->at(i); + int detInd = detId * 4 + cfgnTotalSystem * 4 * (nmode - 2); if (nmode == cfgNmodA) { double phiMinusPsi2; - if (collision.qvecAmp()[detId] < 1e-8) { + if (collision.qvecAmp()[detId] < collQvecAmpDetId) { continue; } float ep2 = helperEP.GetEventPlane(collision.qvecRe()[detInd], collision.qvecIm()[detInd], nmode); @@ -489,7 +865,6 @@ struct JetChargedV2 { continue; } registry.fill(HIST("h_jet_pt_rhoareasubtracted"), jet.pt() - (collision.rho() * jet.area()), 1.0); - registry.fill(HIST("h2_centrality_jet_pt_rhoareasubtracted"), collision.centrality(), jet.pt() - (collision.rho() * jet.area()), 1.0); phiMinusPsi2 = jet.phi() - ep2; if ((phiMinusPsi2 < o2::constants::math::PIQuarter) || (phiMinusPsi2 >= evtPlnAngleA * o2::constants::math::PIQuarter) || (phiMinusPsi2 >= evtPlnAngleB * o2::constants::math::PIQuarter && phiMinusPsi2 < evtPlnAngleC * o2::constants::math::PIQuarter)) { @@ -526,7 +901,123 @@ struct JetChargedV2 { } } } - PROCESS_SWITCH(JetChargedV2, processInOutJetV2, "Jet V2 in and out of plane", true); + PROCESS_SWITCH(JetChargedV2, processInOutJetV2, "Jet V2 in and out of plane", false); + + void processInOutJetV2MCD(soa::Filtered>::iterator const& collision, + soa::Join const& jets, + aod::JetTracks const&) + { + if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { + return; + } + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits)) { + return; + } + //=====================< evt pln [n=2->\Psi_2, n=3->\Psi_3] >=====================// + histosQA.fill(HIST("histCent"), collision.cent()); + //=====================< evt pln [n=2->\Psi_2, n=3->\Psi_3] >=====================// + int cfgNmodA = 2; + int cfgNmodB = 3; + for (uint i = 0; i < cfgnMods->size(); i++) { + int nmode = cfgnMods->at(i); + int detInd = detId * 4 + cfgnTotalSystem * 4 * (nmode - 2); + int refAInd = refAId * 4 + cfgnTotalSystem * 4 * (nmode - 2); + int refBInd = refBId * 4 + cfgnTotalSystem * 4 * (nmode - 2); + + if (nmode == cfgNmodA) { + if (collision.qvecAmp()[detId] > collQvecAmpDetId || collision.qvecAmp()[refAId] < collQvecAmpDetId || collision.qvecAmp()[refBId] < collQvecAmpDetId) { + histosQA.fill(HIST("histQvecUncorV2"), collision.qvecRe()[detInd], collision.qvecIm()[detInd], collision.cent()); + histosQA.fill(HIST("histQvecRectrV2"), collision.qvecRe()[detInd + 1], collision.qvecIm()[detInd + 1], collision.cent()); + histosQA.fill(HIST("histQvecTwistV2"), collision.qvecRe()[detInd + 2], collision.qvecIm()[detInd + 2], collision.cent()); + histosQA.fill(HIST("histQvecFinalV2"), collision.qvecRe()[detInd + 3], collision.qvecIm()[detInd + 3], collision.cent()); + + histosQA.fill(HIST("histEvtPlUncorV2"), helperEP.GetEventPlane(collision.qvecRe()[detInd], collision.qvecIm()[detInd], nmode), collision.cent()); + histosQA.fill(HIST("histEvtPlRectrV2"), helperEP.GetEventPlane(collision.qvecRe()[detInd + 1], collision.qvecIm()[detInd + 1], nmode), collision.cent()); + histosQA.fill(HIST("histEvtPlTwistV2"), helperEP.GetEventPlane(collision.qvecRe()[detInd + 2], collision.qvecIm()[detInd + 2], nmode), collision.cent()); + histosQA.fill(HIST("histEvtPlFinalV2"), helperEP.GetEventPlane(collision.qvecRe()[detInd + 3], collision.qvecIm()[detInd + 3], nmode), collision.cent()); + + histosQA.fill(HIST("histEvtPlRes_SigRefAV2"), helperEP.GetResolution(helperEP.GetEventPlane(collision.qvecRe()[detInd + 3], collision.qvecIm()[detInd + 3], nmode), helperEP.GetEventPlane(collision.qvecRe()[refAInd + 3], collision.qvecIm()[refAInd + 3], nmode), nmode), collision.cent()); + histosQA.fill(HIST("histEvtPlRes_SigRefBV2"), helperEP.GetResolution(helperEP.GetEventPlane(collision.qvecRe()[detInd + 3], collision.qvecIm()[detInd + 3], nmode), helperEP.GetEventPlane(collision.qvecRe()[refBInd + 3], collision.qvecIm()[refBInd + 3], nmode), nmode), collision.cent()); + histosQA.fill(HIST("histEvtPlRes_RefARefBV2"), helperEP.GetResolution(helperEP.GetEventPlane(collision.qvecRe()[refAInd + 3], collision.qvecIm()[refAInd + 3], nmode), helperEP.GetEventPlane(collision.qvecRe()[refBInd + 3], collision.qvecIm()[refBInd + 3], nmode), nmode), collision.cent()); + } + } else if (nmode == cfgNmodB) { + histosQA.fill(HIST("histQvecUncorV3"), collision.qvecRe()[detInd], collision.qvecIm()[detInd], collision.cent()); + histosQA.fill(HIST("histQvecRectrV3"), collision.qvecRe()[detInd + 1], collision.qvecIm()[detInd + 1], collision.cent()); + histosQA.fill(HIST("histQvecTwistV3"), collision.qvecRe()[detInd + 2], collision.qvecIm()[detInd + 2], collision.cent()); + histosQA.fill(HIST("histQvecFinalV3"), collision.qvecRe()[detInd + 3], collision.qvecIm()[detInd + 3], collision.cent()); + + histosQA.fill(HIST("histEvtPlUncorV3"), helperEP.GetEventPlane(collision.qvecRe()[detInd], collision.qvecIm()[detInd], nmode), collision.cent()); + histosQA.fill(HIST("histEvtPlRectrV3"), helperEP.GetEventPlane(collision.qvecRe()[detInd + 1], collision.qvecIm()[detInd + 1], nmode), collision.cent()); + histosQA.fill(HIST("histEvtPlTwistV3"), helperEP.GetEventPlane(collision.qvecRe()[detInd + 2], collision.qvecIm()[detInd + 2], nmode), collision.cent()); + histosQA.fill(HIST("histEvtPlFinalV3"), helperEP.GetEventPlane(collision.qvecRe()[detInd + 3], collision.qvecIm()[detInd + 3], nmode), collision.cent()); + + histosQA.fill(HIST("histEvtPlRes_SigRefAV3"), helperEP.GetResolution(helperEP.GetEventPlane(collision.qvecRe()[detInd + 3], collision.qvecIm()[detInd + 3], nmode), helperEP.GetEventPlane(collision.qvecRe()[refAInd + 3], collision.qvecIm()[refAInd + 3], nmode), nmode), collision.cent()); + histosQA.fill(HIST("histEvtPlRes_SigRefBV3"), helperEP.GetResolution(helperEP.GetEventPlane(collision.qvecRe()[detInd + 3], collision.qvecIm()[detInd + 3], nmode), helperEP.GetEventPlane(collision.qvecRe()[refBInd + 3], collision.qvecIm()[refBInd + 3], nmode), nmode), collision.cent()); + histosQA.fill(HIST("histEvtPlRes_RefARefBV3"), helperEP.GetResolution(helperEP.GetEventPlane(collision.qvecRe()[refAInd + 3], collision.qvecIm()[refAInd + 3], nmode), helperEP.GetEventPlane(collision.qvecRe()[refBInd + 3], collision.qvecIm()[refBInd + 3], nmode), nmode), collision.cent()); + } + } + + int evtPlnAngleA = 7; + int evtPlnAngleB = 3; + int evtPlnAngleC = 5; + for (uint i = 0; i < cfgnMods->size(); i++) { + int nmode = cfgnMods->at(i); + int detInd = detId * 4 + cfgnTotalSystem * 4 * (nmode - 2); + + if (nmode == cfgNmodA) { + double phiMinusPsi2; + if (collision.qvecAmp()[detId] < collQvecAmpDetId) { + continue; + } + float ep2 = helperEP.GetEventPlane(collision.qvecRe()[detInd], collision.qvecIm()[detInd], nmode); + for (auto const& jet : jets) { + if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { + continue; + } + if (!isAcceptedJet(jet)) { + continue; + } + if (jet.r() != round(selectedJetsRadius * 100.0f)) { + continue; + } + registry.fill(HIST("h_jet_pt_rhoareasubtracted"), jet.pt() - (collision.rho() * jet.area()), 1.0); + + phiMinusPsi2 = jet.phi() - ep2; + if ((phiMinusPsi2 < o2::constants::math::PIQuarter) || (phiMinusPsi2 >= evtPlnAngleA * o2::constants::math::PIQuarter) || (phiMinusPsi2 >= evtPlnAngleB * o2::constants::math::PIQuarter && phiMinusPsi2 < evtPlnAngleC * o2::constants::math::PIQuarter)) { + registry.fill(HIST("h_jet_pt_in_plane_v2"), jet.pt() - (collision.rho() * jet.area()), 1.0); + registry.fill(HIST("h2_centrality_jet_pt_in_plane_v2"), collision.centrality(), jet.pt() - (collision.rho() * jet.area()), 1.0); + } else { + registry.fill(HIST("h_jet_pt_out_of_plane_v2"), jet.pt() - (collision.rho() * jet.area()), 1.0); + registry.fill(HIST("h2_centrality_jet_pt_out_of_plane_v2"), collision.centrality(), jet.pt() - (collision.rho() * jet.area()), 1.0); + } + } + } else if (nmode == cfgNmodB) { + double phiMinusPsi3; + float ep3 = helperEP.GetEventPlane(collision.qvecRe()[detInd], collision.qvecIm()[detInd], nmode); + for (auto const& jet : jets) { + if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { + continue; + } + if (!isAcceptedJet(jet)) { + continue; + } + if (jet.r() != round(selectedJetsRadius * 100.0f)) { + continue; + } + phiMinusPsi3 = jet.phi() - ep3; + + if ((phiMinusPsi3 < o2::constants::math::PIQuarter) || (phiMinusPsi3 >= evtPlnAngleA * o2::constants::math::PIQuarter) || (phiMinusPsi3 >= evtPlnAngleB * o2::constants::math::PIQuarter && phiMinusPsi3 < evtPlnAngleC * o2::constants::math::PIQuarter)) { + registry.fill(HIST("h_jet_pt_in_plane_v3"), jet.pt() - (collision.rho() * jet.area()), 1.0); + registry.fill(HIST("h2_centrality_jet_pt_in_plane_v3"), collision.centrality(), jet.pt() - (collision.rho() * jet.area()), 1.0); + } else { + registry.fill(HIST("h_jet_pt_out_of_plane_v3"), jet.pt() - (collision.rho() * jet.area()), 1.0); + registry.fill(HIST("h2_centrality_jet_pt_out_of_plane_v3"), collision.centrality(), jet.pt() - (collision.rho() * jet.area()), 1.0); + } + } + } + } + } + PROCESS_SWITCH(JetChargedV2, processInOutJetV2MCD, "Jet V2 in and out of plane MCD", false); void processSigmaPt(soa::Filtered>::iterator const& collision, soa::Join const& jets, @@ -541,60 +1032,21 @@ struct JetChargedV2 { return; } registry.fill(HIST("h_collisions"), 2.5); + double leadingJetPt = -1; double leadingJetPhi = -1; double leadingJetEta = -1; - for (const auto& jet : jets) { - if (jet.pt() > leadingJetPt) { - leadingJetPt = jet.pt(); - leadingJetEta = jet.eta(); - leadingJetPhi = jet.phi(); - } - } - fillLeadingJetQA(leadingJetPt, leadingJetPhi, leadingJetEta); + fillLeadingJetQA(jets, leadingJetPt, leadingJetPhi, leadingJetEta); int nTrk = 0; - if (jets.size() > 0) { - for (auto const& track : tracks) { - if (jetderiveddatautilities::selectTrack(track, trackSelection) && (std::fabs(track.eta() - leadingJetEta) > jetRadius) && track.pt() >= localRhoFitPtMin && track.pt() <= localRhoFitPtMax) { - registry.fill(HIST("h_accept_Track"), 2.5); - nTrk += 1; - } - } - registry.fill(HIST("h_evtnum_NTrk"), evtnum, nTrk); - } - + getNtrk(tracks, jets, nTrk, evtnum, leadingJetEta); if (nTrk <= 0) { - return; - } - - hPtsumSumptFit = new TH1F("h_ptsum_sumpt_fit", "h_ptsum_sumpt fit use", TMath::CeilNint(std::sqrt(nTrk)), 0., o2::constants::math::TwoPI); - - if (jets.size() > 0) { - for (auto const& trackfit : tracks) { - registry.fill(HIST("h_accept_Track"), 0.5); - if (jetderiveddatautilities::selectTrack(trackfit, trackSelection) && (std::fabs(trackfit.eta() - leadingJetEta) > jetRadius) && trackfit.pt() >= localRhoFitPtMin && trackfit.pt() <= localRhoFitPtMax) { - registry.fill(HIST("h_accept_Track_Fit"), 0.5); - fitTrack += 1; - } - } - - for (auto const& track : tracks) { - registry.fill(HIST("h_accept_Track"), 1.5); - if (jetderiveddatautilities::selectTrack(track, trackSelection) && (std::fabs(track.eta() - leadingJetEta) > jetRadius) && track.pt() >= localRhoFitPtMin && track.pt() <= localRhoFitPtMax) { - accptTrack += 1; - registry.fill(HIST("h_accept_Track"), 2.5); - hPtsumSumptFit->Fill(track.phi(), track.pt()); - registry.fill(HIST("h2_phi_track_eta"), track.eta(), track.phi()); - registry.fill(HIST("h_ptsum_sumpt"), track.phi(), track.pt()); - registry.fill(HIST("h2_centrality_phi_w_pt"), collision.centrality(), track.phi(), track.pt()); - registry.fill(HIST("h2_evtnum_phi_w_pt"), evtnum, track.phi(), track.pt()); - registry.fill(HIST("Thn_evtnum_phi_centrality"), evtnum, track.phi(), collision.centrality()); - registry.fill(HIST("h_accept_Track_init"), accptTrack); - registry.fill(HIST("h_accept_Track_Fit"), 1.5); - } - } + return; } + hPtsumSumptFit = new TH1F("h_ptsum_sumpt_fit", "h_ptsum_sumpt fit use", TMath::CeilNint(std::sqrt(nTrk)), 0., o2::constants::math::TwoPI); + + fillNtrkCheck(collision, tracks, jets, hPtsumSumptFit, leadingJetEta, evtnum); + registry.fill(HIST("h_ptsum_collnum"), 0.5); double ep2 = 0.; @@ -608,17 +1060,16 @@ struct JetChargedV2 { int nmode = cfgnMods->at(i); int detInd = detId * 4 + cfgnTotalSystem * 4 * (nmode - 2); if (nmode == cfgNmodA) { - if (collision.qvecAmp()[detId] > 1e-8) { + if (collision.qvecAmp()[detId] > collQvecAmpDetId) { ep2 = helperEP.GetEventPlane(collision.qvecRe()[detInd + 3], collision.qvecIm()[detInd + 3], nmode); } } else if (nmode == cfgNmodB) { - if (collision.qvecAmp()[detId] > 1e-8) { + if (collision.qvecAmp()[detId] > collQvecAmpDetId) { ep3 = helperEP.GetEventPlane(collision.qvecRe()[detInd + 3], collision.qvecIm()[detInd + 3], nmode); } } } - TF1* fFitModulationV2v3 = 0x0; const char* fitFunctionV2v3 = "[0] * (1. + 2. * ([1] * std::cos(2. * (x - [2])) + [3] * std::cos(3. * (x - [4]))))"; fFitModulationV2v3 = new TF1("fit_kV3", fitFunctionV2v3, 0, o2::constants::math::TwoPI); //=========================< set parameter >=========================// @@ -700,6 +1151,7 @@ struct JetChargedV2 { int evtMidAreaMax = 50; if (evtcent >= evtCentAreaMin && evtcent <= evtCentAreaMax) { registry.fill(HIST("h2_PChi2_CombinFitA"), cDF, chiSqr / (static_cast(nDF))); + } else if (evtcent >= evtMidAreaMin && evtcent <= evtMidAreaMax) { registry.fill(HIST("h2_PChi2_CombinFitB"), cDF, chiSqr / (static_cast(nDF))); } @@ -730,7 +1182,7 @@ struct JetChargedV2 { registry.fill(HIST("h_jet_pt_rholocal"), jet.pt() - (rholocal * jet.area()), 1.0); double phiMinusPsi2; - if (collision.qvecAmp()[detId] < 1e-8) { + if (collision.qvecAmp()[detId] < collQvecAmpDetId) { continue; } phiMinusPsi2 = jet.phi() - ep2; @@ -747,7 +1199,7 @@ struct JetChargedV2 { } } else if (nmode == cfgNmodB) { double phiMinusPsi3; - if (collision.qvecAmp()[detId] < 1e-8) { + if (collision.qvecAmp()[detId] < collQvecAmpDetId) { continue; } ep3 = helperEP.GetEventPlane(collision.qvecRe()[detInd], collision.qvecIm()[detInd], nmode); @@ -821,35 +1273,229 @@ struct JetChargedV2 { } } delete hPtsumSumptFit; + delete fFitModulationV2v3; evtnum += 1; } - PROCESS_SWITCH(JetChargedV2, processSigmaPt, "Sigma pT and bkg as fcn of phi", true); + PROCESS_SWITCH(JetChargedV2, processSigmaPt, "Sigma pT and bkg as fcn of phi", false); - void processRandomConeDataV2(soa::Filtered>::iterator const& collision, - soa::Join const& jets, - soa::Filtered const& tracks) + void processSigmaPtMCD(soa::Filtered>::iterator const& collision, + soa::Join const& jets, + aod::JetTracks const& tracks) { + registry.fill(HIST("h_collisions"), 0.5); + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents)) { + return; + } + registry.fill(HIST("h_collisions"), 1.5); if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { return; } - if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits)) { + registry.fill(HIST("h_collisions"), 2.5); + for (auto const& jet : jets) { + if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { + continue; + } + if (!isAcceptedJet(jet)) { + continue; + } + fillJetAreaSubHistograms(jet, collision.centrality(), collision.rho()); + } + + double leadingJetPt = -1; + double leadingJetPhi = -1; + double leadingJetEta = -1; + fillLeadingJetQA(jets, leadingJetPt, leadingJetPhi, leadingJetEta); + + int nTrk = 0; + getNtrk(tracks, jets, nTrk, evtnum, leadingJetEta); + if (nTrk <= 0) { + return; + } + hPtsumSumptFit = new TH1F("h_ptsum_sumpt_fit", "h_ptsum_sumpt fit use", TMath::CeilNint(std::sqrt(nTrk)), 0., o2::constants::math::TwoPI); + + fillNtrkCheck(collision, tracks, jets, hPtsumSumptFit, leadingJetEta, evtnum); + + registry.fill(HIST("h_ptsum_collnum"), 0.5); + + double ep2 = 0.; + double ep3 = 0.; + int cfgNmodA = 2; + int cfgNmodB = 3; + int evtPlnAngleA = 7; + int evtPlnAngleB = 3; + int evtPlnAngleC = 5; + for (uint i = 0; i < cfgnMods->size(); i++) { + int nmode = cfgnMods->at(i); + int detInd = detId * 4 + cfgnTotalSystem * 4 * (nmode - 2); + if (nmode == cfgNmodA) { + if (collision.qvecAmp()[detId] > collQvecAmpDetId) { + ep2 = helperEP.GetEventPlane(collision.qvecRe()[detInd + 3], collision.qvecIm()[detInd + 3], nmode); + } + } else if (nmode == cfgNmodB) { + if (collision.qvecAmp()[detId] > collQvecAmpDetId) { + ep3 = helperEP.GetEventPlane(collision.qvecRe()[detInd + 3], collision.qvecIm()[detInd + 3], nmode); + } + } + } + + const char* fitFunctionV2v3 = "[0] * (1. + 2. * ([1] * std::cos(2. * (x - [2])) + [3] * std::cos(3. * (x - [4]))))"; + fFitModulationV2v3 = new TF1("fit_kV3", fitFunctionV2v3, 0, o2::constants::math::TwoPI); + //=========================< set parameter >=========================// + fFitModulationV2v3->SetParameter(0, 1.); + fFitModulationV2v3->SetParameter(1, 0.01); + fFitModulationV2v3->SetParameter(3, 0.01); + + double ep2fix = 0.; + double ep3fix = 0.; + + if (ep2 < 0) { + ep2fix = RecoDecay::constrainAngle(ep2); + fFitModulationV2v3->FixParameter(2, ep2fix); + } else { + fFitModulationV2v3->FixParameter(2, ep2); + } + if (ep3 < 0) { + ep3fix = RecoDecay::constrainAngle(ep3); + fFitModulationV2v3->FixParameter(4, ep3fix); + } else { + fFitModulationV2v3->FixParameter(4, ep3); + } + + hPtsumSumptFit->Fit(fFitModulationV2v3, "Q", "ep", 0, o2::constants::math::TwoPI); + + double temppara[5]; + temppara[0] = fFitModulationV2v3->GetParameter(0); + temppara[1] = fFitModulationV2v3->GetParameter(1); + temppara[2] = fFitModulationV2v3->GetParameter(2); + temppara[3] = fFitModulationV2v3->GetParameter(3); + temppara[4] = fFitModulationV2v3->GetParameter(4); + int paraNum = 5; + for (int i = 1; i <= paraNum; i++) { + registry.fill(HIST("h2_evt_fitpara"), evtnum, i - 0.5, temppara[i - 1]); + } + + registry.fill(HIST("h_fitparaRho_evtnum"), evtnum, temppara[0]); + registry.fill(HIST("h_fitparav2obs_evtnum"), evtnum, temppara[1]); + registry.fill(HIST("h_fitparaPsi2_evtnum"), evtnum, temppara[2]); + registry.fill(HIST("h_fitparav3obs_evtnum"), evtnum, temppara[3]); + registry.fill(HIST("h_fitparaPsi3_evtnum"), evtnum, temppara[4]); + + registry.fill(HIST("h_v2obs_centrality"), collision.centrality(), temppara[1]); + registry.fill(HIST("h_v3obs_centrality"), collision.centrality(), temppara[3]); + registry.fill(HIST("h_evtnum_centrlity"), evtnum, collision.centrality()); + + if (temppara[0] == 0) { return; } + registry.fill(HIST("h2_fitParaZero_cent"), collision.centrality(), temppara[0], 1.0); + + int nDF = 1; + int numOfFreePara = 2; + nDF = static_cast(fFitModulationV2v3->GetXaxis()->GetNbins()) - numOfFreePara; + if (nDF == 0 || static_cast(nDF) <= 0.) + return; + double chi2 = 0.; + for (int i = 0; i < hPtsumSumptFit->GetXaxis()->GetNbins(); i++) { + if (hPtsumSumptFit->GetBinContent(i + 1) <= 0.) + continue; + chi2 += std::pow((hPtsumSumptFit->GetBinContent(i + 1) - fFitModulationV2v3->Eval(hPtsumSumptFit->GetXaxis()->GetBinCenter(1 + i))), 2) / hPtsumSumptFit->GetBinContent(i + 1); + } + + double chiSqr = 999.; + double cDF = 1.; + + chiSqr = chi2; + cDF = 1. - chiSquareCDF(nDF, chiSqr); + + registry.fill(HIST("h_PvalueCDF_CombinFit"), cDF); + registry.fill(HIST("h2_PvalueCDFCent_CombinFit"), collision.centrality(), cDF); + registry.fill(HIST("h2_Chi2Cent_CombinFit"), collision.centrality(), chiSqr / (static_cast(nDF))); + registry.fill(HIST("h2_PChi2_CombinFit"), cDF, chiSqr / (static_cast(nDF))); + registry.fill(HIST("Thn_PChi2_CombinFitCent"), collision.centrality(), cDF, chiSqr / (static_cast(nDF))); + double evtcent = collision.centrality(); + int evtCentAreaMin = 0; + int evtCentAreaMax = 5; + int evtMidAreaMin = 30; + int evtMidAreaMax = 50; + if (evtcent >= evtCentAreaMin && evtcent <= evtCentAreaMax) { + registry.fill(HIST("h2_PChi2_CombinFitA"), cDF, chiSqr / (static_cast(nDF))); + + } else if (evtcent >= evtMidAreaMin && evtcent <= evtMidAreaMax) { + registry.fill(HIST("h2_PChi2_CombinFitB"), cDF, chiSqr / (static_cast(nDF))); + } + for (uint i = 0; i < cfgnMods->size(); i++) { + int nmode = cfgnMods->at(i); + int detInd = detId * 4 + cfgnTotalSystem * 4 * (nmode - 2); + + for (auto const& jet : jets) { + if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { + continue; + } + if (!isAcceptedJet(jet)) { + continue; + } + if (jet.r() != round(selectedJetsRadius * 100.0f)) { + continue; + } + + double integralValue = fFitModulationV2v3->Integral(jet.phi() - jetRadius, jet.phi() + jetRadius); + double rholocal = collision.rho() / (2 * jetRadius * temppara[0]) * integralValue; + registry.fill(HIST("h2_phi_rhophi"), jet.phi() - ep2, fFitModulationV2v3->Eval(jet.phi()), 1.0); + registry.fill(HIST("h3_centrality_rhovsphi_phi"), collision.centrality(), fFitModulationV2v3->Eval(jet.phi()), jet.phi() - ep2); + + registry.fill(HIST("h2_phi_rholocal_cent"), collision.centrality(), rholocal, 1.0); + registry.fill(HIST("h3_centrality_localrho_phi"), collision.centrality(), rholocal, jet.phi() - ep2); + + if (nmode == cfgNmodA) { + registry.fill(HIST("h_jet_pt_rholocal"), jet.pt() - (rholocal * jet.area()), 1.0); + + double phiMinusPsi2; + if (collision.qvecAmp()[detId] < collQvecAmpDetId) { + continue; + } + phiMinusPsi2 = jet.phi() - ep2; + + registry.fill(HIST("h2_phi_rholocal"), jet.phi() - ep2, rholocal, 1.0); + registry.fill(HIST("h_jet_pt_inclusive_v2_rho"), jet.pt() - (rholocal * jet.area()), 1.0); + + if ((phiMinusPsi2 < o2::constants::math::PIQuarter) || (phiMinusPsi2 >= evtPlnAngleA * o2::constants::math::PIQuarter) || (phiMinusPsi2 >= evtPlnAngleB * o2::constants::math::PIQuarter && phiMinusPsi2 < evtPlnAngleC * o2::constants::math::PIQuarter)) { + registry.fill(HIST("h_jet_pt_in_plane_v2_rho"), jet.pt() - (rholocal * jet.area()), 1.0); + registry.fill(HIST("h2_centrality_jet_pt_in_plane_v2_rho"), collision.centrality(), jet.pt() - (rholocal * jet.area()), 1.0); + } else { + registry.fill(HIST("h_jet_pt_out_of_plane_v2_rho"), jet.pt() - (rholocal * jet.area()), 1.0); + registry.fill(HIST("h2_centrality_jet_pt_out_of_plane_v2_rho"), collision.centrality(), jet.pt() - (rholocal * jet.area()), 1.0); + } + } else if (nmode == cfgNmodB) { + double phiMinusPsi3; + if (collision.qvecAmp()[detId] < collQvecAmpDetId) { + continue; + } + ep3 = helperEP.GetEventPlane(collision.qvecRe()[detInd], collision.qvecIm()[detInd], nmode); + phiMinusPsi3 = jet.phi() - ep3; + if ((phiMinusPsi3 < o2::constants::math::PIQuarter) || (phiMinusPsi3 >= evtPlnAngleA * o2::constants::math::PIQuarter) || (phiMinusPsi3 >= evtPlnAngleB * o2::constants::math::PIQuarter && phiMinusPsi3 < evtPlnAngleC * o2::constants::math::PIQuarter)) { + registry.fill(HIST("h_jet_pt_in_plane_v3_rho"), jet.pt() - (rholocal * jet.area()), 1.0); + registry.fill(HIST("h2_centrality_jet_pt_in_plane_v3_rho"), collision.centrality(), jet.pt() - (rholocal * jet.area()), 1.0); + } else { + registry.fill(HIST("h_jet_pt_out_of_plane_v3_rho"), jet.pt() - (rholocal * jet.area()), 1.0); + registry.fill(HIST("h2_centrality_jet_pt_out_of_plane_v3_rho"), collision.centrality(), jet.pt() - (rholocal * jet.area()), 1.0); + } + } + } + } + // RCpT for (uint i = 0; i < cfgnMods->size(); i++) { TRandom3 randomNumber(0); float randomConeEta = randomNumber.Uniform(trackEtaMin + randomConeR, trackEtaMax - randomConeR); float randomConePhi = randomNumber.Uniform(0.0, o2::constants::math::TwoPI); float randomConePt = 0; + double integralValueRC = fFitModulationV2v3->Integral(randomConePhi - randomConeR, randomConePhi + randomConeR); + double rholocalRC = collision.rho() / (2 * randomConeR * temppara[0]) * integralValueRC; int nmode = cfgnMods->at(i); - int detInd = detId * 4 + cfgnTotalSystem * 4 * (nmode - 2); - int cfgNmodA = 2; - int cfgNmodB = 3; if (nmode == cfgNmodA) { double rcPhiPsi2; - float evtPl2 = helperEP.GetEventPlane(collision.qvecRe()[detInd], collision.qvecIm()[detInd], nmode); - rcPhiPsi2 = randomConePhi - evtPl2; + rcPhiPsi2 = randomConePhi - ep2; for (auto const& track : tracks) { if (jetderiveddatautilities::selectTrack(track, trackSelection)) { @@ -860,13 +1506,15 @@ struct JetChargedV2 { } } } + registry.fill(HIST("h3_centrality_deltapT_RandomCornPhi_localrhovsphi"), collision.centrality(), randomConePt - o2::constants::math::PI * randomConeR * randomConeR * rholocalRC, rcPhiPsi2, 1.0); + // removing the leading jet from the random cone if (jets.size() > 0) { // if there are no jets in the acceptance (from the jetfinder cuts) then there can be no leading jet float dPhiLeadingJet = RecoDecay::constrainAngle(jets.iteratorAt(0).phi() - randomConePhi, static_cast(-o2::constants::math::PI)); float dEtaLeadingJet = jets.iteratorAt(0).eta() - randomConeEta; bool jetWasInCone = false; - while (std::sqrt(dEtaLeadingJet * dEtaLeadingJet + dPhiLeadingJet * dPhiLeadingJet) < jets.iteratorAt(0).r() / 100.0 + randomConeR) { + while ((randomConeLeadJetDeltaR <= 0 && (std::sqrt(dEtaLeadingJet * dEtaLeadingJet + dPhiLeadingJet * dPhiLeadingJet) < jets.iteratorAt(0).r() / 100.0 + randomConeR)) || (randomConeLeadJetDeltaR > 0 && (std::sqrt(dEtaLeadingJet * dEtaLeadingJet + dPhiLeadingJet * dPhiLeadingJet) < randomConeLeadJetDeltaR))) { jetWasInCone = true; randomConeEta = randomNumber.Uniform(trackEtaMin + randomConeR, trackEtaMax - randomConeR); randomConePhi = randomNumber.Uniform(0.0, o2::constants::math::TwoPI); @@ -876,7 +1524,7 @@ struct JetChargedV2 { if (jetWasInCone) { randomConePt = 0.0; for (auto const& track : tracks) { - if (jetderiveddatautilities::selectTrack(track, trackSelection)) { + if (jetderiveddatautilities::selectTrack(track, trackSelection) && (std::fabs(track.eta() - leadingJetEta) > randomConeR)) { // if track selection is uniformTrack, dcaXY and dcaZ cuts need to be added as they aren't in the selection so that they can be studied here float dPhi = RecoDecay::constrainAngle(track.phi() - randomConePhi, static_cast(-o2::constants::math::PI)); float dEta = track.eta() - randomConeEta; if (std::sqrt(dEta * dEta + dPhi * dPhi) < randomConeR) { @@ -886,30 +1534,151 @@ struct JetChargedV2 { } } } - registry.fill(HIST("h2_centrality_deltapT_RandomCornPhi_RCprocess_rhorandomconewithoutleadingjet"), randomConePt - o2::constants::math::PI * randomConeR * randomConeR * collision.rho(), rcPhiPsi2, 1.0); + registry.fill(HIST("h3_centrality_deltapT_RandomCornPhi_localrhovsphiwithoutleadingjet"), collision.centrality(), randomConePt - o2::constants::math::PI * randomConeR * randomConeR * rholocalRC, rcPhiPsi2, 1.0); + registry.fill(HIST("h3_centrality_deltapT_RandomCornPhi_rhorandomconewithoutleadingjet"), collision.centrality(), randomConePt - o2::constants::math::PI * randomConeR * randomConeR * collision.rho(), rcPhiPsi2, 1.0); } else if (nmode == cfgNmodB) { continue; } } + delete hPtsumSumptFit; + delete fFitModulationV2v3; + evtnum += 1; + } + PROCESS_SWITCH(JetChargedV2, processSigmaPtMCD, "jet spectra with rho-area subtraction for MCD", false); + + void processSigmaPtMCP(McParticleCollision::iterator const& mccollision, + soa::SmallGroups> const& collisions, + soa::Join const& jets, + aod::JetTracks const& tracks, + aod::JetParticles const&) + { + bool mcLevelIsParticleLevel = true; + int acceptSplitCollInMCP = 2; + + registry.fill(HIST("h_mcColl_counts_areasub"), 0.5); + if (std::abs(mccollision.posZ()) > vertexZCut) { + return; + } + registry.fill(HIST("h_mcColl_counts_areasub"), 1.5); + if (collisions.size() < 1) { + return; + } + registry.fill(HIST("h_mcColl_counts_areasub"), 2.5); + if (acceptSplitCollisions == 0 && collisions.size() > 1) { + return; + } + registry.fill(HIST("h_mcColl_counts_areasub"), 3.5); + + bool hasSel8Coll = false; + bool centralityIsGood = false; + bool occupancyIsGood = false; + if (acceptSplitCollisions == acceptSplitCollInMCP) { + if (jetderiveddatautilities::selectCollision(collisions.begin(), eventSelectionBits, skipMBGapEvents)) { + hasSel8Coll = true; + } + if ((centralityMin < collisions.begin().centrality()) && (collisions.begin().centrality() < centralityMax)) { + centralityIsGood = true; + } + if ((trackOccupancyInTimeRangeMin < collisions.begin().trackOccupancyInTimeRange()) && (collisions.begin().trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMax)) { + occupancyIsGood = true; + } + } else { + for (auto const& collision : collisions) { + if (jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents)) { + hasSel8Coll = true; + } + if ((centralityMin < collision.centrality()) && (collision.centrality() < centralityMax)) { + centralityIsGood = true; + } + if ((trackOccupancyInTimeRangeMin < collision.trackOccupancyInTimeRange()) && (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMax)) { + occupancyIsGood = true; + } + } + } + if (!hasSel8Coll) { + return; + } + registry.fill(HIST("h_mcColl_counts_areasub"), 4.5); + + if (!centralityIsGood) { + return; + } + registry.fill(HIST("h_mcColl_counts_areasub"), 5.5); + + if (!occupancyIsGood) { + return; + } + registry.fill(HIST("h_mcColl_counts_areasub"), 6.5); + registry.fill(HIST("h_mcColl_rho"), mccollision.rho()); + + for (auto const& jet : jets) { + if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { + continue; + } + if (!isAcceptedJet(jet, mcLevelIsParticleLevel)) { + continue; + } + fillMCPAreaSubHistograms(jet, mccollision.rho()); + } + + for (auto const& collision : collisions) { + auto collTracks = tracks.sliceBy(tracksPerJCollision, collision.globalIndex()); + + double leadingJetPt = -1; + double leadingJetPhi = -1; + double leadingJetEta = -1; + fillLeadingJetQAMCP(jets, leadingJetPt, leadingJetPhi, leadingJetEta); + + int nTrk = 0; + if (jets.size() > 0) { + for (auto const& track : collTracks) { + if (jetderiveddatautilities::selectTrack(track, trackSelection) && (std::fabs(track.eta() - leadingJetEta) > jetRadius) && track.pt() >= localRhoFitPtMin && track.pt() <= localRhoFitPtMax) { + registry.fill(HIST("h_accept_Track"), 5.5); + nTrk += 1; + } + } + registry.fill(HIST("h_mcp_evtnum_NTrk"), evtnum, nTrk); + } + if (nTrk <= 0) { + return; + } + hPtsumSumptFitMCP = new TH1F("h_ptsum_sumpt_fit", "h_ptsum_sumpt fit use", TMath::CeilNint(std::sqrt(nTrk)), 0., o2::constants::math::TwoPI); + + if (jets.size() > 0) { + for (auto const& track : collTracks) { + if (jetderiveddatautilities::selectTrack(track, trackSelection) && (std::fabs(track.eta() - leadingJetEta) > jetRadius) && track.pt() >= localRhoFitPtMin && track.pt() <= localRhoFitPtMax) { + hPtsumSumptFitMCP->Fill(track.phi(), track.pt()); + registry.fill(HIST("h2_mcp_phi_track_eta"), track.eta(), track.phi()); + registry.fill(HIST("h_mcp_ptsum_sumpt"), track.phi(), track.pt()); + } + } + } + + registry.fill(HIST("h_ptsum_collnum"), 0.5); + fitFncMCP(collision, tracks, jets, hPtsumSumptFitMCP, leadingJetEta, mcLevelIsParticleLevel); + } + + delete hPtsumSumptFitMCP; + delete fFitModulationV2v3P; + evtnum += 1; } - PROCESS_SWITCH(JetChargedV2, processRandomConeDataV2, "QA for random cone estimation of background fluctuations in data", true); + PROCESS_SWITCH(JetChargedV2, processSigmaPtMCP, "jet spectra with area-based subtraction for MC particle level", false); void processTracksQA(soa::Filtered>::iterator const& collision, soa::Filtered> const& tracks) { - registry.fill(HIST("h_collisions"), 0.5); - registry.fill(HIST("h2_centrality_collisions"), collision.centrality(), 0.5); if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits)) { return; } - registry.fill(HIST("h_collisions"), 1.5); - registry.fill(HIST("h2_centrality_collisions"), collision.centrality(), 1.5); if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { return; } - registry.fill(HIST("h_collisions"), 2.5); - registry.fill(HIST("h2_centrality_collisions"), collision.centrality(), 2.5); - fillTrackHistograms(collision, tracks); + for (auto const& track : tracks) { + if (!jetderiveddatautilities::selectTrack(track, trackSelection)) { + continue; + } + fillTrackHistograms(track); + } } PROCESS_SWITCH(JetChargedV2, processTracksQA, "QA for charged tracks", false); }; From f7dace12a5489ea4e724f6cfc0393168cf53e9bf Mon Sep 17 00:00:00 2001 From: Rashi gupta <167059733+rashigupt@users.noreply.github.com> Date: Fri, 13 Jun 2025 18:58:37 +0530 Subject: [PATCH 064/871] [PWGHF] Add configurable for mixed event pair in correlatorHfeHadrons (#11591) Co-authored-by: Rashi Gupta --- PWGHF/HFC/TableProducer/correlatorHfeHadrons.cxx | 5 +++-- .../TableProducer/electronSelectionWithTpcEmcal.cxx | 10 ++++++++-- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/PWGHF/HFC/TableProducer/correlatorHfeHadrons.cxx b/PWGHF/HFC/TableProducer/correlatorHfeHadrons.cxx index 25b5d476269..277111d8817 100644 --- a/PWGHF/HFC/TableProducer/correlatorHfeHadrons.cxx +++ b/PWGHF/HFC/TableProducer/correlatorHfeHadrons.cxx @@ -54,6 +54,7 @@ struct HfCorrelatorHfeHadrons { Configurable zPvPosMax{"zPvPosMax", 10., "Maximum z of the primary vertex (cm)"}; Configurable isRun3{"isRun3", true, "Data is from Run3 or Run2"}; + Configurable numberEventsMixed{"numberEventsMixed", 5, "number of events mixed in ME process"}; // Associated Hadron selection Configurable ptTrackMin{"ptTrackMin", 0.1f, "Transverse momentum range for associated hadron tracks"}; Configurable etaTrackMax{"etaTrackMax", 0.8f, "Eta range for associated hadron tracks"}; @@ -377,7 +378,7 @@ struct HfCorrelatorHfeHadrons { void processDataMixedEvent(TableCollisions const& collision, aod::HfCorrSelEl const& electron, TableTracks const& tracks) { auto tracksTuple = std::make_tuple(electron, tracks); - Pair pair{corrBinning, 5, -1, collision, tracksTuple, &cache}; + Pair pair{corrBinning, numberEventsMixed, -1, collision, tracksTuple, &cache}; // loop over the rows of the new table for (const auto& [c1, tracks1, c2, tracks2] : pair) { @@ -392,7 +393,7 @@ struct HfCorrelatorHfeHadrons { void processMcRecMixedEvent(McTableCollisions const& mccollision, aod::HfCorrSelEl const& electron, McTableTracks const& mcTracks) { auto tracksTuple = std::make_tuple(electron, mcTracks); - Pair pairMcRec{corrBinning, 5, -1, mccollision, tracksTuple, &cache}; + Pair pairMcRec{corrBinning, numberEventsMixed, -1, mccollision, tracksTuple, &cache}; // loop over the rows of the new table for (const auto& [c1, tracks1, c2, tracks2] : pairMcRec) { diff --git a/PWGHF/HFL/TableProducer/electronSelectionWithTpcEmcal.cxx b/PWGHF/HFL/TableProducer/electronSelectionWithTpcEmcal.cxx index ae8be97b6b9..24ebae0ea8a 100644 --- a/PWGHF/HFL/TableProducer/electronSelectionWithTpcEmcal.cxx +++ b/PWGHF/HFL/TableProducer/electronSelectionWithTpcEmcal.cxx @@ -202,8 +202,9 @@ struct HfElectronSelectionWithTpcEmcal { registry.add("hAfterPIDEtaPhi", "PID Info after PID Cuts Eta vs Phi ; #eta; #varphi; ", {HistType::kTH2F, {{axisEta}, {axisPhi}}}); registry.add("hEPRatioAfterPID", "E/P Ratio after PID Cuts apply only trackwodca filter", {HistType::kTH2F, {{axisPt}, {axisEmcEnergy}}}); - registry.add("hPIDAfterPIDCuts", "PID Info after PID cuts; E/P;#it{p}_{T} (GeV#it{/c});n#sigma;m02; m20;", {HistType::kTHnSparseF, {{binsEoP}, {binsPt}, {binsnSigma}, {binsM02}, {binsM20}}}); - registry.add("hEmcClsTrkEtaPhiDiffTime", "EmcClsTrkEtaPhiDiffTime;#Delta#eta;#Delta#varphi;Sec;", {HistType::kTH3F, {{binsDeltaEta}, {binsDeltaPhi}, {binsEmcClsTime}}}); + + registry.add("hPIDAfterPIDCuts", "PID Info after PID cuts; E/P;#it{p}_{T} (GeV#it{/c});n#sigma;m02; m20;", {HistType::kTHnSparseF, {{axisEoP}, {axisPt}, {axisnSigma}, {axisM02}, {axisM20}}}); + registry.add("hEmcClsTrkEtaPhiDiffTime", "EmcClsTrkEtaPhiDiffTime;#Delta#eta;#Delta#varphi;Sec;", {HistType::kTH3F, {{axisDeltaEta}, {axisDeltaPhi}, {axisEmcClsTime}}}); } // Track Selection Cut template @@ -365,6 +366,11 @@ struct HfElectronSelectionWithTpcEmcal { return; registry.fill(HIST("hNevents"), 1); + + // skip events with no clusters + if (emcClusters.size() == 0) { + return; + } registry.fill(HIST("hZvertex"), collision.posZ()); ///////////////////////////////// From ff7830b63c62a4045a82e9af5e1bc5480cbb3e4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADt=20Ku=C4=8Dera?= Date: Fri, 13 Jun 2025 15:39:21 +0200 Subject: [PATCH 065/871] [PWGLF] Include What You Use (#11551) --- PWGLF/DataModel/LFStrangenessTables.h | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/PWGLF/DataModel/LFStrangenessTables.h b/PWGLF/DataModel/LFStrangenessTables.h index ce2e9e65eda..3ee36c7c54a 100644 --- a/PWGLF/DataModel/LFStrangenessTables.h +++ b/PWGLF/DataModel/LFStrangenessTables.h @@ -8,22 +8,29 @@ // 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. + #ifndef PWGLF_DATAMODEL_LFSTRANGENESSTABLES_H_ #define PWGLF_DATAMODEL_LFSTRANGENESSTABLES_H_ -#include -#include -#include "Framework/AnalysisDataModel.h" +#include "PWGLF/DataModel/EPCalibrationTables.h" +#include "PWGLF/DataModel/SPCalibrationTables.h" +#include "PWGUD/DataModel/UDTables.h" + #include "Common/Core/RecoDecay.h" -#include "CommonConstants/PhysicsConstants.h" +#include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/McCollisionExtra.h" // IWYU pragma: keep (FIXME: not used, remove asap) #include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/Centrality.h" #include "Common/DataModel/Qvectors.h" -#include "Common/DataModel/McCollisionExtra.h" -#include "PWGLF/DataModel/EPCalibrationTables.h" -#include "PWGLF/DataModel/SPCalibrationTables.h" -#include "PWGUD/DataModel/UDTables.h" + +#include +#include +#include + +#include +#include +#include +#include namespace o2::aod { From 84277d3cd950e58cd0184339e60c336e153b7fab Mon Sep 17 00:00:00 2001 From: Fabrizio Chinu <91954233+fchinu@users.noreply.github.com> Date: Fri, 13 Jun 2025 16:01:07 +0200 Subject: [PATCH 066/871] [Common,PWGHF] Add reduced workflow for B+, B0s -> J/Psi X analyses (#11368) Co-authored-by: ALICE Action Bot --- Common/Core/RecoDecay.h | 14 + PWGHF/Core/DecayChannels.h | 24 + PWGHF/Core/HfHelper.h | 250 +++- PWGHF/Core/HfMlResponseBplusToJpsiKReduced.h | 179 +++ PWGHF/Core/HfMlResponseBsToJpsiPhiReduced.h | 201 +++ PWGHF/Core/SelectorCuts.h | 159 +++ PWGHF/D2H/DataModel/ReducedDataModel.h | 288 ++++- PWGHF/D2H/TableProducer/CMakeLists.txt | 10 + .../candidateCreatorB0Reduced.cxx | 22 +- .../candidateCreatorBToJpsiReduced.cxx | 482 +++++++ .../candidateCreatorBplusReduced.cxx | 20 +- .../candidateCreatorBsReduced.cxx | 20 +- .../dataCreatorCharmHadPiReduced.cxx | 65 +- .../dataCreatorJpsiHadReduced.cxx | 1120 +++++++++++++++++ PWGHF/D2H/Tasks/CMakeLists.txt | 10 + PWGHF/D2H/Tasks/taskBplusToJpsiKReduced.cxx | 535 ++++++++ PWGHF/D2H/Tasks/taskBsToJpsiPhiReduced.cxx | 582 +++++++++ PWGHF/D2H/Utils/utilsRedDataFormat.h | 35 +- .../DataModel/CandidateReconstructionTables.h | 226 +++- PWGHF/DataModel/CandidateSelectionTables.h | 14 +- PWGHF/Utils/utilsTrkCandHf.h | 27 +- 21 files changed, 4141 insertions(+), 142 deletions(-) create mode 100644 PWGHF/Core/HfMlResponseBplusToJpsiKReduced.h create mode 100644 PWGHF/Core/HfMlResponseBsToJpsiPhiReduced.h create mode 100644 PWGHF/D2H/TableProducer/candidateCreatorBToJpsiReduced.cxx create mode 100644 PWGHF/D2H/TableProducer/dataCreatorJpsiHadReduced.cxx create mode 100644 PWGHF/D2H/Tasks/taskBplusToJpsiKReduced.cxx create mode 100644 PWGHF/D2H/Tasks/taskBsToJpsiPhiReduced.cxx diff --git a/Common/Core/RecoDecay.h b/Common/Core/RecoDecay.h index 2bdf3b82b60..7716a8d64a0 100644 --- a/Common/Core/RecoDecay.h +++ b/Common/Core/RecoDecay.h @@ -22,6 +22,7 @@ #include // std::array #include // std::abs, std::sqrt #include +#include // std::apply #include // std::move #include // std::vector @@ -285,6 +286,19 @@ struct RecoDecay { return static_cast(length) * static_cast(mass) / p(mom); } + /// Calculates proper lifetime times c (pseudoproper decay length) in XY from information on daughter tracks. + /// \param posPV {x, y, z} or {x, y} position of the primary vertex + /// \param posSV {x, y, z} or {x, y} position of the secondary vertex + /// \param mom array of {x, y, z} or {x, y} momentum arrays of the decay products + /// \param mass mass of the decay products + /// \return pseudoproper decay length + template + static double ctXY(const T& posPV, const U& posSV, const std::array, N>& mom, const std::array mass) + { + // c t_xy = l_xy * m c^2 / (pT c) + return distanceXY(posPV, posSV) * m(mom, mass) / std::apply([](const auto&... args) { return pt(args...); }, mom); + } + /// Calculates cosine of θ* (theta star). /// \note Implemented for 2 prongs only. /// \param arrMom array of two 3-momentum arrays diff --git a/PWGHF/Core/DecayChannels.h b/PWGHF/Core/DecayChannels.h index f56e8ce1005..44fefb4eeff 100644 --- a/PWGHF/Core/DecayChannels.h +++ b/PWGHF/Core/DecayChannels.h @@ -174,6 +174,30 @@ enum DecayChannelResonant : int8_t { // LastChannelResonant }; +/// @brief beauty candidates: beauty to J/ψ decay channels +enum DecayChannelToJpsiMain : int8_t { + // B0 + B0ToJpsiPiK = 1, // J/ψ π- K+ + // Bs0 + BsToJpsiKK, // J/ψ K+ K- + // Λb0 + LbToJpsiPK, // J/ψ p K- + // B+ + BplusToJpsiK, // J/ψ K+ + // Bc+ + BcToJpsiPi, // J/ψ π+ + // + LastChannelToJpsiMain +}; +/// @brief beauty candidates: beauty to J/ψ resonant decay channels +enum DecayChannelToJpsiResonant : int8_t { + // B0 + B0ToJpsiKstar0 = 1, // J/ψ K*0(892) + // Bs0 + BsToJpsiPhi, // J/ψ φ + // + LastChannelToJpsiResonant +}; } // namespace hf_cand_beauty } // namespace o2::hf_decay diff --git a/PWGHF/Core/HfHelper.h b/PWGHF/Core/HfHelper.h index 3f991854956..5c613a4b69a 100644 --- a/PWGHF/Core/HfHelper.h +++ b/PWGHF/Core/HfHelper.h @@ -17,21 +17,21 @@ #ifndef PWGHF_CORE_HFHELPER_H_ #define PWGHF_CORE_HFHELPER_H_ -#include -#include // IWYU pragma: keep (do not replace with Math/Vector4Dfwd.h) +#include "PWGHF/Utils/utilsAnalysis.h" + +#include "Common/Core/RecoDecay.h" +#include "Common/Core/TrackSelectorPID.h" #include #include +#include +#include // IWYU pragma: keep (do not replace with Math/Vector4Dfwd.h) + #include #include #include -#include "Common/Core/RecoDecay.h" -#include "Common/Core/TrackSelectorPID.h" - -#include "PWGHF/Utils/utilsAnalysis.h" - class HfHelper { public: @@ -173,6 +173,12 @@ class HfHelper return candidate.m(std::array{o2::constants::physics::MassD0, o2::constants::physics::MassPiPlus}); } + template + auto invMassBplusToJpsiK(const T& candidate) + { + return candidate.m(std::array{o2::constants::physics::MassMuon, o2::constants::physics::MassMuon, o2::constants::physics::MassKPlus}); + } + template auto cosThetaStarBplus(const T& candidate) { @@ -659,6 +665,12 @@ class HfHelper return candidate.m(std::array{o2::constants::physics::MassDSBar, o2::constants::physics::MassPiPlus}); } + template + auto invMassBsToJpsiPhi(const T& candidate) + { + return candidate.m(std::array{o2::constants::physics::MassMuon, o2::constants::physics::MassMuon, o2::constants::physics::MassKPlus, o2::constants::physics::MassKPlus}); + } + template auto cosThetaStarBs(const T& candidate) { @@ -784,8 +796,7 @@ class HfHelper /// \param pidTrackPi PID status of trackPi (prong1 of B0 candidate) /// \param acceptPIDNotApplicable switch to accept Status::NotApplicable /// \return true if prong1 of B0 candidate passes all selections - template - bool selectionB0ToDPiPid(const T1& pidTrackPi, const T2& acceptPIDNotApplicable) + bool selectionB0ToDPiPid(const int pidTrackPi, const bool acceptPIDNotApplicable) { if (!acceptPIDNotApplicable && pidTrackPi != TrackSelectorPID::Accepted) { return false; @@ -805,10 +816,10 @@ class HfHelper template bool selectionBplusToD0PiTopol(const T1& candBp, const T2& cuts, const T3& binsPt) { - auto ptcandBp = candBp.pt(); + auto ptCandBp = candBp.pt(); auto ptPi = RecoDecay::pt(candBp.pxProng1(), candBp.pyProng1()); - int pTBin = o2::analysis::findBin(binsPt, ptcandBp); + int pTBin = o2::analysis::findBin(binsPt, ptCandBp); if (pTBin == -1) { return false; } @@ -860,8 +871,7 @@ class HfHelper /// \param pidTrackPi PID status of trackPi (prong1 of B+ candidate) /// \param acceptPIDNotApplicable switch to accept Status::NotApplicable /// \return true if prong1 of B+ candidate passes all selections - template - bool selectionBplusToD0PiPid(const T1& pidTrackPi, const T2& acceptPIDNotApplicable) + bool selectionBplusToD0PiPid(const int pidTrackPi, const bool acceptPIDNotApplicable) { if (!acceptPIDNotApplicable && pidTrackPi != TrackSelectorPID::Accepted) { return false; @@ -873,6 +883,105 @@ class HfHelper return true; } + // Apply topological cuts as defined in SelectorCuts.h + /// \param candBp B+ candidate + /// \param cuts B+ candidate selection per pT bin + /// \param binsPt pT bin limits + /// \return true if candidate passes all selections + template + bool selectionBplusToJpsiKTopol(const T1& candBp, const T2& cuts, const T3& binsPt) + { + 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 candJpsi = candBp.jpsi(); + float pseudoPropDecLen = candBp.decayLengthXY() * mCandBp / ptCandBp; + + int binPt = o2::analysis::findBin(binsPt, ptCandBp); + if (binPt == -1) { + return false; + } + + // B+ mass cut + if (std::abs(mCandBp - o2::constants::physics::MassBPlus) > cuts->get(binPt, "m")) { + return false; + } + + // kaon pt + if (ptKa < cuts->get(binPt, "pT K")) { + return false; + } + + // J/Psi pt + if (ptJpsi < cuts->get(binPt, "pT J/Psi")) { + return false; + } + + // J/Psi mass + if (std::abs(candJpsi.m() - o2::constants::physics::MassJPsi) < cuts->get(binPt, "DeltaM J/Psi")) { + return false; + } + + // d0(J/Psi)xd0(K) + if (candBp.impactParameterProduct() > cuts->get(binPt, "B Imp. Par. Product")) { + return false; + } + + // B+ Decay length + if (candBp.decayLength() < cuts->get(binPt, "B decLen")) { + return false; + } + + // B+ Decay length XY + if (candBp.decayLengthXY() < cuts->get(binPt, "B decLenXY")) { + return false; + } + + // B+ CPA cut + if (candBp.cpa() < cuts->get(binPt, "CPA")) { + return false; + } + + // B+ CPAXY cut + if (candBp.cpaXY() < cuts->get(binPt, "CPAXY")) { + return false; + } + + // d0 of K + if (std::abs(candBp.impactParameter1()) < cuts->get(binPt, "d0 K")) { + return false; + } + + // d0 of J/Psi + if (std::abs(candBp.impactParameter0()) < cuts->get(binPt, "d0 J/Psi")) { + return false; + } + + // B pseudoproper decay length + if (pseudoPropDecLen < cuts->get(binPt, "B pseudoprop. decLen")) { + return false; + } + + return true; + } + + /// Apply PID selection + /// \param pidTrackKa PID status of trackKa (prong1 of B+ candidate) + /// \param acceptPIDNotApplicable switch to accept Status::NotApplicable + /// \return true if prong1 of B+ candidate passes all selections + bool selectionBplusToJpsiKPid(const int pidTrackKa, const bool acceptPIDNotApplicable) + { + if (!acceptPIDNotApplicable && pidTrackKa != TrackSelectorPID::Accepted) { + return false; + } + if (acceptPIDNotApplicable && pidTrackKa == TrackSelectorPID::Rejected) { + return false; + } + + return true; + } + /// Apply topological cuts as defined in SelectorCuts.h /// \param candBs Bs candidate /// \param cuts Bs candidate selections @@ -947,8 +1056,7 @@ class HfHelper /// \param pidTrackPi PID status of trackPi (prong1 of Bs candidate) /// \param acceptPIDNotApplicable switch to accept Status::NotApplicable /// \return true if prong1 of Bs candidate passes all selections - template - bool selectionBsToDsPiPid(const T1& pidTrackPi, const T2& acceptPIDNotApplicable) + bool selectionBsToDsPiPid(const int pidTrackPi, const bool acceptPIDNotApplicable) { if (!acceptPIDNotApplicable && pidTrackPi != TrackSelectorPID::Accepted) { return false; @@ -960,6 +1068,115 @@ class HfHelper return true; } + // 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 + /// \return true if candidate passes all selections + template + bool selectionBsToJpsiPhiTopol(const T1& candBs, const T2& candKa0, const T3& candKa1, const T4& cuts, const T5& binsPt) + { + auto ptCandBs = candBs.pt(); + auto mCandBs = invMassBsToJpsiPhi(candBs); + std::array pVecKa0 = candKa0.pVector(); + std::array pVecKa1 = candKa1.pVector(); + 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 candJpsi = candBs.jpsi(); + float pseudoPropDecLen = candBs.decayLengthXY() * mCandBs / ptCandBs; + + int binPt = o2::analysis::findBin(binsPt, ptCandBs); + if (binPt == -1) { + return false; + } + + // Bs mass cut + if (std::abs(mCandBs - o2::constants::physics::MassBPlus) > cuts->get(binPt, "m")) { + return false; + } + + // kaon pt + if (candKa0.pt() < cuts->get(binPt, "pT K") && + candKa1.pt() < cuts->get(binPt, "pT K")) { + return false; + } + + // J/Psi pt + if (ptJpsi < cuts->get(binPt, "pT J/Psi")) { + return false; + } + + // phi mass + 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")) { + return false; + } + + // d0(J/Psi)xd0(phi) + if (candBs.impactParameterProduct() > cuts->get(binPt, "B Imp. Par. Product")) { + return false; + } + + // Bs Decay length + if (candBs.decayLength() < cuts->get(binPt, "B decLen")) { + return false; + } + + // Bs Decay length XY + if (candBs.decayLengthXY() < cuts->get(binPt, "B decLenXY")) { + return false; + } + + // Bs CPA cut + if (candBs.cpa() < cuts->get(binPt, "CPA")) { + return false; + } + + // Bs CPAXY cut + if (candBs.cpaXY() < cuts->get(binPt, "CPAXY")) { + return false; + } + + // d0 of phi + if (std::abs(candBs.impactParameter1()) < cuts->get(binPt, "d0 phi")) { + return false; + } + + // d0 of J/Psi + if (std::abs(candBs.impactParameter0()) < cuts->get(binPt, "d0 J/Psi")) { + return false; + } + + // B pseudoproper decay length + if (pseudoPropDecLen < cuts->get(binPt, "B pseudoprop. decLen")) { + return false; + } + + return true; + } + + /// Apply PID selection + /// \param pidTrackKa PID status of trackKa (prong1 of B+ candidate) + /// \param acceptPIDNotApplicable switch to accept Status::NotApplicable + /// \return true if prong1 of B+ candidate passes all selections + bool selectionBsToJpsiPhiPid(const int pidTrackKa, const bool acceptPIDNotApplicable) + { + if (!acceptPIDNotApplicable && pidTrackKa != TrackSelectorPID::Accepted) { + return false; + } + if (acceptPIDNotApplicable && pidTrackKa == TrackSelectorPID::Rejected) { + return false; + } + + return true; + } + /// Apply topological cuts as defined in SelectorCuts.h /// \param candLb Lb candidate /// \param cuts Lb candidate selection per pT bin" @@ -1028,8 +1245,7 @@ class HfHelper /// \param pidTrackPi PID status of trackPi (prong1 of Lb candidate) /// \param acceptPIDNotApplicable switch to accept Status::NotApplicable /// \return true if prong1 of Lb candidate passes all selections - template - bool selectionLbToLcPiPid(const T1& pidTrackPi, const T2& acceptPIDNotApplicable) + bool selectionLbToLcPiPid(const int pidTrackPi, const bool acceptPIDNotApplicable) { if (!acceptPIDNotApplicable && pidTrackPi != TrackSelectorPID::Accepted) { return false; diff --git a/PWGHF/Core/HfMlResponseBplusToJpsiKReduced.h b/PWGHF/Core/HfMlResponseBplusToJpsiKReduced.h new file mode 100644 index 00000000000..5f218ec6259 --- /dev/null +++ b/PWGHF/Core/HfMlResponseBplusToJpsiKReduced.h @@ -0,0 +1,179 @@ +// 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 HfMlResponseBplusToJpsiKReduced.h +/// \brief Class to compute the ML response for B± → J/Psi K± analysis selections in the reduced format +/// \author Fabrizio Chinu , Università degli Studi and INFN Torino + +#ifndef PWGHF_CORE_HFMLRESPONSEBPLUSTOJPSIKREDUCED_H_ +#define PWGHF_CORE_HFMLRESPONSEBPLUSTOJPSIKREDUCED_H_ + +#include "PWGHF/Core/HfMlResponse.h" +#include "PWGHF/D2H/Utils/utilsRedDataFormat.h" + +#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_BPLUS(FEATURE) \ + { \ + #FEATURE, static_cast(InputFeaturesBplusToJpsiKReduced::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 from OBJECT +#define CHECK_AND_FILL_VEC_BPLUS_FULL(OBJECT, FEATURE, GETTER) \ + case static_cast(InputFeaturesBplusToJpsiKReduced::FEATURE): { \ + inputFeatures.emplace_back(OBJECT.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 GETTER function taking OBJECT in argument +#define CHECK_AND_FILL_VEC_BPLUS_FUNC(OBJECT, FEATURE, GETTER) \ + case static_cast(InputFeaturesBplusToJpsiKReduced::FEATURE): { \ + inputFeatures.emplace_back(GETTER(OBJECT)); \ + break; \ + } + +// Specific case of CHECK_AND_FILL_VEC_BPLUS_FULL(OBJECT, FEATURE, GETTER) +// where OBJECT is named candidate and FEATURE = GETTER +#define CHECK_AND_FILL_VEC_BPLUS(GETTER) \ + case static_cast(InputFeaturesBplusToJpsiKReduced::GETTER): { \ + inputFeatures.emplace_back(candidate.GETTER()); \ + break; \ + } + +// Specific case of CHECK_AND_FILL_VEC_BPLUS_FULL(OBJECT, FEATURE, GETTER) +// where OBJECT is named candidate, FEATURE = GETTER, and args are needed +#define CHECK_AND_FILL_VEC_BPLUS_WITH_ARGS(GETTER, ARGS...) \ + case static_cast(InputFeaturesBplusToJpsiKReduced::GETTER): { \ + inputFeatures.emplace_back(candidate.GETTER(ARGS)); \ + break; \ + } + +namespace o2::analysis +{ + +enum class InputFeaturesBplusToJpsiKReduced : uint8_t { + ptProng0 = 0, + ptProng1, + impactParameter0, + impactParameter1, + impactParameter2, + impactParameterProduct, + impactParameterProductJpsi, + chi2PCA, + decayLength, + decayLengthXY, + decayLengthNormalised, + decayLengthXYNormalised, + cpa, + cpaXY, + maxNormalisedDeltaIP, + ctXY, + tpcNSigmaKa1, + tofNSigmaKa1, + tpcTofNSigmaKa1 +}; + +template +class HfMlResponseBplusToJpsiKReduced : public HfMlResponse +{ + public: + /// Default constructor + HfMlResponseBplusToJpsiKReduced() = default; + /// Default destructor + virtual ~HfMlResponseBplusToJpsiKReduced() = default; + + /// Method to get the input features vector needed for ML inference + /// \param candidate is the B+ candidate + /// \param prong1 is the candidate's prong1 + /// \return inputFeatures vector + template + std::vector getInputFeatures(T1 const& candidate, + T2 const& prong1) + { + std::vector inputFeatures; + + for (const auto& idx : MlResponse::mCachedIndices) { + switch (idx) { + CHECK_AND_FILL_VEC_BPLUS(ptProng0); + CHECK_AND_FILL_VEC_BPLUS(ptProng1); + CHECK_AND_FILL_VEC_BPLUS(impactParameter0); + CHECK_AND_FILL_VEC_BPLUS(impactParameter1); + CHECK_AND_FILL_VEC_BPLUS(impactParameter2); + CHECK_AND_FILL_VEC_BPLUS(impactParameterProduct); + CHECK_AND_FILL_VEC_BPLUS(impactParameterProductJpsi); + CHECK_AND_FILL_VEC_BPLUS(chi2PCA); + CHECK_AND_FILL_VEC_BPLUS(decayLength); + CHECK_AND_FILL_VEC_BPLUS(decayLengthXY); + CHECK_AND_FILL_VEC_BPLUS(decayLengthNormalised); + CHECK_AND_FILL_VEC_BPLUS(decayLengthXYNormalised); + CHECK_AND_FILL_VEC_BPLUS(cpa); + CHECK_AND_FILL_VEC_BPLUS(cpaXY); + CHECK_AND_FILL_VEC_BPLUS(maxNormalisedDeltaIP); + CHECK_AND_FILL_VEC_BPLUS_WITH_ARGS(ctXY, std::array{o2::constants::physics::MassMuon, o2::constants::physics::MassMuon, o2::constants::physics::MassKPlus}); + // TPC PID variable + CHECK_AND_FILL_VEC_BPLUS_FULL(prong1, tpcNSigmaKa1, tpcNSigmaKa); + // TOF PID variable + CHECK_AND_FILL_VEC_BPLUS_FULL(prong1, tofNSigmaKa1, tofNSigmaKa); + // Combined PID variables + CHECK_AND_FILL_VEC_BPLUS_FUNC(prong1, tpcTofNSigmaKa1, o2::pid_tpc_tof_utils::getTpcTofNSigmaKa1); + } + } + + return inputFeatures; + } + + protected: + /// Method to fill the map of available input features + void setAvailableInputFeatures() + { + MlResponse::mAvailableInputFeatures = { + FILL_MAP_BPLUS(ptProng0), + FILL_MAP_BPLUS(ptProng1), + FILL_MAP_BPLUS(impactParameter0), + FILL_MAP_BPLUS(impactParameter1), + FILL_MAP_BPLUS(impactParameter2), + FILL_MAP_BPLUS(impactParameterProduct), + FILL_MAP_BPLUS(impactParameterProductJpsi), + FILL_MAP_BPLUS(chi2PCA), + FILL_MAP_BPLUS(decayLength), + FILL_MAP_BPLUS(decayLengthXY), + FILL_MAP_BPLUS(decayLengthNormalised), + FILL_MAP_BPLUS(decayLengthXYNormalised), + FILL_MAP_BPLUS(cpa), + FILL_MAP_BPLUS(cpaXY), + FILL_MAP_BPLUS(maxNormalisedDeltaIP), + FILL_MAP_BPLUS(ctXY), + // TPC PID variable + FILL_MAP_BPLUS(tpcNSigmaKa1), + // TOF PID variable + FILL_MAP_BPLUS(tofNSigmaKa1), + // Combined PID variable + FILL_MAP_BPLUS(tpcTofNSigmaKa1)}; + } +}; + +} // namespace o2::analysis + +#undef FILL_MAP_BPLUS +#undef CHECK_AND_FILL_VEC_BPLUS_FULL +#undef CHECK_AND_FILL_VEC_BPLUS_FUNC +#undef CHECK_AND_FILL_VEC_BPLUS + +#endif // PWGHF_CORE_HFMLRESPONSEBPLUSTOJPSIKREDUCED_H_ diff --git a/PWGHF/Core/HfMlResponseBsToJpsiPhiReduced.h b/PWGHF/Core/HfMlResponseBsToJpsiPhiReduced.h new file mode 100644 index 00000000000..71e19567a2b --- /dev/null +++ b/PWGHF/Core/HfMlResponseBsToJpsiPhiReduced.h @@ -0,0 +1,201 @@ +// 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 HfMlResponseBsToJpsiPhiReduced.h +/// \brief Class to compute the ML response for Bs0 → J/Psi phi analysis selections in the reduced format +/// \author Fabrizio Chinu , Università degli Studi and INFN Torino + +#ifndef PWGHF_CORE_HFMLRESPONSEBSTOJPSIPHIREDUCED_H_ +#define PWGHF_CORE_HFMLRESPONSEBSTOJPSIPHIREDUCED_H_ + +#include "PWGHF/Core/HfMlResponse.h" +#include "PWGHF/D2H/Utils/utilsRedDataFormat.h" + +#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_BS(FEATURE) \ + { \ + #FEATURE, static_cast(InputFeaturesBsToJpsiPhiReduced::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 from OBJECT +#define CHECK_AND_FILL_VEC_BS_FULL(OBJECT, FEATURE, GETTER) \ + case static_cast(InputFeaturesBsToJpsiPhiReduced::FEATURE): { \ + inputFeatures.emplace_back(OBJECT.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 GETTER function taking OBJECT in argument +#define CHECK_AND_FILL_VEC_BS_FUNC(OBJECT, FEATURE, GETTER) \ + case static_cast(InputFeaturesBsToJpsiPhiReduced::FEATURE): { \ + inputFeatures.emplace_back(GETTER(OBJECT)); \ + break; \ + } + +// Specific case of CHECK_AND_FILL_VEC_BS_FULL(OBJECT, FEATURE, GETTER) +// where OBJECT is named candidate and FEATURE = GETTER +#define CHECK_AND_FILL_VEC_BS(GETTER) \ + case static_cast(InputFeaturesBsToJpsiPhiReduced::GETTER): { \ + inputFeatures.emplace_back(candidate.GETTER()); \ + break; \ + } + +// Specific case of CHECK_AND_FILL_VEC_BPLUS_FULL(OBJECT, FEATURE, GETTER) +// where OBJECT is named candidate and FEATURE = GETTER and args are needed +#define CHECK_AND_FILL_VEC_BS_WITH_ARGS(GETTER, ARGS...) \ + case static_cast(InputFeaturesBsToJpsiPhiReduced::GETTER): { \ + inputFeatures.emplace_back(candidate.GETTER(ARGS)); \ + break; \ + } + +namespace o2::analysis +{ + +enum class InputFeaturesBsToJpsiPhiReduced : uint8_t { + ptProng0 = 0, + ptProng1, + impactParameter0, + impactParameter1, + impactParameter2, + impactParameter3, + impactParameterProduct, + impactParameterProductJpsi, + impactParameterProductPhi, + chi2PCA, + decayLength, + decayLengthXY, + decayLengthNormalised, + decayLengthXYNormalised, + cpa, + cpaXY, + maxNormalisedDeltaIP, + ctXY, + tpcNSigmaKa0, + tofNSigmaKa0, + tpcTofNSigmaKa0, + tpcNSigmaKa1, + tofNSigmaKa1, + tpcTofNSigmaKa1 +}; + +template +class HfMlResponseBsToJpsiPhiReduced : public HfMlResponse +{ + public: + /// Default constructor + HfMlResponseBsToJpsiPhiReduced() = default; + /// Default destructor + virtual ~HfMlResponseBsToJpsiPhiReduced() = default; + + /// Method to get the input features vector needed for ML inference + /// \param candidate is the Bs candidate + /// \param prong1 is the candidate's prong1 + /// \return inputFeatures vector + template + std::vector getInputFeatures(T1 const& candidate, + T2 const& prong1, + T3 const& prong2) + { + std::vector inputFeatures; + + for (const auto& idx : MlResponse::mCachedIndices) { + switch (idx) { + CHECK_AND_FILL_VEC_BS(ptProng0); + CHECK_AND_FILL_VEC_BS(ptProng1); + CHECK_AND_FILL_VEC_BS(impactParameter0); + CHECK_AND_FILL_VEC_BS(impactParameter1); + CHECK_AND_FILL_VEC_BS(impactParameter2); + CHECK_AND_FILL_VEC_BS(impactParameter3); + CHECK_AND_FILL_VEC_BS(impactParameterProduct); + CHECK_AND_FILL_VEC_BS(impactParameterProductJpsi); + CHECK_AND_FILL_VEC_BS(impactParameterProductPhi); + CHECK_AND_FILL_VEC_BS(chi2PCA); + CHECK_AND_FILL_VEC_BS(decayLength); + CHECK_AND_FILL_VEC_BS(decayLengthXY); + CHECK_AND_FILL_VEC_BS(decayLengthNormalised); + CHECK_AND_FILL_VEC_BS(decayLengthXYNormalised); + CHECK_AND_FILL_VEC_BS(cpa); + CHECK_AND_FILL_VEC_BS(cpaXY); + CHECK_AND_FILL_VEC_BS(maxNormalisedDeltaIP); + CHECK_AND_FILL_VEC_BS_WITH_ARGS(ctXY, std::array{o2::constants::physics::MassMuon, o2::constants::physics::MassMuon, o2::constants::physics::MassKPlus, o2::constants::physics::MassKPlus}); + // TPC PID variable + CHECK_AND_FILL_VEC_BS_FULL(prong1, tpcNSigmaKa0, tpcNSigmaKa); + // TOF PID variable + CHECK_AND_FILL_VEC_BS_FULL(prong1, tofNSigmaKa0, tofNSigmaKa); + // Combined PID variables + CHECK_AND_FILL_VEC_BS_FUNC(prong1, tpcTofNSigmaKa0, o2::pid_tpc_tof_utils::getTpcTofNSigmaKa1); + // TPC PID variable + CHECK_AND_FILL_VEC_BS_FULL(prong2, tpcNSigmaKa1, tpcNSigmaKa); + // TOF PID variable + CHECK_AND_FILL_VEC_BS_FULL(prong2, tofNSigmaKa1, tofNSigmaKa); + // Combined PID variables + CHECK_AND_FILL_VEC_BS_FUNC(prong2, tpcTofNSigmaKa1, o2::pid_tpc_tof_utils::getTpcTofNSigmaKa1); + } + } + + return inputFeatures; + } + + protected: + /// Method to fill the map of available input features + void setAvailableInputFeatures() + { + MlResponse::mAvailableInputFeatures = { + FILL_MAP_BS(ptProng0), + FILL_MAP_BS(ptProng1), + FILL_MAP_BS(impactParameter0), + FILL_MAP_BS(impactParameter1), + FILL_MAP_BS(impactParameter2), + FILL_MAP_BS(impactParameter3), + FILL_MAP_BS(impactParameterProduct), + FILL_MAP_BS(impactParameterProductJpsi), + FILL_MAP_BS(impactParameterProductPhi), + FILL_MAP_BS(chi2PCA), + FILL_MAP_BS(decayLength), + FILL_MAP_BS(decayLengthXY), + FILL_MAP_BS(decayLengthNormalised), + FILL_MAP_BS(decayLengthXYNormalised), + FILL_MAP_BS(cpa), + FILL_MAP_BS(cpaXY), + FILL_MAP_BS(maxNormalisedDeltaIP), + FILL_MAP_BS(ctXY), + // TPC PID variable + FILL_MAP_BS(tpcNSigmaKa0), + // TOF PID variable + FILL_MAP_BS(tofNSigmaKa0), + // Combined PID variable + FILL_MAP_BS(tpcTofNSigmaKa0), + // TPC PID variable + FILL_MAP_BS(tpcNSigmaKa1), + // TOF PID variable + FILL_MAP_BS(tofNSigmaKa1), + // Combined PID variable + FILL_MAP_BS(tpcTofNSigmaKa1)}; + } +}; + +} // namespace o2::analysis + +#undef FILL_MAP_BS +#undef CHECK_AND_FILL_VEC_BS_FULL +#undef CHECK_AND_FILL_VEC_BS_FUNC +#undef CHECK_AND_FILL_VEC_BS + +#endif // PWGHF_CORE_HFMLRESPONSEBSTOJPSIPHIREDUCED_H_ diff --git a/PWGHF/Core/SelectorCuts.h b/PWGHF/Core/SelectorCuts.h index 61e17b16ff1..7fbd324f8c3 100644 --- a/PWGHF/Core/SelectorCuts.h +++ b/PWGHF/Core/SelectorCuts.h @@ -896,6 +896,53 @@ static const std::vector labelsPt = { static const std::vector labelsCutVar = {"m", "DCA_xy", "DCA_z", "pT El", "chi2PCA"}; } // namespace hf_cuts_jpsi_to_e_e +namespace hf_cuts_jpsi_to_mu_mu +{ +static constexpr int NBinsPt = 9; +static constexpr int NCutVars = 8; +// 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] = { + 0, + 0.5, + 1.0, + 2.0, + 3.0, + 4.0, + 5.0, + 6.0, + 10.0, + 16.0, +}; +auto vecBinsPt = std::vector{BinsPt, BinsPt + NBinsPt + 1}; + +// default values for the cuts +constexpr double Cuts[NBinsPt][NCutVars] = {{0.6, 1.0, 0.2, 0.2, 0.9, 0.9, 0., 0.}, /* 0 < pT < 0.5 */ + {0.6, 1.0, 0.2, 0.2, 0.9, 0.9, 0., 0.}, /* 0.5 < pT < 1 */ + {0.6, 1.0, 0.2, 0.2, 0.9, 0.9, 0., 0.}, /* 1 < pT < 2 */ + {0.6, 1.0, 0.2, 0.2, 0.9, 0.9, 0., 0.}, /* 2 < pT < 3 */ + {0.6, 1.0, 0.2, 0.2, 0.9, 0.9, 0., 0.}, /* 3 < pT < 4 */ + {0.6, 1.0, 0.2, 0.2, 0.9, 0.9, 0., 0.}, /* 4 < pT < 5 */ + {0.8, 1.0, 0.3, 0.3, 0.9, 0.9, 0., 0.}, /* 5 < pT < 6 */ + {0.8, 1.0, 0.3, 0.3, 0.9, 0.9, 1., 0.}, /* 6 < pT < 10 */ + {0.8, 1.0, 0.3, 0.3, 0.9, 0.9, 1., 0.}}; /* 10 < pT < 16 */ + +// row labels +static const std::vector labelsPt = { + "pT bin 0", + "pT bin 1", + "pT bin 2", + "pT bin 3", + "pT bin 4", + "pT bin 5", + "pT bin 6", + "pT bin 7", + "pT bin 8"}; + +// column labels +static const std::vector labelsCutVar = {"m", "pT mu", "decay length", "decay length xy", "cpa", "cpa xy", "d0xd0", "pseudoprop. decay length"}; +} // namespace hf_cuts_jpsi_to_mu_mu + namespace hf_cuts_b0_to_d_pi { static constexpr int NBinsPt = 12; @@ -1003,6 +1050,62 @@ static const std::vector labelsPt = { static const std::vector labelsCutVar = {"m", "CPA", "Chi2PCA", "d0 Ds", "d0 Pi", "pT Ds", "pT Pi", "Bs decLen", "Bs decLenXY", "Imp. Par. Product"}; } // namespace hf_cuts_bs_to_ds_pi +namespace hf_cuts_bs_to_jpsi_phi +{ +static constexpr int NBinsPt = 12; +static constexpr int NCutVars = 13; +// 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] = { + 0, + 0.5, + 1.0, + 2.0, + 3.0, + 4.0, + 5.0, + 7.0, + 10.0, + 13.0, + 16.0, + 20.0, + 24.0}; + +auto vecBinsPt = std::vector{BinsPt, BinsPt + NBinsPt + 1}; + +// default values for the cuts +// DeltaM CPA d0Jpsi d0K pTJpsi pTK BDecayLength BDecayLengthXY BIPProd DeltaMJpsi JpsiIPProd +constexpr double Cuts[NBinsPt][NCutVars] = {{1., 0.8, 0.8, 0.01, 0.01, 1.0, 0.15, 0.05, 0.05, 0., 0.1, 0.02, 0.}, /* 0 < pt < 0.5 */ + {1., 0.8, 0.8, 0.01, 0.01, 1.0, 0.15, 0.05, 0.05, 0., 0.1, 0.02, 0.}, /* 0.5 < pt < 1 */ + {1., 0.8, 0.8, 0.01, 0.01, 1.0, 0.15, 0.05, 0.05, 0., 0.1, 0.02, 0.}, /* 1 < pt < 2 */ + {1., 0.8, 0.8, 0.01, 0.01, 1.0, 0.15, 0.05, 0.05, 0., 0.1, 0.02, 0.}, /* 2 < pt < 3 */ + {1., 0.8, 0.8, 0.01, 0.01, 1.0, 0.15, 0.05, 0.05, 0., 0.1, 0.02, 0.}, /* 3 < pt < 4 */ + {1., 0.8, 0.8, 0.01, 0.01, 1.0, 0.15, 0.05, 0.05, 0., 0.1, 0.02, 0.}, /* 4 < pt < 5 */ + {1., 0.8, 0.8, 0.01, 0.01, 1.0, 0.15, 0.05, 0.05, 0., 0.1, 0.02, 0.}, /* 5 < pt < 7 */ + {1., 0.8, 0.8, 0.01, 0.01, 1.0, 0.15, 0.05, 0.05, 0., 0.1, 0.02, 0.}, /* 7 < pt < 10 */ + {1., 0.8, 0.8, 0.01, 0.01, 1.0, 0.15, 0.05, 0.05, 0., 0.1, 0.02, 0.}, /* 10 < pt < 13 */ + {1., 0.8, 0.8, 0.01, 0.01, 1.0, 0.15, 0.05, 0.05, 0., 0.1, 0.02, 0.}, /* 13 < pt < 16 */ + {1., 0.8, 0.8, 0.01, 0.01, 1.0, 0.15, 0.05, 0.05, 0., 0.1, 0.02, 0.}, /* 16 < pt < 20 */ + {1., 0.8, 0.8, 0.01, 0.01, 1.0, 0.15, 0.05, 0.05, 0., 0.1, 0.02, 0.}}; /* 20 < pt < 24 */ +// row labels +static const std::vector labelsPt = { + "pT bin 0", + "pT bin 1", + "pT bin 2", + "pT bin 3", + "pT bin 4", + "pT bin 5", + "pT bin 6", + "pT bin 7", + "pT bin 8", + "pT bin 9", + "pT bin 10", + "pT bin 11"}; + +// column labels +static const std::vector labelsCutVar = {"m", "CPA", "CPAXY", "d0 J/Psi", "d0 phi", "pT J/Psi", "pT K", "B decLen", "B decLenXY", "B Imp. Par. Product", "DeltaM J/Psi", "DeltaM phi", "B pseudoprop. decLen"}; +} // namespace hf_cuts_bs_to_jpsi_phi + namespace hf_cuts_bplus_to_d0_pi { static constexpr int NBinsPt = 12; @@ -1059,6 +1162,62 @@ static const std::vector labelsPt = { static const std::vector labelsCutVar = {"m", "CPA", "d0 D0", "d0 Pi", "pT D0", "pT Pi", "B decLen", "B decLenXY", "Imp. Par. Product", "DeltaMD0", "Cos ThetaStar"}; } // namespace hf_cuts_bplus_to_d0_pi +namespace hf_cuts_bplus_to_jpsi_k +{ +static constexpr int NBinsPt = 12; +static constexpr int NCutVars = 12; +// 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] = { + 0, + 0.5, + 1.0, + 2.0, + 3.0, + 4.0, + 5.0, + 7.0, + 10.0, + 13.0, + 16.0, + 20.0, + 24.0}; + +auto vecBinsPt = std::vector{BinsPt, BinsPt + NBinsPt + 1}; + +// default values for the cuts +// DeltaM CPA d0Jpsi d0K pTJpsi pTK BDecayLength BDecayLengthXY BIPProd DeltaMJpsi JpsiIPProd +constexpr double Cuts[NBinsPt][NCutVars] = {{1., 0.8, 0.8, 0.01, 0.01, 1.0, 0.15, 0.05, 0.05, 0., 0.1, 0.}, /* 0 < pt < 0.5 */ + {1., 0.8, 0.8, 0.01, 0.01, 1.0, 0.15, 0.05, 0.05, 0., 0.1, 0.}, /* 0.5 < pt < 1 */ + {1., 0.8, 0.8, 0.01, 0.01, 1.0, 0.15, 0.05, 0.05, 0., 0.1, 0.}, /* 1 < pt < 2 */ + {1., 0.8, 0.8, 0.01, 0.01, 1.0, 0.15, 0.05, 0.05, 0., 0.1, 0.}, /* 2 < pt < 3 */ + {1., 0.8, 0.8, 0.01, 0.01, 1.0, 0.15, 0.05, 0.05, 0., 0.1, 0.}, /* 3 < pt < 4 */ + {1., 0.8, 0.8, 0.01, 0.01, 1.0, 0.15, 0.05, 0.05, 0., 0.1, 0.}, /* 4 < pt < 5 */ + {1., 0.8, 0.8, 0.01, 0.01, 1.0, 0.15, 0.05, 0.05, 0., 0.1, 0.}, /* 5 < pt < 7 */ + {1., 0.8, 0.8, 0.01, 0.01, 1.0, 0.15, 0.05, 0.05, 0., 0.1, 0.}, /* 7 < pt < 10 */ + {1., 0.8, 0.8, 0.01, 0.01, 1.0, 0.15, 0.05, 0.05, 0., 0.1, 0.}, /* 10 < pt < 13 */ + {1., 0.8, 0.8, 0.01, 0.01, 1.0, 0.15, 0.05, 0.05, 0., 0.1, 0.}, /* 13 < pt < 16 */ + {1., 0.8, 0.8, 0.01, 0.01, 1.0, 0.15, 0.05, 0.05, 0., 0.1, 0.}, /* 16 < pt < 20 */ + {1., 0.8, 0.8, 0.01, 0.01, 1.0, 0.15, 0.05, 0.05, 0., 0.1, 0.}}; /* 20 < pt < 24 */ +// row labels +static const std::vector labelsPt = { + "pT bin 0", + "pT bin 1", + "pT bin 2", + "pT bin 3", + "pT bin 4", + "pT bin 5", + "pT bin 6", + "pT bin 7", + "pT bin 8", + "pT bin 9", + "pT bin 10", + "pT bin 11"}; + +// column labels +static const std::vector labelsCutVar = {"m", "CPA", "CPAXY", "d0 J/Psi", "d0 K", "pT J/Psi", "pT K", "B decLen", "B decLenXY", "B Imp. Par. Product", "DeltaM J/Psi", "B pseudoprop. decLen"}; +} // namespace hf_cuts_bplus_to_jpsi_k + namespace hf_cuts_lb_to_lc_pi { static constexpr int NBinsPt = 12; diff --git a/PWGHF/D2H/DataModel/ReducedDataModel.h b/PWGHF/D2H/DataModel/ReducedDataModel.h index 092210a22ca..939f0648099 100644 --- a/PWGHF/D2H/DataModel/ReducedDataModel.h +++ b/PWGHF/D2H/DataModel/ReducedDataModel.h @@ -19,16 +19,13 @@ /// \author Fabrizio Grosa , CERN /// \author Luca Aglietta , Università degli Studi di Torino (UniTO) /// \author Biao Zhang , Heidelberg University +/// \author Fabrizio Chinu , Università degli Studi di Torino (UniTO) #ifndef PWGHF_D2H_DATAMODEL_REDUCEDDATAMODEL_H_ #define PWGHF_D2H_DATAMODEL_REDUCEDDATAMODEL_H_ -#include -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoA.h" +#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "PWGHF/Utils/utilsPid.h" #include "Common/Core/RecoDecay.h" #include "Common/DataModel/Centrality.h" @@ -37,8 +34,14 @@ #include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/Qvectors.h" -#include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/Utils/utilsPid.h" +#include "CommonConstants/PhysicsConstants.h" +#include "Framework/ASoA.h" +#include "Framework/AnalysisDataModel.h" + +#include +#include +#include +#include namespace o2 { @@ -278,6 +281,66 @@ DECLARE_SOA_TABLE(HfRedTracksCov, "AOD", "HFREDTRACKCOV", //! Table with track c soa::Index<>, HFTRACKPARCOV_COLUMNS); +// CAREFUL: need to follow convention [Name = Description + 's'] in DECLARE_SOA_TABLE(Name, "AOD", Description) +// to call DECLARE_SOA_INDEX_COLUMN_FULL later on +DECLARE_SOA_TABLE(HfRedBach0Bases, "AOD", "HFREDBACH0BASE", //! Table with track information for reduced workflow + soa::Index<>, + hf_track_index_reduced::TrackId, + hf_track_index_reduced::HfRedCollisionId, + HFTRACKPAR_COLUMNS, + hf_track_vars_reduced::ItsNCls, + hf_track_vars_reduced::TpcNClsCrossedRows, + hf_track_vars_reduced::TpcChi2NCl, + hf_track_vars_reduced::HasTPC, + hf_track_vars_reduced::HasTOF, + pidtpc::TPCNSigmaPi, + pidtof::TOFNSigmaPi, + pidtpc::TPCNSigmaKa, + pidtof::TOFNSigmaKa, + pidtpc::TPCNSigmaPr, + pidtof::TOFNSigmaPr, + hf_track_pid_reduced::TPCTOFNSigmaPi, + hf_track_pid_reduced::TPCTOFNSigmaKa, + hf_track_pid_reduced::TPCTOFNSigmaPr, + aod::track::Px, + aod::track::Py, + aod::track::Pz, + aod::track::PVector); + +DECLARE_SOA_TABLE(HfRedBach0Cov, "AOD", "HFREDBACH0COV", //! Table with track covariance information for reduced workflow + soa::Index<>, + HFTRACKPARCOV_COLUMNS); + +// CAREFUL: need to follow convention [Name = Description + 's'] in DECLARE_SOA_TABLE(Name, "AOD", Description) +// to call DECLARE_SOA_INDEX_COLUMN_FULL later on +DECLARE_SOA_TABLE(HfRedBach1Bases, "AOD", "HFREDBACH1BASE", //! Table with track information for reduced workflow + soa::Index<>, + hf_track_index_reduced::TrackId, + hf_track_index_reduced::HfRedCollisionId, + HFTRACKPAR_COLUMNS, + hf_track_vars_reduced::ItsNCls, + hf_track_vars_reduced::TpcNClsCrossedRows, + hf_track_vars_reduced::TpcChi2NCl, + hf_track_vars_reduced::HasTPC, + hf_track_vars_reduced::HasTOF, + pidtpc::TPCNSigmaPi, + pidtof::TOFNSigmaPi, + pidtpc::TPCNSigmaKa, + pidtof::TOFNSigmaKa, + pidtpc::TPCNSigmaPr, + pidtof::TOFNSigmaPr, + hf_track_pid_reduced::TPCTOFNSigmaPi, + hf_track_pid_reduced::TPCTOFNSigmaKa, + hf_track_pid_reduced::TPCTOFNSigmaPr, + aod::track::Px, + aod::track::Py, + aod::track::Pz, + aod::track::PVector); + +DECLARE_SOA_TABLE(HfRedBach1Cov, "AOD", "HFREDBACH1COV", //! Table with track covariance information for reduced workflow + soa::Index<>, + HFTRACKPARCOV_COLUMNS); + // table with all attributes needed to call statusTpcAndTof() in the selector task DECLARE_SOA_TABLE(HfRedTracksPid, "AOD", "HFREDTRACKPID", //! Table with PID track information for reduced workflow o2::soa::Index<>, @@ -289,8 +352,14 @@ DECLARE_SOA_TABLE(HfRedTracksPid, "AOD", "HFREDTRACKPID", //! Table with PID tra DECLARE_SOA_EXTENDED_TABLE_USER(HfRedTracksExt, HfRedTrackBases, "HFREDTRACKEXT", //! Track parameters at collision vertex aod::track::Pt); +DECLARE_SOA_EXTENDED_TABLE_USER(HfRedBach0Ext, HfRedBach0Bases, "HFREDBACH0EXT", //! Track parameters at collision vertex + aod::track::Pt); +DECLARE_SOA_EXTENDED_TABLE_USER(HfRedBach1Ext, HfRedBach1Bases, "HFREDBACH1EXT", //! Track parameters at collision vertex + aod::track::Pt); using HfRedTracks = HfRedTracksExt; +using HfRedBach0Tracks = HfRedBach0Ext; +using HfRedBach1Tracks = HfRedBach1Ext; namespace hf_charm_cand_reduced { @@ -304,6 +373,105 @@ DECLARE_SOA_COLUMN(MlScorePromptMassHypo1, mlScorePromptMassHypo1, float); DECLARE_SOA_COLUMN(MlScoreNonpromptMassHypo1, mlScoreNonpromptMassHypo1, float); //! ML score for non-prompt class (mass hypothesis 1) } // namespace hf_charm_cand_reduced +namespace hf_jpsi_cand_reduced +{ +DECLARE_SOA_COLUMN(ProngPosId, prongPosId, int); //! Original track index +DECLARE_SOA_COLUMN(ProngNegId, prongNegId, int); //! Original track index +DECLARE_SOA_COLUMN(HfRedCollisionId, hfRedCollisionId, int); //! Collision index +DECLARE_SOA_COLUMN(M, m, float); //! Invariant mass of candidate in GeV/c2 +DECLARE_SOA_COLUMN(XDauPos, xDauPos, float); //! x +DECLARE_SOA_COLUMN(XDauNeg, xDauNeg, float); //! x +DECLARE_SOA_COLUMN(YDauPos, yDauPos, float); //! y +DECLARE_SOA_COLUMN(YDauNeg, yDauNeg, float); //! y +DECLARE_SOA_COLUMN(ZDauPos, zDauPos, float); //! z +DECLARE_SOA_COLUMN(ZDauNeg, zDauNeg, float); //! z +DECLARE_SOA_COLUMN(AlphaDauPos, alphaDauPos, float); //! alpha of the J/Psi positive decay daughter +DECLARE_SOA_COLUMN(AlphaDauNeg, alphaDauNeg, float); //! alpha of the J/Psi negative decay daughter +DECLARE_SOA_COLUMN(SnpDauPos, snpDauPos, float); //! snp of the J/Psi positive decay daughter +DECLARE_SOA_COLUMN(SnpDauNeg, snpDauNeg, float); //! snp of the J/Psi negative decay daughter +DECLARE_SOA_COLUMN(TglDauPos, tglDauPos, float); //! tgl of the J/Psi positive decay daughter +DECLARE_SOA_COLUMN(TglDauNeg, tglDauNeg, float); //! tgl of the J/Psi negative decay daughter +DECLARE_SOA_COLUMN(Signed1PtDauPos, signed1PtDauPos, float); //! signed1Pt of the J/Psi positive decay daughter +DECLARE_SOA_COLUMN(Signed1PtDauNeg, signed1PtDauNeg, float); //! signed1Pt of the J/Psi negative decay daughter + +DECLARE_SOA_DYNAMIC_COLUMN(PxDauPos, pxDauPos, //! Momentum in x-direction in GeV/c + [](float signed1Pt, float snp, float alpha) -> float { + auto pt = 1.f / std::abs(signed1Pt); + // FIXME: GCC & clang should optimize to sincosf + float cs = cosf(alpha), sn = sinf(alpha); + auto r = std::sqrt((1.f - snp) * (1.f + snp)); + return pt * (r * cs - snp * sn); + }); +DECLARE_SOA_DYNAMIC_COLUMN(PyDauPos, pyDauPos, //! Momentum in y-direction in GeV/c + [](float signed1Pt, float snp, float alpha) -> float { + auto pt = 1.f / std::abs(signed1Pt); + // FIXME: GCC & clang should optimize to sincosf + float cs = cosf(alpha), sn = sinf(alpha); + auto r = std::sqrt((1.f - snp) * (1.f + snp)); + return pt * (snp * cs + r * sn); + }); +DECLARE_SOA_DYNAMIC_COLUMN(PzDauPos, pzDauPos, //! Momentum in z-direction in GeV/c + [](float signed1Pt, float tgl) -> float { + auto pt = 1.f / std::abs(signed1Pt); + return pt * tgl; + }); +DECLARE_SOA_DYNAMIC_COLUMN(PxDauNeg, pxDauNeg, //! Momentum in x-direction in GeV/c + [](float signed1Pt, float snp, float alpha) -> float { + auto pt = 1.f / std::abs(signed1Pt); + // FIXME: GCC & clang should optimize to sincosf + float cs = cosf(alpha), sn = sinf(alpha); + auto r = std::sqrt((1.f - snp) * (1.f + snp)); + return pt * (r * cs - snp * sn); + }); +DECLARE_SOA_DYNAMIC_COLUMN(PyDauNeg, pyDauNeg, //! Momentum in y-direction in GeV/c + [](float signed1Pt, float snp, float alpha) -> float { + auto pt = 1.f / std::abs(signed1Pt); + // FIXME: GCC & clang should optimize to sincosf + float cs = cosf(alpha), sn = sinf(alpha); + auto r = std::sqrt((1.f - snp) * (1.f + snp)); + return pt * (snp * cs + r * sn); + }); +DECLARE_SOA_DYNAMIC_COLUMN(PzDauNeg, pzDauNeg, //! Momentum in z-direction in GeV/c + [](float signed1Pt, float tgl) -> float { + auto pt = 1.f / std::abs(signed1Pt); + return pt * tgl; + }); + +// Covariance matrix of the J/Psi positive decay daughter +DECLARE_SOA_COLUMN(CYYDauPos, cYYDauPos, float); //! Covariance matrix +DECLARE_SOA_COLUMN(CZYDauPos, cZYDauPos, float); //! Covariance matrix +DECLARE_SOA_COLUMN(CZZDauPos, cZZDauPos, float); //! Covariance matrix +DECLARE_SOA_COLUMN(CSnpYDauPos, cSnpYDauPos, float); //! Covariance matrix +DECLARE_SOA_COLUMN(CSnpZDauPos, cSnpZDauPos, float); //! Covariance matrix +DECLARE_SOA_COLUMN(CSnpSnpDauPos, cSnpSnpDauPos, float); //! Covariance matrix +DECLARE_SOA_COLUMN(CTglYDauPos, cTglYDauPos, float); //! Covariance matrix +DECLARE_SOA_COLUMN(CTglZDauPos, cTglZDauPos, float); //! Covariance matrix +DECLARE_SOA_COLUMN(CTglSnpDauPos, cTglSnpDauPos, float); //! Covariance matrix +DECLARE_SOA_COLUMN(CTglTglDauPos, cTglTglDauPos, float); //! Covariance matrix +DECLARE_SOA_COLUMN(C1PtYDauPos, c1PtYDauPos, float); //! Covariance matrix +DECLARE_SOA_COLUMN(C1PtZDauPos, c1PtZDauPos, float); //! Covariance matrix +DECLARE_SOA_COLUMN(C1PtSnpDauPos, c1PtSnpDauPos, float); //! Covariance matrix +DECLARE_SOA_COLUMN(C1PtTglDauPos, c1PtTglDauPos, float); //! Covariance matrix +DECLARE_SOA_COLUMN(C1Pt21Pt2DauPos, c1Pt21Pt2DauPos, float); //! Covariance matrix + +// Covariance matrix of the J/Psi negative decay daughter +DECLARE_SOA_COLUMN(CYYDauNeg, cYYDauNeg, float); //! Covariance matrix +DECLARE_SOA_COLUMN(CZYDauNeg, cZYDauNeg, float); //! Covariance matrix +DECLARE_SOA_COLUMN(CZZDauNeg, cZZDauNeg, float); //! Covariance matrix +DECLARE_SOA_COLUMN(CSnpYDauNeg, cSnpYDauNeg, float); //! Covariance matrix +DECLARE_SOA_COLUMN(CSnpZDauNeg, cSnpZDauNeg, float); //! Covariance matrix +DECLARE_SOA_COLUMN(CSnpSnpDauNeg, cSnpSnpDauNeg, float); //! Covariance matrix +DECLARE_SOA_COLUMN(CTglYDauNeg, cTglYDauNeg, float); //! Covariance matrix +DECLARE_SOA_COLUMN(CTglZDauNeg, cTglZDauNeg, float); //! Covariance matrix +DECLARE_SOA_COLUMN(CTglSnpDauNeg, cTglSnpDauNeg, float); //! Covariance matrix +DECLARE_SOA_COLUMN(CTglTglDauNeg, cTglTglDauNeg, float); //! Covariance matrix +DECLARE_SOA_COLUMN(C1PtYDauNeg, c1PtYDauNeg, float); //! Covariance matrix +DECLARE_SOA_COLUMN(C1PtZDauNeg, c1PtZDauNeg, float); //! Covariance matrix +DECLARE_SOA_COLUMN(C1PtSnpDauNeg, c1PtSnpDauNeg, float); //! Covariance matrix +DECLARE_SOA_COLUMN(C1PtTglDauNeg, c1PtTglDauNeg, float); //! Covariance matrix +DECLARE_SOA_COLUMN(C1Pt21Pt2DauNeg, c1Pt21Pt2DauNeg, float); //! Covariance matrix +} // namespace hf_jpsi_cand_reduced + // CAREFUL: need to follow convention [Name = Description + 's'] in DECLARE_SOA_TABLE(Name, "AOD", Description) // to call DECLARE_SOA_INDEX_COLUMN_FULL later on DECLARE_SOA_TABLE(HfRed2Prongs, "AOD", "HFRED2PRONG", //! Table with 2prong candidate information for reduced workflow @@ -370,6 +538,47 @@ DECLARE_SOA_TABLE_VERSIONED(HfRed3ProngsMl_001, "AOD", "HFRED3PRONGML", 1, //! T using HfRed3ProngsMl = HfRed3ProngsMl_001; +// CAREFUL: need to follow convention [Name = Description + 's'] in DECLARE_SOA_TABLE(Name, "AOD", Description) +// to call DECLARE_SOA_INDEX_COLUMN_FULL later on +DECLARE_SOA_TABLE(HfRedJpsis, "AOD", "HFREDJPSI", //! Table with J/Psi candidate information for reduced workflow + o2::soa::Index<>, + hf_jpsi_cand_reduced::ProngPosId, + hf_jpsi_cand_reduced::ProngNegId, + hf_track_index_reduced::HfRedCollisionId, + hf_cand::XSecondaryVertex, hf_cand::YSecondaryVertex, hf_cand::ZSecondaryVertex, + hf_jpsi_cand_reduced::M, + hf_jpsi_cand_reduced::XDauPos, hf_jpsi_cand_reduced::XDauNeg, + hf_jpsi_cand_reduced::YDauPos, hf_jpsi_cand_reduced::YDauNeg, + hf_jpsi_cand_reduced::ZDauPos, hf_jpsi_cand_reduced::ZDauNeg, + hf_jpsi_cand_reduced::AlphaDauPos, hf_jpsi_cand_reduced::AlphaDauNeg, + hf_jpsi_cand_reduced::SnpDauPos, hf_jpsi_cand_reduced::SnpDauNeg, + hf_jpsi_cand_reduced::TglDauPos, hf_jpsi_cand_reduced::TglDauNeg, + hf_jpsi_cand_reduced::Signed1PtDauPos, hf_jpsi_cand_reduced::Signed1PtDauNeg, + hf_jpsi_cand_reduced::PxDauPos, + hf_jpsi_cand_reduced::PxDauNeg, + hf_jpsi_cand_reduced::PyDauPos, + hf_jpsi_cand_reduced::PyDauNeg, + hf_jpsi_cand_reduced::PzDauPos, + hf_jpsi_cand_reduced::PzDauNeg); + +DECLARE_SOA_TABLE(HfRedJpsiCov, "AOD", "HFREDJPSICOV", //! Table with J/Psi candidate covariance for reduced workflow + o2::soa::Index<>, + hf_jpsi_cand_reduced::CYYDauPos, hf_jpsi_cand_reduced::CYYDauNeg, + hf_jpsi_cand_reduced::CZYDauPos, hf_jpsi_cand_reduced::CZYDauNeg, + hf_jpsi_cand_reduced::CZZDauPos, hf_jpsi_cand_reduced::CZZDauNeg, + hf_jpsi_cand_reduced::CSnpYDauPos, hf_jpsi_cand_reduced::CSnpYDauNeg, + hf_jpsi_cand_reduced::CSnpZDauPos, hf_jpsi_cand_reduced::CSnpZDauNeg, + hf_jpsi_cand_reduced::CSnpSnpDauPos, hf_jpsi_cand_reduced::CSnpSnpDauNeg, + hf_jpsi_cand_reduced::CTglYDauPos, hf_jpsi_cand_reduced::CTglYDauNeg, + hf_jpsi_cand_reduced::CTglZDauPos, hf_jpsi_cand_reduced::CTglZDauNeg, + hf_jpsi_cand_reduced::CTglSnpDauPos, hf_jpsi_cand_reduced::CTglSnpDauNeg, + hf_jpsi_cand_reduced::CTglTglDauPos, hf_jpsi_cand_reduced::CTglTglDauNeg, + hf_jpsi_cand_reduced::C1PtYDauPos, hf_jpsi_cand_reduced::C1PtYDauNeg, + hf_jpsi_cand_reduced::C1PtZDauPos, hf_jpsi_cand_reduced::C1PtZDauNeg, + hf_jpsi_cand_reduced::C1PtSnpDauPos, hf_jpsi_cand_reduced::C1PtSnpDauNeg, + hf_jpsi_cand_reduced::C1PtTglDauPos, hf_jpsi_cand_reduced::C1PtTglDauNeg, + hf_jpsi_cand_reduced::C1Pt21Pt2DauPos, hf_jpsi_cand_reduced::C1Pt21Pt2DauNeg); + DECLARE_SOA_TABLE(HfRedPidDau0s_000, "AOD", "HFREDPIDDAU0", //! hf_track_pid_reduced::TPCNSigmaPiProng0, hf_track_pid_reduced::TOFNSigmaPiProng0, @@ -474,6 +683,8 @@ namespace hf_cand_bplus_reduced { DECLARE_SOA_INDEX_COLUMN_FULL(Prong0, prong0, int, HfRed2Prongs, "_0"); //! Prong0 index DECLARE_SOA_INDEX_COLUMN_FULL(Prong1, prong1, int, HfRedTrackBases, "_1"); //! Prong1 index +DECLARE_SOA_INDEX_COLUMN_FULL(Jpsi, jpsi, int, HfRedJpsis, "_0"); //! J/Psi index +DECLARE_SOA_INDEX_COLUMN_FULL(BachKa, bachKa, int, HfRedBach0Bases, "_0"); //! J/Psi index DECLARE_SOA_COLUMN(Prong0MlScoreBkg, prong0MlScoreBkg, float); //! Bkg ML score of the D daughter DECLARE_SOA_COLUMN(Prong0MlScorePrompt, prong0MlScorePrompt, float); //! Prompt ML score of the D daughter DECLARE_SOA_COLUMN(Prong0MlScoreNonprompt, prong0MlScoreNonprompt, float); //! Nonprompt ML score of the D daughter @@ -482,6 +693,9 @@ DECLARE_SOA_COLUMN(Prong0MlScoreNonprompt, prong0MlScoreNonprompt, float); //! N DECLARE_SOA_TABLE(HfRedBplusProngs, "AOD", "HFREDBPPRONG", hf_cand_bplus_reduced::Prong0Id, hf_cand_bplus_reduced::Prong1Id); +DECLARE_SOA_TABLE(HfRedBplus2JpsiDaus, "AOD", "HFREDBP2JPSIDAU", + hf_cand_bplus_reduced::JpsiId, hf_cand_bplus_reduced::BachKaId); + DECLARE_SOA_TABLE(HfRedBplusD0Mls, "AOD", "HFREDBPLUSD0ML", //! Table with ML scores for the D0 daughter hf_cand_bplus_reduced::Prong0MlScoreBkg, hf_cand_bplus_reduced::Prong0MlScorePrompt, @@ -489,19 +703,26 @@ DECLARE_SOA_TABLE(HfRedBplusD0Mls, "AOD", "HFREDBPLUSD0ML", //! Table with ML sc o2::soa::Marker<1>); using HfRedCandBplus = soa::Join; +using HfRedCandBplusToJpsiK = soa::Join; namespace hf_cand_bs_reduced { -DECLARE_SOA_INDEX_COLUMN_FULL(Prong0, prong0, int, HfRed3Prongs, "_0"); //! Prong0 index -DECLARE_SOA_INDEX_COLUMN_FULL(Prong1, prong1, int, HfRedTrackBases, "_1"); //! Prong1 index -DECLARE_SOA_COLUMN(Prong0MlScoreBkg, prong0MlScoreBkg, float); //! Bkg ML score of the D daughter -DECLARE_SOA_COLUMN(Prong0MlScorePrompt, prong0MlScorePrompt, float); //! Prompt ML score of the D daughter -DECLARE_SOA_COLUMN(Prong0MlScoreNonprompt, prong0MlScoreNonprompt, float); //! Nonprompt ML score of the D daughter +DECLARE_SOA_INDEX_COLUMN_FULL(Prong0, prong0, int, HfRed3Prongs, "_0"); //! Prong0 index +DECLARE_SOA_INDEX_COLUMN_FULL(Prong1, prong1, int, HfRedTrackBases, "_1"); //! Prong1 index +DECLARE_SOA_INDEX_COLUMN_FULL(Jpsi, jpsi, int, HfRedJpsis, "_0"); //! J/Psi index +DECLARE_SOA_INDEX_COLUMN_FULL(Prong0Phi, prong0Phi, int, HfRedBach0Bases, "_0"); //! J/Psi index +DECLARE_SOA_INDEX_COLUMN_FULL(Prong1Phi, prong1Phi, int, HfRedBach1Bases, "_0"); //! J/Psi index +DECLARE_SOA_COLUMN(Prong0MlScoreBkg, prong0MlScoreBkg, float); //! Bkg ML score of the D daughter +DECLARE_SOA_COLUMN(Prong0MlScorePrompt, prong0MlScorePrompt, float); //! Prompt ML score of the D daughter +DECLARE_SOA_COLUMN(Prong0MlScoreNonprompt, prong0MlScoreNonprompt, float); //! Nonprompt ML score of the D daughter } // namespace hf_cand_bs_reduced DECLARE_SOA_TABLE(HfRedBsProngs, "AOD", "HFREDBSPRONG", //! Table with Bs daughter indices hf_cand_bs_reduced::Prong0Id, hf_cand_bs_reduced::Prong1Id); +DECLARE_SOA_TABLE(HfRedBs2JpsiDaus, "AOD", "HFREDBS2JPSIDAU", + hf_cand_bs_reduced::JpsiId, hf_cand_bs_reduced::Prong0PhiId, hf_cand_bs_reduced::Prong1PhiId); + DECLARE_SOA_TABLE(HfRedBsDsMls, "AOD", "HFREDBSDSML", //! Table with ML scores for the Ds daughter hf_cand_bs_reduced::Prong0MlScoreBkg, hf_cand_bs_reduced::Prong0MlScorePrompt, @@ -509,6 +730,7 @@ DECLARE_SOA_TABLE(HfRedBsDsMls, "AOD", "HFREDBSDSML", //! Table with ML scores f o2::soa::Marker<1>); using HfRedCandBs = soa::Join; +using HfRedCandBsToJpsiPhi = soa::Join; namespace hf_cand_lb_reduced { @@ -576,6 +798,7 @@ DECLARE_SOA_TABLE(HfMcCheckDpPis, "AOD", "HFMCCHECKDPPI", //! Table with reconst // Table with same size as HFCANDB0 DECLARE_SOA_TABLE(HfMcRecRedB0s, "AOD", "HFMCRECREDB0", //! Reconstruction-level MC information on B0 candidates for reduced workflow hf_cand_b0::FlagMcMatchRec, + hf_cand_b0::ChannelMcMatchRec, hf_cand_b0::FlagWrongCollision, hf_cand_b0::DebugMcRec, hf_b0_mc::PtMother); @@ -591,6 +814,7 @@ DECLARE_SOA_TABLE(HfMcCheckB0s, "AOD", "HFMCCHECKB0", //! Table with reconstruct DECLARE_SOA_TABLE(HfMcGenRedB0s, "AOD", "HFMCGENREDB0", //! Generation-level MC information on B0 candidates for reduced workflow hf_cand_b0::FlagMcMatchGen, + hf_cand_b0::ChannelMcMatchRec, hf_b0_mc::PtTrack, hf_b0_mc::YTrack, hf_b0_mc::EtaTrack, @@ -644,6 +868,16 @@ DECLARE_SOA_TABLE(HfMcRecRedD0Pis, "AOD", "HFMCRECREDD0PI", //! Table with recon hf_cand_bplus::DebugMcRec, hf_bplus_mc::PtMother); +// table with results of reconstruction level MC matching +DECLARE_SOA_TABLE(HfMcRecRedJPKs, "AOD", "HFMCRECREDJPK", //! Table with reconstructed MC information on J/PsiK(<-B+) pairs for reduced workflow + hf_cand_bplus_reduced::JpsiId, + hf_cand_bplus_reduced::Prong1Id, + hf_cand_bplus::FlagMcMatchRec, + hf_cand_bplus::ChannelMcMatchRec, + hf_cand_bplus::FlagWrongCollision, + hf_cand_bplus::DebugMcRec, + hf_bplus_mc::PtMother); + // DECLARE_SOA_EXTENDED_TABLE_USER(ExTable, Tracks, "EXTABLE", DECLARE_SOA_TABLE(HfMcCheckD0Pis, "AOD", "HFMCCHECKD0PI", //! Table with reconstructed MC information on D0Pi(<-B0) pairs for MC checks in reduced workflow hf_bplus_mc::PdgCodeBeautyMother, @@ -656,6 +890,7 @@ DECLARE_SOA_TABLE(HfMcCheckD0Pis, "AOD", "HFMCCHECKD0PI", //! Table with reconst // Table with same size as HFCANDBPLUS DECLARE_SOA_TABLE(HfMcRecRedBps, "AOD", "HFMCRECREDBP", //! Reconstruction-level MC information on B+ candidates for reduced workflow hf_cand_bplus::FlagMcMatchRec, + hf_cand_bplus::ChannelMcMatchRec, hf_cand_bplus::FlagWrongCollision, hf_cand_bplus::DebugMcRec, hf_bplus_mc::PtMother); @@ -670,6 +905,7 @@ DECLARE_SOA_TABLE(HfMcCheckBps, "AOD", "HFMCCHECKBP", //! Table with reconstruct DECLARE_SOA_TABLE(HfMcGenRedBps, "AOD", "HFMCGENREDBP", //! Generation-level MC information on B+ candidates for reduced workflow hf_cand_bplus::FlagMcMatchGen, + hf_cand_bplus::ChannelMcMatchRec, hf_bplus_mc::PtTrack, hf_bplus_mc::YTrack, hf_bplus_mc::EtaTrack, @@ -687,6 +923,7 @@ namespace hf_cand_bplus_config DECLARE_SOA_COLUMN(MySelectionFlagD0, mySelectionFlagD0, int8_t); //! Flag to filter selected D0 mesons DECLARE_SOA_COLUMN(MySelectionFlagD0bar, mySelectionFlagD0bar, int8_t); //! Flag to filter selected D0 mesons DECLARE_SOA_COLUMN(MyInvMassWindowD0Pi, myInvMassWindowD0Pi, float); //! Half-width of the Bplus invariant-mass window in GeV/c2 +DECLARE_SOA_COLUMN(MyInvMassWindowJpsiK, myInvMassWindowJpsiK, float); //! Half-width of the Bplus invariant-mass window in GeV/c2 } // namespace hf_cand_bplus_config DECLARE_SOA_TABLE(HfCandBpConfigs, "AOD", "HFCANDBPCONFIG", //! Table with configurables information for reduced workflow @@ -694,6 +931,9 @@ DECLARE_SOA_TABLE(HfCandBpConfigs, "AOD", "HFCANDBPCONFIG", //! Table with confi hf_cand_bplus_config::MySelectionFlagD0bar, hf_cand_bplus_config::MyInvMassWindowD0Pi); +DECLARE_SOA_TABLE(HfCfgBpToJpsi, "AOD", "HFCFGBPTOJPSI", //! Table with configurables information for reduced workflow + hf_cand_bplus_config::MyInvMassWindowJpsiK); + namespace hf_bs_mc { // MC Rec @@ -726,6 +966,17 @@ DECLARE_SOA_TABLE(HfMcRecRedDsPis, "AOD", "HFMCRECREDDSPI", //! Table with recon hf_cand_bs::DebugMcRec, hf_bs_mc::PtMother); +// table with results of reconstruction level MC matching +DECLARE_SOA_TABLE(HfMcRecRedJPPhis, "AOD", "HFMCRECREDJPPHI", //! Table with reconstructed MC information on DsPi(<-Bs) pairs for reduced workflow + hf_cand_bs_reduced::JpsiId, + hf_cand_bs_reduced::Prong0PhiId, + hf_cand_bs_reduced::Prong1PhiId, + hf_cand_bs::FlagMcMatchRec, + hf_cand_bs::ChannelMcMatchRec, + hf_cand_bs::FlagWrongCollision, + hf_cand_bs::DebugMcRec, + hf_bs_mc::PtMother); + // try with extended table ? // DECLARE_SOA_EXTENDED_TABLE_USER(ExTable, Tracks, "EXTABLE", DECLARE_SOA_TABLE(HfMcCheckDsPis, "AOD", "HFMCCHECKDSPI", //! Table with reconstructed MC information on DsPi(<-Bs) pairs for MC checks in reduced workflow @@ -740,6 +991,7 @@ DECLARE_SOA_TABLE(HfMcCheckDsPis, "AOD", "HFMCCHECKDSPI", //! Table with reconst // Table with same size as HFCANDBS DECLARE_SOA_TABLE(HfMcRecRedBss, "AOD", "HFMCRECREDBS", //! Reconstruction-level MC information on Bs candidates for reduced workflow hf_cand_bs::FlagMcMatchRec, + hf_cand_bs::ChannelMcMatchRec, hf_cand_bs::FlagWrongCollision, hf_cand_bs::DebugMcRec, hf_bs_mc::PtMother); @@ -755,6 +1007,7 @@ DECLARE_SOA_TABLE(HfMcCheckBss, "AOD", "HFMCCHECKBS", //! Table with reconstruct DECLARE_SOA_TABLE(HfMcGenRedBss, "AOD", "HFMCGENREDBS", //! Generation-level MC information on Bs candidates for reduced workflow hf_cand_bs::FlagMcMatchGen, + hf_cand_bs::ChannelMcMatchRec, hf_bs_mc::PtTrack, hf_bs_mc::YTrack, hf_bs_mc::EtaTrack, @@ -769,14 +1022,17 @@ DECLARE_SOA_TABLE(HfMcGenRedBss, "AOD", "HFMCGENREDBS", //! Generation-level MC // so we can use them in the Bs part namespace hf_cand_bs_config { -DECLARE_SOA_COLUMN(MySelectionFlagD, mySelectionFlagD, int8_t); //! Flag to filter selected Ds mesons -DECLARE_SOA_COLUMN(MyInvMassWindowDPi, myInvMassWindowDPi, float); //! Half-width of the Bs invariant-mass window in GeV/c2 +DECLARE_SOA_COLUMN(MySelectionFlagD, mySelectionFlagD, int8_t); //! Flag to filter selected Ds mesons +DECLARE_SOA_COLUMN(MyInvMassWindowDPi, myInvMassWindowDPi, float); //! Half-width of the Bs invariant-mass window in GeV/c2 +DECLARE_SOA_COLUMN(MyInvMassWindowJpsiPhi, myInvMassWindowJpsiPhi, float); //! Half-width of the Bs invariant-mass window in GeV/c2 } // namespace hf_cand_bs_config DECLARE_SOA_TABLE(HfCandBsConfigs, "AOD", "HFCANDBSCONFIG", //! Table with configurables information for reduced workflow hf_cand_bs_config::MySelectionFlagD, hf_cand_bs_config::MyInvMassWindowDPi); +DECLARE_SOA_TABLE(HfCfgBsToJpsis, "AOD", "HFCFGBSTOJPSI", //! Table with configurables information for reduced workflow + hf_cand_bs_config::MyInvMassWindowJpsiPhi); namespace hf_lb_mc { // MC Rec @@ -1053,7 +1309,7 @@ DECLARE_SOA_COLUMN(DebugMcRec, debugMcRec, int8_t); // deb DECLARE_SOA_COLUMN(Origin, origin, int8_t); // Flag for origin of MC particle 1=promt, 2=FD DECLARE_SOA_COLUMN(SignD0, signD0, int8_t); // Sign of the D0 in the channels with D* -> D0 pi, needed in case of non-matched D* DECLARE_SOA_COLUMN(InvMassGen, invMassGen, float); //! Invariant mass at generation level in GeV/c2 -DECLARE_SOA_DYNAMIC_COLUMN(Pt, pt, //! +DECLARE_SOA_DYNAMIC_COLUMN(Pt, pt, //! [](float pxProng0, float pxProng1, float pyProng0, float pyProng1) -> float { return RecoDecay::pt((1.f * pxProng0 + 1.f * pxProng1), (1.f * pyProng0 + 1.f * pyProng1)); }); DECLARE_SOA_DYNAMIC_COLUMN(PtProng0, ptProng0, //! [](float pxProng0, float pyProng0) -> float { return RecoDecay::pt(pxProng0, pyProng0); }); diff --git a/PWGHF/D2H/TableProducer/CMakeLists.txt b/PWGHF/D2H/TableProducer/CMakeLists.txt index 928359768a9..a60ab1d78ab 100644 --- a/PWGHF/D2H/TableProducer/CMakeLists.txt +++ b/PWGHF/D2H/TableProducer/CMakeLists.txt @@ -11,6 +11,11 @@ # Candidate creators +o2physics_add_dpl_workflow(candidate-creator-b-to-jpsi-reduced + SOURCES candidateCreatorBToJpsiReduced.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::MLCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(candidate-creator-b0-reduced SOURCES candidateCreatorB0Reduced.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::DCAFitter @@ -70,6 +75,11 @@ o2physics_add_dpl_workflow(data-creator-charm-reso-reduced PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::EventFilteringUtils COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(data-creator-jpsi-had-reduced + SOURCES dataCreatorJpsiHadReduced.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::EventFilteringUtils + COMPONENT_NAME Analysis) + # Converters o2physics_add_dpl_workflow(converter-reduced-3-prongs-ml diff --git a/PWGHF/D2H/TableProducer/candidateCreatorB0Reduced.cxx b/PWGHF/D2H/TableProducer/candidateCreatorB0Reduced.cxx index 89562743ef4..6434b88e024 100644 --- a/PWGHF/D2H/TableProducer/candidateCreatorB0Reduced.cxx +++ b/PWGHF/D2H/TableProducer/candidateCreatorB0Reduced.cxx @@ -15,7 +15,13 @@ /// \author Alexandre Bigot , IPHC Strasbourg /// \author Fabrizio Grosa , CERN -#include +#include "PWGHF/D2H/DataModel/ReducedDataModel.h" +#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "PWGHF/Utils/utilsTrkCandHf.h" + +#include "Common/Core/trackUtilities.h" +#include "Common/DataModel/CollisionAssociationTables.h" #include "CommonConstants/PhysicsConstants.h" #include "DCAFitter/DCAFitterN.h" @@ -23,13 +29,7 @@ #include "Framework/runDataProcessing.h" #include "ReconstructionDataFormats/DCA.h" -#include "Common/Core/trackUtilities.h" -#include "Common/DataModel/CollisionAssociationTables.h" - -#include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" -#include "PWGHF/D2H/DataModel/ReducedDataModel.h" -#include "PWGHF/Utils/utilsTrkCandHf.h" +#include using namespace o2; using namespace o2::aod; @@ -203,7 +203,7 @@ struct HfCandidateCreatorB0Reduced { rowCandidateDmesMlScores(candD.mlScoreBkgMassHypo0(), candD.mlScorePromptMassHypo0(), candD.mlScoreNonpromptMassHypo0()); } } // pi loop - } // D loop + } // D loop } void processData(HfRedCollisionsWithExtras const& collisions, @@ -295,7 +295,7 @@ struct HfCandidateCreatorB0ReducedExpressions { if ((rowDPiMcRec.prong0Id() != candB0.prong0Id()) || (rowDPiMcRec.prong1Id() != candB0.prong1Id())) { continue; } - rowB0McRec(rowDPiMcRec.flagMcMatchRec(), rowDPiMcRec.flagWrongCollision(), rowDPiMcRec.debugMcRec(), rowDPiMcRec.ptMother()); + rowB0McRec(rowDPiMcRec.flagMcMatchRec(), -1 /*channel*/, rowDPiMcRec.flagWrongCollision(), rowDPiMcRec.debugMcRec(), rowDPiMcRec.ptMother()); filledMcInfo = true; if constexpr (checkDecayTypeMc) { rowB0McCheck(rowDPiMcRec.pdgCodeBeautyMother(), @@ -308,7 +308,7 @@ struct HfCandidateCreatorB0ReducedExpressions { break; } if (!filledMcInfo) { // protection to get same size tables in case something went wrong: we created a candidate that was not preselected in the D-Pi creator - rowB0McRec(0, -1, -1, -1.f); + rowB0McRec(0, -1, -1, -1, -1.f); if constexpr (checkDecayTypeMc) { rowB0McCheck(-1, -1, -1, -1, -1, -1); } diff --git a/PWGHF/D2H/TableProducer/candidateCreatorBToJpsiReduced.cxx b/PWGHF/D2H/TableProducer/candidateCreatorBToJpsiReduced.cxx new file mode 100644 index 00000000000..9fc5d845a04 --- /dev/null +++ b/PWGHF/D2H/TableProducer/candidateCreatorBToJpsiReduced.cxx @@ -0,0 +1,482 @@ +// 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 candidateCreatorBToJpsiReduced.cxx +/// \brief Reconstruction of B->J/Psi hadron candidates +/// +/// \author Fabrizio Chinu , Università degli Studi and INFN Torino +/// \author Fabrizio Grosa , CERN + +#include "PWGHF/D2H/DataModel/ReducedDataModel.h" +#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "PWGHF/Utils/utilsTrkCandHf.h" + +#include "Common/Core/RecoDecay.h" +#include "Common/Core/trackUtilities.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::aod; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::hf_trkcandsel; + +enum DecayChannel : uint8_t { + B0ToJpsiK0Star = 0, + BplusToJpsiK, + BsToJpsiPhi +}; + +/// Reconstruction of B+ candidates +struct HfCandidateCreatorBToJpsiReduced { + Produces rowCandidateBpBase; // table defined in CandidateReconstructionTables.h + Produces rowCandidateBpProngs; // table defined in ReducedDataModel.h + Produces rowCandidateBsBase; // table defined in CandidateReconstructionTables.h + Produces rowCandidateBsProngs; // table defined in ReducedDataModel.h + + // vertexing + Configurable propagateToPCA{"propagateToPCA", true, "create tracks version propagated to PCA"}; + Configurable useAbsDCA{"useAbsDCA", true, "Minimise abs. distance rather than chi2"}; + Configurable useWeightedFinalPCA{"useWeightedFinalPCA", false, "Recalculate vertex position using track covariances, effective only if useAbsDCA is true"}; + Configurable maxR{"maxR", 200., "reject PCA's above this radius"}; + Configurable maxDZIni{"maxDZIni", 4., "reject (if>0) PCA candidate if tracks DZ exceeds threshold"}; + Configurable minParamChange{"minParamChange", 1.e-3, "stop iterations if largest change of any B+ is smaller than this"}; + Configurable minRelChi2Change{"minRelChi2Change", 0.9, "stop iterations is chi2/chi2old > this"}; + + Configurable runJpsiToee{"runJpsiToee", false, "Run analysis for J/Psi to ee (debug)"}; + // selection + Configurable invMassWindowJpsiHadTolerance{"invMassWindowJpsiHadTolerance", 0.01, "invariant-mass window tolerance for J/Psi K pair preselections (GeV/c2)"}; + + float myInvMassWindowJpsiK{1.}, myInvMassWindowJpsiPhi{1.}; // variable that will store the value of invMassWindowJpsiK (defined in dataCreatorJpsiKReduced.cxx) + double massBplus{0.}, massBs{0.}; + double bz{0.}; + o2::vertexing::DCAFitterN<2> df2; // fitter for B vertex (2-prong vertex fitter) + o2::vertexing::DCAFitterN<3> df3; // fitter for B vertex (3-prong vertex fitter) + o2::vertexing::DCAFitterN<4> df4; // fitter for B vertex (4-prong vertex fitter) + + using HfRedCollisionsWithExtras = soa::Join; + + Preslice> candsJpsiPerCollision = hf_track_index_reduced::hfRedCollisionId; + Preslice> tracksLf0PerCollision = hf_track_index_reduced::hfRedCollisionId; + Preslice> tracksLf1PerCollision = hf_track_index_reduced::hfRedCollisionId; + + std::shared_ptr hCandidatesB, hCandidatesPhi; + o2::base::Propagator::MatCorrType noMatCorr = o2::base::Propagator::MatCorrType::USEMatCorrNONE; + HistogramRegistry registry{"registry"}; + + void init(InitContext const&) + { + // invariant-mass window cut + massBplus = o2::constants::physics::MassBPlus; + massBs = o2::constants::physics::MassBS; + + // Initialize fitters + df2.setPropagateToPCA(propagateToPCA); + df2.setMaxR(maxR); + df2.setMaxDZIni(maxDZIni); + df2.setMinParamChange(minParamChange); + df2.setMinRelChi2Change(minRelChi2Change); + df2.setUseAbsDCA(useAbsDCA); + df2.setWeightedFinalPCA(useWeightedFinalPCA); + df2.setMatCorrType(noMatCorr); + + df3.setPropagateToPCA(propagateToPCA); + df3.setMaxR(maxR); + df3.setMaxDZIni(maxDZIni); + df3.setMinParamChange(minParamChange); + df3.setMinRelChi2Change(minRelChi2Change); + df3.setUseAbsDCA(useAbsDCA); + df3.setWeightedFinalPCA(useWeightedFinalPCA); + df3.setMatCorrType(noMatCorr); + + df4.setPropagateToPCA(propagateToPCA); + df4.setMaxR(maxR); + df4.setMaxDZIni(maxDZIni); + df4.setMinParamChange(minParamChange); + df4.setMinRelChi2Change(minRelChi2Change); + df4.setUseAbsDCA(useAbsDCA); + df4.setWeightedFinalPCA(useWeightedFinalPCA); + df4.setMatCorrType(noMatCorr); + + // histograms + registry.add("hMassJpsi", "J/Psi mass;#it{M}_{#mu#mu} (GeV/#it{c}^{2});Counts", {HistType::kTH1F, {{600, 2.5, 3.7, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("hMassBplusToJpsiK", "2-prong candidates;inv. mass (B^{+} #rightarrow #overline{D^{0}}#pi^{#plus} #rightarrow #pi^{#minus}K^{#plus}#pi^{#plus}) (GeV/#it{c}^{2});entries", {HistType::kTH1F, {{500, 3., 8.}}}); + registry.add("hCovPVXX", "2-prong candidates;XX element of cov. matrix of prim. vtx. position (cm^{2});entries", {HistType::kTH1F, {{100, 0., 1.e-4}}}); + registry.add("hCovSVXX", "2-prong candidates;XX element of cov. matrix of sec. vtx. position (cm^{2});entries", {HistType::kTH1F, {{100, 0., 0.2}}}); + registry.add("hEvents", "Events;;entries", HistType::kTH1F, {{1, 0.5, 1.5}}); + + /// candidate monitoring + hCandidatesB = registry.add("hFitCandidatesJpsi", "candidates counter", {HistType::kTH1D, {axisCands}}); + hCandidatesPhi = registry.add("hFitCandidatesPhi", "candidates counter", {HistType::kTH1D, {axisCands}}); + setLabelHistoCands(hCandidatesB); + setLabelHistoCands(hCandidatesPhi); + } + + /// Main function to perform B+ candidate creation + /// \param collision the collision + /// \param candsJpsiThisColl J/Psi candidates in this collision + /// \param tracksLfThisCollisionArr LF tracks in this collision + /// \param invMass2JpsiHadMin minimum B invariant-mass + /// \param invMass2JpsiHadMax maximum B invariant-mass + template + void runCandidateCreation(Coll const& collision, + Cands const& candsJpsiThisColl, + TTracks0 const& tracksLfDau0ThisCollision, + TTracks1 const& tracksLfDau1ThisCollision, + const float invMass2JpsiHadMin, + const float invMass2JpsiHadMax) + { + auto primaryVertex = getPrimaryVertex(collision); + auto covMatrixPV = primaryVertex.getCov(); + + // Set the magnetic field from ccdb + bz = collision.bz(); + df2.setBz(bz); + df3.setBz(bz); + df4.setBz(bz); + + for (const auto& candJpsi : candsJpsiThisColl) { + o2::track::TrackParametrizationWithError trackPosParCov( + candJpsi.xDauPos(), candJpsi.alphaDauPos(), {candJpsi.yDauPos(), candJpsi.zDauPos(), candJpsi.snpDauPos(), candJpsi.tglDauPos(), candJpsi.signed1PtDauPos()}, 1 /*Charge*/, 1 /*Muon*/); + o2::track::TrackParametrizationWithError trackNegParCov( + candJpsi.xDauNeg(), candJpsi.alphaDauNeg(), {candJpsi.yDauNeg(), candJpsi.zDauNeg(), candJpsi.snpDauNeg(), candJpsi.tglDauNeg(), candJpsi.signed1PtDauNeg()}, -1 /*Charge*/, 1 /*Muon*/); + + // --------------------------------- + // reconstruct J/Psi candidate + o2::track::TrackParCov trackParCovJpsi{}; + std::array pVecJpsi{}; + registry.fill(HIST("hFitCandidatesJpsi"), SVFitting::BeforeFit); + try { + if (df2.process(trackPosParCov, trackNegParCov) == 0) { + LOG(info) << "DCAFitterN failed to reconstruct J/Psi candidate, skipping the candidate."; + continue; + } + } catch (const std::runtime_error& error) { + LOG(info) << "Run time error found: " << error.what() << ". DCAFitterN cannot work, skipping the candidate."; + registry.fill(HIST("hFitCandidatesJpsi"), SVFitting::Fail); + continue; + } + registry.fill(HIST("hFitCandidatesJpsi"), SVFitting::FitOk); + + std::array pVecDauPos{candJpsi.pxDauPos(), candJpsi.pyDauPos(), candJpsi.pzDauPos()}; + std::array pVecDauNeg{candJpsi.pxDauNeg(), candJpsi.pyDauNeg(), candJpsi.pzDauNeg()}; + + df2.getTrack(0).getPxPyPzGlo(pVecDauPos); + df2.getTrack(1).getPxPyPzGlo(pVecDauNeg); + pVecJpsi = RecoDecay::pVec(pVecDauPos, pVecDauNeg); + trackParCovJpsi = df2.createParentTrackParCov(); + trackParCovJpsi.setAbsCharge(0); // to be sure + + float invMassJpsi{0.f}; + if (runJpsiToee) { + invMassJpsi = RecoDecay::m2(std::array{pVecDauPos, pVecDauNeg}, std::array{o2::constants::physics::MassElectron, o2::constants::physics::MassElectron}); + } else { + invMassJpsi = RecoDecay::m2(std::array{pVecDauPos, pVecDauNeg}, std::array{o2::constants::physics::MassMuon, o2::constants::physics::MassMuon}); + } + invMassJpsi = std::sqrt(invMassJpsi); + registry.fill(HIST("hMassJpsi"), invMassJpsi); + + for (const auto& trackLf0 : tracksLfDau0ThisCollision) { + // this track is among daughters + if (trackLf0.trackId() == candJpsi.prongPosId() || trackLf0.trackId() == candJpsi.prongNegId()) { + continue; + } + auto trackParCovLf0 = getTrackParCov(trackLf0); + std::array pVecTrackLf0{}; + if constexpr (decChannel == DecayChannel::BplusToJpsiK) { + // --------------------------------- + // reconstruct the 3-prong B+ vertex + hCandidatesB->Fill(SVFitting::BeforeFit); + try { + if (df3.process(trackPosParCov, trackNegParCov, trackParCovLf0) == 0) { + continue; + } + } catch (const std::runtime_error& error) { + LOG(info) << "Run time error found: " << error.what() << ". DCAFitterN cannot work, skipping the candidate."; + hCandidatesB->Fill(SVFitting::Fail); + continue; + } + hCandidatesB->Fill(SVFitting::FitOk); + // JpsiK passed B+ reconstruction + + // calculate relevant properties + const auto& secondaryVertexBplus = df3.getPCACandidate(); + auto chi2PCA = df3.getChi2AtPCACandidate(); + auto covMatrixPCA = df3.calcPCACovMatrixFlat(); + registry.fill(HIST("hCovSVXX"), covMatrixPCA[0]); + registry.fill(HIST("hCovPVXX"), covMatrixPV[0]); + + // propagate Jpsi daugthers and K to the B+ vertex + df3.propagateTracksToVertex(); + // track.getPxPyPzGlo(pVec) modifies pVec of track + df3.getTrack(0).getPxPyPzGlo(pVecDauPos); // momentum of positive Jpsi daughter at the B+ vertex + df3.getTrack(1).getPxPyPzGlo(pVecDauNeg); // momentum of negative Jpsi daughter at the B+ vertex + df3.getTrack(2).getPxPyPzGlo(pVecTrackLf0); // momentum of K at the B+ vertex + + // compute invariant mass square and apply selection + auto invMass2JpsiK = RecoDecay::m2(std::array{pVecDauPos, pVecDauNeg, pVecTrackLf0}, std::array{o2::constants::physics::MassMuon, o2::constants::physics::MassMuon, o2::constants::physics::MassKPlus}); + if ((invMass2JpsiK < invMass2JpsiHadMin) || (invMass2JpsiK > invMass2JpsiHadMax)) { + continue; + } + registry.fill(HIST("hMassBplusToJpsiK"), std::sqrt(invMass2JpsiK)); + + // compute impact parameters of Jpsi and K + o2::dataformats::DCA dcaDauPos, dcaDauNeg, dcaKaon; + trackPosParCov.propagateToDCA(primaryVertex, bz, &dcaDauPos); + trackNegParCov.propagateToDCA(primaryVertex, bz, &dcaDauNeg); + trackParCovLf0.propagateToDCA(primaryVertex, bz, &dcaKaon); + + // get uncertainty of the decay length + double phi, theta; + // getPointDirection modifies phi and theta + getPointDirection(std::array{collision.posX(), collision.posY(), collision.posZ()}, secondaryVertexBplus, phi, theta); + auto errorDecayLength = std::sqrt(getRotatedCovMatrixXX(covMatrixPV, phi, theta) + getRotatedCovMatrixXX(covMatrixPCA, phi, theta)); + auto errorDecayLengthXY = std::sqrt(getRotatedCovMatrixXX(covMatrixPV, phi, 0.) + getRotatedCovMatrixXX(covMatrixPCA, phi, 0.)); + + // fill the candidate table for the B+ here: + rowCandidateBpBase(collision.globalIndex(), + collision.posX(), collision.posY(), collision.posZ(), + secondaryVertexBplus[0], secondaryVertexBplus[1], secondaryVertexBplus[2], + errorDecayLength, errorDecayLengthXY, + chi2PCA, + pVecDauPos[0], pVecDauPos[1], pVecDauPos[2], + pVecDauNeg[0], pVecDauNeg[1], pVecDauNeg[2], + pVecTrackLf0[0], pVecTrackLf0[1], pVecTrackLf0[2], + dcaDauPos.getY(), dcaDauNeg.getY(), dcaKaon.getY(), + std::sqrt(dcaDauPos.getSigmaY2()), std::sqrt(dcaDauNeg.getSigmaY2()), std::sqrt(dcaKaon.getSigmaY2())); + + rowCandidateBpProngs(candJpsi.globalIndex(), trackLf0.globalIndex()); + } else if constexpr (decChannel == DecayChannel::BsToJpsiPhi) { + for (const auto& trackLf1 : tracksLfDau1ThisCollision) { + // this track is among daughters + if (trackLf1.trackId() == candJpsi.prongPosId() || trackLf1.trackId() == candJpsi.prongNegId()) { + continue; + } + auto trackParCovLf1 = getTrackParCov(trackLf1); + std::array pVecTrackLf1 = trackLf1.pVector(); + + // --------------------------------- + // reconstruct the 4-prong Bs vertex + hCandidatesB->Fill(SVFitting::BeforeFit); + try { + if (df4.process(trackPosParCov, trackNegParCov, trackParCovLf0, trackParCovLf1) == 0) { + continue; + } + } catch (const std::runtime_error& error) { + LOG(info) << "Run time error found: " << error.what() << ". DCAFitterN cannot work, skipping the candidate."; + hCandidatesB->Fill(SVFitting::Fail); + continue; + } + hCandidatesB->Fill(SVFitting::FitOk); + // passed Bs reconstruction + + // calculate relevant properties + const auto& secondaryVertexBs = df4.getPCACandidate(); + auto chi2PCA = df4.getChi2AtPCACandidate(); + auto covMatrixPCA = df4.calcPCACovMatrixFlat(); + registry.fill(HIST("hCovSVXX"), covMatrixPCA[0]); + registry.fill(HIST("hCovPVXX"), covMatrixPV[0]); + + // propagate Jpsi and phi to the Bs vertex + df4.propagateTracksToVertex(); + // track.getPxPyPzGlo(pVec) modifies pVec of track + df4.getTrack(0).getPxPyPzGlo(pVecDauPos); // momentum of Jpsi at the B+ vertex + df4.getTrack(1).getPxPyPzGlo(pVecDauNeg); // momentum of Jpsi at the B+ vertex + df4.getTrack(2).getPxPyPzGlo(pVecTrackLf0); // momentum of K at the B+ vertex + df4.getTrack(3).getPxPyPzGlo(pVecTrackLf1); // momentum of K at the B+ vertex + + // compute invariant mass square and apply selection + auto invMass2JpsiPhi = RecoDecay::m2(std::array{pVecDauPos, pVecDauNeg, pVecTrackLf0, pVecTrackLf1}, std::array{o2::constants::physics::MassMuon, o2::constants::physics::MassMuon, o2::constants::physics::MassKPlus, o2::constants::physics::MassKPlus}); + if ((invMass2JpsiPhi < invMass2JpsiHadMin) || (invMass2JpsiPhi > invMass2JpsiHadMax)) { + continue; + } + registry.fill(HIST("hMassBplusToJpsiK"), std::sqrt(invMass2JpsiPhi)); + + // compute impact parameters of Jpsi and K + o2::dataformats::DCA dcaDauPos, dcaDauNeg, dcaTrackLf0, dcaTrackLf1; + trackPosParCov.propagateToDCA(primaryVertex, bz, &dcaDauPos); + trackNegParCov.propagateToDCA(primaryVertex, bz, &dcaDauNeg); + trackParCovLf0.propagateToDCA(primaryVertex, bz, &dcaTrackLf0); + trackParCovLf1.propagateToDCA(primaryVertex, bz, &dcaTrackLf1); + + // get uncertainty of the decay length + double phi, theta; + // getPointDirection modifies phi and theta + getPointDirection(std::array{collision.posX(), collision.posY(), collision.posZ()}, secondaryVertexBs, phi, theta); + auto errorDecayLength = std::sqrt(getRotatedCovMatrixXX(covMatrixPV, phi, theta) + getRotatedCovMatrixXX(covMatrixPCA, phi, theta)); + auto errorDecayLengthXY = std::sqrt(getRotatedCovMatrixXX(covMatrixPV, phi, 0.) + getRotatedCovMatrixXX(covMatrixPCA, phi, 0.)); + + // fill the candidate table for the Bs here: + rowCandidateBsBase(collision.globalIndex(), + collision.posX(), collision.posY(), collision.posZ(), + secondaryVertexBs[0], secondaryVertexBs[1], secondaryVertexBs[2], + errorDecayLength, errorDecayLengthXY, + chi2PCA, + pVecDauPos[0], pVecDauPos[1], pVecDauPos[2], + pVecDauNeg[0], pVecDauNeg[1], pVecDauPos[2], + pVecTrackLf0[0], pVecTrackLf0[1], pVecTrackLf0[2], + pVecTrackLf1[0], pVecTrackLf1[1], pVecTrackLf0[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()); + } + } + } // TrackLf0 loop + } // J/Psi loop + } // end runCandidateCreation + + void processDataBplus(HfRedCollisionsWithExtras const& collisions, + soa::Join const& candsJpsi, + soa::Join const& tracksKaon, + aod::HfOrigColCounts const& collisionsCounter, + aod::HfCfgBpToJpsi const& configs) + { + // Jpsi K invariant-mass window cut + for (const auto& config : configs) { + myInvMassWindowJpsiK = config.myInvMassWindowJpsiK(); + } + // invMassWindowJpsiHadTolerance is used to apply a slightly tighter cut than in JpsiK pair preselection + // to avoid accepting JpsiK pairs that were not formed in JpsiK pair creator + double invMass2JpsiKMin = (massBplus - myInvMassWindowJpsiK + invMassWindowJpsiHadTolerance) * (massBplus - myInvMassWindowJpsiK + invMassWindowJpsiHadTolerance); + double invMass2JpsiKMax = (massBplus + myInvMassWindowJpsiK - invMassWindowJpsiHadTolerance) * (massBplus + myInvMassWindowJpsiK - invMassWindowJpsiHadTolerance); + + for (const auto& collisionCounter : collisionsCounter) { + registry.fill(HIST("hEvents"), 1, collisionCounter.originalCollisionCount()); + } + + for (const auto& collision : collisions) { + auto thisCollId = collision.globalIndex(); + auto candsJpsiThisColl = candsJpsi.sliceBy(candsJpsiPerCollision, thisCollId); + auto tracksKaonThisCollision = tracksKaon.sliceBy(tracksLf0PerCollision, thisCollId); + runCandidateCreation(collision, candsJpsiThisColl, tracksKaonThisCollision, tracksKaonThisCollision, invMass2JpsiKMin, invMass2JpsiKMax); + } + } // processDataBplus + PROCESS_SWITCH(HfCandidateCreatorBToJpsiReduced, processDataBplus, "Process data for B+", true); + + void processDataBs(HfRedCollisionsWithExtras const& collisions, + soa::Join const& candsJpsi, + soa::Join const& tracksLfDau0, + soa::Join const& tracksLfDau1, + aod::HfOrigColCounts const& collisionsCounter, + aod::HfCfgBsToJpsis const& configs) + { + // Jpsi K invariant-mass window cut + for (const auto& config : configs) { + myInvMassWindowJpsiPhi = config.myInvMassWindowJpsiPhi(); + } + // invMassWindowJpsiHadTolerance is used to apply a slightly tighter cut than in JpsiK pair preselection + // to avoid accepting JpsiK pairs that were not formed in JpsiK pair creator + double invMass2JpsiKMin = (massBs - myInvMassWindowJpsiPhi + invMassWindowJpsiHadTolerance) * (massBs - myInvMassWindowJpsiPhi + invMassWindowJpsiHadTolerance); + double invMass2JpsiKMax = (massBs + myInvMassWindowJpsiPhi - invMassWindowJpsiHadTolerance) * (massBs + myInvMassWindowJpsiPhi - invMassWindowJpsiHadTolerance); + + for (const auto& collisionCounter : collisionsCounter) { + registry.fill(HIST("hEvents"), 1, collisionCounter.originalCollisionCount()); + } + + for (const auto& collision : collisions) { + auto thisCollId = collision.globalIndex(); + auto candsJpsiThisColl = candsJpsi.sliceBy(candsJpsiPerCollision, thisCollId); + auto tracksLf0ThisCollision = tracksLfDau0.sliceBy(tracksLf0PerCollision, thisCollId); + auto tracksLf1ThisCollision = tracksLfDau1.sliceBy(tracksLf1PerCollision, thisCollId); + runCandidateCreation(collision, candsJpsiThisColl, tracksLf0ThisCollision, tracksLf1ThisCollision, invMass2JpsiKMin, invMass2JpsiKMax); + } + } // processDataBs + PROCESS_SWITCH(HfCandidateCreatorBToJpsiReduced, processDataBs, "Process data for Bs", false); +}; // struct + +/// Extends the table base with expression columns and performs MC matching. +struct HfCandidateCreatorBToJpsiReducedExpressions { + Spawns rowCandidateBPlus; + Spawns rowCandidateBs; + Spawns rowTracksExt0; + Spawns rowTracksExt1; + Produces rowBplusMcRec; + Produces rowBsMcRec; + + /// Fill candidate information at MC reconstruction level + /// \param rowsJpsiHadMcRec MC reco information on Jpsi hadron pairs + /// \param candsBIds prong global indices of B candidates + template + void fillMcRec(McRec const& rowsJpsiHadMcRec, CCands const& candsBIds) + { + for (const auto& candB : candsBIds) { + bool filledMcInfo{false}; + if constexpr (decChannel == DecayChannel::BplusToJpsiK) { + for (const auto& rowJpsiHadMcRec : rowsJpsiHadMcRec) { + if ((rowJpsiHadMcRec.jpsiId() != candB.jpsiId()) || (rowJpsiHadMcRec.prong1Id() != candB.bachKaId())) { + continue; + } + rowBplusMcRec(rowJpsiHadMcRec.flagMcMatchRec(), rowJpsiHadMcRec.channelMcMatchRec(), rowJpsiHadMcRec.flagWrongCollision(), rowJpsiHadMcRec.debugMcRec(), rowJpsiHadMcRec.ptMother()); + filledMcInfo = true; + break; + } + if (!filledMcInfo) { // protection to get same size tables in case something went wrong: we created a candidate that was not preselected in the Jpsi-K creator + rowBplusMcRec(0, -1, -1, -1, -1.f); + } + } else if constexpr (decChannel == DecayChannel::BsToJpsiPhi) { + for (const auto& rowJpsiHadMcRec : rowsJpsiHadMcRec) { + if ((rowJpsiHadMcRec.jpsiId() != candB.jpsiId()) || (rowJpsiHadMcRec.prong0PhiId() != candB.prong0PhiId()) || (rowJpsiHadMcRec.prong1PhiId() != candB.prong1PhiId())) { + continue; + } + rowBsMcRec(rowJpsiHadMcRec.flagMcMatchRec(), rowJpsiHadMcRec.channelMcMatchRec(), rowJpsiHadMcRec.flagWrongCollision(), rowJpsiHadMcRec.debugMcRec(), rowJpsiHadMcRec.ptMother()); + filledMcInfo = true; + break; + } + if (!filledMcInfo) { // protection to get same size tables in case something went wrong: we created a candidate that was not preselected in the Jpsi-K creator + rowBsMcRec(0, -1, -1, -1, -1.f); + } + } + } + } + + void processMcBPlus(HfMcRecRedJPKs const& rowsJpsiKMcRec, HfRedBplus2JpsiDaus const& candsBplus) + { + fillMcRec(rowsJpsiKMcRec, candsBplus); + } + PROCESS_SWITCH(HfCandidateCreatorBToJpsiReducedExpressions, processMcBPlus, "Process MC", false); + + void processMcBs(HfMcRecRedJPPhis const& rowsJpsiPhiMcRec, HfRedBs2JpsiDaus const& Bs) + { + fillMcRec(rowsJpsiPhiMcRec, Bs); + } + PROCESS_SWITCH(HfCandidateCreatorBToJpsiReducedExpressions, processMcBs, "Process MC", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc), + adaptAnalysisTask(cfgc)}; +} diff --git a/PWGHF/D2H/TableProducer/candidateCreatorBplusReduced.cxx b/PWGHF/D2H/TableProducer/candidateCreatorBplusReduced.cxx index 3cd3e0f571b..bbd8f9df356 100644 --- a/PWGHF/D2H/TableProducer/candidateCreatorBplusReduced.cxx +++ b/PWGHF/D2H/TableProducer/candidateCreatorBplusReduced.cxx @@ -14,7 +14,13 @@ /// /// \author Antonio Palasciano , Università degli Studi di Bari -#include +#include "PWGHF/D2H/DataModel/ReducedDataModel.h" +#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "PWGHF/Utils/utilsTrkCandHf.h" + +#include "Common/Core/trackUtilities.h" +#include "Common/DataModel/CollisionAssociationTables.h" #include "CommonConstants/PhysicsConstants.h" #include "DCAFitter/DCAFitterN.h" @@ -23,13 +29,7 @@ #include "ReconstructionDataFormats/DCA.h" #include "ReconstructionDataFormats/V0.h" -#include "Common/Core/trackUtilities.h" -#include "Common/DataModel/CollisionAssociationTables.h" - -#include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" -#include "PWGHF/D2H/DataModel/ReducedDataModel.h" -#include "PWGHF/Utils/utilsTrkCandHf.h" +#include using namespace o2; using namespace o2::aod; @@ -293,7 +293,7 @@ struct HfCandidateCreatorBplusReducedExpressions { if ((rowD0PiMcRec.prong0Id() != candBplus.prong0Id()) || (rowD0PiMcRec.prong1Id() != candBplus.prong1Id())) { continue; } - rowBplusMcRec(rowD0PiMcRec.flagMcMatchRec(), rowD0PiMcRec.flagWrongCollision(), rowD0PiMcRec.debugMcRec(), rowD0PiMcRec.ptMother()); + rowBplusMcRec(rowD0PiMcRec.flagMcMatchRec(), -1 /*channel*/, rowD0PiMcRec.flagWrongCollision(), rowD0PiMcRec.debugMcRec(), rowD0PiMcRec.ptMother()); filledMcInfo = true; if constexpr (checkDecayTypeMc) { rowBplusMcCheck(rowD0PiMcRec.pdgCodeBeautyMother(), @@ -305,7 +305,7 @@ struct HfCandidateCreatorBplusReducedExpressions { break; } if (!filledMcInfo) { // protection to get same size tables in case something went wrong: we created a candidate that was not preselected in the D0-Pi creator - rowBplusMcRec(0, -1, -1, -1.f); + rowBplusMcRec(0, -1, -1, -1, -1.f); if constexpr (checkDecayTypeMc) { rowBplusMcCheck(-1, -1, -1, -1, -1); } diff --git a/PWGHF/D2H/TableProducer/candidateCreatorBsReduced.cxx b/PWGHF/D2H/TableProducer/candidateCreatorBsReduced.cxx index 7198796bc9b..a20adc78f7e 100644 --- a/PWGHF/D2H/TableProducer/candidateCreatorBsReduced.cxx +++ b/PWGHF/D2H/TableProducer/candidateCreatorBsReduced.cxx @@ -14,7 +14,13 @@ /// /// \author Fabio Catalano , CERN -#include +#include "PWGHF/D2H/DataModel/ReducedDataModel.h" +#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "PWGHF/Utils/utilsTrkCandHf.h" + +#include "Common/Core/trackUtilities.h" +#include "Common/DataModel/CollisionAssociationTables.h" #include "CommonConstants/PhysicsConstants.h" #include "DCAFitter/DCAFitterN.h" @@ -22,13 +28,7 @@ #include "Framework/runDataProcessing.h" #include "ReconstructionDataFormats/DCA.h" -#include "Common/Core/trackUtilities.h" -#include "Common/DataModel/CollisionAssociationTables.h" - -#include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" -#include "PWGHF/D2H/DataModel/ReducedDataModel.h" -#include "PWGHF/Utils/utilsTrkCandHf.h" +#include using namespace o2; using namespace o2::aod; @@ -292,7 +292,7 @@ struct HfCandidateCreatorBsReducedExpressions { if ((rowDPiMcRec.prong0Id() != candB.prong0Id()) || (rowDPiMcRec.prong1Id() != candB.prong1Id())) { continue; } - rowBsMcRec(rowDPiMcRec.flagMcMatchRec(), rowDPiMcRec.flagWrongCollision(), rowDPiMcRec.debugMcRec(), rowDPiMcRec.ptMother()); + rowBsMcRec(rowDPiMcRec.flagMcMatchRec(), -1 /*channel*/, rowDPiMcRec.flagWrongCollision(), rowDPiMcRec.debugMcRec(), rowDPiMcRec.ptMother()); filledMcInfo = true; if constexpr (checkDecayTypeMc) { rowBsMcCheck(rowDPiMcRec.pdgCodeBeautyMother(), @@ -305,7 +305,7 @@ struct HfCandidateCreatorBsReducedExpressions { break; } if (!filledMcInfo) { // protection to get same size tables in case something went wrong: we created a candidate that was not preselected in the DsPi creator - rowBsMcRec(0, -1, -1, -1.f); + rowBsMcRec(0, -1, -1, -1, -1.f); if constexpr (checkDecayTypeMc) { rowBsMcCheck(-1, -1, -1, -1, -1, -1); } diff --git a/PWGHF/D2H/TableProducer/dataCreatorCharmHadPiReduced.cxx b/PWGHF/D2H/TableProducer/dataCreatorCharmHadPiReduced.cxx index d03f8d9eda0..fde8c3b553e 100644 --- a/PWGHF/D2H/TableProducer/dataCreatorCharmHadPiReduced.cxx +++ b/PWGHF/D2H/TableProducer/dataCreatorCharmHadPiReduced.cxx @@ -18,24 +18,6 @@ /// \author Fabio Catalano , CERN /// \author Biao Zhang , Heidelberg University -#include -#include -#include -#include -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "DCAFitter/DCAFitterN.h" -#include "Framework/AnalysisTask.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/DCA.h" - -#include "Common/Core/trackUtilities.h" -#include "Common/DataModel/CollisionAssociationTables.h" -#include "Common/DataModel/Centrality.h" -#include "Common/DataModel/Qvectors.h" - #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/D2H/DataModel/ReducedDataModel.h" @@ -46,6 +28,24 @@ #include "PWGHF/Utils/utilsEvSelHf.h" #include "PWGHF/Utils/utilsTrkCandHf.h" +#include "Common/Core/trackUtilities.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/CollisionAssociationTables.h" +#include "Common/DataModel/Qvectors.h" + +#include "CommonConstants/PhysicsConstants.h" +#include "DCAFitter/DCAFitterN.h" +#include "Framework/AnalysisTask.h" +#include "Framework/O2DatabasePDGPlugin.h" +#include "Framework/runDataProcessing.h" +#include "ReconstructionDataFormats/DCA.h" + +#include +#include +#include +#include +#include + using namespace o2; using namespace o2::analysis; using namespace o2::aod; @@ -341,7 +341,7 @@ struct HfDataCreatorCharmHadPiReduced { return false; } // minimum pT and eta selection - if (trackParCovPion.getPt() < trackPionConfigurations.ptPionMin || std::abs(trackParCovPion.getEta()) > trackPionConfigurations.etaPionMax || !isSelectedTrackDCA(trackParCovPion, dcaPion)) { + if (trackParCovPion.getPt() < trackPionConfigurations.ptPionMin || std::abs(trackParCovPion.getEta()) > trackPionConfigurations.etaPionMax || !isSelectedTrackDCA(trackParCovPion, dcaPion, trackPionConfigurations.binsPtPion, trackPionConfigurations.cutsTrackPionDCA)) { return false; } // reject pions that are charm-hadron daughters @@ -354,27 +354,6 @@ struct HfDataCreatorCharmHadPiReduced { return true; } - /// Single-track cuts for pions on dcaXY - /// \param trackPar is the track parametrisation - /// \param dca is the 2-D array with track DCAs - /// \return true if track passes all cuts - template - bool isSelectedTrackDCA(const T1& trackPar, const T2& dca) - { - auto pTBinTrack = findBin(trackPionConfigurations.binsPtPion, trackPar.getPt()); - if (pTBinTrack == -1) { - return false; - } - - if (std::abs(dca[0]) < trackPionConfigurations.cutsTrackPionDCA->get(pTBinTrack, "min_dcaxytoprimary")) { - return false; // minimum DCAxy - } - if (std::abs(dca[0]) > trackPionConfigurations.cutsTrackPionDCA->get(pTBinTrack, "max_dcaxytoprimary")) { - return false; // maximum DCAxy - } - return true; - } - /// Calculates the index of the collision with the maximum number of contributions. ///\param collisions are the collisions to search through. ///\return The index of the collision with the maximum number of contributions. @@ -1332,7 +1311,7 @@ struct HfDataCreatorCharmHadPiReduced { yProngs[counter] = RecoDecay::y(daught.pVector(), pdg->Mass(daught.pdgCode())); counter++; } - rowHfB0McGenReduced(flag, ptParticle, yParticle, etaParticle, + rowHfB0McGenReduced(flag, -1 /*channel*/, ptParticle, yParticle, etaParticle, ptProngs[0], yProngs[0], etaProngs[0], ptProngs[1], yProngs[1], etaProngs[1]); } else if constexpr (decayChannel == DecayChannel::BsToDsminusPi) { @@ -1407,7 +1386,7 @@ struct HfDataCreatorCharmHadPiReduced { yProngs[counter] = RecoDecay::y(daught.pVector(), pdg->Mass(daught.pdgCode())); counter++; } - rowHfBsMcGenReduced(flag, ptParticle, yParticle, etaParticle, + rowHfBsMcGenReduced(flag, -1 /*channel*/, ptParticle, yParticle, etaParticle, ptProngs[0], yProngs[0], etaProngs[0], ptProngs[1], yProngs[1], etaProngs[1]); } else if constexpr (decayChannel == DecayChannel::BplusToD0barPi) { @@ -1440,7 +1419,7 @@ struct HfDataCreatorCharmHadPiReduced { yProngs[counter] = RecoDecay::y(daught.pVector(), pdg->Mass(daught.pdgCode())); counter++; } - rowHfBpMcGenReduced(flag, ptParticle, yParticle, etaParticle, + rowHfBpMcGenReduced(flag, -1 /*channel*/, ptParticle, yParticle, etaParticle, ptProngs[0], yProngs[0], etaProngs[0], ptProngs[1], yProngs[1], etaProngs[1]); } else if constexpr (decayChannel == DecayChannel::LbToLcplusPi) { diff --git a/PWGHF/D2H/TableProducer/dataCreatorJpsiHadReduced.cxx b/PWGHF/D2H/TableProducer/dataCreatorJpsiHadReduced.cxx new file mode 100644 index 00000000000..3a382d62dcf --- /dev/null +++ b/PWGHF/D2H/TableProducer/dataCreatorJpsiHadReduced.cxx @@ -0,0 +1,1120 @@ +// 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 dataCreatorJpsiHadReduced.cxx +/// \brief Creation of J/Psi-LF hadron pairs for Beauty hadron analyses +/// +/// \author Fabrizio Chinu , Università degli Studi and INFN Torino +/// \author Fabrizio Grosa , CERN + +#include "PWGHF/Core/CentralityEstimation.h" +#include "PWGHF/Core/DecayChannels.h" +#include "PWGHF/Core/HfHelper.h" +#include "PWGHF/Core/SelectorCuts.h" +#include "PWGHF/D2H/DataModel/ReducedDataModel.h" +#include "PWGHF/D2H/Utils/utilsRedDataFormat.h" +#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "PWGHF/Utils/utilsEvSelHf.h" +#include "PWGHF/Utils/utilsTrkCandHf.h" + +#include "Common/Core/RecoDecay.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 + +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace o2; +using namespace o2::analysis; +using namespace o2::aod; +using namespace o2::constants::physics; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::hf_trkcandsel; + +enum Event : uint8_t { // TODO: check if needed + Processed = 0, + NoCharmHadPiSelected, + CharmHadPiSelected, + NEvent +}; + +enum DecayChannel : uint8_t { + B0ToJpsiK0Star = 0, + BplusToJpsiK, + BsToJpsiPhi +}; + +enum WrongCollisionType : uint8_t { + None = 0, + WrongAssociation, + SplitCollision, +}; + +/// Creation of Jpsi-Had pairs for Beauty hadrons +struct HfDataCreatorJpsiHadReduced { + // Produces AOD tables to store track information + // collision related tables + Produces hfReducedCollision; + Produces hfReducedCollCentrality; + Produces hfReducedQvector; + Produces hfReducedCollExtra; + Produces hfCollisionCounter; + // J/Psi related tables + Produces hfJpsi; + Produces hfRedJpsiCov; + // Ka bachelor related tables + Produces hfTrackLfDau0; + Produces hfTrackCovLfDau0; + Produces hfTrackLfDau1; + Produces hfTrackCovLfDau1; + // MC related tables + Produces rowHfJpsiKMcRecReduced; + Produces rowHfJpsiPhiMcRecReduced; + Produces rowHfBpMcGenReduced; + Produces rowHfBsMcGenReduced; + + Produces rowCandidateConfigBplus; + Produces rowCandidateConfigBs; + + Configurable propagateToPCA{"propagateToPCA", true, "create tracks version propagated to PCA"}; + Configurable useAbsDCA{"useAbsDCA", false, "Minimise abs. distance rather than chi2"}; + Configurable useWeightedFinalPCA{"useWeightedFinalPCA", false, "Recalculate vertex position using track covariances, effective only if useAbsDCA is true"}; + Configurable maxR{"maxR", 200., "reject PCA's above this radius"}; + Configurable maxDZIni{"maxDZIni", 4., "reject (if>0) PCA candidate if tracks DZ exceeds threshold"}; + Configurable minParamChange{"minParamChange", 1.e-3, "stop iterations if largest change of any B0 is smaller than this"}; + Configurable minRelChi2Change{"minRelChi2Change", 0.9, "stop iterations is chi2/chi2old > this"}; + + Configurable runJpsiToee{"runJpsiToee", false, "Run analysis for J/Psi to ee (debug)"}; + Configurable ptJpsiMin{"ptJpsiMin", 0., "Lower bound of J/Psi pT"}; + Configurable ptJpsiMax{"ptJpsiMax", 50., "Upper bound of J/Psi pT"}; + Configurable useTrackIsGlobalTrackWoDCA{"useTrackIsGlobalTrackWoDCA", true, "check isGlobalTrackWoDCA status for the bachelor tracks"}; + Configurable ptTrackMin{"ptTrackMin", 0.5, "minimum bachelor track pT threshold (GeV/c)"}; + Configurable absEtaTrackMax{"absEtaTrackMax", 0.8, "maximum bachelor track absolute eta threshold"}; + Configurable> binsPtTrack{"binsPtTrack", std::vector{hf_cuts_single_track::vecBinsPtTrack}, "track pT bin limits for bachelor track DCA XY pT-dependent cut"}; + Configurable> cutsTrackDCA{"cutsTrackDCA", {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 selections per pT bin for bachelor track"}; + // topological/kinematic cuts + Configurable> binsPt{"binsPt", std::vector{hf_cuts_jpsi_to_mu_mu::vecBinsPt}, "J/Psi pT bin limits"}; + Configurable> cuts{"cuts", {hf_cuts_jpsi_to_mu_mu::Cuts[0], hf_cuts_jpsi_to_mu_mu::NBinsPt, hf_cuts_jpsi_to_mu_mu::NCutVars, hf_cuts_jpsi_to_mu_mu::labelsPt, hf_cuts_jpsi_to_mu_mu::labelsCutVar}, "J/Psi candidate selection per pT bin"}; + Configurable invMassWindowJpsiHad{"invMassWindowJpsiHad", 0.3, "invariant-mass window for Jpsi-Had pair preselections (GeV/c2)"}; + Configurable deltaMPhiMax{"deltaMPhiMax", 0.02, "invariant-mass window for phi preselections (GeV/c2) (only for Bs->J/PsiPhi)"}; + Configurable cpaMin{"cpaMin", 0., "Minimum cosine of pointing angle for B candidates"}; + Configurable decLenMin{"decLenMin", 0., "Minimum decay length for B candidates"}; + + // magnetic field setting from CCDB + Configurable ccdbUrl{"ccdbUrl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable ccdbPathGrpMag{"ccdbPathGrpMag", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object (Run 3)"}; + + HfHelper hfHelper; + + // CCDB service + Service ccdb; + // O2DatabasePDG service + Service pdg; + + using TracksPid = soa::Join; + using TracksPidWithSel = soa::Join; + using TracksSel = soa::Join; + using TracksPidWithSelAndMc = soa::Join; + using CollisionsWCMcLabels = soa::Join; + + Preslice candsJpsiPerCollision = aod::track_association::collisionId; + Preslice trackIndicesPerCollision = aod::track_association::collisionId; + PresliceUnsorted colPerMcCollision = aod::mccollisionlabel::mcCollisionId; + + o2::base::Propagator::MatCorrType noMatCorr = o2::base::Propagator::MatCorrType::USEMatCorrNONE; + int runNumber; + double bz{0.}; + double invMass2JpsiHadMin, invMass2JpsiHadMax; + bool isHfCandBhadConfigFilled = false; + + o2::hf_evsel::HfEventSelection hfEvSel; + o2::vertexing::DCAFitterN<2> df2; + o2::vertexing::DCAFitterN<3> df3; + o2::vertexing::DCAFitterN<4> df4; + + HistogramRegistry registry{"registry"}; + + void init(InitContext const&) + { + std::array doProcess = {doprocessJpsiKData, doprocessJpsiKMc, doprocessJpsiPhiData, doprocessJpsiPhiMc}; + if (std::accumulate(doProcess.begin(), doProcess.end(), 0) != 1) { + LOGP(fatal, "One and only one process function can be enabled at a time, please fix your configuration!"); + } + + // Set up the histogram registry + constexpr int kNBinsSelections = 2 + aod::SelectionStep::RecoTopol; + std::string labels[kNBinsSelections]; + labels[0] = "No selection"; + labels[1 + aod::SelectionStep::RecoSkims] = "Skims selection"; + labels[1 + aod::SelectionStep::RecoTopol] = "Skims & Topological selections"; + static const AxisSpec axisSelections = {kNBinsSelections, 0.5, kNBinsSelections + 0.5, ""}; + registry.add("hSelectionsJpsi", "J/Psi selection;;#it{p}_{T} (GeV/#it{c})", {HistType::kTH2F, {axisSelections, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); + for (int iBin = 0; iBin < kNBinsSelections; ++iBin) { + registry.get(HIST("hSelectionsJpsi"))->GetXaxis()->SetBinLabel(iBin + 1, labels[iBin].data()); + } + + constexpr int kNBinsEvents = NEvent; + std::string labelsEvents[kNBinsEvents]; + labelsEvents[Event::Processed] = "processed"; + labelsEvents[Event::NoCharmHadPiSelected] = "without CharmHad-Pi pairs"; + labelsEvents[Event::CharmHadPiSelected] = "with CharmHad-Pi pairs"; + static const AxisSpec axisEvents = {kNBinsEvents, 0.5, kNBinsEvents + 0.5, ""}; + registry.add("hEvents", "Events;;entries", HistType::kTH1F, {axisEvents}); + for (int iBin = 0; iBin < kNBinsEvents; iBin++) { + registry.get(HIST("hEvents"))->GetXaxis()->SetBinLabel(iBin + 1, labelsEvents[iBin].data()); + } + + registry.add("hMassJpsi", "J/Psi mass;#it{M}_{#mu#mu} (GeV/#it{c}^{2});Counts", {HistType::kTH1F, {{600, 2.8, 3.4, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("hPtJpsi", "J/Psi #it{p}_{T};#it{p}_{T} (GeV/#it{c});Counts", {HistType::kTH1F, {{(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("hCpaJpsi", "J/Psi cos#theta_{p};J/Psi cos#theta_{p};Counts", {HistType::kTH1F, {{200, -1., 1, "J/Psi cos#theta_{p}"}}}); + std::shared_ptr hFitCandidatesJpsi = registry.add("hFitCandidatesJpsi", "Jpsi candidate counter", {HistType::kTH1D, {axisCands}}); + std::shared_ptr hFitCandidatesBPlus = registry.add("hFitCandidatesBPlus", "hFitCandidatesBPlus candidate counter", {HistType::kTH1D, {axisCands}}); + std::shared_ptr hFitCandidatesBS = registry.add("hFitCandidatesBS", "hFitCandidatesBS candidate counter", {HistType::kTH1D, {axisCands}}); + setLabelHistoCands(hFitCandidatesJpsi); + setLabelHistoCands(hFitCandidatesBPlus); + setLabelHistoCands(hFitCandidatesBS); + if (doprocessJpsiKData || doprocessJpsiKMc) { + registry.add("hPtKaon", "Kaon #it{p}_{T};#it{p}_{T} (GeV/#it{c});Counts", {HistType::kTH1F, {{100, 0., 10.}}}); + registry.add("hMassJpsiKaon", "J/Psi Kaon mass;#it{M}_{J/#PsiK} (GeV/#it{c}^{2});Counts", {HistType::kTH1F, {{800, 4.9, 5.7}}}); + } else if (doprocessJpsiPhiData || doprocessJpsiPhiMc) { + registry.add("hPtPhi", "Phi #it{p}_{T};#it{p}_{T} (GeV/#it{c});Counts", {HistType::kTH1F, {{100, 0., 10.}}}); + registry.add("hMassPhi", "Phi mass;#it{M}_{KK} (GeV/#it{c}^{2});Counts", {HistType::kTH1F, {{200, 0.9, 1.2}}}); + registry.add("hMassJpsiPhi", "J/Psi Phi mass;#it{M}_{J/#Psi#phi} (GeV/#it{c}^{2});Counts", {HistType::kTH1F, {{800, 4.9, 5.7}}}); + std::shared_ptr hFitCandidatesPhi = registry.add("hFitCandidatesPhi", "Phi candidate counter", {HistType::kTH1D, {axisCands}}); + setLabelHistoCands(hFitCandidatesPhi); + } + + df2.setPropagateToPCA(propagateToPCA); + df2.setMaxR(maxR); + df2.setMaxDZIni(maxDZIni); + df2.setMinParamChange(minParamChange); + df2.setMinRelChi2Change(minRelChi2Change); + df2.setUseAbsDCA(useAbsDCA); + df2.setWeightedFinalPCA(useWeightedFinalPCA); + df2.setMatCorrType(noMatCorr); + + df3.setPropagateToPCA(propagateToPCA); + df3.setMaxR(maxR); + df3.setMaxDZIni(maxDZIni); + df3.setMinParamChange(minParamChange); + df3.setMinRelChi2Change(minRelChi2Change); + df3.setUseAbsDCA(useAbsDCA); + df3.setWeightedFinalPCA(useWeightedFinalPCA); + df3.setMatCorrType(noMatCorr); + + df4.setPropagateToPCA(propagateToPCA); + df4.setMaxR(maxR); + df4.setMaxDZIni(maxDZIni); + df4.setMinParamChange(minParamChange); + df4.setMinRelChi2Change(minRelChi2Change); + df4.setUseAbsDCA(useAbsDCA); + df4.setWeightedFinalPCA(useWeightedFinalPCA); + df4.setMatCorrType(noMatCorr); + + // Configure CCDB access + ccdb->setURL(ccdbUrl); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + runNumber = 0; + + if (doprocessJpsiKData || doprocessJpsiKMc) { + invMass2JpsiHadMin = (MassBPlus - invMassWindowJpsiHad) * (MassBPlus - invMassWindowJpsiHad); + invMass2JpsiHadMax = (MassBPlus + invMassWindowJpsiHad) * (MassBPlus + invMassWindowJpsiHad); + } else if (doprocessJpsiPhiData || doprocessJpsiPhiMc) { + invMass2JpsiHadMin = (MassBS - invMassWindowJpsiHad) * (MassBS - invMassWindowJpsiHad); + invMass2JpsiHadMax = (MassBS + invMassWindowJpsiHad) * (MassBS + invMassWindowJpsiHad); + } + } + + /// Topological cuts + /// \param candidate is candidate + /// \param trackPos is the positive track + /// \param trackNeg is the negative track + /// \return true if candidate passes all cuts + template + bool selectionTopol(const T1& candidate, const T2& trackPos, const T2& trackNeg) + { + auto candpT = candidate.pt(); + auto candInvMass = runJpsiToee ? hfHelper.invMassJpsiToEE(candidate) : hfHelper.invMassJpsiToMuMu(candidate); + auto pseudoPropDecLen = candidate.decayLengthXY() * candInvMass / candpT; + auto pTBin = findBin(binsPt, candpT); + if (pTBin == -1) { + return false; + } + + // check that the candidate pT is within the analysis range + if (candpT < ptJpsiMin || candpT >= ptJpsiMax) { + return false; + } + + // cut on μ+ μ− (e+e−) invariant mass + if (std::abs(candInvMass - o2::constants::physics::MassJPsi) > cuts->get(pTBin, "m")) { + return false; + } + + // cut on daughter pT (same cut used for both channels) + if (trackNeg.pt() < cuts->get(pTBin, "pT mu") || trackPos.pt() < cuts->get(pTBin, "pT mu")) { + return false; + } + + // decay length + if (candidate.decayLength() < cuts->get(pTBin, "decay length")) { + return false; + } + + // decay length in XY plane + if (candidate.decayLengthXY() < cuts->get(pTBin, "decay length xy")) { + return false; + } + + // cosine of pointing angle + if (candidate.cpa() < cuts->get(pTBin, "cpa")) { + return false; + } + + // cosine of pointing angle XY + if (candidate.cpaXY() < cuts->get(pTBin, "cpa xy")) { + return false; + } + + // product of daughter impact parameters + if (candidate.impactParameterProduct() > cuts->get(pTBin, "d0xd0")) { + return false; + } + + // pseudoproper decay length + if (pseudoPropDecLen < cuts->get(pTBin, "pseudoprop. decay length")) { + return false; + } + + return true; + } + + /// Kaon selection (J/Psi K+ <-- B+) + /// \param track is the considered track + /// \param trackParCov is the track parametrisation + /// \param dca is the 2-D array with track DCAs + /// \param jPsiDautracks J/Psi daughter tracks + /// \return true if track passes all cuts + template + bool isTrackSelected(const T1& track, const T2& trackParCov, const T3& dca, const std::vector& jPsiDautracks) + { + // check isGlobalTrackWoDCA status for kaons if wanted + if (useTrackIsGlobalTrackWoDCA && !track.isGlobalTrackWoDCA()) { + return false; + } + // minimum pT, eta, and DCA selection + if (trackParCov.getPt() < ptTrackMin || std::abs(trackParCov.getEta()) > absEtaTrackMax || !isSelectedTrackDCA(trackParCov, dca, binsPtTrack, cutsTrackDCA)) { + return false; + } + // reject kaons that are J/Psi daughters + for (const auto& trackJpsi : jPsiDautracks) { + if (track.globalIndex() == trackJpsi.globalIndex()) { + return false; + } + } + + return true; + } + + /// B meson preselections + /// \param momentum is the B meson momentum + /// \param secondaryVertex is the reconstructed secondary vertex + /// \param collision is the reconstructed collision + template + bool isBSelected(const T1& momentum, const T2& secondaryVertex, const T3& collision) + { + // B candidate CPA + if (RecoDecay::cpa(std::array{collision.posX(), collision.posY(), collision.posZ()}, secondaryVertex, momentum) < cpaMin) { + return false; + } + + // B candidate decay length + if (RecoDecay::distance(std::array{collision.posX(), collision.posY(), collision.posZ()}, secondaryVertex) < decLenMin) { + return false; + } + + return true; + } + + /// Checks if the B meson is associated with a different collision than the one it was generated in + /// \param particleMother is the mother particle + /// \param collision is the reconstructed collision + /// \param indexCollisionMaxNumContrib is the index of the collision associated with a given MC collision with the largest number of contributors. + /// \param flagWrongCollision is the flag indicating if whether the associated collision is incorrect. + template + void checkWrongCollision(const PParticle& particleMother, + const CColl& collision, + const int64_t& indexCollisionMaxNumContrib, + int8_t& flagWrongCollision) + { + + if (particleMother.mcCollision().globalIndex() != collision.mcCollisionId()) { + flagWrongCollision = WrongCollisionType::WrongAssociation; + } else { + if (collision.globalIndex() != indexCollisionMaxNumContrib) { + flagWrongCollision = WrongCollisionType::SplitCollision; + } + } + } + + /// Function for filling MC reco information in the tables + /// \param particlesMc is the table with MC particles + /// \param vecDaughtersB is the vector with all daughter tracks (Jpsi daughters in first position) + /// \param indexHfCandJpsi is the index of the Jpsi candidate + /// \param selectedTracksBach is the map with the indices of selected bachelor pion tracks + template + void fillMcRecoInfo(const CColl& collision, + const PParticles& particlesMc, + const std::vector& vecDaughtersB, + int& indexHfCandJpsi, + std::array, 2> selectedTracksBach, + const int64_t indexCollisionMaxNumContrib) + { + + // we check the MC matching to be stored + int8_t sign{0}, flag{0}, channel{0}; + int8_t flagWrongCollision{WrongCollisionType::None}; + int8_t debug{0}; + float motherPt{-1.f}; + + if constexpr (decChannel == DecayChannel::BplusToJpsiK) { + // B+ → J/Psi K+ → (µ+µ-) K+ + int indexRec = -1; + if (!runJpsiToee) { + indexRec = RecoDecay::getMatchedMCRec(particlesMc, std::array{vecDaughtersB[0], vecDaughtersB[1], vecDaughtersB[2]}, Pdg::kBPlus, std::array{-kMuonMinus, +kMuonMinus, +kKPlus}, true, &sign, 3); + } else { + indexRec = RecoDecay::getMatchedMCRec(particlesMc, std::array{vecDaughtersB[0], vecDaughtersB[1], vecDaughtersB[2]}, Pdg::kBPlus, std::array{-kElectron, +kElectron, +kKPlus}, true, &sign, 3); + } + if (indexRec > -1) { + // J/Psi → µ+µ- + if (!runJpsiToee) { + indexRec = RecoDecay::getMatchedMCRec(particlesMc, std::array{vecDaughtersB[0], vecDaughtersB[1]}, Pdg::kJPsi, std::array{-kMuonMinus, +kMuonMinus}, true); + } else { + indexRec = RecoDecay::getMatchedMCRec(particlesMc, std::array{vecDaughtersB[0], vecDaughtersB[1]}, Pdg::kJPsi, std::array{-kElectron, +kElectron}, true); + } + if (indexRec > -1) { + flag = sign * o2::hf_decay::hf_cand_beauty::BplusToJpsiK; + } else { + debug = 1; + LOGF(debug, "B+ decays in the expected final state but the condition on the intermediate state is not fulfilled"); + } + + auto indexMother = RecoDecay::getMother(particlesMc, vecDaughtersB.back().template mcParticle_as(), Pdg::kBPlus, true); + if (indexMother >= 0) { + auto particleMother = particlesMc.rawIteratorAt(indexMother); + motherPt = particleMother.pt(); + checkWrongCollision(particleMother, collision, indexCollisionMaxNumContrib, flagWrongCollision); + } + } + rowHfJpsiKMcRecReduced(indexHfCandJpsi, selectedTracksBach[0][vecDaughtersB.back().globalIndex()], flag, channel, flagWrongCollision, debug, motherPt); + } else if constexpr (decChannel == DecayChannel::BsToJpsiPhi) { + // Bs → J/Psi phi → (µ+µ-) (K+K-) + int indexRec = -1; + if (!runJpsiToee) { + indexRec = RecoDecay::getMatchedMCRec(particlesMc, std::array{vecDaughtersB[0], vecDaughtersB[1], vecDaughtersB[2], vecDaughtersB[3]}, Pdg::kBS, std::array{-kMuonMinus, +kMuonMinus, +kKPlus, -kKPlus}, true, &sign, 4); + } else { + indexRec = RecoDecay::getMatchedMCRec(particlesMc, std::array{vecDaughtersB[0], vecDaughtersB[1], vecDaughtersB[2], vecDaughtersB[3]}, Pdg::kBS, std::array{-kElectron, +kElectron, +kKPlus, -kKPlus}, true, &sign, 4); + } + if (indexRec > -1) { + // J/Psi → µ+µ- + if (!runJpsiToee) { + indexRec = RecoDecay::getMatchedMCRec(particlesMc, std::array{vecDaughtersB[0], vecDaughtersB[1]}, Pdg::kJPsi, std::array{-kMuonMinus, +kMuonMinus}, true, &sign, 1); + } else { + indexRec = RecoDecay::getMatchedMCRec(particlesMc, std::array{vecDaughtersB[0], vecDaughtersB[1]}, Pdg::kJPsi, std::array{-kElectron, +kElectron}, true, &sign, 1); + } + if (indexRec > -1) { + flag = sign * o2::hf_decay::hf_cand_beauty::BsToJpsiKK; + indexRec = RecoDecay::getMatchedMCRec(particlesMc, std::array{vecDaughtersB[2], vecDaughtersB[3]}, Pdg::kPhi, std::array{-kKPlus, +kKPlus}, true, &sign, 1); + if (indexRec > -1) { + channel = o2::hf_decay::hf_cand_beauty::BsToJpsiPhi; + } else { + debug = 1; + LOGF(debug, "Bs decays in the expected final state but the condition on the phi intermediate state is not fulfilled"); + } + } else { + debug = 1; + LOGF(debug, "Bs decays in the expected final state but the condition on the J/Psi intermediate state is not fulfilled"); + } + + auto indexMother = RecoDecay::getMother(particlesMc, vecDaughtersB.back().template mcParticle_as(), Pdg::kBS, true); + if (indexMother >= 0) { + auto particleMother = particlesMc.rawIteratorAt(indexMother); + motherPt = particleMother.pt(); + checkWrongCollision(particleMother, collision, indexCollisionMaxNumContrib, flagWrongCollision); + } + } + rowHfJpsiPhiMcRecReduced(indexHfCandJpsi, selectedTracksBach[0][vecDaughtersB.back().globalIndex()], selectedTracksBach[1][vecDaughtersB.back().globalIndex()], flag, channel, flagWrongCollision, debug, motherPt); + } + } + + /// Calculates the index of the collision with the maximum number of contributions. + ///\param collisions are the collisions to search through. + ///\return The index of the collision with the maximum number of contributions. + template + int64_t getIndexCollisionMaxNumContrib(const CColl& collisions) + { + unsigned maxNumContrib = 0; + int64_t indexCollisionMaxNumContrib = -1; + for (const auto& collision : collisions) { + if (collision.numContrib() > maxNumContrib) { + maxNumContrib = collision.numContrib(); + indexCollisionMaxNumContrib = collision.globalIndex(); + } + } + return indexCollisionMaxNumContrib; + } + + template + void runMcGen(aod::McParticles const& particlesMc) + { + // Match generated particles. + for (const auto& particle : particlesMc) { + int8_t sign{0}, flag{0}, channel{0}; + if constexpr (decChannel == DecayChannel::BplusToJpsiK) { + // B+ → J/Psi K+ → (µ+µ-) K+ + if (RecoDecay::isMatchedMCGen(particlesMc, particle, Pdg::kBPlus, std::array{static_cast(Pdg::kJPsi), +kKPlus}, true, &sign)) { + // Match J/Psi -> µ+µ- + auto candJpsiMC = particlesMc.rawIteratorAt(particle.daughtersIds().front()); + // Printf("Checking J/Psi -> µ+µ-"); + if (!runJpsiToee) { + if (RecoDecay::isMatchedMCGen(particlesMc, candJpsiMC, static_cast(Pdg::kJPsi), std::array{-kMuonMinus, +kMuonMinus}, true)) { + flag = sign * o2::hf_decay::hf_cand_beauty::BplusToJpsiK; + } + } else { // debug + // Printf("Checking J/Psi -> e+e-"); + if (RecoDecay::isMatchedMCGen(particlesMc, candJpsiMC, static_cast(Pdg::kJPsi), std::array{-kElectron, +kElectron}, true)) { + flag = sign * o2::hf_decay::hf_cand_beauty::BplusToJpsiK; + } + } + } + + // save information for B+ task + if (std::abs(flag) != o2::hf_decay::hf_cand_beauty::BplusToJpsiK) { + continue; + } + + auto ptParticle = particle.pt(); + auto yParticle = RecoDecay::y(particle.pVector(), MassBPlus); + auto etaParticle = particle.eta(); + + std::array ptProngs; + std::array yProngs; + std::array etaProngs; + int counter = 0; + for (const auto& daught : particle.daughters_as()) { + ptProngs[counter] = daught.pt(); + etaProngs[counter] = daught.eta(); + yProngs[counter] = RecoDecay::y(daught.pVector(), pdg->Mass(daught.pdgCode())); + counter++; + } + rowHfBpMcGenReduced(flag, channel, ptParticle, yParticle, etaParticle, + ptProngs[0], yProngs[0], etaProngs[0], + ptProngs[1], yProngs[1], etaProngs[1]); + } else if constexpr (decChannel == DecayChannel::BsToJpsiPhi) { + // Bs → J/Psi phi → (µ+µ-) (K+K-) + if (RecoDecay::isMatchedMCGen(particlesMc, particle, Pdg::kBS, std::array{static_cast(Pdg::kJPsi), +kKPlus, -kKPlus}, true, &sign, 2)) { + // Match J/Psi -> µ+µ- and phi -> K+K- + auto candJpsiMC = particlesMc.rawIteratorAt(particle.daughtersIds().front()); + auto candPhiMC = particlesMc.rawIteratorAt(particle.daughtersIds().back()); + // Printf("Checking J/Psi -> µ+µ- and phi -> K+K-"); + if (runJpsiToee && RecoDecay::isMatchedMCGen(particlesMc, candJpsiMC, static_cast(Pdg::kJPsi), std::array{-kElectron, +kElectron}, true)) { + flag = sign * o2::hf_decay::hf_cand_beauty::BsToJpsiKK; + } else if (!runJpsiToee && RecoDecay::isMatchedMCGen(particlesMc, candJpsiMC, static_cast(Pdg::kJPsi), std::array{-kMuonMinus, +kMuonMinus}, true)) { + flag = sign * o2::hf_decay::hf_cand_beauty::BsToJpsiKK; + } + // Check phi -> K+K- + if (RecoDecay::isMatchedMCGen(particlesMc, candPhiMC, static_cast(Pdg::kPhi), std::array{-kKPlus, +kKPlus}, true)) { + channel = o2::hf_decay::hf_cand_beauty::BsToJpsiPhi; + } + } + + // save information for Bs task + if (std::abs(flag) != o2::hf_decay::hf_cand_beauty::BsToJpsiKK) { + continue; + } + + auto ptParticle = particle.pt(); + auto yParticle = RecoDecay::y(particle.pVector(), MassBPlus); + auto etaParticle = particle.eta(); + + std::array ptProngs; + std::array yProngs; + std::array etaProngs; + int counter = 0; + for (const auto& daught : particle.daughters_as()) { + ptProngs[counter] = daught.pt(); + etaProngs[counter] = daught.eta(); + yProngs[counter] = RecoDecay::y(daught.pVector(), pdg->Mass(daught.pdgCode())); + counter++; + } + rowHfBsMcGenReduced(flag, channel, ptParticle, yParticle, etaParticle, + ptProngs[0], yProngs[0], etaProngs[0], + ptProngs[1], yProngs[1], etaProngs[1]); + } + } // gen + } + + // Jpsi candidate selection + template + void runDataCreation(Coll const& collision, + JpsiCands const& candsJpsi, + aod::TrackAssoc const& trackIndices, + TTracks const&, + PParticles const& particlesMc, + uint64_t const& indexCollisionMaxNumContrib, + aod::BCsWithTimestamps const&) + { + + // helpers for ReducedTables filling + int indexHfReducedCollision = hfReducedCollision.lastIndex() + 1; + // std::map where the key is the track.globalIndex() and + // the value is the track index in the table of the selected tracks + std::map selectedTracksBach; + std::map selectedTracksBach2; // for the second daughter (for B0 and Bs) + + bool fillHfReducedCollision = false; + + auto primaryVertex = getPrimaryVertex(collision); + + // Set the magnetic field from ccdb. + // The static instance of the propagator was already modified in the HFTrackIndexSkimCreator, + // but this is not true when running on Run2 data/MC already converted into AO2Ds. + auto bc = collision.template bc_as(); + if (runNumber != bc.runNumber()) { + LOG(info) << ">>>>>>>>>>>> Current run number: " << runNumber; + o2::parameters::GRPMagField* grpo = ccdb->getForTimeStamp(ccdbPathGrpMag, bc.timestamp()); + if (grpo == nullptr) { + LOGF(fatal, "Run 3 GRP object (type o2::parameters::GRPMagField) is not available in CCDB for run=%d at timestamp=%llu", bc.runNumber(), bc.timestamp()); + } + o2::base::Propagator::initFieldFromGRP(grpo); + bz = o2::base::Propagator::Instance()->getNominalBz(); + LOG(info) << ">>>>>>>>>>>> Magnetic field: " << bz; + runNumber = bc.runNumber(); + } + df2.setBz(bz); + df3.setBz(bz); + df4.setBz(bz); + + auto thisCollId = collision.globalIndex(); + // looping over 2-prong candidates + for (const auto& candidate : candsJpsi) { + + // Apply the selections on the J/Psi candidates + registry.fill(HIST("hSelectionsJpsi"), 1, candidate.pt()); + + if (!(candidate.hfflag() & 1 << aod::hf_cand_2prong::DecayType::JpsiToMuMu)) { + continue; + } + registry.fill(HIST("hSelectionsJpsi"), 2 + aod::SelectionStep::RecoSkims, candidate.pt()); + + auto trackPos = candidate.template prong0_as(); // positive daughter + auto trackNeg = candidate.template prong1_as(); // negative daughter + + auto trackPosParCov = getTrackParCov(trackPos); + auto trackNegParCov = getTrackParCov(trackNeg); + + std::vector jPsiDauTracks{trackPos, trackNeg}; + + auto dca0 = o2::dataformats::DCA(jPsiDauTracks[0].dcaXY(), jPsiDauTracks[0].dcaZ(), jPsiDauTracks[0].cYY(), jPsiDauTracks[0].cZY(), jPsiDauTracks[0].cZZ()); + auto dca1 = o2::dataformats::DCA(jPsiDauTracks[1].dcaXY(), jPsiDauTracks[1].dcaZ(), jPsiDauTracks[1].cYY(), jPsiDauTracks[1].cZY(), jPsiDauTracks[1].cZZ()); + + // repropagate tracks to this collision if needed + if (jPsiDauTracks[0].collisionId() != thisCollId) { + trackPosParCov.propagateToDCA(primaryVertex, bz, &dca0); + } + + if (jPsiDauTracks[1].collisionId() != thisCollId) { + trackNegParCov.propagateToDCA(primaryVertex, bz, &dca1); + } + + // --------------------------------- + // reconstruct J/Psi candidate secondary vertex + o2::track::TrackParCov trackParCovJpsi{}; + std::array pVecJpsi{}; + registry.fill(HIST("hFitCandidatesJpsi"), SVFitting::BeforeFit); + try { + if (df2.process(trackPosParCov, trackNegParCov) == 0) { + continue; + } + } catch (const std::runtime_error& error) { + LOG(info) << "Run time error found: " << error.what() << ". DCAFitterN cannot work, skipping the candidate."; + registry.fill(HIST("hFitCandidatesJpsi"), SVFitting::Fail); + continue; + } + registry.fill(HIST("hFitCandidatesJpsi"), SVFitting::FitOk); + + // topological selection + if (!selectionTopol(candidate, trackPos, trackNeg)) { + continue; + } + registry.fill(HIST("hSelectionsJpsi"), 2 + aod::SelectionStep::RecoTopol, candidate.pt()); + + int indexHfCandJpsi = hfJpsi.lastIndex() + 1; + float invMassJpsi{0.f}; + if (runJpsiToee) { + invMassJpsi = hfHelper.invMassJpsiToEE(candidate); + } else { + invMassJpsi = hfHelper.invMassJpsiToMuMu(candidate); + } + registry.fill(HIST("hMassJpsi"), invMassJpsi); + registry.fill(HIST("hPtJpsi"), candidate.pt()); + registry.fill(HIST("hCpaJpsi"), candidate.cpa()); + + bool fillHfCandJpsi = false; + + // TODO: add single track information (min eta, min ITS/TPC clusters, etc.) + double invMass2JpsiHad{0.}; + for (const auto& trackId : trackIndices) { + auto trackBach = trackId.template track_as(); + + // apply selections on bachelor tracks + auto trackParCovBach = getTrackParCov(trackBach); + std::array dcaBach{trackBach.dcaXY(), trackBach.dcaZ()}; + std::array pVecBach = trackBach.pVector(); + if (trackBach.collisionId() != thisCollId) { + o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, trackParCovBach, 2.f, noMatCorr, &dcaBach); + getPxPyPz(trackParCovBach, pVecBach); + } + + // apply selections on bachelor tracks + if (!isTrackSelected(trackBach, trackParCovBach, dcaBach, jPsiDauTracks)) { + continue; + } + + if constexpr (decChannel == DecayChannel::BplusToJpsiK) { + registry.fill(HIST("hPtKaon"), trackParCovBach.getPt()); + // compute invariant mass square and apply selection + invMass2JpsiHad = RecoDecay::m2(std::array{pVecJpsi, pVecBach}, std::array{MassJPsi, MassKPlus}); + if ((invMass2JpsiHad < invMass2JpsiHadMin) || (invMass2JpsiHad > invMass2JpsiHadMax)) { + continue; + } + registry.fill(HIST("hMassJpsiKaon"), std::sqrt(invMass2JpsiHad)); + + registry.fill(HIST("hFitCandidatesBPlus"), SVFitting::BeforeFit); + try { + if (df3.process(trackPosParCov, trackNegParCov, trackParCovBach) == 0) { + continue; + } + } catch (const std::runtime_error& error) { + LOG(info) << "Run time error found: " << error.what() << ". DCAFitterN cannot work, skipping the candidate."; + registry.fill(HIST("hFitCandidatesBPlus"), SVFitting::Fail); + continue; + } + registry.fill(HIST("hFitCandidatesBPlus"), SVFitting::FitOk); + + o2::track::TrackParCov trackParCovBPlus{}; + std::array pVecBPlus{}, pVec0{}, pVec1{}, pVec2{}; + + auto secondaryVertexBPlus = df3.getPCACandidate(); + df3.propagateTracksToVertex(); + df3.getTrack(0).getPxPyPzGlo(pVec0); + df3.getTrack(1).getPxPyPzGlo(pVec1); + df3.getTrack(2).getPxPyPzGlo(pVec2); + pVecBPlus = RecoDecay::pVec(pVec0, pVec1, pVec2); + trackParCovBPlus = df3.createParentTrackParCov(); + trackParCovBPlus.setAbsCharge(0); // to be sure + + if (!isBSelected(pVecBPlus, secondaryVertexBPlus, collision)) { + continue; + } + + // fill Kaon tracks table + // if information on track already stored, go to next track + if (!selectedTracksBach.count(trackBach.globalIndex())) { + hfTrackLfDau0(trackBach.globalIndex(), indexHfReducedCollision, + trackParCovBach.getX(), trackParCovBach.getAlpha(), + trackParCovBach.getY(), trackParCovBach.getZ(), trackParCovBach.getSnp(), + trackParCovBach.getTgl(), trackParCovBach.getQ2Pt(), + trackBach.itsNCls(), trackBach.tpcNClsCrossedRows(), trackBach.tpcChi2NCl(), + trackBach.hasTPC(), trackBach.hasTOF(), + trackBach.tpcNSigmaPi(), trackBach.tofNSigmaPi(), + trackBach.tpcNSigmaKa(), trackBach.tofNSigmaKa(), + trackBach.tpcNSigmaPr(), trackBach.tofNSigmaPr()); + hfTrackCovLfDau0(trackParCovBach.getSigmaY2(), trackParCovBach.getSigmaZY(), trackParCovBach.getSigmaZ2(), + trackParCovBach.getSigmaSnpY(), trackParCovBach.getSigmaSnpZ(), + trackParCovBach.getSigmaSnp2(), trackParCovBach.getSigmaTglY(), trackParCovBach.getSigmaTglZ(), + trackParCovBach.getSigmaTglSnp(), trackParCovBach.getSigmaTgl2(), + trackParCovBach.getSigma1PtY(), trackParCovBach.getSigma1PtZ(), trackParCovBach.getSigma1PtSnp(), + trackParCovBach.getSigma1PtTgl(), trackParCovBach.getSigma1Pt2()); + // add trackBach.globalIndex() to a list + // to keep memory of the pions filled in the table and avoid refilling them if they are paired to another Jpsi candidate + // and keep track of their index in hfTrackLfDau0 for McRec purposes + selectedTracksBach[trackBach.globalIndex()] = hfTrackLfDau0.lastIndex(); + } + + if constexpr (doMc) { + std::vector beautyHadDauTracks{}; + for (const auto& track : jPsiDauTracks) { + beautyHadDauTracks.push_back(track); + } + beautyHadDauTracks.push_back(trackBach); + fillMcRecoInfo(collision, particlesMc, beautyHadDauTracks, indexHfCandJpsi, std::array, 2>{selectedTracksBach}, indexCollisionMaxNumContrib); + } + fillHfCandJpsi = true; + } else if constexpr (decChannel == DecayChannel::BsToJpsiPhi) { + for (auto trackBachId2 = trackId + 1; trackBachId2 != trackIndices.end(); ++trackBachId2) { + auto trackBach2 = trackBachId2.template track_as(); + auto trackBach2ParCov = getTrackParCov(trackBach2); + + std::array dcaBach2{trackBach2.dcaXY(), trackBach2.dcaZ()}; + std::array pVecBach2 = trackBach2.pVector(); + if (trackBach2.collisionId() != thisCollId) { + o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, trackBach2ParCov, 2.f, noMatCorr, &dcaBach2); + getPxPyPz(trackBach2ParCov, pVecBach2); + } + + // apply selections on bachelor tracks + if (!isTrackSelected(trackBach2, trackBach2ParCov, dcaBach2, jPsiDauTracks)) { + continue; + } + std::array pVec2{trackBach.pVector()}, pVec3{trackBach2.pVector()}; + auto invMassPhi = RecoDecay::m(std::array{pVec2, pVec3}, std::array{MassKPlus, MassKPlus}); + + if (std::abs(invMassPhi - MassPhi) > deltaMPhiMax) { + continue; + } + + // --------------------------------- + // reconstruct Bs candidate secondary vertex + + registry.fill(HIST("hFitCandidatesBS"), SVFitting::BeforeFit); + try { + if (df4.process(trackPosParCov, trackNegParCov, trackParCovBach, trackBach2ParCov) == 0) { + continue; + } + } catch (const std::runtime_error& error) { + LOG(info) << "Run time error found: " << error.what() << ". DCAFitterN cannot work, skipping the candidate."; + registry.fill(HIST("hFitCandidatesBS"), SVFitting::Fail); + continue; + } + registry.fill(HIST("hFitCandidatesBS"), SVFitting::FitOk); + + o2::track::TrackParCov trackParCovBS{}; + std::array pVecBS{}, pVec0{}, pVec1{}, pVecPhi{}; + + auto secondaryVertexBS = df4.getPCACandidate(); + df4.propagateTracksToVertex(); + df4.getTrack(0).getPxPyPzGlo(pVec0); + df4.getTrack(1).getPxPyPzGlo(pVec1); + df4.getTrack(2).getPxPyPzGlo(pVec2); + df4.getTrack(3).getPxPyPzGlo(pVec3); + pVecBS = RecoDecay::pVec(pVec0, pVec1, pVec2, pVec3); + pVecPhi = RecoDecay::pVec(pVec2, pVec3); + trackParCovBS = df4.createParentTrackParCov(); + trackParCovBS.setAbsCharge(0); // to be sure + + if (!isBSelected(pVecBS, secondaryVertexBS, collision)) { + continue; + } + + registry.fill(HIST("hPtPhi"), RecoDecay::pt(pVecBach, pVecBach2)); + registry.fill(HIST("hMassPhi"), RecoDecay::m(std::array{pVecBach, pVecBach2}, std::array{MassKPlus, MassKPlus})); + invMass2JpsiHad = RecoDecay::m2(std::array{pVecJpsi, pVecPhi}, std::array{MassJPsi, MassPhi}); + if ((invMass2JpsiHad < invMass2JpsiHadMin) || (invMass2JpsiHad > invMass2JpsiHadMax)) { + continue; + } + registry.fill(HIST("hMassJpsiPhi"), std::sqrt(invMass2JpsiHad)); + + // fill daughter tracks table + // if information on track already stored, go to next track + if (!selectedTracksBach.count(trackBach.globalIndex())) { + hfTrackLfDau0(trackBach.globalIndex(), indexHfReducedCollision, + trackParCovBach.getX(), trackParCovBach.getAlpha(), + trackParCovBach.getY(), trackParCovBach.getZ(), trackParCovBach.getSnp(), + trackParCovBach.getTgl(), trackParCovBach.getQ2Pt(), + trackBach.itsNCls(), trackBach.tpcNClsCrossedRows(), trackBach.tpcChi2NCl(), + trackBach.hasTPC(), trackBach.hasTOF(), + trackBach.tpcNSigmaPi(), trackBach.tofNSigmaPi(), + trackBach.tpcNSigmaKa(), trackBach.tofNSigmaKa(), + trackBach.tpcNSigmaPr(), trackBach.tofNSigmaPr()); + hfTrackCovLfDau0(trackParCovBach.getSigmaY2(), trackParCovBach.getSigmaZY(), trackParCovBach.getSigmaZ2(), + trackParCovBach.getSigmaSnpY(), trackParCovBach.getSigmaSnpZ(), + trackParCovBach.getSigmaSnp2(), trackParCovBach.getSigmaTglY(), trackParCovBach.getSigmaTglZ(), + trackParCovBach.getSigmaTglSnp(), trackParCovBach.getSigmaTgl2(), + trackParCovBach.getSigma1PtY(), trackParCovBach.getSigma1PtZ(), trackParCovBach.getSigma1PtSnp(), + trackParCovBach.getSigma1PtTgl(), trackParCovBach.getSigma1Pt2()); + // add trackBach.globalIndex() to a list + // to keep memory of the pions filled in the table and avoid refilling them if they are paired to another Jpsi candidate + // and keep track of their index in hfTrackLfDau0 for McRec purposes + selectedTracksBach[trackBach.globalIndex()] = hfTrackLfDau0.lastIndex(); + } + + // fill daughter tracks table + // if information on track already stored, go to next track + if (!selectedTracksBach2.count(trackBach2.globalIndex())) { + hfTrackLfDau1(trackBach2.globalIndex(), indexHfReducedCollision, + trackBach2ParCov.getX(), trackBach2ParCov.getAlpha(), + trackBach2ParCov.getY(), trackBach2ParCov.getZ(), trackBach2ParCov.getSnp(), + trackBach2ParCov.getTgl(), trackBach2ParCov.getQ2Pt(), + trackBach2.itsNCls(), trackBach2.tpcNClsCrossedRows(), trackBach2.tpcChi2NCl(), + trackBach2.hasTPC(), trackBach2.hasTOF(), + trackBach2.tpcNSigmaPi(), trackBach2.tofNSigmaPi(), + trackBach2.tpcNSigmaKa(), trackBach2.tofNSigmaKa(), + trackBach2.tpcNSigmaPr(), trackBach2.tofNSigmaPr()); + hfTrackCovLfDau1(trackBach2ParCov.getSigmaY2(), trackBach2ParCov.getSigmaZY(), trackBach2ParCov.getSigmaZ2(), + trackBach2ParCov.getSigmaSnpY(), trackBach2ParCov.getSigmaSnpZ(), + trackBach2ParCov.getSigmaSnp2(), trackBach2ParCov.getSigmaTglY(), trackBach2ParCov.getSigmaTglZ(), + trackBach2ParCov.getSigmaTglSnp(), trackBach2ParCov.getSigmaTgl2(), + trackBach2ParCov.getSigma1PtY(), trackBach2ParCov.getSigma1PtZ(), trackBach2ParCov.getSigma1PtSnp(), + trackBach2ParCov.getSigma1PtTgl(), trackBach2ParCov.getSigma1Pt2()); + // add trackBach2.globalIndex() to a list + // to keep memory of the pions filled in the table and avoid refilling them if they are paired to another Jpsi candidate + // and keep track of their index in hfTrackLfDau1 for McRec purposes + selectedTracksBach2[trackBach2.globalIndex()] = hfTrackLfDau1.lastIndex(); + } + + if constexpr (doMc) { + std::vector beautyHadDauTracks{}; + for (const auto& track : jPsiDauTracks) { + beautyHadDauTracks.push_back(track); + } + beautyHadDauTracks.push_back(trackBach); + fillMcRecoInfo(collision, particlesMc, beautyHadDauTracks, indexHfCandJpsi, std::array, 2>{selectedTracksBach, selectedTracksBach2}, indexCollisionMaxNumContrib); + } + fillHfCandJpsi = true; + } + } + } // kaon loop + if (fillHfCandJpsi) { // fill Jpsi table only once per Jpsi candidate + double invMassJpsi{0.}; + if (runJpsiToee) { + invMassJpsi = hfHelper.invMassJpsiToEE(candidate); + } else { + invMassJpsi = hfHelper.invMassJpsiToMuMu(candidate); + } + hfJpsi(trackPos.globalIndex(), trackNeg.globalIndex(), + indexHfReducedCollision, + candidate.xSecondaryVertex(), candidate.ySecondaryVertex(), candidate.zSecondaryVertex(), + invMassJpsi, + trackPosParCov.getX(), trackNegParCov.getX(), + trackPosParCov.getY(), trackNegParCov.getY(), + trackPosParCov.getZ(), trackNegParCov.getZ(), + trackPosParCov.getAlpha(), trackNegParCov.getAlpha(), + trackPosParCov.getSnp(), trackNegParCov.getSnp(), + trackPosParCov.getTgl(), trackNegParCov.getTgl(), + trackPosParCov.getQ2Pt(), trackNegParCov.getQ2Pt()); // Q/pT + hfRedJpsiCov(trackPosParCov.getSigmaY2(), trackNegParCov.getSigmaY2(), + trackPosParCov.getSigmaZY(), trackNegParCov.getSigmaZY(), + trackPosParCov.getSigmaZ2(), trackNegParCov.getSigmaZ2(), + trackPosParCov.getSigmaSnpY(), trackNegParCov.getSigmaSnpY(), + trackPosParCov.getSigmaSnpZ(), trackNegParCov.getSigmaSnpZ(), + trackPosParCov.getSigmaSnp2(), trackNegParCov.getSigmaSnp2(), + trackPosParCov.getSigmaTglY(), trackNegParCov.getSigmaTglY(), + trackPosParCov.getSigmaTglZ(), trackNegParCov.getSigmaTglZ(), + trackPosParCov.getSigmaTglSnp(), trackNegParCov.getSigmaTglSnp(), + trackPosParCov.getSigmaTgl2(), trackNegParCov.getSigmaTgl2(), + trackPosParCov.getSigma1PtY(), trackNegParCov.getSigma1PtY(), + trackPosParCov.getSigma1PtZ(), trackNegParCov.getSigma1PtZ(), + trackPosParCov.getSigma1PtSnp(), trackNegParCov.getSigma1PtSnp(), + trackPosParCov.getSigma1PtTgl(), trackNegParCov.getSigma1PtTgl(), + trackPosParCov.getSigma1Pt2(), trackNegParCov.getSigma1Pt2()); + fillHfReducedCollision = true; + } + } // candsJpsi loop + + registry.fill(HIST("hEvents"), 1 + Event::Processed); + if (!fillHfReducedCollision) { + registry.fill(HIST("hEvents"), 1 + Event::NoCharmHadPiSelected); + return; + } + registry.fill(HIST("hEvents"), 1 + Event::CharmHadPiSelected); + float centrality = -1.f; + uint16_t hfRejMap = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb, registry); + // fill collision table if it contains a J/Psi K pair at minimum + hfReducedCollision(collision.posX(), collision.posY(), collision.posZ(), collision.numContrib(), hfRejMap, bz); + hfReducedCollExtra(collision.covXX(), collision.covXY(), collision.covYY(), + collision.covXZ(), collision.covYZ(), collision.covZZ()); + // hfReducedCollCentrality(collision.centFT0C(), collision.centFT0M(), collision.trackOccupancyInTimeRange(), collision.ft0cOccupancyInTimeRange()); // TODO: add + // if constexpr (withQvec) { + // hfReducedQvector(collision.qvecFT0CRe(), collision.qvecFT0CIm(), collision.sumAmplFT0C(), + // collision.qvecFT0ARe(), collision.qvecFT0AIm(), collision.sumAmplFT0A(), + // collision.qvecFT0MRe(), collision.qvecFT0MIm(), collision.sumAmplFT0M(), + // collision.qvecTPCposRe(), collision.qvecTPCposIm(), collision.nTrkTPCpos(), + // collision.qvecTPCnegRe(), collision.qvecTPCnegIm(), collision.nTrkTPCneg(), + // collision.qvecTPCallRe(), collision.qvecTPCallIm(), collision.nTrkTPCall()); + // } + } + + void processJpsiKData(soa::Join const& collisions, + aod::HfCand2ProngWPid const& candsJpsi, + aod::TrackAssoc const& trackIndices, + TracksPidWithSel const& tracks, + aod::BCsWithTimestamps const& bcs) + { + // store configurables needed for B0 workflow + if (!isHfCandBhadConfigFilled) { + rowCandidateConfigBplus(invMassWindowJpsiHad.value); + isHfCandBhadConfigFilled = true; + } + + int zvtxColl{0}; + int sel8Coll{0}; + int zvtxAndSel8Coll{0}; + int zvtxAndSel8CollAndSoftTrig{0}; + int allSelColl{0}; + for (const auto& collision : collisions) { + o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); + + auto thisCollId = collision.globalIndex(); + auto candsJpsiThisColl = candsJpsi.sliceBy(candsJpsiPerCollision, thisCollId); + auto trackIdsThisCollision = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); + runDataCreation(collision, candsJpsiThisColl, trackIdsThisCollision, tracks, tracks, -1, bcs); + } + // handle normalization by the right number of collisions + hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); + } + PROCESS_SWITCH(HfDataCreatorJpsiHadReduced, processJpsiKData, "Process J/Psi K without MC info", true); + + void processJpsiPhiData(soa::Join const& collisions, + aod::HfCand2ProngWPid const& candsJpsi, + aod::TrackAssoc const& trackIndices, + TracksPidWithSel const& tracks, + aod::BCsWithTimestamps const& bcs) + { + // store configurables needed for B0 workflow + if (!isHfCandBhadConfigFilled) { + rowCandidateConfigBs(invMassWindowJpsiHad.value); + isHfCandBhadConfigFilled = true; + } + + int zvtxColl{0}; + int sel8Coll{0}; + int zvtxAndSel8Coll{0}; + int zvtxAndSel8CollAndSoftTrig{0}; + int allSelColl{0}; + for (const auto& collision : collisions) { + o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); + + auto thisCollId = collision.globalIndex(); + auto candsJpsiThisColl = candsJpsi.sliceBy(candsJpsiPerCollision, thisCollId); + auto trackIdsThisCollision = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); + runDataCreation(collision, candsJpsiThisColl, trackIdsThisCollision, tracks, tracks, -1, bcs); + } + // handle normalization by the right number of collisions + hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); + } + PROCESS_SWITCH(HfDataCreatorJpsiHadReduced, processJpsiPhiData, "Process J/Psi phi without MC info", false); + + void processJpsiKMc(CollisionsWCMcLabels const& collisions, + aod::HfCand2ProngWPid const& candsJpsi, + aod::TrackAssoc const& trackIndices, + TracksPidWithSelAndMc const& tracks, + aod::McParticles const& particlesMc, + aod::BCsWithTimestamps const& bcs, + McCollisions const&) + { + // store configurables needed for B+ workflow + if (!isHfCandBhadConfigFilled) { + rowCandidateConfigBplus(invMassWindowJpsiHad.value); + isHfCandBhadConfigFilled = true; + } + + int zvtxColl{0}; + int sel8Coll{0}; + int zvtxAndSel8Coll{0}; + int zvtxAndSel8CollAndSoftTrig{0}; + int allSelColl{0}; + for (const auto& collision : collisions) { + o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); + + auto thisCollId = collision.globalIndex(); + auto candsJpsiThisColl = candsJpsi.sliceBy(candsJpsiPerCollision, thisCollId); + auto trackIdsThisCollision = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); + auto collsSameMcCollision = collisions.sliceBy(colPerMcCollision, collision.mcCollisionId()); + int64_t indexCollisionMaxNumContrib = getIndexCollisionMaxNumContrib(collsSameMcCollision); + runDataCreation(collision, candsJpsiThisColl, trackIdsThisCollision, tracks, particlesMc, indexCollisionMaxNumContrib, bcs); + } + // handle normalization by the right number of collisions + hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); + runMcGen(particlesMc); + } + PROCESS_SWITCH(HfDataCreatorJpsiHadReduced, processJpsiKMc, "Process J/Psi K with MC info", false); + + void processJpsiPhiMc(CollisionsWCMcLabels const& collisions, + aod::HfCand2ProngWPid const& candsJpsi, + aod::TrackAssoc const& trackIndices, + TracksPidWithSelAndMc const& tracks, + aod::McParticles const& particlesMc, + aod::BCsWithTimestamps const& bcs, + McCollisions const&) + { + // store configurables needed for B+ workflow + if (!isHfCandBhadConfigFilled) { + rowCandidateConfigBs(invMassWindowJpsiHad.value); + isHfCandBhadConfigFilled = true; + } + + int zvtxColl{0}; + int sel8Coll{0}; + int zvtxAndSel8Coll{0}; + int zvtxAndSel8CollAndSoftTrig{0}; + int allSelColl{0}; + for (const auto& collision : collisions) { + o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); + + auto thisCollId = collision.globalIndex(); + auto candsJpsiThisColl = candsJpsi.sliceBy(candsJpsiPerCollision, thisCollId); + auto trackIdsThisCollision = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); + auto collsSameMcCollision = collisions.sliceBy(colPerMcCollision, collision.mcCollisionId()); + int64_t indexCollisionMaxNumContrib = getIndexCollisionMaxNumContrib(collsSameMcCollision); + runDataCreation(collision, candsJpsiThisColl, trackIdsThisCollision, tracks, particlesMc, indexCollisionMaxNumContrib, bcs); + } + // handle normalization by the right number of collisions + hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); + runMcGen(particlesMc); + } + PROCESS_SWITCH(HfDataCreatorJpsiHadReduced, processJpsiPhiMc, "Process J/Psi phi with MC info", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} diff --git a/PWGHF/D2H/Tasks/CMakeLists.txt b/PWGHF/D2H/Tasks/CMakeLists.txt index 52019c9227e..53b22dfe969 100644 --- a/PWGHF/D2H/Tasks/CMakeLists.txt +++ b/PWGHF/D2H/Tasks/CMakeLists.txt @@ -29,11 +29,21 @@ o2physics_add_dpl_workflow(task-bplus-reduced PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(task-bplus-to-jpsi-k-reduced + SOURCES taskBplusToJpsiKReduced.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::MLCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(task-bs-reduced SOURCES taskBsReduced.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(task-bs-to-jpsi-phi-reduced + SOURCES taskBsToJpsiPhiReduced.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::MLCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(task-bs SOURCES taskBs.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore diff --git a/PWGHF/D2H/Tasks/taskBplusToJpsiKReduced.cxx b/PWGHF/D2H/Tasks/taskBplusToJpsiKReduced.cxx new file mode 100644 index 00000000000..680d7933c48 --- /dev/null +++ b/PWGHF/D2H/Tasks/taskBplusToJpsiKReduced.cxx @@ -0,0 +1,535 @@ +// 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 taskBplusToJpsiKReduced.cxx +/// \brief B+ → Jpsi K+ → (µ+ µ-) K+ analysis task +/// +/// \author Fabrizio Chinu , Università degli Studi and INFN Torino +/// \author Fabrizio Grosa , CERN + +#include "PWGHF/Core/DecayChannels.h" +#include "PWGHF/Core/HfHelper.h" +#include "PWGHF/Core/HfMlResponseBplusToJpsiKReduced.h" +#include "PWGHF/Core/SelectorCuts.h" +#include "PWGHF/D2H/DataModel/ReducedDataModel.h" +#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "PWGHF/Utils/utilsPid.h" + +#include "Common/Core/TrackSelectorPID.h" + +#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::aod; +using namespace o2::analysis; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::aod::pid_tpc_tof_utils; + +namespace o2::aod +{ +namespace hf_cand_bplustojpsik_lite +{ +DECLARE_SOA_COLUMN(PtJpsi, ptJpsi, float); //! Transverse momentum of Jpsi daughter candidate (GeV/c) +DECLARE_SOA_COLUMN(PtBach, ptBach, float); //! Transverse momentum of bachelor kaon (GeV/c) +// DECLARE_SOA_COLUMN(AbsEtaBach, absEtaBach, float); //! Absolute pseudorapidity of bachelor kaon +// DECLARE_SOA_COLUMN(ItsNClsBach, itsNClsBach, int); //! Number of ITS clusters of bachelor kaon +// DECLARE_SOA_COLUMN(TpcNClsCrossedRowsBach, tpcNClsCrossedRowsBach, int); //! Number of TPC crossed rows of prongs of bachelor kaon +// DECLARE_SOA_COLUMN(TpcChi2NClBach, tpcChi2NClBach, float); //! Maximum TPC chi2 of prongs of Jpsi-meson daughter candidate +// DECLARE_SOA_COLUMN(PtJpsiProngMin, ptJpsiProngMin, float); //! Minimum pT of prongs of Jpsi daughter candidate (GeV/c) +// DECLARE_SOA_COLUMN(AbsEtaJpsiProngMin, absEtaJpsiProngMin, float); //! Minimum absolute pseudorapidity of prongs of Jpsi daughter candidate +// DECLARE_SOA_COLUMN(ItsNClsJpsiProngMin, itsNClsJpsiProngMin, int); //! Minimum number of ITS clusters of prongs of Jpsi daughter candidate +// DECLARE_SOA_COLUMN(TpcNClsCrossedRowsJpsiProngMin, tpcNClsCrossedRowsJpsiProngMin, int); //! Minimum number of TPC crossed rows of prongs of Jpsi daughter candidate +// DECLARE_SOA_COLUMN(TpcChi2NClJpsiProngMax, tpcChi2NClJpsiProngMax, float); //! Maximum TPC chi2 of prongs of Jpsi daughter candidate +DECLARE_SOA_COLUMN(MJpsi, mJpsi, float); //! Invariant mass of Jpsi daughter candidates (GeV/c) +DECLARE_SOA_COLUMN(M, m, float); //! Invariant mass of candidate (GeV/c2) +DECLARE_SOA_COLUMN(Pt, pt, float); //! Transverse momentum of candidate (GeV/c) +DECLARE_SOA_COLUMN(PtGen, ptGen, float); //! Transverse momentum of candidate (GeV/c) +DECLARE_SOA_COLUMN(P, p, float); //! Momentum of candidate (GeV/c) +DECLARE_SOA_COLUMN(Y, y, float); //! Rapidity of candidate +DECLARE_SOA_COLUMN(Eta, eta, float); //! Pseudorapidity of candidate +DECLARE_SOA_COLUMN(Phi, phi, float); //! Azimuth angle of candidate +DECLARE_SOA_COLUMN(E, e, float); //! Energy of candidate (GeV) +DECLARE_SOA_COLUMN(NSigTpcKaBachelor, nSigTpcKaBachelor, float); //! TPC Nsigma separation for bachelor with kaon mass hypothesis +DECLARE_SOA_COLUMN(NSigTofKaBachelor, nSigTofKaBachelor, float); //! TOF Nsigma separation for bachelor with kaon mass hypothesis +DECLARE_SOA_COLUMN(NSigTpcTofKaBachelor, nSigTpcTofKaBachelor, float); //! Combined TPC and TOF Nsigma separation for bachelor with kaon mass hypothesis +DECLARE_SOA_COLUMN(NSigTpcMuJpsiDauPos, nSigTpcMuJpsiDauPos, float); //! TPC Nsigma separation for Jpsi DauPos with muon mass hypothesis +DECLARE_SOA_COLUMN(NSigTofMuJpsiDauPos, nSigTofMuJpsiDauPos, float); //! TOF Nsigma separation for Jpsi DauPos with muon mass hypothesis +DECLARE_SOA_COLUMN(NSigTpcTofMuJpsiDauPos, nSigTpcTofMuJpsiDauPos, float); //! Combined TPC and TOF Nsigma separation for Jpsi prong0 with muon mass hypothesis +DECLARE_SOA_COLUMN(NSigTpcMuJpsiDauNeg, nSigTpcMuJpsiDauNeg, float); //! TPC Nsigma separation for Jpsi DauNeg with muon mass hypothesis +DECLARE_SOA_COLUMN(NSigTofMuJpsiDauNeg, nSigTofMuJpsiDauNeg, float); //! TOF Nsigma separation for Jpsi DauNeg with muon mass hypothesis +DECLARE_SOA_COLUMN(NSigTpcTofMuJpsiDauNeg, nSigTpcTofMuJpsiDauNeg, float); //! Combined TPC and TOF Nsigma separation for Jpsi prong1 with muon mass hypothesis +DECLARE_SOA_COLUMN(DecayLength, decayLength, float); //! Decay length of candidate (cm) +DECLARE_SOA_COLUMN(DecayLengthXY, decayLengthXY, float); //! Transverse decay length of candidate (cm) +DECLARE_SOA_COLUMN(DecayLengthNormalised, decayLengthNormalised, float); //! Normalised decay length of candidate +DECLARE_SOA_COLUMN(DecayLengthXYNormalised, decayLengthXYNormalised, float); //! Normalised transverse decay length of candidate +DECLARE_SOA_COLUMN(CtXY, ctXY, float); //! Pseudo-proper decay length of candidate +DECLARE_SOA_COLUMN(ImpactParameterProduct, impactParameterProduct, float); //! Impact parameter product of B daughters +DECLARE_SOA_COLUMN(ImpactParameterProductJpsi, impactParameterProductJpsi, float); //! Impact parameter product of Jpsi daughters +DECLARE_SOA_COLUMN(ImpactParameterJpsiDauPos, impactParameterJpsiDauPos, float); //! Impact parameter of Jpsi daughter candidate +DECLARE_SOA_COLUMN(ImpactParameterJpsiDauNeg, impactParameterJpsiDauNeg, float); //! Impact parameter of Jpsi daughter candidate +DECLARE_SOA_COLUMN(ImpactParameterLfTrack0, impactParameterLfTrack0, float); //! Impact parameter of Phi daughter candidate +DECLARE_SOA_COLUMN(Cpa, cpa, float); //! Cosine pointing angle of candidate +DECLARE_SOA_COLUMN(CpaXY, cpaXY, float); //! Cosine pointing angle of candidate in transverse plane +DECLARE_SOA_COLUMN(CpaJpsi, cpaJpsi, float); //! Cosine pointing angle of Jpsi daughter candidate +DECLARE_SOA_COLUMN(CpaXYJpsi, cpaXYJpsi, float); //! Cosine pointing angle in transverse plane of Jpsi daughter candidate +DECLARE_SOA_COLUMN(MaxNormalisedDeltaIP, maxNormalisedDeltaIP, float); //! Maximum normalized difference between measured and expected impact parameter of candidate prongs +DECLARE_SOA_COLUMN(MlScoreSig, mlScoreSig, float); //! ML score for signal class +DECLARE_SOA_COLUMN(FlagWrongCollision, flagWrongCollision, int8_t); //! Flag for association with wrong collision +} // namespace hf_cand_bplustojpsik_lite + +DECLARE_SOA_TABLE(HfRedCandBpLites, "AOD", "HFREDCANDBPLITE", //! Table with some B+ properties + hf_cand_bplustojpsik_lite::M, + hf_cand_bplustojpsik_lite::Pt, + hf_cand_bplustojpsik_lite::Eta, + hf_cand_bplustojpsik_lite::Phi, + hf_cand_bplustojpsik_lite::Y, + hf_cand_bplustojpsik_lite::Cpa, + hf_cand_bplustojpsik_lite::CpaXY, + hf_cand::Chi2PCA, + hf_cand_bplustojpsik_lite::DecayLength, + hf_cand_bplustojpsik_lite::DecayLengthXY, + hf_cand_bplustojpsik_lite::DecayLengthNormalised, + hf_cand_bplustojpsik_lite::DecayLengthXYNormalised, + hf_cand_bplustojpsik_lite::CtXY, + hf_cand_bplustojpsik_lite::ImpactParameterProduct, + hf_cand_bplustojpsik_lite::ImpactParameterProductJpsi, + hf_cand_bplustojpsik_lite::MaxNormalisedDeltaIP, + hf_cand_bplustojpsik_lite::MlScoreSig, + // hf_sel_candidate_bplus::IsSelBplusToJpsiPi, + // Jpsi meson features + hf_cand_bplustojpsik_lite::MJpsi, + hf_cand_bplustojpsik_lite::PtJpsi, + hf_cand_bplustojpsik_lite::ImpactParameterJpsiDauPos, + hf_cand_bplustojpsik_lite::ImpactParameterJpsiDauNeg, + hf_cand_bplustojpsik_lite::ImpactParameterLfTrack0, + // hf_cand_bplustojpsik_lite::PtJpsiProngMin, + // hf_cand_bplustojpsik_lite::AbsEtaJpsiProngMin, + // hf_cand_bplustojpsik_lite::ItsNClsJpsiProngMin, + // hf_cand_bplustojpsik_lite::TpcNClsCrossedRowsJpsiProngMin, + // hf_cand_bplustojpsik_lite::TpcChi2NClJpsiProngMax, + // kaon features + hf_cand_bplustojpsik_lite::PtBach, + // hf_cand_bplustojpsik_lite::AbsEtaBach, + // hf_cand_bplustojpsik_lite::ItsNClsBach, + // hf_cand_bplustojpsik_lite::TpcNClsCrossedRowsBach, + // hf_cand_bplustojpsik_lite::TpcChi2NClBach, + hf_cand_bplustojpsik_lite::NSigTpcKaBachelor, + hf_cand_bplustojpsik_lite::NSigTofKaBachelor, + hf_cand_bplustojpsik_lite::NSigTpcTofKaBachelor, + // MC truth + hf_cand_bplus::FlagMcMatchRec, + hf_cand_bplus::ChannelMcMatchRec, + hf_cand_bplus::OriginMcRec, + hf_cand_bplustojpsik_lite::FlagWrongCollision, + hf_cand_bplustojpsik_lite::PtGen); + +// DECLARE_SOA_TABLE(HfRedBpMcCheck, "AOD", "HFREDBPMCCHECK", //! Table with MC decay type check +// hf_cand_2prong::FlagMcMatchRec, +// hf_cand_bplustojpsik_lite::FlagWrongCollision, +// hf_cand_bplustojpsik_lite::MJpsi, +// hf_cand_bplustojpsik_lite::PtJpsi, +// hf_cand_bplustojpsik_lite::M, +// hf_cand_bplustojpsik_lite::Pt, +// // hf_cand_bplustojpsik_lite::MlScoreSig, +// hf_bplus_mc::PdgCodeBeautyMother, +// hf_bplus_mc::PdgCodeCharmMother, +// hf_bplus_mc::PdgCodeDauPos, +// hf_bplus_mc::PdgCodeDauNeg, +// hf_bplus_mc::PdgCodeProng2); +} // namespace o2::aod + +// string definitions, used for histogram axis labels +const TString stringPt = "#it{p}_{T} (GeV/#it{c})"; +const TString stringPtJpsi = "#it{p}_{T}(Jpsi) (GeV/#it{c});"; +const TString bPlusCandTitle = "B+ candidates;"; +const TString entries = "entries"; +const TString bPlusCandMatch = "B+ candidates (matched);"; +const TString bPlusCandUnmatch = "B+ candidates (unmatched);"; +const TString mcParticleMatched = "MC particles (matched);"; + +/// B+ analysis task +struct HfTaskBplusToJpsiKReduced { + Produces hfRedCandBpLite; + // Produces hfRedBpMcCheck; + + Configurable selectionFlagBplus{"selectionFlagBplus", 1, "Selection Flag for Bplus"}; + Configurable yCandGenMax{"yCandGenMax", 0.5, "max. gen particle rapidity"}; + Configurable yCandRecoMax{"yCandRecoMax", 0.8, "max. cand. rapidity"}; + Configurable etaTrackMax{"etaTrackMax", 0.8, "max. track pseudo-rapidity"}; + Configurable ptTrackMin{"ptTrackMin", 0.1, "min. track transverse momentum"}; + 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"}; + // 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"}; + // Enable PID + Configurable kaonPidMethod{"kaonPidMethod", PidMethod::TpcOrTof, "PID selection method for the bachelor kaon (PidMethod::NoPid: none, PidMethod::TpcOrTof: TPC or TOF, PidMethod::TpcAndTof: TPC and TOF)"}; + Configurable acceptPIDNotApplicable{"acceptPIDNotApplicable", true, "Switch to accept Status::NotApplicable [(NotApplicable for one detector) and (NotApplicable or Conditional for the other)] in PID selection"}; + // TPC PID + Configurable ptPidTpcMin{"ptPidTpcMin", 0.15, "Lower bound of track pT for TPC PID"}; + Configurable ptPidTpcMax{"ptPidTpcMax", 20., "Upper bound of track pT for TPC PID"}; + Configurable nSigmaTpcMax{"nSigmaTpcMax", 5., "Nsigma cut on TPC only"}; + Configurable nSigmaTpcCombinedMax{"nSigmaTpcCombinedMax", 5., "Nsigma cut on TPC combined with TOF"}; + // TOF PID + Configurable ptPidTofMin{"ptPidTofMin", 0.15, "Lower bound of track pT for TOF PID"}; + Configurable ptPidTofMax{"ptPidTofMax", 20., "Upper bound of track pT for TOF PID"}; + Configurable nSigmaTofMax{"nSigmaTofMax", 5., "Nsigma cut on TOF only"}; + Configurable nSigmaTofCombinedMax{"nSigmaTofCombinedMax", 5., "Nsigma cut on TOF combined with TPC"}; + // B+ ML inference + Configurable> binsPtBpMl{"binsPtBpMl", std::vector{hf_cuts_ml::vecBinsPt}, "pT bin limits for ML application"}; + Configurable> cutDirBpMl{"cutDirBpMl", std::vector{hf_cuts_ml::vecCutDir}, "Whether to reject score values greater or smaller than the threshold"}; + Configurable> cutsBpMl{"cutsBpMl", {hf_cuts_ml::Cuts[0], hf_cuts_ml::NBinsPt, hf_cuts_ml::NCutScores, hf_cuts_ml::labelsPt, hf_cuts_ml::labelsCutScore}, "ML selections per pT bin"}; + Configurable nClassesBpMl{"nClassesBpMl", static_cast(hf_cuts_ml::NCutScores), "Number of classes in ML model"}; + Configurable> namesInputFeatures{"namesInputFeatures", std::vector{"feature1", "feature2"}, "Names of ML model input features"}; + // CCDB configuration + Configurable ccdbUrl{"ccdbUrl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable> modelPathsCCDB{"modelPathsCCDB", std::vector{"path_ccdb/BDT_BPLUS/"}, "Paths of models on CCDB"}; + Configurable> onnxFileNames{"onnxFileNames", std::vector{"ModelHandler_onnx_BPLUSToJPSIK.onnx"}, "ONNX file names for each pT bin (if not from CCDB full path)"}; + Configurable timestampCCDB{"timestampCCDB", -1, "timestamp of the ONNX file for ML model used to query in CCDB"}; + Configurable loadModelsFromCCDB{"loadModelsFromCCDB", false, "Flag to enable or disable the loading of models from CCDB"}; + + HfHelper hfHelper; + TrackSelectorKa selectorKaon; + o2::analysis::HfMlResponseBplusToJpsiKReduced hfMlResponse; + o2::ccdb::CcdbApi ccdbApi; + + using TracksKaon = soa::Join; + std::vector outputMl = {}; + + // Filter filterSelectCandidates = (aod::hf_sel_candidate_bplus::isSelBplusToJpsiPi >= selectionFlagBplus); + + HistogramRegistry registry{"registry"}; + + void init(InitContext&) + { + std::array processFuncData{doprocessData, doprocessDataWithBplusMl}; + if ((std::accumulate(processFuncData.begin(), processFuncData.end(), 0)) > 1) { + LOGP(fatal, "Only one process function for data can be enabled at a time."); + } + std::array processFuncMc{doprocessMc, doprocessMcWithBplusMl}; + if ((std::accumulate(processFuncMc.begin(), processFuncMc.end(), 0)) > 1) { + LOGP(fatal, "Only one process function for MC can be enabled at a time."); + } + + if (kaonPidMethod < 0 || kaonPidMethod >= PidMethod::NPidMethods) { + LOGP(fatal, "Invalid PID option in configurable, please set 0 (no PID), 1 (TPC or TOF), or 2 (TPC and TOF)"); + } + + if (kaonPidMethod != PidMethod::NoPid) { + selectorKaon.setRangePtTpc(ptPidTpcMin, ptPidTpcMax); + selectorKaon.setRangeNSigmaTpc(-nSigmaTpcMax, nSigmaTpcMax); + selectorKaon.setRangeNSigmaTpcCondTof(-nSigmaTpcCombinedMax, nSigmaTpcCombinedMax); + selectorKaon.setRangePtTof(ptPidTofMin, ptPidTofMax); + selectorKaon.setRangeNSigmaTof(-nSigmaTofMax, nSigmaTofMax); + selectorKaon.setRangeNSigmaTofCondTpc(-nSigmaTofCombinedMax, nSigmaTofCombinedMax); + } + + const AxisSpec axisMassBplus{150, 4.5, 6.0}; + const AxisSpec axisMassJpsi{600, 2.8f, 3.4f}; + const AxisSpec axisPtProng{100, 0., 10.}; + const AxisSpec axisImpactPar{200, -0.05, 0.05}; + const AxisSpec axisPtJpsi{100, 0., 50.}; + const AxisSpec axisRapidity{100, -2., 2.}; + const AxisSpec axisPtB{(std::vector)binsPt, "#it{p}_{T}^{B^{+}} (GeV/#it{c})"}; + const AxisSpec axisPtKa{100, 0.f, 10.f}; + + registry.add("hMass", bPlusCandTitle + "inv. mass J/#Psi K^{+} (GeV/#it{c}^{2});" + stringPt, {HistType::kTH2F, {axisMassBplus, axisPtB}}); + registry.add("hMassJpsi", bPlusCandTitle + "inv. mass #mu^{+}#mu^{#minus} (GeV/#it{c}^{2});" + stringPt, {HistType::kTH2F, {axisMassJpsi, axisPtJpsi}}); + registry.add("hd0K", bPlusCandTitle + "Kaon DCAxy to prim. vertex (cm);" + stringPt, {HistType::kTH2F, {axisImpactPar, axisPtKa}}); + + // histograms processMC + if (doprocessMc || doprocessMcWithBplusMl) { + registry.add("hPtJpsiGen", mcParticleMatched + "J/#Psi #it{p}_{T}^{gen} (GeV/#it{c}); B^{+} " + stringPt, {HistType::kTH2F, {axisPtProng, axisPtB}}); + registry.add("hPtKGen", mcParticleMatched + "Kaon #it{p}_{T}^{gen} (GeV/#it{c}); B^{+} " + stringPt, {HistType::kTH2F, {axisPtProng, axisPtB}}); + registry.add("hYGenWithProngsInAcceptance", mcParticleMatched + "Kaon #it{p}_{T}^{gen} (GeV/#it{c}); B^{+} " + stringPt, {HistType::kTH2F, {axisPtProng, axisRapidity}}); + registry.add("hMassRecSig", bPlusCandMatch + "inv. mass J/#Psi K^{+} (GeV/#it{c}^{2}); B^{+} " + stringPt, {HistType::kTH2F, {axisMassBplus, axisPtB}}); + registry.add("hMassJpsiRecSig", bPlusCandMatch + "inv. mass #mu^{+}#mu^{#minus} (GeV/#it{c}^{2}); J/#Psi " + stringPt, {HistType::kTH2F, {axisMassJpsi, axisPtJpsi}}); + registry.add("hd0KRecSig", bPlusCandMatch + "Kaon DCAxy to prim. vertex (cm); K^{+} " + stringPt, {HistType::kTH2F, {axisImpactPar, axisPtKa}}); + registry.add("hMassRecBg", bPlusCandUnmatch + "inv. mass J/#Psi K^{+} (GeV/#it{c}^{2}); B^{+} " + stringPt, {HistType::kTH2F, {axisMassBplus, axisPtB}}); + registry.add("hMassJpsiRecBg", bPlusCandUnmatch + "inv. mass #mu^{+}#mu^{#minus} (GeV/#it{c}^{2}); J/#Psi " + stringPt, {HistType::kTH2F, {axisMassJpsi, axisPtJpsi}}); + registry.add("hd0KRecBg", bPlusCandMatch + "Kaon DCAxy to prim. vertex (cm); K^{+} " + stringPt, {HistType::kTH2F, {axisImpactPar, axisPtKa}}); + } + + if (doprocessDataWithBplusMl || doprocessMcWithBplusMl) { + hfMlResponse.configure(binsPtBpMl, cutsBpMl, cutDirBpMl, nClassesBpMl); + if (loadModelsFromCCDB) { + ccdbApi.init(ccdbUrl); + hfMlResponse.setModelPathsCCDB(onnxFileNames, ccdbApi, modelPathsCCDB, timestampCCDB); + } else { + hfMlResponse.setModelPathsLocal(onnxFileNames); + } + hfMlResponse.cacheInputFeaturesIndices(namesInputFeatures); + hfMlResponse.init(); + } + } + + /// Selection of B+ daughter in geometrical acceptance + /// \param etaProng is the pseudorapidity of B+ prong + /// \param ptProng is the pT of B+ prong + /// \return true if prong is in geometrical acceptance + template + bool isProngInAcceptance(const T& etaProng, const T& ptProng) + { + return std::abs(etaProng) <= etaTrackMax && ptProng >= ptTrackMin; + } + + /// Fill candidate information at reconstruction level + /// \param doMc is the flag to enable the filling with MC information + /// \param withBplusMl is the flag to enable the filling with ML scores for the B+ candidate + /// \param candidate is the B+ candidate + /// \param candidatesJpsi is the table with Jpsi candidates + template + void fillCand(Cand const& candidate, + aod::HfRedJpsis const& /*candidatesJpsi*/, + aod::HfRedBach0Tracks const&) + { + auto ptCandBplus = candidate.pt(); + auto invMassBplus = hfHelper.invMassBplusToJpsiK(candidate); + auto candJpsi = candidate.template jpsi_as(); + auto candKa = candidate.template bachKa_as(); + auto ptJpsi = candidate.ptProng0(); + auto invMassJpsi = candJpsi.m(); + uint8_t statusBplus = 0; + + int8_t flagMcMatchRec{0}, channelMcMatchRec{0}, flagWrongCollision{0}; + bool isSignal = false; + if constexpr (doMc) { + flagMcMatchRec = candidate.flagMcMatchRec(); + channelMcMatchRec = candidate.channelMcMatchRec(); + flagWrongCollision = candidate.flagWrongCollision(); + isSignal = std::abs(flagMcMatchRec) == o2::hf_decay::hf_cand_beauty::BplusToJpsiK; + } + + SETBIT(statusBplus, SelectionStep::RecoSkims); + if (hfHelper.selectionBplusToJpsiKTopol(candidate, cuts, binsPt)) { + SETBIT(statusBplus, SelectionStep::RecoTopol); + } else if (selectionFlagBplus >= BIT(SelectionStep::RecoTopol) * 2 - 1) { + return; + } + // track-level PID selection + // auto trackKa = candidate.template prong1_as(); + if (kaonPidMethod == PidMethod::TpcOrTof || kaonPidMethod == PidMethod::TpcAndTof) { + int pidTrackKa{TrackSelectorPID::Status::NotApplicable}; + if (kaonPidMethod == PidMethod::TpcOrTof) { + pidTrackKa = selectorKaon.statusTpcOrTof(candKa); + } else if (kaonPidMethod == PidMethod::TpcAndTof) { + pidTrackKa = selectorKaon.statusTpcAndTof(candKa); + } + if (hfHelper.selectionBplusToJpsiKPid(pidTrackKa, acceptPIDNotApplicable.value)) { + // LOGF(info, "B+ candidate selection failed at PID selection"); + SETBIT(statusBplus, SelectionStep::RecoPID); + } else if (selectionFlagBplus >= BIT(SelectionStep::RecoPID) * 2 - 1) { + return; + } + } + + float candidateMlScoreSig = -1; + if constexpr (withBplusMl) { + // B+ ML selections + std::vector inputFeatures = hfMlResponse.getInputFeatures(candidate, candKa); + if (hfMlResponse.isSelectedMl(inputFeatures, ptCandBplus, outputMl)) { + SETBIT(statusBplus, SelectionStep::RecoMl); + } else if (selectionFlagBplus >= BIT(SelectionStep::RecoMl) * 2 - 1) { + return; + } + candidateMlScoreSig = outputMl[1]; + } + + registry.fill(HIST("hMass"), invMassBplus, ptCandBplus); + registry.fill(HIST("hMassJpsi"), invMassJpsi, candidate.ptProng0()); + registry.fill(HIST("hd0K"), candidate.impactParameter1(), candidate.ptProng1()); + 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()); + } else if (fillBackground) { + registry.fill(HIST("hMassRecBg"), invMassBplus, ptCandBplus); + registry.fill(HIST("hMassJpsiRecBg"), invMassJpsi, candidate.ptProng0()); + registry.fill(HIST("hd0KRecBg"), candidate.impactParameter1(), candidate.ptProng1()); + } + } + + float pseudoRndm = ptJpsi * 1000. - static_cast(ptJpsi * 1000); + if (ptCandBplus >= ptMaxForDownSample || pseudoRndm < downSampleBkgFactor) { + float ptMother = -1.; + if constexpr (doMc) { + ptMother = candidate.ptMother(); + } + + hfRedCandBpLite( + // B+ - meson features + invMassBplus, + ptCandBplus, + candidate.eta(), + candidate.phi(), + hfHelper.yBplus(candidate), + candidate.cpa(), + candidate.cpaXY(), + candidate.chi2PCA(), + candidate.decayLength(), + candidate.decayLengthXY(), + candidate.decayLengthNormalised(), + candidate.decayLengthXYNormalised(), + candidate.ctXY(std::array{o2::constants::physics::MassMuon, o2::constants::physics::MassMuon, o2::constants::physics::MassKPlus}), + candidate.impactParameterProduct(), + candidate.impactParameterProductJpsi(), + candidate.maxNormalisedDeltaIP(), + candidateMlScoreSig, + // J/Psi features + invMassJpsi, + ptJpsi, + candidate.impactParameter0(), + candidate.impactParameter1(), + candidate.impactParameter2(), + // candJpsi.ptProngMin(), + // candJpsi.absEtaProngMin(), + // candJpsi.itsNClsProngMin(), + // candJpsi.tpcNClsCrossedRowsProngMin(), + // candJpsi.tpcChi2NClProngMax(), + // kaon features + candidate.ptProng1(), + // std::abs(RecoDecay::eta(candKa.pVector())), + // candKa.itsNCls(), + // candKa.tpcNClsCrossedRows(), + // candKa.tpcChi2NCl(), + candKa.tpcNSigmaKa(), + candKa.tofNSigmaKa(), + candKa.tpcTofNSigmaKa(), + // MC truth + flagMcMatchRec, + channelMcMatchRec, + isSignal, + flagWrongCollision, + ptMother); + } + } + + /// Fill particle histograms (gen MC truth) + void fillCandMcGen(aod::HfMcGenRedBps::iterator const& particle) + { + auto ptParticle = particle.ptTrack(); + auto yParticle = particle.yTrack(); + if (yCandGenMax >= 0. && std::abs(yParticle) > yCandGenMax) { + return; + } + std::array ptProngs = {particle.ptProng0(), particle.ptProng1()}; + std::array etaProngs = {particle.etaProng0(), particle.etaProng1()}; + bool prongsInAcc = isProngInAcceptance(etaProngs[0], ptProngs[0]) && isProngInAcceptance(etaProngs[1], ptProngs[1]); + + registry.fill(HIST("hPtJpsiGen"), ptProngs[0], ptParticle); + registry.fill(HIST("hPtKGen"), ptProngs[1], ptParticle); + + // generated B+ with daughters in geometrical acceptance + if (prongsInAcc) { + registry.fill(HIST("hYGenWithProngsInAcceptance"), ptParticle, yParticle); + } + } + + // Process functions + void processData(aod::HfRedCandBplusToJpsiK const& candidates, + aod::HfRedJpsis const& candidatesJpsi, + aod::HfRedBach0Tracks const& kaonTracks) + { + for (const auto& candidate : candidates) { + if (yCandRecoMax >= 0. && std::abs(hfHelper.yBplus(candidate)) > yCandRecoMax) { + continue; + } + fillCand(candidate, candidatesJpsi, kaonTracks); + } // candidate loop + } // processData + PROCESS_SWITCH(HfTaskBplusToJpsiKReduced, processData, "Process data without ML for B+", true); + + void processDataWithBplusMl(aod::HfRedCandBplusToJpsiK const& candidates, + aod::HfRedJpsis const& candidatesJpsi, + aod::HfRedBach0Tracks const& kaonTracks) + { + for (const auto& candidate : candidates) { + if (yCandRecoMax >= 0. && std::abs(hfHelper.yBplus(candidate)) > yCandRecoMax) { + continue; + } + fillCand(candidate, candidatesJpsi, kaonTracks); + } // candidate loop + } // processDataWithBplusMl + PROCESS_SWITCH(HfTaskBplusToJpsiKReduced, processDataWithBplusMl, "Process data with ML for B+", false); + + void processMc(soa::Join const& candidates, + aod::HfMcGenRedBps const& mcParticles, + aod::HfRedJpsis const& candidatesJpsi, + aod::HfRedBach0Tracks const& kaonTracks) + { + // MC rec + for (const auto& candidate : candidates) { + if (yCandRecoMax >= 0. && std::abs(hfHelper.yBplus(candidate)) > yCandRecoMax) { + continue; + } + fillCand(candidate, candidatesJpsi, kaonTracks); + } // rec + + // MC gen. level + for (const auto& particle : mcParticles) { + fillCandMcGen(particle); + } // gen + } // processMc + PROCESS_SWITCH(HfTaskBplusToJpsiKReduced, processMc, "Process MC without ML for B+", false); + + void processMcWithBplusMl(soa::Join const& candidates, + aod::HfMcGenRedBps const& mcParticles, + aod::HfRedJpsis const& candidatesJpsi, + aod::HfRedBach0Tracks const& kaonTracks) + { + // MC rec + for (const auto& candidate : candidates) { + if (yCandRecoMax >= 0. && std::abs(hfHelper.yBplus(candidate)) > yCandRecoMax) { + continue; + } + fillCand(candidate, candidatesJpsi, kaonTracks); + } // rec + + // MC gen. level + for (const auto& particle : mcParticles) { + fillCandMcGen(particle); + } // gen + } // processMcWithBplusMl + PROCESS_SWITCH(HfTaskBplusToJpsiKReduced, processMcWithBplusMl, "Process MC with ML for B+", false); + +}; // struct + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} diff --git a/PWGHF/D2H/Tasks/taskBsToJpsiPhiReduced.cxx b/PWGHF/D2H/Tasks/taskBsToJpsiPhiReduced.cxx new file mode 100644 index 00000000000..90ce04a9cb7 --- /dev/null +++ b/PWGHF/D2H/Tasks/taskBsToJpsiPhiReduced.cxx @@ -0,0 +1,582 @@ +// 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 taskBsToJpsiPhiReduced.cxx +/// \brief Bs → Jpsi phi → (µ+ µ-) (K+K-) analysis task +/// +/// \author Fabrizio Chinu , Università degli Studi and INFN Torino +/// \author Fabrizio Grosa , CERN + +#include "PWGHF/Core/DecayChannels.h" +#include "PWGHF/Core/HfHelper.h" +#include "PWGHF/Core/HfMlResponseBsToJpsiPhiReduced.h" +#include "PWGHF/Core/SelectorCuts.h" +#include "PWGHF/D2H/DataModel/ReducedDataModel.h" +#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "PWGHF/Utils/utilsPid.h" + +#include "Common/Core/RecoDecay.h" +#include "Common/Core/TrackSelectorPID.h" + +#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::aod; +using namespace o2::analysis; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::aod::pid_tpc_tof_utils; + +namespace o2::aod +{ +namespace hf_cand_bstojpsiphi_lite +{ +DECLARE_SOA_COLUMN(PtJpsi, ptJpsi, float); //! Transverse momentum of Jpsi daughter candidate (GeV/c) +DECLARE_SOA_COLUMN(PtBach0, ptBach0, float); //! Transverse momentum of bachelor kaon(<- phi) (GeV/c) +DECLARE_SOA_COLUMN(PtBach1, ptBach1, float); //! Transverse momentum of bachelor kaon(<- phi) (GeV/c) +// DECLARE_SOA_COLUMN(AbsEtaBach, absEtaBach, float); //! Absolute pseudorapidity of bachelor kaon +// DECLARE_SOA_COLUMN(ItsNClsBach, itsNClsBach, int); //! Number of ITS clusters of bachelor kaon +// DECLARE_SOA_COLUMN(TpcNClsCrossedRowsBach, tpcNClsCrossedRowsBach, int); //! Number of TPC crossed rows of prongs of bachelor kaon +// DECLARE_SOA_COLUMN(TpcChi2NClBach, tpcChi2NClBach, float); //! Maximum TPC chi2 of prongs of Jpsi-meson daughter candidate +// DECLARE_SOA_COLUMN(PtJpsiProngMin, ptJpsiProngMin, float); //! Minimum pT of prongs of Jpsi daughter candidate (GeV/c) +// DECLARE_SOA_COLUMN(AbsEtaJpsiProngMin, absEtaJpsiProngMin, float); //! Minimum absolute pseudorapidity of prongs of Jpsi daughter candidate +// DECLARE_SOA_COLUMN(ItsNClsJpsiProngMin, itsNClsJpsiProngMin, int); //! Minimum number of ITS clusters of prongs of Jpsi daughter candidate +// DECLARE_SOA_COLUMN(TpcNClsCrossedRowsJpsiProngMin, tpcNClsCrossedRowsJpsiProngMin, int); //! Minimum number of TPC crossed rows of prongs of Jpsi daughter candidate +// DECLARE_SOA_COLUMN(TpcChi2NClJpsiProngMax, tpcChi2NClJpsiProngMax, float); //! Maximum TPC chi2 of prongs of Jpsi daughter candidate +DECLARE_SOA_COLUMN(MJpsi, mJpsi, float); //! Invariant mass of Jpsi daughter candidates (GeV/c) +DECLARE_SOA_COLUMN(MPhi, mPhi, float); //! Invariant mass of phi daughter candidates (GeV/c) +DECLARE_SOA_COLUMN(M, m, float); //! Invariant mass of candidate (GeV/c2) +DECLARE_SOA_COLUMN(Pt, pt, float); //! Transverse momentum of candidate (GeV/c) +DECLARE_SOA_COLUMN(PtGen, ptGen, float); //! Transverse momentum of candidate (GeV/c) +DECLARE_SOA_COLUMN(P, p, float); //! Momentum of candidate (GeV/c) +DECLARE_SOA_COLUMN(Y, y, float); //! Rapidity of candidate +DECLARE_SOA_COLUMN(Eta, eta, float); //! Pseudorapidity of candidate +DECLARE_SOA_COLUMN(Phi, phi, float); //! Azimuth angle of candidate +DECLARE_SOA_COLUMN(E, e, float); //! Energy of candidate (GeV) +DECLARE_SOA_COLUMN(NSigTpcKaBachelor0, nSigTpcKaBachelor0, float); //! TPC Nsigma separation for bachelor 0 with kaon mass hypothesis +DECLARE_SOA_COLUMN(NSigTofKaBachelor0, nSigTofKaBachelor0, float); //! TOF Nsigma separation for bachelor 0 with kaon mass hypothesis +DECLARE_SOA_COLUMN(NSigTpcTofKaBachelor0, nSigTpcTofKaBachelor0, float); //! Combined TPC and TOF Nsigma separation for bachelor 0 with kaon mass hypothesis +DECLARE_SOA_COLUMN(NSigTpcKaBachelor1, nSigTpcKaBachelor1, float); //! TPC Nsigma separation for bachelor 1 with kaon mass hypothesis +DECLARE_SOA_COLUMN(NSigTofKaBachelor1, nSigTofKaBachelor1, float); //! TOF Nsigma separation for bachelor 1 with kaon mass hypothesis +DECLARE_SOA_COLUMN(NSigTpcTofKaBachelor1, nSigTpcTofKaBachelor1, float); //! Combined TPC and TOF Nsigma separation for bachelor 1 with kaon mass hypothesis +DECLARE_SOA_COLUMN(NSigTpcMuJpsiDauPos, nSigTpcMuJpsiDauPos, float); //! TPC Nsigma separation for Jpsi DauPos with muon mass hypothesis +DECLARE_SOA_COLUMN(NSigTofMuJpsiDauPos, nSigTofMuJpsiDauPos, float); //! TOF Nsigma separation for Jpsi DauPos with muon mass hypothesis +DECLARE_SOA_COLUMN(NSigTpcTofMuJpsiDauPos, nSigTpcTofMuJpsiDauPos, float); //! Combined TPC and TOF Nsigma separation for Jpsi prong0 with muon mass hypothesis +DECLARE_SOA_COLUMN(NSigTpcMuJpsiDauNeg, nSigTpcMuJpsiDauNeg, float); //! TPC Nsigma separation for Jpsi DauNeg with muon mass hypothesis +DECLARE_SOA_COLUMN(NSigTofMuJpsiDauNeg, nSigTofMuJpsiDauNeg, float); //! TOF Nsigma separation for Jpsi DauNeg with muon mass hypothesis +DECLARE_SOA_COLUMN(NSigTpcTofMuJpsiDauNeg, nSigTpcTofMuJpsiDauNeg, float); //! Combined TPC and TOF Nsigma separation for Jpsi prong1 with muon mass hypothesis +DECLARE_SOA_COLUMN(DecayLength, decayLength, float); //! Decay length of candidate (cm) +DECLARE_SOA_COLUMN(DecayLengthXY, decayLengthXY, float); //! Transverse decay length of candidate (cm) +DECLARE_SOA_COLUMN(DecayLengthNormalised, decayLengthNormalised, float); //! Normalised decay length of candidate +DECLARE_SOA_COLUMN(DecayLengthXYNormalised, decayLengthXYNormalised, float); //! Normalised transverse decay length of candidate +DECLARE_SOA_COLUMN(CtXY, ctXY, float); //! Pseudo-proper decay length of candidate +DECLARE_SOA_COLUMN(ImpactParameterProduct, impactParameterProduct, float); //! Impact parameter product of B daughters +DECLARE_SOA_COLUMN(ImpactParameterProductJpsi, impactParameterProductJpsi, float); //! Impact parameter product of Jpsi daughters +DECLARE_SOA_COLUMN(ImpactParameterProductPhi, impactParameterProductPhi, float); //! Impact parameter product of Phi daughters +DECLARE_SOA_COLUMN(ImpactParameterJpsiDauPos, impactParameterJpsiDauPos, float); //! Impact parameter of Jpsi daughter candidate +DECLARE_SOA_COLUMN(ImpactParameterJpsiDauNeg, impactParameterJpsiDauNeg, float); //! Impact parameter of Jpsi daughter candidate +DECLARE_SOA_COLUMN(ImpactParameterLfTrack0, impactParameterLfTrack0, float); //! Impact parameter of Phi daughter candidate +DECLARE_SOA_COLUMN(ImpactParameterLfTrack1, impactParameterLfTrack1, float); //! Impact parameter of Phi daughter candidate +DECLARE_SOA_COLUMN(Cpa, cpa, float); //! Cosine pointing angle of candidate +DECLARE_SOA_COLUMN(CpaXY, cpaXY, float); //! Cosine pointing angle of candidate in transverse plane +DECLARE_SOA_COLUMN(CpaJpsi, cpaJpsi, float); //! Cosine pointing angle of Jpsi daughter candidate +DECLARE_SOA_COLUMN(CpaXYJpsi, cpaXYJpsi, float); //! Cosine pointing angle in transverse plane of Jpsi daughter candidate +DECLARE_SOA_COLUMN(MaxNormalisedDeltaIP, maxNormalisedDeltaIP, float); //! Maximum normalized difference between measured and expected impact parameter of candidate prongs +DECLARE_SOA_COLUMN(MlScoreSig, mlScoreSig, float); //! ML score for signal class +DECLARE_SOA_COLUMN(FlagWrongCollision, flagWrongCollision, int8_t); //! Flag for association with wrong collision +} // namespace hf_cand_bstojpsiphi_lite + +DECLARE_SOA_TABLE(HfRedCandBsLites, "AOD", "HFREDCANDBSLITE", //! Table with some Bs properties + hf_cand_bstojpsiphi_lite::M, + hf_cand_bstojpsiphi_lite::Pt, + hf_cand_bstojpsiphi_lite::Eta, + hf_cand_bstojpsiphi_lite::Phi, + hf_cand_bstojpsiphi_lite::Y, + hf_cand_bstojpsiphi_lite::Cpa, + hf_cand_bstojpsiphi_lite::CpaXY, + hf_cand::Chi2PCA, + hf_cand_bstojpsiphi_lite::DecayLength, + hf_cand_bstojpsiphi_lite::DecayLengthXY, + hf_cand_bstojpsiphi_lite::DecayLengthNormalised, + hf_cand_bstojpsiphi_lite::DecayLengthXYNormalised, + hf_cand_bstojpsiphi_lite::CtXY, + hf_cand_bstojpsiphi_lite::ImpactParameterProduct, + hf_cand_bstojpsiphi_lite::ImpactParameterProductJpsi, + hf_cand_bstojpsiphi_lite::ImpactParameterProductPhi, + hf_cand_bstojpsiphi_lite::MaxNormalisedDeltaIP, + hf_cand_bstojpsiphi_lite::MlScoreSig, + // hf_sel_candidate_bplus::IsSelBsToJpsiPi, + // Jpsi meson features + hf_cand_bstojpsiphi_lite::MJpsi, + hf_cand_bstojpsiphi_lite::PtJpsi, + hf_cand_bstojpsiphi_lite::MPhi, + hf_cand_bstojpsiphi_lite::ImpactParameterJpsiDauPos, + hf_cand_bstojpsiphi_lite::ImpactParameterJpsiDauNeg, + hf_cand_bstojpsiphi_lite::ImpactParameterLfTrack0, + hf_cand_bstojpsiphi_lite::ImpactParameterLfTrack1, + // hf_cand_bstojpsiphi_lite::PtJpsiProngMin, + // hf_cand_bstojpsiphi_lite::AbsEtaJpsiProngMin, + // hf_cand_bstojpsiphi_lite::ItsNClsJpsiProngMin, + // hf_cand_bstojpsiphi_lite::TpcNClsCrossedRowsJpsiProngMin, + // hf_cand_bstojpsiphi_lite::TpcChi2NClJpsiProngMax, + // kaon features + hf_cand_bstojpsiphi_lite::PtBach0, + // hf_cand_bstojpsiphi_lite::AbsEtaBach0, + // hf_cand_bstojpsiphi_lite::ItsNClsBach0, + // hf_cand_bstojpsiphi_lite::TpcNClsCrossedRowsBach0, + // hf_cand_bstojpsiphi_lite::TpcChi2NClBach0, + hf_cand_bstojpsiphi_lite::NSigTpcKaBachelor0, + hf_cand_bstojpsiphi_lite::NSigTofKaBachelor0, + hf_cand_bstojpsiphi_lite::NSigTpcTofKaBachelor0, + hf_cand_bstojpsiphi_lite::PtBach1, + // hf_cand_bstojpsiphi_lite::AbsEtaBach1, + // hf_cand_bstojpsiphi_lite::ItsNClsBach1, + // hf_cand_bstojpsiphi_lite::TpcNClsCrossedRowsBach1, + // hf_cand_bstojpsiphi_lite::TpcChi2NClBach1, + hf_cand_bstojpsiphi_lite::NSigTpcKaBachelor1, + hf_cand_bstojpsiphi_lite::NSigTofKaBachelor1, + hf_cand_bstojpsiphi_lite::NSigTpcTofKaBachelor1, + // MC truth + hf_cand_bs::FlagMcMatchRec, + hf_cand_bs::ChannelMcMatchRec, + hf_cand_bs::OriginMcRec, + hf_cand_bstojpsiphi_lite::FlagWrongCollision, + hf_cand_bstojpsiphi_lite::PtGen); + +// DECLARE_SOA_TABLE(HfRedBsMcCheck, "AOD", "HFREDBPMCCHECK", //! Table with MC decay type check +// hf_cand_2prong::FlagMcMatchRec, +// hf_cand_bstojpsiphi_lite::FlagWrongCollision, +// hf_cand_bstojpsiphi_lite::MJpsi, +// hf_cand_bstojpsiphi_lite::PtJpsi, +// hf_cand_bstojpsiphi_lite::M, +// hf_cand_bstojpsiphi_lite::Pt, +// // hf_cand_bstojpsiphi_lite::MlScoreSig, +// hf_bplus_mc::PdgCodeBeautyMother, +// hf_bplus_mc::PdgCodeCharmMother, +// hf_bplus_mc::PdgCodeDauPos, +// hf_bplus_mc::PdgCodeDauNeg, +// hf_bplus_mc::PdgCodeProng2); +} // namespace o2::aod + +// string definitions, used for histogram axis labels +const TString stringPt = "#it{p}_{T} (GeV/#it{c})"; +const TString stringPtJpsi = "#it{p}_{T}(Jpsi) (GeV/#it{c});"; +const TString bSCandTitle = "B_{s}^{0} candidates;"; +const TString entries = "entries"; +const TString bSCandMatch = "B_{s}^{0} candidates (matched);"; +const TString bSCandUnmatch = "B_{s}^{0} candidates (unmatched);"; +const TString mcParticleMatched = "MC particles (matched);"; + +/// Bs analysis task +struct HfTaskBsToJpsiPhiReduced { + Produces hfRedCandBsLite; + // Produces hfRedBsMcCheck; + + Configurable selectionFlagBs{"selectionFlagBs", 1, "Selection Flag for Bs"}; + Configurable yCandGenMax{"yCandGenMax", 0.5, "max. gen particle rapidity"}; + Configurable yCandRecoMax{"yCandRecoMax", 0.8, "max. cand. rapidity"}; + Configurable etaTrackMax{"etaTrackMax", 0.8, "max. track pseudo-rapidity"}; + Configurable ptTrackMin{"ptTrackMin", 0.1, "min. track transverse momentum"}; + 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"}; + // 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"}; + // Enable PID + Configurable kaonPidMethod{"kaonPidMethod", PidMethod::TpcOrTof, "PID selection method for the bachelor kaon (PidMethod::NoPid: none, PidMethod::TpcOrTof: TPC or TOF, PidMethod::TpcAndTof: TPC and TOF)"}; + Configurable acceptPIDNotApplicable{"acceptPIDNotApplicable", true, "Switch to accept Status::NotApplicable [(NotApplicable for one detector) and (NotApplicable or Conditional for the other)] in PID selection"}; + // TPC PID + Configurable ptPidTpcMin{"ptPidTpcMin", 0.15, "Lower bound of track pT for TPC PID"}; + Configurable ptPidTpcMax{"ptPidTpcMax", 20., "Upper bound of track pT for TPC PID"}; + Configurable nSigmaTpcMax{"nSigmaTpcMax", 5., "Nsigma cut on TPC only"}; + Configurable nSigmaTpcCombinedMax{"nSigmaTpcCombinedMax", 5., "Nsigma cut on TPC combined with TOF"}; + // TOF PID + Configurable ptPidTofMin{"ptPidTofMin", 0.15, "Lower bound of track pT for TOF PID"}; + Configurable ptPidTofMax{"ptPidTofMax", 20., "Upper bound of track pT for TOF PID"}; + Configurable nSigmaTofMax{"nSigmaTofMax", 5., "Nsigma cut on TOF only"}; + Configurable nSigmaTofCombinedMax{"nSigmaTofCombinedMax", 5., "Nsigma cut on TOF combined with TPC"}; + // Bs ML inference + Configurable> binsPtBsMl{"binsPtBsMl", std::vector{hf_cuts_ml::vecBinsPt}, "pT bin limits for ML application"}; + Configurable> cutDirBsMl{"cutDirBsMl", std::vector{hf_cuts_ml::vecCutDir}, "Whether to reject score values greater or smaller than the threshold"}; + Configurable> cutsBsMl{"cutsBsMl", {hf_cuts_ml::Cuts[0], hf_cuts_ml::NBinsPt, hf_cuts_ml::NCutScores, hf_cuts_ml::labelsPt, hf_cuts_ml::labelsCutScore}, "ML selections per pT bin"}; + Configurable nClassesBsMl{"nClassesBsMl", static_cast(hf_cuts_ml::NCutScores), "Number of classes in ML model"}; + Configurable> namesInputFeatures{"namesInputFeatures", std::vector{"feature1", "feature2"}, "Names of ML model input features"}; + // CCDB configuration + Configurable ccdbUrl{"ccdbUrl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable> modelPathsCCDB{"modelPathsCCDB", std::vector{"path_ccdb/BDT_BS/"}, "Paths of models on CCDB"}; + Configurable> onnxFileNames{"onnxFileNames", std::vector{"ModelHandler_onnx_BSToJpsiPhi.onnx"}, "ONNX file names for each pT bin (if not from CCDB full path)"}; + Configurable timestampCCDB{"timestampCCDB", -1, "timestamp of the ONNX file for ML model used to query in CCDB"}; + Configurable loadModelsFromCCDB{"loadModelsFromCCDB", false, "Flag to enable or disable the loading of models from CCDB"}; + + HfHelper hfHelper; + TrackSelectorKa selectorKaon; + o2::analysis::HfMlResponseBsToJpsiPhiReduced hfMlResponse; + o2::ccdb::CcdbApi ccdbApi; + + using TracksKaon = soa::Join; + std::vector outputMl = {}; + + // Filter filterSelectCandidates = (aod::hf_sel_candidate_bplus::isSelBsToJpsiPi >= selectionFlagBs); + + HistogramRegistry registry{"registry"}; + + void init(InitContext&) + { + std::array processFuncData{doprocessData, doprocessDataWithBsMl}; + if ((std::accumulate(processFuncData.begin(), processFuncData.end(), 0)) > 1) { + LOGP(fatal, "Only one process function for data can be enabled at a time."); + } + std::array processFuncMc{doprocessMc, doprocessMcWithBsMl}; + if ((std::accumulate(processFuncMc.begin(), processFuncMc.end(), 0)) > 1) { + LOGP(fatal, "Only one process function for MC can be enabled at a time."); + } + + if (kaonPidMethod < 0 || kaonPidMethod >= PidMethod::NPidMethods) { + LOGP(fatal, "Invalid PID option in configurable, please set 0 (no PID), 1 (TPC or TOF), or 2 (TPC and TOF)"); + } + + if (kaonPidMethod != PidMethod::NoPid) { + selectorKaon.setRangePtTpc(ptPidTpcMin, ptPidTpcMax); + selectorKaon.setRangeNSigmaTpc(-nSigmaTpcMax, nSigmaTpcMax); + selectorKaon.setRangeNSigmaTpcCondTof(-nSigmaTpcCombinedMax, nSigmaTpcCombinedMax); + selectorKaon.setRangePtTof(ptPidTofMin, ptPidTofMax); + selectorKaon.setRangeNSigmaTof(-nSigmaTofMax, nSigmaTofMax); + selectorKaon.setRangeNSigmaTofCondTpc(-nSigmaTofCombinedMax, nSigmaTofCombinedMax); + } + + const AxisSpec axisMassBs{150, 4.5, 6.0}; + const AxisSpec axisMassJpsi{600, 2.8f, 3.4f}; + const AxisSpec axisMassPhi{200, 0.9f, 1.1f}; + const AxisSpec axisPtProng{100, 0., 10.}; + const AxisSpec axisImpactPar{200, -0.05, 0.05}; + const AxisSpec axisPtJpsi{100, 0., 50.}; + const AxisSpec axisRapidity{100, -2., 2.}; + const AxisSpec axisPtB{(std::vector)binsPt, "#it{p}_{T}^{B_{s}^{0}} (GeV/#it{c})"}; + const AxisSpec axisPtKa{100, 0.f, 10.f}; + const AxisSpec axisPtPhi{100, 0.f, 10.f}; + + 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) { + registry.add("hPtJpsiGen", mcParticleMatched + "J/#Psi #it{p}_{T}^{gen} (GeV/#it{c}); B_{s}^{0} " + stringPt, {HistType::kTH2F, {axisPtProng, axisPtB}}); + registry.add("hPtPhiGen", mcParticleMatched + "#phi #it{p}_{T}^{gen} (GeV/#it{c}); B_{s}^{0} " + stringPt, {HistType::kTH2F, {axisPtProng, axisPtB}}); + registry.add("hPtKGen", mcParticleMatched + "Kaon #it{p}_{T}^{gen} (GeV/#it{c}); B_{s}^{0} " + stringPt, {HistType::kTH2F, {axisPtProng, axisPtB}}); + registry.add("hYGenWithProngsInAcceptance", mcParticleMatched + "Kaon #it{p}_{T}^{gen} (GeV/#it{c}); B_{s}^{0} " + stringPt, {HistType::kTH2F, {axisPtProng, axisRapidity}}); + 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) { + hfMlResponse.configure(binsPtBsMl, cutsBsMl, cutDirBsMl, nClassesBsMl); + if (loadModelsFromCCDB) { + ccdbApi.init(ccdbUrl); + hfMlResponse.setModelPathsCCDB(onnxFileNames, ccdbApi, modelPathsCCDB, timestampCCDB); + } else { + hfMlResponse.setModelPathsLocal(onnxFileNames); + } + hfMlResponse.cacheInputFeaturesIndices(namesInputFeatures); + hfMlResponse.init(); + } + } + + /// Selection of Bs daughter in geometrical acceptance + /// \param etaProng is the pseudorapidity of Bs prong + /// \param ptProng is the pT of Bs prong + /// \return true if prong is in geometrical acceptance + template + bool isProngInAcceptance(const T& etaProng, const T& ptProng) + { + return std::abs(etaProng) <= etaTrackMax && ptProng >= ptTrackMin; + } + + /// Fill candidate information at reconstruction level + /// \param doMc is the flag to enable the filling with MC information + /// \param withBsMl is the flag to enable the filling with ML scores for the Bs candidate + /// \param candidate is the Bs candidate + /// \param candidatesJpsi is the table with Jpsi candidates + template + void fillCand(Cand const& candidate, + aod::HfRedJpsis const& /*candidatesJpsi*/, + aod::HfRedBach0Tracks const&, + aod::HfRedBach1Tracks const&) + { + auto ptCandBs = candidate.pt(); + auto invMassBs = hfHelper.invMassBsToJpsiPhi(candidate); + auto candJpsi = candidate.template jpsi_as(); + auto candKa0 = candidate.template prong0Phi_as(); + auto candKa1 = candidate.template prong1Phi_as(); + std::array pVecKa0 = {candKa0.px(), candKa0.py(), candKa0.pz()}; + std::array pVecKa1 = {candKa1.px(), candKa1.py(), candKa1.pz()}; + auto ptJpsi = candidate.ptProng0(); + auto invMassJpsi = candJpsi.m(); + auto invMassPhi = RecoDecay::m(std::array{pVecKa0, pVecKa1}, std::array{o2::constants::physics::MassKPlus, o2::constants::physics::MassKPlus}); + uint8_t statusBs = 0; + + int8_t flagMcMatchRec{0}, channelMcMatchRec{0}, flagWrongCollision{0}; + bool isSignal = false; + if constexpr (doMc) { + flagMcMatchRec = candidate.flagMcMatchRec(); + channelMcMatchRec = candidate.channelMcMatchRec(); + flagWrongCollision = candidate.flagWrongCollision(); + isSignal = flagMcMatchRec == o2::hf_decay::hf_cand_beauty::BsToJpsiKK && + channelMcMatchRec == o2::hf_decay::hf_cand_beauty::BsToJpsiPhi; + } + + SETBIT(statusBs, SelectionStep::RecoSkims); + if (hfHelper.selectionBsToJpsiPhiTopol(candidate, candKa0, candKa1, cuts, binsPt)) { + SETBIT(statusBs, SelectionStep::RecoTopol); + } else if (selectionFlagBs >= BIT(SelectionStep::RecoTopol) * 2 - 1) { + return; + } + // track-level PID selection + // auto trackKa = candidate.template prong1_as(); + if (kaonPidMethod == PidMethod::TpcOrTof || kaonPidMethod == PidMethod::TpcAndTof) { + int pidTrackKa0{TrackSelectorPID::Status::NotApplicable}; + int pidTrackKa1{TrackSelectorPID::Status::NotApplicable}; + if (kaonPidMethod == PidMethod::TpcOrTof) { + pidTrackKa0 = selectorKaon.statusTpcOrTof(candKa0); + pidTrackKa1 = selectorKaon.statusTpcOrTof(candKa1); + } else if (kaonPidMethod == PidMethod::TpcAndTof) { + pidTrackKa0 = selectorKaon.statusTpcAndTof(candKa0); + pidTrackKa1 = selectorKaon.statusTpcAndTof(candKa1); + } + if (hfHelper.selectionBsToJpsiPhiPid(pidTrackKa0, acceptPIDNotApplicable.value) && + hfHelper.selectionBsToJpsiPhiPid(pidTrackKa1, acceptPIDNotApplicable.value)) { + // LOGF(info, "Bs candidate selection failed at PID selection"); + SETBIT(statusBs, SelectionStep::RecoPID); + } else if (selectionFlagBs >= BIT(SelectionStep::RecoPID) * 2 - 1) { + return; + } + } + + float candidateMlScoreSig = -1; + if constexpr (withBsMl) { + // Bs ML selections + std::vector inputFeatures = hfMlResponse.getInputFeatures(candidate, candKa0, candKa1); + if (hfMlResponse.isSelectedMl(inputFeatures, ptCandBs, outputMl)) { + SETBIT(statusBs, SelectionStep::RecoMl); + } else if (selectionFlagBs >= BIT(SelectionStep::RecoMl) * 2 - 1) { + return; + } + candidateMlScoreSig = outputMl[1]; + } + + 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()); + 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()); + } else if (fillBackground) { + registry.fill(HIST("hMassRecBg"), invMassBs, ptCandBs); + registry.fill(HIST("hMassJpsiRecBg"), invMassJpsi, candidate.ptProng0()); + registry.fill(HIST("hd0KRecBg"), candidate.impactParameter1(), candidate.ptProng1()); + } + } + + float pseudoRndm = ptJpsi * 1000. - static_cast(ptJpsi * 1000); + if (ptCandBs >= ptMaxForDownSample || pseudoRndm < downSampleBkgFactor) { + float ptMother = -1.; + if constexpr (doMc) { + ptMother = candidate.ptMother(); + } + + hfRedCandBsLite( + // Bs - meson features + invMassBs, + ptCandBs, + candidate.eta(), + candidate.phi(), + hfHelper.yBs(candidate), + candidate.cpa(), + candidate.cpaXY(), + candidate.chi2PCA(), + candidate.decayLength(), + candidate.decayLengthXY(), + candidate.decayLengthNormalised(), + candidate.decayLengthXYNormalised(), + candidate.ctXY(std::array{o2::constants::physics::MassMuon, o2::constants::physics::MassMuon, o2::constants::physics::MassKPlus, o2::constants::physics::MassKPlus}), + candidate.impactParameterProduct(), + candidate.impactParameterProductJpsi(), + candidate.impactParameterProductPhi(), + candidate.maxNormalisedDeltaIP(), + candidateMlScoreSig, + // J/Psi features + invMassJpsi, + ptJpsi, + invMassPhi, + candidate.impactParameter0(), + candidate.impactParameter1(), + candidate.impactParameter2(), + candidate.impactParameter3(), + // candJpsi.ptProngMin(), + // candJpsi.absEtaProngMin(), + // candJpsi.itsNClsProngMin(), + // candJpsi.tpcNClsCrossedRowsProngMin(), + // candJpsi.tpcChi2NClProngMax(), + // kaon features + candKa0.pt(), + // std::abs(RecoDecay::eta(candKa0.pVector())), + // candKa0.itsNCls(), + // candKa0.tpcNClsCrossedRows(), + // candKa0.tpcChi2NCl(), + candKa0.tpcNSigmaKa(), + candKa0.tofNSigmaKa(), + candKa0.tpcTofNSigmaKa(), + candKa1.pt(), + candKa1.tpcNSigmaKa(), + candKa1.tofNSigmaKa(), + candKa1.tpcTofNSigmaKa(), + // MC truth + flagMcMatchRec, + channelMcMatchRec, + isSignal, + flagWrongCollision, + ptMother); + } + } + + /// Fill particle histograms (gen MC truth) + void fillCandMcGen(aod::HfMcGenRedBss::iterator const& particle) + { + auto ptParticle = particle.ptTrack(); + auto yParticle = particle.yTrack(); + if (yCandGenMax >= 0. && std::abs(yParticle) > yCandGenMax) { + return; + } + std::array ptProngs = {particle.ptProng0(), particle.ptProng1()}; + std::array etaProngs = {particle.etaProng0(), particle.etaProng1()}; + bool prongsInAcc = isProngInAcceptance(etaProngs[0], ptProngs[0]) && isProngInAcceptance(etaProngs[1], ptProngs[1]); + + registry.fill(HIST("hPtJpsiGen"), ptProngs[0], ptParticle); + registry.fill(HIST("hPtKGen"), ptProngs[1], ptParticle); + + // generated Bs with daughters in geometrical acceptance + if (prongsInAcc) { + registry.fill(HIST("hYGenWithProngsInAcceptance"), ptParticle, yParticle); + } + } + + // Process functions + void processData(aod::HfRedCandBsToJpsiPhi const& candidates, + aod::HfRedJpsis const& candidatesJpsi, + aod::HfRedBach0Tracks const& kaon0Tracks, + aod::HfRedBach1Tracks const& kaon1Tracks) + { + for (const auto& candidate : candidates) { + if (yCandRecoMax >= 0. && std::abs(hfHelper.yBs(candidate)) > yCandRecoMax) { + continue; + } + fillCand(candidate, candidatesJpsi, kaon0Tracks, kaon1Tracks); + } // candidate loop + } // processData + PROCESS_SWITCH(HfTaskBsToJpsiPhiReduced, processData, "Process data without ML for Bs", true); + + void processDataWithBsMl(aod::HfRedCandBsToJpsiPhi const& candidates, + aod::HfRedJpsis const& candidatesJpsi, + aod::HfRedBach0Tracks const& kaon0Tracks, + aod::HfRedBach1Tracks const& kaon1Tracks) + { + for (const auto& candidate : candidates) { + if (yCandRecoMax >= 0. && std::abs(hfHelper.yBs(candidate)) > yCandRecoMax) { + continue; + } + fillCand(candidate, candidatesJpsi, kaon0Tracks, kaon1Tracks); + } // candidate loop + } // processDataWithBsMl + PROCESS_SWITCH(HfTaskBsToJpsiPhiReduced, processDataWithBsMl, "Process data with ML for Bs", false); + + void processMc(soa::Join const& candidates, + aod::HfMcGenRedBss const& mcParticles, + aod::HfRedJpsis const& candidatesJpsi, + aod::HfRedBach0Tracks const& kaon0Tracks, + aod::HfRedBach1Tracks const& kaon1Tracks) + { + // MC rec + for (const auto& candidate : candidates) { + if (yCandRecoMax >= 0. && std::abs(hfHelper.yBs(candidate)) > yCandRecoMax) { + continue; + } + fillCand(candidate, candidatesJpsi, kaon0Tracks, kaon1Tracks); + } // rec + + // MC gen. level + for (const auto& particle : mcParticles) { + fillCandMcGen(particle); + } // gen + } // processMc + PROCESS_SWITCH(HfTaskBsToJpsiPhiReduced, processMc, "Process MC without ML for Bs", false); + + void processMcWithBsMl(soa::Join const& candidates, + aod::HfMcGenRedBss const& mcParticles, + aod::HfRedJpsis const& candidatesJpsi, + aod::HfRedBach0Tracks const& kaon0Tracks, + aod::HfRedBach1Tracks const& kaon1Tracks) + { + // MC rec + for (const auto& candidate : candidates) { + if (yCandRecoMax >= 0. && std::abs(hfHelper.yBs(candidate)) > yCandRecoMax) { + continue; + } + fillCand(candidate, candidatesJpsi, kaon0Tracks, kaon1Tracks); + } // rec + + // MC gen. level + for (const auto& particle : mcParticles) { + fillCandMcGen(particle); + } // gen + } // processMcWithBsMl + PROCESS_SWITCH(HfTaskBsToJpsiPhiReduced, processMcWithBsMl, "Process MC with ML for Bs", false); + +}; // struct + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} diff --git a/PWGHF/D2H/Utils/utilsRedDataFormat.h b/PWGHF/D2H/Utils/utilsRedDataFormat.h index a083e9713b2..513f2a998fc 100644 --- a/PWGHF/D2H/Utils/utilsRedDataFormat.h +++ b/PWGHF/D2H/Utils/utilsRedDataFormat.h @@ -16,16 +16,16 @@ #ifndef PWGHF_D2H_UTILS_UTILSREDDATAFORMAT_H_ #define PWGHF_D2H_UTILS_UTILSREDDATAFORMAT_H_ -#include - -#include +#include "PWGHF/Core/CentralityEstimation.h" +#include "PWGHF/Utils/utilsEvSelHf.h" #include "CCDB/BasicCCDBManager.h" #include "Framework/AnalysisHelpers.h" #include "Framework/HistogramRegistry.h" -#include "PWGHF/Core/CentralityEstimation.h" -#include "PWGHF/Utils/utilsEvSelHf.h" +#include + +#include namespace o2::hf_evsel { @@ -81,6 +81,31 @@ float getTpcTofNSigmaPi1(const T1& prong1) } return defaultNSigma; } + +/// Helper function to retrive PID information of bachelor kaon from b-hadron decay +/// \param prong1 kaon track from reduced data format, aod::HfRedBachProng0Tracks +/// \return the combined TPC and TOF n-sigma for kaon +template +float getTpcTofNSigmaKa1(const T1& prong1) +{ + float defaultNSigma = -999.f; // -999.f is the default value set in TPCPIDResponse.h and PIDTOF.h + + bool hasTpc = prong1.hasTPC(); + bool hasTof = prong1.hasTOF(); + + if (hasTpc && hasTof) { + float tpcNSigma = prong1.tpcNSigmaKa(); + float tofNSigma = prong1.tofNSigmaKa(); + return std::sqrt(.5f * tpcNSigma * tpcNSigma + .5f * tofNSigma * tofNSigma); + } + if (hasTpc) { + return std::abs(prong1.tpcNSigmaKa()); + } + if (hasTof) { + return std::abs(prong1.tofNSigmaKa()); + } + return defaultNSigma; +} } // namespace o2::pid_tpc_tof_utils #endif // PWGHF_D2H_UTILS_UTILSREDDATAFORMAT_H_ diff --git a/PWGHF/DataModel/CandidateReconstructionTables.h b/PWGHF/DataModel/CandidateReconstructionTables.h index 014bfa3e32e..a32a88e1d12 100644 --- a/PWGHF/DataModel/CandidateReconstructionTables.h +++ b/PWGHF/DataModel/CandidateReconstructionTables.h @@ -18,13 +18,9 @@ #ifndef PWGHF_DATAMODEL_CANDIDATERECONSTRUCTIONTABLES_H_ #define PWGHF_DATAMODEL_CANDIDATERECONSTRUCTIONTABLES_H_ -#include -#include -#include - -#include -#include -#include +#include "PWGHF/Core/DecayChannels.h" // FIXME: temporary until propagated where needed +#include "PWGHF/Utils/utilsPid.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" #include "ALICE3/DataModel/ECAL.h" #include "Common/Core/RecoDecay.h" @@ -32,10 +28,13 @@ #include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "PWGLF/DataModel/LFStrangenessTables.h" +#include +#include +#include -#include "PWGHF/Utils/utilsPid.h" -#include "PWGHF/Core/DecayChannels.h" // FIXME: temporary until propagated where needed +#include +#include +#include namespace o2::aod { @@ -485,6 +484,23 @@ DECLARE_SOA_COLUMN(ImpactParameterZ2, impactParameterZ2, float); DECLARE_SOA_COLUMN(ErrorImpactParameterZ2, errorImpactParameterZ2, float); //! DECLARE_SOA_DYNAMIC_COLUMN(ImpactParameterZNormalised2, impactParameterZNormalised2, //! [](float dca, float err) -> float { return dca / err; }); +DECLARE_SOA_COLUMN(PxProng3, pxProng3, float); //! +DECLARE_SOA_COLUMN(PyProng3, pyProng3, float); //! +DECLARE_SOA_COLUMN(PzProng3, pzProng3, float); //! +DECLARE_SOA_DYNAMIC_COLUMN(PtProng3, ptProng3, //! + [](float px, float py) -> float { return RecoDecay::pt(px, py); }); +DECLARE_SOA_DYNAMIC_COLUMN(Pt2Prong3, pt2Prong3, //! + [](float px, float py) -> float { return RecoDecay::pt2(px, py); }); +DECLARE_SOA_DYNAMIC_COLUMN(PVectorProng3, pVectorProng3, //! + [](float px, float py, float pz) -> std::array { return std::array{px, py, pz}; }); +DECLARE_SOA_COLUMN(ImpactParameter3, impactParameter3, float); //! +DECLARE_SOA_COLUMN(ErrorImpactParameter3, errorImpactParameter3, float); //! +DECLARE_SOA_DYNAMIC_COLUMN(ImpactParameterNormalised3, impactParameterNormalised3, //! + [](float dca, float err) -> float { return dca / err; }); +DECLARE_SOA_COLUMN(ImpactParameterZ3, impactParameterZ3, float); //! +DECLARE_SOA_COLUMN(ErrorImpactParameterZ3, errorImpactParameterZ3, float); //! +DECLARE_SOA_DYNAMIC_COLUMN(ImpactParameterZNormalised3, impactParameterZNormalised3, //! + [](float dca, float err) -> float { return dca / err; }); DECLARE_SOA_COLUMN(NProngsContributorsPV, nProngsContributorsPV, uint8_t); //! number of prongs contributing to the primary-vertex reconstruction DECLARE_SOA_COLUMN(BitmapProngsContributorsPV, bitmapProngsContributorsPV, uint8_t); //! bitmap with booleans indicating prongs contributing to the primary-vertex reconstruction /// prong PID nsigma @@ -618,6 +634,8 @@ DECLARE_SOA_DYNAMIC_COLUMN(ImpactParameterProngSqSum, impactParameterProngSqSum, [](float impParProng0, float impParProng1) -> float { return RecoDecay::sumOfSquares(impParProng0, impParProng1); }); DECLARE_SOA_DYNAMIC_COLUMN(MaxNormalisedDeltaIP, maxNormalisedDeltaIP, //! [](float xVtxP, float yVtxP, float xVtxS, float yVtxS, float errDlxy, float pxM, float pyM, float ip0, float errIp0, float ip1, float errIp1, float px0, float py0, float px1, float py1) -> float { return RecoDecay::maxNormalisedDeltaIP(std::array{xVtxP, yVtxP}, std::array{xVtxS, yVtxS}, errDlxy, std::array{pxM, pyM}, std::array{ip0, ip1}, std::array{errIp0, errIp1}, std::array{std::array{px0, py0}, std::array{px1, py1}}); }); +DECLARE_SOA_DYNAMIC_COLUMN(CtXY, ctXY, //! + [](float px0, float py0, float pz0, float px1, float py1, float pz1, float xVtxP, float yVtxP, float xVtxS, float yVtxS, const std::array& m) -> float { return RecoDecay::ctXY(std::array{xVtxP, yVtxP}, std::array{xVtxS, yVtxS}, std::array{std::array{px0, py0, pz0}, std::array{px1, py1, pz1}}, m); }); // MC matching result: DECLARE_SOA_COLUMN(FlagMcMatchRec, flagMcMatchRec, int8_t); //! reconstruction level DECLARE_SOA_COLUMN(FlagMcMatchGen, flagMcMatchGen, int8_t); //! generator level @@ -851,12 +869,17 @@ namespace hf_cand_bplus { DECLARE_SOA_INDEX_COLUMN_FULL(Prong0, prong0, int, HfCand2Prong, "_0"); // D0 index // MC matching result: -DECLARE_SOA_COLUMN(FlagMcMatchRec, flagMcMatchRec, int8_t); // reconstruction level -DECLARE_SOA_COLUMN(FlagWrongCollision, flagWrongCollision, int8_t); // reconstruction level -DECLARE_SOA_COLUMN(FlagMcMatchGen, flagMcMatchGen, int8_t); // generator level -DECLARE_SOA_COLUMN(OriginMcRec, originMcRec, int8_t); // particle origin, reconstruction level -DECLARE_SOA_COLUMN(OriginMcGen, originMcGen, int8_t); // particle origin, generator level -DECLARE_SOA_COLUMN(DebugMcRec, debugMcRec, int8_t); // debug flag for mis-association reconstruction level +DECLARE_SOA_COLUMN(FlagMcMatchRec, flagMcMatchRec, int8_t); // reconstruction level +DECLARE_SOA_COLUMN(ChannelMcMatchRec, channelMcMatchRec, int8_t); // reconstruction level +DECLARE_SOA_COLUMN(FlagWrongCollision, flagWrongCollision, int8_t); // reconstruction level +DECLARE_SOA_COLUMN(FlagMcMatchGen, flagMcMatchGen, int8_t); // generator level +DECLARE_SOA_COLUMN(OriginMcRec, originMcRec, int8_t); // particle origin, reconstruction level +DECLARE_SOA_COLUMN(OriginMcGen, originMcGen, int8_t); // particle origin, generator level +DECLARE_SOA_COLUMN(DebugMcRec, debugMcRec, int8_t); // debug flag for mis-association reconstruction level +DECLARE_SOA_DYNAMIC_COLUMN(ImpactParameterProduct, impactParameterProduct, // Impact parameter product for B+ -> J/Psi K + [](float px0, float py0, float pz0, float px1, float py1, float pz1, float xVtxP, float yVtxP, float zVtxP, float xVtxS, float yVtxS, float zVtxS, float impParK) -> float { return impParK * RecoDecay::impParXY(std::array{xVtxP, yVtxP, zVtxP}, std::array{xVtxS, yVtxS, zVtxS}, RecoDecay::pVec(std::array{px0, py0, pz0}, std::array{px1, py1, pz1})); }); +DECLARE_SOA_DYNAMIC_COLUMN(ImpactParameterProductJpsi, impactParameterProductJpsi, // J/Psi impact parameter for B+ -> J/Psi K + [](float dcaDauPos, float dcaDauNeg) -> float { return dcaDauPos * dcaDauNeg; }); enum DecayType { BplusToD0Pi = 0 }; @@ -865,6 +888,11 @@ enum DecayTypeMc : uint8_t { BplusToD0PiToKPiPi = 0, PartlyRecoDecay, OtherDecay, NDecayTypeMc }; + +enum class DecayTypeBToJpsiMc : uint8_t { BplusToJpsiKToMuMuK = 0, + PartlyRecoDecay, + OtherDecay, + NDecayTypeMc }; } // namespace hf_cand_bplus // declare dedicated BPlus decay candidate table @@ -898,7 +926,8 @@ DECLARE_SOA_TABLE(HfCandBplusBase, "AOD", "HFCANDBPLUSBASE", hf_cand::Phi, hf_cand::Y, hf_cand::E, - hf_cand::E2); + hf_cand::E2, + hf_cand_2prong::CtXY); // extended table with expression columns that can be used as arguments of dynamic columns DECLARE_SOA_EXTENDED_TABLE_USER(HfCandBplusExt, HfCandBplusBase, "HFCANDBPLUSEXT", @@ -936,6 +965,10 @@ DECLARE_SOA_DYNAMIC_COLUMN(ImpactParameterProngSqSum, impactParameterProngSqSum, [](float impParProng0, float impParProng1, float impParProng2) -> float { return RecoDecay::sumOfSquares(impParProng0, impParProng1, impParProng2); }); DECLARE_SOA_DYNAMIC_COLUMN(MaxNormalisedDeltaIP, maxNormalisedDeltaIP, //! [](float xVtxP, float yVtxP, float xVtxS, float yVtxS, float errDlxy, float pxM, float pyM, float ip0, float errIp0, float ip1, float errIp1, float ip2, float errIp2, float px0, float py0, float px1, float py1, float px2, float py2) -> float { return RecoDecay::maxNormalisedDeltaIP(std::array{xVtxP, yVtxP}, std::array{xVtxS, yVtxS}, errDlxy, std::array{pxM, pyM}, std::array{ip0, ip1, ip2}, std::array{errIp0, errIp1, errIp2}, std::array{std::array{px0, py0}, std::array{px1, py1}, std::array{px2, py2}}); }); +DECLARE_SOA_DYNAMIC_COLUMN(CtXY, ctXY, //! + [](float px0, float py0, float pz0, float px1, float py1, float pz1, float px2, float py2, float pz2, float xVtxP, float yVtxP, float xVtxS, float yVtxS, const std::array& m) -> float { + return RecoDecay::ctXY(std::array{xVtxP, yVtxP}, std::array{xVtxS, yVtxS}, std::array{std::array{px0, py0, pz0}, std::array{px1, py1, pz1}, std::array{px2, py2, pz2}}, m); + }); // MC matching result: DECLARE_SOA_COLUMN(FlagMcMatchRec, flagMcMatchRec, int8_t); //! reconstruction level DECLARE_SOA_COLUMN(FlagMcMatchGen, flagMcMatchGen, int8_t); //! generator level @@ -1077,6 +1110,55 @@ DECLARE_SOA_TABLE(HfCand3ProngMcGen, "AOD", "HFCAND3PMCGEN", //! hf_cand_3prong::FlagMcDecayChanGen, hf_cand::IdxBhadMotherPart); +// declare dedicated BPlus -> J/Psi K decay candidate table +// convention: prongs 0 and 1 should be J/Psi decay products +DECLARE_SOA_TABLE(HfCandBpJPBase, "AOD", "HFCANDBPJPBASE", + // general columns + HFCAND_COLUMNS, + /* prong 2 */ hf_cand::ImpactParameterNormalised2, + hf_cand::PtProng2, + hf_cand::Pt2Prong2, + hf_cand::PVectorProng2, + // 3-prong specific columns + o2::soa::Index<>, + hf_cand::PxProng0, hf_cand::PyProng0, hf_cand::PzProng0, + hf_cand::PxProng1, hf_cand::PyProng1, hf_cand::PzProng1, + hf_cand::PxProng2, hf_cand::PyProng2, hf_cand::PzProng2, + hf_cand::ImpactParameter0, hf_cand::ImpactParameter1, hf_cand::ImpactParameter2, + hf_cand::ErrorImpactParameter0, hf_cand::ErrorImpactParameter1, hf_cand::ErrorImpactParameter2, + /* dynamic columns */ + hf_cand_3prong::M, + hf_cand_3prong::M2, + hf_cand_3prong::ImpactParameterProngSqSum, + hf_cand_bplus::ImpactParameterProduct, + hf_cand_bplus::ImpactParameterProductJpsi, + /* 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_3prong::MaxNormalisedDeltaIP, + hf_cand::Eta, + hf_cand::Phi, + hf_cand::Y, + hf_cand::E, + hf_cand::E2, + hf_cand_3prong::CtXY); + +// extended table with expression columns that can be used as arguments of dynamic columns +DECLARE_SOA_EXTENDED_TABLE_USER(HfCandBpJPExt, HfCandBpJPBase, "HFCANDBPJPEXT", + hf_cand_3prong::Px, hf_cand_3prong::Py, hf_cand_3prong::Pz); + +DECLARE_SOA_TABLE(HfCandBpJPDaus, "AOD", "HFCANDBPJPDAUS", + hf_track_index::Prong0Id, hf_track_index::Prong1Id, hf_track_index::Prong2Id); + +using HfCandBplusToJpsi = soa::Join; + namespace hf_cand_casc_lf { // mapping of decay types @@ -1979,6 +2061,7 @@ namespace hf_cand_b0 DECLARE_SOA_INDEX_COLUMN_FULL(Prong0, prong0, int, HfCand3Prong, "_0"); // D index // MC matching result: DECLARE_SOA_COLUMN(FlagMcMatchRec, flagMcMatchRec, int8_t); // reconstruction level +DECLARE_SOA_COLUMN(ChannelMcMatchRec, channelMcMatchRec, int8_t); // reconstruction level DECLARE_SOA_COLUMN(FlagWrongCollision, flagWrongCollision, int8_t); // reconstruction level DECLARE_SOA_COLUMN(FlagMcMatchGen, flagMcMatchGen, int8_t); // generator level DECLARE_SOA_COLUMN(OriginMcRec, originMcRec, int8_t); // particle origin, reconstruction level @@ -1986,7 +2069,7 @@ DECLARE_SOA_COLUMN(OriginMcGen, originMcGen, int8_t); // particle DECLARE_SOA_COLUMN(DebugMcRec, debugMcRec, int8_t); // debug flag for mis-association reconstruction level // mapping of decay types -enum DecayType { B0ToDPi }; +enum DecayType { B0ToDPi = 0 }; enum DecayTypeMc : uint8_t { B0ToDplusPiToPiKPiPi = 0, B0ToDsPiToKKPiPi, @@ -2054,15 +2137,26 @@ namespace hf_cand_bs { DECLARE_SOA_INDEX_COLUMN_FULL(Prong0, prong0, int, HfCand3Prong, "_0"); // Ds index // MC matching result: -DECLARE_SOA_COLUMN(FlagMcMatchRec, flagMcMatchRec, int8_t); // reconstruction level -DECLARE_SOA_COLUMN(FlagWrongCollision, flagWrongCollision, int8_t); // reconstruction level -DECLARE_SOA_COLUMN(FlagMcMatchGen, flagMcMatchGen, int8_t); // generator level -DECLARE_SOA_COLUMN(OriginMcRec, originMcRec, int8_t); // particle origin, reconstruction level -DECLARE_SOA_COLUMN(OriginMcGen, originMcGen, int8_t); // particle origin, generator level -DECLARE_SOA_COLUMN(DebugMcRec, debugMcRec, int8_t); // debug flag for mis-association reconstruction level +DECLARE_SOA_COLUMN(FlagMcMatchRec, flagMcMatchRec, int8_t); // reconstruction level +DECLARE_SOA_COLUMN(ChannelMcMatchRec, channelMcMatchRec, int8_t); // reconstruction level +DECLARE_SOA_COLUMN(FlagWrongCollision, flagWrongCollision, int8_t); // reconstruction level +DECLARE_SOA_COLUMN(FlagMcMatchGen, flagMcMatchGen, int8_t); // generator level +DECLARE_SOA_COLUMN(OriginMcRec, originMcRec, int8_t); // particle origin, reconstruction level +DECLARE_SOA_COLUMN(OriginMcGen, originMcGen, int8_t); // particle origin, generator level +DECLARE_SOA_COLUMN(DebugMcRec, debugMcRec, int8_t); // debug flag for mis-association reconstruction level +DECLARE_SOA_DYNAMIC_COLUMN(ImpactParameterProduct, impactParameterProduct, // Impact parameter product for Bs -> J/Psi phi + [](float pxJpsiDauPos, float pyJpsiDauPos, float pzJpsiDauPos, float pxJpsiDauNeg, float pyJpsiDauNeg, float pzJpsiDauNeg, float pxLfTrack0, float pyLfTrack0, float pzLfTrack0, float pxLfTrack1, float pyLfTrack1, float pzLfTrack1, float xVtxP, float yVtxP, float zVtxP, float xVtxS, float yVtxS, float zVtxS) -> float { + float impParJpsi = RecoDecay::impParXY(std::array{xVtxP, yVtxP, zVtxP}, std::array{xVtxS, yVtxS, zVtxS}, RecoDecay::pVec(std::array{pxJpsiDauPos, pyJpsiDauPos, pzJpsiDauPos}, std::array{pxJpsiDauNeg, pyJpsiDauNeg, pzJpsiDauNeg})); + float impParPhi = RecoDecay::impParXY(std::array{xVtxP, yVtxP, zVtxP}, std::array{xVtxS, yVtxS, zVtxS}, RecoDecay::pVec(std::array{pxLfTrack0, pyLfTrack0, pzLfTrack0}, std::array{pxLfTrack1, pyLfTrack1, pzLfTrack1})); + return impParJpsi * impParPhi; + }); +DECLARE_SOA_DYNAMIC_COLUMN(ImpactParameterProductJpsi, impactParameterProductJpsi, // J/Psi impact parameter for Bs -> J/Psi phi + [](float dcaDauPos, float dcaDauNeg) -> float { return dcaDauPos * dcaDauNeg; }); +DECLARE_SOA_DYNAMIC_COLUMN(ImpactParameterProductPhi, impactParameterProductPhi, // J/Psi impact parameter for Bs -> J/Psi phi + [](float dcaLfTrack0, float dcaLfTrack1) -> float { return dcaLfTrack0 * dcaLfTrack1; }); // mapping of decay types -enum DecayType { BsToDsPi }; +enum DecayType { BsToDsPi = 0 }; enum DecayTypeMc : uint8_t { BsToDsPiToPhiPiPiToKKPiPi = 0, // Bs(bar) → Ds∓ π± → (Phi π∓) π± → (K- K+ π∓) π± BsToDsPiToK0starKPiToKKPiPi, // Bs(bar) → Ds∓ π± → (K0* K∓) π± → (K- K+ π∓) π± @@ -2074,6 +2168,11 @@ enum DecayTypeMc : uint8_t { BsToDsPiToPhiPiPiToKKPiPi = 0, // Bs(bar) → Ds∓ OtherDecay, NDecayTypeMc }; // counter of differentiated MC decay types +enum class DecayTypeBToJpsiMc : uint8_t { BsToJpsiPhiToMuMuKK = 0, // Bs(bar) → J/Psi Phi → (µ+ µ-) (K- K+) + PartlyRecoDecay, // 4 final state particles have another common b-hadron ancestor + OtherDecay, + NDecayTypeMc }; // counter of differentiated MC decay types + } // namespace hf_cand_bs // declare dedicated Bs decay candidate table @@ -2107,6 +2206,7 @@ DECLARE_SOA_TABLE(HfCandBsBase, "AOD", "HFCANDBSBASE", hf_cand::Y, hf_cand::E, hf_cand::E2, + hf_cand_2prong::CtXY, o2::soa::Marker<1>); // extended table with expression columns that can be used as arguments of dynamic columns @@ -2126,6 +2226,82 @@ DECLARE_SOA_TABLE(HfCandBsMcRec, "AOD", "HFCANDBSMCREC", DECLARE_SOA_TABLE(HfCandBsMcGen, "AOD", "HFCANDBSMCGEN", hf_cand_bs::FlagMcMatchGen); +namespace hf_cand_4prong +{ +DECLARE_SOA_EXPRESSION_COLUMN(Px, px, //! + float, 1.f * aod::hf_cand::pxProng0 + 1.f * aod::hf_cand::pxProng1 + 1.f * aod::hf_cand::pxProng2 + 1.f * aod::hf_cand::pxProng3); +DECLARE_SOA_EXPRESSION_COLUMN(Py, py, //! + float, 1.f * aod::hf_cand::pyProng0 + 1.f * aod::hf_cand::pyProng1 + 1.f * aod::hf_cand::pyProng2 + 1.f * aod::hf_cand::pyProng3); +DECLARE_SOA_EXPRESSION_COLUMN(Pz, pz, //! + float, 1.f * aod::hf_cand::pzProng0 + 1.f * aod::hf_cand::pzProng1 + 1.f * aod::hf_cand::pzProng2 + 1.f * aod::hf_cand::pzProng3); +DECLARE_SOA_DYNAMIC_COLUMN(M, m, //! + [](float px0, float py0, float pz0, float px1, float py1, float pz1, float px2, float py2, float pz2, float px3, float py3, float pz3, const std::array& m) -> float { return RecoDecay::m(std::array{std::array{px0, py0, pz0}, std::array{px1, py1, pz1}, std::array{px2, py2, pz2}, std::array{px3, py3, pz3}}, m); }); +DECLARE_SOA_DYNAMIC_COLUMN(M2, m2, //! + [](float px0, float py0, float pz0, float px1, float py1, float pz1, float px2, float py2, float pz2, float px3, float py3, float pz3, const std::array& m) -> float { return RecoDecay::m2(std::array{std::array{px0, py0, pz0}, std::array{px1, py1, pz1}, std::array{px2, py2, pz2}, std::array{px3, py3, pz3}}, m); }); +DECLARE_SOA_DYNAMIC_COLUMN(ImpactParameterProngSqSum, impactParameterProngSqSum, //! + [](float impParProng0, float impParProng1, float impParProng2, float impParProng3) -> float { return RecoDecay::sumOfSquares(impParProng0, impParProng1, impParProng2, impParProng3); }); +DECLARE_SOA_DYNAMIC_COLUMN(MaxNormalisedDeltaIP, maxNormalisedDeltaIP, //! + [](float xVtxP, float yVtxP, float xVtxS, float yVtxS, float errDlxy, float pxM, float pyM, float ip0, float errIp0, float ip1, float errIp1, float ip2, float errIp2, float ip3, float errIp3, float px0, float py0, float px1, float py1, float px2, float py2, float px3, float py3) -> float { return RecoDecay::maxNormalisedDeltaIP(std::array{xVtxP, yVtxP}, std::array{xVtxS, yVtxS}, errDlxy, std::array{pxM, pyM}, std::array{ip0, ip1, ip2, ip3}, std::array{errIp0, errIp1, errIp2, errIp3}, std::array{std::array{px0, py0}, std::array{px1, py1}, std::array{px2, py2}, std::array{px3, py3}}); }); +DECLARE_SOA_DYNAMIC_COLUMN(CtXY, ctXY, //! + [](float px0, float py0, float pz0, float px1, float py1, float pz1, float px2, float py2, float pz2, float px3, float py3, float pz3, float xVtxP, float yVtxP, float xVtxS, float yVtxS, const std::array& m) -> float { return RecoDecay::ctXY(std::array{xVtxP, yVtxP}, std::array{xVtxS, yVtxS}, std::array{std::array{px0, py0, pz0}, std::array{px1, py1, pz1}, std::array{px2, py2, pz2}, std::array{px3, py3, pz3}}, m); }); +} // namespace hf_cand_4prong + +// declare dedicated Bs -> J/Psi phi decay candidate table +// convention: prongs 0 and 1 should be J/Psi decay products, 2 and 3 should be phi decay products +DECLARE_SOA_TABLE(HfCandBsJPBase, "AOD", "HFCANDBSJPBASE", + // general columns + HFCAND_COLUMNS, + /* prong 2 */ hf_cand::ImpactParameterNormalised2, + hf_cand::PtProng2, + hf_cand::Pt2Prong2, + hf_cand::PVectorProng2, + /* prong 3 */ hf_cand::ImpactParameterNormalised3, + hf_cand::PtProng3, + hf_cand::Pt2Prong3, + hf_cand::PVectorProng3, + // 4-prong specific columns + o2::soa::Index<>, + hf_cand::PxProng0, hf_cand::PyProng0, hf_cand::PzProng0, + hf_cand::PxProng1, hf_cand::PyProng1, hf_cand::PzProng1, + hf_cand::PxProng2, hf_cand::PyProng2, hf_cand::PzProng2, + hf_cand::PxProng3, hf_cand::PyProng3, hf_cand::PzProng3, + hf_cand::ImpactParameter0, hf_cand::ImpactParameter1, hf_cand::ImpactParameter2, hf_cand::ImpactParameter3, + hf_cand::ErrorImpactParameter0, hf_cand::ErrorImpactParameter1, hf_cand::ErrorImpactParameter2, hf_cand::ErrorImpactParameter3, + /* dynamic columns */ + hf_cand_4prong::M, + hf_cand_4prong::M2, + hf_cand_4prong::ImpactParameterProngSqSum, + hf_cand_bs::ImpactParameterProduct, + hf_cand_bs::ImpactParameterProductJpsi, + hf_cand_bs::ImpactParameterProductPhi, + /* 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_4prong::MaxNormalisedDeltaIP, + hf_cand::Eta, + hf_cand::Phi, + hf_cand::Y, + hf_cand::E, + hf_cand::E2, + hf_cand_4prong::CtXY, + o2::soa::Marker<1>); + +// extended table with expression columns that can be used as arguments of dynamic columns +DECLARE_SOA_EXTENDED_TABLE_USER(HfCandBsJPExt, HfCandBsJPBase, "HFCANDBSJPEXT", + hf_cand_4prong::Px, hf_cand_4prong::Py, hf_cand_4prong::Pz); + +DECLARE_SOA_TABLE(HfCandBsJPDaus, "AOD", "HFCANDBSJPDAUS", + hf_cand_bs::Prong0Id, hf_track_index::Prong1Id, hf_track_index::Prong2Id, hf_track_index::Prong3Id); + +using HfCandBsToJpsi = soa::Join; + // specific Σc0,++ candidate properties namespace hf_cand_sigmac { diff --git a/PWGHF/DataModel/CandidateSelectionTables.h b/PWGHF/DataModel/CandidateSelectionTables.h index f693605f635..0ac6ffa1a98 100644 --- a/PWGHF/DataModel/CandidateSelectionTables.h +++ b/PWGHF/DataModel/CandidateSelectionTables.h @@ -250,19 +250,23 @@ DECLARE_SOA_TABLE(HfMlB0ToDPi, "AOD", "HFMLB0", //! namespace hf_sel_candidate_bs { -DECLARE_SOA_COLUMN(IsSelBsToDsPi, isSelBsToDsPi, int); //! -DECLARE_SOA_COLUMN(MlProbBsToDsPi, mlProbBsToDsPi, std::vector); //! +DECLARE_SOA_COLUMN(IsSelBsToDsPi, isSelBsToDsPi, int); //! +DECLARE_SOA_COLUMN(MlProbBsToDsPi, mlProbBsToDsPi, std::vector); //! +DECLARE_SOA_COLUMN(MlProbBsToJpsiPhi, mlProbBsToJpsiPhi, std::vector); //! } // namespace hf_sel_candidate_bs DECLARE_SOA_TABLE(HfSelBsToDsPi, "AOD", "HFSELBS", //! hf_sel_candidate_bs::IsSelBsToDsPi); DECLARE_SOA_TABLE(HfMlBsToDsPi, "AOD", "HFMLBS", //! hf_sel_candidate_bs::MlProbBsToDsPi); +DECLARE_SOA_TABLE(HfMlBsToJpsiPhi, "AOD", "HFMLBSTOJPSIPHI", //! + hf_sel_candidate_bs::MlProbBsToDsPi); namespace hf_sel_candidate_bplus { -DECLARE_SOA_COLUMN(IsSelBplusToD0Pi, isSelBplusToD0Pi, int); //! selection flag on B+ candidate -DECLARE_SOA_COLUMN(MlProbBplusToD0Pi, mlProbBplusToD0Pi, float); //! ML score of B+ candidate for signal class +DECLARE_SOA_COLUMN(IsSelBplusToD0Pi, isSelBplusToD0Pi, int); //! selection flag on B+ candidate +DECLARE_SOA_COLUMN(MlProbBplusToD0Pi, mlProbBplusToD0Pi, float); //! ML score of B+ candidate for signal class +DECLARE_SOA_COLUMN(MlProbBplusToJpsiK, mlProbBplusToJpsiK, float); //! ML score of B+ candidate for signal class } // namespace hf_sel_candidate_bplus DECLARE_SOA_TABLE(HfSelBplusToD0Pi, "AOD", "HFSELBPLUS", //! @@ -271,6 +275,8 @@ DECLARE_SOA_TABLE(HfSelBplusToD0Pi, "AOD", "HFSELBPLUS", //! DECLARE_SOA_TABLE(HfMlBplusToD0Pi, "AOD", "HFMLBPLUS", //! hf_sel_candidate_bplus::MlProbBplusToD0Pi); +DECLARE_SOA_TABLE(HfMlBplusToJpsiK, "AOD", "HFMLBPLUSTOJPSIK", //! + hf_sel_candidate_bplus::MlProbBplusToJpsiK); namespace hf_sel_candidate_lb { DECLARE_SOA_COLUMN(IsSelLbToLcPi, isSelLbToLcPi, int); //! selection flag on Lb candidate diff --git a/PWGHF/Utils/utilsTrkCandHf.h b/PWGHF/Utils/utilsTrkCandHf.h index 94fa2084370..43db7a21e08 100644 --- a/PWGHF/Utils/utilsTrkCandHf.h +++ b/PWGHF/Utils/utilsTrkCandHf.h @@ -16,10 +16,12 @@ #ifndef PWGHF_UTILS_UTILSTRKCANDHF_H_ #define PWGHF_UTILS_UTILSTRKCANDHF_H_ -#include +#include "PWGHF/Utils/utilsAnalysis.h" #include +#include + #include namespace o2::hf_trkcandsel @@ -58,6 +60,29 @@ int countOnesInBinary(uint8_t num) return count; } +/// Single-track cuts on dcaXY +/// \param trackPar is the track parametrisation +/// \param dca is the 2-D array with track DCAs +/// \param binsPtTrack is the array of pt bins for track selection +/// \param cutsTrackDCA are the cuts for track DCA selection +/// \return true if track passes all cuts +template +bool isSelectedTrackDCA(const T1& trackPar, const T2& dca, const C1& binsPtTrack, const C2& cutsTrackDCA) +{ + auto binPtTrack = o2::analysis::findBin(binsPtTrack, trackPar.getPt()); + if (binPtTrack == -1) { + return false; + } + + if (std::abs(dca[0]) < cutsTrackDCA->get(binPtTrack, "min_dcaxytoprimary")) { + return false; // minimum DCAxy + } + if (std::abs(dca[0]) > cutsTrackDCA->get(binPtTrack, "max_dcaxytoprimary")) { + return false; // maximum DCAxy + } + return true; +} + } // namespace o2::hf_trkcandsel #endif // PWGHF_UTILS_UTILSTRKCANDHF_H_ From fa29e45d0e1ef836d6e51fa9b5b5a1d1620102b1 Mon Sep 17 00:00:00 2001 From: Rik Spijkers <78484875+rspijkers@users.noreply.github.com> Date: Fri, 13 Jun 2025 16:46:08 +0200 Subject: [PATCH 067/871] [PWGLF] fix eta-cut in closure test correlations (#11606) --- PWGLF/Tasks/Strangeness/cascadecorrelations.cxx | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/PWGLF/Tasks/Strangeness/cascadecorrelations.cxx b/PWGLF/Tasks/Strangeness/cascadecorrelations.cxx index 632d80dd4d1..0d6fd6d67cb 100644 --- a/PWGLF/Tasks/Strangeness/cascadecorrelations.cxx +++ b/PWGLF/Tasks/Strangeness/cascadecorrelations.cxx @@ -1080,7 +1080,7 @@ struct CascadeCorrelations { } // process mixed events Configurable etaGenCascades{"etaGenCascades", 0.8, "min/max of eta for generated cascades"}; - Filter genCascadesFilter = (nabs(aod::mcparticle::pdgCode) == 3312 && nabs(aod::mcparticle::eta) < etaGenCascades); + Filter genCascadesFilter = nabs(aod::mcparticle::pdgCode) == 3312; void processMC(aod::McCollision const&, soa::SmallGroups> const& collisions, soa::Filtered const& genCascades, aod::McParticles const& mcParticles) { @@ -1122,10 +1122,12 @@ struct CascadeCorrelations { auto trigger = *triggerAddress; auto assoc = *assocAddress; - double dphi = RecoDecay::constrainAngle(trigger.phi() - assoc.phi(), -PIHalf); - if (!trigger.isPhysicalPrimary() || !assoc.isPhysicalPrimary()) continue; // require the cascades to be primaries + if (trigger.eta() > etaGenCascades) + continue; // only apply eta cut to trigger - trigger normalization still valid without introducing 2-particle-acceptance effects + + double dphi = RecoDecay::constrainAngle(trigger.phi() - assoc.phi(), -PIHalf); if (trigger.pdgCode() < 0) { // anti-trigg --> Plus if (assoc.pdgCode() < 0) { // anti-assoc --> Plus From 36a03b6ffeca41cc1451463f28fb8986e1bb738a Mon Sep 17 00:00:00 2001 From: Debadatta3337 Date: Fri, 13 Jun 2025 21:49:36 +0530 Subject: [PATCH 068/871] [PWGDQ] Updated HistogramLibrary (#11575) Co-authored-by: Debadatta3337 --- PWGDQ/Core/HistogramsLibrary.cxx | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/PWGDQ/Core/HistogramsLibrary.cxx b/PWGDQ/Core/HistogramsLibrary.cxx index 9fdb5b0cae5..7b975b1c2be 100644 --- a/PWGDQ/Core/HistogramsLibrary.cxx +++ b/PWGDQ/Core/HistogramsLibrary.cxx @@ -84,11 +84,11 @@ void o2::aod::dqhistograms::DefineHistograms(HistogramManager* hm, const char* h if (subGroupStr.Contains("mult")) { if (subGroupStr.Contains("pp")) { hm->AddHistogram(histClass, "MultTPC", "MultTPC", false, 250, 0.0, 500.0, VarManager::kMultTPC); - hm->AddHistogram(histClass, "MultFV0A", "MultFV0A", false, 250, 0.0, 500.0, VarManager::kMultFV0A); - hm->AddHistogram(histClass, "MultFT0A", "MultFT0A", false, 300, 0.0, 300.0, VarManager::kMultFT0A); - hm->AddHistogram(histClass, "MultFT0C", "MultFT0C", false, 300, 0.0, 300.0, VarManager::kMultFT0C); - hm->AddHistogram(histClass, "MultFDDA", "MultFDDA", false, 300, 0.0, 300.0, VarManager::kMultFDDA); - hm->AddHistogram(histClass, "MultFDDC", "MultFDDC", false, 50, 0.0, 50.0, VarManager::kMultFDDC); + hm->AddHistogram(histClass, "MultFV0A", "MultFV0A", false, 1000, 0.0, 25000.0, VarManager::kMultFV0A); + hm->AddHistogram(histClass, "MultFT0A", "MultFT0A", false, 1000, 0.0, 25000.0, VarManager::kMultFT0A); + hm->AddHistogram(histClass, "MultFT0C", "MultFT0C", false, 1000, 0.0, 25000.0, VarManager::kMultFT0C); + hm->AddHistogram(histClass, "MultFDDA", "MultFDDA", false, 1000, 0.0, 25000.0, VarManager::kMultFDDA); + hm->AddHistogram(histClass, "MultFDDC", "MultFDDC", false, 1000, 0.0, 25000.0, VarManager::kMultFDDC); hm->AddHistogram(histClass, "MultTracklets", "MultTracklets", false, 250, 0.0, 250.0, VarManager::kMultTracklets); hm->AddHistogram(histClass, "VtxNContribReal", "Vtx n contributors", false, 150, 0.0, 150.0, VarManager::kVtxNcontribReal); hm->AddHistogram(histClass, "VtxNContrib", "Vtx n contributors", false, 100, 0.0, 100.0, VarManager::kVtxNcontrib); @@ -115,6 +115,11 @@ void o2::aod::dqhistograms::DefineHistograms(HistogramManager* hm, const char* h hm->AddHistogram(histClass, "VtxZ_VtxNcontribReal", "VtxZ vs VtxNcontribReal", false, 100, -10.0, 10.0, VarManager::kVtxZ, 150, 0, 150.0, VarManager::kVtxNcontribReal); hm->AddHistogram(histClass, "VtxZ_MultNTracksPVeta1", "VtxZ vs MultNTracksPVeta1", false, 100, -10.0, 10.0, VarManager::kVtxZ, 150, 0, 150.0, VarManager::kMultNTracksPVeta1); hm->AddHistogram(histClass, "VtxZ_MultNTracksPVetaHalf", "VtxZ vs MultNTracksPVetaHalf", false, 100, -10.0, 10.0, VarManager::kVtxZ, 150, 0, 150.0, VarManager::kMultNTracksPVetaHalf); + hm->AddHistogram(histClass, "VtxZ_MultFV0A", "VtxZ vs MultFV0A", false, 20, -10.0, 10.0, VarManager::kVtxZ, 200, 0, 25000.0, VarManager::kMultFV0A); + hm->AddHistogram(histClass, "VtxZ_MultFT0A", "VtxZ vs MultFT0A", false, 20, -10.0, 10.0, VarManager::kVtxZ, 200, 0, 25000.0, VarManager::kMultFT0A); + hm->AddHistogram(histClass, "VtxZ_MultFT0C", "VtxZ vs MultFT0C", false, 20, -10.0, 10.0, VarManager::kVtxZ, 200, 0, 25000.0, VarManager::kMultFT0C); + hm->AddHistogram(histClass, "VtxZ_MultFDDA", "VtxZ vs MultFDDA", false, 20, -10.0, 10.0, VarManager::kVtxZ, 200, 0, 25000.0, VarManager::kMultFDDA); + hm->AddHistogram(histClass, "VtxZ_MultFDDC", "VtxZ vs MultFDDC", false, 20, -10.0, 10.0, VarManager::kVtxZ, 200, 0, 25000.0, VarManager::kMultFDDC); } else { hm->AddHistogram(histClass, "MultTPC", "MultTPC", false, 200, 0.0, 50000.0, VarManager::kMultTPC); @@ -944,6 +949,13 @@ void o2::aod::dqhistograms::DefineHistograms(HistogramManager* hm, const char* h hm->AddHistogram(histClass, "Mass_MultNTracksPVetaHalf", "Mass vs MultNTracksPVetaHalf", false, 200, 2.0, 5.0, VarManager::kMass, 150, 0, 150.0, VarManager::kMultNTracksPVetaHalf); hm->AddHistogram(histClass, "Mass_MultNTracksPVeta1", "Mass vs MultNTracksPVeta1", false, 200, 2.0, 5.0, VarManager::kMass, 150, 0, 150.0, VarManager::kMultNTracksPVeta1); } + if (subGroupStr.Contains("dimuon_fwdmult")) { + hm->AddHistogram(histClass, "Mass_MultFV0A", "Mass vs MultFV0A", false, 200, 2.0, 5.0, VarManager::kMass, 1000, 0, 25000.0, VarManager::kMultFV0A); + hm->AddHistogram(histClass, "Mass_MultFT0A", "Mass vs MultFT0A", false, 200, 2.0, 5.0, VarManager::kMass, 1000, 0, 25000.0, VarManager::kMultFT0A); + hm->AddHistogram(histClass, "Mass_MultFT0C", "Mass vs MultFT0C", false, 200, 2.0, 5.0, VarManager::kMass, 1000, 0, 25000.0, VarManager::kMultFT0C); + hm->AddHistogram(histClass, "Mass_MultFDDA", "Mass vs MultFDDA", false, 200, 2.0, 5.0, VarManager::kMass, 1000, 0, 25000.0, VarManager::kMultFDDA); + hm->AddHistogram(histClass, "Mass_MultFDDC", "Mass vs MultFDDC", false, 200, 2.0, 5.0, VarManager::kMass, 1000, 0, 25000.0, VarManager::kMultFDDC); + } if (subGroupStr.Contains("barrel")) { hm->AddHistogram(histClass, "Mass", "", false, 500, 0.0, 5.0, VarManager::kMass); hm->AddHistogram(histClass, "Mass_HighRange", "", false, 375, 0.0, 15.0, VarManager::kMass); From acefb1ef9e3a5ea2e75d31edf7ac46f500ef1d35 Mon Sep 17 00:00:00 2001 From: dyx-11 <1260971129@qq.com> Date: Sat, 14 Jun 2025 01:50:28 +0800 Subject: [PATCH 069/871] [PWGUD] nch axis to nsample axis new (#11599) --- PWGUD/Tasks/flowCorrelationsUpc.cxx | 57 ++++++++++++++++------------- 1 file changed, 32 insertions(+), 25 deletions(-) diff --git a/PWGUD/Tasks/flowCorrelationsUpc.cxx b/PWGUD/Tasks/flowCorrelationsUpc.cxx index 59aae4d6c86..11f7820a071 100644 --- a/PWGUD/Tasks/flowCorrelationsUpc.cxx +++ b/PWGUD/Tasks/flowCorrelationsUpc.cxx @@ -14,29 +14,31 @@ /// \author Mingrui Zhao (mingrui.zhao@cern.ch, mingrui.zhao@mail.labz0.org) /// copied from Thor Jensen (thor.kjaersgaard.jensen@cern.ch) and Debojit Sarkar (debojit.sarkar@cern.ch) -#include +#include "PWGCF/Core/CorrelationContainer.h" +#include "PWGCF/Core/PairCuts.h" +#include "PWGCF/DataModel/CorrelationsDerived.h" +#include "PWGUD/Core/SGSelector.h" +#include "PWGUD/DataModel/UDTables.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.h" +#include "Common/Core/RecoDecay.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include "CCDB/BasicCCDBManager.h" +#include "CommonConstants/MathConstants.h" #include "Framework/ASoA.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" #include "Framework/RunningWorkflowInfo.h" -#include "CommonConstants/MathConstants.h" -#include "CCDB/BasicCCDBManager.h" -#include "Common/Core/RecoDecay.h" +#include "Framework/runDataProcessing.h" -#include "PWGUD/DataModel/UDTables.h" -#include "PWGUD/Core/SGSelector.h" +#include "TRandom3.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "Common/DataModel/Centrality.h" -#include "Common/DataModel/Multiplicity.h" -#include "PWGCF/DataModel/CorrelationsDerived.h" -#include "PWGCF/Core/CorrelationContainer.h" -#include "PWGCF/Core/PairCuts.h" +#include namespace o2::aod { @@ -98,6 +100,7 @@ struct FlowCorrelationsUpc { 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, 10, "Maximum multiplicity for collision") + O2_DEFINE_CONFIGURABLE(cfgSampleSize, double, 10, "Sample size for mixed event") ConfigurableAxis axisVertex{"axisVertex", {10, -10, 10}, "vertex axis for histograms"}; ConfigurableAxis axisEta{"axisEta", {40, -1., 1.}, "eta axis for histograms"}; @@ -114,6 +117,7 @@ struct FlowCorrelationsUpc { 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"}; // Added UPC Cuts SGSelector sgSelector; @@ -149,11 +153,11 @@ struct FlowCorrelationsUpc { registry.add("Nch", "N_{ch}", {HistType::kTH1D, {axisMultiplicity}}); registry.add("zVtx", "zVtx", {HistType::kTH1D, {axisVertex}}); - registry.add("Trig_hist", "", {HistType::kTHnSparseF, {{axisMultiplicity, axisVertex, axisPtTrigger}}}); + registry.add("Trig_hist", "", {HistType::kTHnSparseF, {{axisSample, axisVertex, axisPtTrigger}}}); registry.add("eventcount", "bin", {HistType::kTH1F, {{3, 0, 3, "bin"}}}); // histogram to see how many events are in the same and mixed event - std::vector corrAxis = {{axisMultiplicity, "Nch"}, + std::vector corrAxis = {{axisSample, "Sample"}, {axisVertex, "z-vtx (cm)"}, {axisPtTrigger, "p_{T} (GeV/c)"}, {axisPtAssoc, "p_{T} (GeV/c)"}, @@ -190,13 +194,16 @@ struct FlowCorrelationsUpc { } template - void fillCorrelations(TTracks tracks1, TTracks tracks2, float posZ, int system, float Nch) // function to fill the Output functions (sparse) and the delta eta and delta phi histograms + void fillCorrelations(TTracks tracks1, TTracks tracks2, float posZ, int system) // function to fill the Output functions (sparse) and the delta eta and delta phi histograms { + + int fSampleIndex = gRandom->Uniform(0, cfgSampleSize); + // loop over all tracks for (auto const& track1 : tracks1) { if (system == SameEvent) { - registry.fill(HIST("Trig_hist"), Nch, posZ, track1.pt()); + registry.fill(HIST("Trig_hist"), fSampleIndex, posZ, track1.pt()); } for (auto const& track2 : tracks2) { @@ -213,10 +220,10 @@ struct FlowCorrelationsUpc { // fill the right sparse and histograms if (system == SameEvent) { - same->getPairHist()->Fill(step, Nch, posZ, track1.pt(), track2.pt(), deltaPhi, deltaEta); + same->getPairHist()->Fill(step, fSampleIndex, posZ, track1.pt(), track2.pt(), deltaPhi, deltaEta); registry.fill(HIST("deltaEta_deltaPhi_same"), deltaPhi, deltaEta); } else if (system == MixedEvent) { - mixed->getPairHist()->Fill(step, Nch, posZ, track1.pt(), track2.pt(), deltaPhi, deltaEta); + mixed->getPairHist()->Fill(step, fSampleIndex, posZ, track1.pt(), track2.pt(), deltaPhi, deltaEta); registry.fill(HIST("deltaEta_deltaPhi_mixed"), deltaPhi, deltaEta); } } @@ -247,7 +254,7 @@ struct FlowCorrelationsUpc { registry.fill(HIST("eventcount"), SameEvent); // because its same event i put it in the 1 bin fillYield(collision, tracks); - fillCorrelations(tracks, tracks, collision.posZ(), SameEvent, tracks.size()); // fill the SE histogram and Sparse + fillCorrelations(tracks, tracks, collision.posZ(), SameEvent); // fill the SE histogram and Sparse } PROCESS_SWITCH(FlowCorrelationsUpc, processSame, "Process same event", true); @@ -265,7 +272,7 @@ struct FlowCorrelationsUpc { for (auto const& [collision1, tracks1, collision2, tracks2] : pairs) { registry.fill(HIST("eventcount"), MixedEvent); // fill the mixed event in the 3 bin - fillCorrelations(tracks1, tracks2, collision1.posZ(), MixedEvent, tracks1.size()); + fillCorrelations(tracks1, tracks2, collision1.posZ(), MixedEvent); } } PROCESS_SWITCH(FlowCorrelationsUpc, processMixed, "Process mixed events", true); From f87f06229d7f3c94c2e7d0d8d0aeedd2fd29763c Mon Sep 17 00:00:00 2001 From: omvazque Date: Fri, 13 Jun 2025 13:15:04 -0500 Subject: [PATCH 070/871] [PWGLF] Using global ccdb and fixed a bug (#11609) --- PWGLF/Tasks/GlobalEventProperties/uccZdc.cxx | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/PWGLF/Tasks/GlobalEventProperties/uccZdc.cxx b/PWGLF/Tasks/GlobalEventProperties/uccZdc.cxx index 478c49fae87..02874f91014 100644 --- a/PWGLF/Tasks/GlobalEventProperties/uccZdc.cxx +++ b/PWGLF/Tasks/GlobalEventProperties/uccZdc.cxx @@ -83,6 +83,7 @@ struct UccZdc { Configurable isZEMcut{"isZEMcut", true, "Use ZEM cut"}; Configurable useMidRapNchSel{"useMidRapNchSel", true, "Use mid-rapidit Nch selection"}; Configurable applyEff{"applyEff", true, "Apply track-by-track efficiency correction"}; + Configurable applyFD{"applyFD", false, "Apply track-by-track feed down correction"}; Configurable correctNch{"correctNch", true, "Correct also Nch"}; // Event selection @@ -165,6 +166,8 @@ struct UccZdc { HistogramRegistry registry{"registry", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; Service ccdb; + TH1F* fd = nullptr; + void init(InitContext const&) { // define axes you want to use @@ -299,6 +302,7 @@ struct UccZdc { LOG(info) << "\tccdbNoLaterThan=" << ccdbNoLaterThan.value; LOG(info) << "\tapplyEff=" << applyEff.value; + LOG(info) << "\tapplyFD=" << applyFD.value; LOG(info) << "\tcorrectNch=" << correctNch.value; LOG(info) << "\tpaTHEff=" << paTHEff.value; LOG(info) << "\tpaTHFD=" << paTHFD.value; @@ -318,6 +322,11 @@ struct UccZdc { // Not later than now, will be replaced by the value of the train creation // This avoids that users can replace objects **while** a train is running ccdb->setCreatedNotAfter(ccdbNoLaterThan.value); + // Feed Down is the same for all runs -> use a global object + fd = ccdb->getForTimeStamp(paTHFD.value, ccdbNoLaterThan.value); + if (!fd) { + LOGF(fatal, "Feed Down object not found!"); + } } template @@ -697,8 +706,7 @@ struct UccZdc { } auto efficiency = ccdb->getForTimeStamp(paTHEff.value, foundBC.timestamp()); - auto fd = ccdb->getForTimeStamp(paTHFD.value, foundBC.timestamp()); - if (!efficiency || !fd) { + if (!efficiency) { return; } @@ -756,6 +764,9 @@ struct UccZdc { effValue = efficiency->GetBinContent(efficiency->FindBin(pt)); fdValue = fd->GetBinContent(fd->FindBin(pt)); } + if (applyEff && !applyFD) { + fdValue = 1.0; + } if ((effValue > 0.) && (fdValue > 0.)) { pTs.emplace_back(pt); vecOneOverEff.emplace_back(1. / effValue); @@ -844,8 +855,7 @@ struct UccZdc { // To use run-by-run efficiency const auto& foundBC = collision.foundBC_as(); auto efficiency = ccdb->getForTimeStamp(paTHEff.value, foundBC.timestamp()); - auto fd = ccdb->getForTimeStamp(paTHFD.value, foundBC.timestamp()); - if (!efficiency || !fd) { + if (!efficiency) { return; } @@ -930,7 +940,7 @@ struct UccZdc { } double nchMC{0}; - nchMult = std::accumulate(vecFullEff.begin(), vecFullEff.end(), 0); + nchMC = std::accumulate(vecFullEff.begin(), vecFullEff.end(), 0); if (nchMC < minNchSel) { continue; } From 713bb40f05743e16f00b22eeec11784c834e9c55 Mon Sep 17 00:00:00 2001 From: Banajit Barman <113376372+BanajitBarman@users.noreply.github.com> Date: Fri, 13 Jun 2025 21:21:35 +0200 Subject: [PATCH 071/871] [PWGLF] added configurable enablePureDCAHistogram for enabling pure DCA histogram based on nsigmaTPCKa cut (#11593) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Nicolò Jacazio Co-authored-by: ALICE Action Bot --- PWGLF/Tasks/Nuspex/spectraTOF.cxx | 224 ++++++++++++++++-------------- 1 file changed, 118 insertions(+), 106 deletions(-) diff --git a/PWGLF/Tasks/Nuspex/spectraTOF.cxx b/PWGLF/Tasks/Nuspex/spectraTOF.cxx index e1607610ac6..bff2593257a 100644 --- a/PWGLF/Tasks/Nuspex/spectraTOF.cxx +++ b/PWGLF/Tasks/Nuspex/spectraTOF.cxx @@ -18,6 +18,7 @@ /// // O2 includes + #include #include #include "ReconstructionDataFormats/Track.h" @@ -97,6 +98,7 @@ struct tofSpectra { } trkselOptions; Configurable enableDcaGoodEvents{"enableDcaGoodEvents", true, "Enables the MC plots with the correct match between data and MC"}; + Configurable enablePureDCAHistogram{"enablePureDCAHistogram", false, "Enables the pure DCA histograms"}; Configurable enableTrackCutHistograms{"enableTrackCutHistograms", true, "Enables track cut histograms, before and after the cut"}; Configurable enableDeltaHistograms{"enableDeltaHistograms", true, "Enables the delta TPC and TOF histograms"}; Configurable enableTPCTOFHistograms{"enableTPCTOFHistograms", true, "Enables TPC TOF histograms"}; @@ -1017,7 +1019,6 @@ struct tofSpectra { } } } - if constexpr (fillFullInfo) { if (enableDeltaHistograms) { const auto& deltaTOF = o2::aod::pidutils::tofExpSignalDiff(track); @@ -1036,7 +1037,6 @@ struct tofSpectra { } } } - // Filling DCA info with the TPC+TOF PID bool isDCAPureSample = (std::sqrt(nsigmaTOF * nsigmaTOF + nsigmaTPC * nsigmaTPC) < 2.f); if (track.pt() <= 0.4) { @@ -1906,130 +1906,138 @@ struct tofSpectra { if (std::abs(mcParticle.y()) > trkselOptions.cfgCutY) { return; } + if (enablePureDCAHistogram) { + const auto& nsigmaTPCKa = o2::aod::pidutils::tpcNSigma<3>(track); + const auto& nsigmaTOFKa = o2::aod::pidutils::tofNSigma<3>(track); - const auto& nsigmaTPCKa = o2::aod::pidutils::tpcNSigma<3>(track); - const bool isKaonTPC = std::abs(nsigmaTPCKa) < trkselOptions.cfgCutNsigma; - - const auto& nsigmaTOFKa = o2::aod::pidutils::tofNSigma<3>(track); - const bool isKaonTOF = std::abs(nsigmaTOFKa) < trkselOptions.cfgCutNsigma; - - // Filling DCA info with the TPC+TOF PID - bool isDCAPureSample = (std::sqrt(nsigmaTOFKa * nsigmaTOFKa + nsigmaTPCKa * nsigmaTPCKa) < 2.f); - if (track.pt() <= 0.4) { - isDCAPureSample = (nsigmaTPCKa < 1.f); - } - - if (isDCAPureSample) { - if (enableDCAvsmotherHistograms) { - hDcaXYMC[i]->Fill(track.pt(), track.dcaXY()); - hDcaZMC[i]->Fill(track.pt(), track.dcaZ()); + // Filling DCA info with the TPC+TOF PID + bool isDCAPureSample = (std::sqrt(nsigmaTOFKa * nsigmaTOFKa + nsigmaTPCKa * nsigmaTPCKa) < 2.f); + if (track.pt() <= 0.4) { + isDCAPureSample = (nsigmaTPCKa < 1.f); } - if (!mcParticle.isPhysicalPrimary()) { // Secondaries (weak decays and material) - if (mcParticle.getProcess() == 4) { // Particles from decay - if (enableDCAxyzHistograms) { - hDcaXYZStr[i]->Fill(track.pt(), track.dcaXY(), track.dcaZ()); - } else { - histos.fill(HIST(hdcaxystr[i]), track.pt(), track.dcaXY()); - histos.fill(HIST(hdcazstr[i]), track.pt(), track.dcaZ()); - } + if (isDCAPureSample) { + if (enableDCAvsmotherHistograms) { + hDcaXYMC[i]->Fill(track.pt(), track.dcaXY()); + hDcaZMC[i]->Fill(track.pt(), track.dcaZ()); + } - if (mcParticle.has_mothers()) { - for (const auto& mother : mcParticle.template mothers_as()) { - auto daughter0 = mother.template daughters_as().begin(); - double vertexDau[3] = {daughter0.vx(), daughter0.vy(), daughter0.vz()}; - double vertexMoth[3] = {mother.vx(), mother.vy(), mother.vz()}; - auto decayLength = RecoDecay::distance(vertexMoth, vertexDau); - hDecayLengthStr[i]->Fill(track.pt(), decayLength); + if (!mcParticle.isPhysicalPrimary()) { // Secondaries (weak decays and material) + if (mcParticle.getProcess() == 4) { // Particles from decay + if (enableDCAxyzHistograms) { + hDcaXYZStr[i]->Fill(track.pt(), track.dcaXY(), track.dcaZ()); + } else { + histos.fill(HIST(hdcaxystr[i]), track.pt(), track.dcaXY()); + histos.fill(HIST(hdcazstr[i]), track.pt(), track.dcaZ()); + } + + if (mcParticle.has_mothers()) { + for (const auto& mother : mcParticle.template mothers_as()) { + auto daughter0 = mother.template daughters_as().begin(); + double vertexDau[3] = {daughter0.vx(), daughter0.vy(), daughter0.vz()}; + double vertexMoth[3] = {mother.vx(), mother.vy(), mother.vz()}; + auto decayLength = RecoDecay::distance(vertexMoth, vertexDau); + hDecayLengthStr[i]->Fill(track.pt(), decayLength); + } + } + } else { // Particles from the material + if (enableDCAxyzHistograms) { + hDcaXYZMat[i]->Fill(track.pt(), track.dcaXY(), track.dcaZ()); + } else { + histos.fill(HIST(hdcaxymat[i]), track.pt(), track.dcaXY()); + histos.fill(HIST(hdcazmat[i]), track.pt(), track.dcaZ()); } } - } else { // Particles from the material + } else { // Primaries if (enableDCAxyzHistograms) { - hDcaXYZMat[i]->Fill(track.pt(), track.dcaXY(), track.dcaZ()); + hDcaXYZPrm[i]->Fill(track.pt(), track.dcaXY(), track.dcaZ()); + if (enableDcaGoodEvents.value && collision.has_mcCollision()) { + histos.fill(HIST(hdcaxyprmgoodevs[i]), track.pt(), track.dcaXY(), track.dcaZ()); + } } else { - histos.fill(HIST(hdcaxymat[i]), track.pt(), track.dcaXY()); - histos.fill(HIST(hdcazmat[i]), track.pt(), track.dcaZ()); + // DCAxy for all primaries + histos.fill(HIST(hdcaxyprm[i]), track.pt(), track.dcaXY()); + histos.fill(HIST(hdcazprm[i]), track.pt(), track.dcaZ()); } - } - } else { // Primaries - if (enableDCAxyzHistograms) { - hDcaXYZPrm[i]->Fill(track.pt(), track.dcaXY(), track.dcaZ()); if (enableDcaGoodEvents.value && collision.has_mcCollision()) { - histos.fill(HIST(hdcaxyprmgoodevs[i]), track.pt(), track.dcaXY(), track.dcaZ()); + histos.fill(HIST(hdcaxyprmgoodevs[i]), track.pt(), track.dcaXY()); + histos.fill(HIST(hdcazprmgoodevs[i]), track.pt(), track.dcaZ()); } - } else { - // DCAxy for all primaries - histos.fill(HIST(hdcaxyprm[i]), track.pt(), track.dcaXY()); - histos.fill(HIST(hdcazprm[i]), track.pt(), track.dcaZ()); - } - if (enableDcaGoodEvents.value && collision.has_mcCollision()) { - histos.fill(HIST(hdcaxyprmgoodevs[i]), track.pt(), track.dcaXY()); - histos.fill(HIST(hdcazprmgoodevs[i]), track.pt(), track.dcaZ()); - } - if (enableDCAvsmotherHistograms) { - bool IsD0Mother = false; - bool IsCharmMother = false; - bool IsBeautyMother = false; - bool IsNotHFMother = false; - if (mcParticle.has_mothers()) { - const int charmOrigin = RecoDecay::getCharmHadronOrigin(mcParticles, mcParticle, false); - for (const auto& mother : mcParticle.template mothers_as()) { - const int motherPdgCode = std::abs(mother.pdgCode()); - if (motherPdgCode == 421) { - IsD0Mother = true; - } - if (charmOrigin == RecoDecay::OriginType::NonPrompt) { - IsBeautyMother = true; - } - if (charmOrigin == RecoDecay::OriginType::Prompt) { - IsCharmMother = true; - } - if (charmOrigin == RecoDecay::OriginType::None) { - IsNotHFMother = true; + if (enableDCAvsmotherHistograms) { + bool IsD0Mother = false; + bool IsCharmMother = false; + bool IsBeautyMother = false; + bool IsNotHFMother = false; + if (mcParticle.has_mothers()) { + const int charmOrigin = RecoDecay::getCharmHadronOrigin(mcParticles, mcParticle, false); + for (const auto& mother : mcParticle.template mothers_as()) { + const int motherPdgCode = std::abs(mother.pdgCode()); + if (motherPdgCode == 421) { + IsD0Mother = true; + } + if (charmOrigin == RecoDecay::OriginType::NonPrompt) { + IsBeautyMother = true; + } + if (charmOrigin == RecoDecay::OriginType::Prompt) { + IsCharmMother = true; + } + if (charmOrigin == RecoDecay::OriginType::None) { + IsNotHFMother = true; + } } } - } - if (IsD0Mother) { - hDcaXYMCD0[i]->Fill(track.pt(), track.dcaXY()); - hDcaZMCD0[i]->Fill(track.pt(), track.dcaZ()); - } - if (IsCharmMother) { - hDcaXYMCCharm[i]->Fill(track.pt(), track.dcaXY()); - hdcaZMCCharm[i]->Fill(track.pt(), track.dcaZ()); - } - if (IsBeautyMother) { - hDcaXYMCBeauty[i]->Fill(track.pt(), track.dcaXY()); - hDcaZMCBeauty[i]->Fill(track.pt(), track.dcaZ()); - } - if (IsNotHFMother) { - hDcaXYMCNotHF[i]->Fill(track.pt(), track.dcaXY()); - hDcaZMCNotHF[i]->Fill(track.pt(), track.dcaZ()); - } - - if (mcParticle.has_mothers()) { - for (const auto& mother : mcParticle.template mothers_as()) { - auto daughter0 = mother.template daughters_as().begin(); - double vertexDau[3] = {daughter0.vx(), daughter0.vy(), daughter0.vz()}; - double vertexMoth[3] = {mother.vx(), mother.vy(), mother.vz()}; - auto decayLength = RecoDecay::distance(vertexMoth, vertexDau); + if (IsD0Mother) { + hDcaXYMCD0[i]->Fill(track.pt(), track.dcaXY()); + hDcaZMCD0[i]->Fill(track.pt(), track.dcaZ()); + } + if (IsCharmMother) { + hDcaXYMCCharm[i]->Fill(track.pt(), track.dcaXY()); + hdcaZMCCharm[i]->Fill(track.pt(), track.dcaZ()); + } + if (IsBeautyMother) { + hDcaXYMCBeauty[i]->Fill(track.pt(), track.dcaXY()); + hDcaZMCBeauty[i]->Fill(track.pt(), track.dcaZ()); + } + if (IsNotHFMother) { + hDcaXYMCNotHF[i]->Fill(track.pt(), track.dcaXY()); + hDcaZMCNotHF[i]->Fill(track.pt(), track.dcaZ()); + } - if (IsD0Mother) { - hDecayLengthMCD0[i]->Fill(track.pt(), decayLength); - } - if (IsCharmMother) { - hDecayLengthMCCharm[i]->Fill(track.pt(), decayLength); - } - if (IsBeautyMother) { - hDecayLengthMCBeauty[i]->Fill(track.pt(), decayLength); - } - if (IsNotHFMother) { - hDecayLengthMCNotHF[i]->Fill(track.pt(), decayLength); + if (mcParticle.has_mothers()) { + for (const auto& mother : mcParticle.template mothers_as()) { + auto daughter0 = mother.template daughters_as().begin(); + double vertexDau[3] = {daughter0.vx(), daughter0.vy(), daughter0.vz()}; + double vertexMoth[3] = {mother.vx(), mother.vy(), mother.vz()}; + auto decayLength = RecoDecay::distance(vertexMoth, vertexDau); + + if (IsD0Mother) { + hDecayLengthMCD0[i]->Fill(track.pt(), decayLength); + } + if (IsCharmMother) { + hDecayLengthMCCharm[i]->Fill(track.pt(), decayLength); + } + if (IsBeautyMother) { + hDecayLengthMCBeauty[i]->Fill(track.pt(), decayLength); + } + if (IsNotHFMother) { + hDecayLengthMCNotHF[i]->Fill(track.pt(), decayLength); + } } } } } } + } else { + if (!mcParticle.isPhysicalPrimary()) { + if (mcParticle.getProcess() == 4) { + histos.fill(HIST(hdcaxystr[i]), track.pt(), track.dcaXY()); + } else { + histos.fill(HIST(hdcaxymat[i]), track.pt(), track.dcaXY()); + } + } else { + histos.fill(HIST(hdcaxyprm[i]), track.pt(), track.dcaXY()); + } } if ((collision.has_mcCollision() && (mcParticle.mcCollisionId() != collision.mcCollisionId())) || !collision.has_mcCollision()) { @@ -2049,15 +2057,19 @@ struct tofSpectra { } const int pdgCode = mcParticle.pdgCode(); const auto& nsigmaTPCPi = o2::aod::pidutils::tpcNSigma<2>(track); + const auto& nsigmaTPCKa = o2::aod::pidutils::tpcNSigma<3>(track); const auto& nsigmaTPCPr = o2::aod::pidutils::tpcNSigma<4>(track); const bool isPionTPC = std::abs(nsigmaTPCPi) < trkselOptions.cfgCutNsigma; + const bool isKaonTPC = std::abs(nsigmaTPCKa) < trkselOptions.cfgCutNsigma; const bool isProtonTPC = std::abs(nsigmaTPCPr) < trkselOptions.cfgCutNsigma; const auto& nsigmaTOFPi = o2::aod::pidutils::tofNSigma<2>(track); + const auto& nsigmaTOFKa = o2::aod::pidutils::tofNSigma<3>(track); const auto& nsigmaTOFPr = o2::aod::pidutils::tofNSigma<4>(track); const bool isPionTOF = std::abs(nsigmaTOFPi) < trkselOptions.cfgCutNsigma; + const bool isKaonTOF = std::abs(nsigmaTOFKa) < trkselOptions.cfgCutNsigma; const bool isProtonTOF = std::abs(nsigmaTOFPr) < trkselOptions.cfgCutNsigma; if (!mcParticle.isPhysicalPrimary()) { // Is not physical primary From d00c74d91d431b1786b5c93b84e3fce7e3780646 Mon Sep 17 00:00:00 2001 From: fuchuncui <162277233+fuchuncui@users.noreply.github.com> Date: Sat, 14 Jun 2025 03:54:47 +0800 Subject: [PATCH 072/871] [PWGCF] Add v3 flow and optimized track selection (#11601) --- PWGCF/Flow/Tasks/flowGfwOmegaXi.cxx | 946 +++++++++++++++++----------- 1 file changed, 592 insertions(+), 354 deletions(-) diff --git a/PWGCF/Flow/Tasks/flowGfwOmegaXi.cxx b/PWGCF/Flow/Tasks/flowGfwOmegaXi.cxx index c4d9d5d0ef7..de63cd2a413 100644 --- a/PWGCF/Flow/Tasks/flowGfwOmegaXi.cxx +++ b/PWGCF/Flow/Tasks/flowGfwOmegaXi.cxx @@ -14,39 +14,45 @@ /// \since Sep/13/2024 /// \brief This task is to caculate V0s and cascades flow by GenericFramework -#include -#include -#include -#include -#include -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/RunningWorkflowInfo.h" -#include "Framework/HistogramRegistry.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/Core/TrackSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "Common/DataModel/Centrality.h" -#include "Common/DataModel/PIDResponse.h" -#include "Common/DataModel/Multiplicity.h" -#include "GFWPowerArray.h" #include "GFW.h" #include "GFWCumulant.h" +#include "GFWPowerArray.h" #include "GFWWeights.h" -#include "Common/DataModel/Qvectors.h" -#include "Common/Core/EventPlaneHelper.h" -#include "ReconstructionDataFormats/Track.h" -#include "CommonConstants/PhysicsConstants.h" -#include "Common/Core/trackUtilities.h" + #include "PWGLF/DataModel/LFStrangenessTables.h" #include "PWGMM/Mult/DataModel/Index.h" + +#include "Common/Core/EventPlaneHelper.h" +#include "Common/Core/TrackSelection.h" +#include "Common/Core/trackUtilities.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/PIDResponseITS.h" +#include "Common/DataModel/Qvectors.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include "CommonConstants/PhysicsConstants.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/RunningWorkflowInfo.h" +#include "Framework/runDataProcessing.h" +#include "ReconstructionDataFormats/Track.h" +#include + #include "TList.h" -#include -#include #include #include #include +#include +#include + +#include +#include +#include +#include using namespace o2; using namespace o2::framework; @@ -55,14 +61,19 @@ namespace { std::shared_ptr refc22[10]; std::shared_ptr refc24[10]; +std::shared_ptr refc32[10]; std::shared_ptr k0sc22[10]; std::shared_ptr k0sc24[10]; +std::shared_ptr k0sc32[10]; std::shared_ptr lambdac22[10]; std::shared_ptr lambdac24[10]; +std::shared_ptr lambdac32[10]; std::shared_ptr xic22[10]; std::shared_ptr xic24[10]; +std::shared_ptr xic32[10]; std::shared_ptr omegac22[10]; std::shared_ptr omegac24[10]; +std::shared_ptr omegac32[10]; } // namespace #define O2_DEFINE_CONFIGURABLE(NAME, TYPE, DEFAULT, HELP) Configurable NAME{#NAME, DEFAULT, HELP}; @@ -70,39 +81,64 @@ std::shared_ptr omegac24[10]; struct FlowGfwOmegaXi { O2_DEFINE_CONFIGURABLE(cfgCutVertex, float, 10.0f, "Accepted z-vertex range") - O2_DEFINE_CONFIGURABLE(cfgCutPtPOIMin, float, 0.2f, "Minimal pT for poi tracks") - O2_DEFINE_CONFIGURABLE(cfgCutPtPOIMax, float, 10.0f, "Maximal pT for poi tracks") - O2_DEFINE_CONFIGURABLE(cfgCutPtMin, float, 0.2f, "Minimal pT for ref tracks") - O2_DEFINE_CONFIGURABLE(cfgCutPtMax, float, 10.0f, "Maximal pT for ref tracks") - O2_DEFINE_CONFIGURABLE(cfgCutEta, float, 0.8f, "Eta range for tracks") O2_DEFINE_CONFIGURABLE(cfgCutChi2prTPCcls, float, 2.5, "Chi2 per TPC clusters") O2_DEFINE_CONFIGURABLE(cfgCutOccupancyHigh, int, 500, "High cut on TPC occupancy") O2_DEFINE_CONFIGURABLE(cfgMassBins, std::vector, (std::vector{80, 32, 14, 16}), "Number of K0s, Lambda, Xi, Omega mass axis bins for c22") O2_DEFINE_CONFIGURABLE(cfgDeltaPhiLocDen, int, 3, "Number of delta phi for local density, 200 bins in 2 pi") - // topological cut for V0 - O2_DEFINE_CONFIGURABLE(cfgv0_radius, float, 5.0f, "minimum 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_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_ArmPodocut, float, 0.2f, "Armenteros Podolski cut for K0") - // topological cut for cascade - O2_DEFINE_CONFIGURABLE(cfgcasc_radius, float, 0.5f, "minimum decay radius") - O2_DEFINE_CONFIGURABLE(cfgcasc_casccospa, float, 0.999f, "minimum cosine of pointing angle") - O2_DEFINE_CONFIGURABLE(cfgcasc_v0cospa, float, 0.998f, "minimum cosine of pointing angle") - O2_DEFINE_CONFIGURABLE(cfgcasc_dcav0topv, float, 0.01f, "minimum daughter DCA to PV") - O2_DEFINE_CONFIGURABLE(cfgcasc_dcabachtopv, float, 0.01f, "minimum bachelor DCA to PV") - O2_DEFINE_CONFIGURABLE(cfgcasc_dcacascdau, float, 0.3f, "maximum DCA among cascade daughters") - O2_DEFINE_CONFIGURABLE(cfgcasc_dcav0dau, float, 1.0f, "maximum DCA among V0 daughters") - O2_DEFINE_CONFIGURABLE(cfgcasc_mlambdawindow, float, 0.04f, "Invariant mass window of lambda") - // track quality and type selections - O2_DEFINE_CONFIGURABLE(cfgtpcclusters, int, 70, "minimum number of TPC clusters requirement") - O2_DEFINE_CONFIGURABLE(cfgitsclusters, int, 1, "minimum number of ITS clusters requirement") - O2_DEFINE_CONFIGURABLE(cfgtpcclufindable, int, 1, "minimum number of findable TPC clusters") - O2_DEFINE_CONFIGURABLE(cfgtpccrossoverfindable, int, 1, "minimum number of Ratio crossed rows over findable clusters") + + struct : ConfigurableGroup { + std::string prefix = "v0BuilderOpts"; + // topological cut for V0 + O2_DEFINE_CONFIGURABLE(cfgv0_radius, float, 5.0f, "minimum 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_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_ArmPodocut, float, 0.2f, "Armenteros Podolski cut for K0") + } v0BuilderOpts; + + struct : ConfigurableGroup { + std::string prefix = "cascBuilderOpts"; + // topological cut for cascade + O2_DEFINE_CONFIGURABLE(cfgcasc_radius, float, 0.5f, "minimum decay radius") + O2_DEFINE_CONFIGURABLE(cfgcasc_casccospa, float, 0.999f, "minimum cosine of pointing angle") + O2_DEFINE_CONFIGURABLE(cfgcasc_v0cospa, float, 0.998f, "minimum cosine of pointing angle") + O2_DEFINE_CONFIGURABLE(cfgcasc_dcav0topv, float, 0.01f, "minimum daughter DCA to PV") + O2_DEFINE_CONFIGURABLE(cfgcasc_dcabachtopv, float, 0.01f, "minimum bachelor DCA to PV") + O2_DEFINE_CONFIGURABLE(cfgcasc_dcacascdau, float, 0.3f, "maximum DCA among cascade daughters") + O2_DEFINE_CONFIGURABLE(cfgcasc_dcav0dau, float, 1.0f, "maximum DCA among V0 daughters") + O2_DEFINE_CONFIGURABLE(cfgcasc_mlambdawindow, float, 0.04f, "Invariant mass window of lambda") + } cascBuilderOpts; + + struct : ConfigurableGroup { + std::string prefix = "trkQualityOpts"; + // track selections + O2_DEFINE_CONFIGURABLE(cfgCutEta, float, 0.8f, "Eta range for tracks") + O2_DEFINE_CONFIGURABLE(cfgCutPtPOIMin, float, 0.2f, "Minimal pT for poi tracks") + O2_DEFINE_CONFIGURABLE(cfgCutPtPOIMax, float, 10.0f, "Maximal pT for poi tracks") + O2_DEFINE_CONFIGURABLE(cfgCutPtMin, float, 0.2f, "Minimal pT for ref tracks") + O2_DEFINE_CONFIGURABLE(cfgCutPtMax, float, 10.0f, "Maximal pT for ref tracks") + O2_DEFINE_CONFIGURABLE(cfgCutPtDauMin, float, 0.2f, "Minimal pT for daughter tracks") + O2_DEFINE_CONFIGURABLE(cfgCutPtDauMax, float, 10.0f, "Maximal pT for daughter tracks") + O2_DEFINE_CONFIGURABLE(cfgCutPtK0sMin, float, 0.2f, "Minimal pT for K0s") + O2_DEFINE_CONFIGURABLE(cfgCutPtK0sMax, float, 10.0f, "Maximal pT for K0s") + O2_DEFINE_CONFIGURABLE(cfgCutPtLambdaMin, float, 0.2f, "Minimal pT for Lambda") + O2_DEFINE_CONFIGURABLE(cfgCutPtLambdaMax, float, 10.0f, "Maximal pT for Lambda") + O2_DEFINE_CONFIGURABLE(cfgCutPtXiMin, float, 0.2f, "Minimal pT for Xi") + O2_DEFINE_CONFIGURABLE(cfgCutPtXiMax, float, 10.0f, "Maximal pT for Xi") + O2_DEFINE_CONFIGURABLE(cfgCutPtOmegaMin, float, 0.2f, "Minimal pT for Omega") + O2_DEFINE_CONFIGURABLE(cfgCutPtOmegaMax, float, 10.0f, "Maximal pT for Omega") + O2_DEFINE_CONFIGURABLE(cfgCutPtPIDDauMin, float, 0.15f, "Minimal pT for daughter PID") + // track quality selections for daughter track + O2_DEFINE_CONFIGURABLE(cfgCheckITSNCls, bool, false, "check minimum number of ITS clusters") + O2_DEFINE_CONFIGURABLE(cfgCheckITSHits, bool, false, "check minimum number of ITS hits") + O2_DEFINE_CONFIGURABLE(cfgCheckITSChi2NDF, bool, false, "check ITS Chi2NDF") + O2_DEFINE_CONFIGURABLE(cfgCheckGlobalTrack, bool, false, "check global track") + } trkQualityOpts; + O2_DEFINE_CONFIGURABLE(cfgCasc_rapidity, float, 0.5, "rapidity") - O2_DEFINE_CONFIGURABLE(cfgNSigmatpctof, std::vector, (std::vector{3, 3, 3, 3, 3, 3}), "tpc and tof NSigma for Pion Proton Kaon") + O2_DEFINE_CONFIGURABLE(cfgNSigmapid, std::vector, (std::vector{9, 9, 9, 3, 3, 3, 3, 3, 3}), "tpc, tof and its NSigma for Pion Proton Kaon") 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(cfgLocDenParaXi, std::vector, (std::vector{-0.000986187, -3.86861, -0.000912481, -3.29206, -0.000859271, -2.89389, -0.000817039, -2.61201, -0.000788792, -2.39079, -0.000780182, -2.19276, -0.000750457, -2.07205, -0.000720279, -1.96865, -0.00073247, -1.85642, -0.000695091, -1.82625, -0.000693332, -1.72679, -0.000681225, -1.74305, -0.000652818, -1.92608, -0.000618892, -2.31985}), "Local density efficiency function parameter for Xi, exp(Ax + B)") @@ -110,13 +146,14 @@ struct FlowGfwOmegaXi { O2_DEFINE_CONFIGURABLE(cfgLocDenParaK0s, std::vector, (std::vector{-0.00043057, -3.2435, -0.000385085, -2.97687, -0.000350298, -2.81502, -0.000326159, -2.71091, -0.000299563, -2.65448, -0.000294284, -2.60865, -0.000277938, -2.589, -0.000277091, -2.56983, -0.000272783, -2.56825, -0.000252706, -2.58996, -0.000247834, -2.63158, -0.00024379, -2.76976, -0.000286468, -2.92484, -0.000310149, -3.27746}), "Local density efficiency function parameter for K0s, exp(Ax + B)") 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)") // switch - O2_DEFINE_CONFIGURABLE(cfgcheckDauTPC, bool, true, "check daughter tracks TPC or not") - O2_DEFINE_CONFIGURABLE(cfgcheckDauTOF, bool, false, "check daughter tracks TOF or not") O2_DEFINE_CONFIGURABLE(cfgDoAccEffCorr, bool, false, "do acc and eff corr") O2_DEFINE_CONFIGURABLE(cfgDoLocDenCorr, bool, false, "do local density corr") O2_DEFINE_CONFIGURABLE(cfgDoJackknife, bool, false, "do jackknife") O2_DEFINE_CONFIGURABLE(cfgOutputNUAWeights, bool, false, "Fill and output NUA weights") O2_DEFINE_CONFIGURABLE(cfgOutputLocDenWeights, bool, false, "Fill and output local density weights") + O2_DEFINE_CONFIGURABLE(cfgDoV0AT0Acut, bool, false, "do V0A-T0A cut") + O2_DEFINE_CONFIGURABLE(cfgOutputQA, bool, false, "do QA") + O2_DEFINE_CONFIGURABLE(cfgMultPVCut, int, 5, "Use apassX MultPVCut function or not") ConfigurableAxis cfgaxisVertex{"cfgaxisVertex", {20, -10, 10}, "vertex axis for histograms"}; ConfigurableAxis cfgaxisPhi{"cfgaxisPhi", {60, 0.0, constants::math::TwoPI}, "phi axis for histograms"}; @@ -124,7 +161,8 @@ struct FlowGfwOmegaXi { ConfigurableAxis cfgaxisPt{"cfgaxisPt", {VARIABLE_WIDTH, 0.20, 0.25, 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.20, 2.40, 2.60, 2.80, 3.00, 3.50, 4.00, 4.50, 5.00, 5.50, 6.00, 10.0}, "pt (GeV)"}; ConfigurableAxis cfgaxisPtXi{"cfgaxisPtXi", {VARIABLE_WIDTH, 0.9, 1.1, 1.3, 1.5, 1.7, 1.9, 2.1, 2.3, 2.5, 2.7, 2.9, 3.9, 4.9, 5.9, 9.9}, "pt (GeV)"}; ConfigurableAxis cfgaxisPtOmega{"cfgaxisPtOmega", {VARIABLE_WIDTH, 0.9, 1.1, 1.3, 1.5, 1.7, 1.9, 2.1, 2.3, 2.5, 2.7, 2.9, 3.9, 4.9, 5.9, 9.9}, "pt (GeV)"}; - ConfigurableAxis cfgaxisPtV0{"cfgaxisPtV0", {VARIABLE_WIDTH, 0.9, 1.1, 1.3, 1.5, 1.7, 1.9, 2.1, 2.3, 2.5, 2.7, 2.9, 3.9, 4.9, 5.9, 9.9}, "pt (GeV)"}; + ConfigurableAxis cfgaxisPtK0s{"cfgaxisPtK0s", {VARIABLE_WIDTH, 0.9, 1.1, 1.3, 1.5, 1.7, 1.9, 2.1, 2.3, 2.5, 2.7, 2.9, 3.9, 4.9, 5.9, 9.9}, "pt (GeV)"}; + ConfigurableAxis cfgaxisPtLambda{"cfgaxisPtLambda", {VARIABLE_WIDTH, 0.9, 1.1, 1.3, 1.5, 1.7, 1.9, 2.1, 2.3, 2.5, 2.7, 2.9, 3.9, 4.9, 5.9, 9.9}, "pt (GeV)"}; ConfigurableAxis cfgaxisOmegaMassforflow{"cfgaxisOmegaMassforflow", {16, 1.63f, 1.71f}, "Inv. Mass (GeV)"}; ConfigurableAxis cfgaxisXiMassforflow{"cfgaxisXiMassforflow", {14, 1.3f, 1.37f}, "Inv. Mass (GeV)"}; ConfigurableAxis cfgaxisK0sMassforflow{"cfgaxisK0sMassforflow", {40, 0.4f, 0.6f}, "Inv. Mass (GeV)"}; @@ -135,12 +173,12 @@ 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) < cfgCutEta) && (aod::track::pt > cfgCutPtPOIMin) && (aod::track::pt < cfgCutPtPOIMax) && ((requireGlobalTrackInFilter()) || (aod::track::isGlobalTrackSDD == (uint8_t) true)) && (aod::track::tpcChi2NCl < cfgCutChi2prTPCcls); + 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); using TracksPID = soa::Join; - using AodTracks = soa::Filtered>; // tracks filter + using AodTracks = soa::Filtered>; // tracks filter using AodCollisions = soa::Filtered>; // collisions filter - using DaughterTracks = soa::Join; + using DaughterTracks = soa::Join; // Connect to ccdb Service ccdb; @@ -158,10 +196,10 @@ struct FlowGfwOmegaXi { // define global variables GFW* fGFW = new GFW(); // GFW class used from main src std::vector corrconfigs; - std::vector cfgAcceptance = cfgAcceptancePath; - std::vector cfgEfficiency = cfgEfficiencyPath; - std::vector cfgNSigma = cfgNSigmatpctof; - std::vector cfgmassbins = cfgMassBins; + std::vector cfgAcceptance; + std::vector cfgEfficiency; + std::vector cfgNSigma; + std::vector cfgmassbins; std::vector mAcceptance; std::vector mEfficiency; @@ -179,8 +217,14 @@ struct FlowGfwOmegaXi { int nXiPtBins = 0; TAxis* fXiPtAxis = nullptr; - int nV0PtBins = 0; - TAxis* fV0PtAxis = nullptr; + int nOmegaPtBins = 0; + TAxis* fOmegaPtAxis = nullptr; + + int nK0sPtBins = 0; + TAxis* fK0sPtAxis = nullptr; + + int nLambdaPtBins = 0; + TAxis* fLambdaPtAxis = nullptr; TAxis* fMultAxis = nullptr; @@ -198,6 +242,11 @@ struct FlowGfwOmegaXi { ccdb->setCaching(true); ccdb->setCreatedNotAfter(cfgnolaterthan.value); + cfgAcceptance = cfgAcceptancePath; + cfgEfficiency = cfgEfficiencyPath; + cfgNSigma = cfgNSigmapid; + cfgmassbins = cfgMassBins; + // Set the pt, mult and phi Axis; o2::framework::AxisSpec axisPt = cfgaxisPt; nPtBins = axisPt.binEdges.size() - 1; @@ -207,9 +256,17 @@ struct FlowGfwOmegaXi { nXiPtBins = axisXiPt.binEdges.size() - 1; fXiPtAxis = new TAxis(nXiPtBins, &(axisXiPt.binEdges)[0]); - o2::framework::AxisSpec axisV0Pt = cfgaxisPtV0; - nV0PtBins = axisV0Pt.binEdges.size() - 1; - fV0PtAxis = new TAxis(nV0PtBins, &(axisV0Pt.binEdges)[0]); + o2::framework::AxisSpec axisOmegaPt = cfgaxisPtOmega; + nOmegaPtBins = axisOmegaPt.binEdges.size() - 1; + fOmegaPtAxis = new TAxis(nOmegaPtBins, &(axisOmegaPt.binEdges)[0]); + + o2::framework::AxisSpec axisK0sPt = cfgaxisPtK0s; + nK0sPtBins = axisK0sPt.binEdges.size() - 1; + fK0sPtAxis = new TAxis(nK0sPtBins, &(axisK0sPt.binEdges)[0]); + + o2::framework::AxisSpec axisLambdaPt = cfgaxisPtLambda; + nLambdaPtBins = axisLambdaPt.binEdges.size() - 1; + fLambdaPtAxis = new TAxis(nLambdaPtBins, &(axisLambdaPt.binEdges)[0]); o2::framework::AxisSpec axisMult = axisMultiplicity; int nMultBins = axisMult.binEdges.size() - 1; @@ -249,49 +306,58 @@ struct FlowGfwOmegaXi { registry.get(HIST("hEventCount"))->GetYaxis()->SetBinLabel(4, "Omega"); // QA - // V0 QA - registry.add("QAhisto/V0/hqaV0radiusbefore", "", {HistType::kTH1D, {{200, 0, 200}}}); - registry.add("QAhisto/V0/hqaV0radiusafter", "", {HistType::kTH1D, {{200, 0, 200}}}); - registry.add("QAhisto/V0/hqaV0cosPAbefore", "", {HistType::kTH1D, {{1000, 0.95, 1}}}); - registry.add("QAhisto/V0/hqaV0cosPAafter", "", {HistType::kTH1D, {{1000, 0.95, 1}}}); - registry.add("QAhisto/V0/hqadcaV0daubefore", "", {HistType::kTH1D, {{100, 0, 1}}}); - registry.add("QAhisto/V0/hqadcaV0dauafter", "", {HistType::kTH1D, {{100, 0, 1}}}); - registry.add("QAhisto/V0/hqaarm_podobefore", "", {HistType::kTH2D, {{100, -1, 1}, {50, 0, 0.3}}}); - registry.add("QAhisto/V0/hqaarm_podoafter", "", {HistType::kTH2D, {{100, -1, 1}, {50, 0, 0.3}}}); - registry.add("QAhisto/V0/hqadcapostoPVbefore", "", {HistType::kTH1D, {{1000, -10, 10}}}); - registry.add("QAhisto/V0/hqadcapostoPVafter", "", {HistType::kTH1D, {{1000, -10, 10}}}); - registry.add("QAhisto/V0/hqadcanegtoPVbefore", "", {HistType::kTH1D, {{1000, -10, 10}}}); - registry.add("QAhisto/V0/hqadcanegtoPVafter", "", {HistType::kTH1D, {{1000, -10, 10}}}); - // Cascade QA - registry.add("QAhisto/Casc/hqaCasccosPAbefore", "", {HistType::kTH1D, {{1000, 0.95, 1}}}); - registry.add("QAhisto/Casc/hqaCasccosPAafter", "", {HistType::kTH1D, {{1000, 0.95, 1}}}); - registry.add("QAhisto/Casc/hqaCascV0cosPAbefore", "", {HistType::kTH1D, {{1000, 0.95, 1}}}); - registry.add("QAhisto/Casc/hqaCascV0cosPAafter", "", {HistType::kTH1D, {{1000, 0.95, 1}}}); - registry.add("QAhisto/Casc/hqadcaCascV0toPVbefore", "", {HistType::kTH1D, {{1000, -10, 10}}}); - registry.add("QAhisto/Casc/hqadcaCascV0toPVafter", "", {HistType::kTH1D, {{1000, -10, 10}}}); - registry.add("QAhisto/Casc/hqadcaCascBachtoPVbefore", "", {HistType::kTH1D, {{1000, -10, 10}}}); - registry.add("QAhisto/Casc/hqadcaCascBachtoPVafter", "", {HistType::kTH1D, {{1000, -10, 10}}}); - registry.add("QAhisto/Casc/hqadcaCascdaubefore", "", {HistType::kTH1D, {{100, 0, 1}}}); - registry.add("QAhisto/Casc/hqadcaCascdauafter", "", {HistType::kTH1D, {{100, 0, 1}}}); - registry.add("QAhisto/Casc/hqadcaCascV0daubefore", "", {HistType::kTH1D, {{100, 0, 1}}}); - registry.add("QAhisto/Casc/hqadcaCascV0dauafter", "", {HistType::kTH1D, {{100, 0, 1}}}); + if (cfgOutputQA) { + // V0 QA + registry.add("QAhisto/V0/hqaV0radiusbefore", "", {HistType::kTH1D, {{200, 0, 200}}}); + registry.add("QAhisto/V0/hqaV0radiusafter", "", {HistType::kTH1D, {{200, 0, 200}}}); + registry.add("QAhisto/V0/hqaV0cosPAbefore", "", {HistType::kTH1D, {{1000, 0.95, 1}}}); + registry.add("QAhisto/V0/hqaV0cosPAafter", "", {HistType::kTH1D, {{1000, 0.95, 1}}}); + registry.add("QAhisto/V0/hqadcaV0daubefore", "", {HistType::kTH1D, {{100, 0, 1}}}); + registry.add("QAhisto/V0/hqadcaV0dauafter", "", {HistType::kTH1D, {{100, 0, 1}}}); + registry.add("QAhisto/V0/hqaarm_podobefore", "", {HistType::kTH2D, {{100, -1, 1}, {50, 0, 0.3}}}); + registry.add("QAhisto/V0/hqaarm_podoafter", "", {HistType::kTH2D, {{100, -1, 1}, {50, 0, 0.3}}}); + registry.add("QAhisto/V0/hqadcapostoPVbefore", "", {HistType::kTH1D, {{1000, -10, 10}}}); + registry.add("QAhisto/V0/hqadcapostoPVafter", "", {HistType::kTH1D, {{1000, -10, 10}}}); + registry.add("QAhisto/V0/hqadcanegtoPVbefore", "", {HistType::kTH1D, {{1000, -10, 10}}}); + registry.add("QAhisto/V0/hqadcanegtoPVafter", "", {HistType::kTH1D, {{1000, -10, 10}}}); + // Cascade QA + registry.add("QAhisto/Casc/hqaCasccosPAbefore", "", {HistType::kTH1D, {{1000, 0.95, 1}}}); + registry.add("QAhisto/Casc/hqaCasccosPAafter", "", {HistType::kTH1D, {{1000, 0.95, 1}}}); + registry.add("QAhisto/Casc/hqaCascV0cosPAbefore", "", {HistType::kTH1D, {{1000, 0.95, 1}}}); + registry.add("QAhisto/Casc/hqaCascV0cosPAafter", "", {HistType::kTH1D, {{1000, 0.95, 1}}}); + registry.add("QAhisto/Casc/hqadcaCascV0toPVbefore", "", {HistType::kTH1D, {{1000, -10, 10}}}); + registry.add("QAhisto/Casc/hqadcaCascV0toPVafter", "", {HistType::kTH1D, {{1000, -10, 10}}}); + registry.add("QAhisto/Casc/hqadcaCascBachtoPVbefore", "", {HistType::kTH1D, {{1000, -10, 10}}}); + registry.add("QAhisto/Casc/hqadcaCascBachtoPVafter", "", {HistType::kTH1D, {{1000, -10, 10}}}); + registry.add("QAhisto/Casc/hqadcaCascdaubefore", "", {HistType::kTH1D, {{100, 0, 1}}}); + registry.add("QAhisto/Casc/hqadcaCascdauafter", "", {HistType::kTH1D, {{100, 0, 1}}}); + registry.add("QAhisto/Casc/hqadcaCascV0daubefore", "", {HistType::kTH1D, {{100, 0, 1}}}); + registry.add("QAhisto/Casc/hqadcaCascV0dauafter", "", {HistType::kTH1D, {{100, 0, 1}}}); + } // cumulant of flow registry.add("c22", ";Centrality (%) ; C_{2}{2} ", {HistType::kTProfile, {axisMultiplicity}}); + registry.add("c32", ";Centrality (%) ; C_{2}{2} ", {HistType::kTProfile, {axisMultiplicity}}); registry.add("c24", ";Centrality (%) ; C_{2}{2} ", {HistType::kTProfile, {axisMultiplicity}}); registry.add("K0sc22", ";Centrality (%) ; C_{2}{2} ", {HistType::kTProfile, {axisMultiplicity}}); registry.add("Lambdac22", ";Centrality (%) ; C_{2}{2} ", {HistType::kTProfile, {axisMultiplicity}}); registry.add("c22dpt", ";Centrality (%) ; C_{2}{2}", {HistType::kTProfile2D, {cfgaxisPt, axisMultiplicity}}); registry.add("c24dpt", ";Centrality (%) ; C_{2}{4}", {HistType::kTProfile2D, {cfgaxisPt, axisMultiplicity}}); // pt-diff cumulant of flow + // v2 registry.add("Xic22dpt", ";pt ; C_{2}{2} ", {HistType::kTProfile3D, {cfgaxisPtXi, cfgaxisXiMassforflow, axisMultiplicity}}); - registry.add("Omegac22dpt", ";pt ; C_{2}{2} ", {HistType::kTProfile3D, {cfgaxisPtXi, cfgaxisOmegaMassforflow, axisMultiplicity}}); - registry.add("K0sc22dpt", ";pt ; C_{2}{2} ", {HistType::kTProfile3D, {cfgaxisPtV0, cfgaxisK0sMassforflow, axisMultiplicity}}); - registry.add("Lambdac22dpt", ";pt ; C_{2}{2} ", {HistType::kTProfile3D, {cfgaxisPtV0, cfgaxisLambdaMassforflow, axisMultiplicity}}); + registry.add("Omegac22dpt", ";pt ; C_{2}{2} ", {HistType::kTProfile3D, {cfgaxisPtOmega, cfgaxisOmegaMassforflow, axisMultiplicity}}); + registry.add("K0sc22dpt", ";pt ; C_{2}{2} ", {HistType::kTProfile3D, {cfgaxisPtK0s, cfgaxisK0sMassforflow, axisMultiplicity}}); + registry.add("Lambdac22dpt", ";pt ; C_{2}{2} ", {HistType::kTProfile3D, {cfgaxisPtLambda, cfgaxisLambdaMassforflow, axisMultiplicity}}); registry.add("Xic24dpt", ";pt ; C_{2}{4} ", {HistType::kTProfile3D, {cfgaxisPtXi, cfgaxisXiMassforflow, axisMultiplicity}}); - registry.add("Omegac24dpt", ";pt ; C_{2}{4} ", {HistType::kTProfile3D, {cfgaxisPtXi, cfgaxisOmegaMassforflow, axisMultiplicity}}); - registry.add("K0sc24dpt", ";pt ; C_{2}{4} ", {HistType::kTProfile3D, {cfgaxisPtV0, cfgaxisK0sMassforflow, axisMultiplicity}}); - registry.add("Lambdac24dpt", ";pt ; C_{2}{4} ", {HistType::kTProfile3D, {cfgaxisPtV0, cfgaxisLambdaMassforflow, axisMultiplicity}}); + registry.add("Omegac24dpt", ";pt ; C_{2}{4} ", {HistType::kTProfile3D, {cfgaxisPtOmega, cfgaxisOmegaMassforflow, axisMultiplicity}}); + registry.add("K0sc24dpt", ";pt ; C_{2}{4} ", {HistType::kTProfile3D, {cfgaxisPtK0s, cfgaxisK0sMassforflow, axisMultiplicity}}); + registry.add("Lambdac24dpt", ";pt ; C_{2}{4} ", {HistType::kTProfile3D, {cfgaxisPtK0s, cfgaxisLambdaMassforflow, axisMultiplicity}}); + // v3 + registry.add("Xic32dpt", ";pt ; C_{2}{2} ", {HistType::kTProfile3D, {cfgaxisPtXi, cfgaxisXiMassforflow, axisMultiplicity}}); + registry.add("Omegac32dpt", ";pt ; C_{2}{2} ", {HistType::kTProfile3D, {cfgaxisPtOmega, cfgaxisOmegaMassforflow, axisMultiplicity}}); + registry.add("K0sc32dpt", ";pt ; C_{2}{2} ", {HistType::kTProfile3D, {cfgaxisPtK0s, cfgaxisK0sMassforflow, axisMultiplicity}}); + registry.add("Lambdac32dpt", ";pt ; C_{2}{2} ", {HistType::kTProfile3D, {cfgaxisPtLambda, cfgaxisLambdaMassforflow, axisMultiplicity}}); // for Jackknife if (cfgDoJackknife) { int nsubevent = 10; @@ -299,43 +365,48 @@ struct FlowGfwOmegaXi { refc22[i - 1] = registry.add(Form("Jackknife/REF/c22_%d", i), ";Centrality (%) ; C_{2}{2} ", {HistType::kTProfile, {axisMultiplicity}}); refc24[i - 1] = registry.add(Form("Jackknife/REF/c24_%d", i), ";Centrality (%) ; C_{2}{2} ", {HistType::kTProfile, {axisMultiplicity}}); xic22[i - 1] = registry.add(Form("Jackknife/Xi/Xic22dpt_%d", i), ";pt ; C_{2}{2} ", {HistType::kTProfile3D, {cfgaxisPtXi, cfgaxisXiMassforflow, axisMultiplicity}}); - omegac22[i - 1] = registry.add(Form("Jackknife/Omega/Omegac22dpt_%d", i), ";pt ; C_{2}{2} ", {HistType::kTProfile3D, {cfgaxisPtXi, cfgaxisOmegaMassforflow, axisMultiplicity}}); - k0sc22[i - 1] = registry.add(Form("Jackknife/K0s/K0sc22dpt_%d", i), ";pt ; C_{2}{2} ", {HistType::kTProfile3D, {cfgaxisPtV0, cfgaxisK0sMassforflow, axisMultiplicity}}); - lambdac22[i - 1] = registry.add(Form("Jackknife/Lambda/Lambdac22dpt_%d", i), ";pt ; C_{2}{2} ", {HistType::kTProfile3D, {cfgaxisPtV0, cfgaxisLambdaMassforflow, axisMultiplicity}}); + omegac22[i - 1] = registry.add(Form("Jackknife/Omega/Omegac22dpt_%d", i), ";pt ; C_{2}{2} ", {HistType::kTProfile3D, {cfgaxisPtOmega, cfgaxisOmegaMassforflow, axisMultiplicity}}); + k0sc22[i - 1] = registry.add(Form("Jackknife/K0s/K0sc22dpt_%d", i), ";pt ; C_{2}{2} ", {HistType::kTProfile3D, {cfgaxisPtK0s, cfgaxisK0sMassforflow, axisMultiplicity}}); + lambdac22[i - 1] = registry.add(Form("Jackknife/Lambda/Lambdac22dpt_%d", i), ";pt ; C_{2}{2} ", {HistType::kTProfile3D, {cfgaxisPtLambda, cfgaxisLambdaMassforflow, axisMultiplicity}}); xic24[i - 1] = registry.add(Form("Jackknife/Xi/Xic24dpt_%d", i), ";pt ; C_{2}{4} ", {HistType::kTProfile3D, {cfgaxisPtXi, cfgaxisXiMassforflow, axisMultiplicity}}); - omegac24[i - 1] = registry.add(Form("Jackknife/Omega/Omegac24dpt_%d", i), ";pt ; C_{2}{4} ", {HistType::kTProfile3D, {cfgaxisPtXi, cfgaxisOmegaMassforflow, axisMultiplicity}}); - k0sc24[i - 1] = registry.add(Form("Jackknife/K0s/K0sc24dpt_%d", i), ";pt ; C_{2}{4} ", {HistType::kTProfile3D, {cfgaxisPtV0, cfgaxisK0sMassforflow, axisMultiplicity}}); - lambdac24[i - 1] = registry.add(Form("Jackknife/Lambda/Lambdac24dpt_%d", i), ";pt ; C_{2}{4} ", {HistType::kTProfile3D, {cfgaxisPtV0, cfgaxisLambdaMassforflow, axisMultiplicity}}); + omegac24[i - 1] = registry.add(Form("Jackknife/Omega/Omegac24dpt_%d", i), ";pt ; C_{2}{4} ", {HistType::kTProfile3D, {cfgaxisPtOmega, cfgaxisOmegaMassforflow, axisMultiplicity}}); + k0sc24[i - 1] = registry.add(Form("Jackknife/K0s/K0sc24dpt_%d", i), ";pt ; C_{2}{4} ", {HistType::kTProfile3D, {cfgaxisPtK0s, cfgaxisK0sMassforflow, axisMultiplicity}}); + lambdac24[i - 1] = registry.add(Form("Jackknife/Lambda/Lambdac24dpt_%d", i), ";pt ; C_{2}{4} ", {HistType::kTProfile3D, {cfgaxisPtLambda, cfgaxisLambdaMassforflow, axisMultiplicity}}); + refc32[i - 1] = registry.add(Form("Jackknife/REF/c32_%d", i), ";Centrality (%) ; C_{2}{2} ", {HistType::kTProfile, {axisMultiplicity}}); + xic32[i - 1] = registry.add(Form("Jackknife/Xi/Xic32dpt_%d", i), ";pt ; C_{2}{2} ", {HistType::kTProfile3D, {cfgaxisPtXi, cfgaxisXiMassforflow, axisMultiplicity}}); + omegac32[i - 1] = registry.add(Form("Jackknife/Omega/Omegac32dpt_%d", i), ";pt ; C_{2}{2} ", {HistType::kTProfile3D, {cfgaxisPtOmega, cfgaxisOmegaMassforflow, axisMultiplicity}}); + k0sc32[i - 1] = registry.add(Form("Jackknife/K0s/K0sc32dpt_%d", i), ";pt ; C_{2}{2} ", {HistType::kTProfile3D, {cfgaxisPtK0s, cfgaxisK0sMassforflow, axisMultiplicity}}); + lambdac32[i - 1] = registry.add(Form("Jackknife/Lambda/Lambdac32dpt_%d", i), ";pt ; C_{2}{2} ", {HistType::kTProfile3D, {cfgaxisPtLambda, cfgaxisLambdaMassforflow, axisMultiplicity}}); } } // MC True flow registry.add("MC/c22MC", ";Centrality (%) ; C_{2}{2} ", {HistType::kTProfile, {axisMultiplicity}}); registry.add("MC/Xic22dptMC", ";pt ; C_{2}{2} ", {HistType::kTProfile2D, {cfgaxisPtXi, axisMultiplicity}}); - registry.add("MC/Omegac22dptMC", ";pt ; C_{2}{2} ", {HistType::kTProfile2D, {cfgaxisPtXi, axisMultiplicity}}); - registry.add("MC/K0sc22dptMC", ";pt ; C_{2}{2} ", {HistType::kTProfile2D, {cfgaxisPtV0, axisMultiplicity}}); - registry.add("MC/Lambdac22dptMC", ";pt ; C_{2}{2} ", {HistType::kTProfile2D, {cfgaxisPtV0, axisMultiplicity}}); + registry.add("MC/Omegac22dptMC", ";pt ; C_{2}{2} ", {HistType::kTProfile2D, {cfgaxisPtOmega, axisMultiplicity}}); + registry.add("MC/K0sc22dptMC", ";pt ; C_{2}{2} ", {HistType::kTProfile2D, {cfgaxisPtK0s, axisMultiplicity}}); + 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 = {70, 1.3f, 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)"}; registry.add("InvMassXi_all", "", {HistType::kTHnSparseF, {cfgaxisPtXi, axisXiMass, cfgaxisEta, axisMultiplicity}}); - registry.add("InvMassOmega_all", "", {HistType::kTHnSparseF, {cfgaxisPtXi, axisOmegaMass, cfgaxisEta, axisMultiplicity}}); - registry.add("InvMassOmega", "", {HistType::kTHnSparseF, {cfgaxisPtXi, axisOmegaMass, cfgaxisEta, axisMultiplicity}}); + registry.add("InvMassOmega_all", "", {HistType::kTHnSparseF, {cfgaxisPtOmega, axisOmegaMass, cfgaxisEta, axisMultiplicity}}); registry.add("InvMassXi", "", {HistType::kTHnSparseF, {cfgaxisPtXi, axisXiMass, cfgaxisEta, axisMultiplicity}}); - registry.add("InvMassK0s_all", "", {HistType::kTHnSparseF, {cfgaxisPtV0, axisK0sMass, cfgaxisEta, axisMultiplicity}}); - registry.add("InvMassLambda_all", "", {HistType::kTHnSparseF, {cfgaxisPtV0, axisLambdaMass, cfgaxisEta, axisMultiplicity}}); - registry.add("InvMassK0s", "", {HistType::kTHnSparseF, {cfgaxisPtV0, axisK0sMass, cfgaxisEta, axisMultiplicity}}); - registry.add("InvMassLambda", "", {HistType::kTHnSparseF, {cfgaxisPtV0, axisLambdaMass, cfgaxisEta, axisMultiplicity}}); + registry.add("InvMassOmega", "", {HistType::kTHnSparseF, {cfgaxisPtOmega, axisOmegaMass, cfgaxisEta, axisMultiplicity}}); + registry.add("InvMassK0s_all", "", {HistType::kTHnSparseF, {cfgaxisPtK0s, axisK0sMass, cfgaxisEta, axisMultiplicity}}); + registry.add("InvMassLambda_all", "", {HistType::kTHnSparseF, {cfgaxisPtLambda, axisLambdaMass, cfgaxisEta, axisMultiplicity}}); + registry.add("InvMassK0s", "", {HistType::kTHnSparseF, {cfgaxisPtK0s, axisK0sMass, cfgaxisEta, axisMultiplicity}}); + registry.add("InvMassLambda", "", {HistType::kTHnSparseF, {cfgaxisPtLambda, axisLambdaMass, cfgaxisEta, axisMultiplicity}}); // for local density correlation - registry.add("MC/densityMCGenK0s", "", {HistType::kTH3D, {cfgaxisPtV0, cfgaxisNch, cfgaxisLocalDensity}}); - registry.add("MC/densityMCGenLambda", "", {HistType::kTH3D, {cfgaxisPtV0, cfgaxisNch, cfgaxisLocalDensity}}); + registry.add("MC/densityMCGenK0s", "", {HistType::kTH3D, {cfgaxisPtK0s, cfgaxisNch, cfgaxisLocalDensity}}); + registry.add("MC/densityMCGenLambda", "", {HistType::kTH3D, {cfgaxisPtLambda, cfgaxisNch, cfgaxisLocalDensity}}); registry.add("MC/densityMCGenXi", "", {HistType::kTH3D, {cfgaxisPtXi, cfgaxisNch, cfgaxisLocalDensity}}); - registry.add("MC/densityMCGenOmega", "", {HistType::kTH3D, {cfgaxisPtXi, cfgaxisNch, cfgaxisLocalDensity}}); - registry.add("MC/densityMCRecK0s", "", {HistType::kTHnSparseF, {cfgaxisPtV0, cfgaxisNch, cfgaxisLocalDensity, axisK0sMass}}); - registry.add("MC/densityMCRecLambda", "", {HistType::kTHnSparseF, {cfgaxisPtV0, cfgaxisNch, cfgaxisLocalDensity, axisLambdaMass}}); + registry.add("MC/densityMCGenOmega", "", {HistType::kTH3D, {cfgaxisPtOmega, cfgaxisNch, cfgaxisLocalDensity}}); + registry.add("MC/densityMCRecK0s", "", {HistType::kTHnSparseF, {cfgaxisPtK0s, cfgaxisNch, cfgaxisLocalDensity, axisK0sMass}}); + registry.add("MC/densityMCRecLambda", "", {HistType::kTHnSparseF, {cfgaxisPtLambda, cfgaxisNch, cfgaxisLocalDensity, axisLambdaMass}}); registry.add("MC/densityMCRecXi", "", {HistType::kTHnSparseF, {cfgaxisPtXi, cfgaxisNch, cfgaxisLocalDensity, axisXiMass}}); - registry.add("MC/densityMCRecOmega", "", {HistType::kTHnSparseF, {cfgaxisPtXi, cfgaxisNch, cfgaxisLocalDensity, axisOmegaMass}}); + registry.add("MC/densityMCRecOmega", "", {HistType::kTHnSparseF, {cfgaxisPtOmega, cfgaxisNch, cfgaxisLocalDensity, axisOmegaMass}}); // Data fGFW->AddRegion("reffull", -0.8, 0.8, 1, 1); // ("name", etamin, etamax, ptbinnum, bitmask)eta region -0.8 to 0.8 @@ -359,13 +430,13 @@ struct FlowGfwOmegaXi { fGFW->AddRegion("poiOmegafulldpt", -0.8, 0.8, nOmegaptMassBins, 4); fGFW->AddRegion("poiOmegaP", 0.4, 0.8, 1, 4); fGFW->AddRegion("poiOmegaN", -0.8, -0.4, 1, 4); - int nK0sptMassBins = nV0PtBins * cfgmassbins[0]; + int nK0sptMassBins = nK0sPtBins * cfgmassbins[0]; fGFW->AddRegion("poiK0sPdpt", 0.4, 0.8, nK0sptMassBins, 8); fGFW->AddRegion("poiK0sNdpt", -0.8, -0.4, nK0sptMassBins, 8); fGFW->AddRegion("poiK0sfulldpt", -0.8, 0.8, nK0sptMassBins, 8); fGFW->AddRegion("poiK0sP", 0.4, 0.8, 1, 8); fGFW->AddRegion("poiK0sN", -0.8, 0.4, 1, 8); - int nLambdaptMassBins = nV0PtBins * cfgmassbins[1]; + int nLambdaptMassBins = nLambdaPtBins * cfgmassbins[1]; fGFW->AddRegion("poiLambdaPdpt", 0.4, 0.8, nLambdaptMassBins, 16); fGFW->AddRegion("poiLambdaNdpt", -0.8, -0.4, nLambdaptMassBins, 16); fGFW->AddRegion("poiLambdafulldpt", -0.8, 0.8, nLambdaptMassBins, 16); @@ -384,6 +455,7 @@ struct FlowGfwOmegaXi { fGFW->AddRegion("poiLambdaNdptMC", -0.8, -0.4, nLambdaptMassBins, 1024); // pushback // Data + // v2 corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiP10dpt {2} refN10 {-2}", "Poi10Gap22dpta", kTRUE)); // 0 corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiN10dpt {2} refP10 {-2}", "Poi10Gap22dptb", kTRUE)); corrconfigs.push_back(fGFW->GetCorrelatorConfig("poifulldpt reffull | poioldpt {2 2 -2 -2}", "Poi10Gap24dpt", kTRUE)); @@ -401,23 +473,44 @@ struct FlowGfwOmegaXi { corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiLambdafulldpt reffull {2 2 -2 -2}", "Xi10Gap24a", kTRUE)); corrconfigs.push_back(fGFW->GetCorrelatorConfig("refP10 {2} refN10 {-2}", "Ref10Gap22a", kFALSE)); // 15 corrconfigs.push_back(fGFW->GetCorrelatorConfig("reffull reffull {2 2 -2 -2}", "Ref10Gap24", kFALSE)); + // v3 + corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiXiPdpt {3} refN10 {-3}", "Xi10Gap32a", kTRUE)); + corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiXiNdpt {3} refP10 {-3}", "Xi10Gap32b", kTRUE)); + corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiOmegaPdpt {3} refN10 {-3}", "Omega10Gap32a", kTRUE)); + corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiOmegaNdpt {3} refP10 {-3}", "Omega10Gap32b", kTRUE)); // 20 + corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiK0sPdpt {3} refN10 {-3}", "K0short10Gap32a", kTRUE)); + corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiK0sNdpt {3} refP10 {-3}", "K0short10Gap32b", kTRUE)); + corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiLambdaPdpt {3} refN10 {-3}", "Lambda10Gap32a", kTRUE)); + corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiLambdaNdpt {3} refP10 {-3}", "Lambda10Gap32b", kTRUE)); + corrconfigs.push_back(fGFW->GetCorrelatorConfig("refP10 {3} refN10 {-3}", "Ref10Gap32a", kFALSE)); // 25 // MC - corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiXiPdptMC {2} refN10MC {-2}", "MCXi10Gap22a", kTRUE)); // 17 + corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiXiPdptMC {2} refN10MC {-2}", "MCXi10Gap22a", kTRUE)); corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiXiNdptMC {2} refP10MC {-2}", "MCXi10Gap22b", kTRUE)); corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiOmegaPdptMC {2} refN10MC {-2}", "MCOmega10Gap22a", kTRUE)); - corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiOmegaNdptMC {2} refP10MC {-2}", "MCOmega10Gap22b", kTRUE)); // 20 - corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiK0sPdptMC {2} refN10MC {-2}", "MCK0s10Gap22a", kTRUE)); + corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiOmegaNdptMC {2} refP10MC {-2}", "MCOmega10Gap22b", kTRUE)); + corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiK0sPdptMC {2} refN10MC {-2}", "MCK0s10Gap22a", kTRUE)); // 30 corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiK0sNdptMC {2} refP10MC {-2}", "MCK0s10Gap22b", kTRUE)); corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiLambdaPdptMC {2} refN10MC {-2}", "MCLambda10Gap22a", kTRUE)); corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiLambdaNdptMC {2} refP10MC {-2}", "MCLambda10Gap22b", kTRUE)); - corrconfigs.push_back(fGFW->GetCorrelatorConfig("refP10MC {2} refN10MC {-2}", "MCRef10Gap22a", kFALSE)); // 25 + corrconfigs.push_back(fGFW->GetCorrelatorConfig("refP10MC {2} refN10MC {-2}", "MCRef10Gap22a", kFALSE)); // 33 fGFW->CreateRegions(); // finalize the initialization // used for event selection - fMultPVCutLow = new TF1("fMultPVCutLow", "[0]+[1]*x+[2]*x*x+[3]*x*x*x+[4]*x*x*x*x - 3.5*([5]+[6must ]*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); - 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); - fMultPVCutHigh->SetParameters(3257.29, -121.848, 1.98492, -0.0172128, 6.47528e-05, 154.756, -1.86072, -0.0274713, 0.000633499, -3.37757e-06); + int caseapass4 = 4; + int caseapass5 = 5; + if (cfgMultPVCut == caseapass4) { + 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); + fMultPVCutLow->SetParameters(3257.29, -121.848, 1.98492, -0.0172128, 6.47528e-05, 154.756, -1.86072, -0.0274713, 0.000633499, -3.37757e-06); + 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); + fMultPVCutHigh->SetParameters(3257.29, -121.848, 1.98492, -0.0172128, 6.47528e-05, 154.756, -1.86072, -0.0274713, 0.000633499, -3.37757e-06); + } + if (cfgMultPVCut == caseapass5) { + 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); + fMultPVCutLow->SetParameters(3074.43, -106.192, 1.46176, -0.00968364, 2.61923e-05, 182.128, -7.43492, 0.193901, -0.00256715, 1.22594e-05); + 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); + fMultPVCutHigh->SetParameters(3074.43, -106.192, 1.46176, -0.00968364, 2.61923e-05, 182.128, -7.43492, 0.193901, -0.00256715, 1.22594e-05); + } + fT0AV0AMean = new TF1("fT0AV0AMean", "[0]+[1]*x", 0, 200000); fT0AV0AMean->SetParameters(-1601.0581, 9.417652e-01); fT0AV0ASigma = new TF1("fT0AV0ASigma", "[0]+[1]*x+[2]*x*x+[3]*x*x*x+[4]*x*x*x*x", 0, 200000); @@ -493,11 +586,11 @@ struct FlowGfwOmegaXi { if (PDGCode == kXiMinus) { fpt = fXiPtAxis; } else if (PDGCode == kOmegaMinus) { - fpt = fXiPtAxis; + fpt = fOmegaPtAxis; } else if (PDGCode == kK0Short) { - fpt = fV0PtAxis; + fpt = fK0sPtAxis; } else if (PDGCode == kLambda0) { - fpt = fV0PtAxis; + fpt = fLambdaPtAxis; } else { LOGF(error, "Error, please put in correct PDGCode of K0s, Lambda, Xi or Omega"); return; @@ -529,18 +622,18 @@ struct FlowGfwOmegaXi { fMass = fXiMass; } else if (PDGCode == kOmegaMinus) { nMassBins = cfgmassbins[3]; - nptbins = nXiPtBins; - fpt = fXiPtAxis; + nptbins = nOmegaPtBins; + fpt = fOmegaPtAxis; fMass = fOmegaMass; } else if (PDGCode == kK0Short) { nMassBins = cfgmassbins[0]; - nptbins = nV0PtBins; - fpt = fV0PtAxis; + nptbins = nK0sPtBins; + fpt = fK0sPtAxis; fMass = fK0sMass; } else if (PDGCode == kLambda0) { nMassBins = cfgmassbins[1]; - nptbins = nV0PtBins; - fpt = fV0PtAxis; + nptbins = nLambdaPtBins; + fpt = fLambdaPtAxis; fMass = fLambdaMass; } else { LOGF(error, "Error, please put in correct PDGCode of K0s, Lambda, Xi or Omega"); @@ -574,18 +667,18 @@ struct FlowGfwOmegaXi { fMass = fXiMass; } else if (PDGCode == kOmegaMinus) { nMassBins = cfgmassbins[3]; - nptbins = nXiPtBins; - fpt = fXiPtAxis; + nptbins = nOmegaPtBins; + fpt = fOmegaPtAxis; fMass = fOmegaMass; } else if (PDGCode == kK0Short) { nMassBins = cfgmassbins[0]; - nptbins = nV0PtBins; - fpt = fV0PtAxis; + nptbins = nK0sPtBins; + fpt = fK0sPtAxis; fMass = fK0sMass; } else if (PDGCode == kLambda0) { nMassBins = cfgmassbins[1]; - nptbins = nV0PtBins; - fpt = fV0PtAxis; + nptbins = nLambdaPtBins; + fpt = fLambdaPtAxis; fMass = fLambdaMass; } else { LOGF(error, "Error, please put in correct PDGCode of K0s, Lambda, Xi or Omega"); @@ -716,23 +809,30 @@ struct FlowGfwOmegaXi { if (std::fabs(vtxz) > cfgCutVertex) return false; - if (multNTracksPV < fMultPVCutLow->Eval(centrality)) - return false; - if (multNTracksPV > fMultPVCutHigh->Eval(centrality)) - return false; + int caseapass4 = 4; + int caseapass5 = 5; + if (cfgMultPVCut == caseapass4 || cfgMultPVCut == caseapass5) { + if (multNTracksPV < fMultPVCutLow->Eval(centrality)) + return false; + if (multNTracksPV > fMultPVCutHigh->Eval(centrality)) + return false; + } if (occupancy > cfgCutOccupancyHigh) return 0; // V0A T0A 5 sigma cut - int nsigma = 5; - if (std::fabs(collision.multFV0A() - fT0AV0AMean->Eval(collision.multFT0A())) > nsigma * fT0AV0ASigma->Eval(collision.multFT0A())) - return 0; + if (cfgDoV0AT0Acut) { + int nsigma = 5; + if (std::fabs(collision.multFV0A() - fT0AV0AMean->Eval(collision.multFT0A())) > nsigma * fT0AV0ASigma->Eval(collision.multFT0A())) + return 0; + } return true; } void processData(AodCollisions::iterator const& collision, aod::BCsWithTimestamps const&, AodTracks const& tracks, aod::CascDataExt const& Cascades, aod::V0Datas const& V0s, DaughterTracks const&) { + o2::aod::ITSResponse itsResponse; int nTot = tracks.size(); int candNumAll[4] = {0, 0, 0, 0}; int candNum[4] = {0, 0, 0, 0}; @@ -775,10 +875,10 @@ struct FlowGfwOmegaXi { registry.fill(HIST("hEtaPhiVtxzREF"), track.phi(), track.eta(), vtxz, wacc); registry.fill(HIST("hPt"), track.pt()); int ptbin = fPtAxis->FindBin(track.pt()) - 1; - if ((track.pt() > cfgCutPtMin) && (track.pt() < cfgCutPtMax)) { + if ((track.pt() > trkQualityOpts.cfgCutPtMin.value) && (track.pt() < trkQualityOpts.cfgCutPtMax.value)) { fGFW->Fill(track.eta(), ptbin, track.phi(), wacc * weff, 1); //(eta, ptbin, phi, wacc*weff, bitmask) } - if ((track.pt() > cfgCutPtPOIMin) && (track.pt() < cfgCutPtPOIMax)) { + if ((track.pt() > trkQualityOpts.cfgCutPtPOIMin.value) && (track.pt() < trkQualityOpts.cfgCutPtPOIMax.value)) { fGFW->Fill(track.eta(), ptbin, track.phi(), wacc * weff, 32); if (cfgDoLocDenCorr) { hLocalDensity->Fill(track.phi(), wacc * weff); @@ -793,79 +893,107 @@ struct FlowGfwOmegaXi { registry.fill(HIST("hCentvsNch"), cent, nch); } // fill GFW of V0 flow - double lowpt = 0.4; + double lowpt = trkQualityOpts.cfgCutPtPIDDauMin.value; + for (const auto& v0 : V0s) { auto v0posdau = v0.posTrack_as(); auto v0negdau = v0.negTrack_as(); // check tpc bool isK0s = false; bool isLambda = false; + + if (v0posdau.pt() < trkQualityOpts.cfgCutPtDauMin.value || v0posdau.pt() > trkQualityOpts.cfgCutPtDauMax.value) + continue; + if (v0negdau.pt() < trkQualityOpts.cfgCutPtDauMin.value || v0negdau.pt() > trkQualityOpts.cfgCutPtDauMax.value) + continue; + // fill QA - registry.fill(HIST("QAhisto/V0/hqaarm_podobefore"), v0.alpha(), v0.qtarm()); + if (cfgOutputQA) { + registry.fill(HIST("QAhisto/V0/hqaarm_podobefore"), v0.alpha(), v0.qtarm()); + } // check daughter TPC and TOF // K0short - if (v0.qtarm() / std::fabs(v0.alpha()) > cfgv0_ArmPodocut && std::fabs(v0.mK0Short() - o2::constants::physics::MassK0Short) < cfgv0_mk0swindow && - (!cfgcheckDauTPC || (std::fabs(v0posdau.tpcNSigmaPi()) < cfgNSigma[0] && std::fabs(v0negdau.tpcNSigmaPi()) < cfgNSigma[0])) && - (!cfgcheckDauTOF || ((std::fabs(v0posdau.tofNSigmaPi()) < cfgNSigma[3] || v0posdau.pt() < lowpt) && (std::fabs(v0negdau.tofNSigmaPi()) < cfgNSigma[3] || v0negdau.pt() < lowpt)))) { - registry.fill(HIST("InvMassK0s_all"), v0.pt(), v0.mK0Short(), v0.eta(), cent); - isK0s = true; - candNumAll[0] = candNumAll[0] + 1; - registry.fill(HIST("QAhisto/V0/hqaarm_podoafter"), v0.alpha(), v0.qtarm()); + 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 && + (std::fabs(v0posdau.tpcNSigmaPi()) < cfgNSigma[0] && std::fabs(v0negdau.tpcNSigmaPi()) < cfgNSigma[0]) && + ((std::fabs(v0posdau.tofNSigmaPi()) < cfgNSigma[3] || v0posdau.pt() < lowpt) && (std::fabs(v0negdau.tofNSigmaPi()) < 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)) { + registry.fill(HIST("InvMassK0s_all"), v0.pt(), v0.mK0Short(), v0.eta(), cent); + isK0s = true; + candNumAll[0] = candNumAll[0] + 1; + if (cfgOutputQA) { + registry.fill(HIST("QAhisto/V0/hqaarm_podoafter"), v0.alpha(), v0.qtarm()); + } + } } // Lambda and antiLambda - if (std::fabs(v0.mLambda() - o2::constants::physics::MassLambda) < cfgv0_mlambdawindow && - (!cfgcheckDauTPC || (std::fabs(v0posdau.tpcNSigmaPr()) < cfgNSigma[1] && std::fabs(v0negdau.tpcNSigmaPi()) < cfgNSigma[0])) && - (!cfgcheckDauTOF || ((std::fabs(v0posdau.tofNSigmaPr()) < cfgNSigma[4] || v0posdau.pt() < lowpt) && (std::fabs(v0negdau.tofNSigmaPi()) < cfgNSigma[3] || v0negdau.pt() < lowpt)))) { - registry.fill(HIST("InvMassLambda_all"), v0.pt(), v0.mLambda(), v0.eta(), cent); - isLambda = true; - candNumAll[1] = candNumAll[1] + 1; - } else if (std::fabs(v0.mLambda() - o2::constants::physics::MassLambda) < cfgv0_mlambdawindow && - (!cfgcheckDauTPC || (std::fabs(v0negdau.tpcNSigmaPr()) < cfgNSigma[1] && std::fabs(v0posdau.tpcNSigmaPi()) < cfgNSigma[0])) && - (!cfgcheckDauTOF || ((std::fabs(v0negdau.tofNSigmaPr()) < cfgNSigma[4] || v0negdau.pt() < lowpt) && (std::fabs(v0posdau.tofNSigmaPi()) < cfgNSigma[3] || v0posdau.pt() < lowpt)))) { - registry.fill(HIST("InvMassLambda_all"), v0.pt(), v0.mLambda(), v0.eta(), cent); - isLambda = true; - candNumAll[1] = candNumAll[1] + 1; + if (v0.pt() > trkQualityOpts.cfgCutPtLambdaMin.value && v0.pt() < trkQualityOpts.cfgCutPtLambdaMax.value) { + 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]) && + ((std::fabs(v0posdau.tofNSigmaPr()) < cfgNSigma[4] || v0posdau.pt() < lowpt) && (std::fabs(v0negdau.tofNSigmaPi()) < 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; + candNumAll[1] = candNumAll[1] + 1; + } 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]) && + ((std::fabs(v0negdau.tofNSigmaPr()) < cfgNSigma[4] || v0negdau.pt() < lowpt) && (std::fabs(v0posdau.tofNSigmaPi()) < cfgNSigma[3] || v0posdau.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; + candNumAll[1] = candNumAll[1] + 1; + } } // fill QA before cut - registry.fill(HIST("QAhisto/V0/hqaV0radiusbefore"), v0.v0radius()); - registry.fill(HIST("QAhisto/V0/hqaV0cosPAbefore"), v0.v0cosPA()); - registry.fill(HIST("QAhisto/V0/hqadcaV0daubefore"), v0.dcaV0daughters()); - registry.fill(HIST("QAhisto/V0/hqadcapostoPVbefore"), v0.dcapostopv()); - registry.fill(HIST("QAhisto/V0/hqadcanegtoPVbefore"), v0.dcanegtopv()); + if (cfgOutputQA) { + registry.fill(HIST("QAhisto/V0/hqaV0radiusbefore"), v0.v0radius()); + registry.fill(HIST("QAhisto/V0/hqaV0cosPAbefore"), v0.v0cosPA()); + registry.fill(HIST("QAhisto/V0/hqadcaV0daubefore"), v0.dcaV0daughters()); + registry.fill(HIST("QAhisto/V0/hqadcapostoPVbefore"), v0.dcapostopv()); + registry.fill(HIST("QAhisto/V0/hqadcanegtoPVbefore"), v0.dcanegtopv()); + } if (!isK0s && !isLambda) continue; // track quality check - if (v0posdau.tpcNClsFound() < cfgtpcclusters) - continue; - if (v0negdau.tpcNClsFound() < cfgtpcclusters) + if (!v0posdau.passedITSNCls() && trkQualityOpts.cfgCheckITSNCls.value) continue; - if (v0posdau.tpcNClsFindable() < cfgtpcclufindable) + if (!v0negdau.passedITSNCls() && trkQualityOpts.cfgCheckITSNCls.value) continue; - if (v0negdau.tpcNClsFindable() < cfgtpcclufindable) + if (!v0posdau.passedITSHits() && trkQualityOpts.cfgCheckITSHits.value) continue; - if (v0posdau.tpcCrossedRowsOverFindableCls() < cfgtpccrossoverfindable) + if (!v0negdau.passedITSHits() && trkQualityOpts.cfgCheckITSHits.value) continue; - if (v0posdau.itsNCls() < cfgitsclusters) + if (!v0posdau.passedITSChi2NDF() && trkQualityOpts.cfgCheckITSChi2NDF.value) continue; - if (v0negdau.itsNCls() < cfgitsclusters) + if (!v0negdau.passedITSChi2NDF() && trkQualityOpts.cfgCheckITSChi2NDF.value) continue; - // topological cut - if (v0.v0radius() < cfgv0_radius) + if (trkQualityOpts.cfgCheckGlobalTrack.value) { + if (!v0posdau.hasTPC() || !v0posdau.hasITS()) + continue; + if (!v0negdau.hasTPC() || !v0negdau.hasITS()) + continue; + } + // // topological cut + if (v0.v0radius() < v0BuilderOpts.cfgv0_radius.value) continue; - if (v0.v0cosPA() < cfgv0_v0cospa) + if (v0.v0cosPA() < v0BuilderOpts.cfgv0_v0cospa.value) continue; - if (v0.dcaV0daughters() > cfgv0_dcav0dau) + if (v0.dcaV0daughters() > v0BuilderOpts.cfgv0_dcav0dau.value) continue; - if (std::fabs(v0.dcapostopv()) < cfgv0_dcadautopv) + if (std::fabs(v0.dcapostopv()) < v0BuilderOpts.cfgv0_dcadautopv.value) continue; - if (std::fabs(v0.dcanegtopv()) < cfgv0_dcadautopv) + if (std::fabs(v0.dcanegtopv()) < v0BuilderOpts.cfgv0_dcadautopv.value) continue; + // fill QA after cut - registry.fill(HIST("QAhisto/V0/hqaV0radiusafter"), v0.v0radius()); - registry.fill(HIST("QAhisto/V0/hqaV0cosPAafter"), v0.v0cosPA()); - registry.fill(HIST("QAhisto/V0/hqadcaV0dauafter"), v0.dcaV0daughters()); - registry.fill(HIST("QAhisto/V0/hqadcapostoPVafter"), v0.dcapostopv()); - registry.fill(HIST("QAhisto/V0/hqadcanegtoPVafter"), v0.dcanegtopv()); + if (cfgOutputQA) { + registry.fill(HIST("QAhisto/V0/hqaV0radiusafter"), v0.v0radius()); + registry.fill(HIST("QAhisto/V0/hqaV0cosPAafter"), v0.v0cosPA()); + registry.fill(HIST("QAhisto/V0/hqadcaV0dauafter"), v0.dcaV0daughters()); + registry.fill(HIST("QAhisto/V0/hqadcapostoPVafter"), v0.dcapostopv()); + registry.fill(HIST("QAhisto/V0/hqadcanegtoPVafter"), v0.dcanegtopv()); + } if (isK0s) { if (cfgDoAccEffCorr) setCurrentParticleWeights(weff, wacc, v0, vtxz, 1); @@ -880,7 +1008,7 @@ struct FlowGfwOmegaXi { candNum[0] = candNum[0] + 1; registry.fill(HIST("InvMassK0s"), v0.pt(), v0.mK0Short(), v0.eta(), cent); registry.fill(HIST("hEtaPhiVtxzPOIK0s"), v0.phi(), v0.eta(), vtxz, wacc); - fGFW->Fill(v0.eta(), fV0PtAxis->FindBin(v0.pt()) - 1 + ((fK0sMass->FindBin(v0.mK0Short()) - 1) * nV0PtBins), v0.phi(), wacc * weff * wloc, 8); + fGFW->Fill(v0.eta(), fK0sPtAxis->FindBin(v0.pt()) - 1 + ((fK0sMass->FindBin(v0.mK0Short()) - 1) * nK0sPtBins), v0.phi(), wacc * weff * wloc, 8); if (cfgOutputNUAWeights) fWeightsK0s->fill(v0.phi(), v0.eta(), vtxz, v0.pt(), cent, 0); } @@ -898,97 +1026,129 @@ struct FlowGfwOmegaXi { candNum[1] = candNum[1] + 1; registry.fill(HIST("InvMassLambda"), v0.pt(), v0.mLambda(), v0.eta(), cent); registry.fill(HIST("hEtaPhiVtxzPOILambda"), v0.phi(), v0.eta(), vtxz, wacc); - fGFW->Fill(v0.eta(), fV0PtAxis->FindBin(v0.pt()) - 1 + ((fLambdaMass->FindBin(v0.mLambda()) - 1) * nV0PtBins), v0.phi(), wacc * weff * wloc, 16); + fGFW->Fill(v0.eta(), fK0sPtAxis->FindBin(v0.pt()) - 1 + ((fLambdaMass->FindBin(v0.mLambda()) - 1) * nK0sPtBins), v0.phi(), wacc * weff * wloc, 16); if (cfgOutputNUAWeights) fWeightsLambda->fill(v0.phi(), v0.eta(), vtxz, v0.pt(), cent, 0); } } + // fill GFW of casc flow for (const auto& casc : Cascades) { auto bachelor = casc.bachelor_as(); auto posdau = casc.posTrack_as(); auto negdau = casc.negTrack_as(); // check TPC - if (cfgcheckDauTPC && (!posdau.hasTPC() || !negdau.hasTPC() || !bachelor.hasTPC())) { - continue; - } bool isOmega = false; bool isXi = false; + + if (bachelor.pt() < trkQualityOpts.cfgCutPtDauMin.value || bachelor.pt() > trkQualityOpts.cfgCutPtDauMax.value) + continue; + if (posdau.pt() < trkQualityOpts.cfgCutPtDauMin.value || posdau.pt() > trkQualityOpts.cfgCutPtDauMax.value) + continue; + if (negdau.pt() < trkQualityOpts.cfgCutPtDauMin.value || negdau.pt() > trkQualityOpts.cfgCutPtDauMax.value) + continue; + // Omega and antiOmega - if (casc.sign() < 0 && std::fabs(casc.yOmega()) < cfgCasc_rapidity && - (!cfgcheckDauTPC || (std::fabs(bachelor.tpcNSigmaKa()) < cfgNSigma[2] && std::fabs(posdau.tpcNSigmaPr()) < cfgNSigma[1] && std::fabs(negdau.tpcNSigmaPi()) < cfgNSigma[0])) && - (!cfgcheckDauTOF || ((std::fabs(bachelor.tofNSigmaKa()) < cfgNSigma[5] || bachelor.pt() < lowpt) && (std::fabs(posdau.tofNSigmaPr()) < cfgNSigma[4] || posdau.pt() < lowpt) && (std::fabs(negdau.tofNSigmaPi()) < cfgNSigma[3] || negdau.pt() < lowpt)))) { - registry.fill(HIST("InvMassOmega_all"), casc.pt(), casc.mOmega(), casc.eta(), cent); - isOmega = true; - candNumAll[3] = candNumAll[3] + 1; - } else if (casc.sign() > 0 && std::fabs(casc.yOmega()) < cfgCasc_rapidity && - (!cfgcheckDauTPC || (std::fabs(bachelor.tpcNSigmaKa()) < cfgNSigma[2] && std::fabs(negdau.tpcNSigmaPr()) < cfgNSigma[1] && std::fabs(posdau.tpcNSigmaPi()) < cfgNSigma[0])) && - (!cfgcheckDauTOF || ((std::fabs(bachelor.tofNSigmaKa()) < cfgNSigma[5] || bachelor.pt() < lowpt) && (std::fabs(negdau.tofNSigmaPr()) < cfgNSigma[4] || negdau.pt() < lowpt) && (std::fabs(posdau.tofNSigmaPi()) < cfgNSigma[3] || posdau.pt() < lowpt)))) { - registry.fill(HIST("InvMassOmega_all"), casc.pt(), casc.mOmega(), casc.eta(), cent); - isOmega = true; - candNumAll[3] = candNumAll[3] + 1; + if (casc.pt() > trkQualityOpts.cfgCutPtOmegaMin.value && casc.pt() < trkQualityOpts.cfgCutPtOmegaMax.value) { + if (casc.sign() < 0 && std::fabs(casc.yOmega()) < cfgCasc_rapidity && + (std::fabs(bachelor.tpcNSigmaKa()) < cfgNSigma[2] && std::fabs(posdau.tpcNSigmaPr()) < cfgNSigma[1] && std::fabs(negdau.tpcNSigmaPi()) < cfgNSigma[0]) && + ((std::fabs(bachelor.tofNSigmaKa()) < cfgNSigma[5] || bachelor.pt() < lowpt) && (std::fabs(posdau.tofNSigmaPr()) < cfgNSigma[4] || posdau.pt() < lowpt) && (std::fabs(negdau.tofNSigmaPi()) < cfgNSigma[3] || negdau.pt() < lowpt)) && + ((std::fabs(itsResponse.nSigmaITS(bachelor)) < cfgNSigma[8]) || bachelor.pt() < lowpt) && ((std::fabs(itsResponse.nSigmaITS(posdau)) < cfgNSigma[7]) || posdau.pt() < lowpt) && ((std::fabs(itsResponse.nSigmaITS(negdau)) < cfgNSigma[6]) || negdau.pt() < lowpt)) { + registry.fill(HIST("InvMassOmega_all"), casc.pt(), casc.mOmega(), casc.eta(), cent); + isOmega = true; + candNumAll[3] = candNumAll[3] + 1; + } else if (casc.sign() > 0 && std::fabs(casc.yOmega()) < cfgCasc_rapidity && + (std::fabs(bachelor.tpcNSigmaKa()) < cfgNSigma[2] && std::fabs(negdau.tpcNSigmaPr()) < cfgNSigma[1] && std::fabs(posdau.tpcNSigmaPi()) < cfgNSigma[0]) && + ((std::fabs(bachelor.tofNSigmaKa()) < cfgNSigma[5] || bachelor.pt() < lowpt) && (std::fabs(negdau.tofNSigmaPr()) < cfgNSigma[4] || negdau.pt() < lowpt) && (std::fabs(posdau.tofNSigmaPi()) < cfgNSigma[3] || posdau.pt() < lowpt)) && + ((std::fabs(itsResponse.nSigmaITS(bachelor)) < cfgNSigma[8]) || bachelor.pt() < lowpt) && ((std::fabs(itsResponse.nSigmaITS(posdau)) < cfgNSigma[7]) || posdau.pt() < lowpt) && ((std::fabs(itsResponse.nSigmaITS(negdau)) < cfgNSigma[6]) || negdau.pt() < lowpt)) { + registry.fill(HIST("InvMassOmega_all"), casc.pt(), casc.mOmega(), casc.eta(), cent); + isOmega = true; + candNumAll[3] = candNumAll[3] + 1; + } } // Xi and antiXi - if (casc.sign() < 0 && std::fabs(casc.yXi()) < cfgCasc_rapidity && - (!cfgcheckDauTPC || (std::fabs(bachelor.tpcNSigmaPi()) < cfgNSigma[0] && std::fabs(posdau.tpcNSigmaPr()) < cfgNSigma[1] && std::fabs(negdau.tpcNSigmaPi()) < cfgNSigma[0])) && - (!cfgcheckDauTOF || ((std::fabs(bachelor.tofNSigmaPi()) < cfgNSigma[3] || bachelor.pt() < lowpt) && (std::fabs(posdau.tofNSigmaPr()) < cfgNSigma[4] || posdau.pt() < lowpt) && (std::fabs(negdau.tofNSigmaPi()) < cfgNSigma[3] || negdau.pt() < lowpt)))) { - registry.fill(HIST("InvMassXi_all"), casc.pt(), casc.mXi(), casc.eta(), cent); - isXi = true; - candNumAll[2] = candNumAll[2] + 1; - } else if (casc.sign() > 0 && std::fabs(casc.yXi()) < cfgCasc_rapidity && - (!cfgcheckDauTPC || (std::fabs(bachelor.tpcNSigmaPi()) < cfgNSigma[0] && std::fabs(negdau.tpcNSigmaPr()) < cfgNSigma[1] && std::fabs(posdau.tpcNSigmaPi()) < cfgNSigma[0])) && - (!cfgcheckDauTOF || ((std::fabs(bachelor.tofNSigmaPi()) < cfgNSigma[3] || bachelor.pt() < lowpt) && (std::fabs(negdau.tofNSigmaPr()) < cfgNSigma[4] || negdau.pt() < lowpt) && (std::fabs(posdau.tofNSigmaPi()) < cfgNSigma[3] || posdau.pt() < lowpt)))) { - registry.fill(HIST("InvMassXi_all"), casc.pt(), casc.mXi(), casc.eta(), cent); - isXi = true; - candNumAll[2] = candNumAll[2] + 1; + if (casc.pt() > trkQualityOpts.cfgCutPtXiMin.value && casc.pt() < trkQualityOpts.cfgCutPtXiMax.value) { + if (casc.sign() < 0 && std::fabs(casc.yXi()) < cfgCasc_rapidity && + (std::fabs(bachelor.tpcNSigmaPi()) < cfgNSigma[0] && std::fabs(posdau.tpcNSigmaPr()) < cfgNSigma[1] && std::fabs(negdau.tpcNSigmaPi()) < cfgNSigma[0]) && + ((std::fabs(bachelor.tofNSigmaPi()) < cfgNSigma[3] || bachelor.pt() < lowpt) && (std::fabs(posdau.tofNSigmaPr()) < cfgNSigma[4] || posdau.pt() < lowpt) && (std::fabs(negdau.tofNSigmaPi()) < cfgNSigma[3] || negdau.pt() < lowpt)) && + ((std::fabs(itsResponse.nSigmaITS(bachelor)) < cfgNSigma[6]) || bachelor.pt() < lowpt) && ((std::fabs(itsResponse.nSigmaITS(posdau)) < cfgNSigma[7]) || posdau.pt() < lowpt) && ((std::fabs(itsResponse.nSigmaITS(negdau)) < cfgNSigma[6]) || negdau.pt() < lowpt)) { + registry.fill(HIST("InvMassXi_all"), casc.pt(), casc.mXi(), casc.eta(), cent); + isXi = true; + candNumAll[2] = candNumAll[2] + 1; + } else if (casc.sign() > 0 && std::fabs(casc.yXi()) < cfgCasc_rapidity && + (std::fabs(bachelor.tpcNSigmaPi()) < cfgNSigma[0] && std::fabs(negdau.tpcNSigmaPr()) < cfgNSigma[1] && std::fabs(posdau.tpcNSigmaPi()) < cfgNSigma[0]) && + ((std::fabs(bachelor.tofNSigmaPi()) < cfgNSigma[3] || bachelor.pt() < lowpt) && (std::fabs(negdau.tofNSigmaPr()) < cfgNSigma[4] || negdau.pt() < lowpt) && (std::fabs(posdau.tofNSigmaPi()) < cfgNSigma[3] || posdau.pt() < lowpt)) && + ((std::fabs(itsResponse.nSigmaITS(bachelor)) < cfgNSigma[6]) || bachelor.pt() < lowpt) && ((std::fabs(itsResponse.nSigmaITS(posdau)) < cfgNSigma[7]) || posdau.pt() < lowpt) && ((std::fabs(itsResponse.nSigmaITS(negdau)) < cfgNSigma[6]) || negdau.pt() < lowpt)) { + registry.fill(HIST("InvMassXi_all"), casc.pt(), casc.mXi(), casc.eta(), cent); + isXi = true; + candNumAll[2] = candNumAll[2] + 1; + } } // fill QA - registry.fill(HIST("QAhisto/Casc/hqaCasccosPAbefore"), casc.casccosPA(collision.posX(), collision.posY(), collision.posZ())); - registry.fill(HIST("QAhisto/Casc/hqaCascV0cosPAbefore"), casc.v0cosPA(collision.posX(), collision.posY(), collision.posZ())); - registry.fill(HIST("QAhisto/Casc/hqadcaCascV0toPVbefore"), casc.dcav0topv(collision.posX(), collision.posY(), collision.posZ())); - registry.fill(HIST("QAhisto/Casc/hqadcaCascBachtoPVbefore"), casc.dcabachtopv()); - registry.fill(HIST("QAhisto/Casc/hqadcaCascdaubefore"), casc.dcacascdaughters()); - registry.fill(HIST("QAhisto/Casc/hqadcaCascV0daubefore"), casc.dcaV0daughters()); + if (cfgOutputQA) { + registry.fill(HIST("QAhisto/Casc/hqaCasccosPAbefore"), casc.casccosPA(collision.posX(), collision.posY(), collision.posZ())); + registry.fill(HIST("QAhisto/Casc/hqaCascV0cosPAbefore"), casc.v0cosPA(collision.posX(), collision.posY(), collision.posZ())); + registry.fill(HIST("QAhisto/Casc/hqadcaCascV0toPVbefore"), casc.dcav0topv(collision.posX(), collision.posY(), collision.posZ())); + registry.fill(HIST("QAhisto/Casc/hqadcaCascBachtoPVbefore"), casc.dcabachtopv()); + registry.fill(HIST("QAhisto/Casc/hqadcaCascdaubefore"), casc.dcacascdaughters()); + registry.fill(HIST("QAhisto/Casc/hqadcaCascV0daubefore"), casc.dcaV0daughters()); + } if (!isXi && !isOmega) continue; - // topological cut - if (casc.cascradius() < cfgcasc_radius) + // // topological cut + if (casc.cascradius() < cascBuilderOpts.cfgcasc_radius.value) continue; - if (casc.casccosPA(collision.posX(), collision.posY(), collision.posZ()) < cfgcasc_casccospa) + if (casc.casccosPA(collision.posX(), collision.posY(), collision.posZ()) < cascBuilderOpts.cfgcasc_casccospa.value) continue; - if (casc.v0cosPA(collision.posX(), collision.posY(), collision.posZ()) < cfgcasc_v0cospa) + if (casc.v0cosPA(collision.posX(), collision.posY(), collision.posZ()) < cascBuilderOpts.cfgcasc_v0cospa.value) continue; - if (std::fabs(casc.dcav0topv(collision.posX(), collision.posY(), collision.posZ())) < cfgcasc_dcav0topv) + if (std::fabs(casc.dcav0topv(collision.posX(), collision.posY(), collision.posZ())) < cascBuilderOpts.cfgcasc_dcav0topv.value) continue; - if (std::fabs(casc.dcabachtopv()) < cfgcasc_dcabachtopv) + if (std::fabs(casc.dcabachtopv()) < cascBuilderOpts.cfgcasc_dcabachtopv.value) continue; - if (casc.dcacascdaughters() > cfgcasc_dcacascdau) + if (casc.dcacascdaughters() > cascBuilderOpts.cfgcasc_dcacascdau.value) continue; - if (casc.dcaV0daughters() > cfgcasc_dcav0dau) + if (casc.dcaV0daughters() > cascBuilderOpts.cfgcasc_dcav0dau.value) continue; - if (std::fabs(casc.mLambda() - o2::constants::physics::MassLambda0) > cfgcasc_mlambdawindow) + if (std::fabs(casc.mLambda() - o2::constants::physics::MassLambda0) > cascBuilderOpts.cfgcasc_mlambdawindow.value) continue; - // track quality check - if (bachelor.tpcNClsFound() < cfgtpcclusters) + // // track quality check + if (!bachelor.passedITSNCls() && trkQualityOpts.cfgCheckITSNCls.value) continue; - if (posdau.tpcNClsFound() < cfgtpcclusters) + if (!posdau.passedITSNCls() && trkQualityOpts.cfgCheckITSNCls.value) continue; - if (negdau.tpcNClsFound() < cfgtpcclusters) + if (!negdau.passedITSNCls() && trkQualityOpts.cfgCheckITSNCls.value) continue; - if (bachelor.itsNCls() < cfgitsclusters) + if (!bachelor.passedITSHits() && trkQualityOpts.cfgCheckITSHits.value) continue; - if (posdau.itsNCls() < cfgitsclusters) + if (!posdau.passedITSHits() && trkQualityOpts.cfgCheckITSHits.value) continue; - if (negdau.itsNCls() < cfgitsclusters) + if (!negdau.passedITSHits() && trkQualityOpts.cfgCheckITSHits.value) continue; + if (!bachelor.passedITSChi2NDF() && trkQualityOpts.cfgCheckITSChi2NDF.value) + continue; + if (!posdau.passedITSChi2NDF() && trkQualityOpts.cfgCheckITSChi2NDF.value) + continue; + if (!negdau.passedITSChi2NDF() && trkQualityOpts.cfgCheckITSChi2NDF.value) + continue; + if (trkQualityOpts.cfgCheckGlobalTrack.value) { + if (!bachelor.hasTPC() || !bachelor.hasITS()) + continue; + if (!posdau.hasTPC() || !posdau.hasITS()) + continue; + if (!negdau.hasTPC() || !negdau.hasITS()) + continue; + } // fill QA - registry.fill(HIST("QAhisto/Casc/hqaCasccosPAafter"), casc.casccosPA(collision.posX(), collision.posY(), collision.posZ())); - registry.fill(HIST("QAhisto/Casc/hqaCascV0cosPAafter"), casc.v0cosPA(collision.posX(), collision.posY(), collision.posZ())); - registry.fill(HIST("QAhisto/Casc/hqadcaCascV0toPVafter"), casc.dcav0topv(collision.posX(), collision.posY(), collision.posZ())); - registry.fill(HIST("QAhisto/Casc/hqadcaCascBachtoPVafter"), casc.dcabachtopv()); - registry.fill(HIST("QAhisto/Casc/hqadcaCascdauafter"), casc.dcacascdaughters()); - registry.fill(HIST("QAhisto/Casc/hqadcaCascV0dauafter"), casc.dcaV0daughters()); + if (cfgOutputQA) { + registry.fill(HIST("QAhisto/Casc/hqaCasccosPAafter"), casc.casccosPA(collision.posX(), collision.posY(), collision.posZ())); + registry.fill(HIST("QAhisto/Casc/hqaCascV0cosPAafter"), casc.v0cosPA(collision.posX(), collision.posY(), collision.posZ())); + registry.fill(HIST("QAhisto/Casc/hqadcaCascV0toPVafter"), casc.dcav0topv(collision.posX(), collision.posY(), collision.posZ())); + registry.fill(HIST("QAhisto/Casc/hqadcaCascBachtoPVafter"), casc.dcabachtopv()); + registry.fill(HIST("QAhisto/Casc/hqadcaCascdauafter"), casc.dcacascdaughters()); + registry.fill(HIST("QAhisto/Casc/hqadcaCascV0dauafter"), casc.dcaV0daughters()); + } if (isOmega) { if (cfgDoAccEffCorr) @@ -1004,7 +1164,7 @@ struct FlowGfwOmegaXi { candNum[3] = candNum[3] + 1; registry.fill(HIST("hEtaPhiVtxzPOIOmega"), casc.phi(), casc.eta(), vtxz, wacc); registry.fill(HIST("InvMassOmega"), casc.pt(), casc.mOmega(), casc.eta(), cent); - fGFW->Fill(casc.eta(), fXiPtAxis->FindBin(casc.pt()) - 1 + ((fOmegaMass->FindBin(casc.mOmega()) - 1) * nXiPtBins), casc.phi(), wacc * weff * wloc, 4); + fGFW->Fill(casc.eta(), fOmegaPtAxis->FindBin(casc.pt()) - 1 + ((fOmegaMass->FindBin(casc.mOmega()) - 1) * nOmegaPtBins), casc.phi(), wacc * weff * wloc, 4); if (cfgOutputNUAWeights) fWeightsOmega->fill(casc.phi(), casc.eta(), vtxz, casc.pt(), cent, 0); } @@ -1039,26 +1199,39 @@ struct FlowGfwOmegaXi { // Filling cumulant with ROOT TProfile and loop for all ptBins fillProfile(corrconfigs.at(15), HIST("c22"), cent); fillProfile(corrconfigs.at(16), HIST("c24"), cent); + fillProfile(corrconfigs.at(25), HIST("c32"), cent); for (int i = 1; i <= nPtBins; i++) { fillProfilepT(corrconfigs.at(0), HIST("c22dpt"), i, cent); fillProfilepT(corrconfigs.at(1), HIST("c22dpt"), i, cent); fillProfilepT(corrconfigs.at(2), HIST("c24dpt"), i, cent); } - for (int i = 1; i <= nV0PtBins; i++) { + for (int i = 1; i <= nK0sPtBins; i++) { fillProfilepTMass(corrconfigs.at(9), HIST("K0sc22dpt"), i, kK0Short, cent); fillProfilepTMass(corrconfigs.at(10), HIST("K0sc22dpt"), i, kK0Short, cent); fillProfilepTMass(corrconfigs.at(11), HIST("K0sc24dpt"), i, kK0Short, cent); + fillProfilepTMass(corrconfigs.at(21), HIST("K0sc32dpt"), i, kK0Short, cent); + fillProfilepTMass(corrconfigs.at(22), HIST("K0sc32dpt"), i, kK0Short, cent); + } + for (int i = 1; i <= nLambdaPtBins; i++) { fillProfilepTMass(corrconfigs.at(12), HIST("Lambdac22dpt"), i, kLambda0, cent); fillProfilepTMass(corrconfigs.at(13), HIST("Lambdac22dpt"), i, kLambda0, cent); fillProfilepTMass(corrconfigs.at(14), HIST("Lambdac24dpt"), i, kLambda0, cent); + fillProfilepTMass(corrconfigs.at(23), HIST("Lambdac32dpt"), i, kLambda0, cent); + fillProfilepTMass(corrconfigs.at(24), HIST("Lambdac32dpt"), i, kLambda0, cent); } for (int i = 1; i <= nXiPtBins; i++) { fillProfilepTMass(corrconfigs.at(3), HIST("Xic22dpt"), i, kXiMinus, cent); fillProfilepTMass(corrconfigs.at(4), HIST("Xic22dpt"), i, kXiMinus, cent); fillProfilepTMass(corrconfigs.at(5), HIST("Xic24dpt"), i, kXiMinus, cent); + fillProfilepTMass(corrconfigs.at(17), HIST("Xic32dpt"), i, kXiMinus, cent); + fillProfilepTMass(corrconfigs.at(18), HIST("Xic32dpt"), i, kXiMinus, cent); + } + for (int i = 1; i <= nOmegaPtBins; i++) { fillProfilepTMass(corrconfigs.at(6), HIST("Omegac22dpt"), i, kOmegaMinus, cent); fillProfilepTMass(corrconfigs.at(7), HIST("Omegac22dpt"), i, kOmegaMinus, cent); fillProfilepTMass(corrconfigs.at(8), HIST("Omegac24dpt"), i, kOmegaMinus, cent); + fillProfilepTMass(corrconfigs.at(19), HIST("Omegac32dpt"), i, kOmegaMinus, cent); + fillProfilepTMass(corrconfigs.at(20), HIST("Omegac32dpt"), i, kOmegaMinus, cent); } // Fill subevents flow if (cfgDoJackknife) { @@ -1070,21 +1243,34 @@ struct FlowGfwOmegaXi { continue; fillProfile(corrconfigs.at(15), refc22[j - 1], cent); fillProfile(corrconfigs.at(16), refc24[j - 1], cent); - for (int i = 1; i <= nV0PtBins; i++) { + fillProfile(corrconfigs.at(25), refc32[j - 1], cent); + for (int i = 1; i <= nK0sPtBins; i++) { fillProfilepTMass(corrconfigs.at(9), k0sc22[j - 1], i, kK0Short, cent); fillProfilepTMass(corrconfigs.at(10), k0sc22[j - 1], i, kK0Short, cent); fillProfilepTMass(corrconfigs.at(11), k0sc24[j - 1], i, kK0Short, cent); + fillProfilepTMass(corrconfigs.at(21), k0sc32[j - 1], i, kK0Short, cent); + fillProfilepTMass(corrconfigs.at(22), k0sc32[j - 1], i, kK0Short, cent); + } + for (int i = 1; i <= nLambdaPtBins; i++) { fillProfilepTMass(corrconfigs.at(12), lambdac22[j - 1], i, kLambda0, cent); fillProfilepTMass(corrconfigs.at(13), lambdac22[j - 1], i, kLambda0, cent); fillProfilepTMass(corrconfigs.at(14), lambdac24[j - 1], i, kLambda0, cent); + fillProfilepTMass(corrconfigs.at(23), lambdac32[j - 1], i, kLambda0, cent); + fillProfilepTMass(corrconfigs.at(24), lambdac32[j - 1], i, kLambda0, cent); } for (int i = 1; i <= nXiPtBins; i++) { fillProfilepTMass(corrconfigs.at(3), xic22[j - 1], i, kXiMinus, cent); fillProfilepTMass(corrconfigs.at(4), xic22[j - 1], i, kXiMinus, cent); fillProfilepTMass(corrconfigs.at(5), xic24[j - 1], i, kXiMinus, cent); + fillProfilepTMass(corrconfigs.at(17), xic32[j - 1], i, kXiMinus, cent); + fillProfilepTMass(corrconfigs.at(18), xic32[j - 1], i, kXiMinus, cent); + } + for (int i = 1; i <= nOmegaPtBins; i++) { fillProfilepTMass(corrconfigs.at(6), omegac22[j - 1], i, kOmegaMinus, cent); fillProfilepTMass(corrconfigs.at(7), omegac22[j - 1], i, kOmegaMinus, cent); fillProfilepTMass(corrconfigs.at(8), omegac24[j - 1], i, kOmegaMinus, cent); + fillProfilepTMass(corrconfigs.at(19), omegac32[j - 1], i, kOmegaMinus, cent); + fillProfilepTMass(corrconfigs.at(20), omegac32[j - 1], i, kOmegaMinus, cent); } } } @@ -1114,10 +1300,7 @@ struct FlowGfwOmegaXi { if (mcParticle.has_tracks()) { auto const& tracks = mcParticle.tracks_as(); for (const auto& track : tracks) { - if (track.pt() < cfgCutPtPOIMin || track.pt() > cfgCutPtPOIMax) { - continue; - } - if (std::fabs(track.eta()) > cfgCutEta) { + if (std::fabs(track.eta()) > trkQualityOpts.cfgCutEta.value) { continue; } if (!(track.isGlobalTrack())) { @@ -1127,10 +1310,10 @@ struct FlowGfwOmegaXi { continue; } int ptbin = fPtAxis->FindBin(mcParticle.pt()) - 1; - if ((mcParticle.pt() > cfgCutPtMin) && (mcParticle.pt() < cfgCutPtMax)) { + if ((mcParticle.pt() > trkQualityOpts.cfgCutPtMin.value) && (mcParticle.pt() < trkQualityOpts.cfgCutPtMax.value)) { fGFW->Fill(mcParticle.eta(), ptbin, mcParticle.phi(), 1, 64); //(eta, ptbin, phi, wacc*weff, bitmask) } - if ((mcParticle.pt() > cfgCutPtPOIMin) && (mcParticle.pt() < cfgCutPtPOIMax)) { + if ((mcParticle.pt() > trkQualityOpts.cfgCutPtPOIMin.value) && (mcParticle.pt() < trkQualityOpts.cfgCutPtPOIMax.value)) { hLocalDensity->Fill(mcParticle.phi(), 1); hLocalDensity->Fill(RecoDecay::constrainAngle(mcParticle.phi(), -constants::math::TwoPI), 1); nch++; @@ -1146,7 +1329,7 @@ struct FlowGfwOmegaXi { int pdgCode = std::abs(straGen.pdgCode()); if (pdgCode != PDG_t::kXiMinus && pdgCode != PDG_t::kOmegaMinus && pdgCode != PDG_t::kK0Short && pdgCode != PDG_t::kLambda0) continue; - if (std::fabs(straGen.eta()) > cfgCutEta) + if (std::fabs(straGen.eta()) > trkQualityOpts.cfgCutEta.value) continue; if (pdgCode == PDG_t::kXiMinus) { @@ -1161,7 +1344,7 @@ struct FlowGfwOmegaXi { double density = hLocalDensity->Integral(phibin - cfgDeltaPhiLocDen, phibin + cfgDeltaPhiLocDen); if (cfgOutputLocDenWeights) registry.fill(HIST("MC/densityMCGenOmega"), straGen.pt(), nch, density); - fGFW->Fill(straGen.eta(), fXiPtAxis->FindBin(straGen.pt()) - 1, straGen.phi(), 1, 256); + fGFW->Fill(straGen.eta(), fOmegaPtAxis->FindBin(straGen.pt()) - 1, straGen.phi(), 1, 256); } if (pdgCode == PDG_t::kK0Short) { @@ -1169,28 +1352,32 @@ struct FlowGfwOmegaXi { double density = hLocalDensity->Integral(phibin - cfgDeltaPhiLocDen, phibin + cfgDeltaPhiLocDen); if (cfgOutputLocDenWeights) registry.fill(HIST("MC/densityMCGenK0s"), straGen.pt(), nch, density); - fGFW->Fill(straGen.eta(), fXiPtAxis->FindBin(straGen.pt()) - 1, straGen.phi(), 1, 512); + fGFW->Fill(straGen.eta(), fK0sPtAxis->FindBin(straGen.pt()) - 1, straGen.phi(), 1, 512); } if (pdgCode == PDG_t::kLambda0) { int phibin = hLocalDensity->FindBin(RecoDecay::constrainAngle(straGen.phi(), -constants::math::PI)); double density = hLocalDensity->Integral(phibin - cfgDeltaPhiLocDen, phibin + cfgDeltaPhiLocDen); if (cfgOutputLocDenWeights) registry.fill(HIST("MC/densityMCGenLambda"), straGen.pt(), nch, density); - fGFW->Fill(straGen.eta(), fXiPtAxis->FindBin(straGen.pt()) - 1, straGen.phi(), 1, 1024); + fGFW->Fill(straGen.eta(), fLambdaPtAxis->FindBin(straGen.pt()) - 1, straGen.phi(), 1, 1024); } } fillProfile(corrconfigs.at(25), HIST("MC/c22MC"), cent); - for (int i = 1; i <= nV0PtBins; i++) { - fillProfilepTMC(corrconfigs.at(21), HIST("MC/K0sc22dptMC"), i, kK0Short, cent); - fillProfilepTMC(corrconfigs.at(22), HIST("MC/K0sc22dptMC"), i, kK0Short, cent); - fillProfilepTMC(corrconfigs.at(23), HIST("MC/Lambdac22dptMC"), i, kLambda0, cent); - fillProfilepTMC(corrconfigs.at(24), HIST("MC/Lambdac22dptMC"), i, kLambda0, cent); + for (int i = 1; i <= nK0sPtBins; i++) { + fillProfilepTMC(corrconfigs.at(30), HIST("MC/K0sc22dptMC"), i, kK0Short, cent); + fillProfilepTMC(corrconfigs.at(31), HIST("MC/K0sc22dptMC"), i, kK0Short, cent); + } + for (int i = 1; i <= nLambdaPtBins; i++) { + fillProfilepTMC(corrconfigs.at(32), HIST("MC/Lambdac22dptMC"), i, kLambda0, cent); + fillProfilepTMC(corrconfigs.at(33), HIST("MC/Lambdac22dptMC"), i, kLambda0, cent); } for (int i = 1; i <= nXiPtBins; i++) { - fillProfilepTMC(corrconfigs.at(17), HIST("MC/Xic22dptMC"), i, kXiMinus, cent); - fillProfilepTMC(corrconfigs.at(18), HIST("MC/Xic22dptMC"), i, kXiMinus, cent); - fillProfilepTMC(corrconfigs.at(19), HIST("MC/Omegac22dptMC"), i, kOmegaMinus, cent); - fillProfilepTMC(corrconfigs.at(20), HIST("MC/Omegac22dptMC"), i, kOmegaMinus, cent); + fillProfilepTMC(corrconfigs.at(26), HIST("MC/Xic22dptMC"), i, kXiMinus, cent); + fillProfilepTMC(corrconfigs.at(27), HIST("MC/Xic22dptMC"), i, kXiMinus, cent); + } + for (int i = 1; i <= nOmegaPtBins; i++) { + fillProfilepTMC(corrconfigs.at(28), HIST("MC/Omegac22dptMC"), i, kOmegaMinus, cent); + fillProfilepTMC(corrconfigs.at(29), HIST("MC/Omegac22dptMC"), i, kOmegaMinus, cent); } delete hLocalDensity; @@ -1218,36 +1405,36 @@ struct FlowGfwOmegaXi { double nch = 0; for (const auto& track : tracks) { - if (!track.has_mcParticle()) + if (track.pt() < trkQualityOpts.cfgCutPtPOIMin.value || track.pt() > trkQualityOpts.cfgCutPtPOIMax.value) continue; - if (track.pt() < cfgCutPtPOIMin || track.pt() > cfgCutPtPOIMax) - continue; - if (std::fabs(track.eta()) > cfgCutEta) + if (std::fabs(track.eta()) > trkQualityOpts.cfgCutEta.value) continue; if (!(track.isGlobalTrack())) continue; if (track.tpcChi2NCl() > cfgCutChi2prTPCcls) continue; - auto mcParticle = track.mcParticle_as(); if (cfgDoAccEffCorr) { if (!setCurrentParticleWeights(weff, wacc, track, vtxz, 0)) continue; } + nch += wacc * weff; + if (!track.has_mcParticle()) + continue; + auto mcParticle = track.mcParticle_as(); registry.fill(HIST("hPhi"), track.phi()); registry.fill(HIST("hPhicorr"), track.phi(), wacc); registry.fill(HIST("hEta"), track.eta()); registry.fill(HIST("hEtaPhiVtxzREF"), track.phi(), track.eta(), vtxz, wacc); registry.fill(HIST("hPt"), track.pt()); int ptbin = fPtAxis->FindBin(track.pt()) - 1; - if ((track.pt() > cfgCutPtMin) && (track.pt() < cfgCutPtMax)) { + if ((track.pt() > trkQualityOpts.cfgCutPtMin.value) && (track.pt() < trkQualityOpts.cfgCutPtMax.value)) { fGFW->Fill(track.eta(), ptbin, track.phi(), wacc * weff, 1); //(eta, ptbin, phi, wacc*weff, bitmask) } - if ((track.pt() > cfgCutPtPOIMin) && (track.pt() < cfgCutPtPOIMax)) { + if ((track.pt() > trkQualityOpts.cfgCutPtPOIMin.value) && (track.pt() < trkQualityOpts.cfgCutPtPOIMax.value)) { fGFW->Fill(track.eta(), ptbin, track.phi(), wacc * weff, 32); if (cfgDoLocDenCorr) { hLocalDensity->Fill(mcParticle.phi(), wacc * weff); hLocalDensity->Fill(RecoDecay::constrainAngle(mcParticle.phi(), -constants::math::TwoPI), wacc * weff); - nch += wacc * weff; } } } @@ -1263,50 +1450,74 @@ struct FlowGfwOmegaXi { auto negdau = casc.negTrack_as(); auto posdau = casc.posTrack_as(); auto bachelor = casc.bachelor_as(); + if (bachelor.pt() < trkQualityOpts.cfgCutPtDauMin.value || bachelor.pt() > trkQualityOpts.cfgCutPtDauMax.value) + continue; + if (posdau.pt() < trkQualityOpts.cfgCutPtDauMin.value || posdau.pt() > trkQualityOpts.cfgCutPtDauMax.value) + continue; + if (negdau.pt() < trkQualityOpts.cfgCutPtDauMin.value || negdau.pt() > trkQualityOpts.cfgCutPtDauMax.value) + continue; // fill QA - registry.fill(HIST("QAhisto/Casc/hqaCasccosPAbefore"), casc.casccosPA(collision.posX(), collision.posY(), collision.posZ())); - registry.fill(HIST("QAhisto/Casc/hqaCascV0cosPAbefore"), casc.v0cosPA(collision.posX(), collision.posY(), collision.posZ())); - registry.fill(HIST("QAhisto/Casc/hqadcaCascV0toPVbefore"), casc.dcav0topv(collision.posX(), collision.posY(), collision.posZ())); - registry.fill(HIST("QAhisto/Casc/hqadcaCascBachtoPVbefore"), casc.dcabachtopv()); - registry.fill(HIST("QAhisto/Casc/hqadcaCascdaubefore"), casc.dcacascdaughters()); - registry.fill(HIST("QAhisto/Casc/hqadcaCascV0daubefore"), casc.dcaV0daughters()); + if (cfgOutputQA) { + registry.fill(HIST("QAhisto/Casc/hqaCasccosPAbefore"), casc.casccosPA(collision.posX(), collision.posY(), collision.posZ())); + registry.fill(HIST("QAhisto/Casc/hqaCascV0cosPAbefore"), casc.v0cosPA(collision.posX(), collision.posY(), collision.posZ())); + registry.fill(HIST("QAhisto/Casc/hqadcaCascV0toPVbefore"), casc.dcav0topv(collision.posX(), collision.posY(), collision.posZ())); + registry.fill(HIST("QAhisto/Casc/hqadcaCascBachtoPVbefore"), casc.dcabachtopv()); + registry.fill(HIST("QAhisto/Casc/hqadcaCascdaubefore"), casc.dcacascdaughters()); + registry.fill(HIST("QAhisto/Casc/hqadcaCascV0daubefore"), casc.dcaV0daughters()); + } // track quality check - if (bachelor.tpcNClsFound() < cfgtpcclusters) + if (!bachelor.passedITSNCls() && trkQualityOpts.cfgCheckITSNCls.value) continue; - if (posdau.tpcNClsFound() < cfgtpcclusters) + if (!posdau.passedITSNCls() && trkQualityOpts.cfgCheckITSNCls.value) continue; - if (negdau.tpcNClsFound() < cfgtpcclusters) + if (!negdau.passedITSNCls() && trkQualityOpts.cfgCheckITSNCls.value) continue; - if (bachelor.itsNCls() < cfgitsclusters) + if (!bachelor.passedITSHits() && trkQualityOpts.cfgCheckITSHits.value) continue; - if (posdau.itsNCls() < cfgitsclusters) + if (!posdau.passedITSHits() && trkQualityOpts.cfgCheckITSHits.value) continue; - if (negdau.itsNCls() < cfgitsclusters) + if (!negdau.passedITSHits() && trkQualityOpts.cfgCheckITSHits.value) continue; - // topological cut - if (casc.cascradius() < cfgcasc_radius) + if (!bachelor.passedITSChi2NDF() && trkQualityOpts.cfgCheckITSChi2NDF.value) continue; - if (casc.casccosPA(collision.posX(), collision.posY(), collision.posZ()) < cfgcasc_casccospa) + if (!posdau.passedITSChi2NDF() && trkQualityOpts.cfgCheckITSChi2NDF.value) continue; - if (casc.v0cosPA(collision.posX(), collision.posY(), collision.posZ()) < cfgcasc_v0cospa) + if (!negdau.passedITSChi2NDF() && trkQualityOpts.cfgCheckITSChi2NDF.value) continue; - if (std::fabs(casc.dcav0topv(collision.posX(), collision.posY(), collision.posZ())) < cfgcasc_dcav0topv) + if (trkQualityOpts.cfgCheckGlobalTrack.value) { + if (!bachelor.hasTPC() || !bachelor.hasITS()) + continue; + if (!posdau.hasTPC() || !posdau.hasITS()) + continue; + if (!negdau.hasTPC() || !negdau.hasITS()) + continue; + } + // // topological cut + if (casc.cascradius() < cascBuilderOpts.cfgcasc_radius.value) + continue; + if (casc.casccosPA(collision.posX(), collision.posY(), collision.posZ()) < cascBuilderOpts.cfgcasc_casccospa.value) + continue; + if (casc.v0cosPA(collision.posX(), collision.posY(), collision.posZ()) < cascBuilderOpts.cfgcasc_v0cospa.value) continue; - if (std::fabs(casc.dcabachtopv()) < cfgcasc_dcabachtopv) + if (std::fabs(casc.dcav0topv(collision.posX(), collision.posY(), collision.posZ())) < cascBuilderOpts.cfgcasc_dcav0topv.value) continue; - if (casc.dcacascdaughters() > cfgcasc_dcacascdau) + if (std::fabs(casc.dcabachtopv()) < cascBuilderOpts.cfgcasc_dcabachtopv.value) continue; - if (casc.dcaV0daughters() > cfgcasc_dcav0dau) + if (casc.dcacascdaughters() > cascBuilderOpts.cfgcasc_dcacascdau.value) continue; - if (std::fabs(casc.mLambda() - o2::constants::physics::MassLambda0) > cfgcasc_mlambdawindow) + if (casc.dcaV0daughters() > cascBuilderOpts.cfgcasc_dcav0dau.value) + continue; + if (std::fabs(casc.mLambda() - o2::constants::physics::MassLambda0) > cascBuilderOpts.cfgcasc_mlambdawindow.value) continue; // fill QA - registry.fill(HIST("QAhisto/Casc/hqaCasccosPAafter"), casc.casccosPA(collision.posX(), collision.posY(), collision.posZ())); - registry.fill(HIST("QAhisto/Casc/hqaCascV0cosPAafter"), casc.v0cosPA(collision.posX(), collision.posY(), collision.posZ())); - registry.fill(HIST("QAhisto/Casc/hqadcaCascV0toPVafter"), casc.dcav0topv(collision.posX(), collision.posY(), collision.posZ())); - registry.fill(HIST("QAhisto/Casc/hqadcaCascBachtoPVafter"), casc.dcabachtopv()); - registry.fill(HIST("QAhisto/Casc/hqadcaCascdauafter"), casc.dcacascdaughters()); - registry.fill(HIST("QAhisto/Casc/hqadcaCascV0dauafter"), casc.dcaV0daughters()); + if (cfgOutputQA) { + registry.fill(HIST("QAhisto/Casc/hqaCasccosPAafter"), casc.casccosPA(collision.posX(), collision.posY(), collision.posZ())); + registry.fill(HIST("QAhisto/Casc/hqaCascV0cosPAafter"), casc.v0cosPA(collision.posX(), collision.posY(), collision.posZ())); + registry.fill(HIST("QAhisto/Casc/hqadcaCascV0toPVafter"), casc.dcav0topv(collision.posX(), collision.posY(), collision.posZ())); + registry.fill(HIST("QAhisto/Casc/hqadcaCascBachtoPVafter"), casc.dcabachtopv()); + registry.fill(HIST("QAhisto/Casc/hqadcaCascdauafter"), casc.dcacascdaughters()); + registry.fill(HIST("QAhisto/Casc/hqadcaCascV0dauafter"), casc.dcaV0daughters()); + } // Omega and antiOmega int pdgCode{cascMC.pdgCode()}; double cascPt{cascMC.pt()}; @@ -1314,7 +1525,7 @@ struct FlowGfwOmegaXi { double cascEta{cascMC.eta()}; if (std::abs(pdgCode) == kOmegaMinus) { if (casc.sign() < 0 && std::fabs(casc.yOmega()) < cfgCasc_rapidity && - (!cfgcheckDauTPC || (std::fabs(bachelor.tpcNSigmaKa()) < cfgNSigma[2] && std::fabs(posdau.tpcNSigmaPr()) < cfgNSigma[1] && std::fabs(negdau.tpcNSigmaPi()) < cfgNSigma[0]))) { + (std::fabs(bachelor.tpcNSigmaKa()) < cfgNSigma[2] && std::fabs(posdau.tpcNSigmaPr()) < cfgNSigma[1] && std::fabs(negdau.tpcNSigmaPi()) < cfgNSigma[0])) { if (cfgDoAccEffCorr) setCurrentParticleWeights(weff, wacc, casc, vtxz, 4); if (cfgDoLocDenCorr) { @@ -1325,9 +1536,9 @@ struct FlowGfwOmegaXi { if (cfgOutputLocDenWeights) registry.fill(HIST("MC/densityMCRecOmega"), cascPt, nch, density, casc.mOmega()); } - fGFW->Fill(cascEta, fXiPtAxis->FindBin(cascPt) - 1, cascPhi, wacc * weff * wloc, 4); + fGFW->Fill(cascEta, fOmegaPtAxis->FindBin(cascPt) - 1, cascPhi, wacc * weff * wloc, 4); } else if (casc.sign() > 0 && std::fabs(casc.yOmega()) < cfgCasc_rapidity && - (!cfgcheckDauTPC || (std::fabs(bachelor.tpcNSigmaKa()) < cfgNSigma[2] && std::fabs(negdau.tpcNSigmaPr()) < cfgNSigma[1] && std::fabs(posdau.tpcNSigmaPi()) < cfgNSigma[0]))) { + (std::fabs(bachelor.tpcNSigmaKa()) < cfgNSigma[2] && std::fabs(negdau.tpcNSigmaPr()) < cfgNSigma[1] && std::fabs(posdau.tpcNSigmaPi()) < cfgNSigma[0])) { if (cfgDoAccEffCorr) setCurrentParticleWeights(weff, wacc, casc, vtxz, 4); if (cfgDoLocDenCorr) { @@ -1338,13 +1549,13 @@ struct FlowGfwOmegaXi { if (cfgOutputLocDenWeights) registry.fill(HIST("MC/densityMCRecOmega"), cascPt, nch, density, casc.mOmega()); } - fGFW->Fill(cascEta, fXiPtAxis->FindBin(cascPt) - 1, cascPhi, wacc * weff * wloc, 4); + fGFW->Fill(cascEta, fOmegaPtAxis->FindBin(cascPt) - 1, cascPhi, wacc * weff * wloc, 4); } } // Xi and antiXi if (std::abs(pdgCode) == kXiMinus) { if (casc.sign() < 0 && std::fabs(casc.yXi()) < cfgCasc_rapidity && - (!cfgcheckDauTPC || (std::fabs(bachelor.tpcNSigmaPi()) < cfgNSigma[0] && std::fabs(posdau.tpcNSigmaPr()) < cfgNSigma[1] && std::fabs(negdau.tpcNSigmaPi()) < cfgNSigma[0]))) { + (std::fabs(bachelor.tpcNSigmaPi()) < cfgNSigma[0] && std::fabs(posdau.tpcNSigmaPr()) < cfgNSigma[1] && std::fabs(negdau.tpcNSigmaPi()) < cfgNSigma[0])) { if (cfgDoAccEffCorr) setCurrentParticleWeights(weff, wacc, casc, vtxz, 3); if (cfgDoLocDenCorr) { @@ -1357,7 +1568,7 @@ struct FlowGfwOmegaXi { } fGFW->Fill(cascEta, fXiPtAxis->FindBin(cascPt) - 1, cascPhi, wacc * weff * wloc, 2); } else if (casc.sign() > 0 && std::fabs(casc.yXi()) < cfgCasc_rapidity && - (!cfgcheckDauTPC || (std::fabs(bachelor.tpcNSigmaPi()) < cfgNSigma[0] && std::fabs(negdau.tpcNSigmaPr()) < cfgNSigma[1] && std::fabs(posdau.tpcNSigmaPi()) < cfgNSigma[0]))) { + (std::fabs(bachelor.tpcNSigmaPi()) < cfgNSigma[0] && std::fabs(negdau.tpcNSigmaPr()) < cfgNSigma[1] && std::fabs(posdau.tpcNSigmaPi()) < cfgNSigma[0])) { if (cfgDoAccEffCorr) setCurrentParticleWeights(weff, wacc, casc, vtxz, 3); if (cfgDoLocDenCorr) { @@ -1380,45 +1591,58 @@ struct FlowGfwOmegaXi { auto v0negdau = v0.negTrack_as(); auto v0posdau = v0.posTrack_as(); - // fill QA before cut - registry.fill(HIST("QAhisto/V0/hqaV0radiusbefore"), v0.v0radius()); - registry.fill(HIST("QAhisto/V0/hqaV0cosPAbefore"), v0.v0cosPA()); - registry.fill(HIST("QAhisto/V0/hqadcaV0daubefore"), v0.dcaV0daughters()); - registry.fill(HIST("QAhisto/V0/hqadcapostoPVbefore"), v0.dcapostopv()); - registry.fill(HIST("QAhisto/V0/hqadcanegtoPVbefore"), v0.dcanegtopv()); - registry.fill(HIST("QAhisto/V0/hqaarm_podobefore"), v0.alpha(), v0.qtarm()); - // track quality check - if (v0posdau.tpcNClsFound() < cfgtpcclusters) + if (v0posdau.pt() < trkQualityOpts.cfgCutPtDauMin.value || v0posdau.pt() > trkQualityOpts.cfgCutPtDauMax.value) continue; - if (v0negdau.tpcNClsFound() < cfgtpcclusters) + if (v0negdau.pt() < trkQualityOpts.cfgCutPtDauMin.value || v0negdau.pt() > trkQualityOpts.cfgCutPtDauMax.value) continue; - if (v0posdau.tpcNClsFindable() < cfgtpcclufindable) + + // fill QA before cut + if (cfgOutputQA) { + registry.fill(HIST("QAhisto/V0/hqaV0radiusbefore"), v0.v0radius()); + registry.fill(HIST("QAhisto/V0/hqaV0cosPAbefore"), v0.v0cosPA()); + registry.fill(HIST("QAhisto/V0/hqadcaV0daubefore"), v0.dcaV0daughters()); + registry.fill(HIST("QAhisto/V0/hqadcapostoPVbefore"), v0.dcapostopv()); + registry.fill(HIST("QAhisto/V0/hqadcanegtoPVbefore"), v0.dcanegtopv()); + registry.fill(HIST("QAhisto/V0/hqaarm_podobefore"), v0.alpha(), v0.qtarm()); + } + // // track quality check + if (!v0posdau.passedITSNCls() && trkQualityOpts.cfgCheckITSNCls.value) + continue; + if (!v0negdau.passedITSNCls() && trkQualityOpts.cfgCheckITSNCls.value) continue; - if (v0negdau.tpcNClsFindable() < cfgtpcclufindable) + if (!v0posdau.passedITSHits() && trkQualityOpts.cfgCheckITSHits.value) continue; - if (v0posdau.tpcCrossedRowsOverFindableCls() < cfgtpccrossoverfindable) + if (!v0negdau.passedITSHits() && trkQualityOpts.cfgCheckITSHits.value) continue; - if (v0posdau.itsNCls() < cfgitsclusters) + if (!v0posdau.passedITSChi2NDF() && trkQualityOpts.cfgCheckITSChi2NDF.value) continue; - if (v0negdau.itsNCls() < cfgitsclusters) + if (!v0negdau.passedITSChi2NDF() && trkQualityOpts.cfgCheckITSChi2NDF.value) continue; + if (trkQualityOpts.cfgCheckGlobalTrack.value) { + if (!v0posdau.hasTPC() || !v0posdau.hasITS()) + continue; + if (!v0negdau.hasTPC() || !v0negdau.hasITS()) + continue; + } // topological cut - if (v0.v0radius() < cfgv0_radius) + if (v0.v0radius() < v0BuilderOpts.cfgv0_radius.value) continue; - if (v0.v0cosPA() < cfgv0_v0cospa) + if (v0.v0cosPA() < v0BuilderOpts.cfgv0_v0cospa.value) continue; - if (v0.dcaV0daughters() > cfgv0_dcav0dau) + if (v0.dcaV0daughters() > v0BuilderOpts.cfgv0_dcav0dau.value) continue; - if (std::fabs(v0.dcapostopv()) < cfgv0_dcadautopv) + if (std::fabs(v0.dcapostopv()) < v0BuilderOpts.cfgv0_dcadautopv.value) continue; - if (std::fabs(v0.dcanegtopv()) < cfgv0_dcadautopv) + if (std::fabs(v0.dcanegtopv()) < v0BuilderOpts.cfgv0_dcadautopv.value) continue; // fill QA after cut - registry.fill(HIST("QAhisto/V0/hqaV0radiusafter"), v0.v0radius()); - registry.fill(HIST("QAhisto/V0/hqaV0cosPAafter"), v0.v0cosPA()); - registry.fill(HIST("QAhisto/V0/hqadcaV0dauafter"), v0.dcaV0daughters()); - registry.fill(HIST("QAhisto/V0/hqadcapostoPVafter"), v0.dcapostopv()); - registry.fill(HIST("QAhisto/V0/hqadcanegtoPVafter"), v0.dcanegtopv()); + if (cfgOutputQA) { + registry.fill(HIST("QAhisto/V0/hqaV0radiusafter"), v0.v0radius()); + registry.fill(HIST("QAhisto/V0/hqaV0cosPAafter"), v0.v0cosPA()); + registry.fill(HIST("QAhisto/V0/hqadcaV0dauafter"), v0.dcaV0daughters()); + registry.fill(HIST("QAhisto/V0/hqadcapostoPVafter"), v0.dcapostopv()); + registry.fill(HIST("QAhisto/V0/hqadcanegtoPVafter"), v0.dcanegtopv()); + } int pdgCode{v0MC.pdgCode()}; double v0Pt{v0MC.pt()}; @@ -1426,8 +1650,9 @@ struct FlowGfwOmegaXi { double v0Eta{v0MC.eta()}; // K0short if (std::abs(pdgCode) == kK0Short) { - if (v0.qtarm() / std::fabs(v0.alpha()) > cfgv0_ArmPodocut && std::fabs(v0.mK0Short() - o2::constants::physics::MassK0Short) < cfgv0_mk0swindow && - (!cfgcheckDauTPC || (std::fabs(v0posdau.tpcNSigmaPi()) < cfgNSigma[0] && std::fabs(v0negdau.tpcNSigmaPi()) < cfgNSigma[0]))) { + 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); if (cfgDoLocDenCorr) { @@ -1438,12 +1663,12 @@ struct FlowGfwOmegaXi { if (cfgOutputLocDenWeights) registry.fill(HIST("MC/densityMCRecK0s"), v0Pt, nch, density, v0.mK0Short()); } - fGFW->Fill(v0Eta, fV0PtAxis->FindBin(v0Pt) - 1, v0Phi, wacc * weff * wloc, 8); + fGFW->Fill(v0Eta, fK0sPtAxis->FindBin(v0Pt) - 1, v0Phi, wacc * weff * wloc, 8); } } // Lambda and antiLambda - if (std::fabs(v0.mLambda() - o2::constants::physics::MassLambda) < cfgv0_mlambdawindow && - (!cfgcheckDauTPC || (std::fabs(v0posdau.tpcNSigmaPr()) < cfgNSigma[1] && std::fabs(v0negdau.tpcNSigmaPi()) < cfgNSigma[0]))) { + 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::abs(pdgCode) == kLambda0) { if (cfgDoAccEffCorr) setCurrentParticleWeights(weff, wacc, v0, vtxz, 2); @@ -1455,10 +1680,10 @@ struct FlowGfwOmegaXi { if (cfgOutputLocDenWeights) registry.fill(HIST("MC/densityMCRecLambda"), v0Pt, nch, density, v0.mLambda()); } - fGFW->Fill(v0Eta, fV0PtAxis->FindBin(v0Pt) - 1, v0Phi, wacc * weff * wloc, 16); + fGFW->Fill(v0Eta, fLambdaPtAxis->FindBin(v0Pt) - 1, v0Phi, wacc * weff * wloc, 16); } - } else if (std::fabs(v0.mLambda() - o2::constants::physics::MassLambda) < cfgv0_mlambdawindow && - (!cfgcheckDauTPC || (std::fabs(v0negdau.tpcNSigmaPr()) < cfgNSigma[1] && std::fabs(v0posdau.tpcNSigmaPi()) < cfgNSigma[0]))) { + } 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])) { if (std::abs(pdgCode) == kLambda0) { if (cfgDoAccEffCorr) setCurrentParticleWeights(weff, wacc, v0, vtxz, 2); @@ -1470,23 +1695,36 @@ struct FlowGfwOmegaXi { if (cfgOutputLocDenWeights) registry.fill(HIST("MC/densityMCRecLambda"), v0Pt, nch, density, v0.mLambda()); } - fGFW->Fill(v0Eta, fV0PtAxis->FindBin(v0Pt) - 1, v0Phi, wacc * weff * wloc, 16); + fGFW->Fill(v0Eta, fLambdaPtAxis->FindBin(v0Pt) - 1, v0Phi, wacc * weff * wloc, 16); } } } delete hLocalDensity; fillProfile(corrconfigs.at(15), HIST("c22"), cent); - for (int i = 1; i <= nV0PtBins; i++) { + fillProfile(corrconfigs.at(25), HIST("c32"), cent); + for (int i = 1; i <= nK0sPtBins; i++) { fillProfilepTMass(corrconfigs.at(9), HIST("K0sc22dpt"), i, kK0Short, cent); fillProfilepTMass(corrconfigs.at(10), HIST("K0sc22dpt"), i, kK0Short, cent); + fillProfilepTMass(corrconfigs.at(21), HIST("K0sc32dpt"), i, kK0Short, cent); + fillProfilepTMass(corrconfigs.at(22), HIST("K0sc32dpt"), i, kK0Short, cent); + } + for (int i = 1; i <= nLambdaPtBins; i++) { fillProfilepTMass(corrconfigs.at(12), HIST("Lambdac22dpt"), i, kLambda0, cent); fillProfilepTMass(corrconfigs.at(13), HIST("Lambdac22dpt"), i, kLambda0, cent); + fillProfilepTMass(corrconfigs.at(23), HIST("Lambdac32dpt"), i, kLambda0, cent); + fillProfilepTMass(corrconfigs.at(24), HIST("Lambdac32dpt"), i, kLambda0, cent); } for (int i = 1; i <= nXiPtBins; i++) { fillProfilepTMass(corrconfigs.at(3), HIST("Xic22dpt"), i, kXiMinus, cent); fillProfilepTMass(corrconfigs.at(4), HIST("Xic22dpt"), i, kXiMinus, cent); + fillProfilepTMass(corrconfigs.at(17), HIST("Xic32dpt"), i, kXiMinus, cent); + fillProfilepTMass(corrconfigs.at(18), HIST("Xic32dpt"), i, kXiMinus, cent); + } + for (int i = 1; i <= nOmegaPtBins; i++) { fillProfilepTMass(corrconfigs.at(6), HIST("Omegac22dpt"), i, kOmegaMinus, cent); fillProfilepTMass(corrconfigs.at(7), HIST("Omegac22dpt"), i, kOmegaMinus, cent); + fillProfilepTMass(corrconfigs.at(19), HIST("Omegac32dpt"), i, kOmegaMinus, cent); + fillProfilepTMass(corrconfigs.at(20), HIST("Omegac32dpt"), i, kOmegaMinus, cent); } } PROCESS_SWITCH(FlowGfwOmegaXi, processMCRec, "", true); From fb0827bb8ab57e345d7532f3632ce5ef1f76b203 Mon Sep 17 00:00:00 2001 From: sawan <124118453+sawankumawat@users.noreply.github.com> Date: Sat, 14 Jun 2025 13:14:37 +0530 Subject: [PATCH 073/871] [PWGLF] Added azimuthal angle phi distribution (#11566) Co-authored-by: Sawan Sawan --- .../Tasks/Resonances/higherMassResonances.cxx | 191 +++++++++++------- 1 file changed, 119 insertions(+), 72 deletions(-) diff --git a/PWGLF/Tasks/Resonances/higherMassResonances.cxx b/PWGLF/Tasks/Resonances/higherMassResonances.cxx index 252fdd6d658..fad39aaf963 100644 --- a/PWGLF/Tasks/Resonances/higherMassResonances.cxx +++ b/PWGLF/Tasks/Resonances/higherMassResonances.cxx @@ -14,6 +14,29 @@ /// \author Sawan // #include +#include "PWGLF/DataModel/LFStrangenessTables.h" // + +#include "Common/Core/TrackSelection.h" +#include "Common/Core/trackUtilities.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" // +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/PIDResponse.h" // +#include "Common/DataModel/TrackSelectionTables.h" + +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" // +#include "Framework/O2DatabasePDGPlugin.h" +#include "Framework/StepTHn.h" +#include "Framework/runDataProcessing.h" // +#include "ReconstructionDataFormats/Track.h" + +#include "Math/GenVector/Boost.h" +#include "Math/Vector3D.h" +#include "Math/Vector4D.h" +#include "TF1.h" +#include "TRandom3.h" #include #include #include @@ -23,33 +46,12 @@ #include #include #include + +#include #include #include #include #include -#include -#include "TF1.h" -#include "TRandom3.h" -#include "Math/Vector3D.h" -#include "Math/Vector4D.h" -#include "Math/GenVector/Boost.h" - -#include "Common/Core/TrackSelection.h" -#include "Common/Core/trackUtilities.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/StepTHn.h" -#include "ReconstructionDataFormats/Track.h" -#include "Framework/O2DatabasePDGPlugin.h" - -#include "Common/DataModel/Centrality.h" -#include "Common/DataModel/EventSelection.h" // -#include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/PIDResponse.h" // -#include "Common/DataModel/TrackSelectionTables.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisTask.h" // -#include "Framework/runDataProcessing.h" // -#include "PWGLF/DataModel/LFStrangenessTables.h" // using namespace o2; using namespace o2::framework; @@ -74,7 +76,7 @@ struct HigherMassResonances { // Configurable invMass1D{"invMass1D", false, "1D invariant mass histograms"}; Configurable correlation2Dhist{"correlation2Dhist", true, "Lamda K0 mass correlation"}; Configurable cDCAv0topv{"cDCAv0topv", false, "DCA V0 to PV"}; - Configurable armcut{"armcut", false, "arm cut"}; + // Configurable armcut{"armcut", false, "arm cut"}; Configurable globalTracks{"globalTracks", false, "Global tracks"}; Configurable hasTPC{"hasTPC", false, "TPC"}; Configurable selectTWOKsOnly{"selectTWOKsOnly", true, "Select only events with two K0s"}; @@ -82,11 +84,11 @@ struct HigherMassResonances { // Configurables for event selection Configurable cutzvertex{"cutzvertex", 10.0f, "Accepted z-vertex range (cm)"}; Configurable cfgETAcut{"cfgETAcut", 0.8f, "Track ETA cut"}; - Configurable timFrameEvsel{"timFrameEvsel", false, "TPC Time frame boundary cut"}; - Configurable piluprejection{"piluprejection", false, "Pileup rejection"}; - Configurable goodzvertex{"goodzvertex", false, "removes collisions with large differences between z of PV by tracks and z of PV from FT0 A-C time difference."}; - Configurable itstpctracks{"itstpctracks", false, "selects collisions with at least one ITS-TPC track,"}; - Configurable additionalEvsel{"additionalEvsel", false, "Additional event selcection"}; + Configurable timFrameEvsel{"timFrameEvsel", true, "TPC Time frame boundary cut"}; + // Configurable piluprejection{"piluprejection", false, "Pileup rejection"}; + // Configurable goodzvertex{"goodzvertex", false, "removes collisions with large differences between z of PV by tracks and z of PV from FT0 A-C time difference."}; + // Configurable itstpctracks{"itstpctracks", false, "selects collisions with at least one ITS-TPC track,"}; + // Configurable additionalEvsel{"additionalEvsel", false, "Additional event selcection"}; // Configurable applyOccupancyCut{"applyOccupancyCut", false, "Apply occupancy cut"}; // Configurable occupancyCut{"occupancyCut", 1000, "Mimimum Occupancy cut"}; @@ -107,7 +109,7 @@ struct HigherMassResonances { Configurable confDaughEta{"confDaughEta", 0.8f, "V0 Daugh sel: max eta"}; Configurable confDaughTPCnclsMin{"confDaughTPCnclsMin", 70.f, "V0 Daugh sel: Min. nCls TPC"}; Configurable confDaughPIDCuts{"confDaughPIDCuts", 5, "PID selections for KS0 daughters"}; - Configurable confarmcut{"confarmcut", 0.2f, "Armenteros cut"}; + // Configurable confarmcut{"confarmcut", 0.2f, "Armenteros cut"}; Configurable confKsrapidity{"confKsrapidity", 0.5f, "Rapidity cut on K0s"}; // Configurable lowmasscutks0{"lowmasscutks0", 0.497 - 4 * 0.005, "Low mass cut on K0s"}; // Configurable highmasscutks0{"highmasscutks0", 0.497 + 4 * 0.005, "High mass cut on K0s"}; @@ -125,6 +127,7 @@ struct HigherMassResonances { Configurable cTVXEvsel{"cTVXEvsel", true, "Triggger selection"}; Configurable avoidsplitrackMC{"avoidsplitrackMC", false, "avoid split track in MC"}; Configurable selectMCparticles{"selectMCparticles", 1, "0: f0(1710), 1: f2(1525), 2: a2(1320), 3: f0(1370), 4: f0(1500)"}; + Configurable apply_rapidityMC{"apply_rapidityMC", true, "Apply rapidity cut on generated and reconstructed particles"}; std::vector pdgCodes = {10331, 335, 115, 10221, 9030221}; // output THnSparses @@ -138,7 +141,7 @@ struct HigherMassResonances { // Configurable rapidityks{"rapidityks", true, "rapidity cut on K0s"}; Configurable applyCompetingcut{"applyCompetingcut", false, "Competing cascade rejection cut"}; Configurable competingcascrejlambda{"competingcascrejlambda", 0.005, "rejecting competing cascade lambda"}; - Configurable competingcascrejlambdaanti{"competingcascrejlambdaanti", 0.005, "rejecting competing cascade anti-lambda"}; // If one of the pions is misidentified as a proton, then instead of Ks we reconstruct lambda, therefore the competing cascade rejection cut is applied in which if the reconstrcted mass of a pion and proton (which we are assuming to be misidentified as proton) is close to lambda or anti-lambda, then the track is rejected + // Configurable competingcascrejlambdaanti{"competingcascrejlambdaanti", 0.005, "rejecting competing cascade anti-lambda"}; // If one of the pions is misidentified as a proton, then instead of Ks we reconstruct lambda, therefore the competing cascade rejection cut is applied in which if the reconstrcted mass of a pion and proton (which we are assuming to be misidentified as proton) is close to lambda or anti-lambda, then the track is rejected Configurable tpcCrossedrows{"tpcCrossedrows", 70, "TPC crossed rows"}; Configurable tpcCrossedrowsOverfcls{"tpcCrossedrowsOverfcls", 0.8, "TPC crossed rows over findable clusters"}; @@ -154,6 +157,7 @@ struct HigherMassResonances { Configurable ksMassBins{"ksMassBins", 200, "Number of mass bins for K0s"}; Configurable rotationalCut{"rotationalCut", 10, "Cut value (Rotation angle pi - pi/cut and pi + pi/cut)"}; ConfigurableAxis configThnAxisPOL{"configThnAxisPOL", {20, -1.0, 1.0}, "Costheta axis"}; + ConfigurableAxis configThnAxisPhi{"configThnAxisPhi", {70, 0.0f, 7.0f}, "Phi axis"}; // 0 to 2pi // ConfigurableAxis axisdEdx{"axisdEdx", {20000, 0.0f, 200.0f}, "dE/dx (a.u.)"}; // ConfigurableAxis axisPtfordEbydx{"axisPtfordEbydx", {2000, 0, 20}, "pT (GeV/c)"}; // ConfigurableAxis axisMultdist{"axisMultdist", {3500, 0, 70000}, "Multiplicity distribution"}; @@ -169,6 +173,8 @@ struct HigherMassResonances { float theta2; ROOT::Math::PxPyPzMVector daughter1, daughter2, fourVecDau1, fourVecMother, fourVecDauCM; ROOT::Math::XYZVector threeVecDauCM, helicityVec, randomVec, beamVec, normalVec; + ROOT::Math::XYZVector z_beam; // ẑ: beam direction in lab frame + // const double massK0s = o2::constants::physics::MassK0Short; bool isMix = false; @@ -182,6 +188,7 @@ struct HigherMassResonances { // AxisSpec multiplicityAxis = {110, 0.0f, 150.0f, "Multiplicity Axis"}; AxisSpec multiplicityAxis = {config.binsCent, "Multiplicity Axis"}; AxisSpec thnAxisPOL{config.configThnAxisPOL, "Configurabel theta axis"}; + AxisSpec thnAxisPhi = {config.configThnAxisPhi, "Configurabel phi axis"}; // 0 to 2pi // AxisSpec occupancyAxis = {occupancyBins, "Occupancy [-40,100]"}; // THnSparses @@ -216,9 +223,9 @@ struct HigherMassResonances { // rEventSelection.add("hNcontributor", "Number of primary vertex contributor", kTH1F, {{2000, 0.0f, 10000.0f}}); } - hglue.add("h3glueInvMassDS", "h3glueInvMassDS", kTHnSparseF, {multiplicityAxis, ptAxis, glueballMassAxis, thnAxisPOL}, true); - hglue.add("h3glueInvMassME", "h3glueInvMassME", kTHnSparseF, {multiplicityAxis, ptAxis, glueballMassAxis, thnAxisPOL}, true); - hglue.add("h3glueInvMassRot", "h3glueInvMassRot", kTHnSparseF, {multiplicityAxis, ptAxis, glueballMassAxis, thnAxisPOL}, true); + hglue.add("h3glueInvMassDS", "h3glueInvMassDS", kTHnSparseF, {multiplicityAxis, ptAxis, glueballMassAxis, thnAxisPOL, thnAxisPhi}, true); + hglue.add("h3glueInvMassME", "h3glueInvMassME", kTHnSparseF, {multiplicityAxis, ptAxis, glueballMassAxis, thnAxisPOL, thnAxisPhi}, true); + hglue.add("h3glueInvMassRot", "h3glueInvMassRot", kTHnSparseF, {multiplicityAxis, ptAxis, glueballMassAxis, thnAxisPOL, thnAxisPhi}, true); hglue.add("heventscheck", "heventscheck", kTH1I, {{10, 0, 10}}); hglue.add("htrackscheck_v0", "htrackscheck_v0", kTH1I, {{15, 0, 15}}); hglue.add("htrackscheck_v0_daughters", "htrackscheck_v0_daughters", kTH1I, {{15, 0, 15}}); @@ -324,20 +331,20 @@ struct HigherMassResonances { } hglue.fill(HIST("heventscheck"), 3.5); - if (config.piluprejection && !collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { - return false; - } - hglue.fill(HIST("heventscheck"), 4.5); + // if (config.piluprejection && !collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { + // return false; + // } + // hglue.fill(HIST("heventscheck"), 4.5); - if (config.goodzvertex && !collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { - return false; - } - hglue.fill(HIST("heventscheck"), 5.5); + // if (config.goodzvertex && !collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { + // return false; + // } + // hglue.fill(HIST("heventscheck"), 5.5); - if (config.itstpctracks && !collision.selection_bit(o2::aod::evsel::kIsVertexITSTPC)) { - return false; - } - hglue.fill(HIST("heventscheck"), 6.5); + // if (config.itstpctracks && !collision.selection_bit(o2::aod::evsel::kIsVertexITSTPC)) { + // return false; + // } + // hglue.fill(HIST("heventscheck"), 6.5); return true; } @@ -345,9 +352,9 @@ struct HigherMassResonances { template bool selectionV0(Collision const& collision, V0 const& candidate, float /*multiplicity*/) { - const float qtarm = candidate.qtarm(); - const float alph = candidate.alpha(); - float arm = qtarm / alph; + // const float qtarm = candidate.qtarm(); + // const float alph = candidate.alpha(); + // float arm = qtarm / alph; const float pT = candidate.pt(); const float tranRad = candidate.v0radius(); const float dcaDaughv0 = candidate.dcaV0daughters(); @@ -441,15 +448,15 @@ struct HigherMassResonances { // if (config.correlation2Dhist) // rKzeroShort.fill(HIST("mass_lambda_kshort_after8"), candidate.mK0Short(), candidate.mLambda()); - if (config.armcut && arm < config.confarmcut) { - return false; - } + // if (config.armcut && arm < config.confarmcut) { + // return false; + // } hglue.fill(HIST("htrackscheck_v0"), 9.5); // if (config.correlation2Dhist) // rKzeroShort.fill(HIST("mass_lambda_kshort_after9"), candidate.mK0Short(), candidate.mLambda()); // if (config.applyCompetingcut && (std::abs(candidate.mLambda() - PDGdatabase->Mass(3122)) <= config.competingcascrejlambda || std::abs(candidate.mAntiLambda() - PDGdatabase->Mass(-3122)) <= config.competingcascrejlambdaanti)) - if (config.applyCompetingcut && (std::abs(candidate.mLambda() - o2::constants::physics::MassLambda0) <= config.competingcascrejlambda || std::abs(candidate.mAntiLambda() - o2::constants::physics::MassLambda0) <= config.competingcascrejlambdaanti)) { + if (config.applyCompetingcut && (std::abs(candidate.mLambda() - o2::constants::physics::MassLambda0) <= config.competingcascrejlambda || std::abs(candidate.mAntiLambda() - o2::constants::physics::MassLambda0) <= config.competingcascrejlambda)) { return false; } hglue.fill(HIST("htrackscheck_v0"), 10.5); @@ -565,59 +572,99 @@ struct HigherMassResonances { using EventCandidatesMC = soa::Join; using TrackCandidatesMC = soa::Filtered>; using V0TrackCandidatesMC = soa::Join; + // z_beam direction in lab frame template void fillInvMass(const T2& lv3, const T3& lv5, float multiplicity, const T4& daughter1, bool isMix) { - // polarization calculations + // //polarization calculations + // z_beam = ROOT::Math::XYZVector(0.f, 0.f, 1.f); // ẑ: beam direction in lab frame - fourVecDau1 = ROOT::Math::PxPyPzMVector(daughter1.Px(), daughter1.Py(), daughter1.Pz(), o2::constants::physics::MassK0Short); // Kaon or Pion + fourVecDau1 = ROOT::Math::PxPyPzMVector(daughter1.Px(), daughter1.Py(), daughter1.Pz(), o2::constants::physics::MassK0Short); - fourVecMother = ROOT::Math::PxPyPzMVector(lv3.Px(), lv3.Py(), lv3.Pz(), lv3.M()); // mass of KshortKshort pair - ROOT::Math::Boost boost{fourVecMother.BoostToCM()}; // boost mother to center of mass frame - fourVecDauCM = boost(fourVecDau1); // boost the frame of daughter same as mother + fourVecMother = ROOT::Math::PxPyPzMVector(lv3.Px(), lv3.Py(), lv3.Pz(), lv3.M()); // 4 vector of mother particle + ROOT::Math::Boost boost{fourVecMother.BoostToCM()}; // define the boost to the center of mass frame + fourVecDauCM = boost(fourVecDau1); // boost the frame of daughter to the center of mass frame threeVecDauCM = fourVecDauCM.Vect(); // get the 3 vector of daughter in the frame of mother + // define y = z_beam x z: Normal to the production plane + // ẑ: mother direction in lab, boosted into mother's rest frame + + // auto motherLabDirection = ROOT::Math::XYZVector(0, 0, fourVecMother.Vect().Z()); // ẑ axis in lab frame + + // // ŷ = z_beam × ẑ + // auto y_axis = z_beam.Cross(motherLabDirection).Unit(); + + // // x̂ = ŷ × ẑ + // auto x_axis = y_axis.Cross(motherLabDirection).Unit(); + + // // Project daughter momentum onto x–y plane + // auto p_proj_x = threeVecDauCM.Dot(x_axis); + // auto p_proj_y = threeVecDauCM.Dot(y_axis); + + // // Calculate φ in [-π, π] + // auto angle_phi = std::atan2(p_proj_y, p_proj_x); // φ in radians + + double BeamMomentum = TMath::Sqrt(13600 * 13600 / 4 - 0.938 * 0.938); // GeV + ROOT::Math::PxPyPzEVector Beam1(0., 0., -BeamMomentum, 13600 / 2); + ROOT::Math::PxPyPzEVector Beam2(0., 0., BeamMomentum, 13600 / 2); + ROOT::Math::XYZVectorF v1_CM{(boost(fourVecDau1).Vect()).Unit()}; + // ROOT::Math::XYZVectorF v2_CM{(boost(fourVecDau1).Vect()).Unit()}; + ROOT::Math::XYZVectorF Beam1_CM{(boost(Beam1).Vect()).Unit()}; + ROOT::Math::XYZVectorF Beam2_CM{(boost(Beam2).Vect()).Unit()}; + // using positive sign convention for the first track + // ROOT::Math::XYZVectorF v_CM = (t1.sign() > 0 ? v1_CM : v2_CM); // here selected decay daughter momentum is intested. here you can choose one decay daughter no need to check both case as it is neutral particle for our case + // Helicity frame + ROOT::Math::XYZVectorF zaxis_HE{(fourVecMother.Vect()).Unit()}; + ROOT::Math::XYZVectorF yaxis_HE{(Beam1_CM.Cross(Beam2_CM)).Unit()}; + ROOT::Math::XYZVectorF xaxis_HE{(yaxis_HE.Cross(zaxis_HE)).Unit()}; + + // CosThetaHE = zaxis_HE.Dot(v_CM); + + auto angle_phi = TMath::ATan2(yaxis_HE.Dot(v1_CM), xaxis_HE.Dot(v1_CM)); + if (angle_phi < 0) { + angle_phi += 2 * TMath::Pi(); // ensure phi is in [0, 2pi] + } if (std::abs(lv3.Rapidity()) < 0.5) { if (config.activateTHnSparseCosThStarHelicity) { helicityVec = fourVecMother.Vect(); // 3 vector of mother in COM frame auto cosThetaStarHelicity = helicityVec.Dot(threeVecDauCM) / (std::sqrt(threeVecDauCM.Mag2()) * std::sqrt(helicityVec.Mag2())); if (!isMix) { - hglue.fill(HIST("h3glueInvMassDS"), multiplicity, lv3.Pt(), lv3.M(), cosThetaStarHelicity); + hglue.fill(HIST("h3glueInvMassDS"), multiplicity, lv3.Pt(), lv3.M(), cosThetaStarHelicity, angle_phi); for (int i = 0; i < config.cRotations; i++) { theta2 = rn->Uniform(o2::constants::math::PI - o2::constants::math::PI / config.rotationalCut, o2::constants::math::PI + o2::constants::math::PI / config.rotationalCut); - hglue.fill(HIST("h3glueInvMassRot"), multiplicity, lv5.Pt(), lv5.M(), cosThetaStarHelicity); + hglue.fill(HIST("h3glueInvMassRot"), multiplicity, lv5.Pt(), lv5.M(), cosThetaStarHelicity, angle_phi); } } else { - hglue.fill(HIST("h3glueInvMassME"), multiplicity, lv3.Pt(), lv3.M(), cosThetaStarHelicity); + hglue.fill(HIST("h3glueInvMassME"), multiplicity, lv3.Pt(), lv3.M(), cosThetaStarHelicity, angle_phi); } } else if (config.activateTHnSparseCosThStarProduction) { normalVec = ROOT::Math::XYZVector(lv3.Py(), -lv3.Px(), 0.f); auto cosThetaStarProduction = normalVec.Dot(threeVecDauCM) / (std::sqrt(threeVecDauCM.Mag2()) * std::sqrt(normalVec.Mag2())); if (!isMix) { - hglue.fill(HIST("h3glueInvMassDS"), multiplicity, lv3.Pt(), lv3.M(), cosThetaStarProduction); + hglue.fill(HIST("h3glueInvMassDS"), multiplicity, lv3.Pt(), lv3.M(), cosThetaStarProduction, angle_phi); for (int i = 0; i < config.cRotations; i++) { theta2 = rn->Uniform(0, o2::constants::math::PI); - hglue.fill(HIST("h3glueInvMassRot"), multiplicity, lv5.Pt(), lv5.M(), cosThetaStarProduction); + hglue.fill(HIST("h3glueInvMassRot"), multiplicity, lv5.Pt(), lv5.M(), cosThetaStarProduction, angle_phi); } } else { - hglue.fill(HIST("h3glueInvMassME"), multiplicity, lv3.Pt(), lv3.M(), cosThetaStarProduction); + hglue.fill(HIST("h3glueInvMassME"), multiplicity, lv3.Pt(), lv3.M(), cosThetaStarProduction, angle_phi); } } else if (config.activateTHnSparseCosThStarBeam) { beamVec = ROOT::Math::XYZVector(0.f, 0.f, 1.f); auto cosThetaStarBeam = beamVec.Dot(threeVecDauCM) / std::sqrt(threeVecDauCM.Mag2()); if (!isMix) { - hglue.fill(HIST("h3glueInvMassDS"), multiplicity, lv3.Pt(), lv3.M(), cosThetaStarBeam); + hglue.fill(HIST("h3glueInvMassDS"), multiplicity, lv3.Pt(), lv3.M(), cosThetaStarBeam, angle_phi); for (int i = 0; i < config.cRotations; i++) { theta2 = rn->Uniform(0, o2::constants::math::PI); - hglue.fill(HIST("h3glueInvMassRot"), multiplicity, lv5.Pt(), lv5.M(), cosThetaStarBeam); + hglue.fill(HIST("h3glueInvMassRot"), multiplicity, lv5.Pt(), lv5.M(), cosThetaStarBeam, angle_phi); } } else { - hglue.fill(HIST("h3glueInvMassME"), multiplicity, lv3.Pt(), lv3.M(), cosThetaStarBeam); + hglue.fill(HIST("h3glueInvMassME"), multiplicity, lv3.Pt(), lv3.M(), cosThetaStarBeam, angle_phi); } } else if (config.activateTHnSparseCosThStarRandom) { @@ -627,13 +674,13 @@ struct HigherMassResonances { randomVec = ROOT::Math::XYZVector(std::sin(thetaRandom) * std::cos(phiRandom), std::sin(thetaRandom) * std::sin(phiRandom), std::cos(thetaRandom)); auto cosThetaStarRandom = randomVec.Dot(threeVecDauCM) / std::sqrt(threeVecDauCM.Mag2()); if (!isMix) { - hglue.fill(HIST("h3glueInvMassDS"), multiplicity, lv3.Pt(), lv3.M(), cosThetaStarRandom); + hglue.fill(HIST("h3glueInvMassDS"), multiplicity, lv3.Pt(), lv3.M(), cosThetaStarRandom, angle_phi); for (int i = 0; i < config.cRotations; i++) { theta2 = rn->Uniform(0, o2::constants::math::PI); - hglue.fill(HIST("h3glueInvMassRot"), multiplicity, lv5.Pt(), lv5.M(), cosThetaStarRandom); + hglue.fill(HIST("h3glueInvMassRot"), multiplicity, lv5.Pt(), lv5.M(), cosThetaStarRandom, angle_phi); } } else { - hglue.fill(HIST("h3glueInvMassME"), multiplicity, lv3.Pt(), lv3.M(), cosThetaStarRandom); + hglue.fill(HIST("h3glueInvMassME"), multiplicity, lv3.Pt(), lv3.M(), cosThetaStarRandom, angle_phi); } } } @@ -979,7 +1026,7 @@ struct HigherMassResonances { // hMChists.fill(HIST("GenPy"), mcParticle.py()); // hMChists.fill(HIST("GenPz"), mcParticle.pz()); - if (std::abs(mcParticle.y()) >= 0.5) { + if (config.apply_rapidityMC && std::abs(mcParticle.y()) >= 0.5) { continue; } hMChists.fill(HIST("events_check"), 6.5); @@ -1159,7 +1206,7 @@ struct HigherMassResonances { } hMChists.fill(HIST("events_checkrec"), 17.5); - if (std::abs(mothertrack1.y()) >= 0.5) { + if (config.apply_rapidityMC && std::abs(mothertrack1.y()) >= 0.5) { continue; } hMChists.fill(HIST("events_checkrec"), 18.5); From d80d8bb7fbcda213cdb09913700fa21899924eee Mon Sep 17 00:00:00 2001 From: Pritam Chakraborty <47203359+prchakra@users.noreply.github.com> Date: Sat, 14 Jun 2025 12:24:22 +0200 Subject: [PATCH 074/871] [PWGCF] FemtoUniverse: Filling 3D histo of qLCMS vs dEta vs dPhi (#11603) --- ...irTaskTrackTrackSpherHarMultKtExtended.cxx | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrackSpherHarMultKtExtended.cxx b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrackSpherHarMultKtExtended.cxx index 977342a3939..d0205e6bb8f 100644 --- a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrackSpherHarMultKtExtended.cxx +++ b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrackSpherHarMultKtExtended.cxx @@ -182,6 +182,7 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { Configurable cfgProcessMultBins{"cfgProcessMultBins", true, "Process kstar histograms in multiplicity bins (in multiplicity bins)"}; Configurable cfgProcessKtBins{"cfgProcessKtBins", true, "Process kstar histograms in kT bins (if cfgProcessMultBins is set false, this will not be processed regardless this Configurable state)"}; Configurable cfgProcessKtMt3DCF{"cfgProcessKtMt3DCF", false, "Process 3D histograms in kT and Mult bins"}; + Configurable ConfIsFillAngqLCMS{"ConfIsFillAngqLCMS", true, "Fill qLCMS vs dEta vs dPhi"}; FemtoUniverseSHContainer sameEventCont; FemtoUniverseSHContainer mixedEventCont; @@ -519,12 +520,21 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { double rand; rand = randgen->Rndm(); + std::vector f3d; + double kv; + switch (ContType) { case 2: { if (rand > 0.5) { sameEventMultContPP.fillMultNumDen(p1, p2, femto_universe_sh_container::EventType::same, 2, multCol, kT, ConfIsIden); + f3d = FemtoUniverseMath::newpairfunc(p1, mass1, p2, mass2, ConfIsIden); } else if (rand <= 0.5) { sameEventMultContPP.fillMultNumDen(p2, p1, femto_universe_sh_container::EventType::same, 2, multCol, kT, ConfIsIden); + f3d = FemtoUniverseMath::newpairfunc(p2, mass2, p1, mass1, ConfIsIden); + } + if (ConfIsFillAngqLCMS) { + kv = std::sqrt(f3d[1] * f3d[1] + f3d[2] * f3d[2] + f3d[3] * f3d[3]); + pairCloseRejection.ClosePairqLCMS(p1, p2, magFieldTesla, femto_universe_container::EventType::same, kv); } break; } @@ -532,8 +542,14 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { case 3: { if (rand > 0.5) { sameEventMultContMM.fillMultNumDen(p1, p2, femto_universe_sh_container::EventType::same, 2, multCol, kT, ConfIsIden); + f3d = FemtoUniverseMath::newpairfunc(p1, mass1, p2, mass2, ConfIsIden); } else if (rand <= 0.5) { sameEventMultContMM.fillMultNumDen(p2, p1, femto_universe_sh_container::EventType::same, 2, multCol, kT, ConfIsIden); + f3d = FemtoUniverseMath::newpairfunc(p2, mass2, p1, mass1, ConfIsIden); + } + if (ConfIsFillAngqLCMS) { + kv = std::sqrt(f3d[1] * f3d[1] + f3d[2] * f3d[2] + f3d[3] * f3d[3]); + pairCloseRejection.ClosePairqLCMS(p1, p2, magFieldTesla, femto_universe_container::EventType::same, kv); } break; } @@ -657,6 +673,9 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { double rand; rand = randgen->Rndm(); + std::vector f3d; + double kv; + switch (ContType) { case 1: { if (rand > 0.5) { @@ -670,8 +689,14 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { case 2: { if (rand > 0.5) { mixedEventMultContPP.fillMultNumDen(p1, p2, femto_universe_sh_container::EventType::mixed, 2, multCol, kT, ConfIsIden); + f3d = FemtoUniverseMath::newpairfunc(p1, mass1, p2, mass2, ConfIsIden); } else { mixedEventMultContPP.fillMultNumDen(p2, p1, femto_universe_sh_container::EventType::mixed, 2, multCol, kT, ConfIsIden); + f3d = FemtoUniverseMath::newpairfunc(p2, mass2, p1, mass1, ConfIsIden); + } + if (ConfIsFillAngqLCMS) { + kv = std::sqrt(f3d[1] * f3d[1] + f3d[2] * f3d[2] + f3d[3] * f3d[3]); + pairCloseRejection.ClosePairqLCMS(p1, p2, magFieldTesla, femto_universe_container::EventType::mixed, kv); } break; } @@ -679,8 +704,14 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { case 3: { if (rand > 0.5) { mixedEventMultContMM.fillMultNumDen(p1, p2, femto_universe_sh_container::EventType::mixed, 2, multCol, kT, ConfIsIden); + f3d = FemtoUniverseMath::newpairfunc(p1, mass1, p2, mass2, ConfIsIden); } else { mixedEventMultContMM.fillMultNumDen(p2, p1, femto_universe_sh_container::EventType::mixed, 2, multCol, kT, ConfIsIden); + f3d = FemtoUniverseMath::newpairfunc(p2, mass2, p1, mass1, ConfIsIden); + } + if (ConfIsFillAngqLCMS) { + kv = std::sqrt(f3d[1] * f3d[1] + f3d[2] * f3d[2] + f3d[3] * f3d[3]); + pairCloseRejection.ClosePairqLCMS(p1, p2, magFieldTesla, femto_universe_container::EventType::mixed, kv); } break; } From 1f25a5a0555601b45836a67b1b58f153d9ec3105 Mon Sep 17 00:00:00 2001 From: Zhiyong <71517277+Luzhiyongg@users.noreply.github.com> Date: Sat, 14 Jun 2025 18:52:19 +0800 Subject: [PATCH 075/871] [PWGCF] add pT-diff correlations (#11617) --- PWGCF/TwoParticleCorrelations/Tasks/diHadronCor.cxx | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/PWGCF/TwoParticleCorrelations/Tasks/diHadronCor.cxx b/PWGCF/TwoParticleCorrelations/Tasks/diHadronCor.cxx index e79c61b3096..13c8b352d9f 100644 --- a/PWGCF/TwoParticleCorrelations/Tasks/diHadronCor.cxx +++ b/PWGCF/TwoParticleCorrelations/Tasks/diHadronCor.cxx @@ -94,6 +94,7 @@ struct DiHadronCor { O2_DEFINE_CONFIGURABLE(cfgLocalEfficiency, bool, false, "Use local efficiency object") O2_DEFINE_CONFIGURABLE(cfgVerbosity, bool, false, "Verbose output") O2_DEFINE_CONFIGURABLE(cfgUseEventWeights, bool, false, "Use event weights for mixed event") + O2_DEFINE_CONFIGURABLE(cfgUsePtDiff, bool, false, "To enable pt differential vn, one needs to set this to true and set the pt bins accordingly") SliceCache cache; @@ -472,8 +473,10 @@ struct DiHadronCor { associatedWeight = efficiencyAssociatedCache[track2.filteredIndex()]; } - if (track1.pt() <= track2.pt()) - continue; // skip if the trigger pt is less than the associate pt + if (cfgUsePtDiff && track1.globalIndex() == track2.globalIndex()) + continue; // For pt-differential correlations, skip if the trigger and associate are the same track + if (!cfgUsePtDiff && track1.pt() <= track2.pt()) + continue; // Without pt-differential correlations, skip if the trigger pt is less than the associate pt float deltaPhi = RecoDecay::constrainAngle(track1.phi() - track2.phi(), -PIHalf); float deltaEta = track1.eta() - track2.eta(); @@ -537,8 +540,10 @@ struct DiHadronCor { if (doprocessOntheflyMixed && !genTrackSelected(track2)) continue; - if (track1.pt() <= track2.pt()) - continue; // skip if the trigger pt is less than the associate pt + if (cfgUsePtDiff && track1.globalIndex() == track2.globalIndex()) + continue; // For pt-differential correlations, skip if the trigger and associate are the same track + if (!cfgUsePtDiff && track1.pt() <= track2.pt()) + continue; // Without pt-differential correlations, skip if the trigger pt is less than the associate pt float deltaPhi = RecoDecay::constrainAngle(track1.phi() - track2.phi(), -PIHalf); float deltaEta = track1.eta() - track2.eta(); From 420d8cb36a586aae68b714d357b6011d6f9d586d Mon Sep 17 00:00:00 2001 From: ddobrigk Date: Sat, 14 Jun 2025 15:21:23 +0200 Subject: [PATCH 076/871] [Common] Add hepmc info for O-O cent studies (#11621) Co-authored-by: David Dobrigkeit Chinellato Co-authored-by: ALICE Builder --- Common/DataModel/Multiplicity.h | 5 +++++ Common/TableProducer/multiplicityTable.cxx | 14 ++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/Common/DataModel/Multiplicity.h b/Common/DataModel/Multiplicity.h index ce6aa4ba046..864e2a9cd1c 100644 --- a/Common/DataModel/Multiplicity.h +++ b/Common/DataModel/Multiplicity.h @@ -184,9 +184,14 @@ DECLARE_SOA_TABLE_VERSIONED(MultMCExtras_001, "AOD", "MULTMCEXTRA", 1, //! Table mult::IsInelGt1, o2::soa::Marker<1>); +DECLARE_SOA_TABLE(MultHepMCHIs, "AOD", "MULTHEPMCHI", //! complementary table for heavy-ion mc info (subset of HepMCHeavyIons) + o2::soa::Index<>, hepmcheavyion::McCollisionId, hepmcheavyion::NcollHard, hepmcheavyion::NpartProj, hepmcheavyion::NpartTarg, + hepmcheavyion::Ncoll, hepmcheavyion::ImpactParameter); + using MultMCExtras = MultMCExtras_001; using MultMCExtra = MultMCExtras::iterator; using MultsExtraMC = MultMCExtras; // for backwards compatibility with previous naming scheme +using MultHepMCHI = MultHepMCHIs::iterator; // crosslinks namespace mult diff --git a/Common/TableProducer/multiplicityTable.cxx b/Common/TableProducer/multiplicityTable.cxx index 6deb146daab..eb9648ecf2b 100644 --- a/Common/TableProducer/multiplicityTable.cxx +++ b/Common/TableProducer/multiplicityTable.cxx @@ -100,6 +100,7 @@ struct MultiplicityTable { Produces tablePVZeqs; // 12 Produces tableExtraMc; // 13 Produces tableExtraMult2MCExtras; + Produces multHepMCHIs; // Not accounted for, produced using custom process function to avoid dependencies Produces mftMults; // Not accounted for, produced using custom process function to avoid dependencies Produces multsGlobal; // Not accounted for, produced based on process function processGlobalTrackingCounters @@ -734,6 +735,18 @@ struct MultiplicityTable { using Run3Tracks = soa::Join; Partition pvContribGlobalTracksEta1 = (minPtGlobalTrack < aod::track::pt && aod::track::pt < maxPtGlobalTrack) && (nabs(aod::track::eta) < 1.0f) && ((aod::track::flags & static_cast(o2::aod::track::PVContributor)) == static_cast(o2::aod::track::PVContributor)) && requireQualityTracksInFilter(); + void processHepMCHeavyIons(aod::HepMCHeavyIons const& hepmchis) + { + for (auto const& hepmchi : hepmchis) { + multHepMCHIs(hepmchi.mcCollisionId(), + hepmchi.ncollHard(), + hepmchi.npartProj(), + hepmchi.npartTarg(), + hepmchi.ncoll(), + hepmchi.impactParameter()); + } + } + void processGlobalTrackingCounters(aod::Collision const& collision, soa::Join const& tracksIU, Run3Tracks const&) { // counter from Igor @@ -808,6 +821,7 @@ struct MultiplicityTable { PROCESS_SWITCH(MultiplicityTable, processGlobalTrackingCounters, "Produce Run 3 global counters", false); PROCESS_SWITCH(MultiplicityTable, processMC, "Produce MC multiplicity tables", false); PROCESS_SWITCH(MultiplicityTable, processMC2Mults, "Produce MC -> Mult map", false); + PROCESS_SWITCH(MultiplicityTable, processHepMCHeavyIons, "Produce MultHepMCHIs tables", false); PROCESS_SWITCH(MultiplicityTable, processRun3MFT, "Produce MFT mult tables", false); }; From 7b5501c19ee3dc18ed694984776f06dbd293751b Mon Sep 17 00:00:00 2001 From: Preet-Bhanjan Date: Sat, 14 Jun 2025 15:25:13 +0200 Subject: [PATCH 077/871] [PWGCF] Added ITS PID (#11608) Co-authored-by: Preet Pati Co-authored-by: ALICE Action Bot --- PWGCF/Flow/Tasks/flowPbpbPikp.cxx | 119 ++++++++++++++++++------------ 1 file changed, 71 insertions(+), 48 deletions(-) diff --git a/PWGCF/Flow/Tasks/flowPbpbPikp.cxx b/PWGCF/Flow/Tasks/flowPbpbPikp.cxx index 1d979488da3..97fbc3a3661 100644 --- a/PWGCF/Flow/Tasks/flowPbpbPikp.cxx +++ b/PWGCF/Flow/Tasks/flowPbpbPikp.cxx @@ -13,48 +13,46 @@ /// \brief PID flow using the generic framework /// \author Preet Bhanjan Pati -#include -#include -#include -#include -#include -#include -#include - -#include "Math/Vector4D.h" - -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/RunningWorkflowInfo.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/StepTHn.h" +#include "PWGCF/GenericFramework/Core/FlowContainer.h" +#include "PWGCF/GenericFramework/Core/GFW.h" +#include "PWGCF/GenericFramework/Core/GFWConfig.h" +#include "PWGCF/GenericFramework/Core/GFWCumulant.h" +#include "PWGCF/GenericFramework/Core/GFWPowerArray.h" +#include "PWGCF/GenericFramework/Core/GFWWeights.h" +#include "PWGCF/GenericFramework/Core/GFWWeightsList.h" -#include "Common/DataModel/EventSelection.h" #include "Common/Core/TrackSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" +#include "Common/Core/trackUtilities.h" #include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/PIDResponse.h" #include "Common/DataModel/PIDResponseITS.h" -#include "Common/Core/trackUtilities.h" -#include "Common/DataModel/Multiplicity.h" -#include "CommonConstants/PhysicsConstants.h" - -#include "PWGCF/GenericFramework/Core/GFWPowerArray.h" -#include "PWGCF/GenericFramework/Core/GFW.h" -#include "PWGCF/GenericFramework/Core/GFWCumulant.h" -#include "PWGCF/GenericFramework/Core/FlowContainer.h" -#include "PWGCF/GenericFramework/Core/GFWWeights.h" -#include "PWGCF/GenericFramework/Core/GFWWeightsList.h" -#include "PWGCF/GenericFramework/Core/GFWConfig.h" +#include "Common/DataModel/TrackSelectionTables.h" -#include "ReconstructionDataFormats/Track.h" +#include "CommonConstants/PhysicsConstants.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/RunningWorkflowInfo.h" +#include "Framework/StepTHn.h" +#include "Framework/runDataProcessing.h" #include "ReconstructionDataFormats/PID.h" +#include "ReconstructionDataFormats/Track.h" +#include +#include "Math/Vector4D.h" +#include #include #include -#include + +#include +#include +#include +#include +#include +#include using namespace o2; using namespace o2::framework; @@ -72,6 +70,7 @@ GFWCorrConfigs configs; using namespace o2::analysis::genericframework; struct FlowPbpbPikp { + o2::aod::ITSResponse itsResponse; Service ccdb; Configurable noLaterThan{"noLaterThan", std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(), "latest acceptable timestamp of creation for the object"}; Configurable ccdbUrl{"ccdbUrl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; @@ -107,11 +106,12 @@ struct FlowPbpbPikp { O2_DEFINE_CONFIGURABLE(cfgUseStrictPID, bool, true, "Use strict PID cuts for TPC") O2_DEFINE_CONFIGURABLE(cfgV0AT0Acut, int, 5, "V0AT0A cut") O2_DEFINE_CONFIGURABLE(cfgUseAsymmetricPID, bool, false, "Use asymmetric PID cuts"); + O2_DEFINE_CONFIGURABLE(cfgUseItsPID, bool, true, "Use ITS PID for particle identification"); Configurable> cfgTrackDensityP0{"cfgTrackDensityP0", std::vector{0.7217476707, 0.7384792571, 0.7542625668, 0.7640680200, 0.7701951667, 0.7755299053, 0.7805901710, 0.7849446786, 0.7957356586, 0.8113039262, 0.8211968966, 0.8280558878, 0.8329342135}, "parameter 0 for track density efficiency correction"}; Configurable> cfgTrackDensityP1{"cfgTrackDensityP1", std::vector{-2.169488e-05, -2.191913e-05, -2.295484e-05, -2.556538e-05, -2.754463e-05, -2.816832e-05, -2.846502e-05, -2.843857e-05, -2.705974e-05, -2.477018e-05, -2.321730e-05, -2.203315e-05, -2.109474e-05}, "parameter 1 for track density efficiency correction"}; Configurable> cfgTofNsigmaCut{"cfgTofNsigmaCut", 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"}; - Configurable> cfgItsNsigmaCut{"cfgItsNsigmaCut", 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> cfgItsNsigmaCut{"cfgItsNsigmaCut", std::vector{3, 3, 3, -3, -3, -3}, "ITS n-sigma cut for pions_posNsigma, kaons_posNsigma, protons_posNsigma, pions_negNsigma, kaons_negNsigma, protons_negNsigma"}; Configurable> cfgTpcNsigmaCut{"cfgTpcNsigmaCut", 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"}; Configurable> cfgUseEventCuts{"cfgUseEventCuts", std::vector{1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0}, "Switch for various event cuts [kNoTimeFrameBorder, kNoITSROFrameBorder, kNoSameBunchPileup, kIsGoodZvtxFT0vsPV, kNoCollInTimeRangeStandard, kIsGoodITSLayersAll, kNoCollInRofStandard, kNoHighMultCollInPrevRof, Occupancy, Multiplicity correlation, T0AV0A 3 sigma cut, kIsVertexITSTPC, kTVXinTRD]"}; @@ -125,6 +125,7 @@ struct FlowPbpbPikp { ConfigurableAxis axisMultiplicity{"axisMultiplicity", {VARIABLE_WIDTH, 0, 5, 10, 20, 30, 40, 50, 60, 70, 80, 90}, "centrality axis for histograms"}; ConfigurableAxis axisNsigmaTPC{"axisNsigmaTPC", {80, -5, 5}, "nsigmaTPC axis"}; ConfigurableAxis axisNsigmaTOF{"axisNsigmaTOF", {80, -5, 5}, "nsigmaTOF axis"}; + ConfigurableAxis axisNsigmaITS{"axisNsigmaITS", {80, -5, 5}, "nsigmaITS axis"}; ConfigurableAxis axisParticles{"axisParticles", {3, 0, 3}, "axis for different hadrons"}; ConfigurableAxis axisTPCsignal{"axisTPCsignal", {10000, 0, 1000}, "axis for TPC signal"}; ConfigurableAxis axisTOFbeta{"axisTOFbeta", {200, 0, 2}, "axis for TOF beta"}; @@ -249,9 +250,14 @@ struct FlowPbpbPikp { histos.add("TofBeta", "", {HistType::kTH2D, {axisPt, axisTOFbeta}}); histos.add("TofTpcNsigma_before", "", {HistType::kTHnSparseD, {{axisParticles, axisNsigmaTPC, axisNsigmaTOF, axisPt}}}); - histos.add("TofTpcNsigma_after", "", {HistType::kTHnSparseD, {{axisParticles, axisNsigmaTPC, axisNsigmaTOF, axisPt}}}); + if (!cfgUseItsPID) + histos.add("TofTpcNsigma_after", "", {HistType::kTHnSparseD, {{axisParticles, axisNsigmaTPC, axisNsigmaTOF, axisPt}}}); histos.add("partCount", "", {HistType::kTHnSparseD, {{axisParticles, axisMultiplicity, axisPt}}}); + histos.add("TofItsNsigma_before", "", {HistType::kTHnSparseD, {{axisParticles, axisNsigmaITS, axisNsigmaTOF, axisPt}}}); + if (cfgUseItsPID) + histos.add("TofItsNsigma_after", "", {HistType::kTHnSparseD, {{axisParticles, axisNsigmaITS, axisNsigmaTOF, axisPt}}}); + histos.add("hEventCount", "Number of Events;; Count", {HistType::kTH1D, {{15, 0, 15}}}); histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(1, "Filtered event"); histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(2, "After sel8"); @@ -448,7 +454,10 @@ struct FlowPbpbPikp { histos.fill(HIST("partCount"), pidIndex - 1, collision.centFT0C(), track.pt()); switch (pidIndex) { case 1: - histos.fill(HIST("TofTpcNsigma_after"), pidIndex - 1, track.tpcNSigmaPi(), track.tofNSigmaPi(), track.pt()); + if (!cfgUseItsPID) + histos.fill(HIST("TofTpcNsigma_after"), pidIndex - 1, track.tpcNSigmaPi(), track.tofNSigmaPi(), track.pt()); + if (cfgUseItsPID) + histos.fill(HIST("TofItsNsigma_after"), pidIndex - 1, itsResponse.nSigmaITS(track), track.tofNSigmaPi(), track.pt()); histos.fill(HIST("hTrackCount"), 7.5); // Pion count if (!cfgAcceptance.value.empty() && cfgUseWeightPhiEtaVtxz) histos.fill(HIST("PhiCorrected/hPhiEtaVtxz_pi_corrd"), track.phi(), track.eta(), collision.posZ(), wacc); // pion weights @@ -458,7 +467,10 @@ struct FlowPbpbPikp { histos.fill(HIST("PhiCorrected/hPhiEtaPt_pi_corrd"), track.phi(), track.eta(), track.pt(), wacc); break; case 2: - histos.fill(HIST("TofTpcNsigma_after"), pidIndex - 1, track.tpcNSigmaKa(), track.tofNSigmaKa(), track.pt()); + if (!cfgUseItsPID) + histos.fill(HIST("TofTpcNsigma_after"), pidIndex - 1, track.tpcNSigmaKa(), track.tofNSigmaKa(), track.pt()); + if (cfgUseItsPID) + histos.fill(HIST("TofItsNsigma_after"), pidIndex - 1, itsResponse.nSigmaITS(track), track.tofNSigmaKa(), track.pt()); histos.fill(HIST("hTrackCount"), 8.5); // Kaon count if (!cfgAcceptance.value.empty() && cfgUseWeightPhiEtaVtxz) histos.fill(HIST("PhiCorrected/hPhiEtaVtxz_ka_corrd"), track.phi(), track.eta(), collision.posZ(), wacc); // kaon weights @@ -468,7 +480,10 @@ struct FlowPbpbPikp { histos.fill(HIST("PhiCorrected/hPhiEtaPt_ka_corrd"), track.phi(), track.eta(), track.pt(), wacc); break; case 3: - histos.fill(HIST("TofTpcNsigma_after"), pidIndex - 1, track.tpcNSigmaPr(), track.tofNSigmaPr(), track.pt()); + if (!cfgUseItsPID) + histos.fill(HIST("TofTpcNsigma_after"), pidIndex - 1, track.tpcNSigmaPr(), track.tofNSigmaPr(), track.pt()); + if (cfgUseItsPID) + histos.fill(HIST("TofItsNsigma_after"), pidIndex - 1, itsResponse.nSigmaITS(track), track.tofNSigmaPr(), track.pt()); histos.fill(HIST("hTrackCount"), 9.5); // Proton count if (!cfgAcceptance.value.empty() && cfgUseWeightPhiEtaVtxz) histos.fill(HIST("PhiCorrected/hPhiEtaVtxz_pr_corrd"), track.phi(), track.eta(), collision.posZ(), wacc); // proton weights @@ -512,17 +527,21 @@ struct FlowPbpbPikp { } template - int getNsigmaPIDTpcTofAssymmetric(TTrack track) + int getNsigmaPIDAssymmetric(TTrack track) { // Computing Nsigma arrays for pion, kaon, and protons std::array nSigmaTPC = {track.tpcNSigmaPi(), track.tpcNSigmaKa(), track.tpcNSigmaPr()}; std::array nSigmaTOF = {track.tofNSigmaPi(), track.tofNSigmaKa(), track.tofNSigmaPr()}; + std::array nSigmaITS = {itsResponse.nSigmaITS(track), itsResponse.nSigmaITS(track), itsResponse.nSigmaITS(track)}; int pid = -1; + std::array nSigmaToUse = cfgUseItsPID ? nSigmaITS : nSigmaTPC; // Choose which nSigma to use: TPC or ITS + std::vector detectorNsigmaCut = cfgUseItsPID ? itsNsigmaCut : tpcNsigmaCut; // Choose which nSigma to use: TPC or ITS + bool isPion, isKaon, isProton; - bool isTpcPion = nSigmaTPC[0] < tpcNsigmaCut[0] && nSigmaTPC[0] > tpcNsigmaCut[0 + 3]; - bool isTpcKaon = nSigmaTPC[1] < tpcNsigmaCut[1] && nSigmaTPC[1] > tpcNsigmaCut[1 + 3]; - bool isTpcProton = nSigmaTPC[2] < tpcNsigmaCut[2] && nSigmaTPC[2] > tpcNsigmaCut[2 + 3]; + bool isDetectedPion = nSigmaToUse[0] < detectorNsigmaCut[0] && nSigmaToUse[0] > detectorNsigmaCut[0 + 3]; + bool isDetectedKaon = nSigmaToUse[1] < detectorNsigmaCut[1] && nSigmaToUse[1] > detectorNsigmaCut[1 + 3]; + bool isDetectedProton = nSigmaToUse[2] < detectorNsigmaCut[2] && nSigmaToUse[2] > detectorNsigmaCut[2 + 3]; bool isTofPion = nSigmaTOF[0] < tofNsigmaCut[0] && nSigmaTOF[0] > tofNsigmaCut[0 + 3]; bool isTofKaon = nSigmaTOF[1] < tofNsigmaCut[1] && nSigmaTOF[1] > tofNsigmaCut[1 + 3]; @@ -531,13 +550,13 @@ struct FlowPbpbPikp { if (track.pt() > cfgTofPtCut && !track.hasTOF()) { return 0; } else if (track.pt() > cfgTofPtCut && track.hasTOF()) { - isPion = isTofPion && isTpcPion; - isKaon = isTofKaon && isTpcKaon; - isProton = isTofProton && isTpcProton; + isPion = isTofPion && isDetectedPion; + isKaon = isTofKaon && isDetectedKaon; + isProton = isTofProton && isDetectedProton; } else { - isPion = isTpcPion; - isKaon = isTpcKaon; - isProton = isTpcProton; + isPion = isDetectedPion; + isKaon = isDetectedKaon; + isProton = isDetectedProton; } if ((isPion && isKaon) || (isPion && isProton) || (isKaon && isProton)) { @@ -917,10 +936,14 @@ struct FlowPbpbPikp { histos.fill(HIST("TofTpcNsigma_before"), KAONS, track.tpcNSigmaKa(), track.tofNSigmaKa(), pt); histos.fill(HIST("TofTpcNsigma_before"), PROTONS, track.tpcNSigmaPr(), track.tofNSigmaPr(), pt); + histos.fill(HIST("TofItsNsigma_before"), PIONS, itsResponse.nSigmaITS(track), track.tofNSigmaPi(), pt); + histos.fill(HIST("TofItsNsigma_before"), KAONS, itsResponse.nSigmaITS(track), track.tofNSigmaKa(), pt); + histos.fill(HIST("TofItsNsigma_before"), PROTONS, itsResponse.nSigmaITS(track), track.tofNSigmaPr(), pt); + bool withinPtPOI = (cfgCutPtPOIMin < pt) && (pt < cfgCutPtPOIMax); // within POI pT range bool withinPtRef = (cfgCutPtMin < pt) && (pt < cfgCutPtMax); // within RF pT range - pidIndex = cfgUseAsymmetricPID ? getNsigmaPIDTpcTofAssymmetric(track) : getNsigmaPIDTpcTof(track); + pidIndex = cfgUseAsymmetricPID ? getNsigmaPIDAssymmetric(track) : getNsigmaPIDTpcTof(track); weff = 1; // Initializing weff for each track // NUA weights From 981ff92a0d9dcbe3f5005a72bf5a58c13ecd5d11 Mon Sep 17 00:00:00 2001 From: hernasab Date: Sat, 14 Jun 2025 09:55:43 -0500 Subject: [PATCH 078/871] [PWGCF] remove obsolete variables (#11614) Co-authored-by: Sabrina Hernandez --- PWGCF/Flow/Tasks/flowZdcTask.cxx | 250 +++++++++++++------------------ 1 file changed, 100 insertions(+), 150 deletions(-) diff --git a/PWGCF/Flow/Tasks/flowZdcTask.cxx b/PWGCF/Flow/Tasks/flowZdcTask.cxx index 18b92bbfff8..3daec8cf2c7 100644 --- a/PWGCF/Flow/Tasks/flowZdcTask.cxx +++ b/PWGCF/Flow/Tasks/flowZdcTask.cxx @@ -189,10 +189,6 @@ struct FlowZdcTask { { // define axes const AxisSpec axisCounter{1, 0, +1, ""}; - const AxisSpec axisQ{100, -1, 1, "Q"}; - const AxisSpec axisQZNA{100, -1, 1, "Q"}; - const AxisSpec axisREQ{100, -1, 1, "real Q"}; - const AxisSpec axisIMQ{100, -1, 1, "imag Q"}; const AxisSpec axisEvent{18, 0.5, 18.5, ""}; const AxisSpec axisZpos{48, -12., 12., "Vtx_{z} (cm)"}; @@ -203,33 +199,15 @@ struct FlowZdcTask { // create histograms histos.add("hEventCounter", "Event counter", kTH1F, {axisEvent}); histos.add("zPos", ";;Entries;", kTH1F, {axisZpos}); - histos.add("etaHistogram", "etaHistogram", kTH1F, {axisEta}); - histos.add("ptHistogram", "ptHistogram", kTH1F, {axisPt}); histos.add("eventCounter", "eventCounter", kTH1F, {axisCounter}); histos.add("centHistogram", "centHistogram", kTH1F, {axisCent}); histos.add("multHistogram", "multHistogram", kTH1F, {axisMultiplicity}); - histos.add("multvsCent", "centrality vs multiplicity", kTH2F, {axisCent, axisMultiplicity}); histos.add("phiHistogram", "phiHistogram", kTH1F, {axisPhi}); - histos.add("TPCmultiplicity", "TPCmultiplicity", kTH1F, {axisMultTpc}); - - histos.add("REqHistogram", "REqHistogram", kTH1F, {axisQ}); - histos.add("IMqHistogram", "IMqHistogram", kTH1F, {axisQ}); - - histos.add("REqHistogramZNA", "REqHistogramZNA", kTH1F, {axisQZNA}); - histos.add("IMqHistogramZNA", "IMqHistogramZNA", kTH1F, {axisQZNA}); - - histos.add("REqHistogramZNC", "REqHistogramZNC", kTH1F, {axisQZNA}); - histos.add("IMqHistogramZNC", "IMqHistogramZNC", kTH1F, {axisQZNA}); - - histos.add("EnergyZNA", "ZNA Sector Energy", kTH1F, {axisEnergy}); - histos.add("EnergyZNC", "ZNC Sector Energy", kTH1F, {axisEnergy}); - histos.add("hCentFT0C", "FT0C Centrality Distribution", kTH1F, {{100, 0, 105}}); histos.add("hZNvsFT0Ccent", "ZN Energy vs FT0C Centrality", kTH2F, {axisCent, axisZN}); - histos.add("hZPvsFT0Ccent", "ZP Energy vs FT0C Centrality;Centrality [%];ZP Energy", kTH2F, @@ -237,7 +215,6 @@ struct FlowZdcTask { histos.add("hNchvsNPV", ";NPVTracks (|#eta|<1);N_{ch} (|#eta|<0.8);", kTH2F, {{{nBinsNch, -0.5, maxNch}, {nBinsNch, -0.5, maxNch}}}); - histos.add("revsimag", "revsimag", kTH2F, {axisREQ, axisIMQ}); // for q vector recentering histos.add("hYield", "Nch vs pT", kTH2F, {axisMultiplicity, axisPt}); histos.add("hGlobalTracks", "hGlobalTracks", kTH1F, {axisMultiplicity}); // event selection steps @@ -268,17 +245,13 @@ struct FlowZdcTask { if (doprocessZdcCollAssoc) { // Check if the process function for ZDCCollAssoc is enabled histos.add("ZNAcoll", "ZNAcoll; ZNA amplitude; Entries", {HistType::kTH1F, {{nBinsAmp, -0.5, maxZn}}}); histos.add("ZNCcoll", "ZNCcoll; ZNC amplitude; Entries", {HistType::kTH1F, {{nBinsAmp, -0.5, maxZn}}}); + histos.add("ZPCcoll", "ZPCcoll; ZPC amplitude; Entries", {HistType::kTH1F, {{nBinsAmp, -0.5, maxZn}}}); + histos.add("ZPAcoll", "ZPAcoll; ZPA amplitude; Entries", {HistType::kTH1F, {{nBinsAmp, -0.5, maxZn}}}); histos.add("ZEM1coll", "ZEM1coll; ZEM1 amplitude; Entries", {HistType::kTH1F, {{nBinsAmp, -0.5, maxZem}}}); histos.add("ZEM2coll", "ZEM2coll; ZEM2 amplitude; Entries", {HistType::kTH1F, {{nBinsAmp, -0.5, maxZem}}}); histos.add("ZNvsZEMcoll", "ZNvsZEMcoll; ZEM; ZNA+ZNC", {HistType::kTH2F, {{{nBinsAmp, -0.5, maxZem}, {nBinsAmp, -0.5, 2. * maxZn}}}}); histos.add("ZNAvsZNCcoll", "ZNAvsZNCcoll; ZNC; ZNA", {HistType::kTH2F, {{{nBinsAmp, -0.5, maxZn}, {nBinsAmp, -0.5, maxZn}}}}); - histos.add("RealQHistogramZNA", "RealQHistogramZNA", kTH1F, {axisQZNA}); - histos.add("ImagQHistogramZNA", "ImagQHistogramZNA", kTH1F, {axisQZNA}); - histos.add("RealQHistogramZNC", "RealQHistogramZNC", kTH1F, {axisQZNA}); - histos.add("ImagQHistogramZNC", "ImagQHistogramZNC", kTH1F, {axisQZNA}); - - histos.add("Acorrelations", "Acorrelations", kTH2F, {{axisQZNA}, {axisQZNA}}); histos.add("SPAngleZNA", "Spectator Plane Angle ZNA;Angle (radians);Entries", {HistType::kTH1F, {{100, -o2::constants::math::PI, o2::constants::math::PI}}}); histos.add("SPAngleZNC", "Spectator Plane Angle ZNC;Angle (radians);Entries", {HistType::kTH1F, {{100, -o2::constants::math::PI, o2::constants::math::PI}}}); @@ -351,15 +324,6 @@ struct FlowZdcTask { histos.add("ZNVsNch", ";#it{N}_{ch} (|#eta|<0.8);ZNA+ZNC;", kTH2F, {{{nBinsNch, minNch, maxNch}, {nBinsZDC, minNch, maxZn}}}); histos.add("ZNDifVsNch", ";#it{N}_{ch} (|#eta|<0.8);ZNA-ZNC;", kTH2F, {{{nBinsNch, minNch, maxNch}, {100, -50., 50.}}}); } - LOG(info) << "\tccdbNoLaterThan=" << ccdbNoLaterThan.value; - LOG(info) << "\tapplyEff=" << applyEff.value; - LOG(info) << "\tpaTH=" << paTH.value; - LOG(info) << "\tuseMidRapNchSel=" << useMidRapNchSel.value; - LOG(info) << "\tpaTHmeanNch=" << paTHmeanNch.value; - LOG(info) << "\tpaTHsigmaNch=" << paTHsigmaNch.value; - LOG(info) << "\tminPt=" << minPt.value; - LOG(info) << "\tmaxPt=" << maxPt.value; - LOG(info) << "\tmaxPtSpectra=" << maxPtSpectra.value; ccdb->setURL("http://alice-ccdb.cern.ch"); // Enabling object caching, otherwise each call goes to the CCDB server @@ -491,6 +455,17 @@ struct FlowZdcTask { float tZPC{zdc.timeZPC()}; float tZDCdif{tZNC + tZPC - tZNA - tZPA}; float tZDCsum{tZNC + tZPC + tZNA + tZPA}; + const double normT0M{(aT0A + aT0C) / 100.}; + float znA = zdc.amplitudeZNA() / cfgCollisionEnergy; + float znC = zdc.amplitudeZNC() / cfgCollisionEnergy; + float zpA = zdc.amplitudeZPA() / cfgCollisionEnergy; + float zpC = zdc.amplitudeZPC() / cfgCollisionEnergy; + float aZEM1{zdc.amplitudeZEM1()}; + float aZEM2{zdc.amplitudeZEM2()}; + float sumZEMs{aZEM1 + aZEM2}; + float tZEM1{zdc.timeZEM1()}; + float tZEM2{zdc.timeZEM2()}; + float sumZNs{znA + znC}; // TDC cut if (isTDCcut) { @@ -500,10 +475,6 @@ struct FlowZdcTask { histos.fill(HIST("hEventCounter"), EvCutLabel::Tdc); } - float aZEM1{zdc.amplitudeZEM1()}; - float aZEM2{zdc.amplitudeZEM2()}; - float sumZEMs{aZEM1 + aZEM2}; - // ZEM cut if (isZEMcut) { if (sumZEMs < zemCut) { @@ -512,29 +483,22 @@ struct FlowZdcTask { histos.fill(HIST("hEventCounter"), EvCutLabel::Zem); } - const double normT0M{(aT0A + aT0C) / 100.}; - float znA = zdc.amplitudeZNA() / cfgCollisionEnergy; - float znC = zdc.amplitudeZNC() / cfgCollisionEnergy; - float zpA = zdc.amplitudeZPA() / cfgCollisionEnergy; - float zpC = zdc.amplitudeZPC() / cfgCollisionEnergy; - - float tZEM1{zdc.timeZEM1()}; - float tZEM2{zdc.timeZEM2()}; - float sumZNs{znA + znC}; - float sumZNC = (zdc.energySectorZNC())[0] + (zdc.energySectorZNC())[1] + (zdc.energySectorZNC())[2] + (zdc.energySectorZNC())[3]; float sumZNA = (zdc.energySectorZNA())[0] + (zdc.energySectorZNA())[1] + (zdc.energySectorZNA())[2] + (zdc.energySectorZNA())[3]; float sumZPC = (zdc.energySectorZPC())[0] + (zdc.energySectorZPC())[1] + (zdc.energySectorZPC())[2] + (zdc.energySectorZPC())[3]; float sumZPA = (zdc.energySectorZPA())[0] + (zdc.energySectorZPA())[1] + (zdc.energySectorZPA())[2] + (zdc.energySectorZPA())[3]; - int itsTracks = 0, glbTracks = 0; float et = 0., meanpt = 0.; + int itsTracks = 0, glbTracks = 0; for (const auto& track : tracks) { - if (track.hasITS() && track.itsNCls() >= minITSnCls) { + if (track.hasITS()) { itsTracks++; } // Track Selection - if (track.isGlobalTrack()) { + if (!track.isGlobalTrack()) { + continue; + } + if ((track.pt() < minPt) || (track.pt() > maxPt)) { continue; } glbTracks++; @@ -637,42 +601,6 @@ struct FlowZdcTask { } } - void processQVector(AodCollisions::iterator const& collision, aod::BCsWithTimestamps const&, AodTracks const& tracks, BCsRun3 const& /*bcs*/, aod::Zdcs const& /*zdcsData*/, aod::ZDCMults const& /*zdcMults*/) - { - if (!isEventSelected(collision)) { - return; - } - histos.fill(HIST("eventCounter"), 0.5); - histos.fill(HIST("centHistogram"), collision.centFT0C()); - const auto& tracksGrouped = tracksIUWithTPC->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); - const int multTPC = tracksGrouped.size(); - const auto cent = collision.centFT0C(); - int globalTracks = tracks.size(); - if (globalTracks < 1) - return; - int nTot{0}; // Tracks are already filtered with GlobalTrack || GlobalTrackSDD - for (const auto& track : tracks) { - nTot++; - histos.fill(HIST("etaHistogram"), track.eta()); - histos.fill(HIST("phiHistogram"), track.phi()); - histos.fill(HIST("ptHistogram"), track.pt()); - } // end track loop 1 - double pT{0}; - for (const auto& track : tracks) { - if (track.tpcNClsCrossedRows() < minTpcNcrossedRows) - continue; - if (std::fabs(track.dcaXY()) > cfgCutDCAxy) - continue; - pT = track.pt(); - pT++; - } // end track loop 2 - histos.fill(HIST("multvsCent"), cent, nTot); - histos.fill(HIST("hYield"), nTot, pT); - histos.fill(HIST("multHistogram"), nTot); - - histos.fill(HIST("TPCmultiplicity"), multTPC); - histos.fill(HIST("hGlobalTracks"), globalTracks); - } void processZdcCollAssoc( AodCollisions::iterator const& collision, AodTracks const& tracks, @@ -683,10 +611,10 @@ struct FlowZdcTask { if (!isEventSelected(collision)) { return; } + const auto& foundBC = collision.foundBC_as(); int nTot = tracks.size(); double ft0aAmp = 0; double ft0cAmp = 0; - const auto& foundBC = collision.foundBC_as(); if (collision.has_foundFT0()) { auto ft0 = collision.foundFT0(); for (const auto& amplitude : ft0.amplitudeA()) { @@ -696,66 +624,89 @@ struct FlowZdcTask { ft0cAmp += amplitude; } } + const double normT0M{(ft0aAmp + ft0aAmp) / 100.}; histos.fill(HIST("hFT0AAmp"), ft0aAmp); - histos.fill(HIST("hFT0CAmp"), ft0cAmp); - double ft0mAmp = ft0aAmp + ft0cAmp; - histos.fill(HIST("hFT0MAmp"), ft0mAmp); - if (foundBC.has_zdc()) { - const auto& zdcread = foundBC.zdc(); - const auto cent = collision.centFT0C(); - - // ZDC data and histogram filling - histos.get(HIST("ZNAcoll"))->Fill(zdcread.amplitudeZNA()); - histos.get(HIST("ZNCcoll"))->Fill(zdcread.amplitudeZNC()); - histos.get(HIST("ZNvsZEMcoll"))->Fill(zdcread.amplitudeZEM1() + zdcread.amplitudeZEM2(), zdcread.amplitudeZNA() + zdcread.amplitudeZNC()); - histos.get(HIST("ZNAvsZNCcoll"))->Fill(zdcread.amplitudeZNC(), zdcread.amplitudeZNA()); - - histos.get(HIST("ZEM1coll"))->Fill(zdcread.amplitudeZEM1()); - histos.get(HIST("ZEM2coll"))->Fill(zdcread.amplitudeZEM2()); - - float sumZNC = (zdcread.energySectorZNC())[0] + (zdcread.energySectorZNC())[1] + (zdcread.energySectorZNC())[2] + (zdcread.energySectorZNC())[3]; - float sumZNA = (zdcread.energySectorZNA())[0] + (zdcread.energySectorZNA())[1] + (zdcread.energySectorZNA())[2] + (zdcread.energySectorZNA())[3]; - float sumZPC = (zdcread.energySectorZPC())[0] + (zdcread.energySectorZPC())[1] + (zdcread.energySectorZPC())[2] + (zdcread.energySectorZPC())[3]; - float sumZPA = (zdcread.energySectorZPA())[0] + (zdcread.energySectorZPA())[1] + (zdcread.energySectorZPA())[2] + (zdcread.energySectorZPA())[3]; - float sumZDC = sumZPA + sumZPC + sumZNA + sumZNC; - float sumZEM = zdcread.amplitudeZEM1() + zdcread.amplitudeZEM2(); - // ZEM cut - if (isZEMcut) { - if (sumZEM < zemCut) { - return; - } + histos.fill(HIST("hFT0CAmp"), ft0aAmp); + histos.fill(HIST("hFT0MAmp"), normT0M); + + if (!foundBC.has_zdc()) { + return; + } + const auto& zdcread = foundBC.zdc(); + const auto cent = collision.centFT0C(); + + // ZDC data and histogram filling + float znA = zdcread.amplitudeZNA(); + float znC = zdcread.amplitudeZNC(); + float zpA = zdcread.amplitudeZPA(); + float zpC = zdcread.amplitudeZPC(); + float tZNA{zdcread.timeZNA()}; + float tZNC{zdcread.timeZNC()}; + float tZPA{zdcread.timeZPA()}; + float tZPC{zdcread.timeZPC()}; + float tZDCdif{tZNC + tZPC - tZNA - tZPA}; + float tZDCsum{tZNC + tZPC + tZNA + tZPA}; + float sumZNC = (zdcread.energySectorZNC())[0] + (zdcread.energySectorZNC())[1] + (zdcread.energySectorZNC())[2] + (zdcread.energySectorZNC())[3]; + float sumZNA = (zdcread.energySectorZNA())[0] + (zdcread.energySectorZNA())[1] + (zdcread.energySectorZNA())[2] + (zdcread.energySectorZNA())[3]; + float sumZPC = (zdcread.energySectorZPC())[0] + (zdcread.energySectorZPC())[1] + (zdcread.energySectorZPC())[2] + (zdcread.energySectorZPC())[3]; + float sumZPA = (zdcread.energySectorZPA())[0] + (zdcread.energySectorZPA())[1] + (zdcread.energySectorZPA())[2] + (zdcread.energySectorZPA())[3]; + float sumZDC = sumZPA + sumZPC + sumZNA + sumZNC; + float sumZEM = zdcread.amplitudeZEM1() + zdcread.amplitudeZEM2(); + znA /= cfgCollisionEnergy; + znC /= cfgCollisionEnergy; + zpA /= cfgCollisionEnergy; + zpC /= cfgCollisionEnergy; + // TDC cut + if (isTDCcut) { + if (std::sqrt(std::pow(tZDCdif, 2.) + std::pow(tZDCsum, 2.)) > tdcCut) { + return; + } + histos.fill(HIST("hEventCounter"), EvCutLabel::Tdc); + } + // ZEM cut + if (isZEMcut) { + if (sumZEM < zemCut) { + return; } - // common energies - float commonSumZnc = (zdcread.energyCommonZNC()); - float commonSumZna = (zdcread.energyCommonZNA()); - float commonSumZpc = (zdcread.energyCommonZPC()); - float commonSumZpa = (zdcread.energyCommonZPA()); - float sumZN = (sumZNC) + (sumZNA); - float sumZP = (sumZPC) + (sumZPA); - - histos.fill(HIST("ZNenergy"), sumZN); - histos.fill(HIST("ZPenergy"), sumZP); - histos.fill(HIST("ZNCenergy"), commonSumZnc); - histos.fill(HIST("ZNAenergy"), commonSumZna); - histos.fill(HIST("ZPAenergy"), commonSumZpa); - histos.fill(HIST("ZPCenergy"), commonSumZpc); - histos.fill(HIST("hZNvsFT0Ccent"), cent, sumZN); - histos.fill(HIST("hZPvsFT0Ccent"), cent, sumZP); - histos.fill(HIST("hZNvsFT0CAmp"), ft0cAmp, sumZN); - histos.fill(HIST("hZPvsFT0CAmp"), ft0cAmp, sumZP); - histos.fill(HIST("hZNvsMult"), nTot, sumZN); - histos.fill(HIST("hZPvsMult"), nTot, sumZP); - histos.fill(HIST("hNchvsNPV"), collision.multNTracksPVeta1(), nTot); - - float ratioZN = sumZNC / sumZNA; - float ratioZP = sumZPC / sumZPA; - pZNratiovscent->Fill(cent, ratioZN); - pZPratiovscent->Fill(cent, ratioZP); - pZNvsFT0Ccent->Fill(cent, sumZN); - pZPvsFT0Ccent->Fill(cent, sumZP); - - histos.get(HIST("ZDC_energy_vs_ZEM"))->Fill(sumZEM, sumZDC); } + // common energies + float commonSumZnc = (zdcread.energyCommonZNC()); + float commonSumZna = (zdcread.energyCommonZNA()); + float commonSumZpc = (zdcread.energyCommonZPC()); + float commonSumZpa = (zdcread.energyCommonZPA()); + float sumZN = (sumZNC) + (sumZNA); + float sumZP = (sumZPC) + (sumZPA); + histos.fill(HIST("zPos"), collision.posZ()); + histos.fill(HIST("T0Ccent"), collision.centFT0C()); + histos.fill(HIST("ZNAcoll"), znA); + histos.fill(HIST("ZNCcoll"), znC); + histos.fill(HIST("ZPAcoll"), zpA); + histos.fill(HIST("ZPCcoll"), zpC); + histos.get(HIST("ZNvsZEMcoll"))->Fill(zdcread.amplitudeZEM1() + zdcread.amplitudeZEM2(), zdcread.amplitudeZNA() + zdcread.amplitudeZNC()); + histos.get(HIST("ZNAvsZNCcoll"))->Fill(zdcread.amplitudeZNC(), zdcread.amplitudeZNA()); + histos.get(HIST("ZEM1coll"))->Fill(zdcread.amplitudeZEM1()); + histos.get(HIST("ZEM2coll"))->Fill(zdcread.amplitudeZEM2()); + histos.fill(HIST("ZNenergy"), sumZN); + histos.fill(HIST("ZPenergy"), sumZP); + histos.fill(HIST("ZNCenergy"), commonSumZnc); + histos.fill(HIST("ZNAenergy"), commonSumZna); + histos.fill(HIST("ZPAenergy"), commonSumZpa); + histos.fill(HIST("ZPCenergy"), commonSumZpc); + histos.fill(HIST("hZNvsFT0Ccent"), cent, sumZN); + histos.fill(HIST("hZPvsFT0Ccent"), cent, sumZP); + histos.fill(HIST("hZNvsFT0CAmp"), ft0cAmp, sumZN); + histos.fill(HIST("hZPvsFT0CAmp"), ft0cAmp, sumZP); + histos.fill(HIST("hZNvsMult"), nTot, sumZN); + histos.fill(HIST("hZPvsMult"), nTot, sumZP); + histos.fill(HIST("hNchvsNPV"), collision.multNTracksPVeta1(), nTot); + + float ratioZN = sumZNC / sumZNA; + float ratioZP = sumZPC / sumZPA; + pZNratiovscent->Fill(cent, ratioZN); + pZPratiovscent->Fill(cent, ratioZP); + pZNvsFT0Ccent->Fill(cent, sumZN); + pZPvsFT0Ccent->Fill(cent, sumZP); + histos.get(HIST("ZDC_energy_vs_ZEM"))->Fill(sumZEM, sumZDC); } void processCorrelation(CollisionDataTable::iterator const& collision, FilTrackDataTable const& tracks) @@ -779,7 +730,6 @@ struct FlowZdcTask { PROCESS_SWITCH(FlowZdcTask, processZdcCollAssoc, "Processing ZDC w. collision association", true); PROCESS_SWITCH(FlowZdcTask, processQA, "Process QA", true); - PROCESS_SWITCH(FlowZdcTask, processQVector, "Process before recentering", true); PROCESS_SWITCH(FlowZdcTask, processCorrelation, "Process correlations", true); }; // end of struct function From 7ba64f63897987e898d0b42425999c5955036814 Mon Sep 17 00:00:00 2001 From: ddobrigk Date: Sun, 15 Jun 2025 10:43:27 +0200 Subject: [PATCH 079/871] [Common] Change index column identifier (#11622) --- Common/DataModel/Multiplicity.h | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/Common/DataModel/Multiplicity.h b/Common/DataModel/Multiplicity.h index 864e2a9cd1c..0ac2a0074c6 100644 --- a/Common/DataModel/Multiplicity.h +++ b/Common/DataModel/Multiplicity.h @@ -8,6 +8,11 @@ // 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 Multiplicity.h +/// \brief multiplicity tables +/// \author ALICE + #ifndef COMMON_DATAMODEL_MULTIPLICITY_H_ #define COMMON_DATAMODEL_MULTIPLICITY_H_ @@ -184,14 +189,9 @@ DECLARE_SOA_TABLE_VERSIONED(MultMCExtras_001, "AOD", "MULTMCEXTRA", 1, //! Table mult::IsInelGt1, o2::soa::Marker<1>); -DECLARE_SOA_TABLE(MultHepMCHIs, "AOD", "MULTHEPMCHI", //! complementary table for heavy-ion mc info (subset of HepMCHeavyIons) - o2::soa::Index<>, hepmcheavyion::McCollisionId, hepmcheavyion::NcollHard, hepmcheavyion::NpartProj, hepmcheavyion::NpartTarg, - hepmcheavyion::Ncoll, hepmcheavyion::ImpactParameter); - using MultMCExtras = MultMCExtras_001; using MultMCExtra = MultMCExtras::iterator; using MultsExtraMC = MultMCExtras; // for backwards compatibility with previous naming scheme -using MultHepMCHI = MultHepMCHIs::iterator; // crosslinks namespace mult @@ -202,6 +202,12 @@ DECLARE_SOA_INDEX_COLUMN(MultMCExtra, multMCExtra); DECLARE_SOA_TABLE(Mult2MCExtras, "AOD", "Mult2MCEXTRA", //! Relate reco mult entry to MC extras entry o2::soa::Index<>, mult::MultMCExtraId); +DECLARE_SOA_TABLE(MultHepMCHIs, "AOD", "MULTHEPMCHI", //! complementary table for heavy-ion mc info (subset of HepMCHeavyIons) + o2::soa::Index<>, mult::MultMCExtraId, hepmcheavyion::NcollHard, hepmcheavyion::NpartProj, hepmcheavyion::NpartTarg, + hepmcheavyion::Ncoll, hepmcheavyion::ImpactParameter); + +using MultHepMCHI = MultHepMCHIs::iterator; + namespace multZeq { DECLARE_SOA_COLUMN(MultZeqFV0A, multZeqFV0A, float); //! Multiplicity equalized for the vertex position with the FV0A detector From 1e539435884fccaa13a52317093d3012549d7a69 Mon Sep 17 00:00:00 2001 From: Roman Lietava Date: Sun, 15 Jun 2025 10:45:20 +0200 Subject: [PATCH 080/871] [PWGLF,Trigger] Omegamult: added toi mask (#11619) --- EventFiltering/Zorro.h | 8 ++++- PWGLF/DataModel/LFNonPromptCascadeTables.h | 13 ++++--- PWGLF/Tasks/Strangeness/nonPromptCascade.cxx | 38 ++++++++++++++------ 3 files changed, 44 insertions(+), 15 deletions(-) diff --git a/EventFiltering/Zorro.h b/EventFiltering/Zorro.h index c818e45ce48..16da5d578ca 100644 --- a/EventFiltering/Zorro.h +++ b/EventFiltering/Zorro.h @@ -9,7 +9,12 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. // -// Zero Obstacles Results Retriever for Offline trigger selections + +/// +/// \file Zorro.h +/// \brief Zero Obstacles Results Retriever for Offline trigger selections +/// \author M Puccio +/// #ifndef EVENTFILTERING_ZORRO_H_ #define EVENTFILTERING_ZORRO_H_ @@ -54,6 +59,7 @@ class Zorro std::vector getTOIcounters() const { return mTOIcounts; } std::vector getTriggerOfInterestResults(uint64_t bcGlobalId, uint64_t tolerance = 100); std::vector getTriggerOfInterestResults() const; + int getNTOIs() const { return mTOIs.size(); } void setCCDBpath(std::string path) { mBaseCCDBPath = path; } void setBaseCCDBPath(std::string path) { mBaseCCDBPath = path; } diff --git a/PWGLF/DataModel/LFNonPromptCascadeTables.h b/PWGLF/DataModel/LFNonPromptCascadeTables.h index 177167d5997..a4e15df33ef 100644 --- a/PWGLF/DataModel/LFNonPromptCascadeTables.h +++ b/PWGLF/DataModel/LFNonPromptCascadeTables.h @@ -119,6 +119,7 @@ DECLARE_SOA_COLUMN(MultFT0M, multFT0M, float); DECLARE_SOA_COLUMN(CentFT0C, centFT0C, float); DECLARE_SOA_COLUMN(CentFT0A, centFT0A, float); DECLARE_SOA_COLUMN(CentFT0M, centFT0M, float); +DECLARE_SOA_COLUMN(ToiMask, toiMask, uint32_t); } // namespace NPCascadeTable DECLARE_SOA_TABLE(NPCascTable, "AOD", "NPCASCTABLE", @@ -183,7 +184,8 @@ DECLARE_SOA_TABLE(NPCascTable, "AOD", "NPCASCTABLE", NPCascadeTable::MultFT0M, NPCascadeTable::CentFT0C, NPCascadeTable::CentFT0A, - NPCascadeTable::CentFT0M) + NPCascadeTable::CentFT0M, + NPCascadeTable::ToiMask) DECLARE_SOA_TABLE(NPCascTableNT, "AOD", "NPCASCTABLENT", NPCascadeTable::MatchingChi2, @@ -247,7 +249,8 @@ DECLARE_SOA_TABLE(NPCascTableNT, "AOD", "NPCASCTABLENT", NPCascadeTable::MultFT0M, NPCascadeTable::CentFT0C, NPCascadeTable::CentFT0A, - NPCascadeTable::CentFT0M) + NPCascadeTable::CentFT0M, + NPCascadeTable::ToiMask) DECLARE_SOA_TABLE(NPCascTableMC, "AOD", "NPCASCTABLEMC", NPCascadeTable::MatchingChi2, @@ -330,7 +333,8 @@ DECLARE_SOA_TABLE(NPCascTableMC, "AOD", "NPCASCTABLEMC", NPCascadeTable::DCAzMC, NPCascadeTable::MCcollisionMatch, NPCascadeTable::HasFakeReassociation, - NPCascadeTable::MotherDecayDaughters) + NPCascadeTable::MotherDecayDaughters, + NPCascadeTable::ToiMask) DECLARE_SOA_TABLE(NPCascTableMCNT, "AOD", "NPCASCTABLEMCNT", NPCascadeTable::MatchingChi2, @@ -413,7 +417,8 @@ DECLARE_SOA_TABLE(NPCascTableMCNT, "AOD", "NPCASCTABLEMCNT", NPCascadeTable::DCAzMC, NPCascadeTable::MCcollisionMatch, NPCascadeTable::HasFakeReassociation, - NPCascadeTable::MotherDecayDaughters) + NPCascadeTable::MotherDecayDaughters, + NPCascadeTable::ToiMask) DECLARE_SOA_TABLE(NPCascTableGen, "AOD", "NPCASCTABLEGen", NPCascadeTable::gPt, diff --git a/PWGLF/Tasks/Strangeness/nonPromptCascade.cxx b/PWGLF/Tasks/Strangeness/nonPromptCascade.cxx index c5388c034a2..bb2960e745b 100644 --- a/PWGLF/Tasks/Strangeness/nonPromptCascade.cxx +++ b/PWGLF/Tasks/Strangeness/nonPromptCascade.cxx @@ -125,6 +125,7 @@ struct NPCascCandidate { float centFT0C; float centFT0A; float centFT0M; + uint32_t toiMask; }; std::array isFromHF(auto& particle) { @@ -287,7 +288,7 @@ struct NonPromptCascadeTask { return true; } - void zorroAccounting(const auto& collisions) + void zorroAccounting(const auto& collisions, auto& toiMap) { if (cfgSkimmedProcessing) { int runNumber{-1}; @@ -295,15 +296,26 @@ struct NonPromptCascadeTask { auto bc = coll.template bc_as(); if (runNumber != bc.runNumber()) { mZorro.initCCDB(mCCDB.service, bc.runNumber(), bc.timestamp(), cfgTriggersOfInterest.value); + if (mZorro.getNTOIs() > 32) { + LOG(fatal) << "N TOIs:" << mZorro.getNTOIs() << " Max 32 TOIs possible."; + } mZorro.populateHistRegistry(mRegistry, bc.runNumber()); runNumber = bc.runNumber(); } - mZorro.isSelected(bc.globalBC()); /// Just let Zorro do the accounting + bool sel = mZorro.isSelected(bc.globalBC()); /// Just let Zorro do the accounting + if (sel) { + std::vector toivect = mZorro.getTriggerOfInterestResults(); + uint32_t toiMask = 0; + for (size_t i{0}; i < toivect.size(); i++) { + toiMask += toivect[i] << i; + } + toiMap[bc.globalBC()] = toiMask; + } } } } template - void fillCandidatesVector(CollisionType const&, TrackType const& tracks, auto const& cascades, auto& candidates) + void fillCandidatesVector(CollisionType const&, TrackType const& tracks, auto const& cascades, auto& candidates, std::map toiMap = {}) { const auto& getCascade = [](auto const& candidate) { @@ -507,6 +519,10 @@ struct NonPromptCascadeTask { } else { o2::base::Propagator::Instance()->propagateToDCA(primaryVertex, ntCascadeTrack, mBz, 2.f, matCorr, &motherDCA); } + uint32_t toiMask = 0x0; + if (toiMap.count(bc.globalBC())) { + toiMask = toiMap[bc.globalBC()]; + } candidates.emplace_back(NPCascCandidate{mcParticleID, trackedCascGlobalIndex, itsTrackGlobalIndex, candidate.collisionId(), matchingChi2, deltaPtITSCascade, deltaPtCascade, cascITSclsSize, hasReassociatedClusters, hasFakeReassociation, isGoodMatch, isGoodCascade, pdgCodeMom, itsTrackPDG, fromHF[0], fromHF[1], collision.numContrib(), cascPVContribs, collision.collisionTimeRes(), primaryVertex.getX(), primaryVertex.getY(), primaryVertex.getZ(), cascadeLvector.pt(), cascadeLvector.eta(), cascadeLvector.phi(), @@ -517,7 +533,7 @@ struct NonPromptCascadeTask { cascITSclusters, protonTrack.itsNCls(), pionTrack.itsNCls(), bachelor.itsNCls(), protonTrack.tpcNClsFound(), pionTrack.tpcNClsFound(), bachelor.tpcNClsFound(), protonTrack.tpcNSigmaPr(), pionTrack.tpcNSigmaPi(), bachelor.tpcNSigmaKa(), bachelor.tpcNSigmaPi(), protonTrack.hasTOF(), pionTrack.hasTOF(), bachelor.hasTOF(), - protonTrack.tofNSigmaPr(), pionTrack.tofNSigmaPi(), bachelor.tofNSigmaKa(), bachelor.tofNSigmaPi(), collision.sel8(), collision.multFT0C(), collision.multFT0A(), collision.multFT0M(), collision.centFT0C(), collision.centFT0A(), collision.centFT0M()}); + protonTrack.tofNSigmaPr(), pionTrack.tofNSigmaPi(), bachelor.tofNSigmaKa(), bachelor.tofNSigmaPi(), collision.sel8(), collision.multFT0C(), collision.multFT0A(), collision.multFT0M(), collision.centFT0C(), collision.centFT0A(), collision.centFT0M(), toiMask}); } } @@ -537,7 +553,7 @@ struct NonPromptCascadeTask { c.protonTPCNSigma, c.pionTPCNSigma, c.bachKaonTPCNSigma, c.bachPionTPCNSigma, c.protonHasTOF, c.pionHasTOF, c.bachHasTOF, c.protonTOFNSigma, c.pionTOFNSigma, c.bachKaonTOFNSigma, c.bachPionTOFNSigma, - c.sel8, c.multFT0C, c.multFT0A, c.multFT0M, c.centFT0C, c.centFT0A, c.centFT0M); + c.sel8, c.multFT0C, c.multFT0A, c.multFT0M, c.centFT0C, c.centFT0A, c.centFT0M, c.toiMask); } } @@ -576,7 +592,7 @@ struct NonPromptCascadeTask { c.sel8, c.multFT0C, c.multFT0A, c.multFT0M, c.centFT0C, c.centFT0A, c.centFT0M, particle.pt(), particle.eta(), particle.phi(), mcCollision.posX(), mcCollision.posY(), mcCollision.posZ(), particle.pdgCode(), mcCollision.posX() - particle.vx(), mcCollision.posY() - particle.vy(), - mcCollision.posZ() - particle.vz(), mcCollision.globalIndex() == recCollision.mcCollisionId(), c.hasFakeReassociation, motherDecayDaughters); + mcCollision.posZ() - particle.vz(), mcCollision.globalIndex() == recCollision.mcCollisionId(), c.hasFakeReassociation, motherDecayDaughters, c.toiMask); } } @@ -653,8 +669,9 @@ struct NonPromptCascadeTask { aod::V0s const& /*v0s*/, TracksExtData const& tracks, aod::BCsWithTimestamps const&) { - zorroAccounting(collisions); - fillCandidatesVector(collisions, tracks, trackedCascades, gCandidates); + std::map toiMap; + zorroAccounting(collisions, toiMap); + fillCandidatesVector(collisions, tracks, trackedCascades, gCandidates, toiMap); fillDataTable(gCandidates); } PROCESS_SWITCH(NonPromptCascadeTask, processTrackedCascadesData, "process cascades from strangeness tracking: Data analysis", false); @@ -663,8 +680,9 @@ struct NonPromptCascadeTask { aod::V0s const& /*v0s*/, TracksExtData const& tracks, aod::BCsWithTimestamps const&) { - zorroAccounting(collisions); - fillCandidatesVector(collisions, tracks, cascades, gCandidatesNT); + std::map toiMap; + zorroAccounting(collisions, toiMap); + fillCandidatesVector(collisions, tracks, cascades, gCandidatesNT, toiMap); fillDataTable(gCandidatesNT); } PROCESS_SWITCH(NonPromptCascadeTask, processCascadesData, "process cascades: Data analysis", false); From d2584ac35e03f651dc4ff24625c03aa834ab81fd Mon Sep 17 00:00:00 2001 From: mherzer <96999709+mherzer28@users.noreply.github.com> Date: Sun, 15 Jun 2025 14:22:04 +0200 Subject: [PATCH 081/871] [PWGLF] add tof flag, detector map and cfg for its cluster size cut (#11623) Co-authored-by: ALICE Action Bot --- PWGLF/TableProducer/Nuspex/trHeAnalysis.cxx | 65 ++++++++++++++------- 1 file changed, 43 insertions(+), 22 deletions(-) diff --git a/PWGLF/TableProducer/Nuspex/trHeAnalysis.cxx b/PWGLF/TableProducer/Nuspex/trHeAnalysis.cxx index f00fc314870..40378ba6df4 100644 --- a/PWGLF/TableProducer/Nuspex/trHeAnalysis.cxx +++ b/PWGLF/TableProducer/Nuspex/trHeAnalysis.cxx @@ -61,6 +61,8 @@ DECLARE_SOA_COLUMN(TTpcChi2NCl, tTpcChi2NCl, float); DECLARE_SOA_COLUMN(TItsChi2NCl, tItsChi2NCl, float); DECLARE_SOA_COLUMN(TRigidity, tRigidity, float); DECLARE_SOA_COLUMN(TItsClusterSize, tItsClusterSize, float); +DECLARE_SOA_COLUMN(THasTof, tHasTof, bool); +DECLARE_SOA_COLUMN(TDetectorMap, tDetectorMap, int8_t); } // namespace h3_data DECLARE_SOA_TABLE(H3Data, "AOD", "h3_data", h3_data::TPt, h3_data::TEta, h3_data::TPhi, h3_data::TCharge, h3_data::TH3DeDx, @@ -69,7 +71,7 @@ DECLARE_SOA_TABLE(H3Data, "AOD", "h3_data", h3_data::TPt, h3_data::TEta, h3_data::TSigmaZ, h3_data::TnTpcCluster, h3_data::TnItsCluster, h3_data::TTpcChi2NCl, h3_data::TItsChi2NCl, h3_data::TRigidity, - h3_data::TItsClusterSize); + h3_data::TItsClusterSize, h3_data::THasTof, h3_data::TDetectorMap); namespace he_data { DECLARE_SOA_COLUMN(TPt, tPt, float); @@ -91,6 +93,8 @@ DECLARE_SOA_COLUMN(TTpcChi2NCl, tTpcChi2NCl, float); DECLARE_SOA_COLUMN(TItsChi2NCl, tItsChi2NCl, float); DECLARE_SOA_COLUMN(TRigidity, tRigidity, float); DECLARE_SOA_COLUMN(TItsClusterSize, tItsClusterSize, float); +DECLARE_SOA_COLUMN(THasTof, tHasTof, bool); +DECLARE_SOA_COLUMN(TDetectorMap, tDetectorMap, int8_t); } // namespace he_data DECLARE_SOA_TABLE(HeData, "AOD", "he_data", he_data::TPt, he_data::TEta, he_data::TPhi, he_data::TCharge, he_data::THeDeDx, @@ -99,7 +103,7 @@ DECLARE_SOA_TABLE(HeData, "AOD", "he_data", he_data::TPt, he_data::TEta, he_data::TSigmaZ, he_data::TnTpcCluster, he_data::TnItsCluster, he_data::TTpcChi2NCl, he_data::TItsChi2NCl, he_data::TRigidity, - he_data::TItsClusterSize); + he_data::TItsClusterSize, he_data::THasTof, he_data::TDetectorMap); } // namespace o2::aod namespace { @@ -189,6 +193,7 @@ struct TrHeAnalysis { Configurable cfgTPCPidMethod{"cfgTPCPidMethod", false, "Using own or built in bethe parametrization"}; // false for built in Configurable cfgMassMethod{"cfgMassMethod", 0, "0: Using built in 1: mass calculated with beta 2: mass calculated with the event time"}; + Configurable cfgEnableItsClusterSizeCut{"cfgEnableItsClusterSizeCut", false, "Enable ITS cluster size cut"}; // Set the multiplity event limits Configurable cfgLowMultCut{"cfgLowMultCut", 0.0f, "Accepted multiplicity percentage lower limit"}; Configurable cfgHighMultCut{"cfgHighMultCut", 100.0f, "Accepted multiplicity percentage higher limit"}; @@ -387,10 +392,12 @@ struct TrHeAnalysis { histos.fill(HIST("histogram/cuts"), 7); continue; } - if (getMeanItsClsSize(track) / std::cosh(track.eta()) <= cfgCutMinItsClusterSizeH3 || - getMeanItsClsSize(track) / std::cosh(track.eta()) >= cfgCutMaxItsClusterSizeH3) { - histos.fill(HIST("histogram/cuts"), 12); - continue; + if (cfgEnableItsClusterSizeCut) { + if (getMeanItsClsSize(track) / std::cosh(track.eta()) <= cfgCutMinItsClusterSizeHe || + getMeanItsClsSize(track) / std::cosh(track.eta()) >= cfgCutMaxItsClusterSizeHe) { + histos.fill(HIST("histogram/cuts"), 12); + continue; + } } if (getMass(track) < cfgCutMinTofMassH3 || getMass(track) > cfgCutMaxTofMassH3) { histos.fill(HIST("histogram/cuts"), 13); @@ -421,10 +428,12 @@ struct TrHeAnalysis { float tRigidity = getRigidity(track); float tItsClusterSize = getMeanItsClsSize(track) / std::cosh(track.eta()); + bool tHasTof = track.hasTOF(); + int8_t tDetectorMap = track.detectorMap(); h3Data(tPt, tEta, tPhi, tCharge, tH3DeDx, tnSigmaTpc, tTofSignalH3, tDcaXY, tDcaZ, tSigmaYX, tSigmaXYZ, tSigmaZ, tnTpcCluster, tnItsCluster, tTpcChi2NCl, tItsChi2NCl, tRigidity, - tItsClusterSize); + tItsClusterSize, tHasTof, tDetectorMap); } } if (enableHe && heRapCut) { @@ -438,10 +447,12 @@ struct TrHeAnalysis { histos.fill(HIST("histogram/cuts"), 7); continue; } - if (getMeanItsClsSize(track) / std::cosh(track.eta()) <= cfgCutMinItsClusterSizeHe || - getMeanItsClsSize(track) / std::cosh(track.eta()) >= cfgCutMaxItsClusterSizeHe) { - histos.fill(HIST("histogram/cuts"), 12); - continue; + if (cfgEnableItsClusterSizeCut) { + if (getMeanItsClsSize(track) / std::cosh(track.eta()) <= cfgCutMinItsClusterSizeHe || + getMeanItsClsSize(track) / std::cosh(track.eta()) >= cfgCutMaxItsClusterSizeHe) { + histos.fill(HIST("histogram/cuts"), 12); + continue; + } } histos.fill(HIST("histogram/He/He-TPCsignVsTPCmomentum"), getRigidity(track) * track.sign(), @@ -468,10 +479,12 @@ struct TrHeAnalysis { float tRigidity = getRigidity(track); float tItsClusterSize = getMeanItsClsSize(track) / std::cosh(track.eta()); + bool tHasTof = track.hasTOF(); + int8_t tDetectorMap = track.detectorMap(); heData(tPt, tEta, tPhi, tCharge, tHeDeDx, tnSigmaTpc, tTofSignalHe, tDcaXY, tDcaZ, tSigmaYX, tSigmaXYZ, tSigmaZ, tnTpcCluster, tnItsCluster, tTpcChi2NCl, tItsChi2NCl, tRigidity, - tItsClusterSize); + tItsClusterSize, tHasTof, tDetectorMap); } } } @@ -542,10 +555,12 @@ struct TrHeAnalysis { histos.fill(HIST("histogram/cuts"), 7); continue; } - if (getMeanItsClsSize(track) / std::cosh(track.eta()) <= cfgCutMinItsClusterSizeH3 || - getMeanItsClsSize(track) / std::cosh(track.eta()) >= cfgCutMaxItsClusterSizeH3) { - histos.fill(HIST("histogram/cuts"), 12); - continue; + if (cfgEnableItsClusterSizeCut) { + if (getMeanItsClsSize(track) / std::cosh(track.eta()) <= cfgCutMinItsClusterSizeH3 || + getMeanItsClsSize(track) / std::cosh(track.eta()) >= cfgCutMaxItsClusterSizeH3) { + histos.fill(HIST("histogram/cuts"), 12); + continue; + } } if (getMass(track) < cfgCutMinTofMassH3 || getMass(track) > cfgCutMaxTofMassH3) { histos.fill(HIST("histogram/cuts"), 13); @@ -576,10 +591,12 @@ struct TrHeAnalysis { float tRigidity = getRigidity(track); float tItsClusterSize = getMeanItsClsSize(track) / std::cosh(track.eta()); + bool tHasTof = track.hasTOF(); + int8_t tDetectorMap = track.detectorMap(); h3Data(tPt, tEta, tPhi, tCharge, tH3DeDx, tnSigmaTpc, tTofSignalH3, tDcaXY, tDcaZ, tSigmaYX, tSigmaXYZ, tSigmaZ, tnTpcCluster, tnItsCluster, tTpcChi2NCl, tItsChi2NCl, tRigidity, - tItsClusterSize); + tItsClusterSize, tHasTof, tDetectorMap); } } if (enableHe && heRapCut) { @@ -592,10 +609,12 @@ struct TrHeAnalysis { histos.fill(HIST("histogram/cuts"), 7); continue; } - if (getMeanItsClsSize(track) / std::cosh(track.eta()) <= cfgCutMinItsClusterSizeHe || - getMeanItsClsSize(track) / std::cosh(track.eta()) >= cfgCutMaxItsClusterSizeHe) { - histos.fill(HIST("histogram/cuts"), 12); - continue; + if (cfgEnableItsClusterSizeCut) { + if (getMeanItsClsSize(track) / std::cosh(track.eta()) <= cfgCutMinItsClusterSizeHe || + getMeanItsClsSize(track) / std::cosh(track.eta()) >= cfgCutMaxItsClusterSizeHe) { + histos.fill(HIST("histogram/cuts"), 12); + continue; + } } histos.fill(HIST("histogram/He/He-TPCsignVsTPCmomentum"), getRigidity(track) * track.sign(), @@ -622,10 +641,12 @@ struct TrHeAnalysis { float tRigidity = getRigidity(track); float tItsClusterSize = getMeanItsClsSize(track) / std::cosh(track.eta()); + bool tHasTof = track.hasTOF(); + int8_t tDetectorMap = track.detectorMap(); heData(tPt, tEta, tPhi, tCharge, tHeDeDx, tnSigmaTpc, tTofSignalHe, tDcaXY, tDcaZ, tSigmaYX, tSigmaXYZ, tSigmaZ, tnTpcCluster, tnItsCluster, tTpcChi2NCl, tItsChi2NCl, tRigidity, - tItsClusterSize); + tItsClusterSize, tHasTof, tDetectorMap); } } } From 86764b3040f78648821c813f7deb8735896d0836 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADt=20Ku=C4=8Dera?= Date: Sun, 15 Jun 2025 20:22:55 +0200 Subject: [PATCH 082/871] [Infrastructure] Configure naming conventions in clang-tidy (#11616) --- .clang-tidy | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/.clang-tidy b/.clang-tidy index da768906bcc..490b82a880b 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -1,3 +1,23 @@ CheckOptions: - - key: CheckPathRegex - value: '.*/O2/.*' + - { key: CheckPathRegex, value: ".*/O2/.*" } + # Naming conventions + - { key: readability-identifier-naming.ClassCase, value: CamelCase } + - { key: readability-identifier-naming.ClassMemberPrefix, value: m } + - { key: readability-identifier-naming.ConceptCase, value: CamelCase } + - { key: readability-identifier-naming.ConstexprVariableCase, value: CamelCase } + - { key: readability-identifier-naming.ConstexprVariableIgnoredRegexp, value: "^k[A-Z].*$" } # Allow "k" prefix. + - { key: readability-identifier-naming.EnumCase, value: CamelCase } + - { key: readability-identifier-naming.EnumConstantCase, value: CamelCase } + - { key: readability-identifier-naming.EnumConstantIgnoredRegexp, value: "^k[A-Z].*$" } # Allow "k" prefix. + - { key: readability-identifier-naming.FunctionCase, value: camelBack } + - { key: readability-identifier-naming.MacroDefinitionCase, value: UPPER_CASE } + - { key: readability-identifier-naming.MacroDefinitionIgnoredRegexp, value: "^[A-Z]+(_[A-Z]+)*_$" } # Allow the trailing underscore in header guards. + - { key: readability-identifier-naming.MemberCase, value: camelBack } + - { key: readability-identifier-naming.NamespaceCase, value: lower_case } + - { key: readability-identifier-naming.ParameterCase, value: camelBack } + - { key: readability-identifier-naming.StructCase, value: CamelCase } + - { key: readability-identifier-naming.TemplateParameterCase, value: CamelCase } + - { key: readability-identifier-naming.TypeAliasCase, value: CamelCase } + - { key: readability-identifier-naming.TypedefCase, value: CamelCase } + - { key: readability-identifier-naming.TypeTemplateParameterCase, value: CamelCase } + - { key: readability-identifier-naming.VariableCase, value: camelBack } From 64f092eed6629278f7036c9bf0770b8963e770e0 Mon Sep 17 00:00:00 2001 From: Anisa Khatun Date: Sun, 15 Jun 2025 20:52:38 +0200 Subject: [PATCH 083/871] [PWGUD] Fixing partition issue in udQC tasks (#11626) Co-authored-by: akhatun --- PWGUD/AQC/udQC.cxx | 4 +++- PWGUD/AQC/udQCmidRap.cxx | 12 +++++++----- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/PWGUD/AQC/udQC.cxx b/PWGUD/AQC/udQC.cxx index ddaf01338df..3da67d1f683 100644 --- a/PWGUD/AQC/udQC.cxx +++ b/PWGUD/AQC/udQC.cxx @@ -69,6 +69,8 @@ struct UDQC { using ATs = aod::AmbiguousTracks; using AFTs = aod::AmbiguousFwdTracks; + Partition goodTracks = requireGlobalTrackInFilter(); + void init(InitContext& context) { // initialize global variables @@ -220,7 +222,7 @@ struct UDQC { // vertex tracks normally gives PV contributors from collisions registry.get(HIST("collisions/vtxTracks"))->Fill(collision.numContrib()); // global tracks - Partition goodTracks = requireGlobalTrackInFilter(); + // Partition goodTracks = requireGlobalTrackInFilter(); goodTracks.bindTable(tracks); registry.get(HIST("collisions/globalTracks"))->Fill(goodTracks.size()); diff --git a/PWGUD/AQC/udQCmidRap.cxx b/PWGUD/AQC/udQCmidRap.cxx index e7178cfa042..acb35f21f57 100644 --- a/PWGUD/AQC/udQCmidRap.cxx +++ b/PWGUD/AQC/udQCmidRap.cxx @@ -64,6 +64,8 @@ struct UDQCmid { using ATs = aod::AmbiguousTracks; using AFTs = aod::AmbiguousFwdTracks; + Partition goodTracks = requireGlobalTrackInFilter(); + void init(InitContext& context) { // initialize global variables @@ -132,7 +134,7 @@ struct UDQCmid { } } - // ............................................................................................................................................... + //............................................................................................................................................... void processMain(CC const& collision, BCs const& bct0s, TCs const& tracks, FWs const& fwdtracks, ATs const& /*ambtracks*/, AFTs const& /*ambfwdtracks*/, aod::FT0s const& /*ft0s*/, aod::FV0As const& /*fv0as*/, aod::FDDs const& /*fdds*/, @@ -150,7 +152,7 @@ struct UDQCmid { // vertex tracks normally gives PV contributors from collisions registry.get(HIST("collisions/vtxTracks"))->Fill(collision.numContrib()); // global tracks - Partition goodTracks = requireGlobalTrackInFilter(); + goodTracks.bindTable(tracks); registry.get(HIST("collisions/globalTracks"))->Fill(goodTracks.size()); @@ -223,7 +225,7 @@ struct UDQCmid { registry.get(HIST("DG/hMassAll"))->Fill(ivm.M()); } } // coll - } // dgcand + } // dgcand // loop over all tracks float rgtrwTOF = 0.; @@ -322,7 +324,7 @@ struct UDQCmid { if (track.hasTOF()) { registry.get(HIST("DG/dEdxTOF"))->Fill(track.p() / track.sign(), track.beta()); } // fill TOF - } // pv contributor + } // pv contributor } } // Inavariant mass after FIT @@ -489,7 +491,7 @@ struct UDQCmid { // update #PV contributors in collisions with empty FT0 && FV0&& FDCC registry.get(HIST("fpPVC2"))->Fill(collision.numContrib(), 1.); } // fdd - } // fvo + } // fvo } // ft0 } From 5dd26ffca941d1f10b279118a3403f069b7778f9 Mon Sep 17 00:00:00 2001 From: Francesco Mazzaschi <43742195+fmazzasc@users.noreply.github.com> Date: Sun, 15 Jun 2025 22:06:58 +0200 Subject: [PATCH 084/871] [Infrastructure] Update LF Codeowners (#11624) Co-authored-by: Francesco Mazzaschi --- CODEOWNERS | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/CODEOWNERS b/CODEOWNERS index 3891598e0e8..6116f8c8a5b 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -41,13 +41,14 @@ /PWGHF @alibuild @vkucera @fcolamar @fgrosa @fcatalan92 @mfaggin @mmazzilli @deepathoms @NicoleBastid @hahassan7 @jpxrk @apalasciano @zhangbiao-phy @gluparel # PWG-LF /PWGLF @alibuild @sustripathy @skundu692 -/PWGLF/Tasks/GlobalEventProperties @alibuild @sustripathy @skundu692 @gbencedi @abmodak @omvazque +/PWGLF/DataModel @alibuild @sustripathy @skundu692 @gbencedi @abmodak @fmazzasc @maciacco @dmallick2 @smaff92 @ercolessi @romainschotter +/PWGLF/Tasks/GlobalEventProperties @alibuild @sustripathy @skundu692 @gbencedi @abmodak @omvazque /PWGLF/TableProducer/GlobalEventProperties @alibuild @sustripathy @skundu692 @gbencedi @abmodak @omvazque -/PWGLF/Tasks/Nuspex @alibuild @sustripathy @skundu692 @fmazzasc @chiarapinto @maciacco -/PWGLF/TableProducer/Nuspex @alibuild @sustripathy @skundu692 @fmazzasc @chiarapinto @maciacco -/PWGLF/Tasks/Resonances @alibuild @sustripathy @skundu692 @dmallick2 @smaff92 +/PWGLF/Tasks/Nuspex @alibuild @sustripathy @skundu692 @fmazzasc @maciacco +/PWGLF/TableProducer/Nuspex @alibuild @sustripathy @skundu692 @fmazzasc @maciacco +/PWGLF/Tasks/Resonances @alibuild @sustripathy @skundu692 @dmallick2 @smaff92 /PWGLF/TableProducer/Resonances @alibuild @sustripathy @skundu692 @dmallick2 @smaff92 -/PWGLF/Tasks/Strangeness @alibuild @sustripathy @skundu692 @ercolessi @romainschotter +/PWGLF/Tasks/Strangeness @alibuild @sustripathy @skundu692 @ercolessi @romainschotter /PWGLF/TableProducer/Strangeness @alibuild @sustripathy @skundu692 @ercolessi @romainschotter # PWG-MM From 2942a58a7beec4621d16012d7ed70db8eb2b8d60 Mon Sep 17 00:00:00 2001 From: yuanzhe <90246048+wang-yuanzhe@users.noreply.github.com> Date: Mon, 16 Jun 2025 09:08:50 +0200 Subject: [PATCH 085/871] [PWGLF] Add qa while both mother and daughter tracks found (#11586) --- .../Nuspex/hyperhelium4sigmaRecoTask.cxx | 424 ++++++++++-------- 1 file changed, 234 insertions(+), 190 deletions(-) diff --git a/PWGLF/TableProducer/Nuspex/hyperhelium4sigmaRecoTask.cxx b/PWGLF/TableProducer/Nuspex/hyperhelium4sigmaRecoTask.cxx index 9f700dd8405..3215e5578d4 100644 --- a/PWGLF/TableProducer/Nuspex/hyperhelium4sigmaRecoTask.cxx +++ b/PWGLF/TableProducer/Nuspex/hyperhelium4sigmaRecoTask.cxx @@ -13,29 +13,31 @@ /// \brief QA and analysis task for hyper-helium4sigma (He4S) /// \author Yuanzhe Wang -#include -#include -#include -#include +#include "PWGLF/DataModel/LFHyperhelium4sigmaTables.h" +#include "PWGLF/DataModel/LFKinkDecayTables.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.h" -#include "ReconstructionDataFormats/Track.h" #include "Common/Core/RecoDecay.h" #include "Common/Core/trackUtilities.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/PIDResponse.h" -#include "CommonConstants/PhysicsConstants.h" -#include "PWGLF/DataModel/LFKinkDecayTables.h" -#include "PWGLF/DataModel/LFHyperhelium4sigmaTables.h" +#include "Common/DataModel/PIDResponseITS.h" -#include "DetectorsBase/Propagator.h" -#include "DetectorsBase/GeometryManager.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DataFormatsParameters/GRPMagField.h" #include "CCDB/BasicCCDBManager.h" +#include "CommonConstants/PhysicsConstants.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "DataFormatsParameters/GRPObject.h" +#include "DetectorsBase/GeometryManager.h" +#include "DetectorsBase/Propagator.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" +#include "ReconstructionDataFormats/Track.h" + +#include +#include +#include +#include using namespace o2; using namespace o2::framework; @@ -46,30 +48,48 @@ using MCLabeledCollisionsFull = soa::Join; using MCLabeledTracksIU = soa::Join; +enum Channel { + k2body = 0, // helium4, pion0 + k3body_p, // triton, proton, pion0 + k3body_n, // triton, neutron, pion+ + kNDecayChannel +}; + +enum DaughterType { + kDauAlpha = 0, + kDauTriton, + kDauProton, + kDauChargedPion, + kDauNeutron, + kDauPion0, + kNDaughterType, + kNChargedDaughterType = kDauNeutron +}; + namespace { -constexpr float BzLowerLimit = -990.f; -constexpr std::array LayerRadii{2.33959f, 3.14076f, 3.91924f, 19.6213f, 24.5597f, 34.388f, 39.3329f}; +// constexpr std::array LayerRadii{2.33959f, 3.14076f, 3.91924f, 19.6213f, 24.5597f, 34.388f, 39.3329f}; constexpr int kITSLayers = 7; constexpr int kITSInnerBarrelLayers = 3; // constexpr int kITSOuterBarrelLayers = 4; +constexpr std::array kDaughterPDG = { + o2::constants::physics::Pdg::kAlpha, + o2::constants::physics::Pdg::kTriton, + PDG_t::kProton, + PDG_t::kPiPlus, + PDG_t::kNeutron, + PDG_t::kPi0}; + std::shared_ptr hMotherCounter; std::shared_ptr hMother2BCounter; -std::shared_ptr hDauAlphaCounter; -std::shared_ptr hDauTritonCounter; -std::shared_ptr hDauProtonCounter; -std::shared_ptr hDauPionCounter; +std::shared_ptr hDauCounter[kNChargedDaughterType]; +std::shared_ptr hDauTPCNSigma[kNChargedDaughterType]; +std::shared_ptr hRecoMotherCounter; +std::shared_ptr hRecoDauAlphaCounter; } // namespace //-------------------------------------------------------------- // Check the decay channel of hyperhelium4sigma -enum Channel { - k2body = 0, // helium4, pion0 - k3body_p, // triton, proton, pion0 - k3body_n, // triton, neutron, pion+ - kNDecayChannel -}; - template Channel getDecayChannelHe4S(TMCParticle const& particle, std::vector& list) { @@ -77,7 +97,7 @@ Channel getDecayChannelHe4S(TMCParticle const& particle, std::vector& list) return kNDecayChannel; } - // list: charged, charged or empty, neutral + // list: charged (alpha or triton), charged or empty, neutral list.clear(); list.resize(3, -1); @@ -179,6 +199,31 @@ void setTrackIDForMC(std::vector& mcPartIndices, aod::McParticles const } } +//-------------------------------------------------------------- +// get TPCNSigma for daughter track +template +float getTPCNSigma(const TTrack& track, const int daughterType) +{ + float nSigma = -999.f; + switch (daughterType) { + case kDauAlpha: + nSigma = track.tpcNSigmaAl(); + break; + case kDauTriton: + nSigma = track.tpcNSigmaTr(); + break; + case kDauProton: + nSigma = track.tpcNSigmaPr(); + break; + case kDauChargedPion: + nSigma = track.tpcNSigmaPi(); + break; + default: + break; + } + return nSigma; +} + //-------------------------------------------------------------- struct Hyphe4sCandidate { @@ -248,12 +293,12 @@ struct Hyperhelium4sigmaRecoTask { void init(InitContext const&) { // Axes - const AxisSpec vertexZAxis{100, -15., 15., "vrtx_{Z} [cm]"}; + const AxisSpec vertexZAxis{100, -15., 15., "vtx_{Z} [cm]"}; const AxisSpec ptAxis{50, -10, 10, "#it{p}_{T} (GeV/#it{c})"}; const AxisSpec nSigmaAxis{120, -6.f, 6.f, "n#sigma_{#alpha}"}; const AxisSpec massAxis{100, 3.85, 4.25, "m (GeV/#it{c}^{2})"}; - const AxisSpec diffPtAxis{200, -10.f, 10.f, "#Delta p_{T} (GeV/#it{c})"}; - const AxisSpec diffPzAxis{200, -10.f, 10.f, "#Delta p_{z} (GeV/#it{c})"}; + const AxisSpec diffPtAxis{200, -10.f, 10.f, "#Delta #it{p}_{T} (GeV/#it{c})"}; + const AxisSpec diffPzAxis{200, -10.f, 10.f, "#Delta #it{p}_{z} (GeV/#it{c})"}; const AxisSpec radiusAxis{40, 0.f, 40.f, "R (cm)"}; registry.add("hEventCounter", "hEventCounter", HistType::kTH1F, {{2, 0, 2}}); @@ -265,8 +310,11 @@ struct Hyperhelium4sigmaRecoTask { registry.add("hDiffSVx", ";#Delta x (cm);", HistType::kTH1F, {{200, -10, 10}}); registry.add("hDiffSVy", ";#Delta y (cm);", HistType::kTH1F, {{200, -10, 10}}); registry.add("hDiffSVz", ";#Delta z (cm);", HistType::kTH1F, {{200, -10, 10}}); - registry.add("h2TrueMotherDiffPtVsRecSVR", ";Reconstruced SV R (cm);#Delta p_{T} (GeV/#it{c});", HistType::kTH2F, {radiusAxis, diffPtAxis}); - registry.add("h2TrueMotherDiffPzVsRecSVR", ";Reconstruced SV R (cm);#Delta p_{z} (GeV/#it{c});", HistType::kTH2F, {radiusAxis, diffPzAxis}); + registry.add("h2RecSVRVsTrueSVR", ";Reconstruced SV R (cm);True SV R (cm);", HistType::kTH2F, {radiusAxis, radiusAxis}); + registry.add("h2TrueMotherDiffPtVsRecSVR", ";Reconstruced SV R (cm);#Delta #it{p}_{T} (GeV/#it{c});", HistType::kTH2F, {radiusAxis, diffPtAxis}); + registry.add("h2TrueMotherDiffPzVsRecSVR", ";Reconstruced SV R (cm);#Delta #it{p}_{z} (GeV/#it{c});", HistType::kTH2F, {radiusAxis, diffPzAxis}); + registry.add("h2TrueMotherDiffTglVsRecSVR", ";Reconstruced SV R (cm);#Delta tan#lambda;", HistType::kTH2F, {radiusAxis, {200, -1.f, 1.f}}); + registry.add("h2TrueMotherDiffEtaVsRecSVR", ";Reconstruced SV R (cm);#Delta #eta;", HistType::kTH2F, {radiusAxis, {200, -1.f, 1.f}}); registry.add("hDiffDauPx", ";#Delta p_{x} (GeV/#it{c}); ", HistType::kTH1D, {{200, -10, 10}}); registry.add("hDiffDauPy", ";#Delta p_{y} (GeV/#it{c}); ", HistType::kTH1D, {{200, -10, 10}}); registry.add("hDiffDauPz", ";#Delta p_{z} (GeV/#it{c}); ", HistType::kTH1D, {{200, -10, 10}}); @@ -275,6 +323,11 @@ struct Hyperhelium4sigmaRecoTask { registry.add("hDCAXYMothToRecSV", "hDCAXYMothToRecSV", HistType::kTH1F, {{200, -10, 10}}); registry.add("hDCAZMothToRecSV", "hDCAZMothToRecSV", HistType::kTH1F, {{200, -10, 10}}); + + registry.add("h2TrueMotherDiffPtVsKinkAngle", ";cos(#theta);#Delta p_{T} / p_{T};", HistType::kTH2F, {{100, 0.8f, 1.f}, {100, -5.f, 5.f}}); + registry.add("h2TrueMotherDiffPtVsKinkAngleSV", ";cos(#theta);#Delta p_{T} / p_{T};", HistType::kTH2F, {{100, 0.8f, 1.f}, {100, -5.f, 5.f}}); + registry.add("h2TrueMotherDiffPtVsKinkAngleXY", ";cos(#theta);#Delta p_{T} / p_{T};", HistType::kTH2F, {{100, 0.8f, 1.f}, {100, -5.f, 5.f}}); + registry.add("h2TrueMotherDiffPtVsKinkAngleXYSV", ";cos(#theta);#Delta p_{T} / p_{T};", HistType::kTH2F, {{100, 0.8f, 1.f}, {100, -5.f, 5.f}}); } registry.add("h2MassHyperhelium4sigmaPt", "h2MassHyperhelium4sigmaPt", HistType::kTH2F, {{ptAxis, massAxis}}); @@ -287,40 +340,20 @@ struct Hyperhelium4sigmaRecoTask { lut = o2::base::MatLayerCylSet::rectifyPtrFromFile(ccdb->get(lutPath)); } - void initCCDB(aod::BCsWithTimestamps::iterator const& bc) + void initCCDB(aod::BCs::iterator const& bc) { if (mRunNumber == bc.runNumber()) { return; } - auto timestamp = bc.timestamp(); + mRunNumber = bc.runNumber(); + LOG(info) << "Initializing CCDB for run " << mRunNumber; + o2::parameters::GRPMagField* grpmag = ccdb->getForRun(grpmagPath, mRunNumber); + o2::base::Propagator::initFieldFromGRP(grpmag); + mBz = grpmag->getNominalL3Field(); - o2::parameters::GRPObject* grpo = ccdb->getForTimeStamp(grpPath, timestamp); - o2::parameters::GRPMagField* grpmag = 0x0; - if (grpo) { - o2::base::Propagator::initFieldFromGRP(grpo); - if (inputBz < BzLowerLimit) { - // Fetch magnetic field from ccdb for current collision - mBz = grpo->getNominalL3Field(); - LOG(info) << "Retrieved GRP for timestamp " << timestamp << " with magnetic field of " << mBz << " kZG"; - } else { - mBz = inputBz; - } - } else { - grpmag = ccdb->getForTimeStamp(grpmagPath, timestamp); - if (!grpmag) { - LOG(fatal) << "Got nullptr from CCDB for path " << grpmagPath << " of object GRPMagField and " << grpPath << " of object GRPObject for timestamp " << timestamp; - } - o2::base::Propagator::initFieldFromGRP(grpmag); - if (inputBz < BzLowerLimit) { - // Fetch magnetic field from ccdb for current collision - mBz = std::lround(5.f * grpmag->getL3Current() / 30000.f); - LOG(info) << "Retrieved GRP for timestamp " << timestamp << " with magnetic field of " << mBz << " kZG"; - } else { - mBz = inputBz; - } + if (!lut) { + lut = o2::base::MatLayerCylSet::rectifyPtrFromFile(ccdb->get(lutPath)); } - - mRunNumber = bc.runNumber(); o2::base::Propagator::Instance()->setMatLUT(lut); LOG(info) << "Task initialized for run " << mRunNumber << " with magnetic field " << mBz << " kZG"; } @@ -421,7 +454,7 @@ struct Hyperhelium4sigmaRecoTask { } PROCESS_SWITCH(Hyperhelium4sigmaRecoTask, processData, "process data", true); - void processMC(MCLabeledCollisionsFull const& collisions, aod::KinkCands const& KinkCands, MCLabeledTracksIU const& tracks, aod::McParticles const& particlesMC, aod::McCollisions const& mcCollisions, aod::BCsWithTimestamps const&) + void processMC(MCLabeledCollisionsFull const& collisions, aod::KinkCands const& KinkCands, MCLabeledTracksIU const& tracks, aod::McParticles const& particlesMC, aod::McCollisions const& mcCollisions, aod::BCs const&) { mcHe4sIndices.clear(); std::vector mcPartIndices; @@ -492,8 +525,11 @@ struct Hyperhelium4sigmaRecoTask { registry.fill(HIST("hDiffSVx"), kinkCand.xDecVtx() - mcDauTrack.vx()); registry.fill(HIST("hDiffSVy"), kinkCand.yDecVtx() - mcDauTrack.vy()); registry.fill(HIST("hDiffSVz"), kinkCand.zDecVtx() - mcDauTrack.vz()); + registry.fill(HIST("h2RecSVRVsTrueSVR"), recSVR, std::hypot(mcDauTrack.vx(), mcDauTrack.vy())); registry.fill(HIST("h2TrueMotherDiffPtVsRecSVR"), recSVR, mcMotherTrack.pt() - kinkCand.ptMoth()); registry.fill(HIST("h2TrueMotherDiffPzVsRecSVR"), recSVR, mcMotherTrack.pz() - kinkCand.pzMoth()); + registry.fill(HIST("h2TrueMotherDiffTglVsRecSVR"), recSVR, mcMotherTrack.pz() / mcMotherTrack.pt() - motherTrack.tgl()); + registry.fill(HIST("h2TrueMotherDiffEtaVsRecSVR"), recSVR, mcMotherTrack.eta() - motherTrack.eta()); registry.fill(HIST("hDiffDauPx"), kinkCand.pxDaug() - mcDauTrack.px()); registry.fill(HIST("hDiffDauPy"), kinkCand.pyDaug() - mcDauTrack.py()); registry.fill(HIST("hDiffDauPz"), kinkCand.pzDaug() - mcDauTrack.pz()); @@ -507,13 +543,34 @@ struct Hyperhelium4sigmaRecoTask { fillCandidateMCInfo(hyphe4sCand, mcMotherTrack, mcDauTrack); mcHe4sIndices.push_back(mcMotherTrack.globalIndex()); - auto bc = collision.bc_as(); + auto bc = collision.bc_as(); initCCDB(bc); std::array dcaInfo; auto mcMotherTrackPar = getTrackParFromMC(mcMotherTrack); o2::base::Propagator::Instance()->propagateToDCABxByBz({kinkCand.xDecVtx(), kinkCand.yDecVtx(), kinkCand.zDecVtx()}, mcMotherTrackPar, 2.f, matCorr, &dcaInfo); registry.fill(HIST("hDCAXYMothToRecSV"), dcaInfo[0]); registry.fill(HIST("hDCAZMothToRecSV"), dcaInfo[1]); + + float spKink = kinkCand.pxMoth() * kinkCand.pxDaug() + kinkCand.pyMoth() * kinkCand.pyDaug() + kinkCand.pzMoth() * kinkCand.pzDaug(); + float sptKink = kinkCand.pxMoth() * kinkCand.pxDaug() + kinkCand.pyMoth() * kinkCand.pyDaug(); + float pMoth = std::hypot(kinkCand.pxMoth(), kinkCand.pyMoth(), kinkCand.pzMoth()); + float pDaug = std::hypot(kinkCand.pxDaug(), kinkCand.pyDaug(), kinkCand.pzDaug()); + + float pMothDirVector[3] = {kinkCand.xDecVtx() - collision.posX(), kinkCand.yDecVtx() - collision.posY(), kinkCand.zDecVtx() - collision.posZ()}; + float epMothDirVector = std::hypot(pMothDirVector[0], pMothDirVector[1], pMothDirVector[2]); + float eptMothDirVector = std::hypot(pMothDirVector[0], pMothDirVector[1]); + float spKinkSV = pMothDirVector[0] * kinkCand.pxDaug() + pMothDirVector[1] * kinkCand.pyDaug() + pMothDirVector[2] * kinkCand.pzDaug(); + float sptKinkSV = pMothDirVector[0] * kinkCand.pxDaug() + pMothDirVector[1] * kinkCand.pyDaug(); + + float kinkAngle = spKink / (pMoth * pDaug); + float kinkAngleSV = spKinkSV / (epMothDirVector * pDaug); + float kinkAngleXY = sptKink / (kinkCand.ptMoth() * kinkCand.ptDaug()); + float kinkAngleXYSV = sptKinkSV / (eptMothDirVector * kinkCand.ptDaug()); + + registry.fill(HIST("h2TrueMotherDiffPtVsKinkAngle"), kinkAngle, (mcMotherTrack.pt() - kinkCand.ptMoth()) / kinkCand.ptMoth()); + registry.fill(HIST("h2TrueMotherDiffPtVsKinkAngleSV"), kinkAngleSV, (mcMotherTrack.pt() - kinkCand.ptMoth()) / kinkCand.ptMoth()); + registry.fill(HIST("h2TrueMotherDiffPtVsKinkAngleXY"), kinkAngleXY, (mcMotherTrack.pt() - kinkCand.ptMoth()) / kinkCand.ptMoth()); + registry.fill(HIST("h2TrueMotherDiffPtVsKinkAngleXYSV"), kinkAngleXYSV, (mcMotherTrack.pt() - kinkCand.ptMoth()) / kinkCand.ptMoth()); } outputMCTable( @@ -582,9 +639,14 @@ struct Hyperhelium4sigmaQa { ConfigurableAxis invMassBins{"invMassBins", {100, 3.85f, 4.15f}, "Binning for invariant mass (GeV/#it{c}^{2})"}; ConfigurableAxis radiusBins{"radiusBins", {40, 0.f, 40.f}, "Binning for radius in xy plane (cm)"}; + o2::aod::ITSResponse itsResponse; + void init(InitContext&) { if (doprocessMC == true) { + itsResponse.setMCDefaultParameters(); + + const AxisSpec pAxis{ptBins, "#it{p} (GeV/#it{c})"}; const AxisSpec ptAxis{ptBins, "#it{p}_{T} (GeV/#it{c})"}; const AxisSpec ctAxis{ctBins, "c#it{t} (cm)"}; const AxisSpec rigidityAxis{rigidityBins, "p/z (GeV/#it{c})"}; @@ -619,7 +681,7 @@ struct Hyperhelium4sigmaQa { hEvtSelectedHyperHelium4SigmaCounter->GetXaxis()->SetBinLabel(1, "Generated"); hEvtSelectedHyperHelium4SigmaCounter->GetXaxis()->SetBinLabel(2, "Survived"); - genQAHist.add("hGenHyperHelium4SigmaP", "", HistType::kTH1F, {ptAxis}); + genQAHist.add("hGenHyperHelium4SigmaP", "", HistType::kTH1F, {pAxis}); genQAHist.add("hGenHyperHelium4SigmaPt", "", HistType::kTH1F, {ptAxis}); genQAHist.add("hGenHyperHelium4SigmaCt", "", HistType::kTH1F, {ctAxis}); genQAHist.add("hMcRecoInvMass", "", HistType::kTH1F, {invMassAxis}); @@ -638,37 +700,41 @@ struct Hyperhelium4sigmaQa { hist->GetXaxis()->SetBinLabel(8, "ITS chi2"); hist->GetXaxis()->SetBinLabel(9, "pt"); } - recoQAHist.add("h2TrueMotherSVRVsRLastITS", ";ITS R (cm); Decay Vertex R (cm);", HistType::kTH2F, {itsRadiusAxis, svRadiuAxis}); - recoQAHist.add("h2GoodMotherSVRVsRLastITS", ";ITS R (cm); Decay Vertex R (cm);", HistType::kTH2F, {itsRadiusAxis, svRadiuAxis}); - recoQAHist.add("h2TrueMotherDiffPtVsDiffR", ";#Delta R (cm);#Delta p_{T} (GeV/#it{c});", HistType::kTH2F, {{80, -40.f, 40.f}, diffPtAxis}); - recoQAHist.add("h2GoodMotherDiffPtVsDiffR", ";#Delta R (cm);#Delta p_{T} (GeV/#it{c});", HistType::kTH2F, {{80, -40.f, 40.f}, diffPtAxis}); recoQAHist.add("h2TrueMotherDiffPtVsTrueSVR", ";Decay Vertex R (cm);#Delta p_{T} (GeV/#it{c});", HistType::kTH2F, {svRadiuAxis, diffPtAxis}); recoQAHist.add("h2TrueMotherDiffPzVsTrueSVR", ";Decay Vertex R (cm);#Delta p_{z} (GeV/#it{c});", HistType::kTH2F, {svRadiuAxis, diffPzAxis}); + recoQAHist.add("h2TrueMotherDiffTglVsTrueSVR", ";Decay Vertex R (cm);#Delta tgl;", HistType::kTH2F, {svRadiuAxis, {200, -1.f, 1.f}}); + recoQAHist.add("h2TrueMotherDiffEtaVsTrueSVR", ";Decay Vertex R (cm);#Delta #eta;", HistType::kTH2F, {svRadiuAxis, {200, -1.f, 1.f}}); recoQAHist.add("h2GoodMotherDiffPtVsTrueSVR", ";Decay Vertex R (cm);#Delta p_{T} (GeV/#it{c});", HistType::kTH2F, {svRadiuAxis, diffPtAxis}); recoQAHist.add("h2GoodMotherDiffPzVsTrueSVR", ";Decay Vertex R (cm);#Delta p_{z} (GeV/#it{c});", HistType::kTH2F, {svRadiuAxis, diffPzAxis}); - recoQAHist.add("h2TrueMotherDiffPtVsRLastITS", ";ITS R (cm);#Delta p_{T} (GeV/#it{c});", HistType::kTH2F, {itsRadiusAxis, diffPtAxis}); - recoQAHist.add("h2TrueMotherDiffPzVsRLastITS", ";ITS R (cm);#Delta p_{z} (GeV/#it{c});", HistType::kTH2F, {itsRadiusAxis, diffPzAxis}); - recoQAHist.add("h2GoodMotherDiffPtVsRLastITS", ";ITS R (cm);#Delta p_{T} (GeV/#it{c});", HistType::kTH2F, {itsRadiusAxis, diffPtAxis}); - recoQAHist.add("h2GoodMotherDiffPzVsRLastITS", ";ITS R (cm);#Delta p_{z} (GeV/#it{c});", HistType::kTH2F, {itsRadiusAxis, diffPzAxis}); - - hDauAlphaCounter = recoQAHist.add("hDauAlphaCounter", "", HistType::kTH1F, {{7, 0.f, 7.f}}); - hDauTritonCounter = recoQAHist.add("hDauTritonCounter", "", HistType::kTH1F, {{7, 0.f, 7.f}}); - hDauProtonCounter = recoQAHist.add("hDauProtonCounter", "", HistType::kTH1F, {{7, 0.f, 7.f}}); - hDauPionCounter = recoQAHist.add("hDauPionCounter", "", HistType::kTH1F, {{7, 0.f, 7.f}}); - for (const auto& hist : {hDauAlphaCounter, hDauTritonCounter, hDauProtonCounter, hDauPionCounter}) { + + hDauCounter[kDauAlpha] = recoQAHist.add("hDauAlphaCounter", "", HistType::kTH1F, {{9, 0.f, 9.f}}); + hDauCounter[kDauTriton] = recoQAHist.add("hDauTritonCounter", "", HistType::kTH1F, {{9, 0.f, 9.f}}); + hDauCounter[kDauProton] = recoQAHist.add("hDauProtonCounter", "", HistType::kTH1F, {{9, 0.f, 9.f}}); + hDauCounter[kDauChargedPion] = recoQAHist.add("hDauPionCounter", "", HistType::kTH1F, {{9, 0.f, 9.f}}); + hDauTPCNSigma[kDauAlpha] = recoQAHist.add("hDauAlphaTPCNSigma", "", HistType::kTH2F, {rigidityAxis, nsigmaAxis}); + hDauTPCNSigma[kDauTriton] = recoQAHist.add("hDauTritonTPCNSigma", "", HistType::kTH2F, {rigidityAxis, nsigmaAxis}); + hDauTPCNSigma[kDauProton] = recoQAHist.add("hDauProtonTPCNSigma", "", HistType::kTH2F, {rigidityAxis, nsigmaAxis}); + hDauTPCNSigma[kDauChargedPion] = recoQAHist.add("hDauPionTPCNSigma", "", HistType::kTH2F, {rigidityAxis, nsigmaAxis}); + + hRecoMotherCounter = recoQAHist.add("hRecoMotherCounter", "", HistType::kTH1F, {{9, 0.f, 9.f}}); + hRecoDauAlphaCounter = recoQAHist.add("hRecoDauAlphaCounter", "", HistType::kTH1F, {{9, 0.f, 9.f}}); + for (const auto& hist : {hDauCounter[kDauAlpha], hDauCounter[kDauTriton], hDauCounter[kDauProton], hDauCounter[kDauChargedPion], hRecoMotherCounter, hRecoDauAlphaCounter}) { hist->GetXaxis()->SetBinLabel(1, "Generated"); hist->GetXaxis()->SetBinLabel(2, "Reconstructed"); hist->GetXaxis()->SetBinLabel(3, "eta"); - hist->GetXaxis()->SetBinLabel(4, "has ITS && TPC"); - hist->GetXaxis()->SetBinLabel(5, "ITS quality"); - hist->GetXaxis()->SetBinLabel(6, "TPC n#sigma"); - hist->GetXaxis()->SetBinLabel(7, "has TOF"); + hist->GetXaxis()->SetBinLabel(4, "has ITS&TPC"); + hist->GetXaxis()->SetBinLabel(5, "TPC crossed rows"); + hist->GetXaxis()->SetBinLabel(6, "TPC Ncls"); + hist->GetXaxis()->SetBinLabel(7, "TPC n#sigma"); + hist->GetXaxis()->SetBinLabel(8, "ITS hits"); + hist->GetXaxis()->SetBinLabel(9, "has TOF)"); } - recoQAHist.add("hDauAlphaTPCNSigma", "", HistType::kTH2F, {rigidityAxis, nsigmaAxis}); - recoQAHist.add("hDauTritonTPCNSigma", "", HistType::kTH2F, {rigidityAxis, nsigmaAxis}); - recoQAHist.add("hDauProtonTPCNSigma", "", HistType::kTH2F, {rigidityAxis, nsigmaAxis}); - recoQAHist.add("hDauPionTPCNSigma", "", HistType::kTH2F, {rigidityAxis, nsigmaAxis}); + recoQAHist.add("hMotherIsPVContributer", "", HistType::kTH1F, {{2, 0.f, 2.f}}); + recoQAHist.add("hDauAlphaIsPVContributer", "", HistType::kTH1F, {{2, 0.f, 2.f}}); + recoQAHist.add("hDauAlphaPVsITSNSigma", "", HistType::kTH2F, {pAxis, nsigmaAxis}); + recoQAHist.add("h2BCandDauAlphaPVsITSNSigma", "", HistType::kTH2F, {pAxis, nsigmaAxis}); + recoQAHist.add("hReco2BCandidateCount", "", HistType::kTH1F, {{4, 0.f, 4.f}}); } } @@ -732,34 +798,46 @@ struct Hyperhelium4sigmaQa { // qa for daughter track selection template - void daughterTrackCheck(const TTrack& track, const std::shared_ptr hist, float tpcNSigma) + bool daughterTrackCheck(const TTrack& track, const std::shared_ptr hist, float tpcNSigma) { hist->Fill(1); if (std::abs(track.eta()) > etaMax) { - return; + return false; } hist->Fill(2); if (!track.hasITS() || !track.hasTPC()) { - return; + return false; } hist->Fill(3); - if (track.itsNClsInnerBarrel() != 0 && track.itsNCls() > kITSInnerBarrelLayers && track.tpcNClsCrossedRows() <= minRatioTPCNCls * track.tpcNClsFindable() && track.tpcNClsFound() <= nTPCClusMinDaug) { - return; + if (track.tpcNClsCrossedRows() <= minRatioTPCNCls * track.tpcNClsFindable()) { + return false; } hist->Fill(4); - if (std::abs(tpcNSigma) > tpcPidNsigmaCut) { - return; + if (track.tpcNClsFound() <= nTPCClusMinDaug) { + return false; } hist->Fill(5); - if (track.hasTOF()) { - return; + if (std::abs(tpcNSigma) > tpcPidNsigmaCut) { + return false; } hist->Fill(6); + + if (track.itsNClsInnerBarrel() != 0 || track.itsNCls() > kITSInnerBarrelLayers) { + return false; + } + hist->Fill(7); + + if (track.hasTOF()) { + return false; + } + hist->Fill(8); + + return true; } void processData(o2::aod::Collisions const&) @@ -768,7 +846,7 @@ struct Hyperhelium4sigmaQa { } PROCESS_SWITCH(Hyperhelium4sigmaQa, processData, "process data", true); - void processMC(aod::McCollisions const& mcCollisions, aod::McParticles const& particlesMC, o2::soa::Join const& collisions, MCLabeledTracksIU const& tracks) + void processMC(aod::McCollisions const& mcCollisions, aod::McParticles const& particlesMC, MCLabeledCollisionsFull const& collisions, MCLabeledTracksIU const& tracks, aod::BCs const&) { std::vector mcPartIndices; setTrackIDForMC(mcPartIndices, particlesMC, tracks); @@ -830,81 +908,33 @@ struct Hyperhelium4sigmaQa { } float svPos[3] = {-999, -999, -999}; - float dauAlphaMom[3] = {-999, -999, -999}; - float dauTritonMom[3] = {-999, -999, -999}; - float dauProtonMom[3] = {-999, -999, -999}; - float dauNeuteronMom[3] = {-999, -999, -999}; - float dauChargedPionMom[3] = {-999, -999, -999}; - float dauPion0Mom[3] = {-999, -999, -999}; + std::vector> dauMom(kNDaughterType, std::vector(3, -999.0f)); for (const auto& mcparticleDaughter : mcparticle.daughters_as()) { - if (std::abs(mcparticleDaughter.pdgCode()) == o2::constants::physics::Pdg::kAlpha) { - dauAlphaMom[0] = mcparticleDaughter.px(); - dauAlphaMom[1] = mcparticleDaughter.py(); - dauAlphaMom[2] = mcparticleDaughter.pz(); - - // get SV position for 2body decay - svPos[0] = mcparticleDaughter.vx(); - svPos[1] = mcparticleDaughter.vy(); - svPos[2] = mcparticleDaughter.vz(); - - recoQAHist.fill(HIST("hDauAlphaCounter"), 0); - if (mcPartIndices[mcparticleDaughter.globalIndex()] != -1) { - auto track = tracks.rawIteratorAt(mcPartIndices[mcparticleDaughter.globalIndex()]); - daughterTrackCheck(track, hDauAlphaCounter, track.tpcNSigmaAl()); - if (track.hasTPC()) { - recoQAHist.fill(HIST("hDauAlphaTPCNSigma"), track.p() * track.sign(), track.tpcNSigmaAl()); - } - } - } else if (std::abs(mcparticleDaughter.pdgCode()) == o2::constants::physics::Pdg::kTriton) { - dauTritonMom[0] = mcparticleDaughter.px(); - dauTritonMom[1] = mcparticleDaughter.py(); - dauTritonMom[2] = mcparticleDaughter.pz(); - - // get SV position for 3body decay - svPos[0] = mcparticleDaughter.vx(); - svPos[1] = mcparticleDaughter.vy(); - svPos[2] = mcparticleDaughter.vz(); - - recoQAHist.fill(HIST("hDauTritonCounter"), 0); - if (mcPartIndices[mcparticleDaughter.globalIndex()] != -1) { - auto track = tracks.rawIteratorAt(mcPartIndices[mcparticleDaughter.globalIndex()]); - daughterTrackCheck(track, hDauTritonCounter, track.tpcNSigmaTr()); - if (track.hasTPC()) { - recoQAHist.fill(HIST("hDauTritonTPCNSigma"), track.p() * track.sign(), track.tpcNSigmaTr()); + for (int type = 0; type < kNDaughterType; type++) { + if (std::abs(mcparticleDaughter.pdgCode()) == kDaughterPDG[type]) { + dauMom[type][0] = mcparticleDaughter.px(); + dauMom[type][1] = mcparticleDaughter.py(); + dauMom[type][2] = mcparticleDaughter.pz(); + + if (type <= kDauTriton) { + svPos[0] = mcparticleDaughter.vx(); + svPos[1] = mcparticleDaughter.vy(); + svPos[2] = mcparticleDaughter.vz(); } - } - } else if (std::abs(mcparticleDaughter.pdgCode()) == PDG_t::kProton) { - dauProtonMom[0] = mcparticleDaughter.px(); - dauProtonMom[1] = mcparticleDaughter.py(); - dauProtonMom[2] = mcparticleDaughter.pz(); - - recoQAHist.fill(HIST("hDauProtonCounter"), 0); - if (mcPartIndices[mcparticleDaughter.globalIndex()] != -1) { - auto track = tracks.rawIteratorAt(mcPartIndices[mcparticleDaughter.globalIndex()]); - daughterTrackCheck(track, hDauProtonCounter, track.tpcNSigmaPr()); - if (track.hasTPC()) { - recoQAHist.fill(HIST("hDauProtonTPCNSigma"), track.p() * track.sign(), track.tpcNSigmaPr()); + + if (type < kNChargedDaughterType) { + hDauCounter[type]->Fill(0.f); + // if daughter track is reconstructed + if (type <= kNChargedDaughterType && mcPartIndices[mcparticleDaughter.globalIndex()] != -1) { + auto track = tracks.rawIteratorAt(mcPartIndices[mcparticleDaughter.globalIndex()]); + float tpcNSigma = getTPCNSigma(track, type); + daughterTrackCheck(track, hDauCounter[type], tpcNSigma); + if (track.hasTPC()) { + hDauTPCNSigma[type]->Fill(track.p() * track.sign(), tpcNSigma); + } + } } } - } else if (std::abs(mcparticleDaughter.pdgCode()) == PDG_t::kNeutron) { - dauNeuteronMom[0] = mcparticleDaughter.px(); - dauNeuteronMom[1] = mcparticleDaughter.py(); - dauNeuteronMom[2] = mcparticleDaughter.pz(); - } else if (std::abs(mcparticleDaughter.pdgCode()) == PDG_t::kPiPlus) { - dauChargedPionMom[0] = mcparticleDaughter.px(); - dauChargedPionMom[1] = mcparticleDaughter.py(); - dauChargedPionMom[2] = mcparticleDaughter.pz(); - - recoQAHist.fill(HIST("hDauPionCounter"), 0); - if (mcPartIndices[mcparticleDaughter.globalIndex()] != -1) { - auto track = tracks.rawIteratorAt(mcPartIndices[mcparticleDaughter.globalIndex()]); - recoQAHist.fill(HIST("hDauPionTPCNSigma"), track.p() * track.sign(), track.tpcNSigmaPi()); - daughterTrackCheck(track, hDauPionCounter, track.tpcNSigmaPi()); - } - } else if (mcparticleDaughter.pdgCode() == PDG_t::kPi0) { - dauPion0Mom[0] = mcparticleDaughter.px(); - dauPion0Mom[1] = mcparticleDaughter.py(); - dauPion0Mom[2] = mcparticleDaughter.pz(); } } @@ -913,7 +943,7 @@ struct Hyperhelium4sigmaQa { float ct = RecoDecay::sqrtSumOfSquares(svPos[0] - mcparticle.vx(), svPos[1] - mcparticle.vy(), svPos[2] - mcparticle.vz()) * o2::constants::physics::MassHyperHelium4Sigma / mcparticle.p(); genQAHist.fill(HIST("hGenHyperHelium4SigmaCt"), ct); - // qa if mother track is reconstructed + // if mother track is reconstructed if (mcPartIndices[mcparticle.globalIndex()] != -1) { auto motherTrack = tracks.rawIteratorAt(mcPartIndices[mcparticle.globalIndex()]); bool isGoodMother = motherTrackCheck(motherTrack, hMotherCounter); @@ -924,47 +954,61 @@ struct Hyperhelium4sigmaQa { float diffpt = mcparticle.pt() - 2 * motherTrack.pt(); float diffpz = mcparticle.pz() - 2 * motherTrack.pz(); - int lastITSLayerMoth = 0; - for (int i = 6; i >= 0; i--) { - if ((motherTrack.itsClusterSizes() >> (i * 4)) & 0xf) { - lastITSLayerMoth = i; - break; - } - } - float motherR = LayerRadii[lastITSLayerMoth]; - recoQAHist.fill(HIST("h2TrueMotherSVRVsRLastITS"), motherR, svR); - recoQAHist.fill(HIST("h2TrueMotherDiffPtVsDiffR"), svR - motherR, diffpt); recoQAHist.fill(HIST("h2TrueMotherDiffPtVsTrueSVR"), svR, diffpt); recoQAHist.fill(HIST("h2TrueMotherDiffPzVsTrueSVR"), svR, diffpz); - recoQAHist.fill(HIST("h2TrueMotherDiffPtVsRLastITS"), motherR, diffpt); - recoQAHist.fill(HIST("h2TrueMotherDiffPzVsRLastITS"), motherR, diffpz); + recoQAHist.fill(HIST("h2TrueMotherDiffTglVsTrueSVR"), svR, mcparticle.pz() / mcparticle.pt() - motherTrack.tgl()); + recoQAHist.fill(HIST("h2TrueMotherDiffEtaVsTrueSVR"), svR, mcparticle.eta() - motherTrack.eta()); if (isGoodMother) { - recoQAHist.fill(HIST("h2GoodMotherSVRVsRLastITS"), motherR, svR); - recoQAHist.fill(HIST("h2GoodMotherDiffPtVsDiffR"), svR - motherR, diffpt); recoQAHist.fill(HIST("h2GoodMotherDiffPtVsTrueSVR"), svR, diffpt); recoQAHist.fill(HIST("h2GoodMotherDiffPzVsTrueSVR"), svR, diffpz); - recoQAHist.fill(HIST("h2GoodMotherDiffPtVsRLastITS"), motherR, diffpt); - recoQAHist.fill(HIST("h2GoodMotherDiffPzVsRLastITS"), motherR, diffpz); } - // fill qahist if charged daughters are also reconstructed + // if mother track and charged daughters are all reconstructed bool isDauReconstructed = mcPartIndices[dauIDList[0]] != -1 && (dChannel == k2body ? true : mcPartIndices[dauIDList[1]] != -1); if (isDauReconstructed) { genQAHist.fill(HIST("hGenHyperHelium4SigmaCounter"), 9.5); + + // qa for bc matching for reconstructed tracks + if (dChannel == k2body) { + auto daughterTrack = tracks.rawIteratorAt(mcPartIndices[dauIDList[0]]); + bool isMoth = motherTrackCheck(motherTrack, hRecoMotherCounter); + bool isDaug = daughterTrackCheck(daughterTrack, hRecoDauAlphaCounter, daughterTrack.tpcNSigmaAl()); + + recoQAHist.fill(HIST("hReco2BCandidateCount"), 0.5); + recoQAHist.fill(HIST("hRecoMotherCounter"), 0.5); + recoQAHist.fill(HIST("hRecoDauAlphaCounter"), 0.5); + recoQAHist.fill(HIST("hMotherIsPVContributer"), motherTrack.isPVContributor() ? 1.5 : 0.5); + recoQAHist.fill(HIST("hDauAlphaIsPVContributer"), daughterTrack.isPVContributor() ? 1.5 : 0.5); + + float itsNSigma = itsResponse.nSigmaITS(daughterTrack.itsClusterSizes(), 2 * daughterTrack.p(), daughterTrack.eta()); + recoQAHist.fill(HIST("hDauAlphaPVsITSNSigma"), 2 * daughterTrack.p(), itsNSigma); + + if (motherTrack.has_collision() && daughterTrack.has_collision()) { + recoQAHist.fill(HIST("hReco2BCandidateCount"), 1.5); + if (motherTrack.collisionId() == daughterTrack.collisionId()) { + recoQAHist.fill(HIST("hReco2BCandidateCount"), 2.5); + } + } + + if (isMoth && isDaug) { + recoQAHist.fill(HIST("hReco2BCandidateCount"), 3.5); + recoQAHist.fill(HIST("h2BCandDauAlphaPVsITSNSigma"), 2 * daughterTrack.p(), itsNSigma); + } + } } } // qa for branching ratios and invariant mass if (dChannel == k2body) { genQAHist.fill(HIST("hGenHyperHelium4SigmaCounter"), isMatter ? 3.5 : 4.5); - float hyperHelium4SigmaMCMass = RecoDecay::m(std::array{std::array{dauAlphaMom[0], dauAlphaMom[1], dauAlphaMom[2]}, std::array{dauPion0Mom[0], dauPion0Mom[1], dauPion0Mom[2]}}, std::array{o2::constants::physics::MassAlpha, o2::constants::physics::MassPi0}); + float hyperHelium4SigmaMCMass = RecoDecay::m(std::array{std::array{dauMom[kDauAlpha][0], dauMom[kDauAlpha][1], dauMom[kDauAlpha][2]}, std::array{dauMom[kDauPion0][0], dauMom[kDauPion0][1], dauMom[kDauPion0][2]}}, std::array{o2::constants::physics::MassAlpha, o2::constants::physics::MassPi0}); genQAHist.fill(HIST("hMcRecoInvMass"), hyperHelium4SigmaMCMass); } else if (dChannel == k3body_p) { genQAHist.fill(HIST("hGenHyperHelium4SigmaCounter"), isMatter ? 5.5 : 6.5); - float hyperHelium4SigmaMCMass = RecoDecay::m(std::array{std::array{dauTritonMom[0], dauTritonMom[1], dauTritonMom[2]}, std::array{dauProtonMom[0], dauProtonMom[1], dauProtonMom[2]}, std::array{dauPion0Mom[0], dauPion0Mom[1], dauPion0Mom[2]}}, std::array{o2::constants::physics::MassTriton, o2::constants::physics::MassProton, o2::constants::physics::MassPi0}); + float hyperHelium4SigmaMCMass = RecoDecay::m(std::array{std::array{dauMom[kDauTriton][0], dauMom[kDauTriton][1], dauMom[kDauTriton][2]}, std::array{dauMom[kDauProton][0], dauMom[kDauProton][1], dauMom[kDauProton][2]}, std::array{dauMom[kDauPion0][0], dauMom[kDauPion0][1], dauMom[kDauPion0][2]}}, std::array{o2::constants::physics::MassTriton, o2::constants::physics::MassProton, o2::constants::physics::MassPi0}); genQAHist.fill(HIST("hMcRecoInvMass"), hyperHelium4SigmaMCMass); } else if (dChannel == k3body_n) { genQAHist.fill(HIST("hGenHyperHelium4SigmaCounter"), isMatter ? 7.5 : 8.5); - float hyperHelium4SigmaMCMass = RecoDecay::m(std::array{std::array{dauTritonMom[0], dauTritonMom[1], dauTritonMom[2]}, std::array{dauNeuteronMom[0], dauNeuteronMom[1], dauNeuteronMom[2]}, std::array{dauChargedPionMom[0], dauChargedPionMom[1], dauChargedPionMom[2]}}, std::array{o2::constants::physics::MassTriton, o2::constants::physics::MassNeutron, o2::constants::physics::MassPionCharged}); + float hyperHelium4SigmaMCMass = RecoDecay::m(std::array{std::array{dauMom[kDauTriton][0], dauMom[kDauTriton][1], dauMom[kDauTriton][2]}, std::array{dauMom[kDauNeutron][0], dauMom[kDauNeutron][1], dauMom[kDauNeutron][2]}, std::array{dauMom[kDauChargedPion][0], dauMom[kDauChargedPion][1], dauMom[kDauChargedPion][2]}}, std::array{o2::constants::physics::MassTriton, o2::constants::physics::MassNeutron, o2::constants::physics::MassPiPlus}); genQAHist.fill(HIST("hMcRecoInvMass"), hyperHelium4SigmaMCMass); } } From 32139ade08f3afc379f1627ccc4c708c6ba8e8ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADt=20Ku=C4=8Dera?= Date: Mon, 16 Jun 2025 10:44:58 +0200 Subject: [PATCH 086/871] [PWGJE] Include What You Use (#11550) Co-authored-by: ALICE Builder --- PWGJE/Core/FastJetUtilities.cxx | 4 + PWGJE/Core/FastJetUtilities.h | 9 +-- PWGJE/Core/JetBkgSubUtils.cxx | 25 ++++-- PWGJE/Core/JetBkgSubUtils.h | 21 ++--- PWGJE/Core/JetCandidateUtilities.h | 31 +------- PWGJE/Core/JetDQUtilities.h | 30 +++----- PWGJE/Core/JetDerivedDataUtilities.h | 19 +++-- PWGJE/Core/JetFinder.cxx | 8 +- PWGJE/Core/JetFinder.h | 20 ++--- PWGJE/Core/JetFindingUtilities.h | 46 +++++------ PWGJE/Core/JetHFUtilities.h | 34 +++------ PWGJE/Core/JetMatchingUtilities.h | 38 +++++----- PWGJE/Core/JetSubstructureUtilities.h | 32 ++++---- PWGJE/Core/JetTaggingUtilities.h | 34 +++++---- PWGJE/Core/JetUtilities.h | 13 ++-- PWGJE/Core/JetV0Utilities.h | 35 +++------ PWGJE/Core/MlResponseHfTagging.h | 14 ++-- PWGJE/Core/utilsBcSelEMC.h | 20 +++-- PWGJE/DataModel/EMCALClusterDefinition.h | 21 +++-- PWGJE/DataModel/EMCALClusters.h | 8 +- PWGJE/DataModel/EMCALMatchedCollisions.h | 5 +- PWGJE/DataModel/EMCALMatchedTracks.h | 6 +- PWGJE/DataModel/GammaJetAnalysisTree.h | 9 ++- PWGJE/DataModel/Jet.h | 16 ++-- PWGJE/DataModel/JetReducedData.h | 10 ++- PWGJE/DataModel/JetReducedDataDQ.h | 10 ++- PWGJE/DataModel/JetReducedDataHF.h | 12 ++- PWGJE/DataModel/JetReducedDataSelector.h | 4 +- PWGJE/DataModel/JetReducedDataV0.h | 10 ++- PWGJE/DataModel/JetSubstructure.h | 54 +++++++------ PWGJE/DataModel/JetSubtraction.h | 12 +-- PWGJE/DataModel/JetTagging.h | 15 +++- PWGJE/DataModel/TrackJetQa.h | 16 ++-- .../Duplicates/jetFinderDataCharged1.cxx | 9 +++ .../Duplicates/jetFinderMCDCharged1.cxx | 9 +++ .../Duplicates/jetFinderMCPCharged1.cxx | 9 +++ PWGJE/JetFinders/jetFinder.cxx | 30 ++++---- .../JetFinders/jetFinderBplusDataCharged.cxx | 9 +++ PWGJE/JetFinders/jetFinderBplusMCDCharged.cxx | 9 +++ PWGJE/JetFinders/jetFinderBplusMCPCharged.cxx | 9 +++ PWGJE/JetFinders/jetFinderD0DataCharged.cxx | 9 +++ PWGJE/JetFinders/jetFinderD0MCDCharged.cxx | 9 +++ PWGJE/JetFinders/jetFinderD0MCPCharged.cxx | 9 +++ PWGJE/JetFinders/jetFinderDataCharged.cxx | 9 +++ PWGJE/JetFinders/jetFinderDataFull.cxx | 9 +++ PWGJE/JetFinders/jetFinderDataNeutral.cxx | 9 +++ .../jetFinderDielectronDataCharged.cxx | 9 +++ .../jetFinderDielectronMCDCharged.cxx | 9 +++ .../jetFinderDielectronMCPCharged.cxx | 9 +++ .../JetFinders/jetFinderDplusDataCharged.cxx | 9 +++ PWGJE/JetFinders/jetFinderDplusMCDCharged.cxx | 9 +++ PWGJE/JetFinders/jetFinderDplusMCPCharged.cxx | 9 +++ PWGJE/JetFinders/jetFinderHF.cxx | 29 ++++--- PWGJE/JetFinders/jetFinderLcDataCharged.cxx | 9 +++ PWGJE/JetFinders/jetFinderLcMCDCharged.cxx | 9 +++ PWGJE/JetFinders/jetFinderLcMCPCharged.cxx | 9 +++ PWGJE/JetFinders/jetFinderMCDCharged.cxx | 9 +++ PWGJE/JetFinders/jetFinderMCDFull.cxx | 9 +++ PWGJE/JetFinders/jetFinderMCDNeutral.cxx | 9 +++ PWGJE/JetFinders/jetFinderMCPCharged.cxx | 9 +++ PWGJE/JetFinders/jetFinderMCPFull.cxx | 9 +++ PWGJE/JetFinders/jetFinderMCPNeutral.cxx | 9 +++ PWGJE/JetFinders/jetFinderV0.cxx | 24 +++--- PWGJE/JetFinders/jetFinderV0DataCharged.cxx | 9 +++ PWGJE/JetFinders/jetFinderV0MCDCharged.cxx | 9 +++ PWGJE/JetFinders/jetFinderV0MCPCharged.cxx | 9 +++ .../Duplicates/jetMatchingDuplicates.cxx | 19 ++--- .../jetMatchingDuplicatesChargedData1.cxx | 11 +++ .../jetMatchingDuplicatesChargedMCD1.cxx | 11 +++ .../jetMatchingDuplicatesChargedMCP1.cxx | 11 +++ .../Substructure/jetSubstructureMatching.cxx | 30 ++------ .../jetSubstructureMatchingMCBplusCharged.cxx | 13 +++- .../jetSubstructureMatchingMCCharged.cxx | 13 +++- .../jetSubstructureMatchingMCD0Charged.cxx | 13 +++- ...ubstructureMatchingMCDielectronCharged.cxx | 13 +++- .../jetSubstructureMatchingMCDplusCharged.cxx | 13 +++- .../jetSubstructureMatchingMCLcCharged.cxx | 13 +++- .../jetSubstructureMatchingSub.cxx | 30 ++------ ...jetSubstructureMatchingSubBplusCharged.cxx | 13 +++- .../jetSubstructureMatchingSubCharged.cxx | 13 +++- .../jetSubstructureMatchingSubD0Charged.cxx | 13 +++- ...bstructureMatchingSubDielectronCharged.cxx | 13 +++- ...jetSubstructureMatchingSubDplusCharged.cxx | 13 +++- .../jetSubstructureMatchingSubLcCharged.cxx | 13 +++- .../TableProducer/Matching/jetMatchingMC.cxx | 18 ++--- .../Matching/jetMatchingMCBplusCharged.cxx | 11 +++ .../Matching/jetMatchingMCCharged.cxx | 11 +++ .../Matching/jetMatchingMCD0Charged.cxx | 11 +++ .../jetMatchingMCDielectronCharged.cxx | 11 +++ .../Matching/jetMatchingMCDplusCharged.cxx | 11 +++ .../Matching/jetMatchingMCFull.cxx | 11 +++ .../Matching/jetMatchingMCLcCharged.cxx | 11 +++ .../Matching/jetMatchingMCNeutral.cxx | 11 +++ .../Matching/jetMatchingMCSub.cxx | 18 ++--- .../Matching/jetMatchingMCSubBplusCharged.cxx | 10 +++ .../Matching/jetMatchingMCSubCharged.cxx | 11 +++ .../Matching/jetMatchingMCSubD0Charged.cxx | 10 +++ .../jetMatchingMCSubDielectronCharged.cxx | 10 +++ .../Matching/jetMatchingMCSubDplusCharged.cxx | 10 +++ .../Matching/jetMatchingMCSubLcCharged.cxx | 10 +++ .../Matching/jetMatchingMCV0Charged.cxx | 11 +++ .../TableProducer/Matching/jetMatchingSub.cxx | 19 ++--- .../Matching/jetMatchingSubBplusCharged.cxx | 11 +++ .../Matching/jetMatchingSubCharged.cxx | 12 +++ .../Matching/jetMatchingSubD0Charged.cxx | 11 +++ .../jetMatchingSubDielectronCharged.cxx | 11 +++ .../Matching/jetMatchingSubDplusCharged.cxx | 11 +++ .../Matching/jetMatchingSubLcCharged.cxx | 11 +++ PWGJE/TableProducer/derivedDataProducer.cxx | 76 ++++++++++--------- PWGJE/TableProducer/derivedDataSelector.cxx | 27 ++++--- .../derivedDataTriggerProducer.cxx | 22 +++--- PWGJE/TableProducer/derivedDataWriter.cxx | 31 +++++--- .../emcalClusterHadronicCorrectionTask.cxx | 32 ++++---- PWGJE/TableProducer/emcalCorrectionTask.cxx | 68 ++++++++--------- .../TableProducer/emcalMatchedTracksTask.cxx | 46 +++++------ .../eventwiseConstituentSubtractor.cxx | 44 ++++++----- .../TableProducer/heavyFlavourDefinition.cxx | 20 ++--- PWGJE/TableProducer/jetEventWeightMCD.cxx | 15 ++-- PWGJE/TableProducer/jetEventWeightMCP.cxx | 13 ++-- PWGJE/TableProducer/jetTaggerHF.cxx | 48 ++++++++---- PWGJE/TableProducer/jetTrackDerived.cxx | 31 +++++--- PWGJE/TableProducer/luminosityCalculator.cxx | 16 +++- PWGJE/TableProducer/luminosityProducer.cxx | 21 ++++- PWGJE/TableProducer/rhoEstimator.cxx | 73 ++++++++++-------- .../secondaryVertexReconstruction.cxx | 49 +++++++----- PWGJE/Tasks/bjetTaggingGnn.cxx | 33 ++++---- PWGJE/Tasks/bjetTaggingML.cxx | 36 +++++---- PWGJE/Tasks/bjetTreeCreator.cxx | 45 ++++++----- PWGJE/Tasks/dijetFinderQA.cxx | 34 ++++----- PWGJE/Tasks/emcCellMonitor.cxx | 30 +++++--- PWGJE/Tasks/emcClusterMonitor.cxx | 48 +++++++----- PWGJE/Tasks/emcEventSelectionQA.cxx | 21 +++-- PWGJE/Tasks/emcTmMonitor.cxx | 45 ++++++----- PWGJE/Tasks/emcVertexSelectionQA.cxx | 24 ++++-- PWGJE/Tasks/emcalGammaGammaBcWise.cxx | 26 +++++-- PWGJE/Tasks/emcalPi0EnergyScaleCalib.cxx | 49 ++++++------ PWGJE/Tasks/fullJetSpectra.cxx | 50 ++++++------ PWGJE/Tasks/fullJetTriggerQATask.cxx | 42 ++++++---- PWGJE/Tasks/gammaJetTreeProducer.cxx | 61 +++++++-------- PWGJE/Tasks/hadronPhotonCorrelation.cxx | 48 ++++++------ PWGJE/Tasks/hfFragmentationFunction.cxx | 44 +++++------ PWGJE/Tasks/jetBackgroundAnalysis.cxx | 36 ++++----- PWGJE/Tasks/jetChCorr.cxx | 43 +++++------ PWGJE/Tasks/jetChargedV2.cxx | 46 +++++------ PWGJE/Tasks/jetFinderBplusQA.cxx | 10 +++ PWGJE/Tasks/jetFinderD0QA.cxx | 10 +++ PWGJE/Tasks/jetFinderDielectronQA.cxx | 10 +++ PWGJE/Tasks/jetFinderDplusQA.cxx | 10 +++ PWGJE/Tasks/jetFinderFullQA.cxx | 35 +++++---- PWGJE/Tasks/jetFinderHFQA.cxx | 41 +++++----- PWGJE/Tasks/jetFinderLcQA.cxx | 10 +++ PWGJE/Tasks/jetFinderQA.cxx | 41 +++++----- PWGJE/Tasks/jetFinderV0QA.cxx | 37 ++++----- PWGJE/Tasks/jetFragmentation.cxx | 40 +++++----- PWGJE/Tasks/jetHadronRecoil.cxx | 44 ++++++----- PWGJE/Tasks/jetLundReclustering.cxx | 41 +++++----- PWGJE/Tasks/jetMatchingQA.cxx | 19 +++-- PWGJE/Tasks/jetPlanarFlow.cxx | 36 +++++---- PWGJE/Tasks/jetShape.cxx | 16 ++-- PWGJE/Tasks/jetSpectraCharged.cxx | 37 ++++----- PWGJE/Tasks/jetSpectraEseTask.cxx | 49 ++++++------ PWGJE/Tasks/jetSubstructure.cxx | 46 ++++++----- PWGJE/Tasks/jetSubstructureBplus.cxx | 13 +++- PWGJE/Tasks/jetSubstructureBplusOutput.cxx | 14 +++- PWGJE/Tasks/jetSubstructureD0.cxx | 13 +++- PWGJE/Tasks/jetSubstructureD0Output.cxx | 15 +++- PWGJE/Tasks/jetSubstructureDielectron.cxx | 13 +++- .../Tasks/jetSubstructureDielectronOutput.cxx | 15 +++- PWGJE/Tasks/jetSubstructureDplus.cxx | 13 +++- PWGJE/Tasks/jetSubstructureDplusOutput.cxx | 15 +++- PWGJE/Tasks/jetSubstructureHF.cxx | 47 +++++++----- PWGJE/Tasks/jetSubstructureHFOutput.cxx | 36 ++++----- PWGJE/Tasks/jetSubstructureLc.cxx | 13 +++- PWGJE/Tasks/jetSubstructureLcOutput.cxx | 15 +++- PWGJE/Tasks/jetSubstructureOutput.cxx | 34 ++++----- PWGJE/Tasks/jetTaggerHFQA.cxx | 40 +++++----- PWGJE/Tasks/jetTriggerChargedQa.cxx | 37 ++++----- PWGJE/Tasks/jetTutorial.cxx | 33 ++++---- PWGJE/Tasks/jetTutorialSkeleton.cxx | 25 +++--- PWGJE/Tasks/jetValidationQA.cxx | 23 +++--- PWGJE/Tasks/mcGeneratorStudies.cxx | 28 ++++--- PWGJE/Tasks/nsubjettiness.cxx | 30 ++++---- PWGJE/Tasks/nucleiInJets.cxx | 64 +++++++++------- PWGJE/Tasks/phiInJets.cxx | 54 +++++++------ PWGJE/Tasks/photonIsolationQA.cxx | 49 ++++++------ PWGJE/Tasks/recoilJets.cxx | 23 +++--- PWGJE/Tasks/statPromptPhoton.cxx | 52 +++++-------- PWGJE/Tasks/trackEfficiency.cxx | 36 ++++----- PWGJE/Tasks/trackJetQA.cxx | 30 ++++---- PWGJE/Tasks/triggerCorrelations.cxx | 25 +++--- PWGJE/Tasks/v0JetSpectra.cxx | 28 +++---- PWGJE/Tasks/v0QA.cxx | 39 +++++----- 192 files changed, 2636 insertions(+), 1705 deletions(-) diff --git a/PWGJE/Core/FastJetUtilities.cxx b/PWGJE/Core/FastJetUtilities.cxx index ba7acabbdf3..ca5956a1554 100644 --- a/PWGJE/Core/FastJetUtilities.cxx +++ b/PWGJE/Core/FastJetUtilities.cxx @@ -11,6 +11,10 @@ #include "FastJetUtilities.h" +#include + +#include + void fastjetutilities::setFastJetUserInfo(std::vector& constituents, int index, int status) { fastjet_user_info* user_info = new fastjet_user_info(status, index); // FIXME: can setting this as a pointer be avoided? diff --git a/PWGJE/Core/FastJetUtilities.h b/PWGJE/Core/FastJetUtilities.h index e6d4b2b3794..aebb41ab5d0 100644 --- a/PWGJE/Core/FastJetUtilities.h +++ b/PWGJE/Core/FastJetUtilities.h @@ -17,15 +17,10 @@ #ifndef PWGJE_CORE_FASTJETUTILITIES_H_ #define PWGJE_CORE_FASTJETUTILITIES_H_ +#include + #include -#include -#include -#include #include -#include - -#include "fastjet/PseudoJet.hh" -#include "fastjet/Selector.hh" enum class JetConstituentStatus { track = 0, diff --git a/PWGJE/Core/JetBkgSubUtils.cxx b/PWGJE/Core/JetBkgSubUtils.cxx index 281feccc66c..fe4a0720347 100644 --- a/PWGJE/Core/JetBkgSubUtils.cxx +++ b/PWGJE/Core/JetBkgSubUtils.cxx @@ -12,13 +12,26 @@ // jet finder task // // Author: Hadi Hassan, Universiy of Jväskylä, hadi.hassan@cern.ch -#include -#include -#include "Framework/Logger.h" -#include "Common/Core/RecoDecay.h" -#include "PWGJE/Core/JetUtilities.h" + #include "PWGJE/Core/JetBkgSubUtils.h" -#include "PWGJE/Core/FastJetUtilities.h" + +#include "Common/Core/RecoDecay.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include JetBkgSubUtils::JetBkgSubUtils(float jetBkgR_out, float bkgEtaMin_out, float bkgEtaMax_out, float bkgPhiMin_out, float bkgPhiMax_out, float constSubAlpha_out, float constSubRMax_out, int nHardReject_out, fastjet::GhostedAreaSpec ghostAreaSpec_out) : jetBkgR(jetBkgR_out), bkgEtaMin(bkgEtaMin_out), diff --git a/PWGJE/Core/JetBkgSubUtils.h b/PWGJE/Core/JetBkgSubUtils.h index e74aa512b99..f3c8fcc987a 100644 --- a/PWGJE/Core/JetBkgSubUtils.h +++ b/PWGJE/Core/JetBkgSubUtils.h @@ -17,23 +17,16 @@ #ifndef PWGJE_CORE_JETBKGSUBUTILS_H_ #define PWGJE_CORE_JETBKGSUBUTILS_H_ -#include -#include +#include +#include +#include +#include +#include + #include #include -#include - -#include "PWGJE/Core/FastJetUtilities.h" - -#include "fastjet/PseudoJet.hh" -#include "fastjet/ClusterSequenceArea.hh" -#include "fastjet/AreaDefinition.hh" -#include "fastjet/JetDefinition.hh" -#include "fastjet/tools/JetMedianBackgroundEstimator.hh" -#include "fastjet/tools/Subtractor.hh" -#include "fastjet/contrib/ConstituentSubtractor.hh" -#include "Framework/Logger.h" +#include enum class BkgSubEstimator { none = 0, medianRho = 1, diff --git a/PWGJE/Core/JetCandidateUtilities.h b/PWGJE/Core/JetCandidateUtilities.h index ad7f178b9f0..e1bbdd18819 100644 --- a/PWGJE/Core/JetCandidateUtilities.h +++ b/PWGJE/Core/JetCandidateUtilities.h @@ -17,35 +17,12 @@ #ifndef PWGJE_CORE_JETCANDIDATEUTILITIES_H_ #define PWGJE_CORE_JETCANDIDATEUTILITIES_H_ -#include -#include -#include -#include -#include - -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoA.h" -#include "Framework/O2DatabasePDGPlugin.h" - -#include "Framework/Logger.h" -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectionDefaults.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "PWGJE/DataModel/EMCALClusters.h" - -#include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" -#include "PWGHF/DataModel/DerivedTables.h" - -#include "PWGJE/Core/FastJetUtilities.h" -#include "PWGJE/Core/JetDerivedDataUtilities.h" -#include "PWGJE/Core/JetHFUtilities.h" #include "PWGJE/Core/JetDQUtilities.h" +#include "PWGJE/Core/JetHFUtilities.h" #include "PWGJE/Core/JetV0Utilities.h" -#include "PWGJE/Core/JetFinder.h" -#include "PWGJE/DataModel/Jet.h" + +#include +#include namespace jetcandidateutilities { diff --git a/PWGJE/Core/JetDQUtilities.h b/PWGJE/Core/JetDQUtilities.h index c5fb2117e81..6f33ae0749d 100644 --- a/PWGJE/Core/JetDQUtilities.h +++ b/PWGJE/Core/JetDQUtilities.h @@ -17,31 +17,21 @@ #ifndef PWGJE_CORE_JETDQUTILITIES_H_ #define PWGJE_CORE_JETDQUTILITIES_H_ -#include -#include -#include -#include +#include "PWGJE/DataModel/Jet.h" -#include +#include "Common/Core/RecoDecay.h" -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoA.h" -#include "Framework/O2DatabasePDGPlugin.h" +#include +#include -#include "Framework/Logger.h" -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectionDefaults.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" +#include -#include "PWGDQ/DataModel/ReducedInfoTables.h" +#include -#include "PWGJE/Core/FastJetUtilities.h" -#include "PWGJE/Core/JetDerivedDataUtilities.h" -#include "PWGJE/Core/JetFinder.h" -#include "PWGJE/DataModel/Jet.h" +#include +#include +#include +#include namespace jetdqutilities { diff --git a/PWGJE/Core/JetDerivedDataUtilities.h b/PWGJE/Core/JetDerivedDataUtilities.h index b526dc53fc1..c3dc36ab18f 100644 --- a/PWGJE/Core/JetDerivedDataUtilities.h +++ b/PWGJE/Core/JetDerivedDataUtilities.h @@ -17,10 +17,17 @@ #ifndef PWGJE_CORE_JETDERIVEDDATAUTILITIES_H_ #define PWGJE_CORE_JETDERIVEDDATAUTILITIES_H_ -#include -#include -#include "Common/CCDB/TriggerAliases.h" #include "Common/CCDB/EventSelectionParams.h" +#include "Common/CCDB/TriggerAliases.h" + +#include + +#include +#include +#include +#include +#include +#include namespace jetderiveddatautilities { @@ -153,9 +160,9 @@ uint16_t setEventSelectionBit(T const& collision) if (collision.sel7()) { SETBIT(bit, JCollisionSel::sel7); } - if (collision.alias_bit(kINT7)) { - SETBIT(bit, JCollisionSel::selKINT7); - } + if (collision.alias_bit(kINT7)) { + SETBIT(bit, JCollisionSel::selKINT7); + } if (collision.selection_bit(o2::aod::evsel::kIsTriggerTVX)) { SETBIT(bit, JCollisionSel::selTVX); } diff --git a/PWGJE/Core/JetFinder.cxx b/PWGJE/Core/JetFinder.cxx index 03583a9e622..87a71fb19e3 100644 --- a/PWGJE/Core/JetFinder.cxx +++ b/PWGJE/Core/JetFinder.cxx @@ -15,7 +15,13 @@ /// \author Jochen Klein #include "PWGJE/Core/JetFinder.h" -#include "Framework/Logger.h" + +#include +#include +#include +#include + +#include /// Sets the jet finding parameters void JetFinder::setParams() diff --git a/PWGJE/Core/JetFinder.h b/PWGJE/Core/JetFinder.h index 26b4a3c5f0f..94afd0117ec 100644 --- a/PWGJE/Core/JetFinder.h +++ b/PWGJE/Core/JetFinder.h @@ -18,18 +18,18 @@ #ifndef PWGJE_CORE_JETFINDER_H_ #define PWGJE_CORE_JETFINDER_H_ -#include -#include +#include +#include +#include +#include +#include +#include + +#include -#include -#include -#include +#include -#include "fastjet/PseudoJet.hh" -#include "fastjet/ClusterSequenceArea.hh" -#include "fastjet/AreaDefinition.hh" -#include "fastjet/JetDefinition.hh" -#include "fastjet/tools/Subtractor.hh" +#include enum class JetType { full = 0, diff --git a/PWGJE/Core/JetFindingUtilities.h b/PWGJE/Core/JetFindingUtilities.h index ac81338a99d..2bb9b8375b4 100644 --- a/PWGJE/Core/JetFindingUtilities.h +++ b/PWGJE/Core/JetFindingUtilities.h @@ -17,37 +17,31 @@ #ifndef PWGJE_CORE_JETFINDINGUTILITIES_H_ #define PWGJE_CORE_JETFINDINGUTILITIES_H_ -#include -#include -#include -#include -#include -#include - -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoA.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "Framework/HistogramRegistry.h" - -#include "Framework/Logger.h" -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectionDefaults.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "PWGJE/DataModel/EMCALClusters.h" - -#include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" - -// #include "PWGJE/Core/JetBkgSubUtils.h" #include "PWGJE/Core/FastJetUtilities.h" +#include "PWGJE/Core/JetCandidateUtilities.h" #include "PWGJE/Core/JetDerivedDataUtilities.h" #include "PWGJE/Core/JetFinder.h" #include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" -#include "PWGJE/Core/JetCandidateUtilities.h" -#include "PWGJE/Core/JetHFUtilities.h" +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include namespace jetfindingutilities { diff --git a/PWGJE/Core/JetHFUtilities.h b/PWGJE/Core/JetHFUtilities.h index a5ec07fe157..30d0f0da938 100644 --- a/PWGJE/Core/JetHFUtilities.h +++ b/PWGJE/Core/JetHFUtilities.h @@ -17,33 +17,19 @@ #ifndef PWGJE_CORE_JETHFUTILITIES_H_ #define PWGJE_CORE_JETHFUTILITIES_H_ -#include -#include -#include -#include -#include - -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoA.h" -#include "Framework/O2DatabasePDGPlugin.h" - -#include "Framework/Logger.h" -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectionDefaults.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "PWGJE/DataModel/EMCALClusters.h" - +#include "PWGHF/Core/DecayChannels.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" -#include "PWGHF/DataModel/DerivedTables.h" - -#include "PWGJE/Core/FastJetUtilities.h" -#include "PWGJE/Core/JetDerivedDataUtilities.h" -#include "PWGJE/Core/JetFinder.h" #include "PWGJE/DataModel/Jet.h" +#include +#include + +#include +#include +#include +#include +#include + namespace jethfutilities { diff --git a/PWGJE/Core/JetMatchingUtilities.h b/PWGJE/Core/JetMatchingUtilities.h index 1c499686638..cf22cad5ff9 100644 --- a/PWGJE/Core/JetMatchingUtilities.h +++ b/PWGJE/Core/JetMatchingUtilities.h @@ -20,27 +20,25 @@ #ifndef PWGJE_CORE_JETMATCHINGUTILITIES_H_ #define PWGJE_CORE_JETMATCHINGUTILITIES_H_ -#include -#include -#include -#include -#include -#include - -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoA.h" -#include "Framework/O2DatabasePDGPlugin.h" - -#include "Framework/Logger.h" -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectionDefaults.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "PWGJE/DataModel/EMCALClusters.h" -#include "PWGJE/DataModel/Jet.h" #include "PWGJE/Core/JetCandidateUtilities.h" #include "PWGJE/Core/JetFindingUtilities.h" +#include "PWGJE/DataModel/JetReducedData.h" + +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include namespace jetmatchingutilities { @@ -742,5 +740,5 @@ void doPairMatching(T const& pairsBase, U const& pairsTag, std::vector -#include - -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoA.h" -#include "Framework/O2DatabasePDGPlugin.h" - -#include "Framework/Logger.h" -#include "PWGJE/DataModel/EMCALClusters.h" - -#include "PWGHF/DataModel/CandidateReconstructionTables.h" - #include "PWGJE/Core/FastJetUtilities.h" -#include "PWGJE/Core/JetDerivedDataUtilities.h" -#include "PWGJE/Core/JetFinder.h" #include "PWGJE/Core/JetCandidateUtilities.h" +#include "PWGJE/Core/JetFinder.h" #include "PWGJE/DataModel/Jet.h" -#include "fastjet/contrib/Nsubjettiness.hh" -#include "fastjet/contrib/AxesDefinition.hh" -#include "fastjet/contrib/MeasureDefinition.hh" -#include "fastjet/contrib/SoftDrop.hh" + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include namespace jetsubstructureutilities { diff --git a/PWGJE/Core/JetTaggingUtilities.h b/PWGJE/Core/JetTaggingUtilities.h index ab399bb852d..616929ac1ed 100644 --- a/PWGJE/Core/JetTaggingUtilities.h +++ b/PWGJE/Core/JetTaggingUtilities.h @@ -18,25 +18,31 @@ #ifndef PWGJE_CORE_JETTAGGINGUTILITIES_H_ #define PWGJE_CORE_JETTAGGINGUTILITIES_H_ -#include -#include -#include -#include -#include +#include "PWGJE/Core/JetUtilities.h" + +#include "Common/Core/RecoDecay.h" + +#include +#include + +#include +#include + +#include + #include +#include +#include +#include +#include #include +#include #include #include +#include #include - -#include -#include "CommonConstants/PhysicsConstants.h" - -#include "TF1.h" -#include "Framework/Logger.h" -#include "Common/Core/RecoDecay.h" -#include "Common/Core/trackUtilities.h" -#include "PWGJE/Core/JetUtilities.h" +#include +#include enum JetTaggingSpecies { none = 0, diff --git a/PWGJE/Core/JetUtilities.h b/PWGJE/Core/JetUtilities.h index f1db864ef25..358e1d1dd46 100644 --- a/PWGJE/Core/JetUtilities.h +++ b/PWGJE/Core/JetUtilities.h @@ -18,16 +18,19 @@ #ifndef PWGJE_CORE_JETUTILITIES_H_ #define PWGJE_CORE_JETUTILITIES_H_ +#include "Common/Core/RecoDecay.h" + +#include + +#include #include +#include #include -#include +#include #include #include -#include - -#include "Framework/Logger.h" -#include "Common/Core/RecoDecay.h" +#include namespace jetutilities { diff --git a/PWGJE/Core/JetV0Utilities.h b/PWGJE/Core/JetV0Utilities.h index 3d12cd5d0a3..e7495242e01 100644 --- a/PWGJE/Core/JetV0Utilities.h +++ b/PWGJE/Core/JetV0Utilities.h @@ -17,33 +17,20 @@ #ifndef PWGJE_CORE_JETV0UTILITIES_H_ #define PWGJE_CORE_JETV0UTILITIES_H_ -#include -#include -#include -#include +#include "PWGJE/DataModel/Jet.h" + +#include "Common/Core/RecoDecay.h" + +#include #include -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoA.h" -#include "Framework/O2DatabasePDGPlugin.h" - -#include "Framework/Logger.h" -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectionDefaults.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "PWGJE/DataModel/EMCALClusters.h" - -#include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" -#include "PWGHF/DataModel/DerivedTables.h" - -#include "PWGJE/Core/FastJetUtilities.h" -#include "PWGJE/Core/JetDerivedDataUtilities.h" -#include "PWGJE/Core/JetFinder.h" -#include "PWGJE/DataModel/Jet.h" +#include + +#include +#include +#include +#include namespace jetv0utilities { diff --git a/PWGJE/Core/MlResponseHfTagging.h b/PWGJE/Core/MlResponseHfTagging.h index 2580c5296df..87da7a282e0 100644 --- a/PWGJE/Core/MlResponseHfTagging.h +++ b/PWGJE/Core/MlResponseHfTagging.h @@ -16,12 +16,7 @@ #ifndef PWGJE_CORE_MLRESPONSEHFTAGGING_H_ #define PWGJE_CORE_MLRESPONSEHFTAGGING_H_ -#include -#include -#include - #include "Tools/ML/MlResponse.h" -#include "PWGJE/Core/JetTaggingUtilities.h" #if __has_include() #include @@ -29,6 +24,15 @@ #include #endif +#include + +#include + +#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 diff --git a/PWGJE/Core/utilsBcSelEMC.h b/PWGJE/Core/utilsBcSelEMC.h index c613bba70e2..7c23436e876 100644 --- a/PWGJE/Core/utilsBcSelEMC.h +++ b/PWGJE/Core/utilsBcSelEMC.h @@ -16,15 +16,21 @@ #ifndef PWGJE_CORE_UTILSBCSELEMC_H_ #define PWGJE_CORE_UTILSBCSELEMC_H_ -#include // std::shared_ptr -#include // std::string +#include "Common/CCDB/EventSelectionParams.h" -#include "Framework/Configurable.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/HistogramSpec.h" -#include "Framework/OutputObjHeader.h" +#include +#include +#include +#include -#include "Common/CCDB/EventSelectionParams.h" +#include + +#include + +#include +#include +#include // std::shared_ptr +#include // std::string namespace o2::emc_evsel { diff --git a/PWGJE/DataModel/EMCALClusterDefinition.h b/PWGJE/DataModel/EMCALClusterDefinition.h index ead4a14dde7..41e87590449 100644 --- a/PWGJE/DataModel/EMCALClusterDefinition.h +++ b/PWGJE/DataModel/EMCALClusterDefinition.h @@ -17,7 +17,6 @@ #define PWGJE_DATAMODEL_EMCALCLUSTERDEFINITION_H_ #include -#include "Framework/AnalysisDataModel.h" namespace o2::aod { @@ -31,16 +30,16 @@ enum class ClusterAlgorithm_t { /// cell energy, gradient as well as timing cut struct EMCALClusterDefinition { ClusterAlgorithm_t algorithm; - int storageID = -1; // integer ID used to store cluster definition in a flat table - int selectedCellType = 1; // EMCal cell type (CURRENTLY NOT USED TO AVOID MULTIPLE CELL LOOPS) - std::string name = "kUndefined"; // name of the cluster definition - double seedEnergy = 0.1; // seed threshold (GeV) - double minCellEnergy = 0.05; // minimum cell energy (GeV) - double timeMin = -10000.; // minimum time (ns) - double timeMax = 10000.; // maximum time (ns) - double timeDiff = 20000.; // maximum time difference (ns) between seed cell and aggregation cell - bool doGradientCut = true; // apply gradient cut if true - double gradientCut = -1; // gradient cut + int storageID = -1; // integer ID used to store cluster definition in a flat table + int selectedCellType = 1; // EMCal cell type (CURRENTLY NOT USED TO AVOID MULTIPLE CELL LOOPS) + std::string name = "kUndefined"; // name of the cluster definition + double seedEnergy = 0.1; // seed threshold (GeV) + double minCellEnergy = 0.05; // minimum cell energy (GeV) + double timeMin = -10000.; // minimum time (ns) + double timeMax = 10000.; // maximum time (ns) + double timeDiff = 20000.; // maximum time difference (ns) between seed cell and aggregation cell + bool doGradientCut = true; // apply gradient cut if true + double gradientCut = -1; // gradient cut bool recalcShowerShape5x5 = false; // recalculate shower shape using 5x5 cells // default constructor diff --git a/PWGJE/DataModel/EMCALClusters.h b/PWGJE/DataModel/EMCALClusters.h index c634b4b017e..ca42b0ae68e 100644 --- a/PWGJE/DataModel/EMCALClusters.h +++ b/PWGJE/DataModel/EMCALClusters.h @@ -16,10 +16,14 @@ #ifndef PWGJE_DATAMODEL_EMCALCLUSTERS_H_ #define PWGJE_DATAMODEL_EMCALCLUSTERS_H_ +#include "EMCALClusterDefinition.h" + +#include +#include // IWYU pragma: keep + +#include #include #include -#include "Framework/AnalysisDataModel.h" -#include "EMCALClusterDefinition.h" namespace o2::aod { diff --git a/PWGJE/DataModel/EMCALMatchedCollisions.h b/PWGJE/DataModel/EMCALMatchedCollisions.h index 4acaad9dbed..2e93a2c765b 100644 --- a/PWGJE/DataModel/EMCALMatchedCollisions.h +++ b/PWGJE/DataModel/EMCALMatchedCollisions.h @@ -18,9 +18,8 @@ #ifndef PWGJE_DATAMODEL_EMCALMATCHEDCOLLISIONS_H_ #define PWGJE_DATAMODEL_EMCALMATCHEDCOLLISIONS_H_ -#include -#include "Framework/AnalysisDataModel.h" -#include "EMCALClusterDefinition.h" +#include +#include // IWYU pragma: keep namespace o2::aod { diff --git a/PWGJE/DataModel/EMCALMatchedTracks.h b/PWGJE/DataModel/EMCALMatchedTracks.h index 1dbbfac7b7a..840a384eba8 100644 --- a/PWGJE/DataModel/EMCALMatchedTracks.h +++ b/PWGJE/DataModel/EMCALMatchedTracks.h @@ -16,9 +16,9 @@ #ifndef PWGJE_DATAMODEL_EMCALMATCHEDTRACKS_H_ #define PWGJE_DATAMODEL_EMCALMATCHEDTRACKS_H_ -#include -#include "Framework/AnalysisDataModel.h" -#include "EMCALClusterDefinition.h" +#include + +#include namespace o2::aod { diff --git a/PWGJE/DataModel/GammaJetAnalysisTree.h b/PWGJE/DataModel/GammaJetAnalysisTree.h index cfd58f75773..655fcdfbc37 100644 --- a/PWGJE/DataModel/GammaJetAnalysisTree.h +++ b/PWGJE/DataModel/GammaJetAnalysisTree.h @@ -17,10 +17,11 @@ #ifndef PWGJE_DATAMODEL_GAMMAJETANALYSISTREE_H_ #define PWGJE_DATAMODEL_GAMMAJETANALYSISTREE_H_ -#include "Framework/AnalysisDataModel.h" -#include "PWGJE/DataModel/EMCALClusters.h" -#include "PWGJE/Core/JetDerivedDataUtilities.h" -#include "PWGJE/DataModel/Jet.h" +#include + +#include + +#include namespace o2::aod { diff --git a/PWGJE/DataModel/Jet.h b/PWGJE/DataModel/Jet.h index 57731df23ba..0fbee0ca438 100644 --- a/PWGJE/DataModel/Jet.h +++ b/PWGJE/DataModel/Jet.h @@ -23,20 +23,20 @@ #ifndef PWGJE_DATAMODEL_JET_H_ #define PWGJE_DATAMODEL_JET_H_ -#include -#include "Framework/AnalysisDataModel.h" -#include "PWGJE/DataModel/EMCALClusters.h" +#include "PWGDQ/DataModel/ReducedInfoTables.h" +#include "PWGHF/DataModel/DerivedTables.h" #include "PWGJE/DataModel/JetReducedData.h" +#include "PWGJE/DataModel/JetReducedDataDQ.h" #include "PWGJE/DataModel/JetReducedDataHF.h" #include "PWGJE/DataModel/JetReducedDataV0.h" -#include "PWGJE/DataModel/JetReducedDataDQ.h" #include "PWGJE/DataModel/JetSubtraction.h" - -#include "PWGHF/DataModel/DerivedTables.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" #include "PWGLF/DataModel/LFStrangenessTables.h" #include "PWGLF/DataModel/V0SelectorTables.h" -#include "PWGDQ/DataModel/ReducedInfoTables.h" + +#include + +#include +#include namespace o2::aod { diff --git a/PWGJE/DataModel/JetReducedData.h b/PWGJE/DataModel/JetReducedData.h index 5b97e41ab74..4d5e401fe7d 100644 --- a/PWGJE/DataModel/JetReducedData.h +++ b/PWGJE/DataModel/JetReducedData.h @@ -17,11 +17,15 @@ #ifndef PWGJE_DATAMODEL_JETREDUCEDDATA_H_ #define PWGJE_DATAMODEL_JETREDUCEDDATA_H_ +#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include "PWGJE/DataModel/EMCALClusters.h" // IWYU pragma: keep + +#include +#include // IWYU pragma: keep + #include +#include #include -#include "Framework/AnalysisDataModel.h" -#include "PWGJE/DataModel/EMCALClusters.h" -#include "PWGJE/Core/JetDerivedDataUtilities.h" namespace o2::aod { diff --git a/PWGJE/DataModel/JetReducedDataDQ.h b/PWGJE/DataModel/JetReducedDataDQ.h index bbf2e464cf9..f86754d3a84 100644 --- a/PWGJE/DataModel/JetReducedDataDQ.h +++ b/PWGJE/DataModel/JetReducedDataDQ.h @@ -17,13 +17,15 @@ #ifndef PWGJE_DATAMODEL_JETREDUCEDDATADQ_H_ #define PWGJE_DATAMODEL_JETREDUCEDDATADQ_H_ -#include -#include -#include "Framework/AnalysisDataModel.h" -#include "PWGDQ/DataModel/ReducedInfoTables.h" #include "PWGJE/DataModel/JetReducedData.h" #include "PWGJE/DataModel/JetReducedDataHF.h" +#include +#include // IWYU pragma: keep + +#include +#include + namespace o2::aod { namespace jdielectronmccollision diff --git a/PWGJE/DataModel/JetReducedDataHF.h b/PWGJE/DataModel/JetReducedDataHF.h index cdb2a933d20..5e519b88f18 100644 --- a/PWGJE/DataModel/JetReducedDataHF.h +++ b/PWGJE/DataModel/JetReducedDataHF.h @@ -17,12 +17,16 @@ #ifndef PWGJE_DATAMODEL_JETREDUCEDDATAHF_H_ #define PWGJE_DATAMODEL_JETREDUCEDDATAHF_H_ -#include -#include -#include "Framework/AnalysisDataModel.h" -#include "PWGJE/DataModel/EMCALClusters.h" +#include "PWGJE/DataModel/EMCALClusters.h" // IWYU pragma: keep #include "PWGJE/DataModel/JetReducedData.h" +#include +#include // IWYU pragma: keep + +#include + +#include + namespace o2::aod { diff --git a/PWGJE/DataModel/JetReducedDataSelector.h b/PWGJE/DataModel/JetReducedDataSelector.h index 4e6b07a955b..9529debc58e 100644 --- a/PWGJE/DataModel/JetReducedDataSelector.h +++ b/PWGJE/DataModel/JetReducedDataSelector.h @@ -17,9 +17,9 @@ #ifndef PWGJE_DATAMODEL_JETREDUCEDDATASELECTOR_H_ #define PWGJE_DATAMODEL_JETREDUCEDDATASELECTOR_H_ +#include + #include -#include -#include "Framework/AnalysisDataModel.h" namespace o2::aod { diff --git a/PWGJE/DataModel/JetReducedDataV0.h b/PWGJE/DataModel/JetReducedDataV0.h index d904403b532..433cd885f65 100644 --- a/PWGJE/DataModel/JetReducedDataV0.h +++ b/PWGJE/DataModel/JetReducedDataV0.h @@ -17,12 +17,14 @@ #ifndef PWGJE_DATAMODEL_JETREDUCEDDATAV0_H_ #define PWGJE_DATAMODEL_JETREDUCEDDATAV0_H_ -#include -#include -#include "Framework/AnalysisDataModel.h" -#include "PWGJE/DataModel/EMCALClusters.h" #include "PWGJE/DataModel/JetReducedData.h" +#include +#include // IWYU pragma: keep + +#include +#include + namespace o2::aod { diff --git a/PWGJE/DataModel/JetSubstructure.h b/PWGJE/DataModel/JetSubstructure.h index fcbf2987e52..97f51858553 100644 --- a/PWGJE/DataModel/JetSubstructure.h +++ b/PWGJE/DataModel/JetSubstructure.h @@ -17,22 +17,26 @@ #ifndef PWGJE_DATAMODEL_JETSUBSTRUCTURE_H_ #define PWGJE_DATAMODEL_JETSUBSTRUCTURE_H_ +#include "PWGDQ/DataModel/ReducedInfoTables.h" +#include "PWGHF/DataModel/DerivedTables.h" +#include "PWGJE/DataModel/Jet.h" // IWYU pragma: keep +#include "PWGJE/DataModel/JetReducedData.h" +#include "PWGJE/DataModel/JetReducedDataDQ.h" + +#include + #include +#include #include -#include "Framework/AnalysisDataModel.h" -#include "PWGJE/DataModel/EMCALClusters.h" -#include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGJE/DataModel/Jet.h" -#include "PWGJE/DataModel/JetReducedData.h" namespace o2::aod { namespace jetcollision -{ //! -DECLARE_SOA_COLUMN(PosZ, posZ, float); //! -DECLARE_SOA_COLUMN(Centrality, centrality, float); //! -DECLARE_SOA_COLUMN(EventSel, eventSel, uint8_t); //! +{ //! +DECLARE_SOA_COLUMN(PosZ, posZ, float); //! +DECLARE_SOA_COLUMN(Centrality, centrality, float); //! +DECLARE_SOA_COLUMN(EventSel, eventSel, uint8_t); //! DECLARE_SOA_COLUMN(EventWeight, eventWeight, float); //! } // namespace jetcollision @@ -47,15 +51,15 @@ DECLARE_SOA_COLUMN(EventWeight, eventWeight, float); //! } // namespace jetmccollision namespace jetsubstructure -{ //! -DECLARE_SOA_COLUMN(EnergyMother, energyMother, std::vector); //! -DECLARE_SOA_COLUMN(PtLeading, ptLeading, std::vector); //! -DECLARE_SOA_COLUMN(PtSubLeading, ptSubLeading, std::vector); //! -DECLARE_SOA_COLUMN(Theta, theta, std::vector); //! -DECLARE_SOA_COLUMN(NSub2DR, nSub2DR, float); //! -DECLARE_SOA_COLUMN(NSub1, nSub1, float); //! -DECLARE_SOA_COLUMN(NSub2, nSub2, float); //! -DECLARE_SOA_COLUMN(PairJetPt, pairJetPt, std::vector); //! +{ //! +DECLARE_SOA_COLUMN(EnergyMother, energyMother, std::vector); //! +DECLARE_SOA_COLUMN(PtLeading, ptLeading, std::vector); //! +DECLARE_SOA_COLUMN(PtSubLeading, ptSubLeading, std::vector); //! +DECLARE_SOA_COLUMN(Theta, theta, std::vector); //! +DECLARE_SOA_COLUMN(NSub2DR, nSub2DR, float); //! +DECLARE_SOA_COLUMN(NSub1, nSub1, float); //! +DECLARE_SOA_COLUMN(NSub2, nSub2, float); //! +DECLARE_SOA_COLUMN(PairJetPt, pairJetPt, std::vector); //! DECLARE_SOA_COLUMN(PairJetEnergy, pairJetEnergy, std::vector); //! DECLARE_SOA_COLUMN(PairJetTheta, pairJetTheta, std::vector); //! DECLARE_SOA_COLUMN(PairJetPerpCone1Pt, pairJetPerpCone1Pt, std::vector); //! @@ -67,13 +71,13 @@ DECLARE_SOA_COLUMN(PairPerpCone1PerpCone1Theta, pairPerpCone1PerpCone1Theta, std DECLARE_SOA_COLUMN(PairPerpCone1PerpCone2Pt, pairPerpCone1PerpCone2Pt, std::vector); //! DECLARE_SOA_COLUMN(PairPerpCone1PerpCone2Energy, pairPerpCone1PerpCone2Energy, std::vector); //! DECLARE_SOA_COLUMN(PairPerpCone1PerpCone2Theta, pairPerpCone1PerpCone2Theta, std::vector); //! -DECLARE_SOA_COLUMN(Angularity, angularity, float); //! -DECLARE_SOA_COLUMN(PtLeadingConstituent, ptLeadingConstituent, float); //! -DECLARE_SOA_COLUMN(PerpConeRho, perpConeRho, float); //! -DECLARE_SOA_COLUMN(SplittingMatchingGeo, splittingMatchingGeo, std::vector); //! -DECLARE_SOA_COLUMN(SplittingMatchingPt, splittingMatchingPt, std::vector); //! -DECLARE_SOA_COLUMN(SplittingMatchingHF, splittingMatchingHF, std::vector); //! -DECLARE_SOA_COLUMN(PairMatching, pairMatching, std::vector); //! +DECLARE_SOA_COLUMN(Angularity, angularity, float); //! +DECLARE_SOA_COLUMN(PtLeadingConstituent, ptLeadingConstituent, float); //! +DECLARE_SOA_COLUMN(PerpConeRho, perpConeRho, float); //! +DECLARE_SOA_COLUMN(SplittingMatchingGeo, splittingMatchingGeo, std::vector); //! +DECLARE_SOA_COLUMN(SplittingMatchingPt, splittingMatchingPt, std::vector); //! +DECLARE_SOA_COLUMN(SplittingMatchingHF, splittingMatchingHF, std::vector); //! +DECLARE_SOA_COLUMN(PairMatching, pairMatching, std::vector); //! } // namespace jetsubstructure namespace splitting diff --git a/PWGJE/DataModel/JetSubtraction.h b/PWGJE/DataModel/JetSubtraction.h index 55879d009c1..45b22855325 100644 --- a/PWGJE/DataModel/JetSubtraction.h +++ b/PWGJE/DataModel/JetSubtraction.h @@ -18,14 +18,14 @@ #ifndef PWGJE_DATAMODEL_JETSUBTRACTION_H_ #define PWGJE_DATAMODEL_JETSUBTRACTION_H_ -#include -#include "Framework/AnalysisDataModel.h" -#include "PWGJE/DataModel/EMCALClusters.h" +#include "PWGDQ/DataModel/ReducedInfoTables.h" +#include "PWGHF/DataModel/DerivedTables.h" #include "PWGJE/DataModel/JetReducedData.h" #include "PWGJE/DataModel/JetReducedDataDQ.h" -#include "PWGHF/DataModel/DerivedTables.h" -#include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGDQ/DataModel/ReducedInfoTables.h" + +#include + +#include namespace o2::aod { diff --git a/PWGJE/DataModel/JetTagging.h b/PWGJE/DataModel/JetTagging.h index b84d9f01964..9d8f5eceb80 100644 --- a/PWGJE/DataModel/JetTagging.h +++ b/PWGJE/DataModel/JetTagging.h @@ -18,11 +18,18 @@ #ifndef PWGJE_DATAMODEL_JETTAGGING_H_ #define PWGJE_DATAMODEL_JETTAGGING_H_ -#include -#include -#include "Framework/AnalysisDataModel.h" -#include "PWGJE/DataModel/Jet.h" +#include "RecoDecay.h" + #include "PWGJE/Core/JetTaggingUtilities.h" +#include "PWGJE/DataModel/Jet.h" // IWYU pragma: keep + +#include + +#include + +#include +#include +#include namespace o2::aod { diff --git a/PWGJE/DataModel/TrackJetQa.h b/PWGJE/DataModel/TrackJetQa.h index 913f43c29b0..2ad30d88a51 100644 --- a/PWGJE/DataModel/TrackJetQa.h +++ b/PWGJE/DataModel/TrackJetQa.h @@ -19,18 +19,12 @@ #ifndef PWGJE_DATAMODEL_TRACKJETQA_H_ #define PWGJE_DATAMODEL_TRACKJETQA_H_ -// O2 includes -#include "ReconstructionDataFormats/Track.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/AnalysisDataModel.h" -#include "PWGJE/DataModel/Jet.h" -#include "Framework/StaticFor.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectionDefaults.h" + +#include +#include + +#include // Derived data model for track optimization (and cut variation) namespace o2::aod diff --git a/PWGJE/JetFinders/Duplicates/jetFinderDataCharged1.cxx b/PWGJE/JetFinders/Duplicates/jetFinderDataCharged1.cxx index 46f2dd88df8..ac0363bf901 100644 --- a/PWGJE/JetFinders/Duplicates/jetFinderDataCharged1.cxx +++ b/PWGJE/JetFinders/Duplicates/jetFinderDataCharged1.cxx @@ -15,6 +15,15 @@ #include "PWGJE/JetFinders/jetFinder.cxx" +#include "PWGJE/DataModel/Jet.h" + +#include +#include +#include +#include + +#include + using JetFinderDataCharged1 = JetFinderTask; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/JetFinders/Duplicates/jetFinderMCDCharged1.cxx b/PWGJE/JetFinders/Duplicates/jetFinderMCDCharged1.cxx index 4a13537a48b..49f2ce1d957 100644 --- a/PWGJE/JetFinders/Duplicates/jetFinderMCDCharged1.cxx +++ b/PWGJE/JetFinders/Duplicates/jetFinderMCDCharged1.cxx @@ -15,6 +15,15 @@ #include "PWGJE/JetFinders/jetFinder.cxx" +#include "PWGJE/DataModel/Jet.h" + +#include +#include +#include +#include + +#include + using JetFinderMCDetectorLevelCharged1 = JetFinderTask; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/JetFinders/Duplicates/jetFinderMCPCharged1.cxx b/PWGJE/JetFinders/Duplicates/jetFinderMCPCharged1.cxx index 68e3f861ae6..1ae7eed6100 100644 --- a/PWGJE/JetFinders/Duplicates/jetFinderMCPCharged1.cxx +++ b/PWGJE/JetFinders/Duplicates/jetFinderMCPCharged1.cxx @@ -15,6 +15,15 @@ #include "PWGJE/JetFinders/jetFinder.cxx" +#include "PWGJE/DataModel/Jet.h" + +#include +#include +#include +#include + +#include + using JetFinderMCParticleLevelCharged1 = JetFinderTask; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/JetFinders/jetFinder.cxx b/PWGJE/JetFinders/jetFinder.cxx index 9d0ff6789b3..3c624c8969d 100644 --- a/PWGJE/JetFinders/jetFinder.cxx +++ b/PWGJE/JetFinders/jetFinder.cxx @@ -15,33 +15,33 @@ /// \author Jochen Klein /// \author Raymond Ehlers , ORNL +#include "PWGJE/Core/JetFinder.h" + +#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include "PWGJE/Core/JetFindingUtilities.h" +#include "PWGJE/DataModel/EMCALClusterDefinition.h" +#include "PWGJE/DataModel/EMCALClusters.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" + #include #include #include -#include #include #include #include #include -#include // IWYU pragma: keep (needed in tasks) +#include // IWYU pragma: export -#include -#include -#include +#include +#include #include #include -#include -#include - -#include "PWGJE/Core/JetDerivedDataUtilities.h" -#include "PWGJE/Core/JetFinder.h" -#include "PWGJE/Core/JetFindingUtilities.h" -#include "PWGJE/DataModel/EMCALClusterDefinition.h" -#include "PWGJE/DataModel/EMCALClusters.h" -#include "PWGJE/DataModel/Jet.h" -#include "PWGJE/DataModel/JetReducedData.h" +#include +#include +#include using namespace o2; using namespace o2::framework; diff --git a/PWGJE/JetFinders/jetFinderBplusDataCharged.cxx b/PWGJE/JetFinders/jetFinderBplusDataCharged.cxx index 402527211fb..087fbc6b37e 100644 --- a/PWGJE/JetFinders/jetFinderBplusDataCharged.cxx +++ b/PWGJE/JetFinders/jetFinderBplusDataCharged.cxx @@ -15,6 +15,15 @@ #include "PWGJE/JetFinders/jetFinderHF.cxx" +#include "PWGJE/DataModel/Jet.h" + +#include +#include +#include +#include + +#include + using JetFinderBplusDataCharged = JetFinderHFTask; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/JetFinders/jetFinderBplusMCDCharged.cxx b/PWGJE/JetFinders/jetFinderBplusMCDCharged.cxx index 4eed52e30b3..9dba69eba51 100644 --- a/PWGJE/JetFinders/jetFinderBplusMCDCharged.cxx +++ b/PWGJE/JetFinders/jetFinderBplusMCDCharged.cxx @@ -15,6 +15,15 @@ #include "PWGJE/JetFinders/jetFinderHF.cxx" +#include "PWGJE/DataModel/Jet.h" + +#include +#include +#include +#include + +#include + using JetFinderBplusMCDetectorLevelCharged = JetFinderHFTask; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/JetFinders/jetFinderBplusMCPCharged.cxx b/PWGJE/JetFinders/jetFinderBplusMCPCharged.cxx index 83a1e7c9d60..639b02bfe2e 100644 --- a/PWGJE/JetFinders/jetFinderBplusMCPCharged.cxx +++ b/PWGJE/JetFinders/jetFinderBplusMCPCharged.cxx @@ -15,6 +15,15 @@ #include "PWGJE/JetFinders/jetFinderHF.cxx" +#include "PWGJE/DataModel/Jet.h" + +#include +#include +#include +#include + +#include + using JetFinderBplusMCParticleLevelCharged = JetFinderHFTask; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/JetFinders/jetFinderD0DataCharged.cxx b/PWGJE/JetFinders/jetFinderD0DataCharged.cxx index 29ab757dbce..70e00c246d4 100644 --- a/PWGJE/JetFinders/jetFinderD0DataCharged.cxx +++ b/PWGJE/JetFinders/jetFinderD0DataCharged.cxx @@ -15,6 +15,15 @@ #include "PWGJE/JetFinders/jetFinderHF.cxx" +#include "PWGJE/DataModel/Jet.h" + +#include +#include +#include +#include + +#include + using JetFinderD0DataCharged = JetFinderHFTask; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/JetFinders/jetFinderD0MCDCharged.cxx b/PWGJE/JetFinders/jetFinderD0MCDCharged.cxx index 46847bf8651..62c740a7152 100644 --- a/PWGJE/JetFinders/jetFinderD0MCDCharged.cxx +++ b/PWGJE/JetFinders/jetFinderD0MCDCharged.cxx @@ -15,6 +15,15 @@ #include "PWGJE/JetFinders/jetFinderHF.cxx" +#include "PWGJE/DataModel/Jet.h" + +#include +#include +#include +#include + +#include + using JetFinderD0MCDetectorLevelCharged = JetFinderHFTask; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/JetFinders/jetFinderD0MCPCharged.cxx b/PWGJE/JetFinders/jetFinderD0MCPCharged.cxx index a21aceff347..34bee4644ce 100644 --- a/PWGJE/JetFinders/jetFinderD0MCPCharged.cxx +++ b/PWGJE/JetFinders/jetFinderD0MCPCharged.cxx @@ -15,6 +15,15 @@ #include "PWGJE/JetFinders/jetFinderHF.cxx" +#include "PWGJE/DataModel/Jet.h" + +#include +#include +#include +#include + +#include + using JetFinderD0MCParticleLevelCharged = JetFinderHFTask; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/JetFinders/jetFinderDataCharged.cxx b/PWGJE/JetFinders/jetFinderDataCharged.cxx index e713eb4fa7c..016d83611bb 100644 --- a/PWGJE/JetFinders/jetFinderDataCharged.cxx +++ b/PWGJE/JetFinders/jetFinderDataCharged.cxx @@ -15,6 +15,15 @@ #include "PWGJE/JetFinders/jetFinder.cxx" +#include "PWGJE/DataModel/Jet.h" + +#include +#include +#include +#include + +#include + using JetFinderDataCharged = JetFinderTask; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/JetFinders/jetFinderDataFull.cxx b/PWGJE/JetFinders/jetFinderDataFull.cxx index 07d103d93b2..acf33725099 100644 --- a/PWGJE/JetFinders/jetFinderDataFull.cxx +++ b/PWGJE/JetFinders/jetFinderDataFull.cxx @@ -15,6 +15,15 @@ #include "PWGJE/JetFinders/jetFinder.cxx" +#include "PWGJE/DataModel/Jet.h" + +#include +#include +#include +#include + +#include + using JetFinderDataFull = JetFinderTask; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/JetFinders/jetFinderDataNeutral.cxx b/PWGJE/JetFinders/jetFinderDataNeutral.cxx index 28a1b898a15..afb223deb74 100644 --- a/PWGJE/JetFinders/jetFinderDataNeutral.cxx +++ b/PWGJE/JetFinders/jetFinderDataNeutral.cxx @@ -15,6 +15,15 @@ #include "PWGJE/JetFinders/jetFinder.cxx" +#include "PWGJE/DataModel/Jet.h" + +#include +#include +#include +#include + +#include + using JetFinderDataNeutral = JetFinderTask; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/JetFinders/jetFinderDielectronDataCharged.cxx b/PWGJE/JetFinders/jetFinderDielectronDataCharged.cxx index 2b040080579..7f4657d1127 100644 --- a/PWGJE/JetFinders/jetFinderDielectronDataCharged.cxx +++ b/PWGJE/JetFinders/jetFinderDielectronDataCharged.cxx @@ -15,6 +15,15 @@ #include "PWGJE/JetFinders/jetFinderHF.cxx" +#include "PWGJE/DataModel/Jet.h" + +#include +#include +#include +#include + +#include + using JetFinderDielectronDataCharged = JetFinderHFTask; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/JetFinders/jetFinderDielectronMCDCharged.cxx b/PWGJE/JetFinders/jetFinderDielectronMCDCharged.cxx index 105b58d459a..1d14666ca10 100644 --- a/PWGJE/JetFinders/jetFinderDielectronMCDCharged.cxx +++ b/PWGJE/JetFinders/jetFinderDielectronMCDCharged.cxx @@ -15,6 +15,15 @@ #include "PWGJE/JetFinders/jetFinderHF.cxx" +#include "PWGJE/DataModel/Jet.h" + +#include +#include +#include +#include + +#include + using JetFinderDielectronMCDetectorLevelCharged = JetFinderHFTask; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/JetFinders/jetFinderDielectronMCPCharged.cxx b/PWGJE/JetFinders/jetFinderDielectronMCPCharged.cxx index b6aa797e80e..b0be942e08e 100644 --- a/PWGJE/JetFinders/jetFinderDielectronMCPCharged.cxx +++ b/PWGJE/JetFinders/jetFinderDielectronMCPCharged.cxx @@ -15,6 +15,15 @@ #include "PWGJE/JetFinders/jetFinderHF.cxx" +#include "PWGJE/DataModel/Jet.h" + +#include +#include +#include +#include + +#include + using JetFinderDielectronMCParticleLevelCharged = JetFinderHFTask; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/JetFinders/jetFinderDplusDataCharged.cxx b/PWGJE/JetFinders/jetFinderDplusDataCharged.cxx index a0cdbdf2a24..c684fbc2e8c 100644 --- a/PWGJE/JetFinders/jetFinderDplusDataCharged.cxx +++ b/PWGJE/JetFinders/jetFinderDplusDataCharged.cxx @@ -15,6 +15,15 @@ #include "PWGJE/JetFinders/jetFinderHF.cxx" +#include "PWGJE/DataModel/Jet.h" + +#include +#include +#include +#include + +#include + using JetFinderDplusDataCharged = JetFinderHFTask; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/JetFinders/jetFinderDplusMCDCharged.cxx b/PWGJE/JetFinders/jetFinderDplusMCDCharged.cxx index 0a401d330ef..ebdbe27c015 100644 --- a/PWGJE/JetFinders/jetFinderDplusMCDCharged.cxx +++ b/PWGJE/JetFinders/jetFinderDplusMCDCharged.cxx @@ -15,6 +15,15 @@ #include "PWGJE/JetFinders/jetFinderHF.cxx" +#include "PWGJE/DataModel/Jet.h" + +#include +#include +#include +#include + +#include + using JetFinderDplusMCDetectorLevelCharged = JetFinderHFTask; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/JetFinders/jetFinderDplusMCPCharged.cxx b/PWGJE/JetFinders/jetFinderDplusMCPCharged.cxx index 4c5cb4a604d..da79b1c2c0e 100644 --- a/PWGJE/JetFinders/jetFinderDplusMCPCharged.cxx +++ b/PWGJE/JetFinders/jetFinderDplusMCPCharged.cxx @@ -15,6 +15,15 @@ #include "PWGJE/JetFinders/jetFinderHF.cxx" +#include "PWGJE/DataModel/Jet.h" + +#include +#include +#include +#include + +#include + using JetFinderDplusMCParticleLevelCharged = JetFinderHFTask; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/JetFinders/jetFinderHF.cxx b/PWGJE/JetFinders/jetFinderHF.cxx index 68a874e2955..66cb612075d 100644 --- a/PWGJE/JetFinders/jetFinderHF.cxx +++ b/PWGJE/JetFinders/jetFinderHF.cxx @@ -14,33 +14,32 @@ /// \author Nima Zardoshti /// \author Jochen Klein +#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include "PWGJE/Core/JetFinder.h" +#include "PWGJE/Core/JetFindingUtilities.h" +#include "PWGJE/DataModel/EMCALClusterDefinition.h" +#include "PWGJE/DataModel/EMCALClusters.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" +#include "PWGJE/DataModel/JetSubtraction.h" + #include #include #include -#include #include #include #include #include -#include // IWYU pragma: keep (needed in tasks) +#include // IWYU pragma: export -#include -#include +#include +#include #include #include -#include -#include - -#include "PWGJE/Core/JetDerivedDataUtilities.h" -#include "PWGJE/Core/JetFinder.h" -#include "PWGJE/Core/JetFindingUtilities.h" -#include "PWGJE/DataModel/EMCALClusterDefinition.h" -#include "PWGJE/DataModel/EMCALClusters.h" -#include "PWGJE/DataModel/Jet.h" -#include "PWGJE/DataModel/JetReducedData.h" -#include "PWGJE/DataModel/JetSubtraction.h" +#include +#include using namespace o2; using namespace o2::framework; diff --git a/PWGJE/JetFinders/jetFinderLcDataCharged.cxx b/PWGJE/JetFinders/jetFinderLcDataCharged.cxx index 821cbd87df8..37af66ca1b4 100644 --- a/PWGJE/JetFinders/jetFinderLcDataCharged.cxx +++ b/PWGJE/JetFinders/jetFinderLcDataCharged.cxx @@ -15,6 +15,15 @@ #include "PWGJE/JetFinders/jetFinderHF.cxx" +#include "PWGJE/DataModel/Jet.h" + +#include +#include +#include +#include + +#include + using JetFinderLcDataCharged = JetFinderHFTask; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/JetFinders/jetFinderLcMCDCharged.cxx b/PWGJE/JetFinders/jetFinderLcMCDCharged.cxx index c25f35c0efb..9172f395fb8 100644 --- a/PWGJE/JetFinders/jetFinderLcMCDCharged.cxx +++ b/PWGJE/JetFinders/jetFinderLcMCDCharged.cxx @@ -15,6 +15,15 @@ #include "PWGJE/JetFinders/jetFinderHF.cxx" +#include "PWGJE/DataModel/Jet.h" + +#include +#include +#include +#include + +#include + using JetFinderLcMCDetectorLevelCharged = JetFinderHFTask; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/JetFinders/jetFinderLcMCPCharged.cxx b/PWGJE/JetFinders/jetFinderLcMCPCharged.cxx index 41607ed57d9..e9a1fd14346 100644 --- a/PWGJE/JetFinders/jetFinderLcMCPCharged.cxx +++ b/PWGJE/JetFinders/jetFinderLcMCPCharged.cxx @@ -15,6 +15,15 @@ #include "PWGJE/JetFinders/jetFinderHF.cxx" +#include "PWGJE/DataModel/Jet.h" + +#include +#include +#include +#include + +#include + using JetFinderLcMCParticleLevelCharged = JetFinderHFTask; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/JetFinders/jetFinderMCDCharged.cxx b/PWGJE/JetFinders/jetFinderMCDCharged.cxx index d8558a57770..198d1b87d98 100644 --- a/PWGJE/JetFinders/jetFinderMCDCharged.cxx +++ b/PWGJE/JetFinders/jetFinderMCDCharged.cxx @@ -15,6 +15,15 @@ #include "PWGJE/JetFinders/jetFinder.cxx" +#include "PWGJE/DataModel/Jet.h" + +#include +#include +#include +#include + +#include + using JetFinderMCDetectorLevelCharged = JetFinderTask; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/JetFinders/jetFinderMCDFull.cxx b/PWGJE/JetFinders/jetFinderMCDFull.cxx index 0123b75d823..ce5b8ec42ec 100644 --- a/PWGJE/JetFinders/jetFinderMCDFull.cxx +++ b/PWGJE/JetFinders/jetFinderMCDFull.cxx @@ -15,6 +15,15 @@ #include "PWGJE/JetFinders/jetFinder.cxx" +#include "PWGJE/DataModel/Jet.h" + +#include +#include +#include +#include + +#include + using JetFinderMCDetectorLevelFull = JetFinderTask; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/JetFinders/jetFinderMCDNeutral.cxx b/PWGJE/JetFinders/jetFinderMCDNeutral.cxx index 9e8225b0c5f..e532c3d528b 100644 --- a/PWGJE/JetFinders/jetFinderMCDNeutral.cxx +++ b/PWGJE/JetFinders/jetFinderMCDNeutral.cxx @@ -15,6 +15,15 @@ #include "PWGJE/JetFinders/jetFinder.cxx" +#include "PWGJE/DataModel/Jet.h" + +#include +#include +#include +#include + +#include + using JetFinderMCDetectorLevelNeutral = JetFinderTask; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/JetFinders/jetFinderMCPCharged.cxx b/PWGJE/JetFinders/jetFinderMCPCharged.cxx index 9cba0092a53..98538de9708 100644 --- a/PWGJE/JetFinders/jetFinderMCPCharged.cxx +++ b/PWGJE/JetFinders/jetFinderMCPCharged.cxx @@ -15,6 +15,15 @@ #include "PWGJE/JetFinders/jetFinder.cxx" +#include "PWGJE/DataModel/Jet.h" + +#include +#include +#include +#include + +#include + using JetFinderMCParticleLevelCharged = JetFinderTask; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/JetFinders/jetFinderMCPFull.cxx b/PWGJE/JetFinders/jetFinderMCPFull.cxx index ff9c26e4d91..217a1cfe928 100644 --- a/PWGJE/JetFinders/jetFinderMCPFull.cxx +++ b/PWGJE/JetFinders/jetFinderMCPFull.cxx @@ -15,6 +15,15 @@ #include "PWGJE/JetFinders/jetFinder.cxx" +#include "PWGJE/DataModel/Jet.h" + +#include +#include +#include +#include + +#include + using JetFinderMCParticleLevelFull = JetFinderTask; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/JetFinders/jetFinderMCPNeutral.cxx b/PWGJE/JetFinders/jetFinderMCPNeutral.cxx index 8593fb1f644..b2240dbe6e4 100644 --- a/PWGJE/JetFinders/jetFinderMCPNeutral.cxx +++ b/PWGJE/JetFinders/jetFinderMCPNeutral.cxx @@ -15,6 +15,15 @@ #include "PWGJE/JetFinders/jetFinder.cxx" +#include "PWGJE/DataModel/Jet.h" + +#include +#include +#include +#include + +#include + using JetFinderMCParticleLevelNeutral = JetFinderTask; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/JetFinders/jetFinderV0.cxx b/PWGJE/JetFinders/jetFinderV0.cxx index ece753369d9..efa00d6a7dc 100644 --- a/PWGJE/JetFinders/jetFinderV0.cxx +++ b/PWGJE/JetFinders/jetFinderV0.cxx @@ -13,31 +13,29 @@ // /// \author Nima Zardoshti +#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include "PWGJE/Core/JetFinder.h" +#include "PWGJE/Core/JetFindingUtilities.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" + #include #include #include -#include #include #include #include #include -#include // IWYU pragma: keep (needed in tasks) +#include // IWYU pragma: export -#include -#include +#include +#include #include #include -#include -#include - -#include "PWGJE/Core/JetDerivedDataUtilities.h" -#include "PWGJE/Core/JetFinder.h" -#include "PWGJE/Core/JetFindingUtilities.h" -#include "PWGJE/DataModel/Jet.h" -#include "PWGJE/DataModel/JetReducedData.h" -#include "PWGLF/DataModel/V0SelectorTables.h" +#include +#include using namespace o2; using namespace o2::framework; diff --git a/PWGJE/JetFinders/jetFinderV0DataCharged.cxx b/PWGJE/JetFinders/jetFinderV0DataCharged.cxx index 7b1ac0a261f..1b239661afd 100644 --- a/PWGJE/JetFinders/jetFinderV0DataCharged.cxx +++ b/PWGJE/JetFinders/jetFinderV0DataCharged.cxx @@ -15,6 +15,15 @@ #include "PWGJE/JetFinders/jetFinderV0.cxx" +#include "PWGJE/DataModel/Jet.h" + +#include +#include +#include +#include + +#include + using JetFinderV0DataCharged = JetFinderV0Task; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/JetFinders/jetFinderV0MCDCharged.cxx b/PWGJE/JetFinders/jetFinderV0MCDCharged.cxx index 30442208085..890b3334776 100644 --- a/PWGJE/JetFinders/jetFinderV0MCDCharged.cxx +++ b/PWGJE/JetFinders/jetFinderV0MCDCharged.cxx @@ -15,6 +15,15 @@ #include "PWGJE/JetFinders/jetFinderV0.cxx" +#include "PWGJE/DataModel/Jet.h" + +#include +#include +#include +#include + +#include + using JetFinderV0MCDetectorLevelCharged = JetFinderV0Task; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/JetFinders/jetFinderV0MCPCharged.cxx b/PWGJE/JetFinders/jetFinderV0MCPCharged.cxx index 27de0bdbc3c..3704f8f67b0 100644 --- a/PWGJE/JetFinders/jetFinderV0MCPCharged.cxx +++ b/PWGJE/JetFinders/jetFinderV0MCPCharged.cxx @@ -15,6 +15,15 @@ #include "PWGJE/JetFinders/jetFinderV0.cxx" +#include "PWGJE/DataModel/Jet.h" + +#include +#include +#include +#include + +#include + using JetFinderV0MCParticleLevelCharged = JetFinderV0Task; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/TableProducer/Matching/Duplicates/jetMatchingDuplicates.cxx b/PWGJE/TableProducer/Matching/Duplicates/jetMatchingDuplicates.cxx index 1155c169f55..9e7d28ef94f 100644 --- a/PWGJE/TableProducer/Matching/Duplicates/jetMatchingDuplicates.cxx +++ b/PWGJE/TableProducer/Matching/Duplicates/jetMatchingDuplicates.cxx @@ -13,20 +13,17 @@ /// \brief matching duplicate jets /// \author Nima Zardoshti -#include +#include "PWGJE/Core/JetMatchingUtilities.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" #include "Framework/ASoA.h" -#include "Framework/runDataProcessing.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" +#include +#include +#include +#include // IWYU pragma: export -#include "PWGJE/DataModel/Jet.h" -#include "PWGJE/Core/JetUtilities.h" -#include "PWGJE/Core/JetFindingUtilities.h" -#include "PWGJE/Core/JetMatchingUtilities.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" +#include using namespace o2; using namespace o2::framework; diff --git a/PWGJE/TableProducer/Matching/Duplicates/jetMatchingDuplicatesChargedData1.cxx b/PWGJE/TableProducer/Matching/Duplicates/jetMatchingDuplicatesChargedData1.cxx index 8115c95bf04..acf6346f615 100644 --- a/PWGJE/TableProducer/Matching/Duplicates/jetMatchingDuplicatesChargedData1.cxx +++ b/PWGJE/TableProducer/Matching/Duplicates/jetMatchingDuplicatesChargedData1.cxx @@ -15,6 +15,17 @@ #include "PWGJE/TableProducer/Matching/Duplicates/jetMatchingDuplicates.cxx" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" + +#include +#include +#include +#include +#include + +#include + using Charged1JetDataMatchingDupliacates = JetMatchingDuplicates, soa::Join, aod::ChargedJetsMatchedToCharged1Jets, diff --git a/PWGJE/TableProducer/Matching/Duplicates/jetMatchingDuplicatesChargedMCD1.cxx b/PWGJE/TableProducer/Matching/Duplicates/jetMatchingDuplicatesChargedMCD1.cxx index 96033d17d4e..b900fb9f0c1 100644 --- a/PWGJE/TableProducer/Matching/Duplicates/jetMatchingDuplicatesChargedMCD1.cxx +++ b/PWGJE/TableProducer/Matching/Duplicates/jetMatchingDuplicatesChargedMCD1.cxx @@ -15,6 +15,17 @@ #include "PWGJE/TableProducer/Matching/Duplicates/jetMatchingDuplicates.cxx" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" + +#include +#include +#include +#include +#include + +#include + using Charged1JetMCDMatchingDupliacates = JetMatchingDuplicates, soa::Join, aod::ChargedMCDetectorLevelJetsMatchedToCharged1MCDetectorLevelJets, diff --git a/PWGJE/TableProducer/Matching/Duplicates/jetMatchingDuplicatesChargedMCP1.cxx b/PWGJE/TableProducer/Matching/Duplicates/jetMatchingDuplicatesChargedMCP1.cxx index 11b39822bcb..f913f810191 100644 --- a/PWGJE/TableProducer/Matching/Duplicates/jetMatchingDuplicatesChargedMCP1.cxx +++ b/PWGJE/TableProducer/Matching/Duplicates/jetMatchingDuplicatesChargedMCP1.cxx @@ -15,6 +15,17 @@ #include "PWGJE/TableProducer/Matching/Duplicates/jetMatchingDuplicates.cxx" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" + +#include +#include +#include +#include +#include + +#include + using Charged1JetMCPMatchingDupliacates = JetMatchingDuplicates, soa::Join, aod::ChargedMCParticleLevelJetsMatchedToCharged1MCParticleLevelJets, diff --git a/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatching.cxx b/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatching.cxx index 6d72dbf880f..3759901939d 100644 --- a/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatching.cxx +++ b/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatching.cxx @@ -14,36 +14,22 @@ /// \author Nima Zardoshti // -#include - -#include "fastjet/PseudoJet.hh" -#include "fastjet/ClusterSequenceArea.hh" +#include "PWGJE/Core/JetMatchingUtilities.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetSubstructure.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" #include "Framework/ASoA.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "Framework/HistogramRegistry.h" - -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectionDefaults.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" +#include +#include +#include +#include // IWYU pragma: export -#include "PWGJE/DataModel/Jet.h" -#include "PWGJE/DataModel/JetSubstructure.h" -#include "PWGJE/Core/JetFinder.h" -#include "PWGJE/Core/FastJetUtilities.h" -#include "PWGJE/Core/JetUtilities.h" -#include "PWGJE/Core/JetSubstructureUtilities.h" -#include "PWGJE/Core/JetMatchingUtilities.h" +#include using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; -#include "Framework/runDataProcessing.h" - template struct JetSubstructureMatching { diff --git a/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingMCBplusCharged.cxx b/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingMCBplusCharged.cxx index 06e1fe45729..27bfc4ca22f 100644 --- a/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingMCBplusCharged.cxx +++ b/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingMCBplusCharged.cxx @@ -13,9 +13,20 @@ // /// \author Nima Zardoshti -#include #include "PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatching.cxx" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" +#include "PWGJE/DataModel/JetSubstructure.h" + +#include +#include +#include +#include +#include + +#include + using BplusChargedJetSubstructureMatchingMC = JetSubstructureMatching, soa::Join, aod::BplusChargedMCDetectorLevelSPsMatchedToBplusChargedMCParticleLevelSPs, diff --git a/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingMCCharged.cxx b/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingMCCharged.cxx index 42df0f0bb10..e73fab8c77e 100644 --- a/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingMCCharged.cxx +++ b/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingMCCharged.cxx @@ -13,9 +13,20 @@ // /// \author Nima Zardoshti -#include #include "PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatching.cxx" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" +#include "PWGJE/DataModel/JetSubstructure.h" + +#include +#include +#include +#include +#include + +#include + using ChargedJetSubstructureMatchingMC = JetSubstructureMatching, soa::Join, aod::ChargedMCDetectorLevelSPsMatchedToChargedMCParticleLevelSPs, diff --git a/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingMCD0Charged.cxx b/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingMCD0Charged.cxx index 1781ed34392..82ae0adbb91 100644 --- a/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingMCD0Charged.cxx +++ b/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingMCD0Charged.cxx @@ -13,9 +13,20 @@ // /// \author Nima Zardoshti -#include #include "PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatching.cxx" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" +#include "PWGJE/DataModel/JetSubstructure.h" + +#include +#include +#include +#include +#include + +#include + using D0ChargedJetSubstructureMatchingMC = JetSubstructureMatching, soa::Join, aod::D0ChargedMCDetectorLevelSPsMatchedToD0ChargedMCParticleLevelSPs, diff --git a/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingMCDielectronCharged.cxx b/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingMCDielectronCharged.cxx index f063d263478..395617bed72 100644 --- a/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingMCDielectronCharged.cxx +++ b/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingMCDielectronCharged.cxx @@ -13,9 +13,20 @@ // /// \author Nima Zardoshti -#include #include "PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatching.cxx" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" +#include "PWGJE/DataModel/JetSubstructure.h" + +#include +#include +#include +#include +#include + +#include + using DielectronChargedJetSubstructureMatchingMC = JetSubstructureMatching, soa::Join, aod::DielectronChargedMCDetectorLevelSPsMatchedToDielectronChargedMCParticleLevelSPs, diff --git a/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingMCDplusCharged.cxx b/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingMCDplusCharged.cxx index 34f4f145f13..47ee3fb6757 100644 --- a/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingMCDplusCharged.cxx +++ b/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingMCDplusCharged.cxx @@ -13,9 +13,20 @@ // /// \author Nima Zardoshti -#include #include "PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatching.cxx" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" +#include "PWGJE/DataModel/JetSubstructure.h" + +#include +#include +#include +#include +#include + +#include + using DplusChargedJetSubstructureMatchingMC = JetSubstructureMatching, soa::Join, aod::DplusChargedMCDetectorLevelSPsMatchedToDplusChargedMCParticleLevelSPs, diff --git a/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingMCLcCharged.cxx b/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingMCLcCharged.cxx index b5b5bb302a5..1744d6b24fe 100644 --- a/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingMCLcCharged.cxx +++ b/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingMCLcCharged.cxx @@ -13,9 +13,20 @@ // /// \author Nima Zardoshti -#include #include "PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatching.cxx" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" +#include "PWGJE/DataModel/JetSubstructure.h" + +#include +#include +#include +#include +#include + +#include + using LcChargedJetSubstructureMatchingMC = JetSubstructureMatching, soa::Join, aod::LcChargedMCDetectorLevelSPsMatchedToLcChargedMCParticleLevelSPs, diff --git a/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingSub.cxx b/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingSub.cxx index 5c1382671d2..f1eb5333081 100644 --- a/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingSub.cxx +++ b/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingSub.cxx @@ -15,36 +15,22 @@ /// \author Nima Zardoshti // -#include - -#include "fastjet/PseudoJet.hh" -#include "fastjet/ClusterSequenceArea.hh" +#include "PWGJE/Core/JetMatchingUtilities.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetSubstructure.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" #include "Framework/ASoA.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "Framework/HistogramRegistry.h" - -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectionDefaults.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" +#include +#include +#include +#include // IWYU pragma: export -#include "PWGJE/DataModel/Jet.h" -#include "PWGJE/DataModel/JetSubstructure.h" -#include "PWGJE/Core/JetFinder.h" -#include "PWGJE/Core/FastJetUtilities.h" -#include "PWGJE/Core/JetUtilities.h" -#include "PWGJE/Core/JetSubstructureUtilities.h" -#include "PWGJE/Core/JetMatchingUtilities.h" +#include using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; -#include "Framework/runDataProcessing.h" - template struct JetSubstructureMatchingSub { diff --git a/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingSubBplusCharged.cxx b/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingSubBplusCharged.cxx index 901ff6226a3..fd7fecd0264 100644 --- a/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingSubBplusCharged.cxx +++ b/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingSubBplusCharged.cxx @@ -13,9 +13,20 @@ // /// \author Nima Zardoshti -#include #include "PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingSub.cxx" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" +#include "PWGJE/DataModel/JetSubstructure.h" + +#include +#include +#include +#include +#include + +#include + using BplusChargedJetSubstructureMatchingSub = JetSubstructureMatchingSub, soa::Join, aod::BplusChargedSPsMatchedToBplusChargedEventWiseSubtractedSPs, diff --git a/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingSubCharged.cxx b/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingSubCharged.cxx index 618d55d7c5b..60fe610ad61 100644 --- a/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingSubCharged.cxx +++ b/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingSubCharged.cxx @@ -13,9 +13,20 @@ // /// \author Nima Zardoshti -#include #include "PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingSub.cxx" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" +#include "PWGJE/DataModel/JetSubstructure.h" + +#include +#include +#include +#include +#include + +#include + using ChargedJetSubstructureMatchingSub = JetSubstructureMatchingSub, soa::Join, aod::ChargedSPsMatchedToChargedEventWiseSubtractedSPs, diff --git a/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingSubD0Charged.cxx b/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingSubD0Charged.cxx index f53ebf3ae39..45e2bcb3ef2 100644 --- a/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingSubD0Charged.cxx +++ b/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingSubD0Charged.cxx @@ -13,9 +13,20 @@ // /// \author Nima Zardoshti -#include #include "PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingSub.cxx" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" +#include "PWGJE/DataModel/JetSubstructure.h" + +#include +#include +#include +#include +#include + +#include + using D0ChargedJetSubstructureMatchingSub = JetSubstructureMatchingSub, soa::Join, aod::D0ChargedSPsMatchedToD0ChargedEventWiseSubtractedSPs, diff --git a/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingSubDielectronCharged.cxx b/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingSubDielectronCharged.cxx index 71fad02021d..d9f748252f5 100644 --- a/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingSubDielectronCharged.cxx +++ b/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingSubDielectronCharged.cxx @@ -13,9 +13,20 @@ // /// \author Nima Zardoshti -#include #include "PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingSub.cxx" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" +#include "PWGJE/DataModel/JetSubstructure.h" + +#include +#include +#include +#include +#include + +#include + using DielectronChargedJetSubstructureMatchingSub = JetSubstructureMatchingSub, soa::Join, aod::DielectronChargedSPsMatchedToDielectronChargedEventWiseSubtractedSPs, diff --git a/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingSubDplusCharged.cxx b/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingSubDplusCharged.cxx index 662b227b08a..9d07e6a3bde 100644 --- a/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingSubDplusCharged.cxx +++ b/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingSubDplusCharged.cxx @@ -13,9 +13,20 @@ // /// \author Nima Zardoshti -#include #include "PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingSub.cxx" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" +#include "PWGJE/DataModel/JetSubstructure.h" + +#include +#include +#include +#include +#include + +#include + using DplusChargedJetSubstructureMatchingSub = JetSubstructureMatchingSub, soa::Join, aod::DplusChargedSPsMatchedToDplusChargedEventWiseSubtractedSPs, diff --git a/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingSubLcCharged.cxx b/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingSubLcCharged.cxx index 9ab84673b9c..59f994282a1 100644 --- a/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingSubLcCharged.cxx +++ b/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingSubLcCharged.cxx @@ -13,9 +13,20 @@ // /// \author Nima Zardoshti -#include #include "PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingSub.cxx" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" +#include "PWGJE/DataModel/JetSubstructure.h" + +#include +#include +#include +#include +#include + +#include + using LcChargedJetSubstructureMatchingSub = JetSubstructureMatchingSub, soa::Join, aod::LcChargedSPsMatchedToLcChargedEventWiseSubtractedSPs, diff --git a/PWGJE/TableProducer/Matching/jetMatchingMC.cxx b/PWGJE/TableProducer/Matching/jetMatchingMC.cxx index 72206247c50..5faba83064e 100644 --- a/PWGJE/TableProducer/Matching/jetMatchingMC.cxx +++ b/PWGJE/TableProducer/Matching/jetMatchingMC.cxx @@ -17,20 +17,16 @@ /// \author Aimeric Lanodu /// \author Nima Zardoshti -#include +#include "PWGJE/Core/JetMatchingUtilities.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" #include "Framework/ASoA.h" -#include "Framework/runDataProcessing.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" +#include +#include +#include -#include "PWGJE/DataModel/Jet.h" -#include "PWGJE/Core/JetUtilities.h" -#include "PWGJE/Core/JetFindingUtilities.h" -#include "PWGJE/Core/JetMatchingUtilities.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" +#include using namespace o2; using namespace o2::framework; diff --git a/PWGJE/TableProducer/Matching/jetMatchingMCBplusCharged.cxx b/PWGJE/TableProducer/Matching/jetMatchingMCBplusCharged.cxx index 8a5705f273f..e9066924fcc 100644 --- a/PWGJE/TableProducer/Matching/jetMatchingMCBplusCharged.cxx +++ b/PWGJE/TableProducer/Matching/jetMatchingMCBplusCharged.cxx @@ -15,6 +15,17 @@ #include "PWGJE/TableProducer/Matching/jetMatchingMC.cxx" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" + +#include +#include +#include +#include +#include + +#include + using BplusChargedJetMatchingMC = JetMatchingMc, soa::Join, aod::BplusChargedMCDetectorLevelJetsMatchedToBplusChargedMCParticleLevelJets, diff --git a/PWGJE/TableProducer/Matching/jetMatchingMCCharged.cxx b/PWGJE/TableProducer/Matching/jetMatchingMCCharged.cxx index fe951be4566..da8a956efc6 100644 --- a/PWGJE/TableProducer/Matching/jetMatchingMCCharged.cxx +++ b/PWGJE/TableProducer/Matching/jetMatchingMCCharged.cxx @@ -15,6 +15,17 @@ #include "PWGJE/TableProducer/Matching/jetMatchingMC.cxx" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" + +#include +#include +#include +#include +#include + +#include + using ChargedJetMatchingMC = JetMatchingMc, soa::Join, aod::ChargedMCDetectorLevelJetsMatchedToChargedMCParticleLevelJets, diff --git a/PWGJE/TableProducer/Matching/jetMatchingMCD0Charged.cxx b/PWGJE/TableProducer/Matching/jetMatchingMCD0Charged.cxx index 64abc51c79d..a56a9f21ff5 100644 --- a/PWGJE/TableProducer/Matching/jetMatchingMCD0Charged.cxx +++ b/PWGJE/TableProducer/Matching/jetMatchingMCD0Charged.cxx @@ -15,6 +15,17 @@ #include "PWGJE/TableProducer/Matching/jetMatchingMC.cxx" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" + +#include +#include +#include +#include +#include + +#include + using D0ChargedJetMatchingMC = JetMatchingMc, soa::Join, aod::D0ChargedMCDetectorLevelJetsMatchedToD0ChargedMCParticleLevelJets, diff --git a/PWGJE/TableProducer/Matching/jetMatchingMCDielectronCharged.cxx b/PWGJE/TableProducer/Matching/jetMatchingMCDielectronCharged.cxx index 7d284ecbee4..740c30d5f8b 100644 --- a/PWGJE/TableProducer/Matching/jetMatchingMCDielectronCharged.cxx +++ b/PWGJE/TableProducer/Matching/jetMatchingMCDielectronCharged.cxx @@ -15,6 +15,17 @@ #include "PWGJE/TableProducer/Matching/jetMatchingMC.cxx" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" + +#include +#include +#include +#include +#include + +#include + using DielectronChargedJetMatchingMC = JetMatchingMc, soa::Join, aod::DielectronChargedMCDetectorLevelJetsMatchedToDielectronChargedMCParticleLevelJets, diff --git a/PWGJE/TableProducer/Matching/jetMatchingMCDplusCharged.cxx b/PWGJE/TableProducer/Matching/jetMatchingMCDplusCharged.cxx index 31c3391533b..7032c3a42e9 100644 --- a/PWGJE/TableProducer/Matching/jetMatchingMCDplusCharged.cxx +++ b/PWGJE/TableProducer/Matching/jetMatchingMCDplusCharged.cxx @@ -15,6 +15,17 @@ #include "PWGJE/TableProducer/Matching/jetMatchingMC.cxx" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" + +#include +#include +#include +#include +#include + +#include + using DplusChargedJetMatchingMC = JetMatchingMc, soa::Join, aod::DplusChargedMCDetectorLevelJetsMatchedToDplusChargedMCParticleLevelJets, diff --git a/PWGJE/TableProducer/Matching/jetMatchingMCFull.cxx b/PWGJE/TableProducer/Matching/jetMatchingMCFull.cxx index e4bf6f3979d..a98f0c7c5bb 100644 --- a/PWGJE/TableProducer/Matching/jetMatchingMCFull.cxx +++ b/PWGJE/TableProducer/Matching/jetMatchingMCFull.cxx @@ -15,6 +15,17 @@ #include "PWGJE/TableProducer/Matching/jetMatchingMC.cxx" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" + +#include +#include +#include +#include +#include + +#include + using FullJetMatchingMC = JetMatchingMc, soa::Join, aod::FullMCDetectorLevelJetsMatchedToFullMCParticleLevelJets, diff --git a/PWGJE/TableProducer/Matching/jetMatchingMCLcCharged.cxx b/PWGJE/TableProducer/Matching/jetMatchingMCLcCharged.cxx index 9be7e169e57..ef10653f179 100644 --- a/PWGJE/TableProducer/Matching/jetMatchingMCLcCharged.cxx +++ b/PWGJE/TableProducer/Matching/jetMatchingMCLcCharged.cxx @@ -15,6 +15,17 @@ #include "PWGJE/TableProducer/Matching/jetMatchingMC.cxx" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" + +#include +#include +#include +#include +#include + +#include + using LcChargedJetMatchingMC = JetMatchingMc, soa::Join, aod::LcChargedMCDetectorLevelJetsMatchedToLcChargedMCParticleLevelJets, diff --git a/PWGJE/TableProducer/Matching/jetMatchingMCNeutral.cxx b/PWGJE/TableProducer/Matching/jetMatchingMCNeutral.cxx index 8af1d2513bc..204d0f4afda 100644 --- a/PWGJE/TableProducer/Matching/jetMatchingMCNeutral.cxx +++ b/PWGJE/TableProducer/Matching/jetMatchingMCNeutral.cxx @@ -15,6 +15,17 @@ #include "PWGJE/TableProducer/Matching/jetMatchingMC.cxx" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" + +#include +#include +#include +#include +#include + +#include + using NeutralJetMatchingMC = JetMatchingMc, soa::Join, aod::NeutralMCDetectorLevelJetsMatchedToNeutralMCParticleLevelJets, diff --git a/PWGJE/TableProducer/Matching/jetMatchingMCSub.cxx b/PWGJE/TableProducer/Matching/jetMatchingMCSub.cxx index 45e57923721..927298a53b5 100644 --- a/PWGJE/TableProducer/Matching/jetMatchingMCSub.cxx +++ b/PWGJE/TableProducer/Matching/jetMatchingMCSub.cxx @@ -13,20 +13,16 @@ /// \brief matching event-wise constituent subtracted detector level and unsubtracted generated level jets (this is usseful as a template for embedding matching) /// \author Nima Zardoshti -#include +#include "PWGJE/Core/JetMatchingUtilities.h" +#include "PWGJE/DataModel/Jet.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" #include "Framework/ASoA.h" -#include "Framework/runDataProcessing.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" +#include +#include +#include +#include // IWYU pragma: export -#include "PWGJE/DataModel/Jet.h" -#include "PWGJE/Core/JetUtilities.h" -#include "PWGJE/Core/JetFindingUtilities.h" -#include "PWGJE/Core/JetMatchingUtilities.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" +#include using namespace o2; using namespace o2::framework; diff --git a/PWGJE/TableProducer/Matching/jetMatchingMCSubBplusCharged.cxx b/PWGJE/TableProducer/Matching/jetMatchingMCSubBplusCharged.cxx index 86db7221aa6..38e0b9034d2 100644 --- a/PWGJE/TableProducer/Matching/jetMatchingMCSubBplusCharged.cxx +++ b/PWGJE/TableProducer/Matching/jetMatchingMCSubBplusCharged.cxx @@ -15,6 +15,16 @@ #include "PWGJE/TableProducer/Matching/jetMatchingMCSub.cxx" +#include "PWGJE/DataModel/Jet.h" + +#include +#include +#include +#include +#include + +#include + using D0ChargedJetMatchingMCSub = JetMatchingMcSub, soa::Join, aod::D0ChargedMCDetectorLevelJetsMatchedToD0ChargedMCDetectorLevelEventWiseSubtractedJets, diff --git a/PWGJE/TableProducer/Matching/jetMatchingMCSubCharged.cxx b/PWGJE/TableProducer/Matching/jetMatchingMCSubCharged.cxx index 2b0c5c19992..eb19ef698f3 100644 --- a/PWGJE/TableProducer/Matching/jetMatchingMCSubCharged.cxx +++ b/PWGJE/TableProducer/Matching/jetMatchingMCSubCharged.cxx @@ -15,6 +15,17 @@ #include "PWGJE/TableProducer/Matching/jetMatchingMCSub.cxx" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" + +#include +#include +#include +#include +#include + +#include + using ChargedJetMatchingMCSub = JetMatchingMcSub, soa::Join, aod::ChargedMCDetectorLevelJetsMatchedToChargedMCDetectorLevelEventWiseSubtractedJets, diff --git a/PWGJE/TableProducer/Matching/jetMatchingMCSubD0Charged.cxx b/PWGJE/TableProducer/Matching/jetMatchingMCSubD0Charged.cxx index 92a71c20900..31313b99421 100644 --- a/PWGJE/TableProducer/Matching/jetMatchingMCSubD0Charged.cxx +++ b/PWGJE/TableProducer/Matching/jetMatchingMCSubD0Charged.cxx @@ -15,6 +15,16 @@ #include "PWGJE/TableProducer/Matching/jetMatchingMCSub.cxx" +#include "PWGJE/DataModel/Jet.h" + +#include +#include +#include +#include +#include + +#include + using D0ChargedJetMatchingMCSub = JetMatchingMcSub, soa::Join, aod::D0ChargedMCDetectorLevelJetsMatchedToD0ChargedMCDetectorLevelEventWiseSubtractedJets, diff --git a/PWGJE/TableProducer/Matching/jetMatchingMCSubDielectronCharged.cxx b/PWGJE/TableProducer/Matching/jetMatchingMCSubDielectronCharged.cxx index 376e904f473..8d9082f2884 100644 --- a/PWGJE/TableProducer/Matching/jetMatchingMCSubDielectronCharged.cxx +++ b/PWGJE/TableProducer/Matching/jetMatchingMCSubDielectronCharged.cxx @@ -15,6 +15,16 @@ #include "PWGJE/TableProducer/Matching/jetMatchingMCSub.cxx" +#include "PWGJE/DataModel/Jet.h" + +#include +#include +#include +#include +#include + +#include + using DielectronChargedJetMatchingMCSub = JetMatchingMcSub, soa::Join, aod::DielectronChargedMCDetectorLevelJetsMatchedToDielectronChargedMCDetectorLevelEventWiseSubtractedJets, diff --git a/PWGJE/TableProducer/Matching/jetMatchingMCSubDplusCharged.cxx b/PWGJE/TableProducer/Matching/jetMatchingMCSubDplusCharged.cxx index d8b0e0aaf50..936b7b8d718 100644 --- a/PWGJE/TableProducer/Matching/jetMatchingMCSubDplusCharged.cxx +++ b/PWGJE/TableProducer/Matching/jetMatchingMCSubDplusCharged.cxx @@ -15,6 +15,16 @@ #include "PWGJE/TableProducer/Matching/jetMatchingMCSub.cxx" +#include "PWGJE/DataModel/Jet.h" + +#include +#include +#include +#include +#include + +#include + using DplusChargedJetMatchingMCSub = JetMatchingMcSub, soa::Join, aod::DplusChargedMCDetectorLevelJetsMatchedToDplusChargedMCDetectorLevelEventWiseSubtractedJets, diff --git a/PWGJE/TableProducer/Matching/jetMatchingMCSubLcCharged.cxx b/PWGJE/TableProducer/Matching/jetMatchingMCSubLcCharged.cxx index 6a9456eb241..d645f297f9c 100644 --- a/PWGJE/TableProducer/Matching/jetMatchingMCSubLcCharged.cxx +++ b/PWGJE/TableProducer/Matching/jetMatchingMCSubLcCharged.cxx @@ -15,6 +15,16 @@ #include "PWGJE/TableProducer/Matching/jetMatchingMCSub.cxx" +#include "PWGJE/DataModel/Jet.h" + +#include +#include +#include +#include +#include + +#include + using LcChargedJetMatchingMCSub = JetMatchingMcSub, soa::Join, aod::LcChargedMCDetectorLevelJetsMatchedToLcChargedMCDetectorLevelEventWiseSubtractedJets, diff --git a/PWGJE/TableProducer/Matching/jetMatchingMCV0Charged.cxx b/PWGJE/TableProducer/Matching/jetMatchingMCV0Charged.cxx index d0910abc488..35c569d4651 100644 --- a/PWGJE/TableProducer/Matching/jetMatchingMCV0Charged.cxx +++ b/PWGJE/TableProducer/Matching/jetMatchingMCV0Charged.cxx @@ -15,6 +15,17 @@ #include "PWGJE/TableProducer/Matching/jetMatchingMC.cxx" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" + +#include +#include +#include +#include +#include + +#include + using V0ChargedJetMatchingMC = JetMatchingMc, soa::Join, aod::V0ChargedMCDetectorLevelJetsMatchedToV0ChargedMCParticleLevelJets, diff --git a/PWGJE/TableProducer/Matching/jetMatchingSub.cxx b/PWGJE/TableProducer/Matching/jetMatchingSub.cxx index 002fedd3a0d..97ac2461acd 100644 --- a/PWGJE/TableProducer/Matching/jetMatchingSub.cxx +++ b/PWGJE/TableProducer/Matching/jetMatchingSub.cxx @@ -13,20 +13,17 @@ /// \brief matching event-wise constituent subtracted data jets and unsubtracted data jets /// \author Nima Zardoshti -#include +#include "PWGJE/Core/JetMatchingUtilities.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" #include "Framework/ASoA.h" -#include "Framework/runDataProcessing.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" +#include +#include +#include +#include // IWYU pragma: export -#include "PWGJE/DataModel/Jet.h" -#include "PWGJE/Core/JetUtilities.h" -#include "PWGJE/Core/JetFindingUtilities.h" -#include "PWGJE/Core/JetMatchingUtilities.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" +#include using namespace o2; using namespace o2::framework; diff --git a/PWGJE/TableProducer/Matching/jetMatchingSubBplusCharged.cxx b/PWGJE/TableProducer/Matching/jetMatchingSubBplusCharged.cxx index a24b7c6de6f..bd8591a4340 100644 --- a/PWGJE/TableProducer/Matching/jetMatchingSubBplusCharged.cxx +++ b/PWGJE/TableProducer/Matching/jetMatchingSubBplusCharged.cxx @@ -15,6 +15,17 @@ #include "PWGJE/TableProducer/Matching/jetMatchingSub.cxx" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetSubtraction.h" + +#include +#include +#include +#include +#include + +#include + using BplusChargedJetMatchingSub = JetMatchingSub, soa::Join, aod::BplusChargedJetsMatchedToBplusChargedEventWiseSubtractedJets, diff --git a/PWGJE/TableProducer/Matching/jetMatchingSubCharged.cxx b/PWGJE/TableProducer/Matching/jetMatchingSubCharged.cxx index 4d12c3c0448..406345bc8c2 100644 --- a/PWGJE/TableProducer/Matching/jetMatchingSubCharged.cxx +++ b/PWGJE/TableProducer/Matching/jetMatchingSubCharged.cxx @@ -15,6 +15,18 @@ #include "PWGJE/TableProducer/Matching/jetMatchingSub.cxx" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" +#include "PWGJE/DataModel/JetSubtraction.h" + +#include +#include +#include +#include +#include + +#include + using ChargedJetMatchingSub = JetMatchingSub, soa::Join, aod::ChargedJetsMatchedToChargedEventWiseSubtractedJets, diff --git a/PWGJE/TableProducer/Matching/jetMatchingSubD0Charged.cxx b/PWGJE/TableProducer/Matching/jetMatchingSubD0Charged.cxx index d07f5186d95..2912f249d37 100644 --- a/PWGJE/TableProducer/Matching/jetMatchingSubD0Charged.cxx +++ b/PWGJE/TableProducer/Matching/jetMatchingSubD0Charged.cxx @@ -15,6 +15,17 @@ #include "PWGJE/TableProducer/Matching/jetMatchingSub.cxx" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetSubtraction.h" + +#include +#include +#include +#include +#include + +#include + using D0ChargedJetMatchingSub = JetMatchingSub, soa::Join, aod::D0ChargedJetsMatchedToD0ChargedEventWiseSubtractedJets, diff --git a/PWGJE/TableProducer/Matching/jetMatchingSubDielectronCharged.cxx b/PWGJE/TableProducer/Matching/jetMatchingSubDielectronCharged.cxx index 94960e214d8..1cdd5c20c54 100644 --- a/PWGJE/TableProducer/Matching/jetMatchingSubDielectronCharged.cxx +++ b/PWGJE/TableProducer/Matching/jetMatchingSubDielectronCharged.cxx @@ -15,6 +15,17 @@ #include "PWGJE/TableProducer/Matching/jetMatchingSub.cxx" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetSubtraction.h" + +#include +#include +#include +#include +#include + +#include + using DielectronChargedJetMatchingSub = JetMatchingSub, soa::Join, aod::DielectronChargedJetsMatchedToDielectronChargedEventWiseSubtractedJets, diff --git a/PWGJE/TableProducer/Matching/jetMatchingSubDplusCharged.cxx b/PWGJE/TableProducer/Matching/jetMatchingSubDplusCharged.cxx index 181bd2a93a2..533b129b598 100644 --- a/PWGJE/TableProducer/Matching/jetMatchingSubDplusCharged.cxx +++ b/PWGJE/TableProducer/Matching/jetMatchingSubDplusCharged.cxx @@ -15,6 +15,17 @@ #include "PWGJE/TableProducer/Matching/jetMatchingSub.cxx" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetSubtraction.h" + +#include +#include +#include +#include +#include + +#include + using DplusChargedJetMatchingSub = JetMatchingSub, soa::Join, aod::DplusChargedJetsMatchedToDplusChargedEventWiseSubtractedJets, diff --git a/PWGJE/TableProducer/Matching/jetMatchingSubLcCharged.cxx b/PWGJE/TableProducer/Matching/jetMatchingSubLcCharged.cxx index eabc5209fa8..72ac5bd7253 100644 --- a/PWGJE/TableProducer/Matching/jetMatchingSubLcCharged.cxx +++ b/PWGJE/TableProducer/Matching/jetMatchingSubLcCharged.cxx @@ -15,6 +15,17 @@ #include "PWGJE/TableProducer/Matching/jetMatchingSub.cxx" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetSubtraction.h" + +#include +#include +#include +#include +#include + +#include + using LcChargedJetMatchingSub = JetMatchingSub, soa::Join, aod::LcChargedJetsMatchedToLcChargedEventWiseSubtractedJets, diff --git a/PWGJE/TableProducer/derivedDataProducer.cxx b/PWGJE/TableProducer/derivedDataProducer.cxx index 3398b33ce42..a759b76a2b1 100644 --- a/PWGJE/TableProducer/derivedDataProducer.cxx +++ b/PWGJE/TableProducer/derivedDataProducer.cxx @@ -13,49 +13,53 @@ // /// \author Nima Zardoshti -#include -#include -#include -#include -#include - -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoA.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "TDatabasePDG.h" - -#include "CCDB/BasicCCDBManager.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DetectorsBase/Propagator.h" -#include "DetectorsVertexing/PVertexer.h" -#include "ReconstructionDataFormats/Vertex.h" +#include "PWGDQ/DataModel/ReducedInfoTables.h" +#include "PWGHF/DataModel/DerivedTables.h" +#include "PWGHF/Utils/utilsBfieldCCDB.h" +#include "PWGJE/Core/JetDQUtilities.h" +#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include "PWGJE/Core/JetV0Utilities.h" +#include "PWGJE/DataModel/EMCALClusters.h" +#include "PWGJE/DataModel/EMCALMatchedCollisions.h" +#include "PWGJE/DataModel/JetReducedData.h" +#include "PWGJE/DataModel/JetReducedDataDQ.h" +#include "PWGJE/DataModel/JetReducedDataHF.h" +#include "PWGJE/DataModel/JetReducedDataV0.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectionDefaults.h" +#include "Common/CCDB/ctpRateFetcher.h" +#include "Common/Core/RecoDecay.h" #include "Common/Core/trackUtilities.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" #include "Common/DataModel/Centrality.h" -#include "Common/Core/RecoDecay.h" -#include "Common/CCDB/ctpRateFetcher.h" #include "Common/DataModel/CollisionAssociationTables.h" -#include "PWGJE/DataModel/EMCALClusters.h" - -#include "EventFiltering/filterTables.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/TrackSelectionTables.h" #include "EventFiltering/Zorro.h" -#include "PWGJE/Core/JetFinder.h" -#include "PWGJE/DataModel/Jet.h" -#include "PWGJE/DataModel/EMCALMatchedCollisions.h" -#include "PWGJE/Core/JetDerivedDataUtilities.h" -#include "PWGJE/Core/JetHFUtilities.h" -#include "PWGJE/Core/JetV0Utilities.h" -#include "PWGJE/Core/JetDQUtilities.h" +#include "CCDB/BasicCCDBManager.h" +#include "DetectorsBase/Propagator.h" +#include "Framework/ASoA.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/O2DatabasePDGPlugin.h" +#include "ReconstructionDataFormats/Vertex.h" +#include +#include +#include +#include +#include +#include +#include -#include "PWGHF/Utils/utilsBfieldCCDB.h" +#include +#include +#include +#include +#include +#include +#include +#include using namespace o2; using namespace o2::framework; diff --git a/PWGJE/TableProducer/derivedDataSelector.cxx b/PWGJE/TableProducer/derivedDataSelector.cxx index f4336b228a2..8524fd32866 100644 --- a/PWGJE/TableProducer/derivedDataSelector.cxx +++ b/PWGJE/TableProducer/derivedDataSelector.cxx @@ -16,22 +16,27 @@ /// \author Nima Zardoshti /// \author Jochen Klein -#include -#include -#include -#include - -#include - -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoA.h" -#include "Framework/runDataProcessing.h" +#include "JetDerivedDataUtilities.h" #include "PWGJE/DataModel/Jet.h" #include "PWGJE/DataModel/JetReducedData.h" #include "PWGJE/DataModel/JetReducedDataSelector.h" +#include "Framework/ASoA.h" +#include "Framework/AnalysisTask.h" +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; diff --git a/PWGJE/TableProducer/derivedDataTriggerProducer.cxx b/PWGJE/TableProducer/derivedDataTriggerProducer.cxx index a1a1636dd1b..b90495d0bb6 100644 --- a/PWGJE/TableProducer/derivedDataTriggerProducer.cxx +++ b/PWGJE/TableProducer/derivedDataTriggerProducer.cxx @@ -13,20 +13,20 @@ // /// \author Nima Zardoshti -#include -#include - -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoA.h" -#include "Framework/O2DatabasePDGPlugin.h" +#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include "PWGJE/DataModel/JetReducedData.h" #include "EventFiltering/filterTables.h" -#include "PWGJE/Core/JetFinder.h" -#include "PWGJE/DataModel/Jet.h" -#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include "Framework/ASoA.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include +#include +#include +#include + +#include using namespace o2; using namespace o2::framework; diff --git a/PWGJE/TableProducer/derivedDataWriter.cxx b/PWGJE/TableProducer/derivedDataWriter.cxx index dfd1c82b200..2742c848f83 100644 --- a/PWGJE/TableProducer/derivedDataWriter.cxx +++ b/PWGJE/TableProducer/derivedDataWriter.cxx @@ -16,22 +16,33 @@ /// \author Jochen Klein /// \author Nima Zardoshti -#include -#include -#include -#include - -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoA.h" -#include "Framework/runDataProcessing.h" +#include "JetDerivedDataUtilities.h" -#include "PWGJE/Core/JetHFUtilities.h" +#include "PWGDQ/DataModel/ReducedInfoTables.h" +#include "PWGHF/DataModel/DerivedTables.h" #include "PWGJE/Core/JetDQUtilities.h" +#include "PWGJE/Core/JetHFUtilities.h" #include "PWGJE/DataModel/Jet.h" #include "PWGJE/DataModel/JetReducedData.h" +#include "PWGJE/DataModel/JetReducedDataDQ.h" +#include "PWGJE/DataModel/JetReducedDataHF.h" #include "PWGJE/DataModel/JetReducedDataSelector.h" +#include "Framework/ASoA.h" +#include "Framework/AnalysisTask.h" +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; diff --git a/PWGJE/TableProducer/emcalClusterHadronicCorrectionTask.cxx b/PWGJE/TableProducer/emcalClusterHadronicCorrectionTask.cxx index 69e1f1051dc..4e4cdedd197 100644 --- a/PWGJE/TableProducer/emcalClusterHadronicCorrectionTask.cxx +++ b/PWGJE/TableProducer/emcalClusterHadronicCorrectionTask.cxx @@ -12,28 +12,26 @@ // **Hadronic Correction in the EMCAL framework: to avoid the double counting of the charged particles' contribution in jets** /// \author Archita Rani Dash -#include -#include -#include -#include -#include -#include -#include "TVector2.h" +#include "PWGJE/DataModel/EMCALClusterDefinition.h" +#include "PWGJE/DataModel/EMCALClusters.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" #include "Framework/ASoA.h" +#include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" +#include +#include +#include +#include +#include -#include "DetectorsBase/GeometryManager.h" - -#include "PWGJE/DataModel/JetReducedData.h" -#include "PWGJE/DataModel/Jet.h" - -#include "PWGJE/Core/JetUtilities.h" +#include "TVector2.h" +#include -#include "CommonDataFormat/InteractionRecord.h" +#include +#include +#include using namespace o2; using namespace o2::framework; diff --git a/PWGJE/TableProducer/emcalCorrectionTask.cxx b/PWGJE/TableProducer/emcalCorrectionTask.cxx index 1c1261827de..e7d14189114 100644 --- a/PWGJE/TableProducer/emcalCorrectionTask.cxx +++ b/PWGJE/TableProducer/emcalCorrectionTask.cxx @@ -18,54 +18,52 @@ /// \author Raymond Ehlers (raymond.ehlers@cern.ch) ORNL, Florian Jonas (florian.jonas@cern.ch) /// -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "CCDB/BasicCCDBManager.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisHelpers.h" -#include "Framework/ASoA.h" -#include "Framework/Configurable.h" -#include "Framework/Expressions.h" -#include "Framework/HistogramSpec.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/InitContext.h" -#include "Framework/WorkflowSpec.h" - -#include "DetectorsBase/GeometryManager.h" - +#include "PWGJE/Core/JetUtilities.h" #include "PWGJE/DataModel/EMCALClusterDefinition.h" #include "PWGJE/DataModel/EMCALClusters.h" #include "PWGJE/DataModel/EMCALMatchedCollisions.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "DataFormatsEMCAL/ClusterLabel.h" + +#include "CCDB/BasicCCDBManager.h" +#include "DataFormatsEMCAL/AnalysisCluster.h" #include "DataFormatsEMCAL/Cell.h" #include "DataFormatsEMCAL/CellLabel.h" #include "DataFormatsEMCAL/Constants.h" -#include "DataFormatsEMCAL/AnalysisCluster.h" -#include "EMCALBase/Geometry.h" +#include "DetectorsBase/GeometryManager.h" #include "EMCALBase/ClusterFactory.h" +#include "EMCALBase/Geometry.h" #include "EMCALBase/NonlinearityHandler.h" #include "EMCALReconstruction/Clusterizer.h" -#include "PWGJE/Core/JetUtilities.h" -#include "GPUROOTCartesianFwd.h" +#include "Framework/ASoA.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include +#include +#include +#include +#include +#include +#include +#include + #include "TVector2.h" -#include "TH1.h" +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include using namespace o2; using namespace o2::framework; diff --git a/PWGJE/TableProducer/emcalMatchedTracksTask.cxx b/PWGJE/TableProducer/emcalMatchedTracksTask.cxx index 4134b8455e3..55781eb6bc4 100644 --- a/PWGJE/TableProducer/emcalMatchedTracksTask.cxx +++ b/PWGJE/TableProducer/emcalMatchedTracksTask.cxx @@ -9,34 +9,36 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#include -#include -#include -#include -#include -#include -#include - -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoA.h" -#include "Framework/HistogramRegistry.h" +#include "PWGJE/DataModel/EMCALClusters.h" +#include "PWGJE/DataModel/EMCALMatchedTracks.h" +#include "Common/CCDB/TriggerAliases.h" #include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/Centrality.h" -#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/PIDResponseTOF.h" +#include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/TrackSelectionTables.h" +#include "CommonDataFormat/InteractionRecord.h" #include "EMCALBase/Geometry.h" -#include "EMCALCalib/BadChannelMap.h" -#include "PWGJE/DataModel/EMCALClusters.h" -#include "PWGJE/DataModel/EMCALMatchedTracks.h" -#include "DataFormatsEMCAL/Cell.h" -#include "DataFormatsEMCAL/Constants.h" -#include "DataFormatsEMCAL/AnalysisCluster.h" +#include "Framework/ASoA.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include +#include +#include +#include +#include +#include +#include -#include "CommonDataFormat/InteractionRecord.h" +#include + +#include +#include +#include +#include +#include // \struct EmcalMatchedTracksTask /// \brief Simple table producer task for EMCal matched tracks diff --git a/PWGJE/TableProducer/eventwiseConstituentSubtractor.cxx b/PWGJE/TableProducer/eventwiseConstituentSubtractor.cxx index 476fa4157d7..914f10e28cb 100644 --- a/PWGJE/TableProducer/eventwiseConstituentSubtractor.cxx +++ b/PWGJE/TableProducer/eventwiseConstituentSubtractor.cxx @@ -13,17 +13,25 @@ // /// \author Nima Zardoshti -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" +#include "PWGJE/Core/JetBkgSubUtils.h" +#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include "PWGJE/Core/JetFindingUtilities.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" +#include "PWGJE/DataModel/JetSubtraction.h" + #include "Framework/ASoA.h" +#include "Framework/AnalysisTask.h" #include "Framework/O2DatabasePDGPlugin.h" +#include +#include +#include +#include -#include "PWGJE/Core/FastJetUtilities.h" -#include "PWGJE/Core/JetFindingUtilities.h" -#include "PWGJE/Core/JetDerivedDataUtilities.h" -#include "PWGJE/DataModel/Jet.h" -#include "PWGJE/Core/JetBkgSubUtils.h" -#include "Framework/runDataProcessing.h" +#include + +#include +#include using namespace o2; using namespace o2::framework; @@ -184,17 +192,17 @@ struct eventWiseConstituentSubtractorTask { } PROCESS_SWITCH(eventWiseConstituentSubtractorTask, processLcMcCollisions, "Fill table of subtracted tracks for collisions with Lc MCP candidates", false); - void processBplusCollisions(aod::JetCollision const&, soa::Filtered const& tracks, soa::Join const& candidates) - { - analyseHF(tracks, candidates, trackSubtractedBplusTable); - } - PROCESS_SWITCH(eventWiseConstituentSubtractorTask, processBplusCollisions, "Fill table of subtracted tracks for collisions with Bplus candidates", false); + void processBplusCollisions(aod::JetCollision const&, soa::Filtered const& tracks, soa::Join const& candidates) + { + analyseHF(tracks, candidates, trackSubtractedBplusTable); + } + PROCESS_SWITCH(eventWiseConstituentSubtractorTask, processBplusCollisions, "Fill table of subtracted tracks for collisions with Bplus candidates", false); - void processBplusMcCollisions(aod::JetMcCollision const&, soa::Filtered const& tracks, soa::Join const& candidates) - { - analyseHFMc(tracks, candidates, particleSubtractedBplusTable); - } - PROCESS_SWITCH(eventWiseConstituentSubtractorTask, processBplusMcCollisions, "Fill table of subtracted tracks for collisions with Bplus MCP candidates", false); + void processBplusMcCollisions(aod::JetMcCollision const&, soa::Filtered const& tracks, soa::Join const& candidates) + { + analyseHFMc(tracks, candidates, particleSubtractedBplusTable); + } + PROCESS_SWITCH(eventWiseConstituentSubtractorTask, processBplusMcCollisions, "Fill table of subtracted tracks for collisions with Bplus MCP candidates", false); void processDielectronCollisions(aod::JetCollision const&, soa::Filtered const& tracks, soa::Join const& candidates) { diff --git a/PWGJE/TableProducer/heavyFlavourDefinition.cxx b/PWGJE/TableProducer/heavyFlavourDefinition.cxx index f28368b10dc..a9f52f96a35 100644 --- a/PWGJE/TableProducer/heavyFlavourDefinition.cxx +++ b/PWGJE/TableProducer/heavyFlavourDefinition.cxx @@ -13,19 +13,19 @@ /// \brief Task to produce a table joinable to the jet tables for a flavour definition on MC /// \author Hanseo Park -#include -#include +#include "PWGJE/Core/JetTaggingUtilities.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" +#include "PWGJE/DataModel/JetTagging.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" #include "Framework/ASoA.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "Framework/runDataProcessing.h" -#include "Common/Core/trackUtilities.h" +#include "Framework/AnalysisTask.h" +#include +#include +#include +#include -#include "PWGJE/DataModel/Jet.h" -#include "PWGJE/DataModel/JetTagging.h" -#include "PWGJE/Core/JetTaggingUtilities.h" +#include using namespace o2; using namespace o2::framework; diff --git a/PWGJE/TableProducer/jetEventWeightMCD.cxx b/PWGJE/TableProducer/jetEventWeightMCD.cxx index 40ea278c51e..48f8ab749c9 100644 --- a/PWGJE/TableProducer/jetEventWeightMCD.cxx +++ b/PWGJE/TableProducer/jetEventWeightMCD.cxx @@ -13,19 +13,22 @@ // /// \author Nima Zardoshti -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" + #include "Framework/ASoA.h" -#include "Framework/O2DatabasePDGPlugin.h" +#include "Framework/AnalysisTask.h" +#include +#include +#include +#include -#include "PWGJE/DataModel/Jet.h" +#include using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; -#include "Framework/runDataProcessing.h" - template struct JetEventWeightMCDTask { diff --git a/PWGJE/TableProducer/jetEventWeightMCP.cxx b/PWGJE/TableProducer/jetEventWeightMCP.cxx index 5727cf57a43..3b9cf4340ba 100644 --- a/PWGJE/TableProducer/jetEventWeightMCP.cxx +++ b/PWGJE/TableProducer/jetEventWeightMCP.cxx @@ -13,19 +13,20 @@ // /// \author Nima Zardoshti +#include "PWGJE/DataModel/Jet.h" + #include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoA.h" -#include "Framework/O2DatabasePDGPlugin.h" +#include +#include +#include +#include -#include "PWGJE/DataModel/Jet.h" +#include using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; -#include "Framework/runDataProcessing.h" - template struct JetEventWeightMCPTask { diff --git a/PWGJE/TableProducer/jetTaggerHF.cxx b/PWGJE/TableProducer/jetTaggerHF.cxx index 2a37871c970..6e336d9516b 100644 --- a/PWGJE/TableProducer/jetTaggerHF.cxx +++ b/PWGJE/TableProducer/jetTaggerHF.cxx @@ -16,27 +16,43 @@ /// \author Hanseo Park /// \author Hadi Hassan , University of Jyväskylä -#include -#include -#include -#include -#include +#include "MlResponse.h" + +#include "PWGJE/Core/JetTaggingUtilities.h" +#include "PWGJE/Core/MlResponseHfTagging.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" +#include "PWGJE/DataModel/JetTagging.h" + +#include "Common/DataModel/TrackSelectionTables.h" + +#include "Framework/ASoA.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include #include -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoA.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "Framework/runDataProcessing.h" -#include "Common/Core/trackUtilities.h" +#include -#include "PWGJE/DataModel/Jet.h" -#include "PWGJE/DataModel/JetTagging.h" -#include "PWGJE/Core/JetTaggingUtilities.h" -#include "PWGJE/Core/JetDerivedDataUtilities.h" -#include "PWGJE/Core/MlResponseHfTagging.h" +#include +#include +#include +#include +#include +#include +#include +#include using namespace o2; using namespace o2::framework; diff --git a/PWGJE/TableProducer/jetTrackDerived.cxx b/PWGJE/TableProducer/jetTrackDerived.cxx index 827ec6c1c15..9111ae36c3c 100644 --- a/PWGJE/TableProducer/jetTrackDerived.cxx +++ b/PWGJE/TableProducer/jetTrackDerived.cxx @@ -17,23 +17,32 @@ /// // O2 includes -#include "ReconstructionDataFormats/Track.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/AnalysisDataModel.h" -#include "PWGJE/DataModel/Jet.h" -#include "Framework/StaticFor.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "Common/DataModel/EventSelection.h" +#include "PWGJE/DataModel/TrackJetQa.h" + #include "Common/Core/TrackSelection.h" #include "Common/Core/TrackSelectionDefaults.h" -#include "PWGJE/DataModel/TrackJetQa.h" #include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" #include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#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; diff --git a/PWGJE/TableProducer/luminosityCalculator.cxx b/PWGJE/TableProducer/luminosityCalculator.cxx index b1d509ab321..8767ae604e2 100644 --- a/PWGJE/TableProducer/luminosityCalculator.cxx +++ b/PWGJE/TableProducer/luminosityCalculator.cxx @@ -14,13 +14,21 @@ /// /// \author Nima Zardoshti -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" +#include "PWGJE/DataModel/JetReducedData.h" + #include "Framework/ASoA.h" -#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" +#include +#include +#include +#include +#include -#include "PWGJE/DataModel/JetReducedData.h" +#include + +#include +#include using namespace o2; using namespace o2::framework; diff --git a/PWGJE/TableProducer/luminosityProducer.cxx b/PWGJE/TableProducer/luminosityProducer.cxx index 6877da8a812..455ab4e5910 100644 --- a/PWGJE/TableProducer/luminosityProducer.cxx +++ b/PWGJE/TableProducer/luminosityProducer.cxx @@ -14,14 +14,27 @@ /// /// \author Nima Zardoshti -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoA.h" -#include "Framework/runDataProcessing.h" +#include "JetDerivedDataUtilities.h" #include "PWGJE/DataModel/Jet.h" #include "PWGJE/DataModel/JetReducedData.h" +#include "Common/CCDB/EventSelectionParams.h" + +#include "Framework/ASoA.h" +#include "Framework/AnalysisTask.h" +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; diff --git a/PWGJE/TableProducer/rhoEstimator.cxx b/PWGJE/TableProducer/rhoEstimator.cxx index a64a2d90e5d..dba3cfb50c8 100644 --- a/PWGJE/TableProducer/rhoEstimator.cxx +++ b/PWGJE/TableProducer/rhoEstimator.cxx @@ -13,20 +13,29 @@ // /// \author Nima Zardoshti -#include -#include +#include "PWGJE/Core/JetBkgSubUtils.h" +#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include "PWGJE/Core/JetFindingUtilities.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" +#include "PWGJE/DataModel/JetSubtraction.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" #include "Framework/ASoA.h" +#include "Framework/AnalysisTask.h" #include "Framework/O2DatabasePDGPlugin.h" +#include +#include +#include +#include -#include "PWGJE/Core/FastJetUtilities.h" -#include "PWGJE/Core/JetFindingUtilities.h" -#include "PWGJE/Core/JetDerivedDataUtilities.h" -#include "PWGJE/DataModel/Jet.h" -#include "PWGJE/Core/JetBkgSubUtils.h" -#include "Framework/runDataProcessing.h" +#include +#include + +#include +#include +#include + +#include using namespace o2; using namespace o2::framework; @@ -308,34 +317,34 @@ struct RhoEstimatorTask { rhoBplusTable(rho, rhoM); } } - PROCESS_SWITCH(RhoEstimatorTask, processBplusCollisions, "Fill rho tables for collisions with Bplus candidates", false); + PROCESS_SWITCH(RhoEstimatorTask, processBplusCollisions, "Fill rho tables for collisions with Bplus candidates", false); - void processBplusMcCollisions(aod::JetMcCollision const&, soa::Filtered const& particles, aod::CandidatesBplusMCP const& candidates) - { - for (auto& candidate : candidates) { - inputParticles.clear(); - jetfindingutilities::analyseParticles(inputParticles, particleSelection, 1, particles, pdgDatabase, &candidate); + void processBplusMcCollisions(aod::JetMcCollision const&, soa::Filtered const& particles, aod::CandidatesBplusMCP const& candidates) + { + for (auto& candidate : candidates) { + inputParticles.clear(); + jetfindingutilities::analyseParticles(inputParticles, particleSelection, 1, particles, pdgDatabase, &candidate); - auto [rho, rhoM] = bkgSub.estimateRhoAreaMedian(inputParticles, config.doSparse); - rhoBplusMcTable(rho, rhoM); - } + auto [rho, rhoM] = bkgSub.estimateRhoAreaMedian(inputParticles, config.doSparse); + rhoBplusMcTable(rho, rhoM); } - PROCESS_SWITCH(RhoEstimatorTask, processBplusMcCollisions, "Fill rho tables for collisions with Bplus MCP candidates", false); - - void processDielectronCollisions(aod::JetCollision const& collision, soa::Filtered const& tracks, aod::CandidatesDielectronData const& candidates) - { - for (auto& candidate : candidates) { - if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits) || collision.centrality() < config.centralityMin || collision.centrality() >= config.centralityMax || collision.trackOccupancyInTimeRange() > config.trackOccupancyInTimeRangeMax || std::abs(collision.posZ()) > config.vertexZCut) { - rhoDielectronTable(0.0, 0.0); - continue; - } - inputParticles.clear(); - jetfindingutilities::analyseTracks(inputParticles, tracks, trackSelection, config.trackingEfficiency, &candidate); + } + PROCESS_SWITCH(RhoEstimatorTask, processBplusMcCollisions, "Fill rho tables for collisions with Bplus MCP candidates", false); - auto [rho, rhoM] = bkgSub.estimateRhoAreaMedian(inputParticles, config.doSparse); - rhoDielectronTable(rho, rhoM); + void processDielectronCollisions(aod::JetCollision const& collision, soa::Filtered const& tracks, aod::CandidatesDielectronData const& candidates) + { + for (auto& candidate : candidates) { + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits) || collision.centrality() < config.centralityMin || collision.centrality() >= config.centralityMax || collision.trackOccupancyInTimeRange() > config.trackOccupancyInTimeRangeMax || std::abs(collision.posZ()) > config.vertexZCut) { + rhoDielectronTable(0.0, 0.0); + continue; } + inputParticles.clear(); + jetfindingutilities::analyseTracks(inputParticles, tracks, trackSelection, config.trackingEfficiency, &candidate); + + auto [rho, rhoM] = bkgSub.estimateRhoAreaMedian(inputParticles, config.doSparse); + rhoDielectronTable(rho, rhoM); } + } PROCESS_SWITCH(RhoEstimatorTask, processDielectronCollisions, "Fill rho tables for collisions with Dielectron candidates", false); void processDielectronMcCollisions(aod::JetMcCollision const&, soa::Filtered const& particles, aod::CandidatesDielectronMCP const& candidates) diff --git a/PWGJE/TableProducer/secondaryVertexReconstruction.cxx b/PWGJE/TableProducer/secondaryVertexReconstruction.cxx index c1f7598d176..f86371a5d67 100644 --- a/PWGJE/TableProducer/secondaryVertexReconstruction.cxx +++ b/PWGJE/TableProducer/secondaryVertexReconstruction.cxx @@ -13,31 +13,42 @@ /// \brief Task to produce a SV indices table joinable to the jet tables and 3/2-prong SV for hf jet tagging /// \author Hadi Hassan -#include -#include -#include -#include +#include "PWGHF/Utils/utilsBfieldCCDB.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" +#include "PWGJE/DataModel/JetTagging.h" -#include -#include +#include "Common/Core/RecoDecay.h" +#include "Common/Core/trackUtilities.h" +#include "Common/DataModel/TrackSelectionTables.h" #include "CommonConstants/PhysicsConstants.h" #include "DCAFitter/DCAFitterN.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" #include "Framework/ASoA.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "Framework/runDataProcessing.h" -#include "Common/Core/trackUtilities.h" -#include "Common/Core/RecoDecay.h" - +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" #include "ReconstructionDataFormats/DCA.h" - -#include "PWGJE/DataModel/Jet.h" -#include "PWGJE/DataModel/JetTagging.h" -#include "PWGJE/Core/JetDerivedDataUtilities.h" - -#include "PWGHF/Utils/utilsBfieldCCDB.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; diff --git a/PWGJE/Tasks/bjetTaggingGnn.cxx b/PWGJE/Tasks/bjetTaggingGnn.cxx index 9cc4e89088a..1e74fb21ff3 100644 --- a/PWGJE/Tasks/bjetTaggingGnn.cxx +++ b/PWGJE/Tasks/bjetTaggingGnn.cxx @@ -14,30 +14,25 @@ /// /// \author Changhwan Choi , Pusan National University -#include -#include -#include -#include - -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/ASoA.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" -#include "PWGJE/Core/JetUtilities.h" #include "PWGJE/Core/JetDerivedDataUtilities.h" #include "PWGJE/Core/JetTaggingUtilities.h" -#include "PWGJE/DataModel/JetTagging.h" #include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" +#include "PWGJE/DataModel/JetTagging.h" -#include "Common/Core/trackUtilities.h" -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectionDefaults.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "Common/Core/RecoDecay.h" +#include "Framework/ASoA.h" +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include +#include +#include +#include -#include "Framework/Logger.h" +#include +#include +#include +#include +#include using namespace o2; using namespace o2::framework; diff --git a/PWGJE/Tasks/bjetTaggingML.cxx b/PWGJE/Tasks/bjetTaggingML.cxx index afa34a243e6..4f89b482677 100644 --- a/PWGJE/Tasks/bjetTaggingML.cxx +++ b/PWGJE/Tasks/bjetTaggingML.cxx @@ -14,28 +14,32 @@ /// /// \author Hadi Hassan , University of Jyväskylä -#include -#include -#include - -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/ASoA.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" -#include "PWGJE/Core/JetUtilities.h" #include "PWGJE/Core/JetDerivedDataUtilities.h" #include "PWGJE/Core/JetTaggingUtilities.h" -#include "PWGJE/DataModel/JetTagging.h" +#include "PWGJE/Core/JetUtilities.h" #include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" +#include "PWGJE/DataModel/JetTagging.h" -#include "Common/Core/trackUtilities.h" -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectionDefaults.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" #include "Common/Core/RecoDecay.h" +#include "Framework/ASoA.h" +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.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; diff --git a/PWGJE/Tasks/bjetTreeCreator.cxx b/PWGJE/Tasks/bjetTreeCreator.cxx index ba7c8e49c6d..103de117469 100644 --- a/PWGJE/Tasks/bjetTreeCreator.cxx +++ b/PWGJE/Tasks/bjetTreeCreator.cxx @@ -15,30 +15,39 @@ /// /// \author Hadi Hassan , University of Jyväskylä -#include -#include -#include -#include - -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/ASoA.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" -#include "PWGJE/Core/FastJetUtilities.h" -#include "PWGJE/Core/JetUtilities.h" -#include "PWGJE/Core/JetFinder.h" #include "PWGJE/Core/JetDerivedDataUtilities.h" #include "PWGJE/Core/JetTaggingUtilities.h" +#include "PWGJE/Core/JetUtilities.h" #include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" #include "PWGJE/DataModel/JetTagging.h" -#include "Common/Core/trackUtilities.h" -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectionDefaults.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" #include "Common/Core/RecoDecay.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include "Framework/ASoA.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include using namespace o2; using namespace o2::framework; diff --git a/PWGJE/Tasks/dijetFinderQA.cxx b/PWGJE/Tasks/dijetFinderQA.cxx index d2697e614bf..b5410727b7c 100644 --- a/PWGJE/Tasks/dijetFinderQA.cxx +++ b/PWGJE/Tasks/dijetFinderQA.cxx @@ -13,32 +13,30 @@ // /// \author Dongguk Kim -#include -#include -#include -#include +#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include "PWGJE/Core/JetFindingUtilities.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" #include "Framework/ASoA.h" -#include "Framework/AnalysisDataModel.h" #include "Framework/AnalysisTask.h" -#include "Framework/O2DatabasePDGPlugin.h" #include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" +#include +#include +#include +#include -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectionDefaults.h" +#include -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" +#include -#include "PWGJE/Core/FastJetUtilities.h" -#include "PWGJE/Core/JetFinder.h" -#include "PWGJE/Core/JetFindingUtilities.h" -#include "PWGJE/DataModel/Jet.h" - -#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include +#include +#include +#include +#include -#include "EventFiltering/filterTables.h" +#include using namespace o2; using namespace o2::framework; diff --git a/PWGJE/Tasks/emcCellMonitor.cxx b/PWGJE/Tasks/emcCellMonitor.cxx index bb1d8fb3f9f..880ce14e490 100644 --- a/PWGJE/Tasks/emcCellMonitor.cxx +++ b/PWGJE/Tasks/emcCellMonitor.cxx @@ -9,25 +9,31 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. +#include "CommonDataFormat/InteractionRecord.h" +#include "DataFormatsEMCAL/Constants.h" +#include "EMCALBase/Geometry.h" +#include "EMCALCalib/BadChannelMap.h" +#include "Framework/ASoA.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include +#include +#include +#include +#include + +#include + +#include #include #include -#include #include #include #include +#include #include -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoA.h" -#include "Framework/HistogramRegistry.h" - -#include "DataFormatsEMCAL/Constants.h" -#include "EMCALBase/Geometry.h" -#include "EMCALCalib/BadChannelMap.h" -#include "CommonDataFormat/InteractionRecord.h" - /// \struct CellMonitor /// \brief Simple monitoring task for cell related quantities /// \author Markus Fasel , Oak Ridge National Laoratory diff --git a/PWGJE/Tasks/emcClusterMonitor.cxx b/PWGJE/Tasks/emcClusterMonitor.cxx index 37ee979cc67..fbb8885c5be 100644 --- a/PWGJE/Tasks/emcClusterMonitor.cxx +++ b/PWGJE/Tasks/emcClusterMonitor.cxx @@ -9,33 +9,39 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#include -#include -#include -#include -#include -#include -#include -#include +#include "PWGJE/DataModel/EMCALClusters.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" +#include "Common/CCDB/TriggerAliases.h" +#include "Common/DataModel/EventSelection.h" + +#include "CommonDataFormat/InteractionRecord.h" +#include "EMCALBase/Geometry.h" #include "Framework/ASoA.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" +#include +#include +#include +#include +#include +#include -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/Centrality.h" -#include "Common/DataModel/PIDResponse.h" +#include +#include +#include -#include "EMCALBase/Geometry.h" -#include "EMCALCalib/BadChannelMap.h" -#include "PWGJE/DataModel/EMCALClusters.h" -#include "DataFormatsEMCAL/Cell.h" -#include "DataFormatsEMCAL/Constants.h" -#include "DataFormatsEMCAL/AnalysisCluster.h" +#include -#include "CommonDataFormat/InteractionRecord.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include // \struct ClusterMonitor /// \brief Simple monitoring task for EMCal clusters diff --git a/PWGJE/Tasks/emcEventSelectionQA.cxx b/PWGJE/Tasks/emcEventSelectionQA.cxx index 53bc21b56b4..49fa5d97b7b 100644 --- a/PWGJE/Tasks/emcEventSelectionQA.cxx +++ b/PWGJE/Tasks/emcEventSelectionQA.cxx @@ -13,16 +13,25 @@ /// \brief Monitoring task for EMCAL event selection /// \author Markus Fasel , Oak Ridge National Laoratory -#include +#include "PWGJE/Core/utilsBcSelEMC.h" + +#include "Common/CCDB/EventSelectionParams.h" +#include "Common/CCDB/TriggerAliases.h" +#include "Common/DataModel/EventSelection.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" #include "Framework/ASoA.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" +#include +#include +#include -#include "Common/DataModel/EventSelection.h" -#include "PWGJE/Core/utilsBcSelEMC.h" +#include + +#include +#include +#include using namespace o2; using namespace o2::framework; diff --git a/PWGJE/Tasks/emcTmMonitor.cxx b/PWGJE/Tasks/emcTmMonitor.cxx index 3a191cba635..9fa8df59dec 100644 --- a/PWGJE/Tasks/emcTmMonitor.cxx +++ b/PWGJE/Tasks/emcTmMonitor.cxx @@ -9,33 +9,36 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#include -#include -#include -#include -#include -#include -#include - -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoA.h" -#include "Framework/HistogramRegistry.h" +#include "PWGJE/DataModel/EMCALClusters.h" +#include "Common/CCDB/TriggerAliases.h" #include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/Centrality.h" -#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/TrackSelectionTables.h" #include "EMCALBase/Geometry.h" -#include "EMCALCalib/BadChannelMap.h" -#include "PWGJE/DataModel/EMCALClusters.h" -#include "DataFormatsEMCAL/Cell.h" -#include "DataFormatsEMCAL/Constants.h" -#include "DataFormatsEMCAL/AnalysisCluster.h" +#include "Framework/ASoA.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include +#include +#include +#include +#include +#include +#include + +#include + +#include -#include "CommonDataFormat/InteractionRecord.h" +#include +#include +#include +#include +#include +#include // \struct TrackMatchingMonitor /// \brief Simple monitoring task for EMCal clusters diff --git a/PWGJE/Tasks/emcVertexSelectionQA.cxx b/PWGJE/Tasks/emcVertexSelectionQA.cxx index 1ec997d4edd..eb579326966 100644 --- a/PWGJE/Tasks/emcVertexSelectionQA.cxx +++ b/PWGJE/Tasks/emcVertexSelectionQA.cxx @@ -13,18 +13,26 @@ // /// \author Nicolas Strangmann , Goethe University Frankfurt / Oak Ridge National Laoratory -#include -#include -#include +#include "Common/CCDB/EventSelectionParams.h" +#include "Common/CCDB/TriggerAliases.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/TrackSelectionTables.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" #include "Framework/ASoA.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" +#include +#include +#include +#include -#include "Common/DataModel/TrackSelectionTables.h" -#include "Common/DataModel/EventSelection.h" +#include +#include +#include +#include + +#include using namespace o2; using namespace o2::framework; diff --git a/PWGJE/Tasks/emcalGammaGammaBcWise.cxx b/PWGJE/Tasks/emcalGammaGammaBcWise.cxx index 7007f94bc15..d9674888aed 100644 --- a/PWGJE/Tasks/emcalGammaGammaBcWise.cxx +++ b/PWGJE/Tasks/emcalGammaGammaBcWise.cxx @@ -16,17 +16,29 @@ /// \author Nicolas Strangmann (nicolas.strangmann@cern.ch) - Goethe University Frankfurt /// +#include "PWGJE/DataModel/EMCALClusters.h" + +#include "Common/CCDB/EventSelectionParams.h" +#include "Common/CCDB/TriggerAliases.h" +#include "Common/DataModel/EventSelection.h" + +#include "EMCALBase/Geometry.h" +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" #include -#include +#include +#include +#include +#include +#include +#include +#include + #include "TLorentzVector.h" #include "TVector3.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Common/DataModel/EventSelection.h" -#include "EMCALBase/Geometry.h" -#include "PWGJE/DataModel/EMCALClusters.h" +#include +#include using namespace o2; using namespace o2::framework; diff --git a/PWGJE/Tasks/emcalPi0EnergyScaleCalib.cxx b/PWGJE/Tasks/emcalPi0EnergyScaleCalib.cxx index bb1abd5a986..273907b8056 100644 --- a/PWGJE/Tasks/emcalPi0EnergyScaleCalib.cxx +++ b/PWGJE/Tasks/emcalPi0EnergyScaleCalib.cxx @@ -9,35 +9,40 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#include -#include -#include -#include -#include -#include -#include -#include - -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoA.h" -#include "Framework/HistogramRegistry.h" +#include "PWGJE/DataModel/EMCALClusters.h" +#include "PWGJE/DataModel/EMCALMatchedCollisions.h" +#include "Common/CCDB/TriggerAliases.h" #include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/Centrality.h" #include "EMCALBase/Geometry.h" -#include "PWGJE/DataModel/EMCALClusters.h" -#include "PWGJE/DataModel/EMCALMatchedCollisions.h" -#include "DataFormatsEMCAL/Cell.h" -#include "DataFormatsEMCAL/Constants.h" -#include "DataFormatsEMCAL/AnalysisCluster.h" - -#include "CommonDataFormat/InteractionRecord.h" +#include "Framework/ASoA.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include +#include +#include +#include +#include #include "TLorentzVector.h" #include "TVector3.h" +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include /// \brief Simple pi0 reconstruction task used to scale the cell energy based on the difference in mass position in data and MC /// \author Nicolas Strangmann , Goethe University Frankfurt / Oak Ridge National Laoratory diff --git a/PWGJE/Tasks/fullJetSpectra.cxx b/PWGJE/Tasks/fullJetSpectra.cxx index 5ddcde82ffb..d490cf5959e 100644 --- a/PWGJE/Tasks/fullJetSpectra.cxx +++ b/PWGJE/Tasks/fullJetSpectra.cxx @@ -13,46 +13,42 @@ /// \brief Task for full jet spectra studies in pp collisions. /// \author Archita Rani Dash -#include -#include -#include -#include -#include +#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include "PWGJE/Core/JetFindingUtilities.h" +#include "PWGJE/Core/JetUtilities.h" +#include "PWGJE/DataModel/EMCALClusterDefinition.h" +#include "PWGJE/DataModel/EMCALClusters.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" + +#include "Common/CCDB/TriggerAliases.h" +#include "Common/DataModel/Multiplicity.h" -#include "CommonConstants/PhysicsConstants.h" #include "Framework/ASoA.h" -#include "Framework/AnalysisDataModel.h" #include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" #include "Framework/O2DatabasePDGPlugin.h" -#include "Framework/runDataProcessing.h" -#include "Framework/RunningWorkflowInfo.h" -#include "Framework/Logger.h" +#include +#include +#include +#include +#include +#include -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectionDefaults.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/PIDResponse.h" -#include "Common/DataModel/TrackSelectionTables.h" +#include -#include "PWGHF/Core/HfHelper.h" - -#include "PWGJE/DataModel/Jet.h" -#include "PWGJE/DataModel/EMCALClusters.h" -#include "PWGJE/DataModel/EMCALMatchedCollisions.h" -#include "PWGJE/Core/JetFinder.h" -#include "PWGJE/Core/JetUtilities.h" -#include "PWGJE/Core/JetDerivedDataUtilities.h" -#include "PWGJE/Core/JetFindingUtilities.h" +#include +#include +#include +#include +#include -#include "EventFiltering/filterTables.h" +#include using namespace std; using namespace o2; -using namespace o2::analysis; using namespace o2::framework; using namespace o2::framework::expressions; -// using namespace jetderiveddatautilities; struct FullJetSpectra { diff --git a/PWGJE/Tasks/fullJetTriggerQATask.cxx b/PWGJE/Tasks/fullJetTriggerQATask.cxx index bbab8a61f0d..1831a3c3372 100644 --- a/PWGJE/Tasks/fullJetTriggerQATask.cxx +++ b/PWGJE/Tasks/fullJetTriggerQATask.cxx @@ -13,25 +13,41 @@ // /// \author Gijs van Weelden // -#include -#include +#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include "PWGJE/Core/JetFinder.h" +#include "PWGJE/DataModel/EMCALClusterDefinition.h" +#include "PWGJE/DataModel/EMCALClusters.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" -#include "TH1F.h" -#include "TTree.h" +#include "Common/CCDB/TriggerAliases.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" #include "Framework/ASoA.h" -#include "Framework/RunningWorkflowInfo.h" +#include "Framework/AnalysisTask.h" +#include +#include +#include +#include +#include +#include -#include "Common/DataModel/EventSelection.h" +#include "TTree.h" +#include +#include +#include +#include -#include "PWGJE/DataModel/Jet.h" -#include "PWGJE/Core/JetFinder.h" -#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include +#include -#include "EventFiltering/filterTables.h" +#include +#include +#include +#include +#include +#include +#include +#include using namespace o2; using namespace o2::framework; diff --git a/PWGJE/Tasks/gammaJetTreeProducer.cxx b/PWGJE/Tasks/gammaJetTreeProducer.cxx index 351742682d0..42dbfa869ef 100644 --- a/PWGJE/Tasks/gammaJetTreeProducer.cxx +++ b/PWGJE/Tasks/gammaJetTreeProducer.cxx @@ -9,54 +9,49 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -// C++ system headers first -#include -#include -#include - -// Framework and other headers after -#include "Framework/ASoA.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" - -#include "Common/Core/RecoDecay.h" -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectionDefaults.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" +/// \struct GammaJetTreeProducer +/// \brief Task to produce a tree for gamma-jet analysis, including photons (and information of isolation) and charged and full jets +/// \author Florian Jonas , UC Berkeley/LBNL +/// \since 02.08.2024 +/// -#include "PWGJE/Core/FastJetUtilities.h" #include "PWGJE/Core/JetDerivedDataUtilities.h" #include "PWGJE/Core/JetUtilities.h" -#include "PWGJE/DataModel/Jet.h" #include "PWGJE/DataModel/GammaJetAnalysisTree.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" +#include "PWGJE/DataModel/JetSubtraction.h" + +#include "Common/Core/RecoDecay.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include -#include "EMCALBase/Geometry.h" -#include "EMCALCalib/BadChannelMap.h" -#include "PWGJE/DataModel/EMCALClusters.h" -#include "DataFormatsEMCAL/Cell.h" -#include "DataFormatsEMCAL/Constants.h" -#include "DataFormatsEMCAL/AnalysisCluster.h" #include "TVector2.h" +#include -#include "CommonDataFormat/InteractionRecord.h" +#include + +#include +#include +#include +#include -#include "EventFiltering/filterTables.h" +#include -// \struct GammaJetTreeProducer -/// \brief Task to produce a tree for gamma-jet analysis, including photons (and information of isolation) and charged and full jets -/// \author Florian Jonas , UC Berkeley/LBNL -/// \since 02.08.2024 -/// using namespace o2; using namespace o2::aod; using namespace o2::framework; using namespace o2::framework::expressions; using emcClusters = o2::soa::Join; -#include "Framework/runDataProcessing.h" - struct GammaJetTreeProducer { // analysis tree // charged jets diff --git a/PWGJE/Tasks/hadronPhotonCorrelation.cxx b/PWGJE/Tasks/hadronPhotonCorrelation.cxx index 70850130b5c..bd6496f2296 100644 --- a/PWGJE/Tasks/hadronPhotonCorrelation.cxx +++ b/PWGJE/Tasks/hadronPhotonCorrelation.cxx @@ -16,40 +16,36 @@ /// for hadrons and photons to compute angular correlations /// -#include -#include -#include -#include +#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" +#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" +#include "Common/Core/RecoDecay.h" +#include "Common/DataModel/PIDResponseTPC.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include "CommonConstants/MathConstants.h" #include "Framework/ASoA.h" -#include "Framework/ASoAHelpers.h" #include "Framework/AnalysisDataModel.h" #include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" +#include "Framework/Configurable.h" #include "Framework/Expressions.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "Framework/runDataProcessing.h" +#include "Framework/HistogramRegistry.h" #include "Framework/HistogramSpec.h" -#include "Framework/Configurable.h" +#include "Framework/O2DatabasePDGPlugin.h" +#include +#include +#include -#include "Common/Core/RecoDecay.h" -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectionDefaults.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "Common/DataModel/PIDResponse.h" -#include "Common/DataModel/Centrality.h" -#include "Common/DataModel/Multiplicity.h" -#include "Common/Core/trackUtilities.h" -#include "CommonConstants/PhysicsConstants.h" -#include "CommonConstants/MathConstants.h" +#include -#include "PWGJE/DataModel/Jet.h" -#include "PWGJE/DataModel/JetReducedData.h" -#include "PWGJE/Core/JetUtilities.h" - -#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" -#include "PWGEM/PhotonMeson/Utils/PCMUtilities.h" +#include +#include +#include +#include +#include using namespace o2; using namespace o2::aod; diff --git a/PWGJE/Tasks/hfFragmentationFunction.cxx b/PWGJE/Tasks/hfFragmentationFunction.cxx index 9100e78391a..dcfdaf90360 100644 --- a/PWGJE/Tasks/hfFragmentationFunction.cxx +++ b/PWGJE/Tasks/hfFragmentationFunction.cxx @@ -16,36 +16,34 @@ /// /// The task store data relevant to the calculation of hadronization observables radial /// profile and/or jet momentum fraction for charmed hadrons -#include -#include +#include "JetDerivedDataUtilities.h" +#include "RecoDecay.h" -#include "TVector3.h" - -#include "fastjet/PseudoJet.hh" -#include "fastjet/ClusterSequenceArea.hh" +#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "PWGJE/Core/JetUtilities.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" #include "Framework/ASoA.h" -#include "Framework/runDataProcessing.h" -#include "Framework/O2DatabasePDGPlugin.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" +#include +#include +#include +#include +#include +#include +#include -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectionDefaults.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" +#include "TVector3.h" +#include -#include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" +#include -#include "PWGJE/DataModel/Jet.h" -#include "PWGJE/DataModel/JetSubstructure.h" -#include "PWGJE/Core/JetFinder.h" -#include "PWGJE/Core/FastJetUtilities.h" -#include "PWGJE/Core/JetHFUtilities.h" -#include "PWGJE/Core/JetUtilities.h" +#include +#include +#include using namespace o2; using namespace o2::framework; diff --git a/PWGJE/Tasks/jetBackgroundAnalysis.cxx b/PWGJE/Tasks/jetBackgroundAnalysis.cxx index ece360113ec..596bfc14b73 100644 --- a/PWGJE/Tasks/jetBackgroundAnalysis.cxx +++ b/PWGJE/Tasks/jetBackgroundAnalysis.cxx @@ -14,33 +14,29 @@ /// \author Aimeric Landou /// \author Nima Zardoshti -#include -#include -#include -#include -#include "TLorentzVector.h" +#include "RecoDecay.h" + +#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" +#include "PWGJE/DataModel/JetSubtraction.h" #include "Framework/ASoA.h" -#include "Framework/AnalysisDataModel.h" #include "Framework/AnalysisTask.h" -#include "Framework/O2DatabasePDGPlugin.h" #include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" - -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectionDefaults.h" +#include +#include +#include +#include -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" - -#include "PWGJE/Core/FastJetUtilities.h" -#include "PWGJE/Core/JetFinder.h" -#include "PWGJE/Core/JetFindingUtilities.h" -#include "PWGJE/DataModel/Jet.h" +#include +#include -#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include +#include +#include -#include "EventFiltering/filterTables.h" +#include using namespace o2; using namespace o2::framework; diff --git a/PWGJE/Tasks/jetChCorr.cxx b/PWGJE/Tasks/jetChCorr.cxx index 43486b4567c..4311fc5c7d8 100644 --- a/PWGJE/Tasks/jetChCorr.cxx +++ b/PWGJE/Tasks/jetChCorr.cxx @@ -14,38 +14,35 @@ /// Mriganka Mouli Mondal originally modified from Nima Zardoshti // -#include -#include -#include -#include -#include -#include -#include - -#include "fastjet/PseudoJet.hh" -#include "fastjet/ClusterSequenceArea.hh" +#include "PWGJE/Core/FastJetUtilities.h" +#include "PWGJE/Core/JetFinder.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" #include "Framework/ASoA.h" -#include "Framework/O2DatabasePDGPlugin.h" +#include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" +#include "Framework/O2DatabasePDGPlugin.h" -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectionDefaults.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" +#include +#include +#include -#include "PWGJE/DataModel/Jet.h" -#include "PWGJE/DataModel/JetSubstructure.h" -#include "PWGJE/Core/JetFinder.h" -#include "PWGJE/Core/FastJetUtilities.h" +#include "fastjet/ClusterSequenceArea.hh" +#include "fastjet/PseudoJet.hh" +#include -#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include +#include +#include // #include "PWGLF/DataModel/LFResonanceTables.h" -#include "Framework/runDataProcessing.h" +#include +#include +#include +#include +#include using namespace std; using namespace o2; diff --git a/PWGJE/Tasks/jetChargedV2.cxx b/PWGJE/Tasks/jetChargedV2.cxx index 20ea7907a75..208d2de6f98 100644 --- a/PWGJE/Tasks/jetChargedV2.cxx +++ b/PWGJE/Tasks/jetChargedV2.cxx @@ -13,42 +13,36 @@ /// \file jetChargedV2.cxx /// \brief This file contains the implementation for the Charged Jet v2 analysis in the ALICE experiment -#include "PWGJE/Core/FastJetUtilities.h" #include "PWGJE/Core/JetDerivedDataUtilities.h" -#include "PWGJE/Core/JetFinder.h" #include "PWGJE/Core/JetFindingUtilities.h" #include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" +#include "PWGJE/DataModel/JetSubtraction.h" #include "Common/Core/EventPlaneHelper.h" -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectionDefaults.h" -#include "Common/DataModel/EventSelection.h" +#include "Common/Core/RecoDecay.h" #include "Common/DataModel/Qvectors.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "EventFiltering/filterTables.h" - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/ASoA.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "Framework/RunningWorkflowInfo.h" -#include "Framework/StaticFor.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 -#include #include #include #include diff --git a/PWGJE/Tasks/jetFinderBplusQA.cxx b/PWGJE/Tasks/jetFinderBplusQA.cxx index 4b7c42b4580..a713c3a767e 100644 --- a/PWGJE/Tasks/jetFinderBplusQA.cxx +++ b/PWGJE/Tasks/jetFinderBplusQA.cxx @@ -15,6 +15,16 @@ #include "PWGJE/Tasks/jetFinderHFQA.cxx" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetSubtraction.h" + +#include +#include +#include +#include + +#include + using JetFinderBplusQATask = JetFinderHFQATask; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/Tasks/jetFinderD0QA.cxx b/PWGJE/Tasks/jetFinderD0QA.cxx index 2db58308d87..1ebe0ec649b 100644 --- a/PWGJE/Tasks/jetFinderD0QA.cxx +++ b/PWGJE/Tasks/jetFinderD0QA.cxx @@ -15,6 +15,16 @@ #include "PWGJE/Tasks/jetFinderHFQA.cxx" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetSubtraction.h" + +#include +#include +#include +#include + +#include + using JetFinderD0QATask = JetFinderHFQATask; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/Tasks/jetFinderDielectronQA.cxx b/PWGJE/Tasks/jetFinderDielectronQA.cxx index 516f4501a7b..296ede5979a 100644 --- a/PWGJE/Tasks/jetFinderDielectronQA.cxx +++ b/PWGJE/Tasks/jetFinderDielectronQA.cxx @@ -15,6 +15,16 @@ #include "PWGJE/Tasks/jetFinderHFQA.cxx" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetSubtraction.h" + +#include +#include +#include +#include + +#include + using JetFinderDielectronQATask = JetFinderHFQATask; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/Tasks/jetFinderDplusQA.cxx b/PWGJE/Tasks/jetFinderDplusQA.cxx index bf5468eae57..877cbf60d8a 100644 --- a/PWGJE/Tasks/jetFinderDplusQA.cxx +++ b/PWGJE/Tasks/jetFinderDplusQA.cxx @@ -15,6 +15,16 @@ #include "PWGJE/Tasks/jetFinderHFQA.cxx" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetSubtraction.h" + +#include +#include +#include +#include + +#include + using JetFinderDplusQATask = JetFinderHFQATask; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/Tasks/jetFinderFullQA.cxx b/PWGJE/Tasks/jetFinderFullQA.cxx index 9b01d787959..0a95900c39b 100644 --- a/PWGJE/Tasks/jetFinderFullQA.cxx +++ b/PWGJE/Tasks/jetFinderFullQA.cxx @@ -13,28 +13,35 @@ // /// \author Nima Zardoshti -#include "CommonConstants/PhysicsConstants.h" +#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include "PWGJE/Core/JetFindingUtilities.h" +#include "PWGJE/DataModel/EMCALClusterDefinition.h" +#include "PWGJE/DataModel/EMCALClusters.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" + #include "Framework/ASoA.h" -#include "Framework/AnalysisDataModel.h" #include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" +#include +#include +#include +#include +#include +#include +#include -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectionDefaults.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" +#include -#include "PWGHF/Core/HfHelper.h" - -#include "PWGJE/DataModel/Jet.h" -#include "PWGJE/Core/JetDerivedDataUtilities.h" -#include "PWGJE/Core/JetFindingUtilities.h" +#include +#include +#include +#include +#include -#include "EventFiltering/filterTables.h" +#include using namespace o2; -using namespace o2::analysis; using namespace o2::framework; using namespace o2::framework::expressions; diff --git a/PWGJE/Tasks/jetFinderHFQA.cxx b/PWGJE/Tasks/jetFinderHFQA.cxx index a63cbef6563..0dbcb8bb609 100644 --- a/PWGJE/Tasks/jetFinderHFQA.cxx +++ b/PWGJE/Tasks/jetFinderHFQA.cxx @@ -13,31 +13,34 @@ // /// \author Nima Zardoshti -#include +#include "RecoDecay.h" + +#include "PWGHF/Core/HfHelper.h" +#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include "PWGJE/Core/JetFindingUtilities.h" +#include "PWGJE/Core/JetHFUtilities.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" +#include "PWGJE/DataModel/JetSubtraction.h" -#include "CommonConstants/PhysicsConstants.h" #include "Framework/ASoA.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" - -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectionDefaults.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" +#include +#include +#include -#include "PWGHF/Core/HfHelper.h" -#include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" - -#include "PWGJE/DataModel/Jet.h" +#include +#include +#include -#include "PWGJE/Core/JetDerivedDataUtilities.h" -#include "PWGJE/Core/JetHFUtilities.h" -#include "PWGJE/Core/JetFindingUtilities.h" +#include +#include +#include +#include +#include +#include -#include "EventFiltering/filterTables.h" +#include using namespace o2; using namespace o2::analysis; diff --git a/PWGJE/Tasks/jetFinderLcQA.cxx b/PWGJE/Tasks/jetFinderLcQA.cxx index 311086c86c8..4986d583707 100644 --- a/PWGJE/Tasks/jetFinderLcQA.cxx +++ b/PWGJE/Tasks/jetFinderLcQA.cxx @@ -15,6 +15,16 @@ #include "PWGJE/Tasks/jetFinderHFQA.cxx" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetSubtraction.h" + +#include +#include +#include +#include + +#include + using JetFinderLcQATask = JetFinderHFQATask; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/Tasks/jetFinderQA.cxx b/PWGJE/Tasks/jetFinderQA.cxx index 1a6cd948200..a054005cef7 100644 --- a/PWGJE/Tasks/jetFinderQA.cxx +++ b/PWGJE/Tasks/jetFinderQA.cxx @@ -13,33 +13,34 @@ // /// \author Nima Zardoshti -#include -#include -#include -#include -#include +#include "RecoDecay.h" + +#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include "PWGJE/Core/JetFindingUtilities.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" +#include "PWGJE/DataModel/JetSubtraction.h" #include "Framework/ASoA.h" -#include "Framework/AnalysisDataModel.h" #include "Framework/AnalysisTask.h" -#include "Framework/O2DatabasePDGPlugin.h" #include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" - -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectionDefaults.h" +#include +#include +#include +#include -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" - -#include "PWGJE/Core/FastJetUtilities.h" -#include "PWGJE/Core/JetFinder.h" -#include "PWGJE/Core/JetFindingUtilities.h" -#include "PWGJE/DataModel/Jet.h" +#include +#include +#include -#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include +#include +#include +#include +#include +#include -#include "EventFiltering/filterTables.h" +#include using namespace o2; using namespace o2::framework; diff --git a/PWGJE/Tasks/jetFinderV0QA.cxx b/PWGJE/Tasks/jetFinderV0QA.cxx index 9c681fa3bce..a62e7f6b1cf 100644 --- a/PWGJE/Tasks/jetFinderV0QA.cxx +++ b/PWGJE/Tasks/jetFinderV0QA.cxx @@ -13,37 +13,30 @@ // /// \author Nima Zardoshti -#include -#include -#include +#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include "PWGJE/Core/JetFindingUtilities.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" -#include "CommonConstants/PhysicsConstants.h" #include "Framework/ASoA.h" -#include "Framework/AnalysisDataModel.h" #include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" - -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectionDefaults.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" +#include +#include +#include +#include +#include -#include "PWGHF/Core/HfHelper.h" -#include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" +#include -#include "PWGJE/DataModel/Jet.h" - -#include "PWGJE/Core/JetDerivedDataUtilities.h" -#include "PWGJE/Core/JetHFUtilities.h" -#include "PWGJE/Core/JetV0Utilities.h" -#include "PWGJE/Core/JetFindingUtilities.h" +#include +#include +#include +#include -#include "EventFiltering/filterTables.h" +#include using namespace o2; -using namespace o2::analysis; using namespace o2::framework; using namespace o2::framework::expressions; diff --git a/PWGJE/Tasks/jetFragmentation.cxx b/PWGJE/Tasks/jetFragmentation.cxx index 18d5dea2c56..eae04024d08 100644 --- a/PWGJE/Tasks/jetFragmentation.cxx +++ b/PWGJE/Tasks/jetFragmentation.cxx @@ -14,27 +14,33 @@ /// /// \author Gijs van Weelden -#include -#include -#include "TH1F.h" -#include "TTree.h" +#include "JetDerivedDataUtilities.h" +#include "RecoDecay.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoA.h" -#include "Framework/RunningWorkflowInfo.h" +#include "PWGJE/Core/JetFindingUtilities.h" +#include "PWGJE/Core/JetUtilities.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/TrackSelectionTables.h" #include "CommonConstants/PhysicsConstants.h" - -#include "PWGJE/DataModel/Jet.h" -#include "PWGJE/Core/JetFinder.h" -#include "PWGJE/Core/JetUtilities.h" -#include "PWGJE/Core/JetFindingUtilities.h" -#include "PWGLF/DataModel/V0SelectorTables.h" +#include "Framework/ASoA.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include using namespace o2; using namespace o2::framework; diff --git a/PWGJE/Tasks/jetHadronRecoil.cxx b/PWGJE/Tasks/jetHadronRecoil.cxx index 97cd31cfb5c..03e06f5d07a 100644 --- a/PWGJE/Tasks/jetHadronRecoil.cxx +++ b/PWGJE/Tasks/jetHadronRecoil.cxx @@ -13,34 +13,38 @@ /// \brief Task for analysing hadron triggered events. /// \author Daniel Jones -#include -#include +#include "PWGJE/Core/FastJetUtilities.h" +#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include "PWGJE/Core/JetFinder.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" +#include "PWGJE/DataModel/JetSubtraction.h" -#include "TRandom3.h" +#include "Common/Core/RecoDecay.h" +#include "CommonConstants/MathConstants.h" #include "Framework/ASoA.h" -#include "Framework/AnalysisDataModel.h" #include "Framework/AnalysisTask.h" -#include "Framework/O2DatabasePDGPlugin.h" #include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" - -#include "CommonConstants/MathConstants.h" -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectionDefaults.h" -#include "Common/Core/RecoDecay.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" +#include "Framework/O2DatabasePDGPlugin.h" +#include +#include +#include +#include +#include +#include -#include "PWGJE/Core/FastJetUtilities.h" -#include "PWGJE/Core/JetFinder.h" -#include "PWGJE/Core/JetFindingUtilities.h" -#include "PWGJE/DataModel/Jet.h" -#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include "TRandom3.h" -#include "EventFiltering/filterTables.h" +#include +#include +#include -#include "PWGJE/DataModel/JetSubstructure.h" +#include +#include +#include +#include +#include using namespace o2; using namespace o2::framework; diff --git a/PWGJE/Tasks/jetLundReclustering.cxx b/PWGJE/Tasks/jetLundReclustering.cxx index c18053343cf..b78c6f2b6ef 100644 --- a/PWGJE/Tasks/jetLundReclustering.cxx +++ b/PWGJE/Tasks/jetLundReclustering.cxx @@ -17,35 +17,30 @@ // Task performing jet reclustering and producing primary Lund Plane histograms // -#include -#include -#include -#include -#include - -#include "fastjet/contrib/LundGenerator.hh" -#include "fastjet/PseudoJet.hh" -#include "fastjet/ClusterSequenceArea.hh" +#include "PWGJE/Core/FastJetUtilities.h" +#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include "PWGJE/Core/JetFinder.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" #include "Framework/ASoA.h" -#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" -#include "TDatabasePDG.h" +#include +#include +#include +#include -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectionDefaults.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" +#include "fastjet/ClusterSequenceArea.hh" +#include "fastjet/PseudoJet.hh" +#include -#include "Common/Core/RecoDecay.h" +#include +#include +#include +#include -#include "PWGJE/DataModel/Jet.h" -#include "PWGJE/Core/JetFinder.h" -#include "PWGJE/DataModel/JetSubstructure.h" -#include "PWGJE/Core/FastJetUtilities.h" -#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include using namespace o2; using namespace o2::track; diff --git a/PWGJE/Tasks/jetMatchingQA.cxx b/PWGJE/Tasks/jetMatchingQA.cxx index e752b47e2a5..6770d42e47e 100644 --- a/PWGJE/Tasks/jetMatchingQA.cxx +++ b/PWGJE/Tasks/jetMatchingQA.cxx @@ -15,14 +15,21 @@ /// \author Jochen Klein /// \author Aimeric Lanodu -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoA.h" -#include "Framework/runDataProcessing.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" #include "PWGJE/DataModel/Jet.h" +#include "Framework/ASoA.h" +#include "Framework/AnalysisTask.h" +#include +#include +#include +#include +#include +#include + +#include + +#include + using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; diff --git a/PWGJE/Tasks/jetPlanarFlow.cxx b/PWGJE/Tasks/jetPlanarFlow.cxx index d54ebea1ac2..ec4fc39b870 100644 --- a/PWGJE/Tasks/jetPlanarFlow.cxx +++ b/PWGJE/Tasks/jetPlanarFlow.cxx @@ -14,26 +14,30 @@ /// \author Nima Zardoshti // -#include -#include - -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoA.h" -#include "Framework/runDataProcessing.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "Framework/Logger.h" -#include "Framework/HistogramRegistry.h" +#include "JetDerivedDataUtilities.h" -#include "PWGJE/DataModel/Jet.h" -#include "PWGJE/Core/JetUtilities.h" -#include "PWGJE/Core/JetFinder.h" -#include "PWGJE/Core/FastJetUtilities.h" #include "PWGJE/Core/JetFindingUtilities.h" #include "PWGJE/Core/JetSubstructureUtilities.h" +#include "PWGJE/Core/JetUtilities.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" +#include "PWGJE/DataModel/JetSubtraction.h" + +#include "Framework/ASoA.h" +#include "Framework/AnalysisTask.h" +#include +#include +#include +#include +#include + +#include + #include "fastjet/contrib/AxesDefinition.hh" -#include "fastjet/contrib/MeasureDefinition.hh" + +#include +#include +#include using namespace o2; using namespace o2::framework; diff --git a/PWGJE/Tasks/jetShape.cxx b/PWGJE/Tasks/jetShape.cxx index 3c2bfb4c03c..b52bee180ab 100644 --- a/PWGJE/Tasks/jetShape.cxx +++ b/PWGJE/Tasks/jetShape.cxx @@ -13,24 +13,28 @@ /// \author Yuto Nishida /// \brief Task for measuring the dependence of the jet shape function rho(r) on the distance r from the jet axis. -#include "PWGJE/Core/FastJetUtilities.h" #include "PWGJE/Core/JetDerivedDataUtilities.h" -#include "PWGJE/Core/JetUtilities.h" #include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" +#include "PWGJE/DataModel/JetSubtraction.h" #include "Common/Core/RecoDecay.h" -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectionDefaults.h" -#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/PIDResponseTOF.h" +#include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/TrackSelectionTables.h" #include "Framework/ASoA.h" #include "Framework/AnalysisDataModel.h" #include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" +#include +#include +#include +#include +#include #include +#include #include #include diff --git a/PWGJE/Tasks/jetSpectraCharged.cxx b/PWGJE/Tasks/jetSpectraCharged.cxx index f1dfda25418..9eb8221163f 100644 --- a/PWGJE/Tasks/jetSpectraCharged.cxx +++ b/PWGJE/Tasks/jetSpectraCharged.cxx @@ -13,34 +13,27 @@ /// \brief Charged-particle jet spectra task /// \author Nima Zardoshti , Aimeric Landou , Wenhui Feng -#include -#include -#include -#include -#include -#include +#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include "PWGJE/Core/JetFindingUtilities.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" +#include "PWGJE/DataModel/JetSubtraction.h" #include "Framework/ASoA.h" -#include "Framework/AnalysisDataModel.h" #include "Framework/AnalysisTask.h" -#include "Framework/O2DatabasePDGPlugin.h" #include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" - -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectionDefaults.h" - -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" +#include +#include +#include +#include +#include -#include "PWGJE/Core/FastJetUtilities.h" -#include "PWGJE/Core/JetFinder.h" -#include "PWGJE/Core/JetFindingUtilities.h" -#include "PWGJE/DataModel/Jet.h" - -#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include -#include "EventFiltering/filterTables.h" +#include +#include +#include +#include using namespace o2; using namespace o2::framework; diff --git a/PWGJE/Tasks/jetSpectraEseTask.cxx b/PWGJE/Tasks/jetSpectraEseTask.cxx index 81741c3b0e1..cc8a84f8f1d 100644 --- a/PWGJE/Tasks/jetSpectraEseTask.cxx +++ b/PWGJE/Tasks/jetSpectraEseTask.cxx @@ -14,39 +14,44 @@ /// /// \author Joachim C. K. B. Hansen, Lund University -#include -#include -#include -#include - -#include -#include - -#include "Framework/ASoA.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" - -#include "Common/Core/RecoDecay.h" -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectionDefaults.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" - -#include "PWGJE/Core/FastJetUtilities.h" #include "PWGJE/Core/JetDerivedDataUtilities.h" #include "PWGJE/Core/JetFindingUtilities.h" #include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" +#include "PWGJE/DataModel/JetSubtraction.h" +#include "Common/Core/RecoDecay.h" #include "Common/DataModel/EseTable.h" #include "Common/DataModel/Qvectors.h" +#include "Framework/ASoA.h" +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.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; -#include "Framework/runDataProcessing.h" - struct JetSpectraEseTask { ConfigurableAxis binJetPt{"binJetPt", {250, -50., 200.}, ""}; ConfigurableAxis bindPhi{"bindPhi", {180, -o2::constants::math::PI, o2::constants::math::PI}, ""}; diff --git a/PWGJE/Tasks/jetSubstructure.cxx b/PWGJE/Tasks/jetSubstructure.cxx index f6cd4c9dd72..9980893e4e5 100644 --- a/PWGJE/Tasks/jetSubstructure.cxx +++ b/PWGJE/Tasks/jetSubstructure.cxx @@ -14,36 +14,44 @@ /// \author Nima Zardoshti // -#include -#include +#include "PWGJE/DataModel/JetSubstructure.h" -#include "fastjet/PseudoJet.hh" -#include "fastjet/ClusterSequenceArea.hh" +#include "RecoDecay.h" + +#include "PWGJE/Core/FastJetUtilities.h" +#include "PWGJE/Core/JetFinder.h" +#include "PWGJE/Core/JetSubstructureUtilities.h" +#include "PWGJE/Core/JetUtilities.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" +#include "PWGJE/DataModel/JetSubtraction.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" #include "Framework/ASoA.h" -#include "Framework/O2DatabasePDGPlugin.h" +#include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" +#include "Framework/O2DatabasePDGPlugin.h" +#include +#include +#include +#include +#include -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectionDefaults.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" +#include -#include "PWGJE/DataModel/Jet.h" -#include "PWGJE/DataModel/JetSubstructure.h" -#include "PWGJE/Core/JetFinder.h" -#include "PWGJE/Core/FastJetUtilities.h" -#include "PWGJE/Core/JetUtilities.h" -#include "PWGJE/Core/JetSubstructureUtilities.h" +#include "fastjet/ClusterSequenceArea.hh" +#include "fastjet/PseudoJet.hh" +#include + +#include +#include +#include +#include +#include using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; -#include "Framework/runDataProcessing.h" - struct JetSubstructureTask { Produces jetSubstructureDataTable; Produces jetSubstructureMCDTable; diff --git a/PWGJE/Tasks/jetSubstructureBplus.cxx b/PWGJE/Tasks/jetSubstructureBplus.cxx index 2d6d60f3d5a..527429af742 100644 --- a/PWGJE/Tasks/jetSubstructureBplus.cxx +++ b/PWGJE/Tasks/jetSubstructureBplus.cxx @@ -13,9 +13,20 @@ // /// \author Nima Zardoshti -#include #include "PWGJE/Tasks/jetSubstructureHF.cxx" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetSubstructure.h" +#include "PWGJE/DataModel/JetSubtraction.h" + +#include +#include +#include +#include +#include + +#include + using JetSubstructureBplus = JetSubstructureHFTask, soa::Join, soa::Join, soa::Join, aod::CandidatesBplusData, aod::CandidatesBplusMCP, aod::BplusCJetSSs, aod::BplusChargedSPs, aod::BplusChargedPRs, aod::BplusCMCDJetSSs, aod::BplusChargedMCDetectorLevelSPs, aod::BplusChargedMCDetectorLevelPRs, aod::BplusCMCPJetSSs, aod::BplusChargedMCParticleLevelSPs, aod::BplusChargedMCParticleLevelPRs, aod::BplusCEWSJetSSs, aod::BplusChargedEventWiseSubtractedSPs, aod::BplusChargedEventWiseSubtractedPRs, aod::JTrackBplusSubs>; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/Tasks/jetSubstructureBplusOutput.cxx b/PWGJE/Tasks/jetSubstructureBplusOutput.cxx index fec4c2a27ec..04a2585d5bc 100644 --- a/PWGJE/Tasks/jetSubstructureBplusOutput.cxx +++ b/PWGJE/Tasks/jetSubstructureBplusOutput.cxx @@ -13,9 +13,21 @@ // /// \author Nima Zardoshti -#include #include "PWGJE/Tasks/jetSubstructureHFOutput.cxx" +#include "PWGHF/DataModel/DerivedTables.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetSubstructure.h" +#include "PWGJE/DataModel/JetSubtraction.h" + +#include +#include +#include +#include +#include + +#include + using JetSubstructureOutputBplus = JetSubstructureHFOutputTask, aod::McCollisionsBplus, aod::CandidatesBplusData, aod::CandidatesBplusMCD, aod::CandidatesBplusMCP, aod::BkgBplusRhos, aod::BkgBplusMcRhos, aod::JTrackBplusSubs, soa::Join, soa::Join, soa::Join, soa::Join, aod::BplusCJetCOs, aod::BplusCJetOs, aod::BplusCJetSSOs, aod::BplusCJetMOs, soa::Join, soa::Join, soa::Join, aod::BplusCMCDJetCOs, aod::BplusCMCDJetOs, aod::BplusCMCDJetSSOs, aod::BplusCMCDJetMOs, soa::Join, soa::Join, soa::Join, soa::Join, aod::BplusCMCPJetCOs, aod::BplusCMCPJetMCCOs, aod::BplusCMCPJetOs, aod::BplusCMCPJetSSOs, aod::BplusCMCPJetMOs, soa::Join, soa::Join, soa::Join, aod::BplusCEWSJetCOs, aod::BplusCEWSJetOs, aod::BplusCEWSJetSSOs, aod::BplusCEWSJetMOs, aod::StoredHfBplusCollBase, aod::StoredHfBplusBases, aod::StoredHfBplusPars, aod::StoredHfBplusParEs, aod::StoredHfBplusParD0s, aod::StoredHfBplusSels, aod::StoredHfBplusMls, aod::StoredHfBplusMlD0s, aod::StoredHfBplusMcs, aod::StoredHfBplusMcCollBases, aod::StoredHfBplusMcRCollIds, aod::StoredHfBplusPBases>; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/Tasks/jetSubstructureD0.cxx b/PWGJE/Tasks/jetSubstructureD0.cxx index 593c5294a9c..cf77baa7ffd 100644 --- a/PWGJE/Tasks/jetSubstructureD0.cxx +++ b/PWGJE/Tasks/jetSubstructureD0.cxx @@ -13,9 +13,20 @@ // /// \author Nima Zardoshti -#include #include "PWGJE/Tasks/jetSubstructureHF.cxx" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetSubstructure.h" +#include "PWGJE/DataModel/JetSubtraction.h" + +#include +#include +#include +#include +#include + +#include + using JetSubstructureD0 = JetSubstructureHFTask, soa::Join, soa::Join, soa::Join, aod::CandidatesD0Data, aod::CandidatesD0MCP, aod::D0CJetSSs, aod::D0ChargedSPs, aod::D0ChargedPRs, aod::D0CMCDJetSSs, aod::D0ChargedMCDetectorLevelSPs, aod::D0ChargedMCDetectorLevelPRs, aod::D0CMCPJetSSs, aod::D0ChargedMCParticleLevelSPs, aod::D0ChargedMCParticleLevelPRs, aod::D0CEWSJetSSs, aod::D0ChargedEventWiseSubtractedSPs, aod::D0ChargedEventWiseSubtractedPRs, aod::JTrackD0Subs>; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/Tasks/jetSubstructureD0Output.cxx b/PWGJE/Tasks/jetSubstructureD0Output.cxx index 43b909a3688..d8bdaaf06d1 100644 --- a/PWGJE/Tasks/jetSubstructureD0Output.cxx +++ b/PWGJE/Tasks/jetSubstructureD0Output.cxx @@ -13,9 +13,22 @@ // /// \author Nima Zardoshti -#include #include "PWGJE/Tasks/jetSubstructureHFOutput.cxx" +#include "PWGHF/DataModel/DerivedTables.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedDataHF.h" +#include "PWGJE/DataModel/JetSubstructure.h" +#include "PWGJE/DataModel/JetSubtraction.h" + +#include +#include +#include +#include +#include + +#include + using JetSubstructureOutputD0 = JetSubstructureHFOutputTask, aod::McCollisionsD0, aod::CandidatesD0Data, aod::CandidatesD0MCD, aod::CandidatesD0MCP, aod::BkgD0Rhos, aod::BkgD0McRhos, aod::JTrackD0Subs, soa::Join, soa::Join, soa::Join, soa::Join, aod::D0CJetCOs, aod::D0CJetOs, aod::D0CJetSSOs, aod::D0CJetMOs, soa::Join, soa::Join, soa::Join, aod::D0CMCDJetCOs, aod::D0CMCDJetOs, aod::D0CMCDJetSSOs, aod::D0CMCDJetMOs, soa::Join, soa::Join, soa::Join, soa::Join, aod::D0CMCPJetCOs, aod::D0CMCPJetMCCOs, aod::D0CMCPJetOs, aod::D0CMCPJetSSOs, aod::D0CMCPJetMOs, soa::Join, soa::Join, soa::Join, aod::D0CEWSJetCOs, aod::D0CEWSJetOs, aod::D0CEWSJetSSOs, aod::D0CEWSJetMOs, aod::StoredHfD0CollBase, aod::StoredHfD0Bases, aod::StoredHfD0Pars, aod::StoredHfD0ParEs, aod::JDumD0ParDaus, aod::StoredHfD0Sels, aod::StoredHfD0Mls, aod::JDumD0MlDaus, aod::StoredHfD0Mcs, aod::StoredHfD0McCollBases, aod::StoredHfD0McRCollIds, aod::StoredHfD0PBases>; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/Tasks/jetSubstructureDielectron.cxx b/PWGJE/Tasks/jetSubstructureDielectron.cxx index 665d0f2f636..5ba3468727c 100644 --- a/PWGJE/Tasks/jetSubstructureDielectron.cxx +++ b/PWGJE/Tasks/jetSubstructureDielectron.cxx @@ -13,9 +13,20 @@ // /// \author Nima Zardoshti -#include #include "PWGJE/Tasks/jetSubstructureHF.cxx" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetSubstructure.h" +#include "PWGJE/DataModel/JetSubtraction.h" + +#include +#include +#include +#include +#include + +#include + using JetSubstructureDielectron = JetSubstructureHFTask, soa::Join, soa::Join, soa::Join, aod::CandidatesDielectronData, aod::CandidatesDielectronMCP, aod::DielectronCJetSSs, aod::DielectronChargedSPs, aod::DielectronChargedPRs, aod::DielectronCMCDJetSSs, aod::DielectronChargedMCDetectorLevelSPs, aod::DielectronChargedMCDetectorLevelPRs, aod::DielectronCMCPJetSSs, aod::DielectronChargedMCParticleLevelSPs, aod::DielectronChargedMCParticleLevelPRs, aod::DielectronCEWSJetSSs, aod::DielectronChargedEventWiseSubtractedSPs, aod::DielectronChargedEventWiseSubtractedPRs, aod::JTrackDielectronSubs>; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/Tasks/jetSubstructureDielectronOutput.cxx b/PWGJE/Tasks/jetSubstructureDielectronOutput.cxx index 8c8d7a8980d..84ef77afc4e 100644 --- a/PWGJE/Tasks/jetSubstructureDielectronOutput.cxx +++ b/PWGJE/Tasks/jetSubstructureDielectronOutput.cxx @@ -13,9 +13,22 @@ // /// \author Nima Zardoshti -#include #include "PWGJE/Tasks/jetSubstructureHFOutput.cxx" +#include "PWGDQ/DataModel/ReducedInfoTables.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedDataDQ.h" +#include "PWGJE/DataModel/JetSubstructure.h" +#include "PWGJE/DataModel/JetSubtraction.h" + +#include +#include +#include +#include +#include + +#include + using JetSubstructureOutputDielectron = JetSubstructureHFOutputTask, aod::McCollisionsDielectron, aod::CandidatesDielectronData, aod::CandidatesDielectronMCD, aod::CandidatesDielectronMCP, aod::BkgDielectronRhos, aod::BkgDielectronMcRhos, aod::JTrackDielectronSubs, soa::Join, soa::Join, soa::Join, soa::Join, aod::DielectronCJetCOs, aod::DielectronCJetOs, aod::DielectronCJetSSOs, aod::DielectronCJetMOs, soa::Join, soa::Join, soa::Join, aod::DielectronCMCDJetCOs, aod::DielectronCMCDJetOs, aod::DielectronCMCDJetSSOs, aod::DielectronCMCDJetMOs, soa::Join, soa::Join, soa::Join, soa::Join, aod::DielectronCMCPJetCOs, aod::DielectronCMCPJetMCCOs, aod::DielectronCMCPJetOs, aod::DielectronCMCPJetSSOs, aod::DielectronCMCPJetMOs, soa::Join, soa::Join, soa::Join, aod::DielectronCEWSJetCOs, aod::DielectronCEWSJetOs, aod::DielectronCEWSJetSSOs, aod::DielectronCEWSJetMOs, aod::StoredReducedEvents, aod::StoredDielectrons, aod::JDielectron1Dummys, aod::JDielectron2Dummys, aod::JDielectron3Dummys, aod::JDielectron4Dummys, aod::JDielectron5Dummys, aod::JDielectron6Dummys, aod::JDielectron7Dummys, aod::StoredJDielectronMcCollisions, aod::JDielectronMcRCollDummys, aod::StoredJDielectronMcs>; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/Tasks/jetSubstructureDplus.cxx b/PWGJE/Tasks/jetSubstructureDplus.cxx index 1aee6336c8d..e1550673039 100644 --- a/PWGJE/Tasks/jetSubstructureDplus.cxx +++ b/PWGJE/Tasks/jetSubstructureDplus.cxx @@ -13,9 +13,20 @@ // /// \author Nima Zardoshti -#include #include "PWGJE/Tasks/jetSubstructureHF.cxx" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetSubstructure.h" +#include "PWGJE/DataModel/JetSubtraction.h" + +#include +#include +#include +#include +#include + +#include + using JetSubstructureDplus = JetSubstructureHFTask, soa::Join, soa::Join, soa::Join, aod::CandidatesDplusData, aod::CandidatesDplusMCP, aod::DplusCJetSSs, aod::DplusChargedSPs, aod::DplusChargedPRs, aod::DplusCMCDJetSSs, aod::DplusChargedMCDetectorLevelSPs, aod::DplusChargedMCDetectorLevelPRs, aod::DplusCMCPJetSSs, aod::DplusChargedMCParticleLevelSPs, aod::DplusChargedMCParticleLevelPRs, aod::DplusCEWSJetSSs, aod::DplusChargedEventWiseSubtractedSPs, aod::DplusChargedEventWiseSubtractedPRs, aod::JTrackDplusSubs>; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/Tasks/jetSubstructureDplusOutput.cxx b/PWGJE/Tasks/jetSubstructureDplusOutput.cxx index e45dfc5833c..22a869bfcfa 100644 --- a/PWGJE/Tasks/jetSubstructureDplusOutput.cxx +++ b/PWGJE/Tasks/jetSubstructureDplusOutput.cxx @@ -13,9 +13,22 @@ // /// \author Nima Zardoshti -#include #include "PWGJE/Tasks/jetSubstructureHFOutput.cxx" +#include "PWGHF/DataModel/DerivedTables.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedDataHF.h" +#include "PWGJE/DataModel/JetSubstructure.h" +#include "PWGJE/DataModel/JetSubtraction.h" + +#include +#include +#include +#include +#include + +#include + using JetSubstructureOutputDplus = JetSubstructureHFOutputTask, aod::McCollisionsDplus, aod::CandidatesDplusData, aod::CandidatesDplusMCD, aod::CandidatesDplusMCP, aod::BkgDplusRhos, aod::BkgDplusMcRhos, aod::JTrackDplusSubs, soa::Join, soa::Join, soa::Join, soa::Join, aod::DplusCJetCOs, aod::DplusCJetOs, aod::DplusCJetSSOs, aod::DplusCJetMOs, soa::Join, soa::Join, soa::Join, aod::DplusCMCDJetCOs, aod::DplusCMCDJetOs, aod::DplusCMCDJetSSOs, aod::DplusCMCDJetMOs, soa::Join, soa::Join, soa::Join, soa::Join, aod::DplusCMCPJetCOs, aod::DplusCMCPJetMCCOs, aod::DplusCMCPJetOs, aod::DplusCMCPJetSSOs, aod::DplusCMCPJetMOs, soa::Join, soa::Join, soa::Join, aod::DplusCEWSJetCOs, aod::DplusCEWSJetOs, aod::DplusCEWSJetSSOs, aod::DplusCEWSJetMOs, aod::StoredHfDplusCollBase, aod::StoredHfDplusBases, aod::StoredHfDplusPars, aod::StoredHfDplusParEs, aod::JDumDplusParDaus, aod::StoredHfDplusSels, aod::StoredHfDplusMls, aod::JDumDplusMlDaus, aod::StoredHfDplusMcs, aod::StoredHfDplusMcCollBases, aod::StoredHfDplusMcRCollIds, aod::StoredHfDplusPBases>; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/Tasks/jetSubstructureHF.cxx b/PWGJE/Tasks/jetSubstructureHF.cxx index 3cbdbf6fd34..36394d45286 100644 --- a/PWGJE/Tasks/jetSubstructureHF.cxx +++ b/PWGJE/Tasks/jetSubstructureHF.cxx @@ -14,39 +14,44 @@ /// \author Nima Zardoshti // -#include -#include +#include "RecoDecay.h" -#include "fastjet/PseudoJet.hh" -#include "fastjet/ClusterSequenceArea.hh" +#include "PWGJE/Core/FastJetUtilities.h" +#include "PWGJE/Core/JetDQUtilities.h" +#include "PWGJE/Core/JetFinder.h" +#include "PWGJE/Core/JetHFUtilities.h" +#include "PWGJE/Core/JetSubstructureUtilities.h" +#include "PWGJE/Core/JetUtilities.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" +#include "PWGJE/DataModel/JetSubtraction.h" -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" #include "Framework/ASoA.h" -#include "Framework/O2DatabasePDGPlugin.h" #include "Framework/HistogramRegistry.h" +#include "Framework/O2DatabasePDGPlugin.h" +#include +#include +#include +#include -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectionDefaults.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" +#include -#include "PWGJE/DataModel/Jet.h" -#include "PWGJE/DataModel/JetSubstructure.h" -#include "PWGJE/Core/JetFinder.h" -#include "PWGJE/Core/FastJetUtilities.h" -#include "PWGJE/Core/JetUtilities.h" -#include "PWGJE/Core/JetHFUtilities.h" -#include "PWGJE/Core/JetDQUtilities.h" -#include "PWGJE/Core/JetSubstructureUtilities.h" +#include "fastjet/ClusterSequenceArea.hh" +#include "fastjet/PseudoJet.hh" +#include + +#include +#include +#include +#include + +#include using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; // NB: runDataProcessing.h must be included after customize! -#include "Framework/runDataProcessing.h" template struct JetSubstructureHFTask { diff --git a/PWGJE/Tasks/jetSubstructureHFOutput.cxx b/PWGJE/Tasks/jetSubstructureHFOutput.cxx index 8a781d84bfb..e071303a55d 100644 --- a/PWGJE/Tasks/jetSubstructureHFOutput.cxx +++ b/PWGJE/Tasks/jetSubstructureHFOutput.cxx @@ -14,36 +14,30 @@ /// \author Nima Zardoshti // -#include -#include -#include -#include +#include "PWGJE/Core/JetFindingUtilities.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" +#include "PWGJE/DataModel/JetReducedDataHF.h" +#include "PWGJE/DataModel/JetSubstructure.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" #include "Framework/ASoA.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "TDatabasePDG.h" - -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectionDefaults.h" -#include "Common/DataModel/TrackSelectionTables.h" +#include +#include +#include -#include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" - -#include "PWGJE/DataModel/Jet.h" -#include "PWGJE/DataModel/JetSubstructure.h" -#include "PWGJE/Core/JetFinder.h" -#include "PWGJE/Core/JetFindingUtilities.h" -#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include +#include +#include +#include +#include +#include +#include using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; // NB: runDataProcessing.h must be included after customize! -#include "Framework/runDataProcessing.h" template struct JetSubstructureHFOutputTask { diff --git a/PWGJE/Tasks/jetSubstructureLc.cxx b/PWGJE/Tasks/jetSubstructureLc.cxx index 4f2350bb0a6..6f8260ab2c5 100644 --- a/PWGJE/Tasks/jetSubstructureLc.cxx +++ b/PWGJE/Tasks/jetSubstructureLc.cxx @@ -13,9 +13,20 @@ // /// \author Nima Zardoshti -#include #include "PWGJE/Tasks/jetSubstructureHF.cxx" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetSubstructure.h" +#include "PWGJE/DataModel/JetSubtraction.h" + +#include +#include +#include +#include +#include + +#include + using JetSubstructureLc = JetSubstructureHFTask, soa::Join, soa::Join, soa::Join, aod::CandidatesLcData, aod::CandidatesLcMCP, aod::LcCJetSSs, aod::LcChargedSPs, aod::LcChargedPRs, aod::LcCMCDJetSSs, aod::LcChargedMCDetectorLevelSPs, aod::LcChargedMCDetectorLevelPRs, aod::LcCMCPJetSSs, aod::LcChargedMCParticleLevelSPs, aod::LcChargedMCParticleLevelPRs, aod::LcCEWSJetSSs, aod::LcChargedEventWiseSubtractedSPs, aod::LcChargedEventWiseSubtractedPRs, aod::JTrackLcSubs>; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/Tasks/jetSubstructureLcOutput.cxx b/PWGJE/Tasks/jetSubstructureLcOutput.cxx index 992dc6e2259..e25c204b580 100644 --- a/PWGJE/Tasks/jetSubstructureLcOutput.cxx +++ b/PWGJE/Tasks/jetSubstructureLcOutput.cxx @@ -13,9 +13,22 @@ // /// \author Nima Zardoshti -#include #include "PWGJE/Tasks/jetSubstructureHFOutput.cxx" +#include "PWGHF/DataModel/DerivedTables.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedDataHF.h" +#include "PWGJE/DataModel/JetSubstructure.h" +#include "PWGJE/DataModel/JetSubtraction.h" + +#include +#include +#include +#include +#include + +#include + using JetSubstructureOutputLc = JetSubstructureHFOutputTask, aod::McCollisionsLc, aod::CandidatesLcData, aod::CandidatesLcMCD, aod::CandidatesLcMCP, aod::BkgLcRhos, aod::BkgLcMcRhos, aod::JTrackLcSubs, soa::Join, soa::Join, soa::Join, soa::Join, aod::LcCJetCOs, aod::LcCJetOs, aod::LcCJetSSOs, aod::LcCJetMOs, soa::Join, soa::Join, soa::Join, aod::LcCMCDJetCOs, aod::LcCMCDJetOs, aod::LcCMCDJetSSOs, aod::LcCMCDJetMOs, soa::Join, soa::Join, soa::Join, soa::Join, aod::LcCMCPJetCOs, aod::LcCMCPJetMCCOs, aod::LcCMCPJetOs, aod::LcCMCPJetSSOs, aod::LcCMCPJetMOs, soa::Join, soa::Join, soa::Join, aod::LcCEWSJetCOs, aod::LcCEWSJetOs, aod::LcCEWSJetSSOs, aod::LcCEWSJetMOs, aod::StoredHfLcCollBase, aod::StoredHfLcBases, aod::StoredHfLcPars, aod::StoredHfLcParEs, aod::JDumLcParDaus, aod::StoredHfLcSels, aod::StoredHfLcMls, aod::JDumLcMlDaus, aod::StoredHfLcMcs, aod::StoredHfLcMcCollBases, aod::StoredHfLcMcRCollIds, aod::StoredHfLcPBases>; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/Tasks/jetSubstructureOutput.cxx b/PWGJE/Tasks/jetSubstructureOutput.cxx index 9d2df7c032a..6a907482a58 100644 --- a/PWGJE/Tasks/jetSubstructureOutput.cxx +++ b/PWGJE/Tasks/jetSubstructureOutput.cxx @@ -14,35 +14,31 @@ /// \author Nima Zardoshti // -#include -#include -#include -#include +#include "PWGJE/Core/JetFindingUtilities.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetSubstructure.h" +#include "PWGJE/DataModel/JetSubtraction.h" #include "Framework/ASoA.h" -#include "Framework/AnalysisDataModel.h" #include "Framework/AnalysisTask.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "TDatabasePDG.h" - -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectionDefaults.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/CCDB/EventSelectionParams.h" -#include "Common/DataModel/TrackSelectionTables.h" +#include +#include +#include +#include -#include "PWGJE/Core/JetFinder.h" -#include "PWGJE/Core/JetFindingUtilities.h" -#include "PWGJE/DataModel/Jet.h" -#include "PWGJE/DataModel/JetSubstructure.h" -#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include +#include +#include +#include +#include +#include +#include using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; // NB: runDataProcessing.h must be included after customize! -#include "Framework/runDataProcessing.h" struct JetSubstructureOutputTask { diff --git a/PWGJE/Tasks/jetTaggerHFQA.cxx b/PWGJE/Tasks/jetTaggerHFQA.cxx index 7e2efeceaa3..52a36b2c6e5 100644 --- a/PWGJE/Tasks/jetTaggerHFQA.cxx +++ b/PWGJE/Tasks/jetTaggerHFQA.cxx @@ -14,28 +14,30 @@ /// /// \author Hanseo Park -#include -#include -#include -#include - -#include "TF1.h" +#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include "PWGJE/Core/JetFindingUtilities.h" +#include "PWGJE/Core/JetTaggingUtilities.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" +#include "PWGJE/DataModel/JetTagging.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" #include "Framework/ASoA.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "Framework/runDataProcessing.h" -#include "Common/Core/trackUtilities.h" - -#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include +#include +#include +#include +#include +#include +#include +#include -#include "PWGJE/DataModel/Jet.h" -#include "PWGJE/DataModel/JetTagging.h" -#include "PWGJE/Core/JetFindingUtilities.h" -#include "PWGJE/Core/JetDerivedDataUtilities.h" -#include "PWGJE/Core/JetUtilities.h" -#include "PWGJE/Core/JetTaggingUtilities.h" +#include +#include +#include +#include +#include using namespace o2; using namespace o2::framework; diff --git a/PWGJE/Tasks/jetTriggerChargedQa.cxx b/PWGJE/Tasks/jetTriggerChargedQa.cxx index 3cbb9e18070..f1cb9309cd1 100644 --- a/PWGJE/Tasks/jetTriggerChargedQa.cxx +++ b/PWGJE/Tasks/jetTriggerChargedQa.cxx @@ -14,33 +14,26 @@ /// \file jetTriggerChargedQa.cxx /// \brief QA of trigger performance for charged jets -#include -#include -#include -#include -#include +#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" +#include "Common/CCDB/EventSelectionParams.h" +#include "Common/DataModel/EventSelection.h" + +#include "CommonConstants/MathConstants.h" #include "Framework/ASoA.h" #include "Framework/AnalysisDataModel.h" #include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - -#include "EventFiltering/filterTables.h" - -#include "CommonConstants/MathConstants.h" -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectionDefaults.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" - -#include "PWGJE/Core/JetFinder.h" -#include "PWGJE/Core/FastJetUtilities.h" -#include "PWGJE/Core/JetFindingUtilities.h" -#include "PWGJE/Core/JetDerivedDataUtilities.h" -#include "PWGJE/DataModel/EMCALClusters.h" -#include "PWGJE/DataModel/Jet.h" - #include "Framework/HistogramRegistry.h" +#include +#include +#include +#include + +#include +#include +#include using namespace o2; using namespace o2::framework; diff --git a/PWGJE/Tasks/jetTutorial.cxx b/PWGJE/Tasks/jetTutorial.cxx index cdc02e582f1..42f3153dc65 100644 --- a/PWGJE/Tasks/jetTutorial.cxx +++ b/PWGJE/Tasks/jetTutorial.cxx @@ -14,31 +14,34 @@ /// \author Nima Zardoshti // -#include -#include +#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include "PWGJE/Core/JetUtilities.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" +#include "PWGJE/DataModel/JetSubtraction.h" + +#include "Common/Core/RecoDecay.h" +#include "Common/DataModel/TrackSelectionTables.h" #include "Framework/ASoA.h" #include "Framework/AnalysisDataModel.h" #include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" - -#include "Common/Core/RecoDecay.h" -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectionDefaults.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" - -#include "PWGJE/Core/FastJetUtilities.h" -#include "PWGJE/Core/JetUtilities.h" -#include "PWGJE/Core/JetDerivedDataUtilities.h" -#include "PWGJE/DataModel/Jet.h" +#include +#include +#include +#include +#include + +#include +#include +#include +#include using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; -#include "Framework/runDataProcessing.h" - struct JetTutorialTask { HistogramRegistry registry{"registry", {{"h_collisions", "event status;event status;entries", {HistType::kTH1F, {{4, 0.0, 4.0}}}}, diff --git a/PWGJE/Tasks/jetTutorialSkeleton.cxx b/PWGJE/Tasks/jetTutorialSkeleton.cxx index df2098539e8..eeccd409d26 100644 --- a/PWGJE/Tasks/jetTutorialSkeleton.cxx +++ b/PWGJE/Tasks/jetTutorialSkeleton.cxx @@ -14,31 +14,24 @@ /// \author Nima Zardoshti // -#include -#include +#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" #include "Framework/ASoA.h" -#include "Framework/AnalysisDataModel.h" #include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" +#include +#include +#include +#include -#include "Common/Core/RecoDecay.h" -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectionDefaults.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" - -#include "PWGJE/Core/FastJetUtilities.h" -#include "PWGJE/Core/JetUtilities.h" -#include "PWGJE/Core/JetDerivedDataUtilities.h" -#include "PWGJE/DataModel/Jet.h" - +#include +#include using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; -#include "Framework/runDataProcessing.h" - struct JetTutorialSkeletonTask { HistogramRegistry registry{"registry", {{"h_collisions", "event status;event status;entries", {HistType::kTH1F, {{4, 0.0, 4.0}}}}, diff --git a/PWGJE/Tasks/jetValidationQA.cxx b/PWGJE/Tasks/jetValidationQA.cxx index 9facbcaf6e9..bf4c8348c10 100644 --- a/PWGJE/Tasks/jetValidationQA.cxx +++ b/PWGJE/Tasks/jetValidationQA.cxx @@ -12,18 +12,23 @@ /// \author Johanna Lömker // \since Dec 2022 -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" +#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" + +#include "Common/DataModel/TrackSelectionTables.h" + #include "Framework/ASoA.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" +#include +#include +#include +#include -#include "PWGJE/DataModel/Jet.h" -#include "PWGJE/Core/JetDerivedDataUtilities.h" - -#include "Common/DataModel/EventSelection.h" -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectionDefaults.h" +#include +#include using namespace o2; using namespace o2::framework; diff --git a/PWGJE/Tasks/mcGeneratorStudies.cxx b/PWGJE/Tasks/mcGeneratorStudies.cxx index 53d9ef15ef0..c783a0a8c09 100644 --- a/PWGJE/Tasks/mcGeneratorStudies.cxx +++ b/PWGJE/Tasks/mcGeneratorStudies.cxx @@ -13,21 +13,29 @@ // /// \author Nicolas Strangmann , Goethe University Frankfurt / Oak Ridge National Laoratory -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoA.h" -#include "Framework/HistogramRegistry.h" - #include "PWGJE/DataModel/EMCALMatchedCollisions.h" -#include "DetectorsBase/GeometryManager.h" -#include "EMCALBase/Geometry.h" - -#include "Common/DataModel/TrackSelectionTables.h" +#include "Common/CCDB/EventSelectionParams.h" +#include "Common/CCDB/TriggerAliases.h" #include "Common/DataModel/EventSelection.h" +#include "EMCALBase/Geometry.h" +#include "Framework/ASoA.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include +#include +#include +#include +#include + #include "TDatabasePDG.h" +#include +#include + +#include +#include using namespace o2; using namespace o2::framework; diff --git a/PWGJE/Tasks/nsubjettiness.cxx b/PWGJE/Tasks/nsubjettiness.cxx index 1eabf7c6c50..e80219c0f82 100644 --- a/PWGJE/Tasks/nsubjettiness.cxx +++ b/PWGJE/Tasks/nsubjettiness.cxx @@ -15,23 +15,27 @@ /// \author Aimeric Landou /// \author Nima Zardoshti -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" +#include "PWGJE/Core/JetFinder.h" +#include "PWGJE/Core/JetSubstructureUtilities.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" + #include "Framework/ASoA.h" -#include "Framework/runDataProcessing.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "Framework/Logger.h" +#include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" +#include +#include +#include +#include +#include + +#include +#include -#include "PWGJE/DataModel/Jet.h" -#include "PWGJE/Core/JetUtilities.h" -#include "PWGJE/Core/JetFinder.h" -#include "PWGJE/Core/FastJetUtilities.h" -#include "PWGJE/Core/JetFindingUtilities.h" -#include "PWGJE/Core/JetSubstructureUtilities.h" #include "fastjet/contrib/AxesDefinition.hh" -#include "fastjet/contrib/MeasureDefinition.hh" +#include + +#include using namespace o2; using namespace o2::framework; diff --git a/PWGJE/Tasks/nucleiInJets.cxx b/PWGJE/Tasks/nucleiInJets.cxx index 0d620b1986f..6f96263f3a2 100644 --- a/PWGJE/Tasks/nucleiInJets.cxx +++ b/PWGJE/Tasks/nucleiInJets.cxx @@ -11,42 +11,50 @@ // author: Arvind Khuntia (arvind.khuntia@cern.ch) INFN Bologna, Italy -#include -#include -#include -#include -#include -#include -#include -#include - -#include "Framework/ASoA.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" +#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" +#include "PWGLF/DataModel/LFParticleIdentification.h" -#include "CCDB/BasicCCDBManager.h" #include "Common/Core/RecoDecay.h" -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectionDefaults.h" -#include "Common/Core/trackUtilities.h" #include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" #include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/PIDResponse.h" -#include "CommonConstants/PhysicsConstants.h" - +#include "Common/DataModel/PIDResponseTOF.h" +#include "Common/DataModel/PIDResponseTPC.h" +#include "Common/DataModel/TrackSelectionTables.h" #include "EventFiltering/Zorro.h" #include "EventFiltering/ZorroSummary.h" -#include "ReconstructionDataFormats/Track.h" -#include "PWGLF/DataModel/LFParticleIdentification.h" +#include "CCDB/BasicCCDBManager.h" +#include "Framework/ASoA.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include -#include "PWGJE/Core/FastJetUtilities.h" -#include "PWGJE/Core/JetDerivedDataUtilities.h" -#include "PWGJE/DataModel/Jet.h" -#include "PWGJE/DataModel/JetReducedDataSelector.h" +#include +#include +#include +#include +#include +#include +#include +#include + +#include using namespace o2; using namespace o2::framework; diff --git a/PWGJE/Tasks/phiInJets.cxx b/PWGJE/Tasks/phiInJets.cxx index 88a09016b44..821169310b0 100644 --- a/PWGJE/Tasks/phiInJets.cxx +++ b/PWGJE/Tasks/phiInJets.cxx @@ -15,36 +15,46 @@ /// /// \author Adrian Fereydon Nassirpour -#include -#include -#include -#include -#include -#include +#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" -#include "TRandom.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" + +#include "CommonConstants/PhysicsConstants.h" #include "Framework/ASoA.h" #include "Framework/AnalysisDataModel.h" #include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/Track.h" +#include +#include +#include +#include +#include +#include -#include "Common/Core/RecoDecay.h" -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectionDefaults.h" -#include "Common/Core/trackUtilities.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/PIDResponse.h" -#include "CommonConstants/PhysicsConstants.h" +#include "TRandom.h" +#include +#include +#include +#include -#include "PWGJE/Core/FastJetUtilities.h" -#include "PWGJE/Core/JetDerivedDataUtilities.h" -#include "PWGJE/DataModel/Jet.h" +#include + +#include +#include +#include +#include +#include +#include +#include +#include -#include "PWGLF/DataModel/LFResonanceTables.h" +#include using namespace o2; using namespace o2::framework; diff --git a/PWGJE/Tasks/photonIsolationQA.cxx b/PWGJE/Tasks/photonIsolationQA.cxx index 7bac1ce3d5b..1738fef952f 100644 --- a/PWGJE/Tasks/photonIsolationQA.cxx +++ b/PWGJE/Tasks/photonIsolationQA.cxx @@ -9,38 +9,37 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoA.h" -#include "Framework/HistogramRegistry.h" +#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include "PWGJE/DataModel/EMCALClusters.h" #include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/Centrality.h" -#include "Common/DataModel/PIDResponse.h" #include "Common/DataModel/TrackSelectionTables.h" #include "EMCALBase/Geometry.h" #include "EMCALCalib/BadChannelMap.h" -#include "PWGJE/DataModel/JetReducedData.h" -#include "PWGJE/DataModel/EMCALClusters.h" -#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include "Framework/ASoA.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include -#include "DataFormatsEMCAL/Cell.h" -#include "DataFormatsEMCAL/Constants.h" -#include "DataFormatsEMCAL/AnalysisCluster.h" -#include "CommonDataFormat/InteractionRecord.h" +#include // \struct PhotonIsolationQA /// \brief Task to select emcal clusters originating from promt photons diff --git a/PWGJE/Tasks/recoilJets.cxx b/PWGJE/Tasks/recoilJets.cxx index 26abd49517a..1a7b3c785ff 100644 --- a/PWGJE/Tasks/recoilJets.cxx +++ b/PWGJE/Tasks/recoilJets.cxx @@ -13,32 +13,33 @@ /// \file recoilJets.cxx /// \brief hadron-jet correlation analysis -#include "PWGJE/Core/FastJetUtilities.h" #include "PWGJE/Core/JetDerivedDataUtilities.h" -#include "PWGJE/Core/JetFinder.h" -#include "PWGJE/Core/JetFindingUtilities.h" #include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" +#include "PWGJE/DataModel/JetSubtraction.h" #include "Common/Core/RecoDecay.h" -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectionDefaults.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "EventFiltering/filterTables.h" #include "CommonConstants/MathConstants.h" #include "Framework/ASoA.h" -#include "Framework/AnalysisDataModel.h" #include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" #include "Framework/O2DatabasePDGPlugin.h" -#include "Framework/runDataProcessing.h" +#include +#include +#include +#include +#include #include "TRandom3.h" -#include "TVector2.h" +#include +#include +#include +#include #include #include +#include #include using namespace o2; diff --git a/PWGJE/Tasks/statPromptPhoton.cxx b/PWGJE/Tasks/statPromptPhoton.cxx index 62d9bf72b97..80ebe23550d 100644 --- a/PWGJE/Tasks/statPromptPhoton.cxx +++ b/PWGJE/Tasks/statPromptPhoton.cxx @@ -14,49 +14,33 @@ /// /// /// \author Adrian Fereydon Nassirpour -#include -#include -#include -#include -#include +#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include "PWGJE/DataModel/EMCALClusters.h" +#include "PWGJE/DataModel/JetReducedData.h" -#include -#include +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/TrackSelectionTables.h" #include "Framework/ASoA.h" #include "Framework/AnalysisDataModel.h" #include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/Track.h" +#include +#include +#include +#include +#include -#include "Common/Core/RecoDecay.h" -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectionDefaults.h" -#include "Common/Core/trackUtilities.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/PIDResponse.h" -#include "CommonConstants/PhysicsConstants.h" - -#include "PWGJE/Core/FastJetUtilities.h" -#include "PWGJE/Core/JetDerivedDataUtilities.h" -#include "PWGJE/DataModel/Jet.h" -#include "PWGJE/DataModel/EMCALClusters.h" -#include "EMCALBase/Geometry.h" -#include "EMCALCalib/BadChannelMap.h" - -#include "DataFormatsEMCAL/Cell.h" -#include "DataFormatsEMCAL/Constants.h" -#include "DataFormatsEMCAL/AnalysisCluster.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DataFormatsParameters/GRPMagField.h" - -#include "DetectorsBase/Propagator.h" +#include +#include +#include -#include "CommonDataFormat/InteractionRecord.h" +#include +#include +#include +#include +#include using namespace o2; using namespace o2::framework; diff --git a/PWGJE/Tasks/trackEfficiency.cxx b/PWGJE/Tasks/trackEfficiency.cxx index 87e37014ae7..ae7344c0876 100644 --- a/PWGJE/Tasks/trackEfficiency.cxx +++ b/PWGJE/Tasks/trackEfficiency.cxx @@ -13,31 +13,27 @@ /// \author Aimeric Landou /// \brief task that creates the histograms necessary for computation of efficiency and purity functions in offline postprocess macros; also can make mcparticle and track QC histograms -#include -#include -#include -#include -#include +#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" #include "Framework/ASoA.h" -#include "Framework/AnalysisDataModel.h" #include "Framework/AnalysisTask.h" -#include "Framework/O2DatabasePDGPlugin.h" #include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" - -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectionDefaults.h" - -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" +#include "Framework/O2DatabasePDGPlugin.h" +#include +#include +#include +#include +#include +#include -#include "PWGJE/Core/FastJetUtilities.h" -#include "PWGJE/Core/JetFinder.h" -#include "PWGJE/Core/JetFindingUtilities.h" -#include "PWGJE/DataModel/Jet.h" +#include -#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include +#include +#include +#include using namespace o2; using namespace o2::framework; @@ -356,7 +352,7 @@ struct TrackEfficiency { registry.fill(HIST("h3_particle_pt_high_particle_eta_particle_phi_mcpartofinterest"), jMcParticle.pt(), jMcParticle.eta(), jMcParticle.phi()); if ((std::abs(jMcParticle.eta()) < trackEtaAcceptanceCountQA)) { // removed from actual cuts for now because all the histograms have an eta axis - registry.fill(HIST("hMcPartCutsCounts"), 3.5); // etaAccept // not actually applied here but it will give an idea of what will be done in the post processing + registry.fill(HIST("hMcPartCutsCounts"), 3.5); // etaAccept // not actually applied here but it will give an idea of what will be done in the post processing } } diff --git a/PWGJE/Tasks/trackJetQA.cxx b/PWGJE/Tasks/trackJetQA.cxx index f0549a0a0e3..2f3c9a51eb6 100644 --- a/PWGJE/Tasks/trackJetQA.cxx +++ b/PWGJE/Tasks/trackJetQA.cxx @@ -15,27 +15,29 @@ /// \since 2023-10-02 /// \brief Task producing jet tracking qa histograms /// -#include - -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" -#include "Framework/ASoA.h" +#include "PWGJE/DataModel/TrackJetQa.h" -#include "Common/DataModel/TrackSelectionTables.h" #include "Common/Core/TrackSelection.h" #include "Common/Core/TrackSelectionDefaults.h" - -#include "PWGJE/DataModel/Jet.h" -#include "PWGJE/DataModel/TrackJetQa.h" -#include "PWGJE/Core/JetDerivedDataUtilities.h" - #include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" #include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include "Framework/ASoA.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include +#include +#include +#include +#include +#include + +#include using namespace o2; -using namespace o2::track; using namespace o2::framework; using namespace o2::framework::expressions; diff --git a/PWGJE/Tasks/triggerCorrelations.cxx b/PWGJE/Tasks/triggerCorrelations.cxx index bb2d43e1f95..89a66e16ff1 100644 --- a/PWGJE/Tasks/triggerCorrelations.cxx +++ b/PWGJE/Tasks/triggerCorrelations.cxx @@ -13,33 +13,26 @@ // /// \author Nima Zardoshti -#include +#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include "PWGJE/DataModel/JetReducedData.h" -#include "EMCALBase/Geometry.h" #include "Framework/ASoA.h" -#include "Framework/AnalysisDataModel.h" #include "Framework/AnalysisTask.h" -#include "Framework/O2DatabasePDGPlugin.h" #include "Framework/HistogramRegistry.h" +#include +#include +#include +#include -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectionDefaults.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "Common/CCDB/TriggerAliases.h" +#include -#include "PWGJE/Core/FastJetUtilities.h" -#include "PWGJE/Core/JetDerivedDataUtilities.h" -#include "PWGJE/DataModel/EMCALClusters.h" -#include "PWGJE/Core/JetFinder.h" -#include "PWGJE/DataModel/Jet.h" +#include +#include using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; -#include "Framework/runDataProcessing.h" - struct TriggerCorrelationsTask { HistogramRegistry registry; diff --git a/PWGJE/Tasks/v0JetSpectra.cxx b/PWGJE/Tasks/v0JetSpectra.cxx index 700f0b33b54..95081bad725 100644 --- a/PWGJE/Tasks/v0JetSpectra.cxx +++ b/PWGJE/Tasks/v0JetSpectra.cxx @@ -14,27 +14,23 @@ /// \author Gijs van Weelden // -#include -#include +#include "JetDerivedDataUtilities.h" -#include "TH1F.h" -#include "TTree.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" #include "Framework/ASoA.h" -#include "Framework/RunningWorkflowInfo.h" - -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/PIDResponse.h" +#include "Framework/AnalysisTask.h" +#include +#include +#include +#include +#include -#include "CommonConstants/PhysicsConstants.h" +#include -#include "PWGJE/DataModel/Jet.h" -#include "PWGJE/Core/JetFinder.h" -#include "PWGJE/Core/JetUtilities.h" -#include "PWGJE/Core/JetFindingUtilities.h" +#include +#include using namespace o2; using namespace o2::framework; diff --git a/PWGJE/Tasks/v0QA.cxx b/PWGJE/Tasks/v0QA.cxx index 8d8d0ab2cfc..0f6793ef4ae 100644 --- a/PWGJE/Tasks/v0QA.cxx +++ b/PWGJE/Tasks/v0QA.cxx @@ -14,29 +14,30 @@ /// /// \author Gijs van Weelden -#include -#include - -#include "TH1F.h" -#include "TTree.h" - -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoA.h" -#include "Framework/RunningWorkflowInfo.h" - -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/PIDResponse.h" - -#include "CommonConstants/PhysicsConstants.h" +#include "JetDerivedDataUtilities.h" -#include "PWGJE/DataModel/Jet.h" -#include "PWGJE/Core/JetFinder.h" -#include "PWGJE/Core/JetUtilities.h" #include "PWGJE/Core/JetFindingUtilities.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" #include "PWGLF/DataModel/V0SelectorTables.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include "Framework/ASoA.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include +#include +#include +#include +#include +#include + +#include +#include +#include + using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; From 830bca1dbb566cf5671adc067cbc119103d44d6a Mon Sep 17 00:00:00 2001 From: nkaratze Date: Mon, 16 Jun 2025 11:09:12 +0100 Subject: [PATCH 087/871] [PWGLF] v0ptinvmassplots: Added INEL>0 (#11560) Co-authored-by: nkaratze --- PWGLF/Tasks/Strangeness/v0ptinvmassplots.cxx | 469 ++++++++++--------- 1 file changed, 242 insertions(+), 227 deletions(-) diff --git a/PWGLF/Tasks/Strangeness/v0ptinvmassplots.cxx b/PWGLF/Tasks/Strangeness/v0ptinvmassplots.cxx index b5f014ffaba..cf92a7cbc65 100644 --- a/PWGLF/Tasks/Strangeness/v0ptinvmassplots.cxx +++ b/PWGLF/Tasks/Strangeness/v0ptinvmassplots.cxx @@ -20,19 +20,25 @@ for different pt ranges (constituting bins). The values are inserted as configur Also feed-down matrices for the Lambda and Anti-Lambda are produced. This analysis includes three processes, one for Real Data and two for MC at the Generated and Reconstructed level*/ -#include -#include -#include +#include "PWGLF/DataModel/LFStrangenessTables.h" +#include "PWGLF/Utils/inelGt.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" #include "Common/DataModel/EventSelection.h" -#include "PWGLF/DataModel/LFStrangenessTables.h" #include "Common/DataModel/PIDResponse.h" -#include "CommonUtils/StringUtils.h" + #include "CommonConstants/PhysicsConstants.h" +#include "CommonUtils/StringUtils.h" +#include "Framework/AnalysisTask.h" +#include "Framework/O2DatabasePDGPlugin.h" +#include "Framework/runDataProcessing.h" + #include "TPDGCode.h" +#include +#include +#include +#include + // namespace to be used for pt plots and bins namespace pthistos { @@ -246,60 +252,65 @@ struct V0PtInvMassPlots { using DaughterTracks = soa::Join; // This is the Process for the MC Generated Data - void genMCProcess(soa::Filtered::iterator const&, - const soa::SmallGroups>&, - aod::McParticles const& mcParticles) + // void genMCProcess(soa::Filtered::iterator const&, + // const soa::SmallGroups>& collision, + // aod::McParticles const& mcParticles) + void genMCProcess( // soa::Filtered::iterator const&, + soa::Filtered>::iterator const& collision, + aod::McParticles const& mcParticles) { for (const auto& mcParticle : mcParticles) { - if (std::abs(mcParticle.y()) < rapidityCut) { - if (mcParticle.isPhysicalPrimary()) { - rPtAnalysis.fill(HIST("GenParticleRapidity"), mcParticle.y()); - if (mcParticle.pdgCode() == kK0Short) // kzero matched - { - rPtAnalysis.fill(HIST("hK0ShGeneratedPtSpectrum"), mcParticle.pt()); - } - if (mcParticle.pdgCode() == kLambda0) // lambda matched - { - rPtAnalysis.fill(HIST("hLambdaGeneratedPtSpectrum"), mcParticle.pt()); - } - if (mcParticle.pdgCode() == kLambda0Bar) // antilambda matched - { - rPtAnalysis.fill(HIST("hAntilambdaGeneratedPtSpectrum"), mcParticle.pt()); - } - if (mcParticle.pdgCode() == kXiMinus) // Xi Minus matched - { - rPtAnalysis.fill(HIST("hXiMinusGeneratedPtSpectrum"), mcParticle.pt()); - } - if (mcParticle.pdgCode() == kXi0) // Xi Zero matched - { - rPtAnalysis.fill(HIST("hXiZeroGeneratedPtSpectrum"), mcParticle.pt()); - } - if (mcParticle.pdgCode() == kOmegaMinus) // Omega matched - { - rPtAnalysis.fill(HIST("hOmegaGeneratedPtSpectrum"), mcParticle.pt()); - } - if (mcParticle.pdgCode() == kXiPlusBar) // Xi Plus matched - { - rPtAnalysis.fill(HIST("hXiPlusGeneratedPtSpectrum"), mcParticle.pt()); - } - if (mcParticle.pdgCode() == -kXi0) // Anti-Xi Zero matched - { - rPtAnalysis.fill(HIST("hAntiXiZeroGeneratedPtSpectrum"), mcParticle.pt()); - } - if (mcParticle.pdgCode() == kOmegaPlusBar) // Anti-Omega matched - { - rPtAnalysis.fill(HIST("hAntiOmegaGeneratedPtSpectrum"), mcParticle.pt()); - } - if (mcParticle.pdgCode() == kPhi) // Anti-Omega matched - { - rPtAnalysis.fill(HIST("hPhiGeneratedPtSpectrum"), mcParticle.pt()); + if (collision.isInelGt0()) { + if (std::abs(mcParticle.y()) < rapidityCut) { + if (mcParticle.isPhysicalPrimary()) { + rPtAnalysis.fill(HIST("GenParticleRapidity"), mcParticle.y()); + if (mcParticle.pdgCode() == kK0Short) // kzero matched + { + rPtAnalysis.fill(HIST("hK0ShGeneratedPtSpectrum"), mcParticle.pt()); + } + if (mcParticle.pdgCode() == kLambda0) // lambda matched + { + rPtAnalysis.fill(HIST("hLambdaGeneratedPtSpectrum"), mcParticle.pt()); + } + if (mcParticle.pdgCode() == kLambda0Bar) // antilambda matched + { + rPtAnalysis.fill(HIST("hAntilambdaGeneratedPtSpectrum"), mcParticle.pt()); + } + if (mcParticle.pdgCode() == kXiMinus) // Xi Minus matched + { + rPtAnalysis.fill(HIST("hXiMinusGeneratedPtSpectrum"), mcParticle.pt()); + } + if (mcParticle.pdgCode() == kXi0) // Xi Zero matched + { + rPtAnalysis.fill(HIST("hXiZeroGeneratedPtSpectrum"), mcParticle.pt()); + } + if (mcParticle.pdgCode() == kOmegaMinus) // Omega matched + { + rPtAnalysis.fill(HIST("hOmegaGeneratedPtSpectrum"), mcParticle.pt()); + } + if (mcParticle.pdgCode() == kXiPlusBar) // Xi Plus matched + { + rPtAnalysis.fill(HIST("hXiPlusGeneratedPtSpectrum"), mcParticle.pt()); + } + if (mcParticle.pdgCode() == -kXi0) // Anti-Xi Zero matched + { + rPtAnalysis.fill(HIST("hAntiXiZeroGeneratedPtSpectrum"), mcParticle.pt()); + } + if (mcParticle.pdgCode() == kOmegaPlusBar) // Anti-Omega matched + { + rPtAnalysis.fill(HIST("hAntiOmegaGeneratedPtSpectrum"), mcParticle.pt()); + } + if (mcParticle.pdgCode() == kPhi) // Anti-Omega matched + { + rPtAnalysis.fill(HIST("hPhiGeneratedPtSpectrum"), mcParticle.pt()); + } } } } } } // This is the Process for the MC reconstructed Data - void recMCProcess(soa::Filtered>::iterator const& collision, + void recMCProcess(soa::Filtered>::iterator const& collision, soa::Join const& V0s, DaughterTracks const&, // no need to define a variable for tracks, if we don't access them directly aod::McParticles const&) @@ -324,119 +335,121 @@ struct V0PtInvMassPlots { antilambdaPtedgevalues[i] = std::stod(pthistos::antilambdaPtBins[i]); } rPtAnalysis.fill(HIST("hVertexZ"), collision.posZ()); - for (const auto& v0 : V0s) { - rPtAnalysis.fill(HIST("hVertexZRec"), collision.posZ()); - // Checking that the V0 is a true K0s/Lambdas/Antilambdas and then filling the parameter histograms and the invariant mass plots for different cuts (which are taken from namespace) - if (v0.has_mcParticle()) { - auto v0mcParticle = v0.mcParticle(); - if (std::abs(v0mcParticle.y()) < rapidityCut) { - rPtAnalysis.fill(HIST("V0Rapidity"), v0.y()); - if (std::abs(v0.posTrack_as().eta()) < etadau && std::abs(v0.negTrack_as().eta()) < etadau) { // daughters pseudorapidityCut cut - rPtAnalysis.fill(HIST("hV0EtaDaughters"), v0.negTrack_as().eta()); - rPtAnalysis.fill(HIST("hV0EtaDaughters"), v0.posTrack_as().eta()); - if (kzeroAnalysis == true) { - if (v0mcParticle.pdgCode() == kK0Short) { // kzero matched - rPtAnalysis.fill(HIST("hMassK0ShortAll"), v0.mK0Short()); - rPtAnalysis.fill(HIST("hK0ShortPtSpectrumBeforeCuts"), v0.pt()); - if (std::abs(v0.mLambda() - mLambdaPDG) > compv0masscut && std::abs(v0.mAntiLambda() - mLambdaPDG) > compv0masscut) { // Kzero competitive v0 mass cut (cut out Lambdas and Anti-Lambdas) - // Implementing best kzero topological cuts - if (v0.v0cosPA() > kaonshSettingcosPA && v0.dcaV0daughters() < kaonshSettingdcav0dau && v0.v0radius() > kaonshSettingradius && std::abs(v0.dcapostopv()) > kaonshSettingdcapostopv && std::abs(v0.dcanegtopv()) > kaonshSettingdcanegtopv) { - rPtAnalysis.fill(HIST("hMassK0ShortAllAfterCuts"), v0.mK0Short()); - rPtAnalysis.fill(HIST("hK0ShortReconstructedPtSpectrum"), v0.pt()); - rPtAnalysis.fill(HIST("hK0shEtaDaughters"), v0.negTrack_as().eta()); - rPtAnalysis.fill(HIST("hK0shEtaDaughters"), v0.posTrack_as().eta()); - rPtAnalysis.fill(HIST("hK0shNegDaughterPt"), v0.negTrack_as().pt()); // Neg Daughter Pt - rPtAnalysis.fill(HIST("hK0shPosDaughterPt"), v0.posTrack_as().pt()); // Pos Daughter Pt - if (v0mcParticle.isPhysicalPrimary()) { - for (int i = 0; i < nmaxHistograms; i++) { - if (kaonptedgevalues[i] <= v0.pt() && v0.pt() < kaonptedgevalues[i + 1]) { // finding v0s with pt within the range of our bin edges - pthistos::kaonPt[i]->Fill(v0.mK0Short()); // filling the k0s namespace histograms + if (collision.isInelGt0()) { + for (const auto& v0 : V0s) { + rPtAnalysis.fill(HIST("hVertexZRec"), collision.posZ()); + // Checking that the V0 is a true K0s/Lambdas/Antilambdas and then filling the parameter histograms and the invariant mass plots for different cuts (which are taken from namespace) + if (v0.has_mcParticle()) { + auto v0mcParticle = v0.mcParticle(); + if (std::abs(v0mcParticle.y()) < rapidityCut) { + rPtAnalysis.fill(HIST("V0Rapidity"), v0.y()); + if (std::abs(v0.posTrack_as().eta()) < etadau && std::abs(v0.negTrack_as().eta()) < etadau) { // daughters pseudorapidityCut cut + rPtAnalysis.fill(HIST("hV0EtaDaughters"), v0.negTrack_as().eta()); + rPtAnalysis.fill(HIST("hV0EtaDaughters"), v0.posTrack_as().eta()); + if (kzeroAnalysis == true) { + if (v0mcParticle.pdgCode() == kK0Short) { // kzero matched + rPtAnalysis.fill(HIST("hMassK0ShortAll"), v0.mK0Short()); + rPtAnalysis.fill(HIST("hK0ShortPtSpectrumBeforeCuts"), v0.pt()); + if (std::abs(v0.mLambda() - mLambdaPDG) > compv0masscut && std::abs(v0.mAntiLambda() - mLambdaPDG) > compv0masscut) { // Kzero competitive v0 mass cut (cut out Lambdas and Anti-Lambdas) + // Implementing best kzero topological cuts + if (v0.v0cosPA() > kaonshSettingcosPA && v0.dcaV0daughters() < kaonshSettingdcav0dau && v0.v0radius() > kaonshSettingradius && std::abs(v0.dcapostopv()) > kaonshSettingdcapostopv && std::abs(v0.dcanegtopv()) > kaonshSettingdcanegtopv) { + rPtAnalysis.fill(HIST("hMassK0ShortAllAfterCuts"), v0.mK0Short()); + rPtAnalysis.fill(HIST("hK0ShortReconstructedPtSpectrum"), v0.pt()); + rPtAnalysis.fill(HIST("hK0shEtaDaughters"), v0.negTrack_as().eta()); + rPtAnalysis.fill(HIST("hK0shEtaDaughters"), v0.posTrack_as().eta()); + rPtAnalysis.fill(HIST("hK0shNegDaughterPt"), v0.negTrack_as().pt()); // Neg Daughter Pt + rPtAnalysis.fill(HIST("hK0shPosDaughterPt"), v0.posTrack_as().pt()); // Pos Daughter Pt + if (v0mcParticle.isPhysicalPrimary()) { + for (int i = 0; i < nmaxHistograms; i++) { + if (kaonptedgevalues[i] <= v0.pt() && v0.pt() < kaonptedgevalues[i + 1]) { // finding v0s with pt within the range of our bin edges + pthistos::kaonPt[i]->Fill(v0.mK0Short()); // filling the k0s namespace histograms + } } } } } } } - } - // lambda analysis - if (lambdaAnalysis == true) { - if (v0mcParticle.pdgCode() == kLambda0) { // lambda matched - rPtAnalysis.fill(HIST("hMassLambdaAll"), v0.mLambda()); - rPtAnalysis.fill(HIST("hLambdaPtSpectrumBeforeCuts"), v0.pt()); - if (std::abs(v0.mK0Short() - mK0shPDG) > compv0masscut) { // lambda competitive v0 mass cut (cut out Kaons) - // Implementing best lambda cuts - if (v0.v0cosPA() > lambdaSettingcosPA && v0.dcaV0daughters() < lambdaSettingdcav0dau && v0.v0radius() > lambdaSettingradius && std::abs(v0.dcapostopv()) > lambdaSettingdcapostopv && std::abs(v0.dcanegtopv()) > lambdaSettingdcanegtopv) { - rPtAnalysis.fill(HIST("hMassLambdaAllAfterCuts"), v0.mLambda()); - rPtAnalysis.fill(HIST("hLambdaReconstructedPtSpectrum"), v0.pt()); - rPtAnalysis.fill(HIST("hLambdaEtaDaughters"), v0.negTrack_as().eta()); - rPtAnalysis.fill(HIST("hLambdaEtaDaughters"), v0.posTrack_as().eta()); - rPtAnalysis.fill(HIST("hLambdaNegDaughterPt"), v0.negTrack_as().pt()); // Neg Daughter Pt - rPtAnalysis.fill(HIST("hLambdaPosDaughterPt"), v0.posTrack_as().pt()); // Pos Daughter Pt - if (v0mcParticle.isPhysicalPrimary()) { - for (int i = 0; i < nmaxHistograms; i++) { - if (lambdaptedgevalues[i] <= v0.pt() && v0.pt() < lambdaptedgevalues[i + 1]) { - pthistos::lambdaPt[i]->Fill(v0.mLambda()); + // lambda analysis + if (lambdaAnalysis == true) { + if (v0mcParticle.pdgCode() == kLambda0) { // lambda matched + rPtAnalysis.fill(HIST("hMassLambdaAll"), v0.mLambda()); + rPtAnalysis.fill(HIST("hLambdaPtSpectrumBeforeCuts"), v0.pt()); + if (std::abs(v0.mK0Short() - mK0shPDG) > compv0masscut) { // lambda competitive v0 mass cut (cut out Kaons) + // Implementing best lambda cuts + if (v0.v0cosPA() > lambdaSettingcosPA && v0.dcaV0daughters() < lambdaSettingdcav0dau && v0.v0radius() > lambdaSettingradius && std::abs(v0.dcapostopv()) > lambdaSettingdcapostopv && std::abs(v0.dcanegtopv()) > lambdaSettingdcanegtopv) { + rPtAnalysis.fill(HIST("hMassLambdaAllAfterCuts"), v0.mLambda()); + rPtAnalysis.fill(HIST("hLambdaReconstructedPtSpectrum"), v0.pt()); + rPtAnalysis.fill(HIST("hLambdaEtaDaughters"), v0.negTrack_as().eta()); + rPtAnalysis.fill(HIST("hLambdaEtaDaughters"), v0.posTrack_as().eta()); + rPtAnalysis.fill(HIST("hLambdaNegDaughterPt"), v0.negTrack_as().pt()); // Neg Daughter Pt + rPtAnalysis.fill(HIST("hLambdaPosDaughterPt"), v0.posTrack_as().pt()); // Pos Daughter Pt + if (v0mcParticle.isPhysicalPrimary()) { + for (int i = 0; i < nmaxHistograms; i++) { + if (lambdaptedgevalues[i] <= v0.pt() && v0.pt() < lambdaptedgevalues[i + 1]) { + pthistos::lambdaPt[i]->Fill(v0.mLambda()); + } } } - } - if (!v0mcParticle.isPhysicalPrimary()) { - auto v0mothers = v0mcParticle.mothers_as(); // Get mothers - if (!v0mothers.empty()) { - auto& v0mcParticleMother = v0mothers.front(); // First mother - if (v0mcParticleMother.pdgCode() == kXiMinus) // Xi Minus Mother Matched - { - rFeeddownMatrices.fill(HIST("hLambdaXiMinusFeeddownMatrix"), v0mcParticle.pt(), v0mcParticleMother.pt()); - } - if (v0mcParticleMother.pdgCode() == kXi0) // Xi Zero Mother Matched - { - rFeeddownMatrices.fill(HIST("hLambdaXiZeroFeeddownMatrix"), v0mcParticle.pt(), v0mcParticleMother.pt()); - } - if (v0mcParticleMother.pdgCode() == kOmegaMinus) // Omega Mother Matched - { - rFeeddownMatrices.fill(HIST("hLambdaOmegaFeeddownMatrix"), v0mcParticle.pt(), v0mcParticleMother.pt()); + if (!v0mcParticle.isPhysicalPrimary()) { + auto v0mothers = v0mcParticle.mothers_as(); // Get mothers + if (!v0mothers.empty()) { + auto& v0mcParticleMother = v0mothers.front(); // First mother + if (v0mcParticleMother.pdgCode() == kXiMinus) // Xi Minus Mother Matched + { + rFeeddownMatrices.fill(HIST("hLambdaXiMinusFeeddownMatrix"), v0mcParticle.pt(), v0mcParticleMother.pt()); + } + if (v0mcParticleMother.pdgCode() == kXi0) // Xi Zero Mother Matched + { + rFeeddownMatrices.fill(HIST("hLambdaXiZeroFeeddownMatrix"), v0mcParticle.pt(), v0mcParticleMother.pt()); + } + if (v0mcParticleMother.pdgCode() == kOmegaMinus) // Omega Mother Matched + { + rFeeddownMatrices.fill(HIST("hLambdaOmegaFeeddownMatrix"), v0mcParticle.pt(), v0mcParticleMother.pt()); + } } } } } } } - } - // antilambda analysis - if (antiLambdaAnalysis == true) { - if (v0mcParticle.pdgCode() == kLambda0Bar) { // antilambda matched - rPtAnalysis.fill(HIST("hMassAntilambdaAll"), v0.mAntiLambda()); - rPtAnalysis.fill(HIST("hantilambdaPtSpectrumBeforeCuts"), v0.pt()); - if (std::abs(v0.mK0Short() - mK0shPDG) > compv0masscut) { // antilambda competitive v0 mass cut (cut out Kaons) - // Implementing best antilambda cuts - if (v0.v0cosPA() > antilambdaSettingcosPA && v0.dcaV0daughters() < antilambdaSettingdcav0dau && v0.v0radius() > antilambdaSettingradius && std::abs(v0.dcapostopv()) > antilambdaSettingdcapostopv && std::abs(v0.dcanegtopv()) > antilambdaSettingdcanegtopv) { - rPtAnalysis.fill(HIST("hMassAntilambdaAllAfterCuts"), v0.mAntiLambda()); - rPtAnalysis.fill(HIST("hAntilambdaReconstructedPtSpectrum"), v0.pt()); - rPtAnalysis.fill(HIST("hAntiLambdaEtaDaughters"), v0.negTrack_as().eta()); - rPtAnalysis.fill(HIST("hAntiLambdaEtaDaughters"), v0.posTrack_as().eta()); - rPtAnalysis.fill(HIST("hAntiLambdaNegDaughterPt"), v0.negTrack_as().pt()); // Neg Daughter Pt - rPtAnalysis.fill(HIST("hAntiLambdaPosDaughterPt"), v0.posTrack_as().pt()); // Pos Daughter Pt - if (v0mcParticle.isPhysicalPrimary()) { - for (int i = 0; i < nmaxHistograms; i++) { - if (antilambdaPtedgevalues[i] <= v0.pt() && v0.pt() < antilambdaPtedgevalues[i + 1]) { - pthistos::antilambdaPt[i]->Fill(v0.mAntiLambda()); + // antilambda analysis + if (antiLambdaAnalysis == true) { + if (v0mcParticle.pdgCode() == kLambda0Bar) { // antilambda matched + rPtAnalysis.fill(HIST("hMassAntilambdaAll"), v0.mAntiLambda()); + rPtAnalysis.fill(HIST("hantilambdaPtSpectrumBeforeCuts"), v0.pt()); + if (std::abs(v0.mK0Short() - mK0shPDG) > compv0masscut) { // antilambda competitive v0 mass cut (cut out Kaons) + // Implementing best antilambda cuts + if (v0.v0cosPA() > antilambdaSettingcosPA && v0.dcaV0daughters() < antilambdaSettingdcav0dau && v0.v0radius() > antilambdaSettingradius && std::abs(v0.dcapostopv()) > antilambdaSettingdcapostopv && std::abs(v0.dcanegtopv()) > antilambdaSettingdcanegtopv) { + rPtAnalysis.fill(HIST("hMassAntilambdaAllAfterCuts"), v0.mAntiLambda()); + rPtAnalysis.fill(HIST("hAntilambdaReconstructedPtSpectrum"), v0.pt()); + rPtAnalysis.fill(HIST("hAntiLambdaEtaDaughters"), v0.negTrack_as().eta()); + rPtAnalysis.fill(HIST("hAntiLambdaEtaDaughters"), v0.posTrack_as().eta()); + rPtAnalysis.fill(HIST("hAntiLambdaNegDaughterPt"), v0.negTrack_as().pt()); // Neg Daughter Pt + rPtAnalysis.fill(HIST("hAntiLambdaPosDaughterPt"), v0.posTrack_as().pt()); // Pos Daughter Pt + if (v0mcParticle.isPhysicalPrimary()) { + for (int i = 0; i < nmaxHistograms; i++) { + if (antilambdaPtedgevalues[i] <= v0.pt() && v0.pt() < antilambdaPtedgevalues[i + 1]) { + pthistos::antilambdaPt[i]->Fill(v0.mAntiLambda()); + } } } - } - if (!v0mcParticle.isPhysicalPrimary()) { - auto v0mothers = v0mcParticle.mothers_as(); // Get mothers - if (!v0mothers.empty()) { - auto& v0mcParticleMother = v0mothers.front(); // First mother - if (v0mcParticleMother.pdgCode() == kXiPlusBar) // Xi Plus Mother Matched - { - rFeeddownMatrices.fill(HIST("hAntiLambdaXiPlusFeeddownMatrix"), v0mcParticle.pt(), v0mcParticleMother.pt()); - } - if (v0mcParticleMother.pdgCode() == -kXi0) // Anti-Xi Zero Mother Matched - { - rFeeddownMatrices.fill(HIST("hAntiLambdaAntiXiZeroFeeddownMatrix"), v0mcParticle.pt(), v0mcParticleMother.pt()); - } - if (v0mcParticleMother.pdgCode() == kOmegaPlusBar) // Anti-Omega (minus) Mother Matched - { - rFeeddownMatrices.fill(HIST("hAntiLambdaAntiOmegaFeeddownMatrix"), v0mcParticle.pt(), v0mcParticleMother.pt()); + if (!v0mcParticle.isPhysicalPrimary()) { + auto v0mothers = v0mcParticle.mothers_as(); // Get mothers + if (!v0mothers.empty()) { + auto& v0mcParticleMother = v0mothers.front(); // First mother + if (v0mcParticleMother.pdgCode() == kXiPlusBar) // Xi Plus Mother Matched + { + rFeeddownMatrices.fill(HIST("hAntiLambdaXiPlusFeeddownMatrix"), v0mcParticle.pt(), v0mcParticleMother.pt()); + } + if (v0mcParticleMother.pdgCode() == -kXi0) // Anti-Xi Zero Mother Matched + { + rFeeddownMatrices.fill(HIST("hAntiLambdaAntiXiZeroFeeddownMatrix"), v0mcParticle.pt(), v0mcParticleMother.pt()); + } + if (v0mcParticleMother.pdgCode() == kOmegaPlusBar) // Anti-Omega (minus) Mother Matched + { + rFeeddownMatrices.fill(HIST("hAntiLambdaAntiOmegaFeeddownMatrix"), v0mcParticle.pt(), v0mcParticleMother.pt()); + } } } } @@ -450,7 +463,7 @@ struct V0PtInvMassPlots { } } // This is the process for Real Data - void dataProcess(soa::Filtered>::iterator const& collision, + void dataProcess(soa::Filtered>::iterator const& collision, aod::V0Datas const& V0s, DaughterTracks const&) { @@ -472,92 +485,94 @@ struct V0PtInvMassPlots { antilambdaPtedgevalues[i] = std::stod(pthistos::antilambdaPtBins[i]); } rPtAnalysis.fill(HIST("hVertexZ"), collision.posZ()); - for (const auto& v0 : V0s) { - const auto& posDaughterTrack = v0.posTrack_as(); - const auto& negDaughterTrack = v0.negTrack_as(); - // Armenteros-Podolandski Plot Values - double pv0 = std::sqrt((v0.px() * v0.px()) + (v0.py() * v0.py()) + (v0.pz() * v0.pz())); - double pposdauparallelv0 = ((v0.posTrack_as().px() * v0.px()) + (v0.posTrack_as().py() * v0.py()) + (v0.posTrack_as().pz() * v0.pz())) / pv0; - double qValue = std::sqrt(((v0.posTrack_as().px() * v0.posTrack_as().px()) + (v0.posTrack_as().py() * v0.posTrack_as().py()) + (v0.posTrack_as().pz() * v0.posTrack_as().pz())) - (pposdauparallelv0 * pposdauparallelv0)); - double plpos = (v0.posTrack_as().px() * v0.px() / pv0) + (v0.posTrack_as().py() * v0.py() / pv0) + (v0.posTrack_as().pz() * v0.pz() / pv0); - double plneg = (v0.negTrack_as().px() * v0.px() / pv0) + (v0.negTrack_as().py() * v0.py() / pv0) + (v0.negTrack_as().pz() * v0.pz() / pv0); - double aValue = (plpos - plneg) / (plpos + plneg); - rPtAnalysis.fill(HIST("hArmenterosPodolanskiPlot"), aValue, qValue); - rPtAnalysis.fill(HIST("hVertexZRec"), collision.posZ()); - if (std::abs(v0.y()) < rapidityCut) { - rPtAnalysis.fill(HIST("V0Rapidity"), v0.y()); - if (std::abs(v0.posTrack_as().eta()) < etadau && std::abs(v0.negTrack_as().eta()) < etadau) { // daughters pseudorapidityCut cut - rPtAnalysis.fill(HIST("hV0EtaDaughters"), v0.negTrack_as().eta()); - rPtAnalysis.fill(HIST("hV0EtaDaughters"), v0.posTrack_as().eta()); - // kzero analysis - if (kzeroAnalysis == true) { - // Filling the five Kzero invariant mass plots for different cuts (which are taken from namespace), for full explanation see the first kzero cut filling in the MC process - rPtAnalysis.fill(HIST("hMassK0ShortAll"), v0.mK0Short()); - if (std::abs(v0.mLambda() - mLambdaPDG) > compv0masscut && std::abs(v0.mAntiLambda() - mLambdaPDG) > compv0masscut) { // antilambda competitive v0 mass cut (cut out Lambdas and Anti-Lambdas) - // Implementing best kzero cuts - if (std::abs(posDaughterTrack.tpcNSigmaPi()) < nSigmaTPCPion && std::abs(negDaughterTrack.tpcNSigmaPi()) < nSigmaTPCPion) { // TPC PID on daughter pions - rPtAnalysis.fill(HIST("hNSigmaPosPiFromK0s"), posDaughterTrack.tpcNSigmaPi(), posDaughterTrack.tpcInnerParam()); - rPtAnalysis.fill(HIST("hNSigmaNegPiFromK0s"), negDaughterTrack.tpcNSigmaPi(), negDaughterTrack.tpcInnerParam()); - if (v0.v0cosPA() > kaonshSettingcosPA && v0.dcaV0daughters() < kaonshSettingdcav0dau && v0.v0radius() > kaonshSettingradius && std::abs(v0.dcapostopv()) > kaonshSettingdcapostopv && std::abs(v0.dcanegtopv()) > kaonshSettingdcanegtopv) { - rPtAnalysis.fill(HIST("hMassK0ShortAllAfterCuts"), v0.mK0Short()); - rPtAnalysis.fill(HIST("hK0shEtaDaughters"), v0.negTrack_as().eta()); - rPtAnalysis.fill(HIST("hK0shEtaDaughters"), v0.posTrack_as().eta()); - rPtAnalysis.fill(HIST("hArmenterosPodolanskiPlotK0Short"), aValue, qValue); - rPtAnalysis.fill(HIST("hK0shNegDaughterPt"), v0.negTrack_as().pt()); // Neg Daughter Pt - rPtAnalysis.fill(HIST("hK0shPosDaughterPt"), v0.posTrack_as().pt()); // Pos Daughter Pt - for (int i = 0; i < nmaxHistograms; i++) { - if (kaonptedgevalues[i] <= v0.pt() && v0.pt() < kaonptedgevalues[i + 1]) { - pthistos::kaonPt[i]->Fill(v0.mK0Short()); + if (collision.isInelGt0()) { + for (const auto& v0 : V0s) { + const auto& posDaughterTrack = v0.posTrack_as(); + const auto& negDaughterTrack = v0.negTrack_as(); + rPtAnalysis.fill(HIST("hVertexZRec"), collision.posZ()); + if (std::abs(v0.y()) < rapidityCut) { + rPtAnalysis.fill(HIST("V0Rapidity"), v0.y()); + if (std::abs(v0.posTrack_as().eta()) < etadau && std::abs(v0.negTrack_as().eta()) < etadau) { // daughters pseudorapidityCut cut + rPtAnalysis.fill(HIST("hV0EtaDaughters"), v0.negTrack_as().eta()); + rPtAnalysis.fill(HIST("hV0EtaDaughters"), v0.posTrack_as().eta()); + // Armenteros-Podolandski Plot Values + double pv0 = std::sqrt((v0.px() * v0.px()) + (v0.py() * v0.py()) + (v0.pz() * v0.pz())); + double pposdauparallelv0 = ((v0.posTrack_as().px() * v0.px()) + (v0.posTrack_as().py() * v0.py()) + (v0.posTrack_as().pz() * v0.pz())) / pv0; + double qValue = std::sqrt(((v0.posTrack_as().px() * v0.posTrack_as().px()) + (v0.posTrack_as().py() * v0.posTrack_as().py()) + (v0.posTrack_as().pz() * v0.posTrack_as().pz())) - (pposdauparallelv0 * pposdauparallelv0)); + double plpos = (v0.posTrack_as().px() * v0.px() / pv0) + (v0.posTrack_as().py() * v0.py() / pv0) + (v0.posTrack_as().pz() * v0.pz() / pv0); + double plneg = (v0.negTrack_as().px() * v0.px() / pv0) + (v0.negTrack_as().py() * v0.py() / pv0) + (v0.negTrack_as().pz() * v0.pz() / pv0); + double aValue = (plpos - plneg) / (plpos + plneg); + rPtAnalysis.fill(HIST("hArmenterosPodolanskiPlot"), aValue, qValue); + // kzero analysis + if (kzeroAnalysis == true) { + // Filling the five Kzero invariant mass plots for different cuts (which are taken from namespace), for full explanation see the first kzero cut filling in the MC process + rPtAnalysis.fill(HIST("hMassK0ShortAll"), v0.mK0Short()); + if (std::abs(v0.mLambda() - mLambdaPDG) > compv0masscut && std::abs(v0.mAntiLambda() - mLambdaPDG) > compv0masscut) { // antilambda competitive v0 mass cut (cut out Lambdas and Anti-Lambdas) + // Implementing best kzero cuts + if (std::abs(posDaughterTrack.tpcNSigmaPi()) < nSigmaTPCPion && std::abs(negDaughterTrack.tpcNSigmaPi()) < nSigmaTPCPion) { // TPC PID on daughter pions + rPtAnalysis.fill(HIST("hNSigmaPosPiFromK0s"), posDaughterTrack.tpcNSigmaPi(), posDaughterTrack.tpcInnerParam()); + rPtAnalysis.fill(HIST("hNSigmaNegPiFromK0s"), negDaughterTrack.tpcNSigmaPi(), negDaughterTrack.tpcInnerParam()); + if (v0.v0cosPA() > kaonshSettingcosPA && v0.dcaV0daughters() < kaonshSettingdcav0dau && v0.v0radius() > kaonshSettingradius && std::abs(v0.dcapostopv()) > kaonshSettingdcapostopv && std::abs(v0.dcanegtopv()) > kaonshSettingdcanegtopv) { + rPtAnalysis.fill(HIST("hMassK0ShortAllAfterCuts"), v0.mK0Short()); + rPtAnalysis.fill(HIST("hK0shEtaDaughters"), v0.negTrack_as().eta()); + rPtAnalysis.fill(HIST("hK0shEtaDaughters"), v0.posTrack_as().eta()); + rPtAnalysis.fill(HIST("hArmenterosPodolanskiPlotK0Short"), aValue, qValue); + rPtAnalysis.fill(HIST("hK0shNegDaughterPt"), v0.negTrack_as().pt()); // Neg Daughter Pt + rPtAnalysis.fill(HIST("hK0shPosDaughterPt"), v0.posTrack_as().pt()); // Pos Daughter Pt + for (int i = 0; i < nmaxHistograms; i++) { + if (kaonptedgevalues[i] <= v0.pt() && v0.pt() < kaonptedgevalues[i + 1]) { + pthistos::kaonPt[i]->Fill(v0.mK0Short()); + } } } } } } - } - // lambda analysis - if (lambdaAnalysis == true) { - // Filling the five lambda invariant mass plots for different cuts (which are taken from namespace), for full explanation see the first kzero cut filling in the MC process - rPtAnalysis.fill(HIST("hMassLambdaAll"), v0.mLambda()); - if (std::abs(v0.mK0Short() - mK0shPDG) > compv0masscut) { // lambda competitive v0 mass cut (cut out Kaons) - if (std::abs(posDaughterTrack.tpcNSigmaPr()) < nSigmaTPCProton && std::abs(negDaughterTrack.tpcNSigmaPi()) < nSigmaTPCPion) { // TPC PID on daughter pion and proton for Lambda - rPtAnalysis.fill(HIST("hNSigmaPosProtonFromLambda"), posDaughterTrack.tpcNSigmaPr(), posDaughterTrack.tpcInnerParam()); - rPtAnalysis.fill(HIST("hNSigmaNegPionFromLambda"), negDaughterTrack.tpcNSigmaPi(), negDaughterTrack.tpcInnerParam()); - // Implementing best lambda cuts - if (v0.v0cosPA() > lambdaSettingcosPA && v0.dcaV0daughters() < lambdaSettingdcav0dau && v0.v0radius() > lambdaSettingradius && std::abs(v0.dcapostopv()) > lambdaSettingdcapostopv && std::abs(v0.dcanegtopv()) > lambdaSettingdcanegtopv) { - rPtAnalysis.fill(HIST("hMassLambdaAllAfterCuts"), v0.mLambda()); - rPtAnalysis.fill(HIST("hLambdaEtaDaughters"), v0.negTrack_as().eta()); - rPtAnalysis.fill(HIST("hLambdaEtaDaughters"), v0.posTrack_as().eta()); - rPtAnalysis.fill(HIST("hArmenterosPodolanskiPlotLambda"), aValue, qValue); - rPtAnalysis.fill(HIST("hLambdaNegDaughterPt"), v0.negTrack_as().pt()); // Neg Daughter Pt - rPtAnalysis.fill(HIST("hLambdaPosDaughterPt"), v0.posTrack_as().pt()); // Pos Daughter Pt - for (int i = 0; i < nmaxHistograms; i++) { - if (lambdaptedgevalues[i] <= v0.pt() && v0.pt() < lambdaptedgevalues[i + 1]) { - pthistos::lambdaPt[i]->Fill(v0.mLambda()); + // lambda analysis + if (lambdaAnalysis == true) { + // Filling the five lambda invariant mass plots for different cuts (which are taken from namespace), for full explanation see the first kzero cut filling in the MC process + rPtAnalysis.fill(HIST("hMassLambdaAll"), v0.mLambda()); + if (std::abs(v0.mK0Short() - mK0shPDG) > compv0masscut) { // lambda competitive v0 mass cut (cut out Kaons) + if (std::abs(posDaughterTrack.tpcNSigmaPr()) < nSigmaTPCProton && std::abs(negDaughterTrack.tpcNSigmaPi()) < nSigmaTPCPion) { // TPC PID on daughter pion and proton for Lambda + rPtAnalysis.fill(HIST("hNSigmaPosProtonFromLambda"), posDaughterTrack.tpcNSigmaPr(), posDaughterTrack.tpcInnerParam()); + rPtAnalysis.fill(HIST("hNSigmaNegPionFromLambda"), negDaughterTrack.tpcNSigmaPi(), negDaughterTrack.tpcInnerParam()); + // Implementing best lambda cuts + if (v0.v0cosPA() > lambdaSettingcosPA && v0.dcaV0daughters() < lambdaSettingdcav0dau && v0.v0radius() > lambdaSettingradius && std::abs(v0.dcapostopv()) > lambdaSettingdcapostopv && std::abs(v0.dcanegtopv()) > lambdaSettingdcanegtopv) { + rPtAnalysis.fill(HIST("hMassLambdaAllAfterCuts"), v0.mLambda()); + rPtAnalysis.fill(HIST("hLambdaEtaDaughters"), v0.negTrack_as().eta()); + rPtAnalysis.fill(HIST("hLambdaEtaDaughters"), v0.posTrack_as().eta()); + rPtAnalysis.fill(HIST("hArmenterosPodolanskiPlotLambda"), aValue, qValue); + rPtAnalysis.fill(HIST("hLambdaNegDaughterPt"), v0.negTrack_as().pt()); // Neg Daughter Pt + rPtAnalysis.fill(HIST("hLambdaPosDaughterPt"), v0.posTrack_as().pt()); // Pos Daughter Pt + for (int i = 0; i < nmaxHistograms; i++) { + if (lambdaptedgevalues[i] <= v0.pt() && v0.pt() < lambdaptedgevalues[i + 1]) { + pthistos::lambdaPt[i]->Fill(v0.mLambda()); + } } } } } } - } - // anti-lambda analysis - if (antiLambdaAnalysis == true) { - // Filling the five Antilambda invariant mass plots for different cuts (which are taken from namespace), for full explanation see the first kzero cut filling in the MC process - rPtAnalysis.fill(HIST("hMassAntilambdaAll"), v0.mAntiLambda()); - if (std::abs(v0.mK0Short() - mK0shPDG) > compv0masscut) { // antilambda competitive v0 mass cut (cut out Kaons) - if (std::abs(negDaughterTrack.tpcNSigmaPr()) < nSigmaTPCProton && std::abs(posDaughterTrack.tpcNSigmaPi()) < nSigmaTPCPion) { // TPC PID on daughter pion and proton for AntiLambda - rPtAnalysis.fill(HIST("hNSigmaPosPionFromAntilambda"), posDaughterTrack.tpcNSigmaPi(), posDaughterTrack.tpcInnerParam()); - rPtAnalysis.fill(HIST("hNSigmaNegProtonFromAntilambda"), negDaughterTrack.tpcNSigmaPr(), negDaughterTrack.tpcInnerParam()); - // implementing best antilambda cuts - if (v0.v0cosPA() > antilambdaSettingcosPA && v0.dcaV0daughters() < antilambdaSettingdcav0dau && v0.v0radius() > antilambdaSettingradius && std::abs(v0.dcapostopv()) > antilambdaSettingdcapostopv && std::abs(v0.dcanegtopv()) > antilambdaSettingdcanegtopv) { - rPtAnalysis.fill(HIST("hMassAntilambdaAllAfterCuts"), v0.mAntiLambda()); - rPtAnalysis.fill(HIST("hAntiLambdaEtaDaughters"), v0.negTrack_as().eta()); - rPtAnalysis.fill(HIST("hAntiLambdaEtaDaughters"), v0.posTrack_as().eta()); - rPtAnalysis.fill(HIST("hArmenterosPodolanskiPlotAntiLambda"), aValue, qValue); - rPtAnalysis.fill(HIST("hAntiLambdaNegDaughterPt"), v0.negTrack_as().pt()); // Neg Daughter Pt - rPtAnalysis.fill(HIST("hAntiLambdaPosDaughterPt"), v0.posTrack_as().pt()); // Pos Daughter Pt - for (int i = 0; i < nmaxHistograms; i++) { - if (lambdaptedgevalues[i] <= v0.pt() && v0.pt() < lambdaptedgevalues[i + 1]) { - pthistos::antilambdaPt[i]->Fill(v0.mAntiLambda()); + // anti-lambda analysis + if (antiLambdaAnalysis == true) { + // Filling the five Antilambda invariant mass plots for different cuts (which are taken from namespace), for full explanation see the first kzero cut filling in the MC process + rPtAnalysis.fill(HIST("hMassAntilambdaAll"), v0.mAntiLambda()); + if (std::abs(v0.mK0Short() - mK0shPDG) > compv0masscut) { // antilambda competitive v0 mass cut (cut out Kaons) + if (std::abs(negDaughterTrack.tpcNSigmaPr()) < nSigmaTPCProton && std::abs(posDaughterTrack.tpcNSigmaPi()) < nSigmaTPCPion) { // TPC PID on daughter pion and proton for AntiLambda + rPtAnalysis.fill(HIST("hNSigmaPosPionFromAntilambda"), posDaughterTrack.tpcNSigmaPi(), posDaughterTrack.tpcInnerParam()); + rPtAnalysis.fill(HIST("hNSigmaNegProtonFromAntilambda"), negDaughterTrack.tpcNSigmaPr(), negDaughterTrack.tpcInnerParam()); + // implementing best antilambda cuts + if (v0.v0cosPA() > antilambdaSettingcosPA && v0.dcaV0daughters() < antilambdaSettingdcav0dau && v0.v0radius() > antilambdaSettingradius && std::abs(v0.dcapostopv()) > antilambdaSettingdcapostopv && std::abs(v0.dcanegtopv()) > antilambdaSettingdcanegtopv) { + rPtAnalysis.fill(HIST("hMassAntilambdaAllAfterCuts"), v0.mAntiLambda()); + rPtAnalysis.fill(HIST("hAntiLambdaEtaDaughters"), v0.negTrack_as().eta()); + rPtAnalysis.fill(HIST("hAntiLambdaEtaDaughters"), v0.posTrack_as().eta()); + rPtAnalysis.fill(HIST("hArmenterosPodolanskiPlotAntiLambda"), aValue, qValue); + rPtAnalysis.fill(HIST("hAntiLambdaNegDaughterPt"), v0.negTrack_as().pt()); // Neg Daughter Pt + rPtAnalysis.fill(HIST("hAntiLambdaPosDaughterPt"), v0.posTrack_as().pt()); // Pos Daughter Pt + for (int i = 0; i < nmaxHistograms; i++) { + if (lambdaptedgevalues[i] <= v0.pt() && v0.pt() < lambdaptedgevalues[i + 1]) { + pthistos::antilambdaPt[i]->Fill(v0.mAntiLambda()); + } } } } From 5ac6f90310a1bbaa1d86ccd462d35e57b68e4b89 Mon Sep 17 00:00:00 2001 From: Jan Fiete Date: Mon, 16 Jun 2025 12:55:15 +0200 Subject: [PATCH 088/871] improve resetting of axes (#11630) --- PWGCF/Core/CorrelationContainer.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PWGCF/Core/CorrelationContainer.cxx b/PWGCF/Core/CorrelationContainer.cxx index a910cf2d1b9..4a68f667350 100644 --- a/PWGCF/Core/CorrelationContainer.cxx +++ b/PWGCF/Core/CorrelationContainer.cxx @@ -309,7 +309,7 @@ void CorrelationContainer::resetBinLimits(THnBase* grid, int max_dimension) for (Int_t i = 0; i < max_dimension; i++) { if (grid->GetAxis(i)->TestBit(TAxis::kAxisRange)) { - grid->GetAxis(i)->SetRangeUser(0, -1); + grid->GetAxis(i)->SetRange(0, 0); // reset range } } } From e40d905f9c4661ef3fb45eab551e3b2ba4d2600f Mon Sep 17 00:00:00 2001 From: Fabrizio Chinu <91954233+fchinu@users.noreply.github.com> Date: Mon, 16 Jun 2025 13:50:49 +0200 Subject: [PATCH 089/871] [PWGHF] Fix unbound indices for B -> JPsi data creator (#11631) --- PWGHF/D2H/DataModel/ReducedDataModel.h | 2 +- PWGHF/D2H/TableProducer/candidateCreatorBToJpsiReduced.cxx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/PWGHF/D2H/DataModel/ReducedDataModel.h b/PWGHF/D2H/DataModel/ReducedDataModel.h index 939f0648099..c385d42f03c 100644 --- a/PWGHF/D2H/DataModel/ReducedDataModel.h +++ b/PWGHF/D2H/DataModel/ReducedDataModel.h @@ -871,7 +871,7 @@ DECLARE_SOA_TABLE(HfMcRecRedD0Pis, "AOD", "HFMCRECREDD0PI", //! Table with recon // table with results of reconstruction level MC matching DECLARE_SOA_TABLE(HfMcRecRedJPKs, "AOD", "HFMCRECREDJPK", //! Table with reconstructed MC information on J/PsiK(<-B+) pairs for reduced workflow hf_cand_bplus_reduced::JpsiId, - hf_cand_bplus_reduced::Prong1Id, + hf_cand_bplus_reduced::BachKaId, hf_cand_bplus::FlagMcMatchRec, hf_cand_bplus::ChannelMcMatchRec, hf_cand_bplus::FlagWrongCollision, diff --git a/PWGHF/D2H/TableProducer/candidateCreatorBToJpsiReduced.cxx b/PWGHF/D2H/TableProducer/candidateCreatorBToJpsiReduced.cxx index 9fc5d845a04..960b05ce667 100644 --- a/PWGHF/D2H/TableProducer/candidateCreatorBToJpsiReduced.cxx +++ b/PWGHF/D2H/TableProducer/candidateCreatorBToJpsiReduced.cxx @@ -436,7 +436,7 @@ struct HfCandidateCreatorBToJpsiReducedExpressions { bool filledMcInfo{false}; if constexpr (decChannel == DecayChannel::BplusToJpsiK) { for (const auto& rowJpsiHadMcRec : rowsJpsiHadMcRec) { - if ((rowJpsiHadMcRec.jpsiId() != candB.jpsiId()) || (rowJpsiHadMcRec.prong1Id() != candB.bachKaId())) { + if ((rowJpsiHadMcRec.jpsiId() != candB.jpsiId()) || (rowJpsiHadMcRec.bachKaId() != candB.bachKaId())) { continue; } rowBplusMcRec(rowJpsiHadMcRec.flagMcMatchRec(), rowJpsiHadMcRec.channelMcMatchRec(), rowJpsiHadMcRec.flagWrongCollision(), rowJpsiHadMcRec.debugMcRec(), rowJpsiHadMcRec.ptMother()); From 677f95ee016535c68fd9d10530e1706459aaf072 Mon Sep 17 00:00:00 2001 From: Zhenjun Xiong <108917659+zjxiongOvO@users.noreply.github.com> Date: Mon, 16 Jun 2025 14:48:11 +0200 Subject: [PATCH 090/871] [PWGDQ] Update on Dilepton-track-track (#11525) --- PWGDQ/Core/HistogramsLibrary.cxx | 32 ++- PWGDQ/Core/VarManager.cxx | 1 + PWGDQ/Core/VarManager.h | 287 ++++++++++++++++++- PWGDQ/DataModel/ReducedInfoTables.h | 390 +++++++++++++++----------- PWGDQ/Tasks/dqEfficiency.cxx | 56 ++-- PWGDQ/Tasks/tableReader.cxx | 55 +++- PWGDQ/Tasks/tableReader_withAssoc.cxx | 262 ++++++++++++++++- git | 0 8 files changed, 890 insertions(+), 193 deletions(-) create mode 100644 git diff --git a/PWGDQ/Core/HistogramsLibrary.cxx b/PWGDQ/Core/HistogramsLibrary.cxx index 7b975b1c2be..a375775f796 100644 --- a/PWGDQ/Core/HistogramsLibrary.cxx +++ b/PWGDQ/Core/HistogramsLibrary.cxx @@ -1866,7 +1866,7 @@ void o2::aod::dqhistograms::DefineHistograms(HistogramManager* hm, const char* h } } if (!groupStr.CompareTo("dilepton-dihadron")) { - if (subGroupStr.EqualTo("xtojpsipipi")) { + if (subGroupStr.Contains("xtojpsipipi") || subGroupStr.Contains("psi2stojpsipipi")) { hm->AddHistogram(histClass, "hMass_X3872", "", false, 1000, 3.0, 5.0, VarManager::kQuadMass); hm->AddHistogram(histClass, "hMass_defaultDileptonMass_X3872", "", false, 1000, 3.0, 5.0, VarManager::kQuadDefaultDileptonMass); hm->AddHistogram(histClass, "hPt_X3872", "", false, 150, 0.0, 15.0, VarManager::kQuadPt); @@ -1875,12 +1875,12 @@ void o2::aod::dqhistograms::DefineHistograms(HistogramManager* hm, const char* h hm->AddHistogram(histClass, "hCostheta_Jpsi_Dihadron", "", false, 100, -1.0, 1.0, VarManager::kCosthetaDileptonDitrack); hm->AddHistogram(histClass, "hPtDilepton_PtDihadron", "", false, 150, 0, 15.0, VarManager::kPairPt, 100, 0, 10, VarManager::kDitrackPt); hm->AddHistogram(histClass, "hPtDilepton_MassDihadron", "", false, 150, 0, 15.0, VarManager::kPairPt, 150, 0.0, 3.0, VarManager::kDitrackMass); - hm->AddHistogram(histClass, "hQ_X3872", "", false, 150, 0.0, 3.0, VarManager::kQ); + hm->AddHistogram(histClass, "hQ_X3872", "", false, 300, -3.0, 3.0, VarManager::kQ); hm->AddHistogram(histClass, "hDeltaR1_X3872", "", false, 100, 0.0, 10.0, VarManager::kDeltaR1); hm->AddHistogram(histClass, "hDeltaR2_X3872", "", false, 100, 0.0, 10.0, VarManager::kDeltaR2); hm->AddHistogram(histClass, "hDeltaR_X3872", "", false, 100, 0.0, 10.0, VarManager::kDeltaR); - hm->AddHistogram(histClass, "hMass_Q_X3872", "", false, 100, 3.0, 5.0, VarManager::kQuadMass, 150, 0.0, 3.0, VarManager::kQ); - hm->AddHistogram(histClass, "hMass_defaultDileptonMass_Q_X3872", "", false, 100, 3.0, 5.0, VarManager::kQuadDefaultDileptonMass, 150, 0.0, 3.0, VarManager::kQ); + hm->AddHistogram(histClass, "hMass_Q_X3872", "", false, 100, 3.0, 5.0, VarManager::kQuadMass, 300, -3.0, 3.0, VarManager::kQ); + hm->AddHistogram(histClass, "hMass_defaultDileptonMass_Q_X3872", "", false, 100, 3.0, 5.0, VarManager::kQuadDefaultDileptonMass, 300, -3.0, 3.0, VarManager::kQ); hm->AddHistogram(histClass, "hMass_DeltaR1_X3872", "", false, 100, 3.0, 5.0, VarManager::kQuadMass, 100, 0.0, 10.0, VarManager::kDeltaR1); hm->AddHistogram(histClass, "hMass_defaultDileptonMass_DeltaR1_X3872", "", false, 100, 3.0, 5.0, VarManager::kQuadDefaultDileptonMass, 100, 0.0, 10.0, VarManager::kDeltaR1); hm->AddHistogram(histClass, "hMass_DeltaR2_X3872", "", false, 100, 3.0, 5.0, VarManager::kQuadMass, 100, 0.0, 10.0, VarManager::kDeltaR2); @@ -1900,6 +1900,30 @@ void o2::aod::dqhistograms::DefineHistograms(HistogramManager* hm, const char* h hm->AddHistogram(histClass, "hMass_defaultDileptonMass_PtTrack1", "", false, 100, 3.0, 5.0, VarManager::kQuadDefaultDileptonMass, 100, 0.0, 10.0, VarManager::kPt); hm->AddHistogram(histClass, "hMass_PtTrack1", "", false, 100, 3.0, 5.0, VarManager::kQuadMass, 100, 0.0, 10.0, VarManager::kPt); } + if (subGroupStr.Contains("vertexing")) { + hm->AddHistogram(histClass, "UsedKF", "", false, 2, -0.5, 1.5, VarManager::kUsedKF); + hm->AddHistogram(histClass, "KFMass", "", false, 750, 0.0, 30.0, VarManager::kKFMass); + hm->AddHistogram(histClass, "Lz", "", false, 1000, -0.2, 0.2, VarManager::kVertexingLz); + hm->AddHistogram(histClass, "Lxy", "", false, 1000, -0.2, 0.2, VarManager::kVertexingLxy); + hm->AddHistogram(histClass, "Lxyz", "", false, 1000, -0.2, 0.2, VarManager::kVertexingLxyz); + hm->AddHistogram(histClass, "Tauz", "", false, 4000, -0.01, 0.01, VarManager::kVertexingTauz); + hm->AddHistogram(histClass, "Tauxy", "", false, 4000, -0.01, 0.01, VarManager::kVertexingTauxy); + hm->AddHistogram(histClass, "LxyzErr", "", false, 100, 0.0, 0.2, VarManager::kVertexingLxyzErr); + hm->AddHistogram(histClass, "LzErr", "", false, 100, 0.0, 0.2, VarManager::kVertexingLzErr); + hm->AddHistogram(histClass, "TauzErr", "", false, 100, 0.0, 0.2, VarManager::kVertexingTauzErr); + hm->AddHistogram(histClass, "VtxingProcCode", "", false, 10, 0.0, 10.0, VarManager::kVertexingProcCode); + hm->AddHistogram(histClass, "VtxingChi2PCA", "", false, 100, 0.0, 10.0, VarManager::kVertexingChi2PCA); + hm->AddHistogram(histClass, "LzProj", "", false, 1000, -0.2, 0.2, VarManager::kVertexingLzProjected); + hm->AddHistogram(histClass, "LxyProj", "", false, 1000, -0.2, 0.2, VarManager::kVertexingLxyProjected); + hm->AddHistogram(histClass, "LxyzProj", "", false, 1000, -0.2, 0.2, VarManager::kVertexingLxyzProjected); + hm->AddHistogram(histClass, "TauzProj", "", false, 4000, -0.5, 0.5, VarManager::kVertexingTauzProjected); + hm->AddHistogram(histClass, "TauxyProj", "", false, 4000, -0.5, 0.5, VarManager::kVertexingTauxyProjected); + hm->AddHistogram(histClass, "CosPointingAngle", "", false, 100, 0.0, 1.0, VarManager::kCosPointingAngle); + hm->AddHistogram(histClass, "DCAxyzBetweenProngs", "", false, 100, 0.0, 1.0, VarManager::kKFDCAxyzBetweenProngs); + hm->AddHistogram(histClass, "KFChi2OverNDFGeo", "", false, 150, -5, 10, VarManager::kKFChi2OverNDFGeo); + hm->AddHistogram(histClass, "hMass_Chi2OverNDFGeo", "", false, 1000, 3.0, 5.0, VarManager::kQuadMass, 150, -5, 10., VarManager::kKFChi2OverNDFGeo); + hm->AddHistogram(histClass, "hMass_defaultDileptonMass_Chi2OverNDFGeo", "", false, 1000, 3.0, 5.0, VarManager::kQuadDefaultDileptonMass, 150, -5, 10., VarManager::kKFChi2OverNDFGeo); + } } if (!groupStr.CompareTo("dilepton-photon-mass")) { hm->AddHistogram(histClass, "Mass_Dilepton", "", false, 500, 0.0, 5.0, VarManager::kPairMassDau); diff --git a/PWGDQ/Core/VarManager.cxx b/PWGDQ/Core/VarManager.cxx index 503101d303f..456f4e763dc 100644 --- a/PWGDQ/Core/VarManager.cxx +++ b/PWGDQ/Core/VarManager.cxx @@ -39,6 +39,7 @@ uint64_t VarManager::fgSOR = 0; uint64_t VarManager::fgEOR = 0; o2::vertexing::DCAFitterN<2> VarManager::fgFitterTwoProngBarrel; o2::vertexing::DCAFitterN<3> VarManager::fgFitterThreeProngBarrel; +o2::vertexing::DCAFitterN<4> VarManager::fgFitterFourProngBarrel; o2::vertexing::FwdDCAFitterN<2> VarManager::fgFitterTwoProngFwd; o2::vertexing::FwdDCAFitterN<3> VarManager::fgFitterThreeProngFwd; o2::globaltracking::MatchGlobalFwd VarManager::mMatching; diff --git a/PWGDQ/Core/VarManager.h b/PWGDQ/Core/VarManager.h index 31c1f69a275..da084fdfb89 100644 --- a/PWGDQ/Core/VarManager.h +++ b/PWGDQ/Core/VarManager.h @@ -146,6 +146,7 @@ class VarManager : public TObject kBtoJpsiEEK, // e.g. B+ -> e+ e- K+ kJpsiEEProton, // e.g. Jpsi-proton correlation, Jpsi to e+e- kXtoJpsiPiPi, // e.g. X(3872) -> J/psi pi+ pi- + kPsi2StoJpsiPiPi, // e.g. Psi(2S) -> J/psi pi+ pi- kChictoJpsiEE, // e.g. Chi_c1 -> J/psi e+ e- kDstarToD0KPiPi, // e.g. D*+ -> D0 pi+ -> K- pi+ pi+ kTripleCandidateToEEPhoton, // e.g. chi_c -> e+ e- photon or pi0 -> e+ e- photon @@ -998,6 +999,25 @@ class VarManager : public TObject fgUsedKF = false; } + // Setup the 4 prong KFParticle + static void SetupFourProngKFParticle(float magField) + { + KFParticle::SetField(magField); + fgUsedKF = true; + } + + // Setup the 4 prong DCAFitterN + static void SetupFourProngDCAFitter(float magField, bool propagateToPCA, float maxR, float /*maxDZIni*/, float minParamChange, float minRelChi2Change, bool useAbsDCA) + { + fgFitterFourProngBarrel.setBz(magField); + fgFitterFourProngBarrel.setPropagateToPCA(propagateToPCA); + fgFitterFourProngBarrel.setMaxR(maxR); + fgFitterFourProngBarrel.setMinParamChange(minParamChange); + fgFitterFourProngBarrel.setMinRelChi2Change(minRelChi2Change); + fgFitterFourProngBarrel.setUseAbsDCA(useAbsDCA); + fgUsedKF = false; + } + static auto getEventPlane(int harm, float qnxa, float qnya) { // Compute event plane angle from qn vector components for the sub-event A @@ -1068,7 +1088,7 @@ class VarManager : public TObject template static void FillTripleMC(T1 const& t1, T2 const& t2, T3 const& t3, float* values = nullptr, PairCandidateType pairType = kTripleCandidateToEEPhoton); template - static void FillQaudMC(T1 const& t1, T2 const& t2, T2 const& t3, float* values = nullptr); + static void FillQuadMC(T1 const& t1, T2 const& t2, T2 const& t3, float* values = nullptr); template static void FillPairVertexing(C const& collision, T const& t1, T const& t2, bool propToSV = false, float* values = nullptr); template @@ -1097,6 +1117,8 @@ class VarManager : public TObject static void FillPairVn(T1 const& t1, T2 const& t2, float* values = nullptr); template static void FillDileptonTrackTrack(T1 const& dilepton, T2 const& hadron1, T3 const& hadron2, float* values = nullptr); + template + static void FillDileptonTrackTrackVertexing(C const& collision, T1 const& lepton1, T1 const& lepton2, T1 const& track1, T1 const& track2, float* values); template static void FillZDC(const T& zdc, float* values = nullptr); @@ -1187,6 +1209,7 @@ class VarManager : public TObject static o2::vertexing::DCAFitterN<2> fgFitterTwoProngBarrel; static o2::vertexing::DCAFitterN<3> fgFitterThreeProngBarrel; + static o2::vertexing::DCAFitterN<4> fgFitterFourProngBarrel; static o2::vertexing::FwdDCAFitterN<2> fgFitterTwoProngFwd; static o2::vertexing::FwdDCAFitterN<3> fgFitterThreeProngFwd; static o2::globaltracking::MatchGlobalFwd mMatching; @@ -5080,9 +5103,269 @@ void VarManager::FillDileptonTrackTrack(T1 const& dilepton, T2 const& hadron1, T } } +//__________________________________________________________________ +template +void VarManager::FillDileptonTrackTrackVertexing(C const& collision, T1 const& lepton1, T1 const& lepton2, T1 const& track1, T1 const& track2, float* values) +{ + constexpr bool eventHasVtxCov = ((collFillMap & Collision) > 0 || (collFillMap & ReducedEventVtxCov) > 0); + constexpr bool trackHasCov = ((fillMap & TrackCov) > 0 || (fillMap & ReducedTrackBarrelCov) > 0); + + if (!eventHasVtxCov || !trackHasCov) { + return; + } + + if (!values) { + values = fgValues; + } + + float mtrack1, mtrack2; + float mlepton1, mlepton2; + + if constexpr (candidateType == kXtoJpsiPiPi || candidateType == kPsi2StoJpsiPiPi) { + mlepton1 = o2::constants::physics::MassElectron; + mlepton2 = o2::constants::physics::MassElectron; + mtrack1 = o2::constants::physics::MassPionCharged; + mtrack2 = o2::constants::physics::MassPionCharged; + } + + ROOT::Math::PtEtaPhiMVector v1(lepton1.pt(), lepton1.eta(), lepton1.phi(), mlepton1); + ROOT::Math::PtEtaPhiMVector v2(lepton2.pt(), lepton2.eta(), lepton2.phi(), mlepton2); + ROOT::Math::PtEtaPhiMVector v3(track1.pt(), track1.eta(), track1.phi(), mtrack1); + ROOT::Math::PtEtaPhiMVector v4(track2.pt(), track2.eta(), track2.phi(), mtrack2); + ROOT::Math::PtEtaPhiMVector v1234 = v1 + v2 + v3 + v4; + + int procCodeDilepton = 0; + int procCodeDileptonTrackTrack = 0; + + values[kUsedKF] = fgUsedKF; + if (!fgUsedKF) { + // create covariance matrix + std::array lepton1pars = {lepton1.y(), lepton1.z(), lepton1.snp(), lepton1.tgl(), lepton1.signed1Pt()}; + std::array lepton1covs = {lepton1.cYY(), lepton1.cZY(), lepton1.cZZ(), lepton1.cSnpY(), lepton1.cSnpZ(), + lepton1.cSnpSnp(), lepton1.cTglY(), lepton1.cTglZ(), lepton1.cTglSnp(), lepton1.cTglTgl(), + lepton1.c1PtY(), lepton1.c1PtZ(), lepton1.c1PtSnp(), lepton1.c1PtTgl(), lepton1.c1Pt21Pt2()}; + o2::track::TrackParCov pars1{lepton1.x(), lepton1.alpha(), lepton1pars, lepton1covs}; + std::array lepton2pars = {lepton2.y(), lepton2.z(), lepton2.snp(), lepton2.tgl(), lepton2.signed1Pt()}; + std::array lepton2covs = {lepton2.cYY(), lepton2.cZY(), lepton2.cZZ(), lepton2.cSnpY(), lepton2.cSnpZ(), + lepton2.cSnpSnp(), lepton2.cTglY(), lepton2.cTglZ(), lepton2.cTglSnp(), lepton2.cTglTgl(), + lepton2.c1PtY(), lepton2.c1PtZ(), lepton2.c1PtSnp(), lepton2.c1PtTgl(), lepton2.c1Pt21Pt2()}; + o2::track::TrackParCov pars2{lepton2.x(), lepton2.alpha(), lepton2pars, lepton2covs}; + std::array track1pars = {track1.y(), track1.z(), track1.snp(), track1.tgl(), track1.signed1Pt()}; + std::array track1covs = {track1.cYY(), track1.cZY(), track1.cZZ(), track1.cSnpY(), track1.cSnpZ(), + track1.cSnpSnp(), track1.cTglY(), track1.cTglZ(), track1.cTglSnp(), track1.cTglTgl(), + track1.c1PtY(), track1.c1PtZ(), track1.c1PtSnp(), track1.c1PtTgl(), track1.c1Pt21Pt2()}; + o2::track::TrackParCov pars3{track1.x(), track1.alpha(), track1pars, track1covs}; + std::array track2pars = {track2.y(), track2.z(), track2.snp(), track2.tgl(), track2.signed1Pt()}; + std::array track2covs = {track2.cYY(), track2.cZY(), track2.cZZ(), track2.cSnpY(), track2.cSnpZ(), + track2.cSnpSnp(), track2.cTglY(), track2.cTglZ(), track2.cTglSnp(), track2.cTglTgl(), + track2.c1PtY(), track2.c1PtZ(), track2.c1PtSnp(), track2.c1PtTgl(), track2.c1Pt21Pt2()}; + o2::track::TrackParCov pars4{track2.x(), track2.alpha(), track2pars, track2covs}; + + procCodeDilepton = VarManager::fgFitterTwoProngBarrel.process(pars1, pars2); + // create dilepton track + // o2::track::TrackParCov parsDilepton = VarManager::fgFitterTwoProngBarrel.createParentTrackParCov(0); + // procCodeDileptonTrackTrack = VarManager::fgFitterThreeProngBarrel.process(parsDilepton, pars3, pars4); + procCodeDileptonTrackTrack = VarManager::fgFitterFourProngBarrel.process(pars1, pars2, pars3, pars4); + + // fill values + if (procCodeDilepton == 0 && procCodeDileptonTrackTrack == 0) { + // TODO: set the other variables to appropriate values and return + values[kVertexingLxy] = -999.; + values[kVertexingLxyz] = -999.; + values[kVertexingLz] = -999.; + values[kVertexingLxyErr] = -999.; + values[kVertexingLxyzErr] = -999.; + values[kVertexingLzErr] = -999.; + values[kVertexingTauxy] = -999.; + values[kVertexingTauxyErr] = -999.; + values[kVertexingTauz] = -999.; + values[kVertexingTauzErr] = -999.; + values[kVertexingLzProjected] = -999.; + values[kVertexingLxyProjected] = -999.; + values[kVertexingLxyzProjected] = -999.; + values[kVertexingTauzProjected] = -999.; + values[kVertexingTauxyProjected] = -999.; + values[kVertexingTauxyzProjected] = -999.; + return; + } else { + Vec3D secondaryVertex; + std::array covMatrixPCA; + secondaryVertex = fgFitterFourProngBarrel.getPCACandidate(); + covMatrixPCA = fgFitterFourProngBarrel.calcPCACovMatrixFlat(); + + o2::math_utils::Point3D vtxXYZ(collision.posX(), collision.posY(), collision.posZ()); + std::array vtxCov{collision.covXX(), collision.covXY(), collision.covYY(), collision.covXZ(), collision.covYZ(), collision.covZZ()}; + o2::dataformats::VertexBase primaryVertex = {std::move(vtxXYZ), std::move(vtxCov)}; + auto covMatrixPV = primaryVertex.getCov(); + + double phi = std::atan2(secondaryVertex[1] - collision.posY(), secondaryVertex[0] - collision.posX()); + double theta = std::atan2(secondaryVertex[2] - collision.posZ(), + std::sqrt((secondaryVertex[0] - collision.posX()) * (secondaryVertex[0] - collision.posX()) + + (secondaryVertex[1] - collision.posY()) * (secondaryVertex[1] - collision.posY()))); + + values[kVertexingLxy] = (collision.posX() - secondaryVertex[0]) * (collision.posX() - secondaryVertex[0]) + + (collision.posY() - secondaryVertex[1]) * (collision.posY() - secondaryVertex[1]); + values[kVertexingLz] = (collision.posZ() - secondaryVertex[2]) * (collision.posZ() - secondaryVertex[2]); + values[kVertexingLxyz] = values[kVertexingLxy] + values[kVertexingLz]; + values[kVertexingLxy] = std::sqrt(values[kVertexingLxy]); + values[kVertexingLz] = std::sqrt(values[kVertexingLz]); + values[kVertexingLxyz] = std::sqrt(values[kVertexingLxyz]); + + values[kVertexingLxyzErr] = std::sqrt(getRotatedCovMatrixXX(covMatrixPV, phi, theta) + getRotatedCovMatrixXX(covMatrixPCA, phi, theta)); + values[kVertexingLxyErr] = std::sqrt(getRotatedCovMatrixXX(covMatrixPV, phi, 0.) + getRotatedCovMatrixXX(covMatrixPCA, phi, 0.)); + values[kVertexingLzErr] = std::sqrt(getRotatedCovMatrixXX(covMatrixPV, 0, theta) + getRotatedCovMatrixXX(covMatrixPCA, 0, theta)); + + values[kVertexingTauz] = (collision.posZ() - secondaryVertex[2]) * v1234.M() / (TMath::Abs(v1234.Pz()) * o2::constants::physics::LightSpeedCm2NS); + values[kVertexingTauxy] = values[kVertexingLxy] * v1234.M() / (v1234.Pt() * o2::constants::physics::LightSpeedCm2NS); + + 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()) / + (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(); + values[kVertexingLzProjected] = values[kVertexingLzProjected] / TMath::Sqrt(v1234.Pz() * v1234.Pz()); + values[kVertexingLxyProjected] = ((secondaryVertex[0] - collision.posX()) * v1234.Px()) + ((secondaryVertex[1] - collision.posY()) * v1234.Py()); + values[kVertexingLxyProjected] = values[kVertexingLxyProjected] / TMath::Sqrt((v1234.Px() * v1234.Px()) + (v1234.Py() * v1234.Py())); + values[kVertexingLxyzProjected] = ((secondaryVertex[0] - collision.posX()) * v1234.Px()) + ((secondaryVertex[1] - collision.posY()) * v1234.Py()) + ((secondaryVertex[2] - collision.posZ()) * v1234.Pz()); + values[kVertexingLxyzProjected] = values[kVertexingLxyzProjected] / TMath::Sqrt((v1234.Px() * v1234.Px()) + (v1234.Py() * v1234.Py()) + (v1234.Pz() * v1234.Pz())); + + values[kVertexingTauzProjected] = values[kVertexingLzProjected] * v1234.M() / TMath::Abs(v1234.Pz()); + values[kVertexingTauxyProjected] = values[kVertexingLxyProjected] * v1234.M() / (v1234.Pt()); + values[kVertexingTauxyzProjected] = values[kVertexingLxyzProjected] * v1234.M() / (v1234.P()); + } + } else if (fgUsedKF) { + KFParticle lepton1KF; // lepton1 + KFParticle lepton2KF; // lepton2 + KFParticle KFGeoTwoLeptons; + KFParticle trk1KF; // track1 + KFParticle trk2KF; // track2 + KFParticle KFGeoTwoTracks; + KFParticle KFGeoFourProng; + if constexpr (candidateType == kXtoJpsiPiPi) { + KFPTrack kfpTrack0 = createKFPTrackFromTrack(lepton1); + lepton1KF = KFParticle(kfpTrack0, -11 * lepton1.sign()); + KFPTrack kfpTrack1 = createKFPTrackFromTrack(lepton2); + lepton2KF = KFParticle(kfpTrack1, -11 * lepton2.sign()); + KFPTrack kfpTrack2 = createKFPTrackFromTrack(track1); + trk1KF = KFParticle(kfpTrack2, 211 * track1.sign()); + KFPTrack kfpTrack3 = createKFPTrackFromTrack(track2); + trk2KF = KFParticle(kfpTrack3, 211 * track2.sign()); + + KFGeoTwoLeptons.SetConstructMethod(2); + KFGeoTwoLeptons.AddDaughter(lepton1KF); + KFGeoTwoLeptons.AddDaughter(lepton2KF); + + if (fgUsedVars[kPairMass] || fgUsedVars[kPairPt]) { + values[VarManager::kPairMass] = KFGeoTwoLeptons.GetMass(); + values[VarManager::kPairPt] = KFGeoTwoLeptons.GetPt(); + } + + KFGeoTwoTracks.SetConstructMethod(2); + KFGeoTwoTracks.AddDaughter(trk1KF); + KFGeoTwoTracks.AddDaughter(trk1KF); + + if (fgUsedVars[kDitrackMass] || fgUsedVars[kDitrackPt]) { + values[VarManager::kDitrackMass] = KFGeoTwoTracks.GetMass(); + values[VarManager::kDitrackPt] = KFGeoTwoTracks.GetPt(); + } + + KFGeoFourProng.SetConstructMethod(2); + KFGeoFourProng.AddDaughter(KFGeoTwoLeptons); + KFGeoFourProng.AddDaughter(KFGeoTwoTracks); + } + + if constexpr (candidateType == kPsi2StoJpsiPiPi) { + KFPTrack kfpTrack0 = createKFPTrackFromTrack(lepton1); + lepton1KF = KFParticle(kfpTrack0, -11 * lepton1.sign()); + KFPTrack kfpTrack1 = createKFPTrackFromTrack(lepton2); + lepton2KF = KFParticle(kfpTrack1, -11 * lepton2.sign()); + KFPTrack kfpTrack2 = createKFPTrackFromTrack(track1); + trk1KF = KFParticle(kfpTrack2, 211 * track1.sign()); + KFPTrack kfpTrack3 = createKFPTrackFromTrack(track2); + trk2KF = KFParticle(kfpTrack3, 211 * track2.sign()); + + KFGeoTwoLeptons.SetConstructMethod(2); + KFGeoTwoLeptons.AddDaughter(lepton1KF); + KFGeoTwoLeptons.AddDaughter(lepton2KF); + + if (fgUsedVars[kPairMass] || fgUsedVars[kPairPt]) { + values[VarManager::kPairMass] = KFGeoTwoLeptons.GetMass(); + values[VarManager::kPairPt] = KFGeoTwoLeptons.GetPt(); + } + + KFGeoFourProng.SetConstructMethod(3); + KFGeoFourProng.AddDaughter(KFGeoTwoLeptons); + KFGeoFourProng.AddDaughter(trk1KF); + KFGeoFourProng.AddDaughter(trk2KF); + } + + if (fgUsedVars[kKFMass]) { + float mass = 0., massErr = 0.; + if (!KFGeoFourProng.GetMass(mass, massErr)) + values[kKFMass] = mass; + else + values[kKFMass] = -999.; + } + + KFPVertex kfpVertex = createKFPVertexFromCollision(collision); + values[kKFNContributorsPV] = kfpVertex.GetNContributors(); + KFParticle KFPV(kfpVertex); + double dxQuadlet2PV = KFGeoFourProng.GetX() - KFPV.GetX(); + double dyQuadlet2PV = KFGeoFourProng.GetY() - KFPV.GetY(); + double dzQuadlet2PV = KFGeoFourProng.GetZ() - KFPV.GetZ(); + + values[kVertexingLxy] = std::sqrt(dxQuadlet2PV * dxQuadlet2PV + dyQuadlet2PV * dyQuadlet2PV); + values[kVertexingLz] = std::sqrt(dzQuadlet2PV * dzQuadlet2PV); + values[kVertexingLxyz] = std::sqrt(dxQuadlet2PV * dxQuadlet2PV + dyQuadlet2PV * dyQuadlet2PV + dzQuadlet2PV * dzQuadlet2PV); + + values[kVertexingLxyErr] = (KFPV.GetCovariance(0) + KFGeoFourProng.GetCovariance(0)) * dxQuadlet2PV * dxQuadlet2PV + (KFPV.GetCovariance(2) + KFGeoFourProng.GetCovariance(2)) * dyQuadlet2PV * dyQuadlet2PV + 2 * ((KFPV.GetCovariance(1) + KFGeoFourProng.GetCovariance(1)) * dxQuadlet2PV * dyQuadlet2PV); + values[kVertexingLzErr] = (KFPV.GetCovariance(5) + KFGeoFourProng.GetCovariance(5)) * dzQuadlet2PV * dzQuadlet2PV; + values[kVertexingLxyzErr] = (KFPV.GetCovariance(0) + KFGeoFourProng.GetCovariance(0)) * dxQuadlet2PV * dxQuadlet2PV + (KFPV.GetCovariance(2) + KFGeoFourProng.GetCovariance(2)) * dyQuadlet2PV * dyQuadlet2PV + (KFPV.GetCovariance(5) + KFGeoFourProng.GetCovariance(5)) * dzQuadlet2PV * dzQuadlet2PV + 2 * ((KFPV.GetCovariance(1) + KFGeoFourProng.GetCovariance(1)) * dxQuadlet2PV * dyQuadlet2PV + (KFPV.GetCovariance(3) + KFGeoFourProng.GetCovariance(3)) * dxQuadlet2PV * dzQuadlet2PV + (KFPV.GetCovariance(4) + KFGeoFourProng.GetCovariance(4)) * dyQuadlet2PV * dzQuadlet2PV); + + if (fabs(values[kVertexingLxy]) < 1.e-8f) + values[kVertexingLxy] = 1.e-8f; + values[kVertexingLxyErr] = values[kVertexingLxyErr] < 0. ? 1.e8f : std::sqrt(values[kVertexingLxyErr]) / values[kVertexingLxy]; + if (fabs(values[kVertexingLz]) < 1.e-8f) + values[kVertexingLz] = 1.e-8f; + values[kVertexingLzErr] = values[kVertexingLzErr] < 0. ? 1.e8f : std::sqrt(values[kVertexingLzErr]) / values[kVertexingLz]; + if (fabs(values[kVertexingLxyz]) < 1.e-8f) + values[kVertexingLxyz] = 1.e-8f; + values[kVertexingLxyzErr] = values[kVertexingLxyzErr] < 0. ? 1.e8f : std::sqrt(values[kVertexingLxyzErr]) / values[kVertexingLxyz]; + + values[kVertexingTauxy] = KFGeoFourProng.GetPseudoProperDecayTime(KFPV, KFGeoFourProng.GetMass()) / (o2::constants::physics::LightSpeedCm2NS); + values[kVertexingTauz] = -1 * dzQuadlet2PV * KFGeoFourProng.GetMass() / (TMath::Abs(KFGeoFourProng.GetPz()) * o2::constants::physics::LightSpeedCm2NS); + values[kVertexingPz] = TMath::Abs(KFGeoFourProng.GetPz()); + values[kVertexingSV] = KFGeoFourProng.GetZ(); + + values[kVertexingTauxyErr] = values[kVertexingLxyErr] * KFGeoFourProng.GetMass() / (KFGeoFourProng.GetPt() * o2::constants::physics::LightSpeedCm2NS); + values[kVertexingTauzErr] = values[kVertexingLzErr] * KFGeoFourProng.GetMass() / (TMath::Abs(KFGeoFourProng.GetPz()) * o2::constants::physics::LightSpeedCm2NS); + values[kVertexingChi2PCA] = KFGeoFourProng.GetChi2(); + values[kCosPointingAngle] = (std::sqrt(dxQuadlet2PV * dxQuadlet2PV) * v1234.Px() + + std::sqrt(dyQuadlet2PV * dyQuadlet2PV) * v1234.Py() + + std::sqrt(dzQuadlet2PV * dzQuadlet2PV) * v1234.Pz()) / + (v1234.P() * values[VarManager::kVertexingLxyz]); + // // run 2 definitions: Decay length projected onto the momentum vector of the candidate + values[kVertexingLzProjected] = (dzQuadlet2PV * KFGeoFourProng.GetPz()) / TMath::Sqrt(KFGeoFourProng.GetPz() * KFGeoFourProng.GetPz()); + values[kVertexingLxyProjected] = (dxQuadlet2PV * KFGeoFourProng.GetPx()) + (dyQuadlet2PV * KFGeoFourProng.GetPy()); + values[kVertexingLxyProjected] = values[kVertexingLxyProjected] / TMath::Sqrt((KFGeoFourProng.GetPx() * KFGeoFourProng.GetPx()) + (KFGeoFourProng.GetPy() * KFGeoFourProng.GetPy())); + values[kVertexingLxyzProjected] = (dxQuadlet2PV * KFGeoFourProng.GetPx()) + (dyQuadlet2PV * KFGeoFourProng.GetPy()) + (dzQuadlet2PV * KFGeoFourProng.GetPz()); + values[kVertexingLxyzProjected] = values[kVertexingLxyzProjected] / TMath::Sqrt((KFGeoFourProng.GetPx() * KFGeoFourProng.GetPx()) + (KFGeoFourProng.GetPy() * KFGeoFourProng.GetPy()) + (KFGeoFourProng.GetPz() * KFGeoFourProng.GetPz())); + values[kVertexingTauxyProjected] = values[kVertexingLxyProjected] * KFGeoFourProng.GetMass() / (KFGeoFourProng.GetPt()); + values[kVertexingTauxyProjectedNs] = values[kVertexingTauxyProjected] / o2::constants::physics::LightSpeedCm2NS; + values[kVertexingTauzProjected] = values[kVertexingLzProjected] * KFGeoFourProng.GetMass() / TMath::Abs(KFGeoFourProng.GetPz()); + values[kKFChi2OverNDFGeo] = KFGeoFourProng.GetChi2() / KFGeoFourProng.GetNDF(); + } else { + return; + } +} + //__________________________________________________________________ template -void VarManager::FillQaudMC(T1 const& dilepton, T2 const& track1, T2 const& track2, float* values) +void VarManager::FillQuadMC(T1 const& dilepton, T2 const& track1, T2 const& track2, float* values) { if (!values) { values = fgValues; diff --git a/PWGDQ/DataModel/ReducedInfoTables.h b/PWGDQ/DataModel/ReducedInfoTables.h index dcf27f9ac9c..519928665e9 100644 --- a/PWGDQ/DataModel/ReducedInfoTables.h +++ b/PWGDQ/DataModel/ReducedInfoTables.h @@ -33,13 +33,13 @@ namespace o2::aod namespace dqppfilter { -DECLARE_SOA_COLUMN(EventFilter, eventFilter, uint64_t); //! Bit-field used for the high level event triggering +DECLARE_SOA_COLUMN(EventFilter, eventFilter, uint64_t); //! Bit-field used for the high level event triggering DECLARE_SOA_COLUMN(NewBcMultFT0A, newBcMultFT0A, float); //! sum of amplitudes on A side of FT0 DECLARE_SOA_COLUMN(NewBcMultFT0C, newBcMultFT0C, float); //! sum of amplitudes on C side of FT0 DECLARE_SOA_COLUMN(NewBcMultFDDA, newBcMultFDDA, float); //! sum of amplitudes on A side of FDD DECLARE_SOA_COLUMN(NewBcMultFDDC, newBcMultFDDC, float); //! sum of amplitudes on C side of FDD DECLARE_SOA_COLUMN(NewBcMultFV0A, newBcMultFV0A, float); //! sum of amplitudes on A side of FDD -} +} // namespace dqppfilter DECLARE_SOA_TABLE(DQEventFilter, "AOD", "EVENTFILTER", //! Store event-level decisions (DQ high level triggers) dqppfilter::EventFilter); @@ -64,11 +64,11 @@ namespace reducedevent { // basic event information -DECLARE_SOA_INDEX_COLUMN(Collision, collision); //! -DECLARE_SOA_BITMAP_COLUMN(Tag, tag, 64); //! Bit-field for storing event information (e.g. high level info, cut decisions) -DECLARE_SOA_COLUMN(MCPosX, mcPosX, float); //! MC event position X -DECLARE_SOA_COLUMN(MCPosY, mcPosY, float); //! MC event position Y -DECLARE_SOA_COLUMN(MCPosZ, mcPosZ, float); //! MC event position Z +DECLARE_SOA_INDEX_COLUMN(Collision, collision); //! +DECLARE_SOA_BITMAP_COLUMN(Tag, tag, 64); //! Bit-field for storing event information (e.g. high level info, cut decisions) +DECLARE_SOA_COLUMN(MCPosX, mcPosX, float); //! MC event position X +DECLARE_SOA_COLUMN(MCPosY, mcPosY, float); //! MC event position Y +DECLARE_SOA_COLUMN(MCPosZ, mcPosZ, float); //! MC event position Z DECLARE_SOA_COLUMN(NTPCoccupContribLongA, nTPCoccupContribLongA, int); //! TPC pileup occupancy on A side (long time range) DECLARE_SOA_COLUMN(NTPCoccupContribLongC, nTPCoccupContribLongC, int); //! TPC pileup occupancy on C side (long time range) DECLARE_SOA_COLUMN(NTPCoccupMeanTimeLongA, nTPCoccupMeanTimeLongA, float); //! TPC pileup mean time on A side (long time range) @@ -93,51 +93,51 @@ DECLARE_SOA_COLUMN(NTrkBPos, nTrkBPos, int); DECLARE_SOA_COLUMN(NTrkBNeg, nTrkBNeg, int); DECLARE_SOA_COLUMN(NTrkBAll, nTrkBAll, int); -DECLARE_SOA_COLUMN(Q1ZNAX, q1znax, float); //! Q-vector x component, evaluated with ZNA (harmonic 1 and power 1) -DECLARE_SOA_COLUMN(Q1ZNAY, q1znay, float); //! Q-vector y component, evaluated with ZNA (harmonic 1 and power 1) -DECLARE_SOA_COLUMN(Q1ZNCX, q1zncx, float); //! Q-vector x component, evaluated with ZNC (harmonic 1 and power 1) -DECLARE_SOA_COLUMN(Q1ZNCY, q1zncy, float); //! Q-vector y component, evaluated with ZNC (harmonic 1 and power 1) -DECLARE_SOA_COLUMN(Q1X0A, q1x0a, float); //! Q-vector x component, with event eta gap A (harmonic 1 and power 1) -DECLARE_SOA_COLUMN(Q1Y0A, q1y0a, float); //! Q-vector y component, with event eta gap A (harmonic 1 and power 1) -DECLARE_SOA_COLUMN(Q1X0B, q1x0b, float); //! Q-vector x component, with event eta gap B (harmonic 1 and power 1) -DECLARE_SOA_COLUMN(Q1Y0B, q1y0b, float); //! Q-vector y component, with event eta gap B (harmonic 1 and power 1) -DECLARE_SOA_COLUMN(Q1X0C, q1x0c, float); //! Q-vector x component, with event eta gap C (harmonic 1 and power 1) -DECLARE_SOA_COLUMN(Q1Y0C, q1y0c, float); //! Q-vector y component, with event eta gap C (harmonic 1 and power 1) -DECLARE_SOA_COLUMN(Q2X0A, q2x0a, float); //! Q-vector x component, with event eta gap A (harmonic 2 and power 1) -DECLARE_SOA_COLUMN(Q2Y0A, q2y0a, float); //! Q-vector y component, with event eta gap A (harmonic 2 and power 1) -DECLARE_SOA_COLUMN(Q2X0B, q2x0b, float); //! Q-vector x component, with event eta gap B (harmonic 2 and power 1) -DECLARE_SOA_COLUMN(Q2Y0B, q2y0b, float); //! Q-vector y component, with event eta gap B (harmonic 2 and power 1) -DECLARE_SOA_COLUMN(Q2X0C, q2x0c, float); //! Q-vector x component, with event eta gap C (harmonic 2 and power 1) -DECLARE_SOA_COLUMN(Q2Y0C, q2y0c, float); //! Q-vector y component, with event eta gap C (harmonic 2 and power 1) -DECLARE_SOA_COLUMN(MultA, multa, float); //! Event multiplicity eta gap A -DECLARE_SOA_COLUMN(MultB, multb, float); //! Event multiplicity eta gap B -DECLARE_SOA_COLUMN(MultC, multc, float); //! Event multiplicity eta gap C -DECLARE_SOA_COLUMN(Q3X0A, q3x0a, float); //! Q-vector x component, with event eta gap A (harmonic 3 and power 1) -DECLARE_SOA_COLUMN(Q3Y0A, q3y0a, float); //! Q-vector y component, with event eta gap A (harmonic 3 and power 1) -DECLARE_SOA_COLUMN(Q3X0B, q3x0b, float); //! Q-vector x component, with event eta gap B (harmonic 3 and power 1) -DECLARE_SOA_COLUMN(Q3Y0B, q3y0b, float); //! Q-vector y component, with event eta gap B (harmonic 3 and power 1) -DECLARE_SOA_COLUMN(Q3X0C, q3x0c, float); //! Q-vector x component, with event eta gap C (harmonic 3 and power 1) -DECLARE_SOA_COLUMN(Q3Y0C, q3y0c, float); //! Q-vector y component, with event eta gap C (harmonic 3 and power 1) -DECLARE_SOA_COLUMN(Q4X0A, q4x0a, float); //! Q-vector x component, with event eta gap A (harmonic 4 and power 1) -DECLARE_SOA_COLUMN(Q4Y0A, q4y0a, float); //! Q-vector y component, with event eta gap A (harmonic 4 and power 1) -DECLARE_SOA_COLUMN(Q4X0B, q4x0b, float); //! Q-vector x component, with event eta gap B (harmonic 4 and power 1) -DECLARE_SOA_COLUMN(Q4Y0B, q4y0b, float); //! Q-vector y component, with event eta gap B (harmonic 4 and power 1) -DECLARE_SOA_COLUMN(Q4X0C, q4x0c, float); //! Q-vector x component, with event eta gap C (harmonic 4 and power 1) -DECLARE_SOA_COLUMN(Q4Y0C, q4y0c, float); //! Q-vector y component, with event eta gap C (harmonic 4 and power 1) -DECLARE_SOA_COLUMN(Q42XA, q42xa, float); //! Q-vector x component, with event eta gap A (harmonic 4 and power 2) -DECLARE_SOA_COLUMN(Q42YA, q42ya, float); //! Q-vector y component, with event eta gap A (harmonic 4 and power 2) -DECLARE_SOA_COLUMN(Q23XA, q23xa, float); //! Q-vector x component, with event eta gap A (harmonic 2 and power 3) -DECLARE_SOA_COLUMN(Q23YA, q23ya, float); //! Q-vector y component, with event eta gap A (harmonic 2 and power 3) -DECLARE_SOA_COLUMN(S11A, s11a, float); //! Weighted multiplicity (p = 1, k = 1) -DECLARE_SOA_COLUMN(S12A, s12a, float); //! Weighted multiplicity (p = 1, k = 2) -DECLARE_SOA_COLUMN(S13A, s13a, float); //! Weighted multiplicity (p = 1, k = 3) -DECLARE_SOA_COLUMN(S31A, s31a, float); //! Weighted multiplicity (p = 3, k = 1) -DECLARE_SOA_COLUMN(CORR2REF, corr2ref, float); //! Ref Flow correlator <2> +DECLARE_SOA_COLUMN(Q1ZNAX, q1znax, float); //! Q-vector x component, evaluated with ZNA (harmonic 1 and power 1) +DECLARE_SOA_COLUMN(Q1ZNAY, q1znay, float); //! Q-vector y component, evaluated with ZNA (harmonic 1 and power 1) +DECLARE_SOA_COLUMN(Q1ZNCX, q1zncx, float); //! Q-vector x component, evaluated with ZNC (harmonic 1 and power 1) +DECLARE_SOA_COLUMN(Q1ZNCY, q1zncy, float); //! Q-vector y component, evaluated with ZNC (harmonic 1 and power 1) +DECLARE_SOA_COLUMN(Q1X0A, q1x0a, float); //! Q-vector x component, with event eta gap A (harmonic 1 and power 1) +DECLARE_SOA_COLUMN(Q1Y0A, q1y0a, float); //! Q-vector y component, with event eta gap A (harmonic 1 and power 1) +DECLARE_SOA_COLUMN(Q1X0B, q1x0b, float); //! Q-vector x component, with event eta gap B (harmonic 1 and power 1) +DECLARE_SOA_COLUMN(Q1Y0B, q1y0b, float); //! Q-vector y component, with event eta gap B (harmonic 1 and power 1) +DECLARE_SOA_COLUMN(Q1X0C, q1x0c, float); //! Q-vector x component, with event eta gap C (harmonic 1 and power 1) +DECLARE_SOA_COLUMN(Q1Y0C, q1y0c, float); //! Q-vector y component, with event eta gap C (harmonic 1 and power 1) +DECLARE_SOA_COLUMN(Q2X0A, q2x0a, float); //! Q-vector x component, with event eta gap A (harmonic 2 and power 1) +DECLARE_SOA_COLUMN(Q2Y0A, q2y0a, float); //! Q-vector y component, with event eta gap A (harmonic 2 and power 1) +DECLARE_SOA_COLUMN(Q2X0B, q2x0b, float); //! Q-vector x component, with event eta gap B (harmonic 2 and power 1) +DECLARE_SOA_COLUMN(Q2Y0B, q2y0b, float); //! Q-vector y component, with event eta gap B (harmonic 2 and power 1) +DECLARE_SOA_COLUMN(Q2X0C, q2x0c, float); //! Q-vector x component, with event eta gap C (harmonic 2 and power 1) +DECLARE_SOA_COLUMN(Q2Y0C, q2y0c, float); //! Q-vector y component, with event eta gap C (harmonic 2 and power 1) +DECLARE_SOA_COLUMN(MultA, multa, float); //! Event multiplicity eta gap A +DECLARE_SOA_COLUMN(MultB, multb, float); //! Event multiplicity eta gap B +DECLARE_SOA_COLUMN(MultC, multc, float); //! Event multiplicity eta gap C +DECLARE_SOA_COLUMN(Q3X0A, q3x0a, float); //! Q-vector x component, with event eta gap A (harmonic 3 and power 1) +DECLARE_SOA_COLUMN(Q3Y0A, q3y0a, float); //! Q-vector y component, with event eta gap A (harmonic 3 and power 1) +DECLARE_SOA_COLUMN(Q3X0B, q3x0b, float); //! Q-vector x component, with event eta gap B (harmonic 3 and power 1) +DECLARE_SOA_COLUMN(Q3Y0B, q3y0b, float); //! Q-vector y component, with event eta gap B (harmonic 3 and power 1) +DECLARE_SOA_COLUMN(Q3X0C, q3x0c, float); //! Q-vector x component, with event eta gap C (harmonic 3 and power 1) +DECLARE_SOA_COLUMN(Q3Y0C, q3y0c, float); //! Q-vector y component, with event eta gap C (harmonic 3 and power 1) +DECLARE_SOA_COLUMN(Q4X0A, q4x0a, float); //! Q-vector x component, with event eta gap A (harmonic 4 and power 1) +DECLARE_SOA_COLUMN(Q4Y0A, q4y0a, float); //! Q-vector y component, with event eta gap A (harmonic 4 and power 1) +DECLARE_SOA_COLUMN(Q4X0B, q4x0b, float); //! Q-vector x component, with event eta gap B (harmonic 4 and power 1) +DECLARE_SOA_COLUMN(Q4Y0B, q4y0b, float); //! Q-vector y component, with event eta gap B (harmonic 4 and power 1) +DECLARE_SOA_COLUMN(Q4X0C, q4x0c, float); //! Q-vector x component, with event eta gap C (harmonic 4 and power 1) +DECLARE_SOA_COLUMN(Q4Y0C, q4y0c, float); //! Q-vector y component, with event eta gap C (harmonic 4 and power 1) +DECLARE_SOA_COLUMN(Q42XA, q42xa, float); //! Q-vector x component, with event eta gap A (harmonic 4 and power 2) +DECLARE_SOA_COLUMN(Q42YA, q42ya, float); //! Q-vector y component, with event eta gap A (harmonic 4 and power 2) +DECLARE_SOA_COLUMN(Q23XA, q23xa, float); //! Q-vector x component, with event eta gap A (harmonic 2 and power 3) +DECLARE_SOA_COLUMN(Q23YA, q23ya, float); //! Q-vector y component, with event eta gap A (harmonic 2 and power 3) +DECLARE_SOA_COLUMN(S11A, s11a, float); //! Weighted multiplicity (p = 1, k = 1) +DECLARE_SOA_COLUMN(S12A, s12a, float); //! Weighted multiplicity (p = 1, k = 2) +DECLARE_SOA_COLUMN(S13A, s13a, float); //! Weighted multiplicity (p = 1, k = 3) +DECLARE_SOA_COLUMN(S31A, s31a, float); //! Weighted multiplicity (p = 3, k = 1) +DECLARE_SOA_COLUMN(CORR2REF, corr2ref, float); //! Ref Flow correlator <2> DECLARE_SOA_COLUMN(CORR2REFetagap, corr2refetagap, float); //! Ref Flow correlator <2> -DECLARE_SOA_COLUMN(CORR4REF, corr4ref, float); //! Ref Flow correlator <4> -DECLARE_SOA_COLUMN(M11REF, m11ref, float); //! Weighted multiplicity of <<2>> for reference flow -DECLARE_SOA_COLUMN(M1111REF, m1111ref, float); //! Weighted multiplicity of <<4>> for reference flow -DECLARE_SOA_COLUMN(M11REFetagap, m11refetagap, float); //! Weighted multiplicity of <<2>> etagap for reference flow +DECLARE_SOA_COLUMN(CORR4REF, corr4ref, float); //! Ref Flow correlator <4> +DECLARE_SOA_COLUMN(M11REF, m11ref, float); //! Weighted multiplicity of <<2>> for reference flow +DECLARE_SOA_COLUMN(M1111REF, m1111ref, float); //! Weighted multiplicity of <<4>> for reference flow +DECLARE_SOA_COLUMN(M11REFetagap, m11refetagap, float); //! Weighted multiplicity of <<2>> etagap for reference flow } // namespace reducedevent DECLARE_SOA_TABLE_STAGED(ReducedEvents, "REDUCEDEVENT", //! Main event information table @@ -614,42 +614,42 @@ DECLARE_SOA_COLUMN(Vt2, vt2, float); //! Production vertex time DECLARE_SOA_COLUMN(IsAmbig1, isAmbig1, int); //! DECLARE_SOA_COLUMN(IsAmbig2, isAmbig2, int); //! -DECLARE_SOA_COLUMN(FwdDcaX1, fwdDcaX1, float); //! X component of forward DCA -DECLARE_SOA_COLUMN(FwdDcaY1, fwdDcaY1, float); //! Y component of forward DCA -DECLARE_SOA_COLUMN(FwdDcaX2, fwdDcaX2, float); //! X component of forward DCA -DECLARE_SOA_COLUMN(FwdDcaY2, fwdDcaY2, float); //! Y component of forward DCA -DECLARE_SOA_COLUMN(ITSNCls1, itsNCls1, int); //! Number of ITS clusters +DECLARE_SOA_COLUMN(FwdDcaX1, fwdDcaX1, float); //! X component of forward DCA +DECLARE_SOA_COLUMN(FwdDcaY1, fwdDcaY1, float); //! Y component of forward DCA +DECLARE_SOA_COLUMN(FwdDcaX2, fwdDcaX2, float); //! X component of forward DCA +DECLARE_SOA_COLUMN(FwdDcaY2, fwdDcaY2, float); //! Y component of forward DCA +DECLARE_SOA_COLUMN(ITSNCls1, itsNCls1, int); //! Number of ITS clusters DECLARE_SOA_COLUMN(ITSClusterMap1, itsClusterMap1, uint8_t); //! ITS clusters map DECLARE_SOA_COLUMN(ITSChi2NCl1, itsChi2NCl1, float); //! ITS chi2/Ncls -DECLARE_SOA_COLUMN(TPCNClsFound1, tpcNClsFound1, float); //! Number of TPC clusters found -DECLARE_SOA_COLUMN(TPCNClsCR1, tpcNClsCR1, float); //! Number of TPC crossed rows -DECLARE_SOA_COLUMN(TPCChi2NCl1, tpcChi2NCl1, float); //! TPC chi2/Ncls -DECLARE_SOA_COLUMN(DcaXY1, dcaXY1, float); //! DCA in XY plane -DECLARE_SOA_COLUMN(DcaZ1, dcaZ1, float); //! DCA in Z -DECLARE_SOA_COLUMN(TPCSignal1, tpcSignal1, float); //! TPC dE/dx signal -DECLARE_SOA_COLUMN(TPCNSigmaEl1, tpcNSigmaEl1, float); //! TPC nSigma electron -DECLARE_SOA_COLUMN(TPCNSigmaPi1, tpcNSigmaPi1, float); //! TPC nSigma pion -DECLARE_SOA_COLUMN(TPCNSigmaPr1, tpcNSigmaPr1, float); //! TPC nSigma proton -DECLARE_SOA_COLUMN(TOFBeta1, tofBeta1, float); //! TOF beta -DECLARE_SOA_COLUMN(TOFNSigmaEl1, tofNSigmaEl1, float); //! TOF nSigma electron -DECLARE_SOA_COLUMN(TOFNSigmaPi1, tofNSigmaPi1, float); //! TOF nSigma pion -DECLARE_SOA_COLUMN(TOFNSigmaPr1, tofNSigmaPr1, float); //! TOF nSigma proton -DECLARE_SOA_COLUMN(ITSNCls2, itsNCls2, int); //! Number of ITS clusters +DECLARE_SOA_COLUMN(TPCNClsFound1, tpcNClsFound1, float); //! Number of TPC clusters found +DECLARE_SOA_COLUMN(TPCNClsCR1, tpcNClsCR1, float); //! Number of TPC crossed rows +DECLARE_SOA_COLUMN(TPCChi2NCl1, tpcChi2NCl1, float); //! TPC chi2/Ncls +DECLARE_SOA_COLUMN(DcaXY1, dcaXY1, float); //! DCA in XY plane +DECLARE_SOA_COLUMN(DcaZ1, dcaZ1, float); //! DCA in Z +DECLARE_SOA_COLUMN(TPCSignal1, tpcSignal1, float); //! TPC dE/dx signal +DECLARE_SOA_COLUMN(TPCNSigmaEl1, tpcNSigmaEl1, float); //! TPC nSigma electron +DECLARE_SOA_COLUMN(TPCNSigmaPi1, tpcNSigmaPi1, float); //! TPC nSigma pion +DECLARE_SOA_COLUMN(TPCNSigmaPr1, tpcNSigmaPr1, float); //! TPC nSigma proton +DECLARE_SOA_COLUMN(TOFBeta1, tofBeta1, float); //! TOF beta +DECLARE_SOA_COLUMN(TOFNSigmaEl1, tofNSigmaEl1, float); //! TOF nSigma electron +DECLARE_SOA_COLUMN(TOFNSigmaPi1, tofNSigmaPi1, float); //! TOF nSigma pion +DECLARE_SOA_COLUMN(TOFNSigmaPr1, tofNSigmaPr1, float); //! TOF nSigma proton +DECLARE_SOA_COLUMN(ITSNCls2, itsNCls2, int); //! Number of ITS clusters DECLARE_SOA_COLUMN(ITSClusterMap2, itsClusterMap2, uint8_t); //! ITS clusters map DECLARE_SOA_COLUMN(ITSChi2NCl2, itsChi2NCl2, float); //! ITS chi2/Ncls -DECLARE_SOA_COLUMN(TPCNClsFound2, tpcNClsFound2, float); //! Number of TPC clusters found -DECLARE_SOA_COLUMN(TPCNClsCR2, tpcNClsCR2, float); //! Number of TPC crossed rows -DECLARE_SOA_COLUMN(TPCChi2NCl2, tpcChi2NCl2, float); //! TPC chi2/Ncls -DECLARE_SOA_COLUMN(DcaXY2, dcaXY2, float); //! DCA in XY plane -DECLARE_SOA_COLUMN(DcaZ2, dcaZ2, float); //! DCA in Z -DECLARE_SOA_COLUMN(TPCSignal2, tpcSignal2, float); //! TPC dE/dx signal -DECLARE_SOA_COLUMN(TPCNSigmaEl2, tpcNSigmaEl2, float); //! TPC nSigma electron -DECLARE_SOA_COLUMN(TPCNSigmaPi2, tpcNSigmaPi2, float); //! TPC nSigma pion -DECLARE_SOA_COLUMN(TPCNSigmaPr2, tpcNSigmaPr2, float); //! TPC nSigma proton -DECLARE_SOA_COLUMN(TOFBeta2, tofBeta2, float); //! TOF beta -DECLARE_SOA_COLUMN(TOFNSigmaEl2, tofNSigmaEl2, float); //! TOF nSigma electron -DECLARE_SOA_COLUMN(TOFNSigmaPi2, tofNSigmaPi2, float); //! TOF nSigma pion -DECLARE_SOA_COLUMN(TOFNSigmaPr2, tofNSigmaPr2, float); //! TOF nSigma proton +DECLARE_SOA_COLUMN(TPCNClsFound2, tpcNClsFound2, float); //! Number of TPC clusters found +DECLARE_SOA_COLUMN(TPCNClsCR2, tpcNClsCR2, float); //! Number of TPC crossed rows +DECLARE_SOA_COLUMN(TPCChi2NCl2, tpcChi2NCl2, float); //! TPC chi2/Ncls +DECLARE_SOA_COLUMN(DcaXY2, dcaXY2, float); //! DCA in XY plane +DECLARE_SOA_COLUMN(DcaZ2, dcaZ2, float); //! DCA in Z +DECLARE_SOA_COLUMN(TPCSignal2, tpcSignal2, float); //! TPC dE/dx signal +DECLARE_SOA_COLUMN(TPCNSigmaEl2, tpcNSigmaEl2, float); //! TPC nSigma electron +DECLARE_SOA_COLUMN(TPCNSigmaPi2, tpcNSigmaPi2, float); //! TPC nSigma pion +DECLARE_SOA_COLUMN(TPCNSigmaPr2, tpcNSigmaPr2, float); //! TPC nSigma proton +DECLARE_SOA_COLUMN(TOFBeta2, tofBeta2, float); //! TOF beta +DECLARE_SOA_COLUMN(TOFNSigmaEl2, tofNSigmaEl2, float); //! TOF nSigma electron +DECLARE_SOA_COLUMN(TOFNSigmaPi2, tofNSigmaPi2, float); //! TOF nSigma pion +DECLARE_SOA_COLUMN(TOFNSigmaPr2, tofNSigmaPr2, float); //! TOF nSigma proton DECLARE_SOA_COLUMN(DCAxyzTrk0KF, dcaxyztrk0KF, float); //! 3D DCA to primary vertex of the first track DECLARE_SOA_COLUMN(DCAxyzTrk1KF, dcaxyztrk1KF, float); //! 3D DCA to primary vertex of the second track @@ -665,58 +665,58 @@ DECLARE_SOA_COLUMN(DeviationxyTrk1KF, deviationxyTrk1KF, float); //! 2D chi2 dev // pair information namespace reducedpair { -DECLARE_SOA_INDEX_COLUMN(ReducedEvent, reducedevent); //! -DECLARE_SOA_INDEX_COLUMN_FULL(Index0, index0, int, ReducedTracks, "_0"); //! Index to first prong -DECLARE_SOA_INDEX_COLUMN_FULL(Index1, index1, int, ReducedTracks, "_1"); //! Index to second prong -DECLARE_SOA_INDEX_COLUMN_FULL(Prong0, prong0, int, Tracks, "_0"); //! Index of first prong in Tracks table -DECLARE_SOA_INDEX_COLUMN_FULL(Prong1, prong1, int, Tracks, "_1"); //! Index of second prong in Tracks table -DECLARE_SOA_BITMAP_COLUMN(EventSelection, evSelection, 8); //! Event selection bits (ambiguity, splitting candidate) -DECLARE_SOA_COLUMN(Mass, mass, float); //! -DECLARE_SOA_COLUMN(Pt, pt, float); //! -DECLARE_SOA_COLUMN(Eta, eta, float); //! -DECLARE_SOA_COLUMN(Phi, phi, float); //! -DECLARE_SOA_COLUMN(Sign, sign, int); //! -DECLARE_SOA_BITMAP_COLUMN(FilterMap, filterMap, 32); //! -DECLARE_SOA_BITMAP_COLUMN(PairFilterMap, pairFilterMap, 32); //! -DECLARE_SOA_BITMAP_COLUMN(CommonFilterMap, commonFilterMap, 32); //! -DECLARE_SOA_COLUMN(McDecision, mcDecision, uint32_t); //! -DECLARE_SOA_COLUMN(Tauz, tauz, float); //! Longitudinal pseudo-proper time of lepton pair (in ns) -DECLARE_SOA_COLUMN(TauzErr, tauzErr, float); //! Error on longitudinal pseudo-proper time of lepton pair (in ns) -DECLARE_SOA_COLUMN(VertexPz, vertexPz, float); //! Longitudinal projection of impulsion -DECLARE_SOA_COLUMN(SVertex, sVertex, float); //! Secondary vertex of lepton pair -DECLARE_SOA_COLUMN(Tauxy, tauxy, float); //! Transverse pseudo-proper time of lepton pair (in ns) -DECLARE_SOA_COLUMN(TauxyErr, tauxyErr, float); //! Error on transverse pseudo-proper time of lepton pair (in ns) -DECLARE_SOA_COLUMN(Lz, lz, float); //! Longitudinal projection of decay length -DECLARE_SOA_COLUMN(Lxy, lxy, float); //! Transverse projection of decay length -DECLARE_SOA_COLUMN(Chi2pca, chi2pca, float); //! Chi2 for PCA of the dilepton -DECLARE_SOA_COLUMN(CosPointingAngle, cosPointingAngle, float); //! Cosine of the pointing angle -DECLARE_SOA_COLUMN(U2Q2, u2q2, float); //! Scalar product between unitary vector with event flow vector (harmonic 2) -DECLARE_SOA_COLUMN(U3Q3, u3q3, float); //! Scalar product between unitary vector with event flow vector (harmonic 3) -DECLARE_SOA_COLUMN(Cos2DeltaPhi, cos2deltaphi, float); //! Cosinus term using event plane angle (harmonic 2) -DECLARE_SOA_COLUMN(Cos3DeltaPhi, cos3deltaphi, float); //! Cosinus term using event plane angle (harmonic 3) -DECLARE_SOA_COLUMN(R2SP_AB, r2spab, float); //! Event plane resolution for SP method n=2 (A,B) TPC-FT0A -DECLARE_SOA_COLUMN(R2SP_AC, r2spac, float); //! Event plane resolution for SP method n=2 (A,C) TPC-FT0C -DECLARE_SOA_COLUMN(R2SP_BC, r2spbc, float); //! Event plane resolution for SP method n=2 (B,C) FT0A-FT0C -DECLARE_SOA_COLUMN(R3SP, r3sp, float); //! Event plane resolution for SP method n=3 -DECLARE_SOA_COLUMN(R2EP, r2ep, float); //! Event plane resolution for EP method n=2 -DECLARE_SOA_COLUMN(R2EP_AB, r2epab, float); //! Event plane resolution for EP method n=2 (A,B) TPC-FT0A -DECLARE_SOA_COLUMN(R2EP_AC, r2epac, float); //! Event plane resolution for EP method n=2 (A,C) TPC-FT0C -DECLARE_SOA_COLUMN(R2EP_BC, r2epbc, float); //! Event plane resolution for EP method n=2 (B,C) FT0A-FT0C -DECLARE_SOA_COLUMN(R3EP, r3ep, float); //! Event plane resolution for EP method n=3 -DECLARE_SOA_COLUMN(CORR2POI, corr2poi, float); //! POI FLOW CORRELATOR <2'> -DECLARE_SOA_COLUMN(CORR4POI, corr4poi, float); //! POI FLOW CORRELATOR <4'> -DECLARE_SOA_COLUMN(M01POI, m01poi, float); //! POI event weight for <2'> -DECLARE_SOA_COLUMN(M0111POI, m0111poi, float); //! POI event weight for <4'> -DECLARE_SOA_COLUMN(MultDimuons, multdimuons, int); //! Dimuon multiplicity -DECLARE_SOA_COLUMN(CentFT0C, centft0c, float); //! Centrality information from FT0C -DECLARE_SOA_COLUMN(CollisionId, collisionId, int32_t); //! -DECLARE_SOA_COLUMN(IsFirst, isfirst, int); //! Flag for the first dilepton in the collision -DECLARE_SOA_COLUMN(DCAxyzBetweenTrksKF, dcaxyzbetweentrksKF, float); //! DCAxyz between the two tracks -DECLARE_SOA_COLUMN(DCAxyBetweenTrksKF, dcaxybetweentrksKF, float); //! DCAxy between the two tracks -DECLARE_SOA_COLUMN(MassKFGeo, massKFGeo, float); //! Pair mass from KFParticle -DECLARE_SOA_COLUMN(CosPAKFGeo, cosPAKFGeo, float); //! Cosine of the pointing angle from KFParticle -DECLARE_SOA_COLUMN(Chi2OverNDFKFGeo, chi2overndfKFGeo, float); //! Chi2 over NDF from KFParticle -DECLARE_SOA_COLUMN(DecayLengthKFGeo, decaylengthKFGeo, float); //! Decay length from KFParticle +DECLARE_SOA_INDEX_COLUMN(ReducedEvent, reducedevent); //! +DECLARE_SOA_INDEX_COLUMN_FULL(Index0, index0, int, ReducedTracks, "_0"); //! Index to first prong +DECLARE_SOA_INDEX_COLUMN_FULL(Index1, index1, int, ReducedTracks, "_1"); //! Index to second prong +DECLARE_SOA_INDEX_COLUMN_FULL(Prong0, prong0, int, Tracks, "_0"); //! Index of first prong in Tracks table +DECLARE_SOA_INDEX_COLUMN_FULL(Prong1, prong1, int, Tracks, "_1"); //! Index of second prong in Tracks table +DECLARE_SOA_BITMAP_COLUMN(EventSelection, evSelection, 8); //! Event selection bits (ambiguity, splitting candidate) +DECLARE_SOA_COLUMN(Mass, mass, float); //! +DECLARE_SOA_COLUMN(Pt, pt, float); //! +DECLARE_SOA_COLUMN(Eta, eta, float); //! +DECLARE_SOA_COLUMN(Phi, phi, float); //! +DECLARE_SOA_COLUMN(Sign, sign, int); //! +DECLARE_SOA_BITMAP_COLUMN(FilterMap, filterMap, 32); //! +DECLARE_SOA_BITMAP_COLUMN(PairFilterMap, pairFilterMap, 32); //! +DECLARE_SOA_BITMAP_COLUMN(CommonFilterMap, commonFilterMap, 32); //! +DECLARE_SOA_COLUMN(McDecision, mcDecision, uint32_t); //! +DECLARE_SOA_COLUMN(Tauz, tauz, float); //! Longitudinal pseudo-proper time of lepton pair (in ns) +DECLARE_SOA_COLUMN(TauzErr, tauzErr, float); //! Error on longitudinal pseudo-proper time of lepton pair (in ns) +DECLARE_SOA_COLUMN(VertexPz, vertexPz, float); //! Longitudinal projection of impulsion +DECLARE_SOA_COLUMN(SVertex, sVertex, float); //! Secondary vertex of lepton pair +DECLARE_SOA_COLUMN(Tauxy, tauxy, float); //! Transverse pseudo-proper time of lepton pair (in ns) +DECLARE_SOA_COLUMN(TauxyErr, tauxyErr, float); //! Error on transverse pseudo-proper time of lepton pair (in ns) +DECLARE_SOA_COLUMN(Lz, lz, float); //! Longitudinal projection of decay length +DECLARE_SOA_COLUMN(Lxy, lxy, float); //! Transverse projection of decay length +DECLARE_SOA_COLUMN(Chi2pca, chi2pca, float); //! Chi2 for PCA of the dilepton +DECLARE_SOA_COLUMN(CosPointingAngle, cosPointingAngle, float); //! Cosine of the pointing angle +DECLARE_SOA_COLUMN(U2Q2, u2q2, float); //! Scalar product between unitary vector with event flow vector (harmonic 2) +DECLARE_SOA_COLUMN(U3Q3, u3q3, float); //! Scalar product between unitary vector with event flow vector (harmonic 3) +DECLARE_SOA_COLUMN(Cos2DeltaPhi, cos2deltaphi, float); //! Cosinus term using event plane angle (harmonic 2) +DECLARE_SOA_COLUMN(Cos3DeltaPhi, cos3deltaphi, float); //! Cosinus term using event plane angle (harmonic 3) +DECLARE_SOA_COLUMN(R2SP_AB, r2spab, float); //! Event plane resolution for SP method n=2 (A,B) TPC-FT0A +DECLARE_SOA_COLUMN(R2SP_AC, r2spac, float); //! Event plane resolution for SP method n=2 (A,C) TPC-FT0C +DECLARE_SOA_COLUMN(R2SP_BC, r2spbc, float); //! Event plane resolution for SP method n=2 (B,C) FT0A-FT0C +DECLARE_SOA_COLUMN(R3SP, r3sp, float); //! Event plane resolution for SP method n=3 +DECLARE_SOA_COLUMN(R2EP, r2ep, float); //! Event plane resolution for EP method n=2 +DECLARE_SOA_COLUMN(R2EP_AB, r2epab, float); //! Event plane resolution for EP method n=2 (A,B) TPC-FT0A +DECLARE_SOA_COLUMN(R2EP_AC, r2epac, float); //! Event plane resolution for EP method n=2 (A,C) TPC-FT0C +DECLARE_SOA_COLUMN(R2EP_BC, r2epbc, float); //! Event plane resolution for EP method n=2 (B,C) FT0A-FT0C +DECLARE_SOA_COLUMN(R3EP, r3ep, float); //! Event plane resolution for EP method n=3 +DECLARE_SOA_COLUMN(CORR2POI, corr2poi, float); //! POI FLOW CORRELATOR <2'> +DECLARE_SOA_COLUMN(CORR4POI, corr4poi, float); //! POI FLOW CORRELATOR <4'> +DECLARE_SOA_COLUMN(M01POI, m01poi, float); //! POI event weight for <2'> +DECLARE_SOA_COLUMN(M0111POI, m0111poi, float); //! POI event weight for <4'> +DECLARE_SOA_COLUMN(MultDimuons, multdimuons, int); //! Dimuon multiplicity +DECLARE_SOA_COLUMN(CentFT0C, centft0c, float); //! Centrality information from FT0C +DECLARE_SOA_COLUMN(CollisionId, collisionId, int32_t); //! +DECLARE_SOA_COLUMN(IsFirst, isfirst, int); //! Flag for the first dilepton in the collision +DECLARE_SOA_COLUMN(DCAxyzBetweenTrksKF, dcaxyzbetweentrksKF, float); //! DCAxyz between the two tracks +DECLARE_SOA_COLUMN(DCAxyBetweenTrksKF, dcaxybetweentrksKF, float); //! DCAxy between the two tracks +DECLARE_SOA_COLUMN(MassKFGeo, massKFGeo, float); //! Pair mass from KFParticle +DECLARE_SOA_COLUMN(CosPAKFGeo, cosPAKFGeo, float); //! Cosine of the pointing angle from KFParticle +DECLARE_SOA_COLUMN(Chi2OverNDFKFGeo, chi2overndfKFGeo, float); //! Chi2 over NDF from KFParticle +DECLARE_SOA_COLUMN(DecayLengthKFGeo, decaylengthKFGeo, float); //! Decay length from KFParticle DECLARE_SOA_COLUMN(DecayLengthOverErrKFGeo, decaylengthovererrKFGeo, float); //! Decay length over error from KFParticle DECLARE_SOA_COLUMN(DecayLengthXYKFGeo, decaylengthxyKFGeo, float); //! Decay length XY from KFParticle DECLARE_SOA_COLUMN(DecayLengthXYOverErrKFGeo, decaylengthxyovererrKFGeo, float); //! Decay length XY over error from KFParticle @@ -946,30 +946,65 @@ using DileptonTrackCandidate = DileptonTrackCandidates::iterator; namespace dileptonTrackTrackCandidate { // infotmation about the dilepton-track-track -DECLARE_SOA_COLUMN(Mass, mass, 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(DeltaQ, deltaQ, float); //! -DECLARE_SOA_COLUMN(R1, r1, float); //! distance between the dilepton and the track1 in theta-phi plane -DECLARE_SOA_COLUMN(R2, r2, float); //! distance between the dilepton and the track2 in theta-phi plane -DECLARE_SOA_COLUMN(R, r, float); //! -DECLARE_SOA_COLUMN(DileptonMass, dileptonMass, float); //! -DECLARE_SOA_COLUMN(DileptonPt, dileptonPt, float); //! -DECLARE_SOA_COLUMN(DileptonEta, dileptonEta, float); //! -DECLARE_SOA_COLUMN(DileptonPhi, dileptonPhi, float); //! -DECLARE_SOA_COLUMN(DileptonSign, dileptonSign, int); //! -DECLARE_SOA_COLUMN(DiTracksMass, diTracksMass, float); //! -DECLARE_SOA_COLUMN(DiTracksPt, diTracksPt, float); //! -DECLARE_SOA_COLUMN(TrackPt1, trackPt1, float); //! -DECLARE_SOA_COLUMN(TrackPt2, trackPt2, float); //! -DECLARE_SOA_COLUMN(TrackEta1, trackEta1, float); //! -DECLARE_SOA_COLUMN(TrackEta2, trackEta2, float); //! -DECLARE_SOA_COLUMN(TrackPhi1, trackPhi1, float); //! -DECLARE_SOA_COLUMN(TrackPhi2, trackPhi2, float); //! -DECLARE_SOA_COLUMN(TrackSign1, trackSign1, int); //! -DECLARE_SOA_COLUMN(TrackSign2, trackSign2, int); //! +DECLARE_SOA_COLUMN(Mass, mass, 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(DeltaQ, deltaQ, float); //! +DECLARE_SOA_COLUMN(R1, r1, float); //! distance between the dilepton and the track1 in theta-phi plane +DECLARE_SOA_COLUMN(R2, r2, float); //! distance between the dilepton and the track2 in theta-phi plane +DECLARE_SOA_COLUMN(R, r, float); //! +DECLARE_SOA_COLUMN(DileptonMass, dileptonMass, float); //! +DECLARE_SOA_COLUMN(DileptonPt, dileptonPt, float); //! +DECLARE_SOA_COLUMN(DileptonEta, dileptonEta, float); //! +DECLARE_SOA_COLUMN(DileptonPhi, dileptonPhi, float); //! +DECLARE_SOA_COLUMN(DileptonSign, dileptonSign, int); //! +DECLARE_SOA_COLUMN(DileptonTPCnSigmaEl1, dileptonTPCnSigmaEl1, float); //! +DECLARE_SOA_COLUMN(DileptonTPCnSigmaPi1, dileptonTPCnSigmaPi1, float); //! +DECLARE_SOA_COLUMN(DileptonTPCnSigmaPr1, dileptonTPCnSigmaPr1, float); //! +DECLARE_SOA_COLUMN(DileptonTPCnCls1, dileptonTPCnCls1, float); //! +DECLARE_SOA_COLUMN(DileptonTPCnSigmaEl2, dileptonTPCnSigmaEl2, float); //! +DECLARE_SOA_COLUMN(DileptonTPCnSigmaPi2, dileptonTPCnSigmaPi2, float); //! +DECLARE_SOA_COLUMN(DileptonTPCnSigmaPr2, dileptonTPCnSigmaPr2, float); //! +DECLARE_SOA_COLUMN(DileptonTPCnCls2, dileptonTPCnCls2, float); //! +DECLARE_SOA_COLUMN(DiTracksMass, diTracksMass, float); //! +DECLARE_SOA_COLUMN(DiTracksPt, diTracksPt, float); //! +DECLARE_SOA_COLUMN(TrackPt1, trackPt1, float); //! +DECLARE_SOA_COLUMN(TrackPt2, trackPt2, float); //! +DECLARE_SOA_COLUMN(TrackEta1, trackEta1, float); //! +DECLARE_SOA_COLUMN(TrackEta2, trackEta2, float); //! +DECLARE_SOA_COLUMN(TrackPhi1, trackPhi1, float); //! +DECLARE_SOA_COLUMN(TrackPhi2, trackPhi2, float); //! +DECLARE_SOA_COLUMN(TrackSign1, trackSign1, int); //! +DECLARE_SOA_COLUMN(TrackSign2, trackSign2, int); //! +DECLARE_SOA_COLUMN(TrackTPCNSigmaPi1, trackTPCNSigmaPi1, float); //! +DECLARE_SOA_COLUMN(TrackTPCNSigmaPi2, trackTPCNSigmaPi2, float); //! +DECLARE_SOA_COLUMN(TrackTPCNSigmaKa1, trackTPCNSigmaKa1, float); //! +DECLARE_SOA_COLUMN(TrackTPCNSigmaKa2, trackTPCNSigmaKa2, float); //! +DECLARE_SOA_COLUMN(TrackTPCNSigmaPr1, trackTPCNSigmaPr1, float); //! +DECLARE_SOA_COLUMN(TrackTPCNSigmaPr2, trackTPCNSigmaPr2, float); //! +DECLARE_SOA_COLUMN(TrackTPCNCls1, trackTPCNCls1, float); //! +DECLARE_SOA_COLUMN(TrackTPCNCls2, trackTPCNCls2, float); //! +DECLARE_SOA_COLUMN(KFMass, kfMass, float); //! +DECLARE_SOA_COLUMN(VertexingProcCode, vertexingProcCode, float); //! +DECLARE_SOA_COLUMN(VertexingChi2PCA, vertexingChi2PCA, float); //! +DECLARE_SOA_COLUMN(CosPointingAngle, cosPointingAngle, float); //! +DECLARE_SOA_COLUMN(KFDCAxyzBetweenProngs, kfDCAxyzBetweenProngs, float); //! +DECLARE_SOA_COLUMN(KFChi2OverNDFGeo, kfChi2OverNDFGeo, float); //! +DECLARE_SOA_COLUMN(VertexingLz, vertexingLz, float); //! +DECLARE_SOA_COLUMN(VertexingLxy, vertexingLxy, float); //! +DECLARE_SOA_COLUMN(VertexingLxyz, vertexingLxyz, float); //! +DECLARE_SOA_COLUMN(VertexingTauz, vertexingTauz, float); //! +DECLARE_SOA_COLUMN(VertexingTauxy, vertexingTauxy, float); //! +DECLARE_SOA_COLUMN(VertexingLzErr, vertexingLzErr, float); //! +DECLARE_SOA_COLUMN(VertexingLxyzErr, vertexingLxyzErr, float); //! +DECLARE_SOA_COLUMN(VertexingTauzErr, vertexingTauzErr, float); //! +DECLARE_SOA_COLUMN(VertexingLzProjected, vertexingLzProjected, float); //! +DECLARE_SOA_COLUMN(VertexingLxyProjected, vertexingLxyProjected, float); //! +DECLARE_SOA_COLUMN(VertexingLxyzProjected, vertexingLxyzProjected, float); //! +DECLARE_SOA_COLUMN(VertexingTauzProjected, vertexingTauzProjected, float); //! +DECLARE_SOA_COLUMN(VertexingTauxyProjected, vertexingTauxyProjected, float); //! } // namespace dileptonTrackTrackCandidate DECLARE_SOA_TABLE(DileptonTrackTrackCandidates, "AOD", "RTDQUADPLET", //! @@ -987,6 +1022,14 @@ DECLARE_SOA_TABLE(DileptonTrackTrackCandidates, "AOD", "RTDQUADPLET", //! dileptonTrackTrackCandidate::DileptonEta, dileptonTrackTrackCandidate::DileptonPhi, dileptonTrackTrackCandidate::DileptonSign, + dileptonTrackTrackCandidate::DileptonTPCnSigmaEl1, + dileptonTrackTrackCandidate::DileptonTPCnSigmaPi1, + dileptonTrackTrackCandidate::DileptonTPCnSigmaPr1, + dileptonTrackTrackCandidate::DileptonTPCnCls1, + dileptonTrackTrackCandidate::DileptonTPCnSigmaEl2, + dileptonTrackTrackCandidate::DileptonTPCnSigmaPi2, + dileptonTrackTrackCandidate::DileptonTPCnSigmaPr2, + dileptonTrackTrackCandidate::DileptonTPCnCls2, dileptonTrackTrackCandidate::DiTracksMass, dileptonTrackTrackCandidate::DiTracksPt, dileptonTrackTrackCandidate::TrackPt1, @@ -996,7 +1039,34 @@ DECLARE_SOA_TABLE(DileptonTrackTrackCandidates, "AOD", "RTDQUADPLET", //! dileptonTrackTrackCandidate::TrackPhi1, dileptonTrackTrackCandidate::TrackPhi2, dileptonTrackTrackCandidate::TrackSign1, - dileptonTrackTrackCandidate::TrackSign2); + dileptonTrackTrackCandidate::TrackSign2, + dileptonTrackTrackCandidate::TrackTPCNSigmaPi1, + dileptonTrackTrackCandidate::TrackTPCNSigmaPi2, + dileptonTrackTrackCandidate::TrackTPCNSigmaKa1, + dileptonTrackTrackCandidate::TrackTPCNSigmaKa2, + dileptonTrackTrackCandidate::TrackTPCNSigmaPr1, + dileptonTrackTrackCandidate::TrackTPCNSigmaPr2, + dileptonTrackTrackCandidate::TrackTPCNCls1, + dileptonTrackTrackCandidate::TrackTPCNCls2, + dileptonTrackTrackCandidate::KFMass, + dileptonTrackTrackCandidate::VertexingProcCode, + dileptonTrackTrackCandidate::VertexingChi2PCA, + dileptonTrackTrackCandidate::CosPointingAngle, + dileptonTrackTrackCandidate::KFDCAxyzBetweenProngs, + dileptonTrackTrackCandidate::KFChi2OverNDFGeo, + dileptonTrackTrackCandidate::VertexingLz, + dileptonTrackTrackCandidate::VertexingLxy, + dileptonTrackTrackCandidate::VertexingLxyz, + dileptonTrackTrackCandidate::VertexingTauz, + dileptonTrackTrackCandidate::VertexingTauxy, + dileptonTrackTrackCandidate::VertexingLzErr, + dileptonTrackTrackCandidate::VertexingLxyzErr, + dileptonTrackTrackCandidate::VertexingTauzErr, + dileptonTrackTrackCandidate::VertexingLzProjected, + dileptonTrackTrackCandidate::VertexingLxyProjected, + dileptonTrackTrackCandidate::VertexingLxyzProjected, + dileptonTrackTrackCandidate::VertexingTauzProjected, + dileptonTrackTrackCandidate::VertexingTauxyProjected); using DileptonTrackTrackCandidate = DileptonTrackTrackCandidates::iterator; diff --git a/PWGDQ/Tasks/dqEfficiency.cxx b/PWGDQ/Tasks/dqEfficiency.cxx index e898e4c4f19..29f7b79392b 100644 --- a/PWGDQ/Tasks/dqEfficiency.cxx +++ b/PWGDQ/Tasks/dqEfficiency.cxx @@ -308,8 +308,8 @@ struct AnalysisTrackSelection { fHistMan->FillHistClass(fHistNamesMCMatched[j][i].Data(), VarManager::fgValues); } } // end loop over cuts - } // end loop over MC signals - } // end loop over tracks + } // end loop over MC signals + } // end loop over tracks } void processSkimmed(MyEventsSelected::iterator const& event, MyBarrelTracks const& tracks, ReducedMCEvents const& eventsMC, ReducedMCTracks const& tracksMC) @@ -481,8 +481,8 @@ struct AnalysisMuonSelection { fHistMan->FillHistClass(fHistNamesMCMatched[j][i].Data(), VarManager::fgValues); } } // end loop over cuts - } // end loop over MC signals - } // end loop over muons + } // end loop over MC signals + } // end loop over muons } void processSkimmed(MyEventsSelected::iterator const& event, MyMuonTracks const& muons, ReducedMCEvents const& eventsMC, ReducedMCTracks const& tracksMC) @@ -622,8 +622,8 @@ struct AnalysisSameEventPairing { } fBarrelHistNamesMCmatched.push_back(mcSigClasses); } // end loop over cuts - } // end if(cutNames.IsNull()) - } // end if processBarrel + } // end if(cutNames.IsNull()) + } // end if processBarrel if (enableMuonHistos) { TString cutNames = fConfigMuonCuts.value; @@ -650,8 +650,8 @@ struct AnalysisSameEventPairing { } fMuonHistNamesMCmatched.push_back(mcSigClasses); } // end loop over cuts - } // end if(cutNames.IsNull()) - } // end if processMuon + } // end if(cutNames.IsNull()) + } // end if processMuon // NOTE: For the electron-muon pairing, the policy is that the user specifies n track and n muon cuts via configurables // So for each barrel cut there is a corresponding muon cut @@ -897,7 +897,7 @@ struct AnalysisSameEventPairing { } } } // end loop over barrel track pairs - } // end runPairing + } // end runPairing template void runMCGen(TTracksMC& groupedMCTracks) @@ -947,7 +947,7 @@ struct AnalysisSameEventPairing { } } } // end of true pairing loop - } // end runMCGen + } // end runMCGen // Preslice perReducedMcEvent = aod::reducedtrackMC::reducedMCeventId; PresliceUnsorted perReducedMcEvent = aod::reducedtrackMC::reducedMCeventId; @@ -1320,6 +1320,8 @@ struct AnalysisDileptonTrackTrack { Configurable fConfigMCRecSignals{"cfgBarrelMCRecSignals", "", "Comma separated list of MC signals (reconstructed)"}; Configurable fConfigMCGenSignals{"cfgBarrelMCGenSignals", "", "Comma separated list of MC signals (generated)"}; Configurable fConfigDileptonMCRecSignal{"cfgDileptonMCRecSignal", "", "Comma separated list of MC signals (reconstructed)"}; + Configurable fConfigUseKFVertexing{"cfgUseKFVertexing", false, "Use KF Particle for secondary vertex reconstruction (DCAFitter is used by default)"}; + Configurable fConfigUseDCAVertexing{"cfgUseDCAVertexing", false, "Use DCA for secondary vertex reconstruction (DCAFitter is used by default)"}; Produces DileptonTrackTrackTable; HistogramManager* fHistMan; @@ -1410,7 +1412,7 @@ struct AnalysisDileptonTrackTrack { if (sig->GetNProngs() == 4) { fRecMCSignals.push_back(*sig); fRecMCSignalsNames.push_back(sig->GetName()); - histNames += Form("MCTruthRecQaud_%s_%s;", fQuadrupletCutNames[icut].Data(), sig->GetName()); + histNames += Form("MCTruthRecQuad_%s_%s;", fQuadrupletCutNames[icut].Data(), sig->GetName()); } } } @@ -1426,7 +1428,7 @@ struct AnalysisDileptonTrackTrack { if (sig) { if (sig->GetNProngs() == 1) { // NOTE: 1-prong signals required fGenMCSignals.push_back(*sig); - histNames += Form("MCTruthGenQaud_%s;", sig->GetName()); // TODO: Add these names to a std::vector to avoid using Form in the process function + histNames += Form("MCTruthGenQuad_%s;", sig->GetName()); // TODO: Add these names to a std::vector to avoid using Form in the process function } } } @@ -1455,6 +1457,15 @@ struct AnalysisDileptonTrackTrack { VarManager::ResetValues(0, VarManager::kNVars, fValuesQuadruplet); VarManager::FillEvent(event, fValuesQuadruplet); + // set up KF or DCAfitter + if (fConfigUseDCAVertexing) { + VarManager::SetupTwoProngDCAFitter(5.0f, true, 200.0f, 4.0f, 1.0e-3f, 0.9f, false); // TODO: get these parameters from Configurables + // VarManager::SetupThreeProngDCAFitter(5.0f, true, 200.0f, 4.0f, 1.0e-3f, 0.9f, false); // TODO: get these parameters from Configurables + VarManager::SetupFourProngDCAFitter(5.0f, true, 200.0f, 4.0f, 1.0e-3f, 0.9f, false); // TODO: get these parameters from Configurables + } else if (fConfigUseKFVertexing) { + VarManager::SetupFourProngKFParticle(5.0f); + } + // LOGF(info, "Number of dileptons: %d", dileptons.size()); int indexOffset = -999; std::vector trackGlobalIndexes; @@ -1506,6 +1517,10 @@ struct AnalysisDileptonTrackTrack { // Fill the Histograms VarManager::FillDileptonTrackTrack(dilepton, t1, t2, fValuesQuadruplet); + // reconstruct the secondary vertex + if (fConfigUseDCAVertexing || fConfigUseKFVertexing) { + VarManager::FillDileptonTrackTrackVertexing(event, lepton1, lepton2, t1, t2, fValuesQuadruplet); + } uint32_t CutDecision = 0; uint32_t mcDecision = 0; int iCut = 0; @@ -1539,7 +1554,7 @@ struct AnalysisDileptonTrackTrack { } for (unsigned int isig = 0; isig < fRecMCSignals.size(); isig++) { if (mcDecision & (static_cast(1) << isig)) { - fHistMan->FillHistClass(Form("MCTruthRecQaud_%s_%s", fQuadrupletCutNames[iCut].Data(), fRecMCSignalsNames[isig].Data()), fValuesQuadruplet); + fHistMan->FillHistClass(Form("MCTruthRecQuad_%s_%s", fQuadrupletCutNames[iCut].Data(), fRecMCSignalsNames[isig].Data()), fValuesQuadruplet); } } } @@ -1554,7 +1569,12 @@ struct AnalysisDileptonTrackTrack { DileptonTrackTrackTable(fValuesQuadruplet[VarManager::kQuadMass], fValuesQuadruplet[VarManager::kQuadPt], fValuesQuadruplet[VarManager::kQuadEta], fValuesQuadruplet[VarManager::kQuadPhi], fValuesQuadruplet[VarManager::kRap], fValuesQuadruplet[VarManager::kQ], fValuesQuadruplet[VarManager::kDeltaR1], fValuesQuadruplet[VarManager::kDeltaR2], fValuesQuadruplet[VarManager::kDeltaR], dilepton.mass(), dilepton.pt(), dilepton.eta(), dilepton.phi(), dilepton.sign(), - fValuesQuadruplet[VarManager::kDitrackMass], fValuesQuadruplet[VarManager::kDitrackPt], t1.pt(), t2.pt(), t1.eta(), t2.eta(), t1.phi(), t2.phi(), t1.sign(), t2.sign()); + lepton1.tpcNSigmaEl(), lepton1.tpcNSigmaPi(), lepton1.tpcNSigmaPr(), lepton1.tpcNClsFound(), + lepton2.tpcNSigmaEl(), lepton2.tpcNSigmaPi(), lepton2.tpcNSigmaPr(), lepton2.tpcNClsFound(), + fValuesQuadruplet[VarManager::kDitrackMass], fValuesQuadruplet[VarManager::kDitrackPt], t1.pt(), t2.pt(), t1.eta(), t2.eta(), t1.phi(), t2.phi(), t1.sign(), t2.sign(), t1.tpcNSigmaPi(), t2.tpcNSigmaPi(), t1.tpcNSigmaKa(), t2.tpcNSigmaKa(), t1.tpcNSigmaPr(), t1.tpcNSigmaPr(), t1.tpcNClsFound(), t2.tpcNClsFound(), + fValuesQuadruplet[VarManager::kKFMass], fValuesQuadruplet[VarManager::kVertexingProcCode], fValuesQuadruplet[VarManager::kVertexingChi2PCA], fValuesQuadruplet[VarManager::kCosPointingAngle], fValuesQuadruplet[VarManager::kKFDCAxyzBetweenProngs], fValuesQuadruplet[VarManager::kKFChi2OverNDFGeo], + fValuesQuadruplet[VarManager::kVertexingLz], fValuesQuadruplet[VarManager::kVertexingLxy], fValuesQuadruplet[VarManager::kVertexingLxyz], fValuesQuadruplet[VarManager::kVertexingTauz], fValuesQuadruplet[VarManager::kVertexingTauxy], fValuesQuadruplet[VarManager::kVertexingLzErr], fValuesQuadruplet[VarManager::kVertexingLxyzErr], + fValuesQuadruplet[VarManager::kVertexingTauzErr], fValuesQuadruplet[VarManager::kVertexingLzProjected], fValuesQuadruplet[VarManager::kVertexingLxyProjected], fValuesQuadruplet[VarManager::kVertexingLxyzProjected], fValuesQuadruplet[VarManager::kVertexingTauzProjected], fValuesQuadruplet[VarManager::kVertexingTauxyProjected]); } // end loop over track - track combinations } // end loop over dileptons }; @@ -1574,9 +1594,9 @@ struct AnalysisDileptonTrackTrack { auto dilepton = mcTracks.rawIteratorAt(daughterIdFirst); auto track1 = mcTracks.rawIteratorAt(daughterIdFirst + 1); auto track2 = mcTracks.rawIteratorAt(daughterIdFirst + 2); - VarManager::FillQaudMC(dilepton, track1, track2); + VarManager::FillQuadMC(dilepton, track1, track2); } - fHistMan->FillHistClass(Form("MCTruthGenQaud_%s", sig.GetName()), VarManager::fgValues); + fHistMan->FillHistClass(Form("MCTruthGenQuad_%s", sig.GetName()), VarManager::fgValues); } } } @@ -1654,7 +1674,7 @@ void DefineHistograms(HistogramManager* histMan, TString histClasses) // histMan->AddHistogram(objArray->At(iclass)->GetName(), "Rapidity", "MC generator y distribution", false, 150, 2.5, 4.0, VarManager::kMCY); histMan->AddHistogram(objArray->At(iclass)->GetName(), "Phi", "MC generator #varphi distribution", false, 50, 0.0, 2. * TMath::Pi(), VarManager::kMCPhi); } - if (classStr.Contains("MCTruthGenQaud")) { + if (classStr.Contains("MCTruthGenQuad")) { dqhistograms::DefineHistograms(histMan, objArray->At(iclass)->GetName(), "mctruth_quad"); } if (classStr.Contains("MCTruthGen")) { @@ -1673,7 +1693,7 @@ void DefineHistograms(HistogramManager* histMan, TString histClasses) if (classStr.Contains("DileptonTrackInvMass")) { dqhistograms::DefineHistograms(histMan, objArray->At(iclass)->GetName(), "dilepton-hadron-mass"); } - if (classStr.Contains("Quadruplet") || classStr.Contains("MCTruthRecQaud")) { + if (classStr.Contains("Quadruplet") || classStr.Contains("MCTruthRecQuad")) { dqhistograms::DefineHistograms(histMan, objArray->At(iclass)->GetName(), "dilepton-dihadron", "xtojpsipipi"); } diff --git a/PWGDQ/Tasks/tableReader.cxx b/PWGDQ/Tasks/tableReader.cxx index eb5d6dae897..b57feaa8afc 100644 --- a/PWGDQ/Tasks/tableReader.cxx +++ b/PWGDQ/Tasks/tableReader.cxx @@ -1959,6 +1959,8 @@ struct AnalysisDileptonTrackTrack { Configurable fConfigQuadrupletCuts{"cfgQuadrupletCuts", "pairX3872Cut1", "Comma separated list of Dilepton-Track-Track cut"}; Configurable fConfigAddDileptonHistogram{"cfgAddDileptonHistogram", "barrel", "Comma separated list of histograms"}; Configurable fConfigAddQuadrupletHistogram{"cfgAddQuadrupletHistogram", "xtojpsipipi", "Comma separated list of histograms"}; + Configurable fConfigUseKFVertexing{"cfgUseKFVertexing", false, "Use KF Particle for secondary vertex reconstruction (DCAFitter is used by default)"}; + Configurable fConfigUseDCAVertexing{"cfgUseDCAVertexing", false, "Use DCA for secondary vertex reconstruction (DCAFitter is used by default)"}; Produces DileptonTrackTrackTable; @@ -1969,7 +1971,6 @@ struct AnalysisDileptonTrackTrack { constexpr static uint32_t fgDileptonFillMap = VarManager::ObjTypes::ReducedTrack | VarManager::ObjTypes::Pair; // fill map // use some values array to avoid mixing up the quantities - float* fValuesDitrack; float* fValuesQuadruplet; HistogramManager* fHistMan; @@ -2010,7 +2011,7 @@ struct AnalysisDileptonTrackTrack { } if (!context.mOptions.get("processDummy")) { - DefineHistograms(fHistMan, Form("Dileptons_%s", configDileptonCutNamesStr.Data()), fConfigAddDileptonHistogram); + DefineHistograms(fHistMan, Form("Pairs_%s", configDileptonCutNamesStr.Data()), fConfigAddDileptonHistogram); if (!configQuadruletCutNamesStr.IsNull()) { for (std::size_t icut = 0; icut < fQuadrupletCutNames.size(); ++icut) { if (fIsSameTrackCut) { @@ -2037,6 +2038,25 @@ struct AnalysisDileptonTrackTrack { // LOGF(info, "Number of dileptons: %d", dileptons.size()); + // set up KF or DCAfitter + if (fConfigUseDCAVertexing) { + VarManager::SetupTwoProngDCAFitter(5.0f, true, 200.0f, 4.0f, 1.0e-3f, 0.9f, false); // TODO: get these parameters from Configurables + // VarManager::SetupThreeProngDCAFitter(5.0f, true, 200.0f, 4.0f, 1.0e-3f, 0.9f, false); // TODO: get these parameters from Configurables + VarManager::SetupFourProngDCAFitter(5.0f, true, 200.0f, 4.0f, 1.0e-3f, 0.9f, false); // TODO: get these parameters from Configurables + } else if (fConfigUseKFVertexing) { + VarManager::SetupFourProngKFParticle(5.0f); + } + + int indexOffset = -999; + std::vector trackGlobalIndexes; + + if (dileptons.size() > 0) { + for (auto track : tracks) { + trackGlobalIndexes.push_back(track.globalIndex()); + // std::cout << track.index() << " " << track.globalIndex() << std::endl; + } + } + // loop over dileptons for (auto dilepton : dileptons) { VarManager::FillTrack(dilepton, fValuesQuadruplet); @@ -2045,12 +2065,20 @@ struct AnalysisDileptonTrackTrack { if (!fDileptonCut.IsSelected(fValuesQuadruplet)) continue; - fHistMan->FillHistClass(Form("Dileptons_%s", fDileptonCut.GetName()), fValuesQuadruplet); + fHistMan->FillHistClass(Form("Pairs_%s", fDileptonCut.GetName()), fValuesQuadruplet); // get the index of the electron legs int indexLepton1 = dilepton.index0Id(); int indexLepton2 = dilepton.index1Id(); + if (indexOffset == -999) { + indexOffset = trackGlobalIndexes.at(0); + } + trackGlobalIndexes.clear(); + + auto lepton1 = tracks.iteratorAt(indexLepton1 - indexOffset); + auto lepton2 = tracks.iteratorAt(indexLepton2 - indexOffset); + // loop over hadrons pairs for (auto& [t1, t2] : combinations(tracks, tracks)) { // avoid self-combinations @@ -2070,6 +2098,10 @@ struct AnalysisDileptonTrackTrack { // fill variables VarManager::FillDileptonTrackTrack(dilepton, t1, t2, fValuesQuadruplet); + // reconstruct the secondary vertex + if (fConfigUseDCAVertexing || fConfigUseKFVertexing) { + VarManager::FillDileptonTrackTrackVertexing(event, lepton1, lepton2, t1, t2, fValuesQuadruplet); + } int iCut = 0; uint32_t CutDecision = 0; @@ -2102,22 +2134,33 @@ struct AnalysisDileptonTrackTrack { DileptonTrackTrackTable(fValuesQuadruplet[VarManager::kQuadMass], fValuesQuadruplet[VarManager::kQuadPt], fValuesQuadruplet[VarManager::kQuadEta], fValuesQuadruplet[VarManager::kQuadPhi], fValuesQuadruplet[VarManager::kRap], fValuesQuadruplet[VarManager::kQ], fValuesQuadruplet[VarManager::kDeltaR1], fValuesQuadruplet[VarManager::kDeltaR2], fValuesQuadruplet[VarManager::kDeltaR], dilepton.mass(), dilepton.pt(), dilepton.eta(), dilepton.phi(), dilepton.sign(), - fValuesQuadruplet[VarManager::kDitrackMass], fValuesQuadruplet[VarManager::kDitrackPt], t1.pt(), t2.pt(), t1.eta(), t2.eta(), t1.phi(), t2.phi(), t1.sign(), t2.sign()); + lepton1.tpcNSigmaEl(), lepton1.tpcNSigmaPi(), lepton1.tpcNSigmaPr(), lepton1.tpcNClsFound(), + lepton2.tpcNSigmaEl(), lepton2.tpcNSigmaPi(), lepton2.tpcNSigmaPr(), lepton2.tpcNClsFound(), + fValuesQuadruplet[VarManager::kDitrackMass], fValuesQuadruplet[VarManager::kDitrackPt], t1.pt(), t2.pt(), t1.eta(), t2.eta(), t1.phi(), t2.phi(), t1.sign(), t2.sign(), t1.tpcNSigmaPi(), t2.tpcNSigmaPi(), t1.tpcNSigmaKa(), t2.tpcNSigmaKa(), t1.tpcNSigmaPr(), t1.tpcNSigmaPr(), t1.tpcNClsFound(), t2.tpcNClsFound(), + fValuesQuadruplet[VarManager::kKFMass], fValuesQuadruplet[VarManager::kVertexingProcCode], fValuesQuadruplet[VarManager::kVertexingChi2PCA], fValuesQuadruplet[VarManager::kCosPointingAngle], fValuesQuadruplet[VarManager::kKFDCAxyzBetweenProngs], fValuesQuadruplet[VarManager::kKFChi2OverNDFGeo], + fValuesQuadruplet[VarManager::kVertexingLz], fValuesQuadruplet[VarManager::kVertexingLxy], fValuesQuadruplet[VarManager::kVertexingLxyz], fValuesQuadruplet[VarManager::kVertexingTauz], fValuesQuadruplet[VarManager::kVertexingTauxy], fValuesQuadruplet[VarManager::kVertexingLzErr], fValuesQuadruplet[VarManager::kVertexingLxyzErr], + fValuesQuadruplet[VarManager::kVertexingTauzErr], fValuesQuadruplet[VarManager::kVertexingLzProjected], fValuesQuadruplet[VarManager::kVertexingLxyProjected], fValuesQuadruplet[VarManager::kVertexingLxyzProjected], fValuesQuadruplet[VarManager::kVertexingTauzProjected], fValuesQuadruplet[VarManager::kVertexingTauxyProjected]); } // end loop over track-track pairs } // end loop over dileptons } - void processJpsiPiPi(soa::Filtered::iterator const& event, MyBarrelTracksSelectedWithCov const& tracks, soa::Filtered const& dileptons) + void processChicToJpsiPiPi(soa::Filtered::iterator const& event, MyBarrelTracksSelectedWithCov const& tracks, soa::Filtered const& dileptons) { runDileptonTrackTrack(event, tracks, dileptons); } + void processPsi2SToJpsiPiPi(soa::Filtered::iterator const& event, MyBarrelTracksSelectedWithCov const& tracks, soa::Filtered const& dileptons) + { + runDileptonTrackTrack(event, tracks, dileptons); + } + void processDummy(MyEvents&) { // do nothing } - PROCESS_SWITCH(AnalysisDileptonTrackTrack, processJpsiPiPi, "Run dilepton-dihadron pairing to study X(3872), using skimmed data", false); + PROCESS_SWITCH(AnalysisDileptonTrackTrack, processChicToJpsiPiPi, "Run dilepton-dihadron pairing to study X(3872), using skimmed data", false); + PROCESS_SWITCH(AnalysisDileptonTrackTrack, processPsi2SToJpsiPiPi, "Run dilepton-dihadron pairing to study Psi(2S), using skimmed data", false); PROCESS_SWITCH(AnalysisDileptonTrackTrack, processDummy, "Dummy function", false); }; diff --git a/PWGDQ/Tasks/tableReader_withAssoc.cxx b/PWGDQ/Tasks/tableReader_withAssoc.cxx index c17a0b3d24c..4fcb823cce5 100644 --- a/PWGDQ/Tasks/tableReader_withAssoc.cxx +++ b/PWGDQ/Tasks/tableReader_withAssoc.cxx @@ -2456,7 +2456,7 @@ struct AnalysisAsymmetricPairing { VarManager::SetupMatLUTFwdDCAFitter(fLUT); dqhistograms::AddHistogramsFromJSON(fHistMan, fConfigAddJSONHistograms.value.c_str()); // ad-hoc histograms via JSON - VarManager::SetUseVars(fHistMan->GetUsedVars()); // provide the list of required variables so that VarManager knows what to fill + VarManager::SetUseVars(fHistMan->GetUsedVars()); // provide the list of required variables so that VarManager knows what to fill fOutputList.setObject(fHistMan->GetMainHistogramList()); LOG(info) << "Initialization of AnalysisAsymmetricPairing finished (idstoreh)"; } @@ -2910,7 +2910,7 @@ struct AnalysisDileptonTrack { int fCurrentRun; // needed to detect if the run changed and trigger update of calibrations etc. int fNCuts; // number of dilepton leg cuts int fNLegCuts; - int fNPairCuts; // number of pair cuts + int fNPairCuts; // number of pair cuts int fNCommonTrackCuts; std::map fCommonTrackCutMap; uint32_t fTrackCutBitMap; // track cut bit mask to be used in the selection of tracks associated with dileptons @@ -3528,6 +3528,257 @@ struct AnalysisDileptonTrack { PROCESS_SWITCH(AnalysisDileptonTrack, processDummy, "Dummy function", false); }; +struct AnalysisDileptonTrackTrack { + OutputObj fOutputList{"output"}; + + Configurable fConfigTrackCut1{"cfgTrackCut1", "pionPIDCut1", "track1 cut"}; // used for select the tracks from SelectedTracks + Configurable fConfigTrackCut2{"cfgTrackCut2", "pionPIDCut2", "track2 cut"}; // used for select the tracks from SelectedTracks + Configurable fConfigDileptonCut{"cfgDiLeptonCut", "pairJpsi2", "Dilepton cut"}; + Configurable fConfigQuadrupletCuts{"cfgQuadrupletCuts", "pairX3872Cut1", "Comma separated list of Dilepton-Track-Track cut"}; + Configurable fConfigAddDileptonHistogram{"cfgAddDileptonHistogram", "barrel", "Comma separated list of histograms"}; + Configurable fConfigAddQuadrupletHistogram{"cfgAddQuadrupletHistogram", "xtojpsipipi", "Comma separated list of histograms"}; + + Configurable fConfigSetupFourProngFitter{"cfgSetupFourProngFitter", false, "Use DCA for secondary vertex reconstruction (DCAFitter is used by default)"}; + Configurable fConfigUseKFVertexing{"cfgUseKFVertexing", false, "Use KF Particle for secondary vertex reconstruction (DCAFitter is used by default)"}; + Configurable fConfigUseRemoteField{"cfgUseRemoteField", false, "Chose whether to fetch the magnetic field from ccdb or set it manually"}; + Configurable fConfigGRPmagPath{"cfgGrpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; + Configurable fConfigMagField{"cfgMagField", 5.0f, "Manually set magnetic field"}; + + Produces DileptonTrackTrackTable; + + int fCurrentRun; // needed to detect if the run changed and trigger update of calibrations etc. + // uint32_t fTrackCutBitMap; // track cut bit mask to be used in the selection of tracks associated with dileptons + // cut name setting + TString fTrackCutName1; + TString fTrackCutName2; + bool fIsSameTrackCut = false; + AnalysisCompositeCut fDileptonCut; + std::vector fQuadrupletCutNames; + std::vector fQuadrupletCuts; + + Service fCCDB; + + Filter eventFilter = aod::dqanalysisflags::isEventSelected > static_cast(0); + Filter dileptonFilter = aod::reducedpair::sign == 0; + Filter filterBarrelTrackSelected = aod::dqanalysisflags::isBarrelSelected > static_cast(0); + + constexpr static uint32_t fgDileptonFillMap = VarManager::ObjTypes::ReducedTrack | VarManager::ObjTypes::Pair; // fill map + + // use some values array to avoid mixing up the quantities + float* fValuesQuadruplet; + HistogramManager* fHistMan; + + void init(o2::framework::InitContext& context) + { + // bool isBarrel = context.mOptions.get("processJpsiPiPi"); + + if (context.mOptions.get("processDummy")) { + return; + } + + fCurrentRun = 0; + + fValuesQuadruplet = new float[VarManager::kNVars]; + VarManager::SetDefaultVarNames(); + fHistMan = new HistogramManager("analysisHistos", "aa", VarManager::kNVars); + fHistMan->SetUseDefaultVariableNames(kTRUE); + fHistMan->SetDefaultVarNames(VarManager::fgVariableNames, VarManager::fgVariableUnits); + + // define cuts + fTrackCutName1 = fConfigTrackCut1.value; + fTrackCutName2 = fConfigTrackCut2.value; + if (fTrackCutName1 == fTrackCutName2) { + fIsSameTrackCut = true; + } + TString configDileptonCutNamesStr = fConfigDileptonCut.value; + fDileptonCut = *dqcuts::GetCompositeCut(configDileptonCutNamesStr.Data()); + TString configQuadruletCutNamesStr = fConfigQuadrupletCuts.value; + std::unique_ptr objArray(configQuadruletCutNamesStr.Tokenize(",")); + for (Int_t icut = 0; icut < objArray->GetEntries(); ++icut) { + TString cutName = objArray->At(icut)->GetName(); + fQuadrupletCutNames.push_back(cutName); + fQuadrupletCuts.push_back(*dqcuts::GetCompositeCut(cutName.Data())); + } + + if (!context.mOptions.get("processDummy")) { + DefineHistograms(fHistMan, Form("Pairs_%s", configDileptonCutNamesStr.Data()), fConfigAddDileptonHistogram.value.data()); + if (!configQuadruletCutNamesStr.IsNull()) { + for (std::size_t icut = 0; icut < fQuadrupletCutNames.size(); ++icut) { + if (fIsSameTrackCut) { + DefineHistograms(fHistMan, Form("QuadrupletSEPM_%s", fQuadrupletCutNames[icut].Data()), fConfigAddQuadrupletHistogram.value.data()); + } else { + DefineHistograms(fHistMan, Form("QuadrupletSEPM_%s", fQuadrupletCutNames[icut].Data()), fConfigAddQuadrupletHistogram.value.data()); + DefineHistograms(fHistMan, Form("QuadrupletSEMP_%s", fQuadrupletCutNames[icut].Data()), fConfigAddQuadrupletHistogram.value.data()); + } + DefineHistograms(fHistMan, Form("QuadrupletSEPP_%s", fQuadrupletCutNames[icut].Data()), fConfigAddQuadrupletHistogram.value.data()); + DefineHistograms(fHistMan, Form("QuadrupletSEMM_%s", fQuadrupletCutNames[icut].Data()), fConfigAddQuadrupletHistogram.value.data()); + } + } + } + + VarManager::SetUseVars(fHistMan->GetUsedVars()); + fOutputList.setObject(fHistMan->GetMainHistogramList()); + } + + // init parameters from CCDB + void initParamsFromCCDB(uint64_t timestamp) + { + if (fConfigUseRemoteField.value) { + o2::parameters::GRPMagField* grpmag = fCCDB->getForTimeStamp(fConfigGRPmagPath.value, timestamp); + float magField = 0.0; + if (grpmag != nullptr) { + magField = grpmag->getNominalL3Field(); + } else { + LOGF(fatal, "GRP object is not available in CCDB at timestamp=%llu", timestamp); + } + if (fConfigUseKFVertexing.value) { + VarManager::SetupTwoProngKFParticle(magField); + VarManager::SetupFourProngKFParticle(magField); + } else if (fConfigSetupFourProngFitter.value) { + VarManager::SetupTwoProngDCAFitter(magField, true, 200.0f, 4.0f, 1.0e-3f, 0.9f, false); // TODO: get these parameters from Configurables + VarManager::SetupFourProngDCAFitter(magField, true, 200.0f, 4.0f, 1.0e-3f, 0.9f, false); // TODO: get these parameters from Configurables + } + } else { + if (fConfigUseKFVertexing.value) { + VarManager::SetupTwoProngKFParticle(fConfigMagField.value); + VarManager::SetupFourProngKFParticle(fConfigMagField.value); + } else if (fConfigSetupFourProngFitter.value) { + LOGP(info, "Setting up DCA fitter for two and four prong candidates"); + VarManager::SetupTwoProngDCAFitter(fConfigMagField.value, true, 200.0f, 4.0f, 1.0e-3f, 0.9f, false); // TODO: get these parameters from Configurables + VarManager::SetupFourProngDCAFitter(fConfigMagField.value, true, 200.0f, 4.0f, 1.0e-3f, 0.9f, false); // TODO: get these parameters from Configurables + } + } + } + + // Template function to run pair - hadron combinations + template + void runDileptonTrackTrack(TEvent const& event, TTrackAssocs const& assocs, TTracks const& tracks, TDileptons const& dileptons) + { + VarManager::ResetValues(0, VarManager::kNVars, fValuesQuadruplet); + VarManager::FillEvent(event, fValuesQuadruplet); + // int indexOffset = -999; + // std::vector trackGlobalIndexes; + + for (auto dilepton : dileptons) { + // get full track info of tracks based on the index + + int indexLepton1 = dilepton.index0Id(); + int indexLepton2 = dilepton.index1Id(); + auto lepton1 = tracks.rawIteratorAt(dilepton.index0Id()); + auto lepton2 = tracks.rawIteratorAt(dilepton.index1Id()); + // Check that the dilepton has zero charge + if (dilepton.sign() != 0) { + continue; + } + VarManager::FillTrack(dilepton, fValuesQuadruplet); + // LOGP(info, "is dilepton selected: {}", fDileptonCut.IsSelected(fValuesQuadruplet)); + + // apply the dilepton cut + if (!fDileptonCut.IsSelected(fValuesQuadruplet)) + continue; + + fHistMan->FillHistClass(Form("Pairs_%s", fDileptonCut.GetName()), fValuesQuadruplet); + + // loop over hadrons pairs + for (auto& [a1, a2] : o2::soa::combinations(assocs, assocs)) { + uint32_t trackSelection = 0; + if (fIsSameTrackCut) { + trackSelection = ((a1.isBarrelSelected_raw() & (static_cast(1) << 1)) || (a2.isBarrelSelected_raw() & (static_cast(1) << 1))); + } else { + trackSelection = ((a1.isBarrelSelected_raw() & (static_cast(1) << 1)) && (a2.isBarrelSelected_raw() & (static_cast(1) << 2))); + } + // LOGP(info, "trackSelection: {}, a1: {}, a2: {}", trackSelection, a1.isBarrelSelected_raw(), a2.isBarrelSelected_raw()); + if (!trackSelection) { + continue; + } + + // get the track from this association + auto track1 = a1.template reducedtrack_as(); + auto track2 = a2.template reducedtrack_as(); + // avoid self combinations + if (track1.globalIndex() == indexLepton1 || track1.globalIndex() == indexLepton2 || track2.globalIndex() == indexLepton1 || track2.globalIndex() == indexLepton2) { + continue; + } + + // fill variables + VarManager::FillDileptonTrackTrack(dilepton, track1, track2, fValuesQuadruplet); + if (fConfigSetupFourProngFitter || fConfigUseKFVertexing) { + // LOGP(info, "Using KF or DCA fitter for secondary vertexing"); + VarManager::FillDileptonTrackTrackVertexing(event, lepton1, lepton2, track1, track2, fValuesQuadruplet); + } + + int iCut = 0; + uint32_t CutDecision = 0; + for (auto cutname = fQuadrupletCutNames.begin(); cutname != fQuadrupletCutNames.end(); cutname++, iCut++) { + // apply dilepton-track-track cut + if (fQuadrupletCuts[iCut].IsSelected(fValuesQuadruplet)) { + CutDecision |= (1 << iCut); + if (fIsSameTrackCut) { + if (track1.sign() * track2.sign() < 0) { + fHistMan->FillHistClass(Form("QuadrupletSEPM_%s", fQuadrupletCutNames[iCut].Data()), fValuesQuadruplet); + } + } else { + if ((track1.sign() < 0) && (track2.sign() > 0)) { + fHistMan->FillHistClass(Form("QuadrupletSEMP_%s", fQuadrupletCutNames[iCut].Data()), fValuesQuadruplet); + } else if ((track1.sign() > 0) && (track2.sign() < 0)) { + fHistMan->FillHistClass(Form("QuadrupletSEPM_%s", fQuadrupletCutNames[iCut].Data()), fValuesQuadruplet); + } + } + if ((track1.sign() > 0) && (track2.sign() > 0)) { + fHistMan->FillHistClass(Form("QuadrupletSEPP_%s", fQuadrupletCutNames[iCut].Data()), fValuesQuadruplet); + } else if ((track1.sign() < 0) && (track2.sign() < 0)) { + fHistMan->FillHistClass(Form("QuadrupletSEMM_%s", fQuadrupletCutNames[iCut].Data()), fValuesQuadruplet); + } + } + } // loop over dilepton-track-track cuts + + // fill table + if (!CutDecision) + continue; + DileptonTrackTrackTable(fValuesQuadruplet[VarManager::kQuadMass], fValuesQuadruplet[VarManager::kQuadPt], fValuesQuadruplet[VarManager::kQuadEta], fValuesQuadruplet[VarManager::kQuadPhi], fValuesQuadruplet[VarManager::kRap], + fValuesQuadruplet[VarManager::kQ], fValuesQuadruplet[VarManager::kDeltaR1], fValuesQuadruplet[VarManager::kDeltaR2], fValuesQuadruplet[VarManager::kDeltaR], + dilepton.mass(), dilepton.pt(), dilepton.eta(), dilepton.phi(), dilepton.sign(), + lepton1.tpcNSigmaEl(), lepton1.tpcNSigmaPi(), lepton1.tpcNSigmaPr(), lepton1.tpcNClsFound(), + lepton2.tpcNSigmaEl(), lepton2.tpcNSigmaPi(), lepton2.tpcNSigmaPr(), lepton2.tpcNClsFound(), + fValuesQuadruplet[VarManager::kDitrackMass], fValuesQuadruplet[VarManager::kDitrackPt], track1.pt(), track2.pt(), track1.eta(), track2.eta(), track1.phi(), track2.phi(), track1.sign(), track2.sign(), track1.tpcNSigmaPi(), track2.tpcNSigmaPi(), track1.tpcNSigmaKa(), track2.tpcNSigmaKa(), track1.tpcNSigmaPr(), track1.tpcNSigmaPr(), track1.tpcNClsFound(), track2.tpcNClsFound(), + fValuesQuadruplet[VarManager::kKFMass], fValuesQuadruplet[VarManager::kVertexingProcCode], fValuesQuadruplet[VarManager::kVertexingChi2PCA], fValuesQuadruplet[VarManager::kCosPointingAngle], fValuesQuadruplet[VarManager::kKFDCAxyzBetweenProngs], fValuesQuadruplet[VarManager::kKFChi2OverNDFGeo], + fValuesQuadruplet[VarManager::kVertexingLz], fValuesQuadruplet[VarManager::kVertexingLxy], fValuesQuadruplet[VarManager::kVertexingLxyz], fValuesQuadruplet[VarManager::kVertexingTauz], fValuesQuadruplet[VarManager::kVertexingTauxy], fValuesQuadruplet[VarManager::kVertexingLzErr], fValuesQuadruplet[VarManager::kVertexingLxyzErr], + fValuesQuadruplet[VarManager::kVertexingTauzErr], fValuesQuadruplet[VarManager::kVertexingLzProjected], fValuesQuadruplet[VarManager::kVertexingLxyProjected], fValuesQuadruplet[VarManager::kVertexingLxyzProjected], fValuesQuadruplet[VarManager::kVertexingTauzProjected], fValuesQuadruplet[VarManager::kVertexingTauxyProjected]); + } + } + } + + Preslice trackAssocsPerCollision = aod::reducedtrack_association::reducedeventId; + Preslice dielectronsPerCollision = aod::reducedpair::reducedeventId; + Preslice ditracksPerCollision = aod::reducedpair::reducedeventId; + + void processJpsiPiPi(soa::Filtered const& events, + soa::Filtered> const& assocs, + MyBarrelTracksWithCov const& tracks, soa::Filtered const& dileptons) + { + if (events.size() == 0) { + return; + } + if (fCurrentRun != events.begin().runNumber()) { // start: runNumber + initParamsFromCCDB(events.begin().timestamp()); + fCurrentRun = events.begin().runNumber(); + } // end: runNumber + for (auto& event : events) { + auto groupedBarrelAssocs = assocs.sliceBy(trackAssocsPerCollision, event.globalIndex()); + auto groupedDielectrons = dileptons.sliceBy(dielectronsPerCollision, event.globalIndex()); + runDileptonTrackTrack(event, groupedBarrelAssocs, tracks, groupedDielectrons); + } + } + + void processDummy(MyEvents&) + { + // do nothing + } + + PROCESS_SWITCH(AnalysisDileptonTrackTrack, processJpsiPiPi, "Run barrel pairing of J/psi with pion candidate", true); + PROCESS_SWITCH(AnalysisDileptonTrackTrack, processDummy, "Dummy function", false); +}; + WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{ @@ -3537,7 +3788,8 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) adaptAnalysisTask(cfgc), adaptAnalysisTask(cfgc), adaptAnalysisTask(cfgc), - adaptAnalysisTask(cfgc)}; + adaptAnalysisTask(cfgc), + adaptAnalysisTask(cfgc)}; } void DefineHistograms(HistogramManager* histMan, TString histClasses, const char* histGroups) @@ -3614,5 +3866,9 @@ void DefineHistograms(HistogramManager* histMan, TString histClasses, const char if (classStr.Contains("DileptonHadronCorrelation")) { dqhistograms::DefineHistograms(histMan, objArray->At(iclass)->GetName(), "dilepton-hadron-correlation"); } + + if (classStr.Contains("Quadruplet")) { + dqhistograms::DefineHistograms(histMan, objArray->At(iclass)->GetName(), "dilepton-dihadron", histName); + } } // end loop over histogram classes } diff --git a/git b/git new file mode 100644 index 00000000000..e69de29bb2d From 6dd98540c28f0b22a670faaa3ebaf0c3f1263506 Mon Sep 17 00:00:00 2001 From: Luca Barioglio Date: Mon, 16 Jun 2025 15:07:00 +0200 Subject: [PATCH 091/871] [PWGLF] Generalise epvector.cxx to higher harmonics (#11543) --- PWGLF/TableProducer/Common/epvector.cxx | 104 ++++++++++++------------ 1 file changed, 53 insertions(+), 51 deletions(-) diff --git a/PWGLF/TableProducer/Common/epvector.cxx b/PWGLF/TableProducer/Common/epvector.cxx index 8d57d3711fd..a662b20bd0b 100644 --- a/PWGLF/TableProducer/Common/epvector.cxx +++ b/PWGLF/TableProducer/Common/epvector.cxx @@ -93,6 +93,7 @@ struct epvector { Configurable cfgCutDCAz{"cfgCutDCAz", 2.0f, "DCAz range for tracks"}; Configurable cfgITScluster{"cfgITScluster", 4, "Number of ITS cluster"}; // Configurable cfgTPCcluster{"cfgTPCcluster", 70, "Number of TPC cluster"}; + Configurable cfgHarmonic{"cfgHarmonic", 2, "Harmonic for event plane calculation"}; Configurable useGainCallib{"useGainCallib", true, "use gain calibration"}; Configurable useRecentere{"useRecentere", true, "use Recentering"}; Configurable useShift{"useShift", false, "use Shift"}; @@ -228,26 +229,28 @@ struct epvector { return TMath::ATan2(chPos.Y() + offsetY, chPos.X() + offsetX); } - double GetPhiInRange(double phi) + double GetPhiInRange(double phi, double harmonic = 2) { double result = phi; + double period = 2. * TMath::Pi() / harmonic; while (result < 0) { - result = result + 2. * TMath::Pi() / 2; + result = result + period; } - while (result > 2. * TMath::Pi() / 2) { - result = result - 2. * TMath::Pi() / 2; + while (result > period) { + result = result - period; } return result; } - double GetDeltaPsiSubInRange(double psi1, double psi2) + double GetDeltaPsiSubInRange(double psi1, double psi2, double harmonic = 2) { double delta = psi1 - psi2; - if (TMath::Abs(delta) > TMath::Pi() / 2) { + double period = TMath::Pi() / harmonic; + if (TMath::Abs(delta) > period) { if (delta > 0.) - delta -= 2. * TMath::Pi() / 2; + delta -= 2. * period; else - delta += 2. * TMath::Pi() / 2; + delta += 2. * period; } return delta; } @@ -320,12 +323,11 @@ struct epvector { float ampl = gainequal * ft0.amplitudeA()[iChA]; histos.fill(HIST("FT0Amp"), chanelid, ampl); auto phiA = GetPhiFT0(chanelid, offsetFT0Ax, offsetFT0Ay); - qxFT0A = qxFT0A + ampl * TMath::Cos(2.0 * phiA); - qyFT0A = qyFT0A + ampl * TMath::Sin(2.0 * phiA); + qxFT0A = qxFT0A + ampl * TMath::Cos(cfgHarmonic.value * phiA); + qyFT0A = qyFT0A + ampl * TMath::Sin(cfgHarmonic.value * phiA); } for (std::size_t iChC = 0; iChC < ft0.channelC().size(); iChC++) { auto chanelid = ft0.channelC()[iChC] + 96; - // printf("Offset for FT0A: x = %d y = %d\n", chanelid, chanelid-96); auto gainequal = 1.0; if (useGainCallib) { gainequal = 1 / gainprofile->GetBinContent(gainprofile->FindBin(chanelid)); @@ -333,23 +335,23 @@ struct epvector { float ampl = gainequal * ft0.amplitudeC()[iChC]; histos.fill(HIST("FT0Amp"), chanelid, ampl); auto phiC = GetPhiFT0(chanelid, offsetFT0Cx, offsetFT0Cy); - qxFT0C = qxFT0C + ampl * TMath::Cos(2.0 * phiC); - qyFT0C = qyFT0C + ampl * TMath::Sin(2.0 * phiC); + qxFT0C = qxFT0C + ampl * TMath::Cos(cfgHarmonic.value * phiC); + qyFT0C = qyFT0C + ampl * TMath::Sin(cfgHarmonic.value * phiC); } for (auto& trk : tracks) { if (!selectionTrack(trk) || TMath::Abs(trk.eta()) > 0.8 || trk.pt() > cfgCutPTMax || TMath::Abs(trk.eta()) < cfgMinEta) { continue; } - qxTPC = qxTPC + trk.pt() * TMath::Cos(2.0 * trk.phi()); - qyTPC = qyTPC + trk.pt() * TMath::Sin(2.0 * trk.phi()); + qxTPC = qxTPC + trk.pt() * TMath::Cos(cfgHarmonic.value * trk.phi()); + qyTPC = qyTPC + trk.pt() * TMath::Sin(cfgHarmonic.value * trk.phi()); if (trk.eta() < 0.0) { - qxTPCL = qxTPCL + trk.pt() * TMath::Cos(2.0 * trk.phi()); - qyTPCL = qyTPCL + trk.pt() * TMath::Sin(2.0 * trk.phi()); + qxTPCL = qxTPCL + trk.pt() * TMath::Cos(cfgHarmonic.value * trk.phi()); + qyTPCL = qyTPCL + trk.pt() * TMath::Sin(cfgHarmonic.value * trk.phi()); } if (trk.eta() > 0.0) { - qxTPCR = qxTPCR + trk.pt() * TMath::Cos(2.0 * trk.phi()); - qyTPCR = qyTPCR + trk.pt() * TMath::Sin(2.0 * trk.phi()); + qxTPCR = qxTPCR + trk.pt() * TMath::Cos(cfgHarmonic.value * trk.phi()); + qyTPCR = qyTPCR + trk.pt() * TMath::Sin(cfgHarmonic.value * trk.phi()); } } if (useRecentere && (currentRunNumber != lastRunNumber)) { @@ -367,11 +369,11 @@ struct epvector { qxTPCR = (qxTPCR - hrecentere->GetBinContent(hrecentere->FindBin(centrality, 8.5))) / hrecentere->GetBinError(hrecentere->FindBin(centrality, 8.5)); qyTPCR = (qyTPCR - hrecentere->GetBinContent(hrecentere->FindBin(centrality, 9.5))) / hrecentere->GetBinError(hrecentere->FindBin(centrality, 9.5)); } - psiFT0C = 0.5 * TMath::ATan2(qyFT0C, qxFT0C); - psiFT0A = 0.5 * TMath::ATan2(qyFT0A, qxFT0A); - psiTPC = 0.5 * TMath::ATan2(qyTPC, qxTPC); - psiTPCL = 0.5 * TMath::ATan2(qyTPCL, qxTPCL); - psiTPCR = 0.5 * TMath::ATan2(qyTPCR, qxTPCR); + psiFT0C = (1.0 / cfgHarmonic.value) * TMath::ATan2(qyFT0C, qxFT0C); + psiFT0A = (1.0 / cfgHarmonic.value) * TMath::ATan2(qyFT0A, qxFT0A); + psiTPC = (1.0 / cfgHarmonic.value) * TMath::ATan2(qyTPC, qxTPC); + psiTPCL = (1.0 / cfgHarmonic.value) * TMath::ATan2(qyTPCL, qxTPCL); + psiTPCR = (1.0 / cfgHarmonic.value) * TMath::ATan2(qyTPCR, qxTPCR); if (useShift && (currentRunNumber != lastRunNumber)) { shiftprofile = ccdb->getForTimeStamp(ConfShift.value, bc.timestamp()); @@ -391,7 +393,7 @@ struct epvector { for (int ishift = 1; ishift <= 10; ishift++) { auto coeffshiftxFT0C = shiftprofile->GetBinContent(shiftprofile->FindBin(centrality, 0.5, ishift - 0.5)); auto coeffshiftyFT0C = shiftprofile->GetBinContent(shiftprofile->FindBin(centrality, 1.5, ishift - 0.5)); - deltapsiFT0C = deltapsiFT0C + ((1 / (1.0 * ishift)) * (-coeffshiftxFT0C * TMath::Cos(ishift * 2.0 * psiFT0C) + coeffshiftyFT0C * TMath::Sin(ishift * 2.0 * psiFT0C))); + deltapsiFT0C = deltapsiFT0C + ((1 / (1.0 * ishift)) * (-coeffshiftxFT0C * TMath::Cos(ishift * cfgHarmonic.value * psiFT0C) + coeffshiftyFT0C * TMath::Sin(ishift * cfgHarmonic.value * psiFT0C))); if (useShift2) { auto coeffshiftxFT0A = shiftprofile2->GetBinContent(shiftprofile2->FindBin(centrality, 0.5, ishift - 0.5)); auto coeffshiftyFT0A = shiftprofile2->GetBinContent(shiftprofile2->FindBin(centrality, 1.5, ishift - 0.5)); @@ -404,10 +406,10 @@ struct epvector { auto coeffshiftxTPCR = shiftprofile5->GetBinContent(shiftprofile5->FindBin(centrality, 0.5, ishift - 0.5)); auto coeffshiftyTPCR = shiftprofile5->GetBinContent(shiftprofile5->FindBin(centrality, 1.5, ishift - 0.5)); - deltapsiFT0A = deltapsiFT0A + ((1 / (1.0 * ishift)) * (-coeffshiftxFT0A * TMath::Cos(ishift * 2.0 * psiFT0A) + coeffshiftyFT0A * TMath::Sin(ishift * 2.0 * psiFT0A))); - deltapsiTPC = deltapsiTPC + ((1 / (1.0 * ishift)) * (-coeffshiftxTPC * TMath::Cos(ishift * 2.0 * psiTPC) + coeffshiftyTPC * TMath::Sin(ishift * 2.0 * psiTPC))); - deltapsiTPCL = deltapsiTPCL + ((1 / (1.0 * ishift)) * (-coeffshiftxTPCL * TMath::Cos(ishift * 2.0 * psiTPCL) + coeffshiftyTPCL * TMath::Sin(ishift * 2.0 * psiTPCL))); - deltapsiTPCR = deltapsiTPCR + ((1 / (1.0 * ishift)) * (-coeffshiftxTPCR * TMath::Cos(ishift * 2.0 * psiTPCR) + coeffshiftyTPCR * TMath::Sin(ishift * 2.0 * psiTPCR))); + deltapsiFT0A = deltapsiFT0A + ((1 / (1.0 * ishift)) * (-coeffshiftxFT0A * TMath::Cos(ishift * cfgHarmonic.value * psiFT0A) + coeffshiftyFT0A * TMath::Sin(ishift * cfgHarmonic.value * psiFT0A))); + deltapsiTPC = deltapsiTPC + ((1 / (1.0 * ishift)) * (-coeffshiftxTPC * TMath::Cos(ishift * cfgHarmonic.value * psiTPC) + coeffshiftyTPC * TMath::Sin(ishift * cfgHarmonic.value * psiTPC))); + deltapsiTPCL = deltapsiTPCL + ((1 / (1.0 * ishift)) * (-coeffshiftxTPCL * TMath::Cos(ishift * cfgHarmonic.value * psiTPCL) + coeffshiftyTPCL * TMath::Sin(ishift * cfgHarmonic.value * psiTPCL))); + deltapsiTPCR = deltapsiTPCR + ((1 / (1.0 * ishift)) * (-coeffshiftxTPCR * TMath::Cos(ishift * cfgHarmonic.value * psiTPCR) + coeffshiftyTPCR * TMath::Sin(ishift * cfgHarmonic.value * psiTPCR))); } } psiFT0C = psiFT0C + deltapsiFT0C; @@ -432,12 +434,12 @@ struct epvector { histos.fill(HIST("QyTPCR"), centrality, qyTPCR); histos.fill(HIST("PsiTPCR"), centrality, psiTPCR); - histos.fill(HIST("ResFT0CFT0A"), centrality, TMath::Cos(2.0 * (psiFT0C - psiFT0A)), occupancy); - histos.fill(HIST("ResFT0CTPC"), centrality, TMath::Cos(2.0 * (psiFT0C - psiTPC)), occupancy); - histos.fill(HIST("ResFT0ATPC"), centrality, TMath::Cos(2.0 * (psiFT0A - psiTPC)), occupancy); - histos.fill(HIST("ResFT0CTPCL"), centrality, TMath::Cos(2.0 * (psiFT0C - psiTPCL)), occupancy); - histos.fill(HIST("ResFT0CTPCR"), centrality, TMath::Cos(2.0 * (psiFT0C - psiTPCR)), occupancy); - histos.fill(HIST("ResTPCRTPCL"), centrality, TMath::Cos(2.0 * (psiTPCR - psiTPCL)), occupancy); + histos.fill(HIST("ResFT0CFT0A"), centrality, TMath::Cos(cfgHarmonic.value * (psiFT0C - psiFT0A)), occupancy); + histos.fill(HIST("ResFT0CTPC"), centrality, TMath::Cos(cfgHarmonic.value * (psiFT0C - psiTPC)), occupancy); + histos.fill(HIST("ResFT0ATPC"), centrality, TMath::Cos(cfgHarmonic.value * (psiFT0A - psiTPC)), occupancy); + histos.fill(HIST("ResFT0CTPCL"), centrality, TMath::Cos(cfgHarmonic.value * (psiFT0C - psiTPCL)), occupancy); + histos.fill(HIST("ResFT0CTPCR"), centrality, TMath::Cos(cfgHarmonic.value * (psiFT0C - psiTPCR)), occupancy); + histos.fill(HIST("ResTPCRTPCL"), centrality, TMath::Cos(cfgHarmonic.value * (psiTPCR - psiTPCL)), occupancy); double qFT0Cmag = TMath::Sqrt(qxFT0C * qxFT0C + qyFT0C * qyFT0C); double qFT0Amag = TMath::Sqrt(qxFT0A * qxFT0A + qyFT0A * qyFT0A); @@ -451,28 +453,28 @@ struct epvector { histos.fill(HIST("QFT0C"), centrality, qFT0Cmag, occupancy); histos.fill(HIST("QFT0A"), centrality, qFT0Amag, occupancy); - histos.fill(HIST("ResFT0CFT0ASP"), centrality, qFT0Cmag * qFT0Amag * TMath::Cos(2.0 * (psiFT0C - psiFT0A)), occupancy); - histos.fill(HIST("ResFT0CTPCSP"), centrality, qFT0Cmag * qTPCmag * TMath::Cos(2.0 * (psiFT0C - psiTPC)), occupancy); - histos.fill(HIST("ResFT0ATPCSP"), centrality, qFT0Amag * qTPCmag * TMath::Cos(2.0 * (psiFT0A - psiTPC)), occupancy); - histos.fill(HIST("ResFT0CTPCLSP"), centrality, qFT0Cmag * qTPCLmag * TMath::Cos(2.0 * (psiFT0C - psiTPCL)), occupancy); - histos.fill(HIST("ResFT0CTPCRSP"), centrality, qFT0Cmag * qTPCRmag * TMath::Cos(2.0 * (psiFT0C - psiTPCR)), occupancy); - histos.fill(HIST("ResTPCRTPCLSP"), centrality, qTPCRmag * qTPCLmag * TMath::Cos(2.0 * (psiTPCR - psiTPCL)), occupancy); + histos.fill(HIST("ResFT0CFT0ASP"), centrality, qFT0Cmag * qFT0Amag * TMath::Cos(cfgHarmonic.value * (psiFT0C - psiFT0A)), occupancy); + histos.fill(HIST("ResFT0CTPCSP"), centrality, qFT0Cmag * qTPCmag * TMath::Cos(cfgHarmonic.value * (psiFT0C - psiTPC)), occupancy); + histos.fill(HIST("ResFT0ATPCSP"), centrality, qFT0Amag * qTPCmag * TMath::Cos(cfgHarmonic.value * (psiFT0A - psiTPC)), occupancy); + histos.fill(HIST("ResFT0CTPCLSP"), centrality, qFT0Cmag * qTPCLmag * TMath::Cos(cfgHarmonic.value * (psiFT0C - psiTPCL)), occupancy); + histos.fill(HIST("ResFT0CTPCRSP"), centrality, qFT0Cmag * qTPCRmag * TMath::Cos(cfgHarmonic.value * (psiFT0C - psiTPCR)), occupancy); + histos.fill(HIST("ResTPCRTPCLSP"), centrality, qTPCRmag * qTPCLmag * TMath::Cos(cfgHarmonic.value * (psiTPCR - psiTPCL)), occupancy); for (int ishift = 1; ishift <= 10; ishift++) { - histos.fill(HIST("ShiftFT0C"), centrality, 0.5, ishift - 0.5, TMath::Sin(ishift * 2.0 * psiFT0C)); - histos.fill(HIST("ShiftFT0C"), centrality, 1.5, ishift - 0.5, TMath::Cos(ishift * 2.0 * psiFT0C)); + histos.fill(HIST("ShiftFT0C"), centrality, 0.5, ishift - 0.5, TMath::Sin(ishift * cfgHarmonic.value * psiFT0C)); + histos.fill(HIST("ShiftFT0C"), centrality, 1.5, ishift - 0.5, TMath::Cos(ishift * cfgHarmonic.value * psiFT0C)); - histos.fill(HIST("ShiftFT0A"), centrality, 0.5, ishift - 0.5, TMath::Sin(ishift * 2.0 * psiFT0A)); - histos.fill(HIST("ShiftFT0A"), centrality, 1.5, ishift - 0.5, TMath::Cos(ishift * 2.0 * psiFT0A)); + histos.fill(HIST("ShiftFT0A"), centrality, 0.5, ishift - 0.5, TMath::Sin(ishift * cfgHarmonic.value * psiFT0A)); + histos.fill(HIST("ShiftFT0A"), centrality, 1.5, ishift - 0.5, TMath::Cos(ishift * cfgHarmonic.value * psiFT0A)); - histos.fill(HIST("ShiftTPC"), centrality, 0.5, ishift - 0.5, TMath::Sin(ishift * 2.0 * psiTPC)); - histos.fill(HIST("ShiftTPC"), centrality, 1.5, ishift - 0.5, TMath::Cos(ishift * 2.0 * psiTPC)); + histos.fill(HIST("ShiftTPC"), centrality, 0.5, ishift - 0.5, TMath::Sin(ishift * cfgHarmonic.value * psiTPC)); + histos.fill(HIST("ShiftTPC"), centrality, 1.5, ishift - 0.5, TMath::Cos(ishift * cfgHarmonic.value * psiTPC)); - histos.fill(HIST("ShiftTPCL"), centrality, 0.5, ishift - 0.5, TMath::Sin(ishift * 2.0 * psiTPCL)); - histos.fill(HIST("ShiftTPCL"), centrality, 1.5, ishift - 0.5, TMath::Cos(ishift * 2.0 * psiTPCL)); + histos.fill(HIST("ShiftTPCL"), centrality, 0.5, ishift - 0.5, TMath::Sin(ishift * cfgHarmonic.value * psiTPCL)); + histos.fill(HIST("ShiftTPCL"), centrality, 1.5, ishift - 0.5, TMath::Cos(ishift * cfgHarmonic.value * psiTPCL)); - histos.fill(HIST("ShiftTPCR"), centrality, 0.5, ishift - 0.5, TMath::Sin(ishift * 2.0 * psiTPCR)); - histos.fill(HIST("ShiftTPCR"), centrality, 1.5, ishift - 0.5, TMath::Cos(ishift * 2.0 * psiTPCR)); + histos.fill(HIST("ShiftTPCR"), centrality, 0.5, ishift - 0.5, TMath::Sin(ishift * cfgHarmonic.value * psiTPCR)); + histos.fill(HIST("ShiftTPCR"), centrality, 1.5, ishift - 0.5, TMath::Cos(ishift * cfgHarmonic.value * psiTPCR)); } lastRunNumber = currentRunNumber; } From a3177d6203132a06c1506a1a8fa132e030b22028 Mon Sep 17 00:00:00 2001 From: Fabrizio Date: Mon, 16 Jun 2025 15:30:22 +0200 Subject: [PATCH 092/871] [DPG] Add first version of derived data creator for D0 calibration studies (#11564) Co-authored-by: ALICE Action Bot --- DPG/Tasks/AOTTrack/CMakeLists.txt | 5 + DPG/Tasks/AOTTrack/D0CalibTables.h | 443 ++++++++++++++++ .../derivedDataCreatorD0Calibration.cxx | 481 ++++++++++++++++++ 3 files changed, 929 insertions(+) create mode 100644 DPG/Tasks/AOTTrack/D0CalibTables.h create mode 100644 DPG/Tasks/AOTTrack/derivedDataCreatorD0Calibration.cxx diff --git a/DPG/Tasks/AOTTrack/CMakeLists.txt b/DPG/Tasks/AOTTrack/CMakeLists.txt index 9974d3d6bc2..b125419f6d0 100644 --- a/DPG/Tasks/AOTTrack/CMakeLists.txt +++ b/DPG/Tasks/AOTTrack/CMakeLists.txt @@ -85,3 +85,8 @@ o2physics_add_dpl_workflow(tag-and-probe-dmesons PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::DetectorsVertexing O2Physics::MLCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(derived-data-creator-d0-calibration + SOURCES derivedDataCreatorD0Calibration.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::AnalysisCore O2::DCAFitter O2Physics::MLCore + COMPONENT_NAME Analysis) + diff --git a/DPG/Tasks/AOTTrack/D0CalibTables.h b/DPG/Tasks/AOTTrack/D0CalibTables.h new file mode 100644 index 00000000000..5825377c736 --- /dev/null +++ b/DPG/Tasks/AOTTrack/D0CalibTables.h @@ -0,0 +1,443 @@ +// 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 D0CalibTables.h +/// \brief Definitions of derived tables produced by data creator for D0 calibration studies +/// \author Fabrizio Grosa , CERN + +#ifndef D0CALIBTABLES_H_ +#define D0CALIBTABLES_H_ + +#include +#include +#include + +#include +#include + +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/TrackSelectionTables.h" + +namespace o2 +{ +namespace hf_calib +{ +enum D0MassHypo : uint8_t { + D0 = 1, + D0Bar, + D0AndD0Bar, + ND0MassHypos +}; + +const float toMicrometers = 10000.; // from cm to µm + +/// It compresses a value to a int8_t with a given precision +///\param origValue is the original values +///\param precision is the desired precision +///\return The value compressed to a int8_t +template +int8_t getCompressedInt8(T origValue, double precision) +{ + int roundValue = static_cast(std::round(origValue / precision)); + return static_cast(std::clamp(roundValue, -128, 128)); +} + +/// It compresses a value to a uint8_t with a given precision +///\param origValue is the original values +///\param precision is the desired precision +///\return The value compressed to a uint8_t +template +uint8_t getCompressedUint8(T origValue, double precision) +{ + int roundValue = static_cast(std::round(origValue / precision)); + return static_cast(std::clamp(roundValue, 0, 255)); +} + +/// It compresses a value to a uint16_t with a given precision +///\param origValue is the original values +///\param precision is the desired precision +///\return The value compressed to a uint16_t +template +uint16_t getCompressedUint16(T origValue, double precision) +{ + int roundValue = static_cast(std::round(origValue / precision)); + return static_cast(std::clamp(roundValue, 0, 65535)); +} + +/// It uses a sinh-based scaling function, which provides a compromise between fixed-step and relative quantization. +// This approach reflects typical resolution formulas and is well-suited for detector calibration data. +///\param origValue is the original value +///\param sigma0 is a asinh parameter +///\param sigma1 is a asinh parameter +///\param clampMin is the maximum value +///\param clampMax is the minimum value +///\return The value compressed +int codeSqrtScaling(float origValue, float sigma0, float sigma1, int clampMin, int clampMax) +{ + float codeF = std::asinh((sigma1 * origValue) / sigma0) / sigma0; + return std::clamp(static_cast(std::round(codeF)), clampMin, clampMax); +} + +/// It compresses the decay length (10 micron precision) +///\param decLen is the decay length in cm +///\return The decay length compressed to a uint8_t with 10 micron precision +template +uint8_t getCompressedDecayLength(T decLen) +{ + return getCompressedUint8(decLen * hf_calib::toMicrometers, 0.1); +} + +/// It compresses the normalised decay length (0.5 precision) +///\param normDecLen is the normalised decay length +///\return The normalised decay length compressed to a uint8_t with 0.5 precision +template +uint8_t getCompressedNormDecayLength(T normDecLen) +{ + return getCompressedUint8(normDecLen, 0.5); +} + +/// It compresses the pointing angle (0.005 precision) +///\param pointAngle is the pointing angle +///\return The pointing angle compressed to a uint8_t with 0.005 precision +template +uint8_t getCompressedPointingAngle(T pointAngle) +{ + return getCompressedUint8(pointAngle, 0.005); +} + +/// It compresses the cosine of pointing angle (0.001 precision) +///\param cosPa is the cosine of pointing angle +///\return The cosine of pointing angle compressed to a uint8_t with 0.001 precision +template +int8_t getCompressedCosPa(T cosPa) +{ + return getCompressedUint8(cosPa - 0.75, 0.001); // in the range from 0.75 to 1 +} + +/// It compresses the chi2 +///\param chi2 is the chi2 +///\return The chi2 compressed to a uint8_t +template +int8_t getCompressedChi2(T chi2) +{ + uint8_t compressedChi2 = static_cast(codeSqrtScaling(chi2, 0.015, 0.015, 0, 255)); + return compressedChi2; +} + +/// It compresses the number of sigma +///\param numSigma is the number of sigma +///\return The number of sigma compressed to a int8_t +template +int8_t getCompressedNumSigmaPid(T numSigma) +{ + int8_t compressedNumSigma = static_cast(codeSqrtScaling(numSigma, 0.05, 0.05, -128, 128)); + return compressedNumSigma; +} + +/// It compresses the bdt score (1./65535 precision) +///\param bdtScore is the bdt score +///\return The bdt score compressed to a uint16_t with 1./65535 precision +template +uint16_t getCompressedBdtScoreBkg(T bdtScore) +{ + return getCompressedUint16(bdtScore, 1. / 65535); +} + +/// It compresses the bdt score (1./255 precision) +///\param bdtScore is the bdt score +///\return The bdt score compressed to a uint8_t with 1./255 precision +template +uint8_t getCompressedBdtScoreSgn(T bdtScore) +{ + return getCompressedUint8(bdtScore, 1. / 255); +} + +/// It compresses the number of sigma (0.1 sigma precision) +///\param occupancy is the occupancy value +///\return The number of sigma compressed to a int8_t with 0.1 precision +template +uint8_t getCompressedOccupancy(T occupancy) +{ + uint8_t compressedOcc = static_cast(codeSqrtScaling(occupancy, 0.04, 0.04, 0, 255)); + return compressedOcc; +} + +static constexpr int NBinsPtTrack = 6; +static constexpr int NCutVarsTrack = 4; +constexpr float BinsPtTrack[NBinsPtTrack + 1] = { + 0, + 0.5, + 1.0, + 1.5, + 2.0, + 3.0, + 1000.0}; +auto vecBinsPtTrack = std::vector{BinsPtTrack, BinsPtTrack + NBinsPtTrack + 1}; + +// default values for the dca_xy and dca_z cuts of displaced tracks +constexpr float CutsTrack[NBinsPtTrack][NCutVarsTrack] = {{0.0015, 2., 0.0000, 2.}, /* 0 < pt < 0.5 */ + {0.0015, 2., 0.0000, 2.}, /* 0.5 < pt < 1 */ + {0.0015, 2., 0.0000, 2.}, /* 1 < pt < 1.5 */ + {0.0015, 2., 0.0000, 2.}, /* 1.5 < pt < 2 */ + {0.0000, 2., 0.0000, 2.}, /* 2 < pt < 3 */ + {0.0000, 2., 0.0000, 2.}}; /* 3 < pt < 1000 */ +// row labels +static const std::vector labelsPtTrack{}; + +// column labels +static const std::vector labelsCutVarTrack = {"min_dcaxytoprimary", "max_dcaxytoprimary", "min_dcaztoprimary", "max_dcaztoprimary"}; + +static constexpr int NBinsPtCand = 10; +static constexpr int NCutVarsCand = 10; +// 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 float BinsPtCand[NBinsPtCand + 1] = { + 0, + 1.0, + 2.0, + 3.0, + 4.0, + 6.0, + 8.0, + 12.0, + 24.0, + 50.0, + 1000.0}; +auto vecBinsPtCand = std::vector{BinsPtCand, BinsPtCand + NBinsPtCand + 1}; + +// default values for the cuts +constexpr float CutsCand[NBinsPtCand][NCutVarsCand] = {{0.400, 0., 10., 10., 0.97, 0.97, 0, 2, 0.01, 0.01}, /* 0 < pT < 1 */ + {0.400, 0., 10., 10., 0.97, 0.97, 0, 2, 0.01, 0.01}, /* 1 < pT < 2 */ + {0.400, 0., 10., 10., 0.95, 0.95, 0, 2, 0.01, 0.01}, /* 2 < pT < 3 */ + {0.400, 0., 10., 10., 0.95, 0.95, 0, 2, 0.01, 0.01}, /* 3 < pT < 4 */ + {0.400, 0., 10., 10., 0.95, 0.95, 0, 2, 0.01, 0.01}, /* 4 < pT < 6 */ + {0.400, 0., 10., 10., 0.95, 0.95, 0, 2, 0.01, 0.01}, /* 6 < pT < 8 */ + {0.400, 0., 10., 10., 0.95, 0.95, 0, 2, 0.01, 0.01}, /* 8 < pT < 12 */ + {0.400, 0., 10., 10., 0.95, 0.95, 0, 2, 0.01, 0.01}, /* 12 < pT < 24 */ + {0.400, 0., 10., 10., 0.95, 0.95, 0, 2, 0.01, 0.01}, /* 24 < pT < 50 */ + {0.400, 0., 10., 10., 0.95, 0.95, 0, 2, 0.01, 0.01}}; /* 50 < pT < 1000 */ + +// row labels +static const std::vector labelsPtCand = { + "pT bin 0", + "pT bin 1", + "pT bin 2", + "pT bin 3", + "pT bin 4", + "pT bin 5", + "pT bin 6", + "pT bin 7", + "pT bin 8", + "pT bin 9"}; + +// column labels +static const std::vector labelsCutVarCand = {"delta inv. mass", "max d0d0", "max pointing angle", "max pointing angle XY", "min cos pointing angle", "min cos pointing angle XY", "min norm decay length", "min norm decay length XY", "min decay length", "min decay length XY"}; + +static constexpr int NBinsPtMl = 10; +// 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 BinsPtMl[NBinsPtMl + 1] = { + 0, + 1.0, + 2.0, + 3.0, + 4.0, + 6.0, + 8.0, + 12.0, + 24.0, + 50.0, + 1000.0}; +auto vecBinsPtMl = std::vector{BinsPtMl, BinsPtMl + NBinsPtMl + 1}; + +// default values for the cuts +constexpr double CutsMl[NBinsPtMl][3] = {{1., 0., 0.}, /* 0 < pT < 1 */ + {1., 0., 0.}, /* 1 < pT < 2 */ + {1., 0., 0.}, /* 2 < pT < 3 */ + {1., 0., 0.}, /* 3 < pT < 4 */ + {1., 0., 0.}, /* 4 < pT < 6 */ + {1., 0., 0.}, /* 6 < pT < 8 */ + {1., 0., 0.}, /* 8 < pT < 12 */ + {1., 0., 0.}, /* 12 < pT < 24 */ + {1., 0., 0.}, /* 24 < pT < 50 */ + {1., 0., 0.}}; /* 50 < pT < 1000 */ + +// row labels +static const std::vector labelsPtMl = { + "pT bin 0", + "pT bin 1", + "pT bin 2", + "pT bin 3", + "pT bin 4", + "pT bin 5", + "pT bin 6", + "pT bin 7", + "pT bin 8", + "pT bin 9"}; + +// column labels +static const std::vector labelsCutMl = {"max BDT score bkg", "min BDT score prompt", "min BDT score nonprompt"}; +} // namespace hf_calib + +namespace aod +{ +namespace hf_calib +{ +DECLARE_SOA_COLUMN(RunNumber, runNumber, int); //! Run number +DECLARE_SOA_COLUMN(Orbit, orbit, uint32_t); //! orbit ID +DECLARE_SOA_COLUMN(CentFT0C, centFT0C, uint8_t); //! FTOC centrality +DECLARE_SOA_COLUMN(OccupancyTracks, occupancyTracks, uint8_t); //! FT0 occupancy +DECLARE_SOA_COLUMN(OccupancyFT0C, occupancyFT0C, uint8_t); //! FT0 occupancy +} // namespace hf_calib + +DECLARE_SOA_TABLE(D0CalibColl, "AOD", "D0CALIBCOLLS", + o2::soa::Index<>, + collision::PosX, + collision::PosY, + collision::PosZ, + collision::CovXX, + collision::CovXY, + collision::CovXZ, + collision::CovYY, + collision::CovYZ, + collision::CovZZ, + collision::NumContrib, + hf_calib::CentFT0C, + hf_calib::OccupancyTracks, + hf_calib::OccupancyFT0C, + hf_calib::Orbit, + hf_calib::RunNumber); + +namespace hf_calib +{ +DECLARE_SOA_INDEX_COLUMN_FULL(Collision, collision, int, D0CalibColl, ""); //! Index of collision +DECLARE_SOA_COLUMN(TpcNumSigmaPi, tpcNumSigmaPi, int8_t); //! compressed NsigmaTPC for pions +DECLARE_SOA_COLUMN(TpcNumSigmaKa, tpcNumSigmaKa, int8_t); //! compressed NsigmaTPC for kaons +DECLARE_SOA_COLUMN(TofNumSigmaPi, tofNumSigmaPi, int8_t); //! compressed NsigmaTOF for pions +DECLARE_SOA_COLUMN(TofNumSigmaKa, tofNumSigmaKa, int8_t); //! compressed NsigmaTOF for kaons +DECLARE_SOA_COLUMN(ITSChi2NCl, itsChi2NCl, uint8_t); //! compressed NsigmaTOF for kaons // o2-linter: disable=name/o2-column +DECLARE_SOA_COLUMN(TPCChi2NCl, tpcChi2NCl, uint8_t); //! compressed NsigmaTOF for kaons // o2-linter: disable=name/o2-column +DECLARE_SOA_COLUMN(TRDChi2, trdChi2, uint8_t); //! compressed NsigmaTOF for kaons // o2-linter: disable=name/o2-column +DECLARE_SOA_COLUMN(TOFChi2, tofChi2, uint8_t); //! compressed NsigmaTOF for kaons // o2-linter: disable=name/o2-column +} // namespace hf_calib + +DECLARE_SOA_TABLE(D0CalibTrack, "AOD", "D0CALIBTRACKS", + o2::soa::Index<>, + /// *** collision index + hf_calib::CollisionId, + /// *** track pars + track::X, + track::Alpha, + track::Y, + track::Z, + track::Snp, + track::Tgl, + track::Signed1Pt, + /// *** track covs + track::CYY, + track::CZY, + track::CZZ, + track::CSnpY, + track::CSnpZ, + track::CSnpSnp, + track::CTglY, + track::CTglZ, + track::CTglSnp, + track::CTglTgl, + track::C1PtY, + track::C1PtZ, + track::C1PtSnp, + track::C1PtTgl, + track::C1Pt21Pt2, + /// *** track extra (static) + track::TPCInnerParam, + track::Flags, + track::ITSClusterSizes, + track::TPCNClsFindable, + track::TPCNClsFindableMinusFound, + track::TPCNClsFindableMinusCrossedRows, + track::TPCNClsShared, + track::TRDPattern, + hf_calib::ITSChi2NCl, + hf_calib::TPCChi2NCl, + hf_calib::TRDChi2, + hf_calib::TOFChi2, + track::TPCSignal, + track::TRDSignal, + track::Length, + track::TOFExpMom, + track::TrackTime, + track::TrackTimeRes, + /// *** track QA --> FIXME: info not present for each track in normal AO2Ds, check how to do + /// *** DCA, Nsigma + track::DcaXY, + track::DcaZ, + hf_calib::TpcNumSigmaPi, + hf_calib::TpcNumSigmaKa, + hf_calib::TofNumSigmaPi, + hf_calib::TofNumSigmaKa); + +namespace hf_calib +{ +DECLARE_SOA_INDEX_COLUMN_FULL(TrackPos, trackPos, int, D0CalibTrack, ""); //! Index of positive track +DECLARE_SOA_INDEX_COLUMN_FULL(TrackNeg, trackNeg, int, D0CalibTrack, ""); //! Index of negative track +DECLARE_SOA_COLUMN(MassHypo, massHypo, uint8_t); //! mass hypothesis for D0 (D0, D0bar, or both) +DECLARE_SOA_COLUMN(Pt, pt, float); //! D0-candidate pT +DECLARE_SOA_COLUMN(Eta, eta, float); //! D0-candidate eta +DECLARE_SOA_COLUMN(Phi, phi, float); //! D0-candidate phi +DECLARE_SOA_COLUMN(InvMassD0, invMassD0, float); //! invariant mass (D0 hypothesis) +DECLARE_SOA_COLUMN(InvMassD0bar, invMassD0bar, float); //! invariant mass (D0bar hypothesis) +DECLARE_SOA_COLUMN(DecLength, decLength, uint8_t); //! compressed decay length +DECLARE_SOA_COLUMN(DecLengthXY, decLengthXY, uint8_t); //! compressed decay length XY +DECLARE_SOA_COLUMN(NormDecLength, normDecLength, uint8_t); //! compressed normalised decay length +DECLARE_SOA_COLUMN(NormDecLengthXY, normDecLengthXY, uint8_t); //! compressed normalised decay length XY +DECLARE_SOA_COLUMN(CosPa, cosPa, uint8_t); //! compressed cosine of pointing angle +DECLARE_SOA_COLUMN(CosPaXY, cosPaXY, uint8_t); //! compressed cosine of pointing angle XY +DECLARE_SOA_COLUMN(PointingAngle, pointingAngle, uint8_t); //! compressed pointing angle +DECLARE_SOA_COLUMN(PointingAngleXY, pointingAngleXY, uint8_t); //! compressed pointing angle XY +DECLARE_SOA_COLUMN(DecVtxChi2, decVtxChi2, uint8_t); //! compressed decay vertex chi2 +DECLARE_SOA_COLUMN(BdtScoreBkgD0, bdtScoreBkgD0, uint16_t); //! compressed BDT score (bkg, D0 mass hypo) +DECLARE_SOA_COLUMN(BdtScorePromptD0, bdtScorePromptD0, uint8_t); //! compressed BDT score (prompt, D0 mass hypo) +DECLARE_SOA_COLUMN(BdtScoreNonpromptD0, bdtScoreNonpromptD0, uint8_t); //! compressed BDT score (non-prompt, D0 mass hypo) +DECLARE_SOA_COLUMN(BdtScoreBkgD0bar, bdtScoreBkgD0bar, uint16_t); //! compressed BDT score (bkg, D0bar mass hypo) +DECLARE_SOA_COLUMN(BdtScorePromptD0bar, bdtScorePromptD0bar, uint8_t); //! compressed BDT score (prompt, D0bar mass hypo) +DECLARE_SOA_COLUMN(BdtScoreNonpromptD0bar, bdtScoreNonpromptD0bar, uint8_t); //! compressed BDT score (non-prompt, D0bar mass hypo) +} // namespace hf_calib + +DECLARE_SOA_TABLE(D0CalibCand, "AOD", "D0CALIBCANDS", + o2::soa::Index<>, + hf_calib::CollisionId, + hf_calib::TrackPosId, + hf_calib::TrackNegId, + hf_calib::MassHypo, + hf_calib::Pt, + hf_calib::Eta, + hf_calib::Phi, + hf_calib::InvMassD0, + hf_calib::InvMassD0bar, + hf_calib::DecLength, + hf_calib::DecLengthXY, + hf_calib::NormDecLength, + hf_calib::NormDecLengthXY, + hf_calib::CosPa, + hf_calib::CosPaXY, + hf_calib::PointingAngle, + hf_calib::PointingAngleXY, + hf_calib::DecVtxChi2, + hf_calib::BdtScoreBkgD0, + hf_calib::BdtScorePromptD0, + hf_calib::BdtScoreNonpromptD0, + hf_calib::BdtScoreBkgD0bar, + hf_calib::BdtScorePromptD0bar, + hf_calib::BdtScoreNonpromptD0bar); +} // namespace aod +} // namespace o2 +#endif // D0CALIBTABLES_H_ diff --git a/DPG/Tasks/AOTTrack/derivedDataCreatorD0Calibration.cxx b/DPG/Tasks/AOTTrack/derivedDataCreatorD0Calibration.cxx new file mode 100644 index 00000000000..1136eaff683 --- /dev/null +++ b/DPG/Tasks/AOTTrack/derivedDataCreatorD0Calibration.cxx @@ -0,0 +1,481 @@ +// 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 derivedDataCreatorD0Calibration.cxx +/// \brief Producer of derived tables of D0 candidates, daughter tracks and collisions for calibration studies +/// +/// \author Fabrizio Grosa , CERN + +#include "D0CalibTables.h" + +#include "PWGHF/Utils/utilsAnalysis.h" +#include "PWGHF/Utils/utilsBfieldCCDB.h" +#include "PWGHF/Utils/utilsPid.h" + +#include "Common/Core/RecoDecay.h" +#include "Common/Core/TrackSelectorPID.h" +#include "Common/Core/trackUtilities.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/CollisionAssociationTables.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/PIDResponseTOF.h" +#include "Common/DataModel/PIDResponseTPC.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "CommonDataFormat/InteractionRecord.h" +#include "Tools/ML/MlResponse.h" + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +using namespace o2; +using namespace o2::analysis; +using namespace o2::constants::physics; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::hf_calib; + +struct DerivedDataCreatorD0Calibration { + + Produces collTable; + Produces trackTable; + Produces candTable; + + struct : ConfigurableGroup { + Configurable ptMin{"ptMin", 0.4, "min. track pT"}; + Configurable absEtaMax{"absEtaMax", 1., "max. track absolute eta"}; + Configurable> binsPt{"binsPt", std::vector{hf_calib::vecBinsPtTrack}, "track pT bin limits for DCA pT-dependent cut"}; + Configurable> limitsDca{"limitsDca", {hf_calib::CutsTrack[0], hf_calib::NBinsPtTrack, hf_calib::NCutVarsTrack, hf_calib::labelsPtTrack, hf_calib::labelsCutVarTrack}, "Single-track selections per pT bin"}; + // TPC PID + Configurable ptPidTpcMin{"ptPidTpcMin", 0., "Lower bound of track pT for TPC PID"}; + Configurable ptPidTpcMax{"ptPidTpcMax", 1000., "Upper bound of track pT for TPC PID"}; + Configurable nSigmaTpcMax{"nSigmaTpcMax", 3., "Nsigma cut on TPC only"}; + Configurable usePidTpcOnly{"usePidTpcOnly", false, "Only use TPC PID"}; + // TOF PID + Configurable ptPidTofMin{"ptPidTofMin", 0., "Lower bound of track pT for TOF PID"}; + Configurable ptPidTofMax{"ptPidTofMax", 1000., "Upper bound of track pT for TOF PID"}; + Configurable nSigmaTofMax{"nSigmaTofMax", 3., "Nsigma cut on TOF only"}; + std::string prefix = "trackCuts"; + } cfgTrackCuts; + + struct : ConfigurableGroup { + Configurable ptMin{"ptMin", 0., "min. D0-candidate pT"}; + Configurable> binsPt{"binsPt", std::vector{hf_calib::vecBinsPtCand}, "pT bin limits"}; + Configurable> topologicalCuts{"topologicalCuts", {hf_calib::CutsCand[0], hf_calib::NBinsPtCand, hf_calib::NCutVarsCand, hf_calib::labelsPtCand, hf_calib::labelsCutVarCand}, "D0 candidate selection per pT bin"}; + std::string prefix = "candidateCuts"; + } cfgCandCuts; + + struct : ConfigurableGroup { + Configurable apply{"apply", false, "flag to apply downsampling"}; + Configurable pathCcdbWeights{"pathCcdbWeights", "", "CCDB path containing pT-differential weights"}; + std::string prefix = "downsampling"; + } cfgDownsampling; + + struct : ConfigurableGroup { + Configurable apply{"apply", false, "flag to apply downsampling"}; + Configurable> binsPt{"binsPt", std::vector{hf_calib::vecBinsPtMl}, "pT bin limits for ML models inference"}; + Configurable> thresholdMlScores{"thresholdMlScores", {hf_calib::CutsMl[0], hf_calib::NBinsPtMl, 3, hf_calib::labelsPtMl, hf_calib::labelsCutMl}, "Threshold values for Ml output scores of D0 candidates"}; + Configurable loadMlModelsFromCCDB{"loadMlModelsFromCCDB", true, "Flag to enable or disable the loading of ML models from CCDB"}; + Configurable> modelPathsCCDB{"modelPathsCCDB", std::vector{"Users/f/fgrosa/D0Calib/BDT/Pt0_1"}, "Paths of models on CCDB"}; + Configurable> onnxFileNames{"onnxFileNames", std::vector{"ModelHandler_pT_0_1.onnx"}, "ONNX file names for each pT bin (if not from CCDB full path)"}; + std::string prefix = "ml"; + } cfgMl; + + using TracksWCovExtraPid = soa::Join; + using CollisionsWEvSel = soa::Join; + + Preslice trackIndicesPerCollision = aod::track_association::collisionId; + + o2::vertexing::DCAFitterN<2> df; // 2-prong vertex fitter + Service ccdb; + o2::ccdb::CcdbApi ccdbApi; + o2::analysis::MlResponse mlResponse; + + TrackSelectorPi selectorPion; + TrackSelectorKa selectorKaon; + + int runNumber{0}; + double bz{0.}; + const float zVtxMax{10.f}; + // tolerances for preselections before vertex reconstruction + const float ptTolerance{0.1f}; + const float invMassTolerance{0.05f}; + + OutputObj histDownSampl{"histDownSampl"}; + + void init(InitContext const&) + { + // First we set the CCDB manager + ccdb->setURL("http://alice-ccdb.cern.ch"); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + + if (cfgDownsampling.apply) { + histDownSampl.setObject(reinterpret_cast(ccdb->getSpecific(cfgDownsampling.pathCcdbWeights))); + } + + if (cfgMl.apply) { + std::vector cutDir = {o2::cuts_ml::CutDirection::CutGreater, o2::cuts_ml::CutDirection::CutSmaller, o2::cuts_ml::CutDirection::CutSmaller}; + mlResponse.configure(cfgMl.binsPt, cfgMl.thresholdMlScores, cutDir, 3); + if (cfgMl.loadMlModelsFromCCDB) { + ccdbApi.init("http://alice-ccdb.cern.ch"); + mlResponse.setModelPathsCCDB(cfgMl.onnxFileNames, ccdbApi, cfgMl.modelPathsCCDB, -1); + } else { + mlResponse.setModelPathsLocal(cfgMl.onnxFileNames); + } + mlResponse.init(); + } + + df.setPropagateToPCA(true); + df.setMaxR(200.f); + df.setMaxDZIni(4.f); + df.setMinParamChange(1.e-3f); + df.setMinRelChi2Change(0.9f); + df.setUseAbsDCA(false); + df.setWeightedFinalPCA(false); + df.setMatCorrType(o2::base::Propagator::MatCorrType::USEMatCorrNONE); // we are always inside the beampipe + + selectorPion.setRangePtTpc(cfgTrackCuts.ptPidTpcMin, cfgTrackCuts.ptPidTpcMax); + selectorPion.setRangeNSigmaTpc(-cfgTrackCuts.nSigmaTpcMax, cfgTrackCuts.nSigmaTpcMax); + selectorPion.setRangePtTof(cfgTrackCuts.ptPidTofMin, cfgTrackCuts.ptPidTofMax); + selectorPion.setRangeNSigmaTof(-cfgTrackCuts.nSigmaTofMax, cfgTrackCuts.nSigmaTofMax); + selectorKaon = selectorPion; + } + + void process(CollisionsWEvSel const& collisions, + aod::TrackAssoc const& trackIndices, + TracksWCovExtraPid const&, + aod::BCsWithTimestamps const&) + { + std::map selectedCollisions; // map with indices of selected collisions (key: original AOD Collision table index, value: D0 collision index) + std::map selectedTracks; // map with indices of selected tracks (key: original AOD Track table index, value: D0 daughter track index) + + for (auto const& collision : collisions) { + + // minimal event selection + if (!collision.sel8()) { + continue; + } + auto primaryVertex = getPrimaryVertex(collision); + if (std::abs(primaryVertex.getZ()) > zVtxMax) { + continue; + } + + auto covMatrixPV = primaryVertex.getCov(); + + auto bc = collision.template bc_as(); + if (runNumber != bc.runNumber()) { + initCCDB(bc, runNumber, ccdb, "GLO/Config/GRPMagField", nullptr, false); + bz = o2::base::Propagator::Instance()->getNominalBz(); + } + o2::InteractionRecord eventIR; + eventIR.setFromLong(bc.globalBC()); + + auto groupedTrackIndices = trackIndices.sliceBy(trackIndicesPerCollision, collision.globalIndex()); + for (auto const& trackIndexPos : groupedTrackIndices) { + auto trackPos = trackIndexPos.template track_as(); + // track selections + if (trackPos.sign() < 0) { // first positive track + continue; + } + if (!trackPos.isGlobalTrackWoDCA()) { + continue; + } + if (trackPos.pt() < cfgTrackCuts.ptMin) { + continue; + } + if (std::abs(trackPos.eta()) > cfgTrackCuts.absEtaMax) { + continue; + } + auto trackParCovPos = getTrackParCov(trackPos); + o2::dataformats::DCA dcaPos; + trackParCovPos.propagateToDCA(primaryVertex, bz, &dcaPos); + if (!isSelectedTrackDca(cfgTrackCuts.binsPt, cfgTrackCuts.limitsDca, trackParCovPos.getPt(), dcaPos.getY(), dcaPos.getZ())) { + continue; + } + + int pidTrackPosKaon{-1}; + int pidTrackPosPion{-1}; + if (cfgTrackCuts.usePidTpcOnly) { + /// kaon TPC PID positive daughter + pidTrackPosKaon = selectorKaon.statusTpc(trackPos); + /// pion TPC PID positive daughter + pidTrackPosPion = selectorPion.statusTpc(trackPos); + } else { + /// kaon TPC, TOF PID positive daughter + pidTrackPosKaon = selectorKaon.statusTpcAndTof(trackPos); + /// pion TPC, TOF PID positive daughter + pidTrackPosPion = selectorPion.statusTpcAndTof(trackPos); + } + + for (auto const& trackIndexNeg : groupedTrackIndices) { + auto trackNeg = trackIndexNeg.template track_as(); + // track selections + if (trackNeg.sign() > 0) { // second negative track + continue; + } + if (!trackNeg.isGlobalTrackWoDCA()) { + continue; + } + if (trackNeg.pt() < cfgTrackCuts.ptMin) { + continue; + } + if (std::abs(trackNeg.eta()) > cfgTrackCuts.absEtaMax) { + continue; + } + auto trackParCovNeg = getTrackParCov(trackNeg); + o2::dataformats::DCA dcaNeg; + trackParCovNeg.propagateToDCA(primaryVertex, bz, &dcaNeg); + if (!isSelectedTrackDca(cfgTrackCuts.binsPt, cfgTrackCuts.limitsDca, trackParCovNeg.getPt(), dcaNeg.getY(), dcaNeg.getZ())) { + continue; + } + + int pidTrackNegKaon{-1}; + int pidTrackNegPion{-1}; + if (cfgTrackCuts.usePidTpcOnly) { + /// kaon TPC PID negative daughter + pidTrackNegKaon = selectorKaon.statusTpc(trackNeg); + /// pion TPC PID negative daughter + pidTrackNegPion = selectorPion.statusTpc(trackNeg); + } else { + /// kaon TPC, TOF PID negative daughter + pidTrackNegKaon = selectorKaon.statusTpcAndTof(trackNeg); + /// pion TPC, TOF PID negative daughter + pidTrackNegPion = selectorPion.statusTpcAndTof(trackNeg); + } + + // preselections + // PID + uint8_t massHypo{D0MassHypo::D0AndD0Bar}; // both mass hypotheses a priori + if (pidTrackPosPion == TrackSelectorPID::Rejected || pidTrackNegKaon == TrackSelectorPID::Rejected) { + massHypo -= D0MassHypo::D0; // exclude D0 + } + if (pidTrackNegPion == TrackSelectorPID::Rejected || pidTrackPosKaon == TrackSelectorPID::Rejected) { + massHypo -= D0MassHypo::D0Bar; // exclude D0Bar + } + if (massHypo == 0) { + continue; + } + + // pt + std::array pVecNoVtxD0 = RecoDecay::pVec(trackPos.pVector(), trackNeg.pVector()); + float ptNoVtxD0 = RecoDecay::pt(pVecNoVtxD0); + if (ptNoVtxD0 - ptTolerance < cfgCandCuts.ptMin) { + continue; + } + int ptBinNoVtxD0 = findBin(cfgTrackCuts.binsPt, ptNoVtxD0 + ptTolerance); // assuming tighter selections at lower pT + if (ptBinNoVtxD0 < 0) { + continue; + } + + // d0xd0 + if (dcaPos.getY() * dcaNeg.getY() > cfgCandCuts.topologicalCuts->get(ptBinNoVtxD0, "max d0d0")) { + continue; + } + + // invariant mass + if (massHypo == D0MassHypo::D0 || massHypo == D0MassHypo::D0AndD0Bar) { + float invMassNoVtxD0 = RecoDecay::m(std::array{trackPos.pVector(), trackNeg.pVector()}, std::array{o2::constants::physics::MassPiPlus, o2::constants::physics::MassKPlus}); + if (std::abs(invMassNoVtxD0 - o2::constants::physics::MassD0) > cfgCandCuts.topologicalCuts->get(ptBinNoVtxD0, "delta inv. mass") + invMassTolerance) { + massHypo -= D0MassHypo::D0; + } + } + if (massHypo >= D0MassHypo::D0Bar) { + float invMassNoVtxD0bar = RecoDecay::m(std::array{trackNeg.pVector(), trackPos.pVector()}, std::array{o2::constants::physics::MassPiPlus, o2::constants::physics::MassKPlus}); + if (std::abs(invMassNoVtxD0bar - o2::constants::physics::MassD0) > cfgCandCuts.topologicalCuts->get(ptBinNoVtxD0, "delta inv. mass") + invMassTolerance) { + massHypo -= D0MassHypo::D0Bar; + } + } + if (massHypo == 0) { + continue; + } + + // reconstruct vertex + if (df.process(trackParCovPos, trackParCovNeg) == 0) { + continue; + } + const auto& secondaryVertex = df.getPCACandidate(); + auto chi2PCA = df.getChi2AtPCACandidate(); + auto covMatrixPCA = df.calcPCACovMatrixFlat(); + auto trackParAtSecVtxPos = df.getTrack(0); + auto trackParAtSecVtxNeg = df.getTrack(1); + + std::array pVecPos{}; + std::array pVecNeg{}; + trackParAtSecVtxPos.getPxPyPzGlo(pVecPos); + trackParAtSecVtxNeg.getPxPyPzGlo(pVecNeg); + std::array pVecD0 = RecoDecay::pVec(pVecPos, pVecNeg); + + // select D0 + // pt + float ptD0 = RecoDecay::pt(pVecD0); + if (ptD0 < cfgCandCuts.ptMin) { + continue; + } + int ptBinD0 = findBin(cfgTrackCuts.binsPt, ptD0); + if (ptBinD0 < 0) { + continue; + } + + // random downsampling already here + if (cfgDownsampling.apply) { + int ptBinWeights{0}; + if (ptD0 < histDownSampl->GetBinLowEdge(1)) { + ptBinWeights = 1; + } else if (ptD0 > histDownSampl->GetXaxis()->GetBinUpEdge(histDownSampl->GetNbinsX())) { + ptBinWeights = histDownSampl->GetNbinsX(); + } else { + ptBinWeights = histDownSampl->GetXaxis()->FindBin(ptD0); + } + float weight = histDownSampl->GetBinContent(ptBinWeights); + if (gRandom->Rndm() > weight) { + continue; + } + } + + // d0xd0 + if (dcaPos.getY() * dcaNeg.getY() > cfgCandCuts.topologicalCuts->get(ptBinD0, "max d0d0")) { + continue; + } + // cospa + float cosPaD0 = RecoDecay::cpa(std::array{primaryVertex.getX(), primaryVertex.getY(), primaryVertex.getZ()}, secondaryVertex, pVecD0); + if (cosPaD0 < cfgCandCuts.topologicalCuts->get(ptBinD0, "min cos pointing angle")) { + continue; + } + // pointing angle + float paD0 = std::acos(cosPaD0); + if (paD0 > cfgCandCuts.topologicalCuts->get(ptBinD0, "max pointing angle")) { + continue; + } + // cospa XY + float cosPaXYD0 = RecoDecay::cpaXY(std::array{primaryVertex.getX(), primaryVertex.getY(), primaryVertex.getZ()}, secondaryVertex, pVecD0); + if (cosPaXYD0 < cfgCandCuts.topologicalCuts->get(ptBinD0, "min cos pointing angle XY")) { + continue; + } + // pointing angle XY + float paXYD0 = std::acos(cosPaXYD0); + if (paXYD0 > cfgCandCuts.topologicalCuts->get(ptBinD0, "max pointing angle XY")) { + continue; + } + // decay length + float decLenD0 = RecoDecay::distance(std::array{primaryVertex.getX(), primaryVertex.getY(), primaryVertex.getZ()}, secondaryVertex); + if (decLenD0 < cfgCandCuts.topologicalCuts->get(ptBinD0, "min decay length")) { + continue; + } + // decay length XY + float decLenXYD0 = RecoDecay::distanceXY(std::array{primaryVertex.getX(), primaryVertex.getY(), primaryVertex.getZ()}, secondaryVertex); + if (decLenXYD0 < cfgCandCuts.topologicalCuts->get(ptBinD0, "min decay length XY")) { + continue; + } + // normalised decay length + float phi{0.f}, theta{0.f}; + getPointDirection(std::array{primaryVertex.getX(), primaryVertex.getY(), primaryVertex.getZ()}, secondaryVertex, phi, theta); + float errorDecayLengthD0 = std::sqrt(getRotatedCovMatrixXX(covMatrixPV, phi, theta) + getRotatedCovMatrixXX(covMatrixPCA, phi, theta)); + if (decLenD0 / errorDecayLengthD0 < cfgCandCuts.topologicalCuts->get(ptBinD0, "min norm decay length")) { + continue; + } + // normalised decay length XY + float errorDecayLengthXYD0 = std::sqrt(getRotatedCovMatrixXX(covMatrixPV, phi, 0.f) + getRotatedCovMatrixXX(covMatrixPCA, phi, 0.f)); + if (decLenXYD0 / errorDecayLengthXYD0 < cfgCandCuts.topologicalCuts->get(ptBinD0, "min norm decay length XY")) { + continue; + } + + float invMassD0{0.f}, invMassD0bar{0.f}; + std::vector bdtScoresD0{0.f, 1.f, 1.f}, bdtScoresD0bar{0.f, 1.f, 1.f}; // always selected a priori + if (massHypo == D0MassHypo::D0 || massHypo == D0MassHypo::D0AndD0Bar) { + invMassD0 = RecoDecay::m(std::array{pVecPos, pVecNeg}, std::array{o2::constants::physics::MassPiPlus, o2::constants::physics::MassKPlus}); + if (std::abs(invMassD0 - o2::constants::physics::MassD0) > cfgCandCuts.topologicalCuts->get(ptBinD0, "delta inv. mass")) { + massHypo -= D0MassHypo::D0; + bdtScoresD0 = std::vector{1.f, 0.f, 0.f}; + } else { + // apply BDT models + if (cfgMl.apply) { + std::vector featuresCandD0 = {dcaPos.getY(), dcaNeg.getY(), chi2PCA, cosPaD0, cosPaXYD0, decLenXYD0, decLenD0, dcaPos.getY() * dcaNeg.getY(), aod::pid_tpc_tof_utils::combineNSigma(trackPos.tpcNSigmaPi(), trackPos.tofNSigmaPi()), aod::pid_tpc_tof_utils::combineNSigma(trackNeg.tpcNSigmaKa(), trackNeg.tofNSigmaKa()), trackPos.tpcNSigmaPi(), trackPos.tpcNSigmaKa(), aod::pid_tpc_tof_utils::combineNSigma(trackPos.tpcNSigmaKa(), trackPos.tofNSigmaKa()), trackNeg.tpcNSigmaPi(), trackNeg.tpcNSigmaKa(), aod::pid_tpc_tof_utils::combineNSigma(trackNeg.tpcNSigmaPi(), trackNeg.tofNSigmaPi())}; + mlResponse.isSelectedMl(featuresCandD0, ptD0, bdtScoresD0); + } + } + } + if (massHypo >= D0MassHypo::D0Bar) { + invMassD0bar = RecoDecay::m(std::array{pVecNeg, pVecPos}, std::array{o2::constants::physics::MassPiPlus, o2::constants::physics::MassKPlus}); + if (std::abs(invMassD0bar - o2::constants::physics::MassD0) > cfgCandCuts.topologicalCuts->get(ptBinD0, "delta inv. mass")) { + massHypo -= D0MassHypo::D0Bar; + bdtScoresD0bar = std::vector{1.f, 0.f, 0.f}; + } else { + // apply BDT models + if (cfgMl.apply) { + std::vector featuresCandD0bar = {dcaPos.getY(), dcaNeg.getY(), chi2PCA, cosPaD0, cosPaXYD0, decLenXYD0, decLenD0, dcaPos.getY() * dcaNeg.getY(), aod::pid_tpc_tof_utils::combineNSigma(trackNeg.tpcNSigmaPi(), trackNeg.tofNSigmaPi()), aod::pid_tpc_tof_utils::combineNSigma(trackPos.tpcNSigmaKa(), trackPos.tofNSigmaKa()), trackNeg.tpcNSigmaPi(), trackNeg.tpcNSigmaKa(), aod::pid_tpc_tof_utils::combineNSigma(trackNeg.tpcNSigmaKa(), trackNeg.tofNSigmaKa()), trackPos.tpcNSigmaPi(), trackPos.tpcNSigmaKa(), aod::pid_tpc_tof_utils::combineNSigma(trackPos.tpcNSigmaPi(), trackPos.tofNSigmaPi())}; + mlResponse.isSelectedMl(featuresCandD0bar, ptD0, bdtScoresD0bar); + } + } + } + if (massHypo == 0) { + continue; + } + + float etaD0 = RecoDecay::eta(pVecD0); + float phiD0 = RecoDecay::phi(pVecD0); + + // fill tables + // collision + if (!selectedCollisions.count(collision.globalIndex())) { + // fill collision table if not yet present + collTable(collision.posX(), collision.posY(), collision.posZ(), + collision.covXX(), collision.covXY(), collision.covXZ(), collision.covYY(), collision.covYZ(), collision.covZZ(), + collision.numContrib(), uint8_t(std::round(collision.centFT0C())), getCompressedOccupancy(collision.trackOccupancyInTimeRange()), getCompressedOccupancy(collision.ft0cOccupancyInTimeRange()), + eventIR.orbit, runNumber); + selectedCollisions[collision.globalIndex()] = collTable.lastIndex(); + } + // tracks + if (!selectedTracks.count(trackPos.globalIndex())) { + // fill track table with positive track if not yet present + trackTable(selectedCollisions[collision.globalIndex()], + trackPos.x(), trackPos.alpha(), trackPos.y(), trackPos.z(), trackPos.snp(), trackPos.tgl(), trackPos.signed1Pt(), // stored at PV + trackPos.cYY(), trackPos.cZY(), trackPos.cZZ(), trackPos.cSnpY(), trackPos.cSnpZ(), trackPos.cSnpSnp(), trackPos.cTglY(), trackPos.cTglZ(), trackPos.cTglSnp(), trackPos.cTglTgl(), trackPos.c1PtY(), trackPos.c1PtZ(), trackPos.c1PtSnp(), trackPos.c1PtTgl(), trackPos.c1Pt21Pt2(), + trackPos.tpcInnerParam(), trackPos.flags(), trackPos.itsClusterSizes(), trackPos.tpcNClsFindable(), trackPos.tpcNClsFindableMinusFound(), trackPos.tpcNClsFindableMinusCrossedRows(), trackPos.tpcNClsShared(), trackPos.trdPattern(), getCompressedChi2(trackPos.itsChi2NCl()), getCompressedChi2(trackPos.tpcChi2NCl()), getCompressedChi2(trackPos.trdChi2()), getCompressedChi2(trackPos.tofChi2()), trackPos.tpcSignal(), trackPos.trdSignal(), trackPos.length(), trackPos.tofExpMom(), trackPos.trackTime(), trackPos.trackTimeRes(), + dcaPos.getY(), dcaPos.getZ(), getCompressedNumSigmaPid(trackPos.tpcNSigmaPi()), getCompressedNumSigmaPid(trackPos.tpcNSigmaKa()), getCompressedNumSigmaPid(trackPos.tofNSigmaPi()), getCompressedNumSigmaPid(trackPos.tofNSigmaKa())); + selectedTracks[trackPos.globalIndex()] = trackTable.lastIndex(); + } + if (!selectedTracks.count(trackNeg.globalIndex())) { + // fill track table with negative track if not yet present + trackTable(selectedCollisions[collision.globalIndex()], + trackNeg.x(), trackNeg.alpha(), trackNeg.y(), trackNeg.z(), trackNeg.snp(), trackNeg.tgl(), trackNeg.signed1Pt(), // stored at PV + trackNeg.cYY(), trackNeg.cZY(), trackNeg.cZZ(), trackNeg.cSnpY(), trackNeg.cSnpZ(), trackNeg.cSnpSnp(), trackNeg.cTglY(), trackNeg.cTglZ(), trackNeg.cTglSnp(), trackNeg.cTglTgl(), trackNeg.c1PtY(), trackNeg.c1PtZ(), trackNeg.c1PtSnp(), trackNeg.c1PtTgl(), trackNeg.c1Pt21Pt2(), + trackNeg.tpcInnerParam(), trackNeg.flags(), trackNeg.itsClusterSizes(), trackNeg.tpcNClsFindable(), trackNeg.tpcNClsFindableMinusFound(), trackNeg.tpcNClsFindableMinusCrossedRows(), trackNeg.tpcNClsShared(), trackNeg.trdPattern(), getCompressedChi2(trackNeg.itsChi2NCl()), getCompressedChi2(trackNeg.tpcChi2NCl()), getCompressedChi2(trackNeg.trdChi2()), getCompressedChi2(trackNeg.tofChi2()), trackNeg.tpcSignal(), trackNeg.trdSignal(), trackNeg.length(), trackNeg.tofExpMom(), trackNeg.trackTime(), trackNeg.trackTimeRes(), + dcaNeg.getY(), dcaNeg.getZ(), getCompressedNumSigmaPid(trackNeg.tpcNSigmaPi()), getCompressedNumSigmaPid(trackNeg.tpcNSigmaKa()), getCompressedNumSigmaPid(trackNeg.tofNSigmaPi()), getCompressedNumSigmaPid(trackNeg.tofNSigmaKa())); + selectedTracks[trackNeg.globalIndex()] = trackTable.lastIndex(); + } + + // candidate + candTable(selectedCollisions[collision.globalIndex()], selectedTracks[trackPos.globalIndex()], selectedTracks[trackNeg.globalIndex()], massHypo, ptD0, etaD0, phiD0, invMassD0, invMassD0bar, + getCompressedDecayLength(decLenD0), getCompressedDecayLength(decLenXYD0), getCompressedNormDecayLength(decLenD0 / errorDecayLengthD0), getCompressedNormDecayLength(decLenXYD0 / errorDecayLengthXYD0), + getCompressedCosPa(cosPaD0), getCompressedCosPa(cosPaXYD0), getCompressedPointingAngle(paD0), getCompressedPointingAngle(paXYD0), getCompressedChi2(chi2PCA), getCompressedBdtScoreBkg(bdtScoresD0[0]), getCompressedBdtScoreSgn(bdtScoresD0[1]), getCompressedBdtScoreSgn(bdtScoresD0[2]), getCompressedBdtScoreBkg(bdtScoresD0bar[0]), getCompressedBdtScoreSgn(bdtScoresD0bar[1]), getCompressedBdtScoreSgn(bdtScoresD0bar[2])); + } // end loop over negative tracks + } // end loop over positive tracks + } // end loop over collisions tracks + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} From 65009380b4539d34b545f3bd565c8bc633402d7f Mon Sep 17 00:00:00 2001 From: Kamaljeet95 Date: Mon, 16 Jun 2025 19:24:38 +0530 Subject: [PATCH 093/871] [PWGDQ] Update MCSignalLibrary.cxx (MC-mumuFromPhi) (#11507) --- PWGDQ/Core/MCSignalLibrary.cxx | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/PWGDQ/Core/MCSignalLibrary.cxx b/PWGDQ/Core/MCSignalLibrary.cxx index 4486a7c8ea9..f342d790590 100644 --- a/PWGDQ/Core/MCSignalLibrary.cxx +++ b/PWGDQ/Core/MCSignalLibrary.cxx @@ -868,6 +868,12 @@ MCSignal* o2::aod::dqmcsignals::GetMCSignal(const char* name) signal = new MCSignal(name, "ee pairs from non-prompt j/psi decays", {prong, prong}, {1, 1}); // signal at pair level return signal; } + if (!nameStr.compare("mumuFromPhi")) { + MCProng prong(2, {13, 333}, {true, true}, {false, false}, {0, 0}, {0, 0}, {false, false}); + prong.SetSourceBit(0, MCProng::kPhysicalPrimary); + signal = new MCSignal(name, "mumu pairs from phi decays", {prong, prong}, {1, 1}); // signal at pair level + return signal; + } if (!nameStr.compare("mumuFromJpsi")) { MCProng prong(2, {13, 443}, {true, true}, {false, false}, {0, 0}, {0, 0}, {false, false}); signal = new MCSignal(name, "mumu pairs from j/psi decays", {prong, prong}, {1, 1}); // signal at pair level From 71fe91a380bfb801b707febfe34f1b579bcc2c90 Mon Sep 17 00:00:00 2001 From: Samuele Cattaruzzi <124249902+scattaru@users.noreply.github.com> Date: Mon, 16 Jun 2025 17:24:40 +0200 Subject: [PATCH 094/871] [PWGHF] Ds-h correlation, adding histograms in MC Gen processes (#11464) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Vít Kučera --- .../HFC/TableProducer/correlatorDsHadrons.cxx | 24 +++- PWGHF/HFC/Tasks/taskCorrelationDsHadrons.cxx | 131 ++++++++++-------- 2 files changed, 98 insertions(+), 57 deletions(-) diff --git a/PWGHF/HFC/TableProducer/correlatorDsHadrons.cxx b/PWGHF/HFC/TableProducer/correlatorDsHadrons.cxx index 2b9ea57bfd5..5460fede3e9 100644 --- a/PWGHF/HFC/TableProducer/correlatorDsHadrons.cxx +++ b/PWGHF/HFC/TableProducer/correlatorDsHadrons.cxx @@ -175,6 +175,7 @@ struct HfCorrelatorDsHadrons { Configurable ptCandMax{"ptCandMax", 50., "max. cand pT"}; Configurable ptTrackMin{"ptTrackMin", 0.3, "min. track pT"}; Configurable ptTrackMax{"ptTrackMax", 50., "max. track pT"}; + Configurable zVtxMax{"zVtxMax", 10., "max. position-z of the reconstructed collision"}; Configurable> classMl{"classMl", {0, 1, 2}, "Indexes of ML scores to be stored. Three indexes max."}; Configurable> binsPtD{"binsPtD", std::vector{o2::analysis::hf_cuts_ds_to_k_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"}; @@ -182,6 +183,7 @@ struct HfCorrelatorDsHadrons { Configurable> efficiencyD{"efficiencyD", {1., 1., 1., 1., 1., 1.}, "efficiency values for Ds meson"}; int hfcReducedCollisionIndex = 0; + static constexpr std::size_t NDaughtersDs{3u}; HfHelper hfHelper; SliceCache cache; @@ -284,6 +286,11 @@ struct HfCorrelatorDsHadrons { registry.add("hEtaMcGen", "Ds,Hadron particles - MC Gen", {HistType::kTH1F, {axisEta}}); registry.add("hPhiMcGen", "Ds,Hadron particles - MC Gen", {HistType::kTH1F, {axisPhi}}); registry.add("hMultFT0AMcGen", "Ds,Hadron multiplicity FT0A - MC Gen", {HistType::kTH1F, {axisMultiplicity}}); + registry.add("hCorrAllPrimaryParticles", "Ds-ch. part. correlations MC Gen", {HistType::kTH3F, {{axisPhi}, {axisPtD}, {axisPtHadron}}}); + registry.add("hCorrAllPrimaryHadrons", "Ds-h correlations MC Gen", {HistType::kTH3F, {{axisPhi}, {axisPtD}, {axisPtHadron}}}); + registry.add("hCorrAllPrimaryPions", "Ds-pion correlations MC Gen", {HistType::kTH3F, {{axisPhi}, {axisPtD}, {axisPtHadron}}}); + registry.add("hCorrAllPrimaryKaons", "Ds-kaon correlations MC Gen", {HistType::kTH3F, {{axisPhi}, {axisPtD}, {axisPtHadron}}}); + registry.add("hCorrAllPrimaryProtons", "Ds-proton correlations MC Gen", {HistType::kTH3F, {{axisPhi}, {axisPtD}, {axisPtHadron}}}); } } @@ -633,7 +640,7 @@ struct HfCorrelatorDsHadrons { if (useSel8 && !collision.sel8()) { continue; } - if (std::abs(collision.posZ()) > 10.) { + if (std::abs(collision.posZ()) > zVtxMax) { continue; } if (selNoSameBunchPileUpColl && !(collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup))) { @@ -666,7 +673,7 @@ struct HfCorrelatorDsHadrons { listDaughters.clear(); RecoDecay::getDaughters(particle, &listDaughters, arrDaughDsPDG, 2); int counterDaughters = 0; - if (listDaughters.size() == 3) { + if (listDaughters.size() == NDaughtersDs) { for (const auto& dauIdx : listDaughters) { // auto daughI = mcParticles.rawIteratorAt(dauIdx - mcParticles.offset()); auto daughI = groupedMcParticles.rawIteratorAt(dauIdx - groupedMcParticles.offset()); @@ -688,6 +695,19 @@ struct HfCorrelatorDsHadrons { if (!particleAssoc.isPhysicalPrimary()) { continue; } + + registry.fill(HIST("hCorrAllPrimaryParticles"), getDeltaPhi(particleAssoc.phi(), particle.phi()), particle.pt(), particleAssoc.pt()); + if (std::abs(particleAssoc.pdgCode()) == kPiPlus) { + registry.fill(HIST("hCorrAllPrimaryHadrons"), getDeltaPhi(particleAssoc.phi(), particle.phi()), particle.pt(), particleAssoc.pt()); + registry.fill(HIST("hCorrAllPrimaryPions"), getDeltaPhi(particleAssoc.phi(), particle.phi()), particle.pt(), particleAssoc.pt()); + } else if (std::abs(particleAssoc.pdgCode()) == kKPlus) { + registry.fill(HIST("hCorrAllPrimaryHadrons"), getDeltaPhi(particleAssoc.phi(), particle.phi()), particle.pt(), particleAssoc.pt()); + registry.fill(HIST("hCorrAllPrimaryKaons"), getDeltaPhi(particleAssoc.phi(), particle.phi()), particle.pt(), particleAssoc.pt()); + } else if (std::abs(particleAssoc.pdgCode()) == kProton) { + registry.fill(HIST("hCorrAllPrimaryHadrons"), getDeltaPhi(particleAssoc.phi(), particle.phi()), particle.pt(), particleAssoc.pt()); + registry.fill(HIST("hCorrAllPrimaryProtons"), getDeltaPhi(particleAssoc.phi(), particle.phi()), particle.pt(), particleAssoc.pt()); + } + // trackOrigin = RecoDecay::getCharmHadronOrigin(mcParticles, particleAssoc, true); trackOrigin = RecoDecay::getCharmHadronOrigin(groupedMcParticles, particleAssoc, true); registry.fill(HIST("hPtParticleAssocMcGen"), particleAssoc.pt()); diff --git a/PWGHF/HFC/Tasks/taskCorrelationDsHadrons.cxx b/PWGHF/HFC/Tasks/taskCorrelationDsHadrons.cxx index 3375d71b86d..5722e3998f1 100644 --- a/PWGHF/HFC/Tasks/taskCorrelationDsHadrons.cxx +++ b/PWGHF/HFC/Tasks/taskCorrelationDsHadrons.cxx @@ -17,6 +17,7 @@ #include #include #include +#include #include "CCDB/BasicCCDBManager.h" #include "Framework/AnalysisTask.h" @@ -87,8 +88,9 @@ struct HfTaskCorrelationDsHadrons { Configurable fdEffCcdbPath{"fdEffCcdbPath", "", "CCDB path for trigger efficiency"}; Configurable timestampCcdb{"timestampCcdb", -1, "timestamp of the efficiency files used to query in CCDB"}; - std::shared_ptr mEfficiencyD = nullptr; - std::shared_ptr mEfficiencyAssociated = nullptr; + std::shared_ptr hEfficiencyD = nullptr; + std::shared_ptr hEfficiencyAssociated = nullptr; + const float epsilon = 1.e-8; enum CandidateStep { kCandidateStepMcGenDsToKKPi = 0, @@ -254,26 +256,79 @@ struct HfTaskCorrelationDsHadrons { ccdb->setLocalObjectValidityChecking(); ccdb->setCreatedNotAfter(std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count()); - mEfficiencyD = std::shared_ptr(ccdb->getForTimeStamp(promptEffCcdbPath, timestampCcdb)); - if (mEfficiencyD == nullptr) { + hEfficiencyD = std::shared_ptr(ccdb->getForTimeStamp(promptEffCcdbPath, timestampCcdb)); + if (hEfficiencyD == nullptr) { LOGF(fatal, "Could not load efficiency histogram for trigger particles from %s", promptEffCcdbPath.value.c_str()); } LOGF(info, "Loaded trigger efficiency (prompt D) histogram from %s", promptEffCcdbPath.value.c_str()); - mEfficiencyAssociated = std::shared_ptr(ccdb->getForTimeStamp(associatedEffCcdbPath, timestampCcdb)); - if (mEfficiencyAssociated == nullptr) { + hEfficiencyAssociated = std::shared_ptr(ccdb->getForTimeStamp(associatedEffCcdbPath, timestampCcdb)); + if (hEfficiencyAssociated == nullptr) { LOGF(fatal, "Could not load efficiency histogram for associated particles from %s", associatedEffCcdbPath.value.c_str()); } LOGF(info, "Loaded associated efficiency histogram from %s", associatedEffCcdbPath.value.c_str()); } } + enum class EfficiencyMode { + DsOnly = 1, + DsHadronPair = 2 + }; + bool isSelectedCandidate(const int ptBinD, const float bdtScorePrompt, const float bdtScoreBkg) { return (ptBinD != -1 && bdtScorePrompt >= mlOutputPromptMin->at(ptBinD) && bdtScorePrompt <= mlOutputPromptMax->at(ptBinD) && bdtScoreBkg <= mlOutputBkg->at(ptBinD)); } + // template + double getEfficiencyWeight(float ptD, std::optional ptAssoc = std::nullopt, EfficiencyMode mode = EfficiencyMode::DsOnly) + { + if (!applyEfficiency) { + return 1.; + } + + double weight = 1.; + + switch (mode) { + case EfficiencyMode::DsOnly: + if (loadAccXEffFromCCDB) { + if (hEfficiencyD->GetBinContent(hEfficiencyD->FindBin(ptD)) <= epsilon) { + LOG(fatal) << "A bin content in Ds-meson efficiency histogram is zero!"; + } + weight = 1. / hEfficiencyD->GetBinContent(hEfficiencyD->FindBin(ptD)); + } else { + if (efficiencyD->at(o2::analysis::findBin(binsPtEfficiencyD, ptD)) <= epsilon) { + LOG(fatal) << "A bin content in Ds-meson efficiency vector is zero!"; + } + weight = 1. / efficiencyD->at(o2::analysis::findBin(binsPtEfficiencyD, ptD)); + } + break; + case EfficiencyMode::DsHadronPair: + if (loadAccXEffFromCCDB) { + if (ptAssoc && hEfficiencyAssociated) { + if (hEfficiencyAssociated->GetBinContent(hEfficiencyAssociated->FindBin(*ptAssoc)) <= epsilon) { + LOG(fatal) << "A bin content in associated particle efficiency histogram is zero!"; + } + weight = 1. / (hEfficiencyD->GetBinContent(hEfficiencyD->FindBin(ptD)) * hEfficiencyAssociated->GetBinContent(hEfficiencyAssociated->FindBin(*ptAssoc))); + } + } else { + if (ptAssoc) { + if (efficiencyHad->at(o2::analysis::findBin(binsPtEfficiencyHad, *ptAssoc)) <= epsilon) { + LOG(fatal) << "A bin content in associated particle efficiency vector is zero!"; + } + weight = 1. / (efficiencyD->at(o2::analysis::findBin(binsPtEfficiencyD, ptD)) * efficiencyHad->at(o2::analysis::findBin(binsPtEfficiencyHad, *ptAssoc))); + } + } + break; + default: + LOG(fatal) << "Unknown efficiency mode!"; + break; + } + + return weight; + } + void processData(DsHadronPairWithMl const& pairEntries, aod::DsCandRecoInfo const& candidates) { @@ -288,13 +343,8 @@ struct HfTaskCorrelationDsHadrons { continue; } - double efficiencyWeightD = 1.; - if (applyEfficiency) { - efficiencyWeightD = 1. / efficiencyD->at(o2::analysis::findBin(binsPtEfficiencyD, ptD)); - if (loadAccXEffFromCCDB) { - efficiencyWeightD = 1. / mEfficiencyD->GetBinContent(mEfficiencyD->FindBin(ptD)); - } - } + double efficiencyWeightD = getEfficiencyWeight(ptD); + registry.fill(HIST("hMassDsVsPt"), massD, ptD, efficiencyWeightD); registry.fill(HIST("hBdtScorePrompt"), bdtScorePrompt); registry.fill(HIST("hBdtScoreBkg"), bdtScoreBkg); @@ -322,13 +372,8 @@ struct HfTaskCorrelationDsHadrons { if (trackDcaXY > dcaXYTrackMax || trackDcaZ > dcaZTrackMax || trackTpcCrossedRows < nTpcCrossedRaws) { continue; } - double efficiencyWeight = 1.; - if (applyEfficiency) { - efficiencyWeight = 1. / (efficiencyD->at(o2::analysis::findBin(binsPtEfficiencyD, ptD)) * efficiencyHad->at(o2::analysis::findBin(binsPtEfficiencyHad, ptHadron))); - if (loadAccXEffFromCCDB) { - efficiencyWeight = 1. / (mEfficiencyD->GetBinContent(mEfficiencyD->FindBin(ptD)) * mEfficiencyAssociated->GetBinContent(mEfficiencyAssociated->FindBin(ptHadron))); - } - } + + double efficiencyWeight = getEfficiencyWeight(ptD, ptHadron, EfficiencyMode::DsHadronPair); // in signal region if (massD > signalRegionInner->at(ptBinD) && massD < signalRegionOuter->at(ptBinD)) { @@ -368,13 +413,8 @@ struct HfTaskCorrelationDsHadrons { continue; } - double efficiencyWeightD = 1.; - if (applyEfficiency) { - efficiencyWeightD = 1. / efficiencyD->at(o2::analysis::findBin(binsPtEfficiencyD, ptD)); - if (loadAccXEffFromCCDB) { - efficiencyWeightD = 1. / mEfficiencyD->GetBinContent(mEfficiencyD->FindBin(ptD)); - } - } + double efficiencyWeightD = getEfficiencyWeight(ptD); + if (isDsPrompt) { registry.fill(HIST("hMassPromptDsVsPt"), massD, ptD, efficiencyWeightD); registry.fill(HIST("hBdtScorePrompt"), bdtScorePrompt); @@ -411,13 +451,9 @@ struct HfTaskCorrelationDsHadrons { if (trackDcaXY > dcaXYTrackMax || trackDcaZ > dcaZTrackMax || trackTpcCrossedRows < nTpcCrossedRaws) { continue; } - double efficiencyWeight = 1.; - if (applyEfficiency) { - efficiencyWeight = 1. / (efficiencyD->at(o2::analysis::findBin(binsPtEfficiencyD, ptD)) * efficiencyHad->at(o2::analysis::findBin(binsPtEfficiencyHad, ptHadron))); - if (loadAccXEffFromCCDB) { - efficiencyWeight = 1. / (mEfficiencyD->GetBinContent(mEfficiencyD->FindBin(ptD)) * mEfficiencyAssociated->GetBinContent(mEfficiencyAssociated->FindBin(ptHadron))); - } - } + + double efficiencyWeight = getEfficiencyWeight(ptD, ptHadron, EfficiencyMode::DsHadronPair); + // in signal region if (massD > signalRegionInner->at(ptBinD) && massD < signalRegionOuter->at(ptBinD)) { // prompt and non-prompt division @@ -506,13 +542,8 @@ struct HfTaskCorrelationDsHadrons { if (trackDcaXY > dcaXYTrackMax || trackDcaZ > dcaZTrackMax || trackTpcCrossedRows < nTpcCrossedRaws) { continue; } - double efficiencyWeight = 1.; - if (applyEfficiency) { - efficiencyWeight = 1. / (efficiencyD->at(o2::analysis::findBin(binsPtEfficiencyD, ptD)) * efficiencyHad->at(o2::analysis::findBin(binsPtEfficiencyHad, ptHadron))); - if (loadAccXEffFromCCDB) { - efficiencyWeight = 1. / (mEfficiencyD->GetBinContent(mEfficiencyD->FindBin(ptD)) * mEfficiencyAssociated->GetBinContent(mEfficiencyAssociated->FindBin(ptHadron))); - } - } + + double efficiencyWeight = getEfficiencyWeight(ptD, ptHadron, EfficiencyMode::DsHadronPair); // in signal region if (massD > signalRegionInner->at(ptBinD) && massD < signalRegionOuter->at(ptBinD)) { @@ -548,13 +579,7 @@ struct HfTaskCorrelationDsHadrons { int poolBin = pairEntry.poolBin(); int ptBinD = o2::analysis::findBin(binsPtD, ptD); - double efficiencyWeight = 1.; - if (applyEfficiency) { - efficiencyWeight = 1. / (efficiencyD->at(o2::analysis::findBin(binsPtEfficiencyD, ptD)) * efficiencyHad->at(o2::analysis::findBin(binsPtEfficiencyHad, ptHadron))); - if (loadAccXEffFromCCDB) { - efficiencyWeight = 1. / (mEfficiencyD->GetBinContent(mEfficiencyD->FindBin(ptD)) * mEfficiencyAssociated->GetBinContent(mEfficiencyAssociated->FindBin(ptHadron))); - } - } + double efficiencyWeight = getEfficiencyWeight(ptD, ptHadron, EfficiencyMode::DsHadronPair); // in signal region if (massD > signalRegionInner->at(ptBinD) && massD < signalRegionOuter->at(ptBinD)) { @@ -606,13 +631,9 @@ struct HfTaskCorrelationDsHadrons { if (trackDcaXY > dcaXYTrackMax || trackDcaZ > dcaZTrackMax || trackTpcCrossedRows < nTpcCrossedRaws) { continue; } - double efficiencyWeight = 1.; - if (applyEfficiency) { - efficiencyWeight = 1. / (efficiencyD->at(o2::analysis::findBin(binsPtEfficiencyD, ptD)) * efficiencyHad->at(o2::analysis::findBin(binsPtEfficiencyHad, ptHadron))); - if (loadAccXEffFromCCDB) { - efficiencyWeight = 1. / (mEfficiencyD->GetBinContent(mEfficiencyD->FindBin(ptD)) * mEfficiencyAssociated->GetBinContent(mEfficiencyAssociated->FindBin(ptHadron))); - } - } + + double efficiencyWeight = getEfficiencyWeight(ptD, ptHadron, EfficiencyMode::DsHadronPair); + // in signal region if (massD > signalRegionInner->at(ptBinD) && massD < signalRegionOuter->at(ptBinD)) { // prompt and non-prompt division From 62fffc96df8836caa37608fd17ed0c60b86f046d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Jacazio?= Date: Mon, 16 Jun 2025 17:34:34 +0200 Subject: [PATCH 095/871] [ALICE3] A3 TOF: warning -> debug (#11635) --- ALICE3/TableProducer/OTF/onTheFlyTofPid.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ALICE3/TableProducer/OTF/onTheFlyTofPid.cxx b/ALICE3/TableProducer/OTF/onTheFlyTofPid.cxx index 099e42ea1b7..9f1659295a6 100644 --- a/ALICE3/TableProducer/OTF/onTheFlyTofPid.cxx +++ b/ALICE3/TableProducer/OTF/onTheFlyTofPid.cxx @@ -553,7 +553,7 @@ struct OnTheFlyTofPid { if (simConfig.considerEventTime.value) { etStatus = eventTime(tracksWithTime, tzero); if (!etStatus) { - LOG(warning) << "Event time calculation failed with " << tracksWithTime.size() << " tracks with time and " << dNdEta << " charged particles"; + LOG(debug) << "Event time calculation failed with " << tracksWithTime.size() << " tracks with time and " << dNdEta << " charged particles"; } } From e76e9fbcf599c51ef8172dd2a720de7a11dca01d Mon Sep 17 00:00:00 2001 From: Daiki Sekihata Date: Mon, 16 Jun 2025 23:15:08 +0200 Subject: [PATCH 096/871] [PWGEM/Dilepton] add kIsVertexTOFmatched for event selection (#11638) Co-authored-by: ALICE Action Bot --- PWGEM/Dilepton/Core/Dilepton.h | 71 ++++++++++--------- PWGEM/Dilepton/Core/DileptonMC.h | 60 ++++++++-------- PWGEM/Dilepton/Core/DimuonCut.h | 24 ++++--- PWGEM/Dilepton/Core/EMEventCut.cxx | 9 ++- PWGEM/Dilepton/Core/EMEventCut.h | 12 +++- PWGEM/Dilepton/Core/SingleTrackQC.h | 67 ++++++++--------- PWGEM/Dilepton/Core/SingleTrackQCMC.h | 69 +++++++++--------- .../TableProducer/skimmerPrimaryMuon.cxx | 62 ++++++++-------- PWGEM/Dilepton/Tasks/matchingMFT.cxx | 22 +++--- PWGEM/Dilepton/Utils/EMTrackUtilities.h | 6 +- 10 files changed, 220 insertions(+), 182 deletions(-) diff --git a/PWGEM/Dilepton/Core/Dilepton.h b/PWGEM/Dilepton/Core/Dilepton.h index 33f0ba99718..d5d63c90b8f 100644 --- a/PWGEM/Dilepton/Core/Dilepton.h +++ b/PWGEM/Dilepton/Core/Dilepton.h @@ -17,47 +17,48 @@ #ifndef PWGEM_DILEPTON_CORE_DILEPTON_H_ #define PWGEM_DILEPTON_CORE_DILEPTON_H_ -#include -#include -#include -#include -#include -#include -#include -#include -#include "TH1D.h" -#include "TString.h" -#include "Math/Vector4D.h" +#include "PWGEM/Dilepton/Core/DielectronCut.h" +#include "PWGEM/Dilepton/Core/DimuonCut.h" +#include "PWGEM/Dilepton/Core/EMEventCut.h" +#include "PWGEM/Dilepton/DataModel/dileptonTables.h" +#include "PWGEM/Dilepton/Utils/EMFwdTrack.h" +#include "PWGEM/Dilepton/Utils/EMTrack.h" +#include "PWGEM/Dilepton/Utils/EMTrackUtilities.h" +#include "PWGEM/Dilepton/Utils/EventHistograms.h" +#include "PWGEM/Dilepton/Utils/EventMixingHandler.h" +#include "PWGEM/Dilepton/Utils/MlResponseDielectronSingleTrack.h" +#include "PWGEM/Dilepton/Utils/PairUtilities.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/ASoAHelpers.h" +#include "Common/CCDB/RCTSelectionFlags.h" #include "Common/Core/RecoDecay.h" #include "Common/Core/trackUtilities.h" +#include "Tools/ML/MlResponse.h" + +#include "CCDB/BasicCCDBManager.h" #include "CommonConstants/LHCConstants.h" -#include "DataFormatsParameters/GRPLHCIFData.h" #include "DataFormatsParameters/GRPECSObject.h" +#include "DataFormatsParameters/GRPLHCIFData.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "DataFormatsParameters/GRPObject.h" +#include "DetectorsBase/GeometryManager.h" +#include "DetectorsBase/Propagator.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" #include "MathUtils/Utils.h" -#include "DetectorsBase/Propagator.h" -#include "DetectorsBase/GeometryManager.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "CCDB/BasicCCDBManager.h" -#include "Tools/ML/MlResponse.h" -#include "Common/CCDB/RCTSelectionFlags.h" +#include "Math/Vector4D.h" +#include "TH1D.h" +#include "TString.h" -#include "PWGEM/Dilepton/DataModel/dileptonTables.h" -#include "PWGEM/Dilepton/Core/DielectronCut.h" -#include "PWGEM/Dilepton/Core/DimuonCut.h" -#include "PWGEM/Dilepton/Core/EMEventCut.h" -#include "PWGEM/Dilepton/Utils/EMTrack.h" -#include "PWGEM/Dilepton/Utils/EMFwdTrack.h" -#include "PWGEM/Dilepton/Utils/EventMixingHandler.h" -#include "PWGEM/Dilepton/Utils/EventHistograms.h" -#include "PWGEM/Dilepton/Utils/EMTrackUtilities.h" -#include "PWGEM/Dilepton/Utils/PairUtilities.h" -#include "PWGEM/Dilepton/Utils/MlResponseDielectronSingleTrack.h" +#include +#include +#include +#include +#include +#include +#include +#include using namespace o2; using namespace o2::aod; @@ -139,7 +140,8 @@ struct Dilepton { Configurable cfgRequireNoTFB{"cfgRequireNoTFB", false, "require No time frame border in event cut"}; Configurable cfgRequireNoITSROFB{"cfgRequireNoITSROFB", false, "require no ITS readout frame border in event cut"}; Configurable cfgRequireNoSameBunchPileup{"cfgRequireNoSameBunchPileup", false, "require no same bunch pileup in event cut"}; - Configurable cfgRequireVertexITSTPC{"cfgRequireVertexITSTPC", false, "require Vertex ITSTPC in event cut"}; // ITS-TPC matched track contributes PV. + 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 cfgRequireGoodZvtxFT0vsPV{"cfgRequireGoodZvtxFT0vsPV", false, "require good Zvtx between FT0 vs. PV in event cut"}; Configurable cfgTrackOccupancyMin{"cfgTrackOccupancyMin", -2, "min. occupancy"}; Configurable cfgTrackOccupancyMax{"cfgTrackOccupancyMax", 1000000000, "max. occupancy"}; @@ -642,6 +644,7 @@ struct Dilepton { fEMEventCut.SetRequireNoITSROFB(eventcuts.cfgRequireNoITSROFB); fEMEventCut.SetRequireNoSameBunchPileup(eventcuts.cfgRequireNoSameBunchPileup); fEMEventCut.SetRequireVertexITSTPC(eventcuts.cfgRequireVertexITSTPC); + fEMEventCut.SetRequireVertexTOFmatched(eventcuts.cfgRequireVertexTOFmatched); fEMEventCut.SetRequireGoodZvtxFT0vsPV(eventcuts.cfgRequireGoodZvtxFT0vsPV); fEMEventCut.SetRequireNoCollInTimeRangeStandard(eventcuts.cfgRequireNoCollInTimeRangeStandard); fEMEventCut.SetRequireNoCollInTimeRangeStrict(eventcuts.cfgRequireNoCollInTimeRangeStrict); diff --git a/PWGEM/Dilepton/Core/DileptonMC.h b/PWGEM/Dilepton/Core/DileptonMC.h index 25ebe949553..b7e24e7d4d5 100644 --- a/PWGEM/Dilepton/Core/DileptonMC.h +++ b/PWGEM/Dilepton/Core/DileptonMC.h @@ -17,40 +17,40 @@ #ifndef PWGEM_DILEPTON_CORE_DILEPTONMC_H_ #define PWGEM_DILEPTON_CORE_DILEPTONMC_H_ -#include -#include -#include -#include +#include "PWGEM/Dilepton/Core/DielectronCut.h" +#include "PWGEM/Dilepton/Core/DimuonCut.h" +#include "PWGEM/Dilepton/Core/EMEventCut.h" +#include "PWGEM/Dilepton/DataModel/dileptonTables.h" +#include "PWGEM/Dilepton/Utils/EMTrackUtilities.h" +#include "PWGEM/Dilepton/Utils/EventHistograms.h" +#include "PWGEM/Dilepton/Utils/MCUtilities.h" +#include "PWGEM/Dilepton/Utils/MlResponseDielectronSingleTrack.h" +#include "PWGEM/Dilepton/Utils/PairUtilities.h" -#include "TString.h" -#include "Math/Vector4D.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/ASoAHelpers.h" +#include "Common/CCDB/RCTSelectionFlags.h" +#include "Common/Core/RecoDecay.h" +#include "Common/Core/trackUtilities.h" +#include "Tools/ML/MlResponse.h" + +#include "CCDB/BasicCCDBManager.h" #include "CommonConstants/LHCConstants.h" -#include "DataFormatsParameters/GRPLHCIFData.h" #include "DataFormatsParameters/GRPECSObject.h" - -#include "DetectorsBase/Propagator.h" -#include "DetectorsBase/GeometryManager.h" -#include "DataFormatsParameters/GRPObject.h" +#include "DataFormatsParameters/GRPLHCIFData.h" #include "DataFormatsParameters/GRPMagField.h" -#include "CCDB/BasicCCDBManager.h" -#include "Tools/ML/MlResponse.h" -#include "Common/CCDB/RCTSelectionFlags.h" +#include "DataFormatsParameters/GRPObject.h" +#include "DetectorsBase/GeometryManager.h" +#include "DetectorsBase/Propagator.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" -#include "Common/Core/RecoDecay.h" -#include "Common/Core/trackUtilities.h" +#include "Math/Vector4D.h" +#include "TString.h" -#include "PWGEM/Dilepton/DataModel/dileptonTables.h" -#include "PWGEM/Dilepton/Core/DielectronCut.h" -#include "PWGEM/Dilepton/Core/DimuonCut.h" -#include "PWGEM/Dilepton/Core/EMEventCut.h" -#include "PWGEM/Dilepton/Utils/MCUtilities.h" -#include "PWGEM/Dilepton/Utils/EventHistograms.h" -#include "PWGEM/Dilepton/Utils/EMTrackUtilities.h" -#include "PWGEM/Dilepton/Utils/PairUtilities.h" -#include "PWGEM/Dilepton/Utils/MlResponseDielectronSingleTrack.h" +#include +#include +#include +#include using namespace o2; using namespace o2::aod; @@ -131,7 +131,8 @@ struct DileptonMC { Configurable cfgRequireNoTFB{"cfgRequireNoTFB", false, "require No time frame border in event cut"}; Configurable cfgRequireNoITSROFB{"cfgRequireNoITSROFB", false, "require no ITS readout frame border in event cut"}; Configurable cfgRequireNoSameBunchPileup{"cfgRequireNoSameBunchPileup", false, "require no same bunch pileup in event cut"}; - Configurable cfgRequireVertexITSTPC{"cfgRequireVertexITSTPC", false, "require Vertex ITSTPC in event cut"}; // ITS-TPC matched track contributes PV. + 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 cfgRequireGoodZvtxFT0vsPV{"cfgRequireGoodZvtxFT0vsPV", false, "require good Zvtx between FT0 vs. PV in event cut"}; Configurable cfgTrackOccupancyMin{"cfgTrackOccupancyMin", -2, "min. occupancy"}; Configurable cfgTrackOccupancyMax{"cfgTrackOccupancyMax", 1000000000, "max. occupancy"}; @@ -608,6 +609,7 @@ struct DileptonMC { fEMEventCut.SetRequireNoITSROFB(eventcuts.cfgRequireNoITSROFB); fEMEventCut.SetRequireNoSameBunchPileup(eventcuts.cfgRequireNoSameBunchPileup); fEMEventCut.SetRequireVertexITSTPC(eventcuts.cfgRequireVertexITSTPC); + fEMEventCut.SetRequireVertexTOFmatched(eventcuts.cfgRequireVertexTOFmatched); fEMEventCut.SetRequireGoodZvtxFT0vsPV(eventcuts.cfgRequireGoodZvtxFT0vsPV); fEMEventCut.SetRequireNoCollInTimeRangeStandard(eventcuts.cfgRequireNoCollInTimeRangeStandard); fEMEventCut.SetRequireNoCollInTimeRangeStrict(eventcuts.cfgRequireNoCollInTimeRangeStrict); diff --git a/PWGEM/Dilepton/Core/DimuonCut.h b/PWGEM/Dilepton/Core/DimuonCut.h index b96afcd7c28..bc638c5a7b6 100644 --- a/PWGEM/Dilepton/Core/DimuonCut.h +++ b/PWGEM/Dilepton/Core/DimuonCut.h @@ -16,19 +16,21 @@ #ifndef PWGEM_DILEPTON_CORE_DIMUONCUT_H_ #define PWGEM_DILEPTON_CORE_DIMUONCUT_H_ +#include "PWGEM/Dilepton/Utils/EMTrackUtilities.h" + +#include "CommonConstants/PhysicsConstants.h" +#include "Framework/DataTypes.h" +#include "Framework/Logger.h" +#include "MathUtils/Utils.h" + +#include "Math/Vector4D.h" +#include "TNamed.h" + #include #include -#include -#include #include -#include "TNamed.h" -#include "Math/Vector4D.h" - -#include "MathUtils/Utils.h" -#include "Framework/Logger.h" -#include "Framework/DataTypes.h" -#include "CommonConstants/PhysicsConstants.h" -#include "PWGEM/Dilepton/Utils/EMTrackUtilities.h" +#include +#include using namespace o2::aod::pwgem::dilepton::utils::emtrackutil; @@ -195,7 +197,7 @@ class DimuonCut : public TNamed return track.chi2() < mMaxChi2; case DimuonCuts::kMatchingChi2MCHMFT: - return track.chi2MatchMCHMFT() < mMaxMatchingChi2MCHMFT; + return track.chi2MatchMCHMFT() / (2.f * (track.nClusters() + track.nClustersMFT()) - 5.f) < mMaxMatchingChi2MCHMFT; case DimuonCuts::kMatchingChi2MCHMID: return track.chi2MatchMCHMID() < mMaxMatchingChi2MCHMID; diff --git a/PWGEM/Dilepton/Core/EMEventCut.cxx b/PWGEM/Dilepton/Core/EMEventCut.cxx index a8f085f2646..682c496b8e7 100644 --- a/PWGEM/Dilepton/Core/EMEventCut.cxx +++ b/PWGEM/Dilepton/Core/EMEventCut.cxx @@ -13,9 +13,10 @@ // Class for em event selection // -#include "Framework/Logger.h" #include "PWGEM/Dilepton/Core/EMEventCut.h" +#include "Framework/Logger.h" + ClassImp(EMEventCut); void EMEventCut::SetRequireSel8(bool flag) @@ -61,6 +62,12 @@ void EMEventCut::SetRequireVertexITSTPC(bool flag) LOG(info) << "EM Event Cut, require vertex reconstructed by ITS-TPC matched track: " << mRequireVertexITSTPC; } +void EMEventCut::SetRequireVertexTOFmatched(bool flag) +{ + mRequireVertexTOFmatched = flag; + LOG(info) << "EM Event Cut, require vertex reconstructed by ITS-TPC matched track: " << mRequireVertexTOFmatched; +} + void EMEventCut::SetRequireGoodZvtxFT0vsPV(bool flag) { mRequireGoodZvtxFT0vsPV = flag; diff --git a/PWGEM/Dilepton/Core/EMEventCut.h b/PWGEM/Dilepton/Core/EMEventCut.h index 7434b6e3f72..8dc1b7ef961 100644 --- a/PWGEM/Dilepton/Core/EMEventCut.h +++ b/PWGEM/Dilepton/Core/EMEventCut.h @@ -16,10 +16,11 @@ #ifndef PWGEM_DILEPTON_CORE_EMEVENTCUT_H_ #define PWGEM_DILEPTON_CORE_EMEVENTCUT_H_ -#include "TNamed.h" #include "Common/CCDB/EventSelectionParams.h" #include "Common/CCDB/TriggerAliases.h" +#include "TNamed.h" + using namespace std; class EMEventCut : public TNamed @@ -37,6 +38,7 @@ class EMEventCut : public TNamed kNoITSROFB, // no ITS read out frame border kNoSameBunchPileup, kIsVertexITSTPC, + kIsVertexTOFmatched, kIsGoodZvtxFT0vsPV, kNoCollInTimeRangeStandard, kNoCollInTimeRangeStrict, @@ -73,6 +75,9 @@ class EMEventCut : public TNamed if (mRequireVertexITSTPC && !IsSelected(collision, EMEventCuts::kIsVertexITSTPC)) { return false; } + if (mRequireVertexTOFmatched && !IsSelected(collision, EMEventCuts::kIsVertexTOFmatched)) { + return false; + } if (mRequireGoodZvtxFT0vsPV && !IsSelected(collision, EMEventCuts::kIsGoodZvtxFT0vsPV)) { return false; } @@ -128,6 +133,9 @@ class EMEventCut : public TNamed case EMEventCuts::kIsVertexITSTPC: return collision.selection_bit(o2::aod::evsel::kIsVertexITSTPC); + case EMEventCuts::kIsVertexTOFmatched: + return collision.selection_bit(o2::aod::evsel::kIsVertexTOFmatched); + case EMEventCuts::kIsGoodZvtxFT0vsPV: return collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV); @@ -168,6 +176,7 @@ class EMEventCut : public TNamed void SetRequireNoITSROFB(bool flag); void SetRequireNoSameBunchPileup(bool flag); void SetRequireVertexITSTPC(bool flag); + void SetRequireVertexTOFmatched(bool flag); void SetRequireGoodZvtxFT0vsPV(bool flag); void SetRequireNoCollInTimeRangeStandard(bool flag); void SetRequireNoCollInTimeRangeStrict(bool flag); @@ -186,6 +195,7 @@ class EMEventCut : public TNamed bool mRequireNoITSROFB{false}; bool mRequireNoSameBunchPileup{false}; bool mRequireVertexITSTPC{false}; + bool mRequireVertexTOFmatched{false}; bool mRequireGoodZvtxFT0vsPV{false}; bool mRequireNoCollInTimeRangeStandard{false}; bool mRequireNoCollInTimeRangeStrict{false}; diff --git a/PWGEM/Dilepton/Core/SingleTrackQC.h b/PWGEM/Dilepton/Core/SingleTrackQC.h index 561e8a2adee..fddb2f1fb11 100644 --- a/PWGEM/Dilepton/Core/SingleTrackQC.h +++ b/PWGEM/Dilepton/Core/SingleTrackQC.h @@ -17,32 +17,33 @@ #ifndef PWGEM_DILEPTON_CORE_SINGLETRACKQC_H_ #define PWGEM_DILEPTON_CORE_SINGLETRACKQC_H_ -#include -#include -#include -#include - -#include "TString.h" -#include "Math/Vector4D.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/ASoAHelpers.h" - -#include "DetectorsBase/GeometryManager.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "CCDB/BasicCCDBManager.h" -#include "Tools/ML/MlResponse.h" -#include "Common/CCDB/RCTSelectionFlags.h" - -#include "PWGEM/Dilepton/DataModel/dileptonTables.h" #include "PWGEM/Dilepton/Core/DielectronCut.h" #include "PWGEM/Dilepton/Core/DimuonCut.h" #include "PWGEM/Dilepton/Core/EMEventCut.h" -#include "PWGEM/Dilepton/Utils/EventHistograms.h" +#include "PWGEM/Dilepton/DataModel/dileptonTables.h" #include "PWGEM/Dilepton/Utils/EMTrackUtilities.h" -#include "PWGEM/Dilepton/Utils/PairUtilities.h" +#include "PWGEM/Dilepton/Utils/EventHistograms.h" #include "PWGEM/Dilepton/Utils/MlResponseDielectronSingleTrack.h" +#include "PWGEM/Dilepton/Utils/PairUtilities.h" + +#include "Common/CCDB/RCTSelectionFlags.h" +#include "Tools/ML/MlResponse.h" + +#include "CCDB/BasicCCDBManager.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "DataFormatsParameters/GRPObject.h" +#include "DetectorsBase/GeometryManager.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" + +#include "Math/Vector4D.h" +#include "TString.h" + +#include +#include +#include +#include using namespace o2; using namespace o2::aod; @@ -95,7 +96,8 @@ struct SingleTrackQC { 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 cfgRequireNoSameBunchPileup{"cfgRequireNoSameBunchPileup", false, "require no same bunch pileup in event cut"}; - Configurable cfgRequireVertexITSTPC{"cfgRequireVertexITSTPC", false, "require Vertex ITSTPC in event cut"}; // ITS-TPC matched track contributes PV. + 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 cfgRequireGoodZvtxFT0vsPV{"cfgRequireGoodZvtxFT0vsPV", false, "require good Zvtx between FT0 vs. PV in event cut"}; Configurable cfgTrackOccupancyMin{"cfgTrackOccupancyMin", -2, "min. occupancy"}; Configurable cfgTrackOccupancyMax{"cfgTrackOccupancyMax", 1000000000, "max. occupancy"}; @@ -242,8 +244,8 @@ struct SingleTrackQC { fRegistry.add("Track/positive/hDCAxyRes_Pt", "DCA_{xy} resolution vs. pT;p_{T} (GeV/c);DCA_{xy} resolution (#mum)", kTH2F, {{200, 0, 10}, {500, 0., 500}}, false); fRegistry.add("Track/positive/hDCAzRes_Pt", "DCA_{z} resolution vs. pT;p_{T} (GeV/c);DCA_{z} resolution (#mum)", kTH2F, {{200, 0, 10}, {500, 0., 400}}, false); fRegistry.add("Track/positive/hDCA3dRes_Pt", "DCA_{3D} resolution vs. pT;p_{T} (GeV/c);DCA_{3D} resolution (#mum)", kTH2F, {{200, 0, 10}, {500, 0., 500}}, false); - fRegistry.add("Track/positive/hNclsTPC", "number of TPC clusters;TPC N_{cls}", kTH1F, {{161, -0.5, 160.5}}, false); - fRegistry.add("Track/positive/hNcrTPC", "number of TPC crossed rows;TPC N_{CR}", kTH1F, {{161, -0.5, 160.5}}, false); + fRegistry.add("Track/positive/hNclsTPC_Pt", "number of TPC clusters;p_{T,e} (GeV/c);TPC N_{cls}", kTH2F, {axis_pt, {161, -0.5, 160.5}}, false); + fRegistry.add("Track/positive/hNcrTPC_Pt", "number of TPC crossed rows;p_{T,e} (GeV/c);TPC N_{CR}", kTH2F, {axis_pt, {161, -0.5, 160.5}}, false); fRegistry.add("Track/positive/hChi2TPC", "chi2/number of TPC clusters;TPC #chi^{2}/N_{CR}", kTH1F, {{100, 0, 10}}, false); fRegistry.add("Track/positive/hDeltaPin", "p_{in} vs. p_{pv};p_{pv} (GeV/c);(p_{in} - p_{pv})/p_{pv}", kTH2F, {{1000, 0, 10}, {200, -1, +1}}, false); fRegistry.add("Track/positive/hTPCNcr2Nf", "TPC Ncr/Nfindable;TPC N_{CR}/N_{cls}^{findable}", kTH1F, {{200, 0, 2}}, false); @@ -299,8 +301,8 @@ struct SingleTrackQC { fRegistry.add("Track/positive/hNclsMFT", "number of MFT clusters", kTH1F, {{11, -0.5, 10.5}}, false); fRegistry.add("Track/positive/hPDCA", "pDCA;R at absorber end (cm);p #times DCA (GeV/c #upoint cm)", kTH2F, {{100, 0, 100}, {100, 0.0f, 1000}}, false); fRegistry.add("Track/positive/hChi2", "chi2;chi2", kTH1F, {{100, 0.0f, 100}}, false); - fRegistry.add("Track/positive/hChi2MatchMCHMID", "chi2 match MCH-MID;chi2", kTH1F, {{100, 0.0f, 100}}, false); - fRegistry.add("Track/positive/hChi2MatchMCHMFT", "chi2 match MCH-MFT;chi2", kTH1F, {{100, 0.0f, 100}}, false); + fRegistry.add("Track/positive/hChi2MatchMCHMID", "chi2 match MCH-MID;chi2", kTH1F, {{100, 0.0f, 10}}, false); + fRegistry.add("Track/positive/hChi2MatchMCHMFT", "chi2 match MCH-MFT;chi2/ndf", kTH1F, {{100, 0.0f, 10}}, false); fRegistry.add("Track/positive/hMFTClusterMap", "MFT cluster map", kTH1F, {{1024, -0.5, 1023.5}}, false); fRegistry.addClone("Track/positive/", "Track/negative/"); } @@ -364,6 +366,7 @@ struct SingleTrackQC { fEMEventCut.SetRequireNoITSROFB(eventcuts.cfgRequireNoITSROFB); fEMEventCut.SetRequireNoSameBunchPileup(eventcuts.cfgRequireNoSameBunchPileup); fEMEventCut.SetRequireVertexITSTPC(eventcuts.cfgRequireVertexITSTPC); + fEMEventCut.SetRequireVertexTOFmatched(eventcuts.cfgRequireVertexTOFmatched); fEMEventCut.SetRequireGoodZvtxFT0vsPV(eventcuts.cfgRequireGoodZvtxFT0vsPV); fEMEventCut.SetRequireNoCollInTimeRangeStandard(eventcuts.cfgRequireNoCollInTimeRangeStandard); fEMEventCut.SetRequireNoCollInTimeRangeStrict(eventcuts.cfgRequireNoCollInTimeRangeStrict); @@ -486,8 +489,8 @@ struct SingleTrackQC { fRegistry.fill(HIST("Track/positive/hDCAzRes_Pt"), track.pt(), std::sqrt(track.cZZ()) * 1e+4); // convert cm to um fRegistry.fill(HIST("Track/positive/hDCA3dRes_Pt"), track.pt(), sigmaDca3D(track) * 1e+4); // convert cm to um fRegistry.fill(HIST("Track/positive/hNclsITS"), track.itsNCls()); - fRegistry.fill(HIST("Track/positive/hNclsTPC"), track.tpcNClsFound()); - fRegistry.fill(HIST("Track/positive/hNcrTPC"), track.tpcNClsCrossedRows()); + fRegistry.fill(HIST("Track/positive/hNclsTPC_Pt"), track.pt(), track.tpcNClsFound()); + fRegistry.fill(HIST("Track/positive/hNcrTPC_Pt"), track.pt(), track.tpcNClsCrossedRows()); fRegistry.fill(HIST("Track/positive/hTPCNcr2Nf"), track.tpcCrossedRowsOverFindableCls()); fRegistry.fill(HIST("Track/positive/hTPCNcls2Nf"), track.tpcFoundOverFindableCls()); fRegistry.fill(HIST("Track/positive/hTPCNclsShared"), track.pt(), track.tpcFractionSharedCls()); @@ -526,8 +529,8 @@ struct SingleTrackQC { fRegistry.fill(HIST("Track/negative/hDCAzRes_Pt"), track.pt(), std::sqrt(track.cZZ()) * 1e+4); // convert cm to um fRegistry.fill(HIST("Track/negative/hDCA3dRes_Pt"), track.pt(), sigmaDca3D(track) * 1e+4); // convert cm to um fRegistry.fill(HIST("Track/negative/hNclsITS"), track.itsNCls()); - fRegistry.fill(HIST("Track/negative/hNclsTPC"), track.tpcNClsFound()); - fRegistry.fill(HIST("Track/negative/hNcrTPC"), track.tpcNClsCrossedRows()); + fRegistry.fill(HIST("Track/negative/hNclsTPC_Pt"), track.pt(), track.tpcNClsFound()); + fRegistry.fill(HIST("Track/negative/hNcrTPC_Pt"), track.pt(), track.tpcNClsCrossedRows()); fRegistry.fill(HIST("Track/negative/hTPCNcr2Nf"), track.tpcCrossedRowsOverFindableCls()); fRegistry.fill(HIST("Track/negative/hTPCNcls2Nf"), track.tpcFoundOverFindableCls()); fRegistry.fill(HIST("Track/negative/hTPCNclsShared"), track.pt(), track.tpcFractionSharedCls()); @@ -589,7 +592,7 @@ struct SingleTrackQC { fRegistry.fill(HIST("Track/positive/hPDCA"), track.rAtAbsorberEnd(), track.pDca()); fRegistry.fill(HIST("Track/positive/hChi2"), track.chi2()); fRegistry.fill(HIST("Track/positive/hChi2MatchMCHMID"), track.chi2MatchMCHMID()); - fRegistry.fill(HIST("Track/positive/hChi2MatchMCHMFT"), track.chi2MatchMCHMFT()); + fRegistry.fill(HIST("Track/positive/hChi2MatchMCHMFT"), track.chi2MatchMCHMFT() / (2 * (track.nClusters() + track.nClustersMFT()) - 5)); fRegistry.fill(HIST("Track/positive/hMFTClusterMap"), track.mftClusterMap()); } else { fRegistry.fill(HIST("Track/negative/hs"), track.pt(), track.eta(), track.phi(), dca_xy, weight); @@ -607,7 +610,7 @@ struct SingleTrackQC { fRegistry.fill(HIST("Track/negative/hPDCA"), track.rAtAbsorberEnd(), track.pDca()); fRegistry.fill(HIST("Track/negative/hChi2"), track.chi2()); fRegistry.fill(HIST("Track/negative/hChi2MatchMCHMID"), track.chi2MatchMCHMID()); - fRegistry.fill(HIST("Track/negative/hChi2MatchMCHMFT"), track.chi2MatchMCHMFT()); + fRegistry.fill(HIST("Track/negative/hChi2MatchMCHMFT"), track.chi2MatchMCHMFT() / (2 * (track.nClusters() + track.nClustersMFT()) - 5)); fRegistry.fill(HIST("Track/negative/hMFTClusterMap"), track.mftClusterMap()); } } diff --git a/PWGEM/Dilepton/Core/SingleTrackQCMC.h b/PWGEM/Dilepton/Core/SingleTrackQCMC.h index 5fb15b4ec26..5fdd69036a8 100644 --- a/PWGEM/Dilepton/Core/SingleTrackQCMC.h +++ b/PWGEM/Dilepton/Core/SingleTrackQCMC.h @@ -17,33 +17,34 @@ #ifndef PWGEM_DILEPTON_CORE_SINGLETRACKQCMC_H_ #define PWGEM_DILEPTON_CORE_SINGLETRACKQCMC_H_ -#include -#include -#include -#include - -#include "TString.h" -#include "Math/Vector4D.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/ASoAHelpers.h" - -#include "DetectorsBase/GeometryManager.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "CCDB/BasicCCDBManager.h" -#include "Tools/ML/MlResponse.h" -#include "Common/CCDB/RCTSelectionFlags.h" - -#include "PWGEM/Dilepton/DataModel/dileptonTables.h" #include "PWGEM/Dilepton/Core/DielectronCut.h" #include "PWGEM/Dilepton/Core/DimuonCut.h" #include "PWGEM/Dilepton/Core/EMEventCut.h" -#include "PWGEM/Dilepton/Utils/MCUtilities.h" -#include "PWGEM/Dilepton/Utils/EventHistograms.h" +#include "PWGEM/Dilepton/DataModel/dileptonTables.h" #include "PWGEM/Dilepton/Utils/EMTrackUtilities.h" -#include "PWGEM/Dilepton/Utils/PairUtilities.h" +#include "PWGEM/Dilepton/Utils/EventHistograms.h" +#include "PWGEM/Dilepton/Utils/MCUtilities.h" #include "PWGEM/Dilepton/Utils/MlResponseDielectronSingleTrack.h" +#include "PWGEM/Dilepton/Utils/PairUtilities.h" + +#include "Common/CCDB/RCTSelectionFlags.h" +#include "Tools/ML/MlResponse.h" + +#include "CCDB/BasicCCDBManager.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "DataFormatsParameters/GRPObject.h" +#include "DetectorsBase/GeometryManager.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" + +#include "Math/Vector4D.h" +#include "TString.h" + +#include +#include +#include +#include using namespace o2; using namespace o2::aod; @@ -103,7 +104,8 @@ struct SingleTrackQCMC { 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 cfgRequireNoSameBunchPileup{"cfgRequireNoSameBunchPileup", false, "require no same bunch pileup in event cut"}; - Configurable cfgRequireVertexITSTPC{"cfgRequireVertexITSTPC", false, "require Vertex ITSTPC in event cut"}; // ITS-TPC matched track contributes PV. + 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 cfgRequireGoodZvtxFT0vsPV{"cfgRequireGoodZvtxFT0vsPV", false, "require good Zvtx between FT0 vs. PV in event cut"}; Configurable cfgTrackOccupancyMin{"cfgTrackOccupancyMin", -2, "min. occupancy"}; Configurable cfgTrackOccupancyMax{"cfgTrackOccupancyMax", 1000000000, "max. occupancy"}; @@ -273,8 +275,8 @@ struct SingleTrackQCMC { fRegistry.add("Track/lf/positive/hDCAxyRes_Pt", "DCA_{xy} resolution vs. pT;p_{T} (GeV/c);DCA_{xy} resolution (#mum)", kTH2F, {{200, 0, 10}, {500, 0., 500}}, false); fRegistry.add("Track/lf/positive/hDCAzRes_Pt", "DCA_{z} resolution vs. pT;p_{T} (GeV/c);DCA_{z} resolution (#mum)", kTH2F, {{200, 0, 10}, {500, 0., 500}}, false); fRegistry.add("Track/lf/positive/hDCA3dRes_Pt", "DCA_{3D} resolution vs. pT;p_{T} (GeV/c);DCA_{3D} resolution (#mum)", kTH2F, {{200, 0, 10}, {500, 0., 500}}, false); - fRegistry.add("Track/lf/positive/hNclsTPC", "number of TPC clusters", kTH1F, {{161, -0.5, 160.5}}, false); - fRegistry.add("Track/lf/positive/hNcrTPC", "number of TPC crossed rows", kTH1F, {{161, -0.5, 160.5}}, false); + fRegistry.add("Track/lf/positive/hNclsTPC_Pt", "number of TPC clusters;p_{T,e} (GeV/c);;TPC N_{cls}", kTH2F, {axis_pt, {161, -0.5, 160.5}}, false); + fRegistry.add("Track/lf/positive/hNcrTPC_Pt", "number of TPC crossed rows;p_{T,e} (GeV/c);;TPC N_{CR}", kTH2F, {axis_pt, {161, -0.5, 160.5}}, false); fRegistry.add("Track/lf/positive/hChi2TPC", "chi2/number of TPC clusters", kTH1F, {{100, 0, 10}}, false); fRegistry.add("Track/lf/positive/hTPCNcr2Nf", "TPC Ncr/Nfindable", kTH1F, {{200, 0, 2}}, false); fRegistry.add("Track/lf/positive/hTPCNcls2Nf", "TPC Ncls/Nfindable", kTH1F, {{200, 0, 2}}, false); @@ -356,8 +358,8 @@ struct SingleTrackQCMC { fRegistry.add("Track/lf/positive/hNclsMFT", "number of MFT clusters", kTH1F, {{11, -0.5, 10.5}}, false); fRegistry.add("Track/lf/positive/hPDCA", "pDCA;R at absorber (cm);p #times DCA (GeV/c #upoint cm)", kTH2F, {{100, 0, 100}, {100, 0.0f, 1000}}, false); fRegistry.add("Track/lf/positive/hChi2", "chi2;chi2", kTH1F, {{100, 0.0f, 100}}, false); - fRegistry.add("Track/lf/positive/hChi2MatchMCHMID", "chi2 match MCH-MID;chi2", kTH1F, {{100, 0.0f, 100}}, false); - fRegistry.add("Track/lf/positive/hChi2MatchMCHMFT", "chi2 match MCH-MFT;chi2", kTH1F, {{100, 0.0f, 100}}, false); + fRegistry.add("Track/lf/positive/hChi2MatchMCHMID", "chi2 match MCH-MID;chi2", kTH1F, {{100, 0.0f, 10}}, false); + fRegistry.add("Track/lf/positive/hChi2MatchMCHMFT", "chi2 match MCH-MFT;chi2/ndf", kTH1F, {{100, 0.0f, 10}}, false); fRegistry.add("Track/lf/positive/hMFTClusterMap", "MFT cluster map", kTH1F, {{1024, -0.5, 1023.5}}, false); fRegistry.add("Track/lf/positive/hPtGen_DeltaPtOverPtGen", "muon p_{T} resolution;p_{T}^{gen} (GeV/c);(p_{T}^{rec} - p_{T}^{gen})/p_{T}^{gen}", kTH2F, {{200, 0, 10}, {200, -1.0f, 1.0f}}, true); fRegistry.add("Track/lf/positive/hPtGen_DeltaEta", "muon #eta resolution;p_{T}^{gen} (GeV/c);#eta^{rec} - #eta^{gen}", kTH2F, {{200, 0, 10}, {100, -0.05f, 0.05f}}, true); @@ -423,6 +425,7 @@ struct SingleTrackQCMC { fEMEventCut.SetRequireNoITSROFB(eventcuts.cfgRequireNoITSROFB); fEMEventCut.SetRequireNoSameBunchPileup(eventcuts.cfgRequireNoSameBunchPileup); fEMEventCut.SetRequireVertexITSTPC(eventcuts.cfgRequireVertexITSTPC); + fEMEventCut.SetRequireVertexTOFmatched(eventcuts.cfgRequireVertexTOFmatched); fEMEventCut.SetRequireGoodZvtxFT0vsPV(eventcuts.cfgRequireGoodZvtxFT0vsPV); fEMEventCut.SetRequireNoCollInTimeRangeStandard(eventcuts.cfgRequireNoCollInTimeRangeStandard); fEMEventCut.SetRequireNoCollInTimeRangeStrict(eventcuts.cfgRequireNoCollInTimeRangeStrict); @@ -590,8 +593,8 @@ struct SingleTrackQCMC { fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hDCAzRes_Pt"), track.pt(), std::sqrt(track.cZZ()) * 1e+4); // convert cm to um fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hDCA3dRes_Pt"), track.pt(), sigmaDca3D(track) * 1e+4); // convert cm to um fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hNclsITS"), track.itsNCls()); - fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hNclsTPC"), track.tpcNClsFound()); - fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hNcrTPC"), track.tpcNClsCrossedRows()); + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hNclsTPC_Pt"), track.pt(), track.tpcNClsFound()); + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hNcrTPC_Pt"), track.pt(), track.tpcNClsCrossedRows()); fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hTPCNcr2Nf"), track.tpcCrossedRowsOverFindableCls()); fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hTPCNcls2Nf"), track.tpcFoundOverFindableCls()); fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hTPCNclsShared"), track.pt(), track.tpcFractionSharedCls()); @@ -635,8 +638,8 @@ struct SingleTrackQCMC { fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hDCAzRes_Pt"), track.pt(), std::sqrt(track.cZZ()) * 1e+4); // convert cm to um fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hDCA3dRes_Pt"), track.pt(), sigmaDca3D(track) * 1e+4); // convert cm to um fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hNclsITS"), track.itsNCls()); - fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hNclsTPC"), track.tpcNClsFound()); - fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hNcrTPC"), track.tpcNClsCrossedRows()); + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hNclsTPC_Pt"), track.pt(), track.tpcNClsFound()); + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hNcrTPC_Pt"), track.pt(), track.tpcNClsCrossedRows()); fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hTPCNcr2Nf"), track.tpcCrossedRowsOverFindableCls()); fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hTPCNcls2Nf"), track.tpcFoundOverFindableCls()); fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hTPCNclsShared"), track.pt(), track.tpcFractionSharedCls()); @@ -705,7 +708,7 @@ struct SingleTrackQCMC { fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hPDCA"), track.rAtAbsorberEnd(), track.pDca()); fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hChi2"), track.chi2()); fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hChi2MatchMCHMID"), track.chi2MatchMCHMID()); - fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hChi2MatchMCHMFT"), track.chi2MatchMCHMFT()); + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hChi2MatchMCHMFT"), track.chi2MatchMCHMFT() / (2 * (track.nClusters() + track.nClustersMFT() - 5))); fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hMFTClusterMap"), track.mftClusterMap()); fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hPtGen_DeltaPtOverPtGen"), mctrack.pt(), (track.pt() - mctrack.pt()) / mctrack.pt()); fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hPtGen_DeltaEta"), mctrack.pt(), track.eta() - mctrack.eta()); @@ -728,7 +731,7 @@ struct SingleTrackQCMC { fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hPDCA"), track.rAtAbsorberEnd(), track.pDca()); fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hChi2"), track.chi2()); fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hChi2MatchMCHMID"), track.chi2MatchMCHMID()); - fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hChi2MatchMCHMFT"), track.chi2MatchMCHMFT()); + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hChi2MatchMCHMFT"), track.chi2MatchMCHMFT() / (2 * (track.nClusters() + track.nClustersMFT() - 5))); fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hMFTClusterMap"), track.mftClusterMap()); fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hPtGen_DeltaPtOverPtGen"), mctrack.pt(), (track.pt() - mctrack.pt()) / mctrack.pt()); fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hPtGen_DeltaEta"), mctrack.pt(), track.eta() - mctrack.eta()); diff --git a/PWGEM/Dilepton/TableProducer/skimmerPrimaryMuon.cxx b/PWGEM/Dilepton/TableProducer/skimmerPrimaryMuon.cxx index 2558b46cb3a..03189bf3f4b 100644 --- a/PWGEM/Dilepton/TableProducer/skimmerPrimaryMuon.cxx +++ b/PWGEM/Dilepton/TableProducer/skimmerPrimaryMuon.cxx @@ -12,36 +12,35 @@ /// \brief write relevant information for muons. /// \author daiki.sekihata@cern.ch -#include -#include -#include -#include -#include - -#include "Math/Vector4D.h" -#include "Math/SMatrix.h" +#include "PWGEM/Dilepton/DataModel/dileptonTables.h" -#include "Framework/DataTypes.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "CommonConstants/PhysicsConstants.h" -#include "Common/DataModel/CollisionAssociationTables.h" #include "Common/Core/TableHelper.h" +#include "Common/Core/fwdtrackUtilities.h" +#include "Common/DataModel/CollisionAssociationTables.h" #include "CCDB/BasicCCDBManager.h" +#include "CommonConstants/PhysicsConstants.h" #include "DataFormatsParameters/GRPMagField.h" -#include "TGeoGlobalMagField.h" -#include "Field/MagneticField.h" - #include "DetectorsBase/Propagator.h" +#include "Field/MagneticField.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/DataTypes.h" +#include "Framework/runDataProcessing.h" #include "GlobalTracking/MatchGlobalFwd.h" #include "MCHTracking/TrackExtrap.h" #include "MCHTracking/TrackParam.h" #include "ReconstructionDataFormats/TrackFwd.h" -#include "Common/Core/fwdtrackUtilities.h" -#include "PWGEM/Dilepton/DataModel/dileptonTables.h" +#include "Math/SMatrix.h" +#include "Math/Vector4D.h" +#include "TGeoGlobalMagField.h" + +#include +#include +#include +#include +#include using namespace o2; using namespace o2::soa; @@ -149,11 +148,11 @@ struct skimmerPrimaryMuon { fRegistry.add("MFTMCHMID/hRatAbsorberEnd", "R at absorber end;R at absorber end (cm)", kTH1F, {{100, 0.0f, 100}}, false); fRegistry.add("MFTMCHMID/hPDCA_Rabs", "pDCA vs. Rabs;R at absorber end (cm);p #times DCA (GeV/c #upoint cm)", kTH2F, {{100, 0, 100}, {100, 0.0f, 1000}}, false); fRegistry.add("MFTMCHMID/hChi2", "chi2;chi2", kTH1F, {{100, 0.0f, 100}}, false); - fRegistry.add("MFTMCHMID/hChi2MFT", "chi2 MFT;chi2 MFT", kTH1F, {{100, 0.0f, 100}}, false); - fRegistry.add("MFTMCHMID/hChi2MatchMCHMID", "chi2 match MCH-MID;chi2", kTH1F, {{100, 0.0f, 100}}, false); - fRegistry.add("MFTMCHMID/hChi2MatchMCHMFT", "chi2 match MCH-MFT;chi2", kTH1F, {{100, 0.0f, 100}}, false); + fRegistry.add("MFTMCHMID/hChi2MFT", "chi2 MFT;chi2 MFT/ndf", kTH1F, {{100, 0.0f, 100}}, false); + fRegistry.add("MFTMCHMID/hChi2MatchMCHMID", "chi2 match MCH-MID;chi2", kTH1F, {{100, 0.0f, 10}}, false); + fRegistry.add("MFTMCHMID/hChi2MatchMCHMFT", "chi2 match MCH-MFT;chi2/ndf", kTH1F, {{100, 0.0f, 10}}, false); fRegistry.add("MFTMCHMID/hMatchScoreMCHMFT", "match score MCH-MFT;score", kTH1F, {{100, 0.0f, 100}}, false); - fRegistry.add("MFTMCHMID/hDCAxy2D", "DCA x vs. y;DCA_{x} (cm);DCA_{y} (cm)", kTH2F, {{200, -0.5, 0.5}, {200, -0.5, +0.5}}, false); + fRegistry.add("MFTMCHMID/hDCAxy2D", "DCA x vs. y;DCA_{x} (cm);DCA_{y} (cm)", kTH2F, {{200, -1, 1}, {200, -1, +1}}, false); fRegistry.add("MFTMCHMID/hDCAxy2DinSigma", "DCA x vs. y in sigma;DCA_{x} (#sigma);DCA_{y} (#sigma)", kTH2F, {{200, -10, 10}, {200, -10, +10}}, false); fRegistry.add("MFTMCHMID/hDCAxy", "DCAxy;DCA_{xy} (cm);", kTH1F, {{100, 0, 1}}, false); fRegistry.add("MFTMCHMID/hDCAxyinSigma", "DCAxy in sigma;DCA_{xy} (#sigma);", kTH1F, {{100, 0, 10}}, false); @@ -208,7 +207,7 @@ struct skimmerPrimaryMuon { template void fillFwdTrackTable(TCollision const& collision, TFwdTrack fwdtrack, TFwdTracks const&, TMFTTracks const&, const bool isAmbiguous) { - if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && (fwdtrack.chi2MatchMCHMFT() > maxMatchingChi2MCHMFT || fwdtrack.chi2() > maxChi2GL)) { + if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && fwdtrack.chi2() > maxChi2GL) { return; } // Users have to decide the best match between MFT and MCH-MID at analysis level. The same global muon is repeatedly stored. @@ -254,6 +253,7 @@ struct skimmerPrimaryMuon { // float tgl = fwdtrack.tgl(); float chi2mft = 0.f; uint64_t mftClusterSizesAndTrackFlags = 0; + int ndf_mchmft = 999; if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) { const auto& mchtrack = fwdtrack.template matchMCHTrack_as(); // MCH-MID @@ -271,7 +271,13 @@ struct skimmerPrimaryMuon { const auto& mfttrack = fwdtrack.template matchMFTTrack_as(); nClustersMFT = mfttrack.nClusters(); mftClusterSizesAndTrackFlags = mfttrack.mftClusterSizesAndTrackFlags(); - chi2mft = mfttrack.chi2(); + chi2mft = mfttrack.chi2() / (2.f * nClustersMFT - 5.f); + ndf_mchmft = 2.f * (mchtrack.nClusters() + nClustersMFT) - 5.f; + + if (fwdtrack.chi2MatchMCHMFT() / ndf_mchmft > maxMatchingChi2MCHMFT) { + return; + } + if (refitGlobalMuon) { eta = mfttrack.eta(); phi = mfttrack.phi(); @@ -343,7 +349,7 @@ struct skimmerPrimaryMuon { fRegistry.fill(HIST("MFTMCHMID/hChi2"), fwdtrack.chi2()); fRegistry.fill(HIST("MFTMCHMID/hChi2MFT"), chi2mft); fRegistry.fill(HIST("MFTMCHMID/hChi2MatchMCHMID"), fwdtrack.chi2MatchMCHMID()); - fRegistry.fill(HIST("MFTMCHMID/hChi2MatchMCHMFT"), fwdtrack.chi2MatchMCHMFT()); + fRegistry.fill(HIST("MFTMCHMID/hChi2MatchMCHMFT"), fwdtrack.chi2MatchMCHMFT() / ndf_mchmft); fRegistry.fill(HIST("MFTMCHMID/hMatchScoreMCHMFT"), fwdtrack.matchScoreMCHMFT()); fRegistry.fill(HIST("MFTMCHMID/hDCAxy2D"), dcaX, dcaY); fRegistry.fill(HIST("MFTMCHMID/hDCAxy2DinSigma"), dcaX / std::sqrt(cXXatDCA), dcaY / std::sqrt(cYYatDCA)); @@ -367,8 +373,8 @@ struct skimmerPrimaryMuon { fRegistry.fill(HIST("MCHMID/hChi2"), fwdtrack.chi2()); fRegistry.fill(HIST("MCHMID/hChi2MFT"), chi2mft); fRegistry.fill(HIST("MCHMID/hChi2MatchMCHMID"), fwdtrack.chi2MatchMCHMID()); - fRegistry.fill(HIST("MCHMID/hChi2MatchMCHMFT"), fwdtrack.chi2MatchMCHMFT()); - fRegistry.fill(HIST("MCHMID/hMatchScoreMCHMFT"), fwdtrack.matchScoreMCHMFT()); + fRegistry.fill(HIST("MCHMID/hChi2MatchMCHMFT"), 0.f); + fRegistry.fill(HIST("MCHMID/hMatchScoreMCHMFT"), 0.f); fRegistry.fill(HIST("MCHMID/hDCAxy2D"), dcaX, dcaY); fRegistry.fill(HIST("MCHMID/hDCAxy2DinSigma"), dcaX / std::sqrt(cXXatDCA), dcaY / std::sqrt(cYYatDCA)); fRegistry.fill(HIST("MCHMID/hDCAxy"), dcaXY); diff --git a/PWGEM/Dilepton/Tasks/matchingMFT.cxx b/PWGEM/Dilepton/Tasks/matchingMFT.cxx index 0a9ee91a4c0..2275956d3dd 100644 --- a/PWGEM/Dilepton/Tasks/matchingMFT.cxx +++ b/PWGEM/Dilepton/Tasks/matchingMFT.cxx @@ -174,8 +174,8 @@ struct matchingMFT { fRegistry.add("MFTMCHMID/primary/correct/hPDCA_Rabs", "pDCA vs. Rabs;R at absorber end (cm);p #times DCA (GeV/c #upoint cm)", kTH2F, {{100, 0, 100}, {100, 0.0f, 1000}}, false); fRegistry.add("MFTMCHMID/primary/correct/hChi2", "chi2;chi2", kTH1F, {{100, 0.0f, 100}}, false); fRegistry.add("MFTMCHMID/primary/correct/hChi2MFT", "chi2 MFT/ndf;chi2 MFT/ndf", kTH1F, {{100, 0.0f, 10}}, false); - fRegistry.add("MFTMCHMID/primary/correct/hChi2MatchMCHMID", "chi2 match MCH-MID;chi2", kTH1F, {{100, 0.0f, 100}}, false); - fRegistry.add("MFTMCHMID/primary/correct/hChi2MatchMCHMFT", "chi2 match MCH-MFT;chi2", kTH1F, {{100, 0.0f, 100}}, false); + fRegistry.add("MFTMCHMID/primary/correct/hChi2MatchMCHMID", "chi2 match MCH-MID;chi2", kTH1F, {{100, 0.0f, 10}}, false); + fRegistry.add("MFTMCHMID/primary/correct/hChi2MatchMCHMFT", "chi2 match MCH-MFT;chi2/ndf", kTH1F, {{100, 0.0f, 10}}, false); fRegistry.add("MFTMCHMID/primary/correct/hDCAxy2D", "DCA x vs. y;DCA_{x} (cm);DCA_{y} (cm)", kTH2F, {{200, -0.5, 0.5}, {200, -0.5, +0.5}}, false); fRegistry.add("MFTMCHMID/primary/correct/hDCAz", "DCA z;DCA_{z} (cm);", kTH1F, {{1000, 0, 10}}, false); fRegistry.add("MFTMCHMID/primary/correct/hDCAxy2DinSigma", "DCA x vs. y in sigma;DCA_{x} (#sigma);DCA_{y} (#sigma)", kTH2F, {{200, -10, 10}, {200, -10, +10}}, false); @@ -299,7 +299,13 @@ struct matchingMFT { // LOGF(info, "mcParticle_MFTMCHMID.pdgCode() = %d, mcParticle_MCHMID.pdgCode() = %d, mcParticle_MFT.pdgCode() = %d", mcParticle_MFTMCHMID.pdgCode(), mcParticle_MCHMID.pdgCode(), mcParticle_MFT.pdgCode()); // LOGF(info, "mcParticle_MFTMCHMID.globalIndex() = %d, mcParticle_MCHMID.globalIndex() = %d, mcParticle_MFT.globalIndex() = %d", mcParticle_MFTMCHMID.globalIndex(), mcParticle_MCHMID.globalIndex(), mcParticle_MFT.globalIndex()); - if (fwdtrack.chi2MatchMCHMFT() > maxMatchingChi2MCHMFT) { + int nClustersMFT = mfttrack.nClusters(); + float chi2mft = mfttrack.chi2() / (2.f * nClustersMFT - 5.f); + if (chi2mft < 0.f || maxChi2MFT < chi2mft) { + return; + } + + if (fwdtrack.chi2MatchMCHMFT() > maxMatchingChi2MCHMFT / (2.f * (mchtrack.nClusters() + nClustersMFT) - 5.f)) { return; } @@ -311,7 +317,7 @@ struct matchingMFT { return; } - if (mfttrack.nClusters() < minNclustersMFT) { + if (nClustersMFT < minNclustersMFT) { return; } @@ -359,12 +365,6 @@ struct matchingMFT { float dcaY_Matched = propmuonAtDCA_Matched.getY() - collision.posY(); float dcaXY_Matched = std::sqrt(dcaX_Matched * dcaX_Matched + dcaY_Matched * dcaY_Matched); float pDCA = mchtrack.p() * dcaXY_Matched; - int nClustersMFT = mfttrack.nClusters(); - float chi2mft = mfttrack.chi2() / (2.f * nClustersMFT - 5.f); - // float chi2mft = mfttrack.chi2(); - if (chi2mft < 0.f || maxChi2MFT < chi2mft) { - return; - } o2::dataformats::GlobalFwdTrack propmuonAtPV_Matched = propagateMuon(mchtrack, collision, propagationPoint::kToVertex); if (refitGlobalMuon) { @@ -417,7 +417,7 @@ struct matchingMFT { fRegistry.fill(HIST("MFTMCHMID/primary/correct/hChi2"), fwdtrack.chi2()); fRegistry.fill(HIST("MFTMCHMID/primary/correct/hChi2MFT"), chi2mft); fRegistry.fill(HIST("MFTMCHMID/primary/correct/hChi2MatchMCHMID"), fwdtrack.chi2MatchMCHMID()); - fRegistry.fill(HIST("MFTMCHMID/primary/correct/hChi2MatchMCHMFT"), fwdtrack.chi2MatchMCHMFT()); + fRegistry.fill(HIST("MFTMCHMID/primary/correct/hChi2MatchMCHMFT"), fwdtrack.chi2MatchMCHMFT() / (2 * (fwdtrack.nClusters() + nClustersMFT) - 5)); fRegistry.fill(HIST("MFTMCHMID/primary/correct/hDCAxy2D"), dcaX, dcaY); fRegistry.fill(HIST("MFTMCHMID/primary/correct/hDCAz"), dcaZ); fRegistry.fill(HIST("MFTMCHMID/primary/correct/hDCAxy2DinSigma"), dcaX / std::sqrt(cXXatDCA), dcaY / std::sqrt(cYYatDCA)); diff --git a/PWGEM/Dilepton/Utils/EMTrackUtilities.h b/PWGEM/Dilepton/Utils/EMTrackUtilities.h index eb73226cd1e..b3712d9e45d 100644 --- a/PWGEM/Dilepton/Utils/EMTrackUtilities.h +++ b/PWGEM/Dilepton/Utils/EMTrackUtilities.h @@ -15,10 +15,12 @@ #ifndef PWGEM_DILEPTON_UTILS_EMTRACKUTILITIES_H_ #define PWGEM_DILEPTON_UTILS_EMTRACKUTILITIES_H_ -#include -#include +#include "Framework/DataTypes.h" + #include #include +#include +#include //_______________________________________________________________________ namespace o2::aod::pwgem::dilepton::utils::emtrackutil From ece670003a9f22a0423117af8c57bb9587e8001b Mon Sep 17 00:00:00 2001 From: Preet-Bhanjan Date: Tue, 17 Jun 2025 01:52:34 +0200 Subject: [PATCH 097/871] [PWGCF] Possible fix on configurable vectors (#11634) Co-authored-by: Preet Pati Co-authored-by: ALICE Action Bot --- PWGCF/Flow/Tasks/flowPbpbPikp.cxx | 235 ++++++++++++++++-------------- 1 file changed, 125 insertions(+), 110 deletions(-) diff --git a/PWGCF/Flow/Tasks/flowPbpbPikp.cxx b/PWGCF/Flow/Tasks/flowPbpbPikp.cxx index 97fbc3a3661..c022cad77c2 100644 --- a/PWGCF/Flow/Tasks/flowPbpbPikp.cxx +++ b/PWGCF/Flow/Tasks/flowPbpbPikp.cxx @@ -105,15 +105,15 @@ struct FlowPbpbPikp { O2_DEFINE_CONFIGURABLE(cfgUseWeightPhiEtaPt, bool, true, "Use Phi, Eta, Pt dependent NUA weights") O2_DEFINE_CONFIGURABLE(cfgUseStrictPID, bool, true, "Use strict PID cuts for TPC") O2_DEFINE_CONFIGURABLE(cfgV0AT0Acut, int, 5, "V0AT0A cut") - O2_DEFINE_CONFIGURABLE(cfgUseAsymmetricPID, bool, false, "Use asymmetric PID cuts"); - O2_DEFINE_CONFIGURABLE(cfgUseItsPID, bool, true, "Use ITS PID for particle identification"); + O2_DEFINE_CONFIGURABLE(cfgUseAsymmetricPID, bool, false, "Use asymmetric PID cuts") + O2_DEFINE_CONFIGURABLE(cfgUseItsPID, bool, true, "Use ITS PID for particle identification") Configurable> cfgTrackDensityP0{"cfgTrackDensityP0", std::vector{0.7217476707, 0.7384792571, 0.7542625668, 0.7640680200, 0.7701951667, 0.7755299053, 0.7805901710, 0.7849446786, 0.7957356586, 0.8113039262, 0.8211968966, 0.8280558878, 0.8329342135}, "parameter 0 for track density efficiency correction"}; Configurable> cfgTrackDensityP1{"cfgTrackDensityP1", std::vector{-2.169488e-05, -2.191913e-05, -2.295484e-05, -2.556538e-05, -2.754463e-05, -2.816832e-05, -2.846502e-05, -2.843857e-05, -2.705974e-05, -2.477018e-05, -2.321730e-05, -2.203315e-05, -2.109474e-05}, "parameter 1 for track density efficiency correction"}; Configurable> cfgTofNsigmaCut{"cfgTofNsigmaCut", 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"}; Configurable> cfgItsNsigmaCut{"cfgItsNsigmaCut", std::vector{3, 3, 3, -3, -3, -3}, "ITS n-sigma cut for pions_posNsigma, kaons_posNsigma, protons_posNsigma, pions_negNsigma, kaons_negNsigma, protons_negNsigma"}; - Configurable> cfgTpcNsigmaCut{"cfgTpcNsigmaCut", 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"}; - Configurable> cfgUseEventCuts{"cfgUseEventCuts", std::vector{1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0}, "Switch for various event cuts [kNoTimeFrameBorder, kNoITSROFrameBorder, kNoSameBunchPileup, kIsGoodZvtxFT0vsPV, kNoCollInTimeRangeStandard, kIsGoodITSLayersAll, kNoCollInRofStandard, kNoHighMultCollInPrevRof, Occupancy, Multiplicity correlation, T0AV0A 3 sigma cut, kIsVertexITSTPC, kTVXinTRD]"}; + Configurable> cfgTpcNsigmaCut{"cfgTpcNsigmaCut", std::vector{10, 10, 10, -10, -10, -10}, "TOF n-sigma cut for pions_posNsigma, kaons_posNsigma, protons_posNsigma, pions_negNsigma, kaons_negNsigma, protons_negNsigma"}; + Configurable> cfgUseEventCuts{"cfgUseEventCuts", std::vector{1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0}, "Switch for various event cuts [Filtered Events, Sel8, kNoTimeFrameBorder, kNoITSROFrameBorder, kNoSameBunchPileup, kIsGoodZvtxFT0vsPV, kNoCollInTimeRangeStandard, kIsGoodITSLayersAll, kNoCollInRofStandard, kNoHighMultCollInPrevRof, Occupancy, Multiplicity correlation, T0AV0A 3 sigma cut, kIsVertexITSTPC, kTVXinTRD]"}; Configurable cfgRegions{"cfgRegions", {{"refN08", "refP08", "full", "poiN", "olN", "poiP", "olP", "poi", "ol", "poiNpi", "olNpi", "poiPpi", "olPpi", "poifullpi", "olfullpi", "poiNka", "olNka", "poiPka", "olPka", "poifullka", "olfullka", "poiNpr", "olNpr", "poiPpr", "olPpr", "poifullpr", "olfullpr"}, {-0.8, 0.4, -0.8, -0.8, -0.8, 0.4, 0.4, -0.8, -0.8, -0.8, -0.8, 0.4, 0.4, -0.8, -0.8, -0.8, -0.8, 0.4, 0.4, -0.8, -0.8, -0.8, -0.8, 0.4, 0.4, -0.8, -0.8}, {-0.4, 0.8, 0.8, -0.4, -0.4, 0.8, 0.8, 0.8, 0.8, -0.4, -0.4, 0.8, 0.8, 0.8, 0.8, -0.4, -0.4, 0.8, 0.8, 0.8, 0.8, -0.4, -0.4, 0.8, 0.8, 0.8, 0.8}, {0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, {1, 1, 1, 128, 256, 128, 256, 128, 256, 2, 16, 2, 16, 2, 16, 4, 32, 4, 32, 4, 32, 8, 64, 8, 64, 8, 64}}, "Configurations for GFW regions"}; Configurable cfgCorrConfig{"cfgCorrConfig", {{"full {2 -2}", "full {2 -2}", "full {2 -2}", "full {2 -2}", "refN08 {2} refP08 {-2}", "refN08 {2} refP08 {-2}", "refN08 {2} refP08 {-2}", "refN08 {2} refP08 {-2}", "refP08 {-2} refN08 {2}", "refP08 {-2} refN08 {2}", "refP08 {-2} refN08 {2}", "refP08 {-2} refN08 {2}", "full {2 2 -2 -2}", "full {2 2 -2 -2}", "full {2 2 -2 -2}", "full {2 2 -2 -2}", "poi full | ol {2 -2}", "poifullpi full | olfullpi {2 -2}", "poifullka full | olfullka {2 -2}", "poifullpr full | olfullpr {2 -2}", "poiN refN08 | olN {2} refP08 {-2}", "poiNpi refN08 | olNpi {2} refP08 {-2}", "poiNka refN08 | olNka {2} refP08 {-2}", "poiNpr refN08 | olNpr {2} refP08 {-2}", "poiP refP08 | olP {2} refN08 {-2}", "poiPpi refP08 | olPpi {2} refN08 {-2}", "poiPka refP08 | olPka {2} refN08 {-2}", "poiPpr refP08 | olPpr {2} refN08 {-2}", "poi full | ol {2 2 -2 -2}", "poifullpi full | olfullpi {2 2 -2 -2}", "poifullka full | olfullka {2 2 -2 -2}", "poifullpr full | olfullpr {2 2 -2 -2}", "refN08 {2 2} refP08 {-2 -2}", "refP08 {-2 -2} refN08 {2 2}", "poiNka refN08 | olNka {2 2} refP08 {-2 -2}", "poiPka refP08 | olPka {2 2} refN08 {-2 -2}"}, {"ChFull22", "PiFull22", "KaFull22", "PrFull22", "Ch08FGap22", "Pi08FGap22", "Ka08FGap22", "Pr08FGap22", "Ch08BGap22", "Pi08BGap22", "Ka08BGap22", "Pr08BGap22", "ChFull24", "PiFull24", "KaFull24", "PrFull24", "ChFull22", "PiFull22", "KaFull22", "PrFull22", "Ch08FGap22", "Pi08FGap22", "Ka08FGap22", "Pr08FGap22", "Ch08BGap22", "Pi08BGap22", "Ka08BGap22", "Pr08BGap22", "ChFull24", "PiFull24", "KaFull24", "PrFull24", "Ka08FGap24", "Ka08BGap24", "Ka08FGap24", "Ka08BGap24"}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 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}}, "Configurations for each correlation to calculate"}; @@ -130,9 +130,10 @@ struct FlowPbpbPikp { ConfigurableAxis axisTPCsignal{"axisTPCsignal", {10000, 0, 1000}, "axis for TPC signal"}; ConfigurableAxis axisTOFbeta{"axisTOFbeta", {200, 0, 2}, "axis for TOF beta"}; - std::vector tofNsigmaCut = cfgTofNsigmaCut; - std::vector itsNsigmaCut = cfgItsNsigmaCut; - std::vector tpcNsigmaCut = cfgTofNsigmaCut; + std::vector tofNsigmaCut; + std::vector itsNsigmaCut; + std::vector tpcNsigmaCut; + std::vector eventCuts; Filter collisionFilter = nabs(aod::collision::posZ) < cfgCutVertex; Filter trackFilter = (nabs(aod::track::dcaXY) < cfgCutDCAxy) && (nabs(aod::track::dcaZ) < cfgCutDCAz) && (nabs(aod::track::eta) < cfgCutEta) && (aod::track::pt > cfgCutPtPOIMin) && (aod::track::pt < cfgCutPtPOIMax) && ((requireGlobalTrackInFilter()) || (aod::track::isGlobalTrackSDD == (uint8_t) true)) && (aod::track::tpcChi2NCl < cfgCutChi2prTPCcls); @@ -159,23 +160,35 @@ struct FlowPbpbPikp { }; enum EventCutTypes { - useNoTimeFrameBorder = 0, - useNoITSROFrameBorder, - useNoSameBunchPileup, - useGoodZvtxFT0vsPV, - useNoCollInTimeRangeStandard, - useGoodITSLayersAll, - useNoCollInRofStandard, - useNoHighMultCollInPrevRof, - useOccupancy, - useMultCorrCut, - useT0AV0ACut, - useVertexITSTPC, - useTVXinTRD + kFilteredEvents = 0, + kAfterSel8, + kUseNoTimeFrameBorder, + kUseNoITSROFrameBorder, + kUseNoSameBunchPileup, + kUseGoodZvtxFT0vsPV, + kUseNoCollInTimeRangeStandard, + kUseGoodITSLayersAll, + kUseNoCollInRofStandard, + kUseNoHighMultCollInPrevRof, + kUseOccupancy, + kUseMultCorrCut, + kUseT0AV0ACut, + kUseVertexITSTPC, + kUseTVXinTRD }; - std::vector fintEvCuts = cfgUseEventCuts; - std::vector eventCuts; + enum TrackCutTypes { + kFilteredTracks = 0, + kUseGlobalTracks, + kUsePvContributor, + kItsClustersCut, + kHasTpcSignal, + kTpcClustersCut, + kTpcCrossedRowsCut, + kNumPions, + kNumKaons, + kNumProtons + }; int lastRunNumer = -1; std::vector runNumbers; @@ -200,15 +213,12 @@ struct FlowPbpbPikp { void init(InitContext const&) { + eventCuts = cfgUseEventCuts; + ccdb->setURL(ccdbUrl.value); ccdb->setCaching(true); ccdb->setCreatedNotAfter(noLaterThan.value); - // Transforming event cuts from int to bool - for (int i = 0; i < static_cast(fintEvCuts.size()); i++) { - eventCuts.push_back(static_cast(fintEvCuts[i])); - } - LOGF(info, "flowGenericFramework::init()"); regions.SetNames(cfgRegions->GetNames()); regions.SetEtaMin(cfgRegions->GetEtaMin()); @@ -252,40 +262,41 @@ struct FlowPbpbPikp { histos.add("TofTpcNsigma_before", "", {HistType::kTHnSparseD, {{axisParticles, axisNsigmaTPC, axisNsigmaTOF, axisPt}}}); if (!cfgUseItsPID) histos.add("TofTpcNsigma_after", "", {HistType::kTHnSparseD, {{axisParticles, axisNsigmaTPC, axisNsigmaTOF, axisPt}}}); - histos.add("partCount", "", {HistType::kTHnSparseD, {{axisParticles, axisMultiplicity, axisPt}}}); histos.add("TofItsNsigma_before", "", {HistType::kTHnSparseD, {{axisParticles, axisNsigmaITS, axisNsigmaTOF, axisPt}}}); if (cfgUseItsPID) histos.add("TofItsNsigma_after", "", {HistType::kTHnSparseD, {{axisParticles, axisNsigmaITS, axisNsigmaTOF, axisPt}}}); - histos.add("hEventCount", "Number of Events;; Count", {HistType::kTH1D, {{15, 0, 15}}}); - histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(1, "Filtered event"); - histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(2, "After sel8"); - histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(3, "kNoTimeFrameBorder"); - histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(4, "kNoITSROFrameBorder"); - histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(5, "kNoSameBunchPileup"); - histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(6, "kIsGoodZvtxFT0vsPV"); - histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(7, "kNoCollInTimeRangeStandard"); - histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(8, "kIsGoodITSLayersAll"); - histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(9, "kNoCollInRofStandard"); - histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(10, "kNoHighMultCollInPrevRof"); - histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(11, "Occupancy Cut"); - histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(12, "Multiplicity correlation Cut"); - histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(13, "T0AV0A cut"); - histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(14, "kIsVertexITSTPC"); - histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(15, "kTVXinTRD"); - - histos.add("hTrackCount", "Number of Tracks;; Count", {HistType::kTH1D, {{10, 0, 10}}}); - histos.get(HIST("hTrackCount"))->GetXaxis()->SetBinLabel(1, "Filtered track"); - histos.get(HIST("hTrackCount"))->GetXaxis()->SetBinLabel(2, "Global tracks"); - histos.get(HIST("hTrackCount"))->GetXaxis()->SetBinLabel(3, "PV contributor"); - histos.get(HIST("hTrackCount"))->GetXaxis()->SetBinLabel(4, "ITS clusters"); - histos.get(HIST("hTrackCount"))->GetXaxis()->SetBinLabel(5, "TPC signal"); - histos.get(HIST("hTrackCount"))->GetXaxis()->SetBinLabel(6, "TPC clusters"); - histos.get(HIST("hTrackCount"))->GetXaxis()->SetBinLabel(7, "TPC crossed rows"); - histos.get(HIST("hTrackCount"))->GetXaxis()->SetBinLabel(8, "Pions"); - histos.get(HIST("hTrackCount"))->GetXaxis()->SetBinLabel(9, "Kaons"); - histos.get(HIST("hTrackCount"))->GetXaxis()->SetBinLabel(10, "Protons"); + histos.add("partCount", "", {HistType::kTHnSparseD, {{axisParticles, axisMultiplicity, axisPt}}}); + + histos.add("hEventCount", "Number of Events;; Count", {HistType::kTH1D, {{15, -0.5, 14.5}}}); + histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(kFilteredEvents + 1, "Filtered event"); + histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(kAfterSel8 + 1, "After sel8"); + histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(kUseNoTimeFrameBorder + 1, "kNoTimeFrameBorder"); + histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(kUseNoITSROFrameBorder + 1, "kNoITSROFrameBorder"); + histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(kUseNoSameBunchPileup + 1, "kNoSameBunchPileup"); + histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(kUseGoodZvtxFT0vsPV + 1, "kIsGoodZvtxFT0vsPV"); + histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(kUseNoCollInRofStandard + 1, "kNoCollInTimeRangeStandard"); + histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(kUseGoodITSLayersAll + 1, "kIsGoodITSLayersAll"); + histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(kUseNoCollInRofStandard + 1, "kNoCollInRofStandard"); + histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(kUseNoHighMultCollInPrevRof + 1, "kNoHighMultCollInPrevRof"); + histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(kUseOccupancy + 1, "Occupancy Cut"); + histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(kUseMultCorrCut + 1, "Multiplicity correlation Cut"); + histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(kUseT0AV0ACut + 1, "T0AV0A cut"); + histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(kUseVertexITSTPC + 1, "kIsVertexITSTPC"); + histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(kUseTVXinTRD + 1, "kTVXinTRD"); + + histos.add("hTrackCount", "Number of Tracks;; Count", {HistType::kTH1D, {{10, -0.5, 9.5}}}); + histos.get(HIST("hTrackCount"))->GetXaxis()->SetBinLabel(kFilteredTracks + 1, "Filtered track"); + histos.get(HIST("hTrackCount"))->GetXaxis()->SetBinLabel(kUseGlobalTracks + 1, "Global tracks"); + histos.get(HIST("hTrackCount"))->GetXaxis()->SetBinLabel(kUsePvContributor + 1, "PV contributor"); + histos.get(HIST("hTrackCount"))->GetXaxis()->SetBinLabel(kItsClustersCut + 1, "ITS clusters"); + histos.get(HIST("hTrackCount"))->GetXaxis()->SetBinLabel(kHasTpcSignal + 1, "TPC signal"); + histos.get(HIST("hTrackCount"))->GetXaxis()->SetBinLabel(kTpcClustersCut + 1, "TPC clusters"); + histos.get(HIST("hTrackCount"))->GetXaxis()->SetBinLabel(kTpcCrossedRowsCut + 1, "TPC crossed rows"); + histos.get(HIST("hTrackCount"))->GetXaxis()->SetBinLabel(kNumPions + 1, "Pions"); + histos.get(HIST("hTrackCount"))->GetXaxis()->SetBinLabel(kNumKaons + 1, "Kaons"); + histos.get(HIST("hTrackCount"))->GetXaxis()->SetBinLabel(kNumProtons + 1, "Protons"); if (cfgOutputNUAWeights && !cfgOutputRunByRun) { histos.add("NUA/hPhiEtaVtxz_ref", ";#varphi;#eta;v_{z}", {HistType::kTH3D, {axisPhi, axisEta, axisVertex}}); @@ -352,7 +363,7 @@ struct FlowPbpbPikp { fFC->Initialize(oba, axisMultiplicity, cfgNbootstrap); delete oba; - if (eventCuts[useMultCorrCut]) { + if (eventCuts[kUseMultCorrCut]) { 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); fMultPVCutLow->SetParameters(3257.29, -121.848, 1.98492, -0.0172128, 6.47528e-05, 154.756, -1.86072, -0.0274713, 0.000633499, -3.37757e-06); 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); @@ -363,7 +374,7 @@ struct FlowPbpbPikp { 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); fMultCutHigh->SetParameters(1654.46, -47.2379, 0.449833, -0.0014125, 150.773, -3.67334, 0.0530503, -0.000614061, 3.15956e-06); } - if (eventCuts[useT0AV0ACut]) { + if (eventCuts[kUseT0AV0ACut]) { fT0AV0AMean = new TF1("fT0AV0AMean", "[0]+[1]*x", 0, 200000); fT0AV0AMean->SetParameters(-1601.0581, 9.417652e-01); fT0AV0ASigma = new TF1("fT0AV0ASigma", "[0]+[1]*x+[2]*x*x+[3]*x*x*x+[4]*x*x*x*x", 0, 200000); @@ -388,7 +399,11 @@ struct FlowPbpbPikp { 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); } - } + + tofNsigmaCut = cfgTofNsigmaCut; + itsNsigmaCut = cfgItsNsigmaCut; + tpcNsigmaCut = cfgTpcNsigmaCut; + } // End of init() enum Particles { PIONS, @@ -414,37 +429,37 @@ struct FlowPbpbPikp { template bool selectionTrack(const TTrack& track) { - histos.fill(HIST("hTrackCount"), 0.5); // Filtered tracks + histos.fill(HIST("hTrackCount"), kFilteredTracks); // Filtered tracks if (cfgUseGlobalTrack && !(track.isGlobalTrack())) { return 0; } if (cfgUseGlobalTrack) - histos.fill(HIST("hTrackCount"), 1.5); // After global track selection + histos.fill(HIST("hTrackCount"), kUseGlobalTracks); // After global track selection if (!(track.isPVContributor())) { return 0; } - histos.fill(HIST("hTrackCount"), 2.5); // After PV contributor selection + histos.fill(HIST("hTrackCount"), kUsePvContributor); // After PV contributor selection if (!(track.itsNCls() > cfgITScluster)) { return 0; } - histos.fill(HIST("hTrackCount"), 3.5); // After ITS cluster selection + histos.fill(HIST("hTrackCount"), kItsClustersCut); // After ITS cluster selection if (!(track.hasTPC())) { return 0; } - histos.fill(HIST("hTrackCount"), 4.5); // If track has TPC signal + histos.fill(HIST("hTrackCount"), kHasTpcSignal); // If track has TPC signal if (!(track.tpcNClsFound() > cfgTpcCluster)) { return 0; } - histos.fill(HIST("hTrackCount"), 5.5); // After TPC cluster selection + histos.fill(HIST("hTrackCount"), kTpcClustersCut); // After TPC cluster selection if (!(track.tpcNClsCrossedRows() > cfgTpcCrossRows)) { return 0; } - histos.fill(HIST("hTrackCount"), 6.5); // After TPC crossed rows selection + histos.fill(HIST("hTrackCount"), kTpcCrossedRowsCut); // After TPC crossed rows selection return 1; } @@ -458,7 +473,7 @@ struct FlowPbpbPikp { histos.fill(HIST("TofTpcNsigma_after"), pidIndex - 1, track.tpcNSigmaPi(), track.tofNSigmaPi(), track.pt()); if (cfgUseItsPID) histos.fill(HIST("TofItsNsigma_after"), pidIndex - 1, itsResponse.nSigmaITS(track), track.tofNSigmaPi(), track.pt()); - histos.fill(HIST("hTrackCount"), 7.5); // Pion count + histos.fill(HIST("hTrackCount"), kNumPions); // Pion count if (!cfgAcceptance.value.empty() && cfgUseWeightPhiEtaVtxz) histos.fill(HIST("PhiCorrected/hPhiEtaVtxz_pi_corrd"), track.phi(), track.eta(), collision.posZ(), wacc); // pion weights if (!cfgAcceptance.value.empty() && cfgUseWeightPhiPtCent) @@ -471,7 +486,7 @@ struct FlowPbpbPikp { histos.fill(HIST("TofTpcNsigma_after"), pidIndex - 1, track.tpcNSigmaKa(), track.tofNSigmaKa(), track.pt()); if (cfgUseItsPID) histos.fill(HIST("TofItsNsigma_after"), pidIndex - 1, itsResponse.nSigmaITS(track), track.tofNSigmaKa(), track.pt()); - histos.fill(HIST("hTrackCount"), 8.5); // Kaon count + histos.fill(HIST("hTrackCount"), kNumKaons); // Kaon count if (!cfgAcceptance.value.empty() && cfgUseWeightPhiEtaVtxz) histos.fill(HIST("PhiCorrected/hPhiEtaVtxz_ka_corrd"), track.phi(), track.eta(), collision.posZ(), wacc); // kaon weights if (!cfgAcceptance.value.empty() && cfgUseWeightPhiPtCent) @@ -484,7 +499,7 @@ struct FlowPbpbPikp { histos.fill(HIST("TofTpcNsigma_after"), pidIndex - 1, track.tpcNSigmaPr(), track.tofNSigmaPr(), track.pt()); if (cfgUseItsPID) histos.fill(HIST("TofItsNsigma_after"), pidIndex - 1, itsResponse.nSigmaITS(track), track.tofNSigmaPr(), track.pt()); - histos.fill(HIST("hTrackCount"), 9.5); // Proton count + histos.fill(HIST("hTrackCount"), kNumProtons); // Proton count if (!cfgAcceptance.value.empty() && cfgUseWeightPhiEtaVtxz) histos.fill(HIST("PhiCorrected/hPhiEtaVtxz_pr_corrd"), track.phi(), track.eta(), collision.posZ(), wacc); // proton weights if (!cfgAcceptance.value.empty() && cfgUseWeightPhiPtCent) @@ -760,70 +775,70 @@ struct FlowPbpbPikp { template bool selectionEvent(TCollision collision, const int mult, const float cent) { - histos.fill(HIST("hEventCount"), 0.5); + histos.fill(HIST("hEventCount"), kFilteredEvents); if (!collision.sel8()) { return 0; } - histos.fill(HIST("hEventCount"), 1.5); + histos.fill(HIST("hEventCount"), kAfterSel8); - if (eventCuts[useNoTimeFrameBorder] && !collision.selection_bit(aod::evsel::kNoTimeFrameBorder)) { + if (eventCuts[kUseNoTimeFrameBorder] && !collision.selection_bit(aod::evsel::kNoTimeFrameBorder)) { return 0; } - if (eventCuts[useNoTimeFrameBorder]) - histos.fill(HIST("hEventCount"), 2.5); + if (eventCuts[kUseNoTimeFrameBorder]) + histos.fill(HIST("hEventCount"), kUseNoTimeFrameBorder); - if (eventCuts[useNoITSROFrameBorder] && !collision.selection_bit(aod::evsel::kNoITSROFrameBorder)) { + if (eventCuts[kUseNoITSROFrameBorder] && !collision.selection_bit(aod::evsel::kNoITSROFrameBorder)) { return 0; } - if (eventCuts[useNoITSROFrameBorder]) - histos.fill(HIST("hEventCount"), 3.5); + if (eventCuts[kUseNoITSROFrameBorder]) + histos.fill(HIST("hEventCount"), kUseNoITSROFrameBorder); - if (eventCuts[useNoSameBunchPileup] && !collision.selection_bit(aod::evsel::kNoSameBunchPileup)) { + if (eventCuts[kUseNoSameBunchPileup] && !collision.selection_bit(aod::evsel::kNoSameBunchPileup)) { return 0; } - if (eventCuts[useNoSameBunchPileup]) - histos.fill(HIST("hEventCount"), 4.5); + if (eventCuts[kUseNoSameBunchPileup]) + histos.fill(HIST("hEventCount"), kUseNoSameBunchPileup); - if (eventCuts[useGoodZvtxFT0vsPV] && !collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { + if (eventCuts[kUseGoodZvtxFT0vsPV] && !collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { return 0; } - if (eventCuts[useGoodZvtxFT0vsPV]) - histos.fill(HIST("hEventCount"), 5.5); + if (eventCuts[kUseGoodZvtxFT0vsPV]) + histos.fill(HIST("hEventCount"), kUseGoodZvtxFT0vsPV); - if (eventCuts[useNoCollInTimeRangeStandard] && !collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { + if (eventCuts[kUseNoCollInTimeRangeStandard] && !collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { return 0; } - if (eventCuts[useNoCollInTimeRangeStandard]) - histos.fill(HIST("hEventCount"), 6.5); + if (eventCuts[kUseNoCollInTimeRangeStandard]) + histos.fill(HIST("hEventCount"), kUseNoCollInTimeRangeStandard); - if (eventCuts[useGoodITSLayersAll] && !collision.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { + if (eventCuts[kUseGoodITSLayersAll] && !collision.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { return 0; } - if (eventCuts[useGoodITSLayersAll]) - histos.fill(HIST("hEventCount"), 7.5); + if (eventCuts[kUseGoodITSLayersAll]) + histos.fill(HIST("hEventCount"), kUseGoodITSLayersAll); - if (eventCuts[useNoCollInRofStandard] && !collision.selection_bit(o2::aod::evsel::kNoCollInRofStandard)) { + if (eventCuts[kUseNoCollInRofStandard] && !collision.selection_bit(o2::aod::evsel::kNoCollInRofStandard)) { return 0; } - if (eventCuts[useNoCollInRofStandard]) - histos.fill(HIST("hEventCount"), 8.5); + if (eventCuts[kUseNoCollInRofStandard]) + histos.fill(HIST("hEventCount"), kUseNoCollInRofStandard); - if (eventCuts[useNoHighMultCollInPrevRof] && !collision.selection_bit(o2::aod::evsel::kNoHighMultCollInPrevRof)) { + if (eventCuts[kUseNoHighMultCollInPrevRof] && !collision.selection_bit(o2::aod::evsel::kNoHighMultCollInPrevRof)) { return 0; } - if (eventCuts[useNoHighMultCollInPrevRof]) - histos.fill(HIST("hEventCount"), 9.5); + if (eventCuts[kUseNoHighMultCollInPrevRof]) + histos.fill(HIST("hEventCount"), kUseNoHighMultCollInPrevRof); auto multNTracksPV = collision.multNTracksPV(); auto occupancy = collision.trackOccupancyInTimeRange(); - if (eventCuts[useOccupancy] && (occupancy < cfgCutOccupancyMin || occupancy > cfgCutOccupancyMax)) { + if (eventCuts[kUseOccupancy] && (occupancy < cfgCutOccupancyMin || occupancy > cfgCutOccupancyMax)) { return 0; } - if (eventCuts[useOccupancy]) - histos.fill(HIST("hEventCount"), 10.5); + if (eventCuts[kUseOccupancy]) + histos.fill(HIST("hEventCount"), kUseOccupancy); - if (eventCuts[useMultCorrCut]) { + if (eventCuts[kUseMultCorrCut]) { if (multNTracksPV < fMultPVCutLow->Eval(cent)) return 0; if (multNTracksPV > fMultPVCutHigh->Eval(cent)) @@ -833,25 +848,25 @@ struct FlowPbpbPikp { if (mult > fMultCutHigh->Eval(cent)) return 0; } - if (eventCuts[useMultCorrCut]) - histos.fill(HIST("hEventCount"), 11.5); + if (eventCuts[kUseMultCorrCut]) + histos.fill(HIST("hEventCount"), kUseMultCorrCut); // V0A T0A 5 sigma cut - if (eventCuts[useT0AV0ACut] && (std::fabs(collision.multFV0A() - fT0AV0AMean->Eval(collision.multFT0A())) > cfgV0AT0Acut * fT0AV0ASigma->Eval(collision.multFT0A()))) + if (eventCuts[kUseT0AV0ACut] && (std::fabs(collision.multFV0A() - fT0AV0AMean->Eval(collision.multFT0A())) > cfgV0AT0Acut * fT0AV0ASigma->Eval(collision.multFT0A()))) return 0; - if (eventCuts[useT0AV0ACut]) - histos.fill(HIST("hEventCount"), 12.5); + if (eventCuts[kUseT0AV0ACut]) + histos.fill(HIST("hEventCount"), kUseT0AV0ACut); - if (eventCuts[useVertexITSTPC] && !collision.selection_bit(o2::aod::evsel::kIsVertexITSTPC)) + if (eventCuts[kUseVertexITSTPC] && !collision.selection_bit(o2::aod::evsel::kIsVertexITSTPC)) return 0; - if (eventCuts[useVertexITSTPC]) - histos.fill(HIST("hEventCount"), 13.5); + if (eventCuts[kUseVertexITSTPC]) + histos.fill(HIST("hEventCount"), kUseVertexITSTPC); - if (eventCuts[useTVXinTRD] && collision.alias_bit(kTVXinTRD)) { + if (eventCuts[kUseTVXinTRD] && collision.alias_bit(kTVXinTRD)) { return 0; } - if (eventCuts[useTVXinTRD]) - histos.fill(HIST("hEventCount"), 14.5); + if (eventCuts[kUseTVXinTRD]) + histos.fill(HIST("hEventCount"), kUseTVXinTRD); return 1; } From aef2da47432b0472fd785ba0610ca358684d8859 Mon Sep 17 00:00:00 2001 From: altsybee Date: Tue, 17 Jun 2025 03:23:29 +0200 Subject: [PATCH 098/871] [DPG] additional dt-dependent occupancy histos for ITS+TOF and ITS+TRD tracks (#11636) --- DPG/Tasks/AOTEvent/detectorOccupancyQa.cxx | 44 ++++++++++++++++------ 1 file changed, 33 insertions(+), 11 deletions(-) diff --git a/DPG/Tasks/AOTEvent/detectorOccupancyQa.cxx b/DPG/Tasks/AOTEvent/detectorOccupancyQa.cxx index a76dc9ea0f7..e8e3a7d9696 100644 --- a/DPG/Tasks/AOTEvent/detectorOccupancyQa.cxx +++ b/DPG/Tasks/AOTEvent/detectorOccupancyQa.cxx @@ -65,6 +65,7 @@ struct DetectorOccupancyQaTask { Configurable confFlagUseNoHighMultCollInPrevRof{"FlagUseNoHighMultCollInPrevRof", false, "Suppress high-multiplicity prev-ROF events for occupancy historams"}; // o2-linter: disable=name/configurable (temporary fix) Configurable confFlagCentralityIsAvailable{"FlagCentralityIsAvailable", true, "Fill centrality-related historams"}; // o2-linter: disable=name/configurable (temporary fix) Configurable confFlagManyHeavyHistos{"FlagManyHeavyHistos", true, "Fill more TH2, TH3, THn historams"}; // o2-linter: disable=name/configurable (temporary fix) + Configurable confFlagIsTOFIsTRDdtStudy{"FlagIsTOFIsTRDdtStudy", true, "Fill THn dt historams with isTOF and isTRD condition"}; // o2-linter: disable=name/configurable (temporary fix) // configuration for small time binning Configurable confTimeIntervalForSmallBins{"TimeIntervalForSmallBins", 100, "Time interval for TPC occupancy calculation in small bins, +/-, us"}; // o2-linter: disable=name/configurable (temporary fix) @@ -328,6 +329,10 @@ struct DetectorOccupancyQaTask { histos.add("occupancyInTimeBins_nITS567_vs_FT0thisCol_occupByFT0_kNoCollInTimeRangeNarrow", ";time bin (#mus);FT0C this collision, this collision;n ITS567cls tracks, this collision;sum FT0 in time window", kTHnF, {axisTimeBins, {nBins3D, 0, kMaxThisEv * 100000}, {nBinsY, 0, kMaxThisEv * 4000}, {nBins3DoccupancyAxis, 0, kMaxOccup * 100000}}); histos.add("occupancyInTimeBins_nITS567_vs_FT0thisCol_occupByFT0_kNoCollInTimeRangeNarrow_NoCollInRofStrict", ";time bin (#mus);FT0C this collision, this collision;n ITS567cls tracks, this collision;sum FT0 in time window", kTHnF, {axisTimeBins, {nBins3D, 0, kMaxThisEv * 100000}, {nBinsY, 0, kMaxThisEv * 4000}, {nBins3DoccupancyAxis, 0, kMaxOccup * 100000}}); } + if (confFlagIsTOFIsTRDdtStudy) { + histos.add("occupancyInTimeBins_nITSTOF_vs_FT0thisCol_kNoCollInTimeRangeNarrow", ";time bin (#mus);FT0C this collision, this collision;n ITSTOF tracks, this collision;ITS tracks with 5,6,7 cls in time window", kTHnF, {axisTimeBins, {nBins3D, 0, kMaxThisEv * 100000}, {nBinsY, 0, kMaxThisEv * 4000}, {nBins3DoccupancyAxis, 0, kMaxOccup * 10000}}); + histos.add("occupancyInTimeBins_nITSTRD_vs_FT0thisCol_kNoCollInTimeRangeNarrow", ";time bin (#mus);FT0C this collision, this collision;n ITSTRD tracks, this collision;ITS tracks with 5,6,7 cls in time window", kTHnF, {axisTimeBins, {nBins3D, 0, kMaxThisEv * 100000}, {nBinsY, 0, kMaxThisEv * 4000}, {nBins3DoccupancyAxis, 0, kMaxOccup * 10000}}); + } histos.add("thisEventITStracksInTimeBins", ";time bin (#mus);n tracks", kTH1F, {axisTimeBins}); histos.add("thisEventITSTPCtracksInTimeBins", ";time bin (#mus);n tracks", kTH1F, {axisTimeBins}); @@ -462,6 +467,8 @@ struct DetectorOccupancyQaTask { std::vector vTracksGlobalPerCollPtEtaCuts(cols.size(), 0); // counter of tracks per found bc for occupancy studies std::vector vTracksITSTPCperColl(cols.size(), 0); // counter of tracks per found bc for occupancy studies std::vector vTracksITSTPCperCollPtEtaCuts(cols.size(), 0); // counter of tracks per found bc for occupancy studies + std::vector vTracksITSTOFperCollPtEtaCuts(cols.size(), 0); // counter of tracks per found bc for occupancy studies + std::vector vTracksITSTRDperCollPtEtaCuts(cols.size(), 0); // counter of tracks per found bc for occupancy studies std::vector vAmpFT0CperColl(cols.size(), 0); // amplitude FT0C per collision std::vector vTFids(cols.size(), 0); @@ -482,6 +489,8 @@ struct DetectorOccupancyQaTask { int nGlobalPtEtaCuts = 0; int nITSTPCtracks = 0; int nITSTPCtracksPtEtaCuts = 0; + int nITSTOFtracksPtEtaCuts = 0; + int nITSTRDtracksPtEtaCuts = 0; int nTOFtracks = 0; // int nTRDtracks = 0; auto tracksGrouped = tracks.sliceBy(perCollision, col.globalIndex()); @@ -489,8 +498,12 @@ struct DetectorOccupancyQaTask { if (!track.isPVContributor()) { continue; } - if (track.itsNCls() >= 5) - nITS567cls++; + // if (track.itsNCls() >= 5) + // nITS567cls++; + if (track.itsNCls() < 5) + continue; + nITS567cls++; + nITSTPCtracks += track.hasITS() && track.hasTPC(); nTOFtracks += track.hasTOF(); // nTRDtracks += track.hasTRD(); @@ -500,15 +513,18 @@ struct DetectorOccupancyQaTask { if (track.eta() < confCutEtaMinTracksThisEvent || track.eta() > confCutEtaMaxTracksThisEvent) continue; - if (track.itsNCls() >= 5) - nITS567clsPtEtaCuts++; + // if (track.itsNCls() >= 5) + nITS567clsPtEtaCuts++; + + nITSTOFtracksPtEtaCuts += track.hasITS() && track.hasTOF(); + nITSTRDtracksPtEtaCuts += track.hasITS() && track.hasTRD(); if (track.tpcNClsFound() < confCutMinTPCcls) continue; nITSTPCtracksPtEtaCuts += track.hasITS() && track.hasTPC(); - if (track.itsNCls() >= 5) - nGlobalPtEtaCuts += track.isGlobalTrack(); + // if (track.itsNCls() >= 5) + nGlobalPtEtaCuts += track.isGlobalTrack(); } int32_t foundBC = bc.globalIndex(); @@ -522,12 +538,14 @@ struct DetectorOccupancyQaTask { vIsVertexTOFmatched[colIndex] = nTOFtracks > 0; - vTracksITS567perColl[colIndex] += nITS567cls; - vTracksITS567perCollPtEtaCuts[colIndex] += nITS567clsPtEtaCuts; - vTracksGlobalPerCollPtEtaCuts[colIndex] += nGlobalPtEtaCuts; + vTracksITS567perColl[colIndex] = nITS567cls; + vTracksITS567perCollPtEtaCuts[colIndex] = nITS567clsPtEtaCuts; + vTracksGlobalPerCollPtEtaCuts[colIndex] = nGlobalPtEtaCuts; - vTracksITSTPCperColl[colIndex] += nITSTPCtracks; - vTracksITSTPCperCollPtEtaCuts[colIndex] += nITSTPCtracksPtEtaCuts; + vTracksITSTPCperColl[colIndex] = nITSTPCtracks; + vTracksITSTPCperCollPtEtaCuts[colIndex] = nITSTPCtracksPtEtaCuts; + vTracksITSTOFperCollPtEtaCuts[colIndex] = nITSTOFtracksPtEtaCuts; + vTracksITSTRDperCollPtEtaCuts[colIndex] = nITSTRDtracksPtEtaCuts; // TF ids within a given cols table int tfId = (bc.globalBC() - bcSOR) / nBCsPerTF; @@ -815,6 +833,10 @@ struct DetectorOccupancyQaTask { if (col.selection_bit(kNoCollInTimeRangeNarrow)) { histos.fill(HIST("occupancyInTimeBins_vs_FT0thisCol_kNoCollInTimeRangeNarrow"), dt, vAmpFT0CperColl[colIndex], confFlagUseGlobalTracks ? vTracksGlobalPerCollPtEtaCuts[colIndex] : vTracksITSTPCperCollPtEtaCuts[colIndex], nITStrInTimeBin); histos.fill(HIST("occupancyInTimeBins_nITS567_vs_FT0thisCol_kNoCollInTimeRangeNarrow"), dt, vAmpFT0CperColl[colIndex], vTracksITS567perCollPtEtaCuts[colIndex], nITStrInTimeBin); + if (confFlagIsTOFIsTRDdtStudy) { + histos.fill(HIST("occupancyInTimeBins_nITSTOF_vs_FT0thisCol_kNoCollInTimeRangeNarrow"), dt, vAmpFT0CperColl[colIndex], vTracksITSTOFperCollPtEtaCuts[colIndex], nITStrInTimeBin); + histos.fill(HIST("occupancyInTimeBins_nITSTRD_vs_FT0thisCol_kNoCollInTimeRangeNarrow"), dt, vAmpFT0CperColl[colIndex], vTracksITSTRDperCollPtEtaCuts[colIndex], nITStrInTimeBin); + } if (confFlagManyHeavyHistos) { histos.fill(HIST("occupancyInTimeBins_occupByFT0_kNoCollInTimeRangeNarrow"), dt, vTracksITS567perCollPtEtaCuts[colIndex], confFlagUseGlobalTracks ? vTracksGlobalPerCollPtEtaCuts[colIndex] : vTracksITSTPCperCollPtEtaCuts[colIndex], nFT0CInTimeBin); histos.fill(HIST("occupancyInTimeBins_vs_FT0thisCol_occupByFT0_kNoCollInTimeRangeNarrow"), dt, vAmpFT0CperColl[colIndex], confFlagUseGlobalTracks ? vTracksGlobalPerCollPtEtaCuts[colIndex] : vTracksITSTPCperCollPtEtaCuts[colIndex], nFT0CInTimeBin); From c20e1db4d8038ba68f515f71764acd4d8fca39ff Mon Sep 17 00:00:00 2001 From: YubiaoWang Date: Tue, 17 Jun 2025 12:01:39 +0800 Subject: [PATCH 099/871] [PWGJE] Add files via uploadFix memory consumption too large, remove plots for test to save memory consumption in Data, MCD and MCP process (#11629) --- PWGJE/Tasks/jetChargedV2.cxx | 292 ++++++++++++----------------------- 1 file changed, 101 insertions(+), 191 deletions(-) diff --git a/PWGJE/Tasks/jetChargedV2.cxx b/PWGJE/Tasks/jetChargedV2.cxx index 208d2de6f98..5952686e688 100644 --- a/PWGJE/Tasks/jetChargedV2.cxx +++ b/PWGJE/Tasks/jetChargedV2.cxx @@ -119,6 +119,7 @@ struct JetChargedV2 { 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 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 cfgChkFitQuality{"cfgChkFitQuality", false, "check fit quality"}; template int getDetId(const T& name) @@ -227,80 +228,9 @@ struct JetChargedV2 { registry.add("h_jet_phat", "jet #hat{p};#hat{p} (GeV/#it{c});entries", {HistType::kTH1F, {{1000, 0, 1000}}}); registry.add("h_jet_phat_weighted", "jet #hat{p};#hat{p} (GeV/#it{c});entries", {HistType::kTH1F, {{1000, 0, 1000}}}); - if (doprocessSigmaPtMCP) { - registry.add("h_jet_eta_part_rhoareasubtracted", "part jet #eta;#eta^{part}; counts", {HistType::kTH1F, {jetEtaAxis}}); - registry.add("h_jet_phi_part_rhoareasubtracted", "part jet #varphi;#varphi^{part}; counts", {HistType::kTH1F, {phiAxis}}); - registry.add("h2_jet_pt_part_jet_area_part_rhoareasubtracted", "part jet #it{p}_{T,jet} vs. Area_{jet}; #it{p}_{T,jet}^{part} (GeV/#it{c}); Area_{jet}^{part}", {HistType::kTH2F, {jetPtAxisRhoAreaSub, {150, 0., 1.5}}}); - registry.add("h3_jet_pt_jet_eta_jet_phi_part_rhoareasubtracted", "part jet pt vs. eta vs.phi", {HistType::kTH3F, {jetPtAxisRhoAreaSub, jetEtaAxis, phiAxis}}); - registry.add("leadJetPtMCP", "MCP leadJet Pt ", {HistType::kTH1F, {{200, 0., 200.0}}}); - registry.add("leadJetPhiMCP", "MCP leadJet constituent #phi ", {HistType::kTH1F, {{80, -1.0, 7.}}}); - registry.add("leadJetEtaMCP", "MCP leadJet constituent #eta ", {HistType::kTH1F, {{100, -1.0, 1.0}}}); - registry.add("h_mcp_evtnum_NTrk", "MCP eventNumber vs Number of Track ; #eventNumber", {HistType::kTH1F, {{1000, 0.0, 1000}}}); - registry.add("h3_mcp_centrality_localrho_phi", "MCP centrality; #rho_{local}; #Delta#varphi_{jet}", {HistType::kTH3F, {{120, -10.0, 110.0}, {200, 0.0, 200.0}, {40, 0., o2::constants::math::TwoPI}}}); - registry.add("h_mcp_jet_pt_rholocal", "jet pT rholocal;#it{p}_{T,jet} (GeV/#it{c});entries", {HistType::kTH1F, {jetPtAxisRhoAreaSub}}); - registry.add("h2_mcp_phi_rholocal", "#varphi vs #rho(#varphi); #varphi - #Psi_{EP,2}; #rho(#varphi) ", {HistType::kTH2F, {{40, 0., o2::constants::math::TwoPI}, {210, -10.0, 200.0}}}); - //< MCP fit test >// - registry.add("h_mcp_ptsum_sumpt", "jet sumpt;sum p_{T};entries", {HistType::kTH1F, {{40, 0., o2::constants::math::TwoPI}}}); - registry.add("h2_mcp_phi_track_eta", "phi vs track eta; #eta (GeV/#it{c}); #varphi", {HistType::kTH2F, {{100, -1.0, 1.0}, {40, 0., o2::constants::math::TwoPI}}}); - registry.add("h_mcp_evtnum_centrlity", "eventNumber vs centrality ; #eventNumber", {HistType::kTH1F, {{1000, 0.0, 1000}}}); - registry.add("h_mcp_v2obs_centrality", "fitparameter v2obs vs centrality ; #centrality", {HistType::kTProfile, {cfgAxisVnCent}}); - registry.add("h_mcp_v3obs_centrality", "fitparameter v3obs vs centrality ; #centrality", {HistType::kTProfile, {cfgAxisVnCent}}); - registry.add("h_mcp_fitparaRho_evtnum", "fitparameter #rho_{0} vs evtnum ; #eventnumber", {HistType::kTH1F, {{1000, 0.0, 1000}}}); - registry.add("h_mcp_fitparaPsi2_evtnum", "fitparameter #Psi_{2} vs evtnum ; #eventnumber", {HistType::kTH1F, {{1000, 0.0, 1000}}}); - registry.add("h_mcp_fitparaPsi3_evtnum", "fitparameter #Psi_{3} vs evtnum ; #eventnumber", {HistType::kTH1F, {{1000, 0.0, 1000}}}); - registry.add("h_mcp_fitparav2obs_evtnum", "fitparameter v2obs vs evtnum ; #eventnumber", {HistType::kTH1F, {{1000, 0.0, 1000}}}); - registry.add("h_mcp_fitparav3obs_evtnum", "fitparameter v3obs vs evtnum ; #eventnumber", {HistType::kTH1F, {{1000, 0.0, 1000}}}); - - registry.add("h_mcp_jet_pt_in_plane_v2_rho", "jet pT;#it{p}^{in-plane}_{T,jet} (GeV/#it{c});entries", {HistType::kTH1F, {jetPtAxisRhoAreaSub}}); - registry.add("h_mcp_jet_pt_out_of_plane_v2_rho", "jet pT;#it{p}^{out-of-plane}_{T,jet} (GeV/#it{c});entries", {HistType::kTH1F, {jetPtAxisRhoAreaSub}}); - registry.add("h_mcp_jet_pt_in_plane_v3_rho", "jet pT;#it{p}^{in-plane}_{T,jet} (GeV/#it{c});entries", {HistType::kTH1F, {jetPtAxisRhoAreaSub}}); - registry.add("h_mcp_jet_pt_out_of_plane_v3_rho", "jet pT;#it{p}^{out-of-plane}_{T,jet} (GeV/#it{c});entries", {HistType::kTH1F, {jetPtAxisRhoAreaSub}}); - - registry.add("h2_mcp_centrality_jet_pt_in_plane_v2_rho", "centrality vs #it{p}^{in-plane}_{T,jet}; centrality; #it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH2F, {{120, -10.0, 110.0}, jetPtAxisRhoAreaSub}}); - registry.add("h2_mcp_centrality_jet_pt_out_of_plane_v2_rho", "centrality vs #it{p}^{out-of-plane}_{T,jet}; centrality; #it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH2F, {{120, -10.0, 110.0}, jetPtAxisRhoAreaSub}}); - registry.add("h2_mcp_centrality_jet_pt_in_plane_v3_rho", "centrality vs #it{p}^{in-plane}_{T,jet}; centrality; #it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH2F, {{120, -10.0, 110.0}, jetPtAxisRhoAreaSub}}); - registry.add("h2_mcp_centrality_jet_pt_out_of_plane_v3_rho", "centrality vs #it{p}^{out-of-plane}_{T,jet}; centrality; #it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH2F, {{120, -10.0, 110.0}, jetPtAxisRhoAreaSub}}); - - registry.add("h3_mcp_centrality_deltapT_RandomCornPhi_localrhovsphi", "centrality; #it{p}_{T,random cone} - #it{area, random cone} * #it{rho}; #Delta#varphi_{jet}", {HistType::kTH3F, {{100, 0.0, 100.0}, {400, -200.0, 200.0}, {100, 0., o2::constants::math::TwoPI}}}); - registry.add("h3_mcp_centrality_deltapT_RandomCornPhi_rhorandomconewithoutleadingjet", "centrality; #it{p}_{T,random cone} - #it{area, random cone} * #it{rho}; #Delta#varphi_{jet}", {HistType::kTH3F, {{100, 0.0, 100.0}, {400, -200.0, 200.0}, {100, 0., o2::constants::math::TwoPI}}}); - registry.add("h3_mcp_centrality_deltapT_RandomCornPhi_localrhovsphiwithoutleadingjet", "centrality; #it{p}_{T,random cone} - #it{area, random cone} * #it{rho}(#varphi); #Delta#varphi_{jet}", {HistType::kTH3F, {{100, 0.0, 100.0}, {400, -200.0, 200.0}, {100, 0., o2::constants::math::TwoPI}}}); - - registry.add("h_mcColl_counts_areasub", " number of mc events; event status; entries", {HistType::kTH1F, {{10, 0, 10}}}); - registry.get(HIST("h_mcColl_counts_areasub"))->GetXaxis()->SetBinLabel(1, "allMcColl"); - registry.get(HIST("h_mcColl_counts_areasub"))->GetXaxis()->SetBinLabel(2, "vertexZ"); - registry.get(HIST("h_mcColl_counts_areasub"))->GetXaxis()->SetBinLabel(3, "noRecoColl"); - registry.get(HIST("h_mcColl_counts_areasub"))->GetXaxis()->SetBinLabel(4, "splitColl"); - registry.get(HIST("h_mcColl_counts_areasub"))->GetXaxis()->SetBinLabel(5, "recoEvtSel"); - registry.get(HIST("h_mcColl_counts_areasub"))->GetXaxis()->SetBinLabel(6, "centralitycut"); - registry.get(HIST("h_mcColl_counts_areasub"))->GetXaxis()->SetBinLabel(7, "occupancycut"); - registry.add("h_mcColl_rho", "mc collision rho;#rho (GeV/#it{c}); counts", {HistType::kTH1F, {{500, 0.0, 500.0}}}); - - //< \sigma p_T at local rho test plot > - registry.add("h_accept_Track", "all and accept track;Track;entries", {HistType::kTH1F, {{10, 0.0, 10.0}}}); - registry.get(HIST("h_accept_Track"))->GetXaxis()->SetBinLabel(1, "acceptTrk"); - registry.get(HIST("h_accept_Track"))->GetXaxis()->SetBinLabel(2, "acceptTrkInFit"); - registry.get(HIST("h_accept_Track"))->GetXaxis()->SetBinLabel(3, "beforeSumptFit"); - registry.get(HIST("h_accept_Track"))->GetXaxis()->SetBinLabel(4, "afterSumptFit"); - registry.get(HIST("h_accept_Track"))->GetXaxis()->SetBinLabel(5, "getNtrk"); - registry.get(HIST("h_accept_Track"))->GetXaxis()->SetBinLabel(6, "getNtrkMCP"); - //< fit test >// - registry.add("h_ptsum_collnum", "ptsum collnum;collnum;entries", {HistType::kTH1F, {{40, 0.0, 40}}}); - registry.add("h_ptsum_sumpt", "jet sumpt;sum p_{T};entries", {HistType::kTH1F, {{40, 0., o2::constants::math::TwoPI}}}); - } - if (doprocessInOutJetV2 || doprocessInOutJetV2MCD || doprocessSigmaPt || doprocessSigmaPtMCD) { //< Track efficiency plots >// registry.add("h_collisions", "event status;event status;entries", {HistType::kTH1F, {{4, 0.0, 4.0}}}); - registry.add("h2_centrality_collisions", "centrality vs collisions; centrality; collisions", {HistType::kTH2F, {{120, -10., 110.}, {4, 0.0, 4.0}}}); - registry.add("h2_centrality_track_pt", "centrality vs track pT; centrality; #it{p}_{T,track} (GeV/#it{c})", {HistType::kTH2F, {{1200, -10.0, 110.0}, {200, 0., 200.}}}); - registry.add("h2_centrality_track_eta", "centrality vs track #eta; centrality; #eta_{track}", {HistType::kTH2F, {{1200, -10.0, 110.0}, {100, -1.0, 1.0}}}); - registry.add("h2_centrality_track_phi", "centrality vs track #varphi; centrality; #varphi_{track}", {HistType::kTH2F, {{1200, -10.0, 110.0}, {160, -1.0, 7.}}}); - registry.add("h2_centrality_track_energy", "centrality vs track energy; centrality; Energy GeV", {HistType::kTH2F, {{120, -10., 110.}, {100, 0.0, 100.0}}}); - registry.add("h2_track_pt_track_sigmapt", "#sigma(#it{p}_{T})/#it{p}_{T}; #it{p}_{T,track} (GeV/#it{c})", {HistType::kTH2F, {{100, 0., 10.}, {100000, 0.0, 100.0}}}); - registry.add("h2_track_pt_high_track_sigmapt", "#sigma(#it{p}_{T})/#it{p}_{T}; #it{p}_{T,track} (GeV/#it{c})", {HistType::kTH2F, {{90, 10., 100.}, {100000, 0.0, 100.0}}}); - registry.add("h2_track_pt_track_sigma1overpt", "#sigma(1/#it{p}_{T}); #it{p}_{T,track} (GeV/#it{c})", {HistType::kTH2F, {{100, 0., 10.}, {1000, 0.0, 10.0}}}); - registry.add("h2_track_pt_high_track_sigma1overpt", "#sigma(1/#it{p}_{T}); #it{p}_{T,track} (GeV/#it{c})", {HistType::kTH2F, {{90, 10., 100.}, {1000, 0.0, 10.0}}}); - //< \sigma p_T at local rho test plot > registry.add("h_accept_Track", "all and accept track;Track;entries", {HistType::kTH1F, {{10, 0.0, 10.0}}}); registry.get(HIST("h_accept_Track"))->GetXaxis()->SetBinLabel(1, "acceptTrk"); @@ -310,48 +240,30 @@ struct JetChargedV2 { registry.get(HIST("h_accept_Track"))->GetXaxis()->SetBinLabel(5, "getNtrk"); registry.get(HIST("h_accept_Track"))->GetXaxis()->SetBinLabel(6, "getNtrkMCP"); - registry.add("h_ptsum_collnum", "ptsum collnum;collnum;entries", {HistType::kTH1F, {{40, 0.0, 40}}}); - registry.add("h_ptsum_sumpt", "jet sumpt;sum p_{T};entries", {HistType::kTH1F, {{40, 0., o2::constants::math::TwoPI}}}); - registry.add("h2_phi_track_eta", "phi vs track eta; #eta (GeV/#it{c}); #varphi", {HistType::kTH2F, {{100, -1.0, 1.0}, {40, 0., o2::constants::math::TwoPI}}}); - registry.add("h2_centrality_phi_w_pt", "centrality vs jet #varphi; centrality; entries", {HistType::kTH2F, {{100, 0.0, 100.0}, {40, 0., o2::constants::math::TwoPI}}}); - registry.add("h2_evtnum_phi_w_pt", "eventNumber vs jet #varphi; #eventNumber; entries", {HistType::kTH2F, {{1000, 0.0, 1000}, {40, 0., o2::constants::math::TwoPI}}}); - //< fit quality >// registry.add("h_PvalueCDF_CombinFit", "cDF #chi^{2}; entries", {HistType::kTH1F, {{50, 0, 1}}}); registry.add("h2_PvalueCDFCent_CombinFit", "p-value cDF vs centrality; centrality; p-value", {HistType::kTH2F, {{100, 0, 100}, {40, 0, 1}}}); registry.add("h2_Chi2Cent_CombinFit", "Chi2 vs centrality; centrality; #tilde{#chi^{2}}", {HistType::kTH2F, {{100, 0, 100}, {100, 0, 5}}}); registry.add("h2_PChi2_CombinFit", "p-value vs #tilde{#chi^{2}}; p-value; #tilde{#chi^{2}}", {HistType::kTH2F, {{100, 0, 1}, {100, 0, 5}}}); - registry.add("Thn_PChi2_CombinFitCent", "p-value vs #tilde{#chi^{2}}; p-value; #tilde{#chi^{2}}", {HistType::kTHnSparseF, {{100, 0.0, 100.0}, {100, 0, 1}, {100, 0, 5}}}); registry.add("h2_PChi2_CombinFitA", "p-value vs #tilde{#chi^{2}}; p-value; #tilde{#chi^{2}}", {HistType::kTH2F, {{100, 0, 1}, {100, 0, 5}}}); registry.add("h2_PChi2_CombinFitB", "p-value vs #tilde{#chi^{2}}; p-value; #tilde{#chi^{2}}", {HistType::kTH2F, {{100, 0, 1}, {100, 0, 5}}}); registry.add("h_evtnum_centrlity", "eventNumber vs centrality ; #eventNumber", {HistType::kTH1F, {{1000, 0.0, 1000}}}); registry.add("h_evtnum_NTrk", "eventNumber vs Number of Track ; #eventNumber", {HistType::kTH1F, {{1000, 0.0, 1000}}}); - registry.add("Thn_evtnum_phi_centrality", "eventNumber vs jet #varphi; #eventNumber; entries", {HistType::kTHnSparseF, {{1000, 0.0, 1000}, {40, 0., o2::constants::math::TwoPI}, {100, 0.0, 100.0}}}); - - registry.add("h2_evt_fitpara", "event vs fit parameter; evtnum; parameter", {HistType::kTH2F, {cfgAxisEvtfit, {5, 0., 5}}}); registry.add("h_v2obs_centrality", "fitparameter v2obs vs centrality ; #centrality", {HistType::kTProfile, {cfgAxisVnCent}}); registry.add("h_v3obs_centrality", "fitparameter v3obs vs centrality ; #centrality", {HistType::kTProfile, {cfgAxisVnCent}}); registry.add("h_fitparaRho_evtnum", "fitparameter #rho_{0} vs evtnum ; #eventnumber", {HistType::kTH1F, {{1000, 0.0, 1000}}}); registry.add("h_fitparaPsi2_evtnum", "fitparameter #Psi_{2} vs evtnum ; #eventnumber", {HistType::kTH1F, {{1000, 0.0, 1000}}}); registry.add("h_fitparaPsi3_evtnum", "fitparameter #Psi_{3} vs evtnum ; #eventnumber", {HistType::kTH1F, {{1000, 0.0, 1000}}}); - registry.add("h_fitparav2obs_evtnum", "fitparameter v2obs vs evtnum ; #eventnumber", {HistType::kTH1F, {{1000, 0.0, 1000}}}); - registry.add("h_fitparav3obs_evtnum", "fitparameter v3obs vs evtnum ; #eventnumber", {HistType::kTH1F, {{1000, 0.0, 1000}}}); - registry.add("h2_fitParaZero_cent", "#varphi vs #rho(#varphi); #cent; #fitParameter[0] ", {HistType::kTH2F, {{100, 0., 100}, {210, -10.0, 200.0}}}); - registry.add("h2_phi_rhophi", "#varphi vs #rho(#varphi); #varphi - #Psi_{EP,2}; #rho_{ch}(#varphi) ", {HistType::kTH2F, {{40, 0., o2::constants::math::TwoPI}, {210, -10.0, 200.0}}}); registry.add("h2_phi_rholocal", "#varphi vs #rho(#varphi); #varphi - #Psi_{EP,2}; #rho(#varphi) ", {HistType::kTH2F, {{40, 0., o2::constants::math::TwoPI}, {210, -10.0, 200.0}}}); - registry.add("h2_phi_rholocal_cent", "#varphi vs #rho(#varphi); #cent; #rho(#varphi) ", {HistType::kTH2F, {{100, 0., 100}, {210, -10.0, 200.0}}}); - registry.add("h3_centrality_localrho_phi", "centrality; #rho_{local}; #Delta#varphi_{jet}", {HistType::kTH3F, {{120, -10.0, 110.0}, {200, 0.0, 200.0}, {40, 0., o2::constants::math::TwoPI}}}); - - registry.add("h3_centrality_rhovsphi_phi", "centrality; #rho(#varphi); #Delta#varphi_{jet}", {HistType::kTH3F, {{120, -10.0, 110.0}, {200, 0.0, 200.0}, {40, 0., o2::constants::math::TwoPI}}}); + registry.add("h2_rholocal_cent", "#varphi vs #rho(#varphi); #cent; #rho(#varphi) ", {HistType::kTH2F, {{100, 0., 100}, {210, -10.0, 200.0}}}); //< \sigma p_T at local rho test plot | end > registry.add("h_jet_pt_rhoareasubtracted", "jet pT rhoareasubtracted;#it{p}_{T,jet} (GeV/#it{c}); entries", {HistType::kTH1F, {jetPtAxisRhoAreaSub}}); - registry.add("h_jet_pt_rholocal", "jet pT rholocal;#it{p}_{T,jet} (GeV/#it{c});entries", {HistType::kTH1F, {jetPtAxisRhoAreaSub}}); registry.add("leadJetPt", "leadJet Pt ", {HistType::kTH1F, {{200, 0., 200.0}}}); registry.add("leadJetPhi", "leadJet constituent #phi ", {HistType::kTH1F, {{80, -1.0, 7.}}}); @@ -371,8 +283,6 @@ struct JetChargedV2 { registry.add("h2_centrality_jet_pt_in_plane_v2", "centrality vs #it{p}^{in-plane}_{T,jet}; centrality; #it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH2F, {{120, -10.0, 110.0}, jetPtAxisRhoAreaSub}}); registry.add("h2_centrality_jet_pt_out_of_plane_v2", "centrality vs #it{p}^{out-of-plane}_{T,jet}; centrality; #it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH2F, {{120, -10.0, 110.0}, jetPtAxisRhoAreaSub}}); - registry.add("h2_centrality_jet_pt_in_plane_v3", "centrality vs #it{p}^{in-plane}_{T,jet}; centrality; #it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH2F, {{120, -10.0, 110.0}, jetPtAxisRhoAreaSub}}); - registry.add("h2_centrality_jet_pt_out_of_plane_v3", "centrality vs #it{p}^{out-of-plane}_{T,jet}; centrality; #it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH2F, {{120, -10.0, 110.0}, jetPtAxisRhoAreaSub}}); //< rho(phi) >// registry.add("h_jet_pt_inclusive_v2_rho", "jet pT;#it{p}_{T,jet} (GeV/#it{c});entries", {HistType::kTH1F, {jetPtAxisRhoAreaSub}}); registry.add("h_jet_pt_in_plane_v2_rho", "jet pT;#it{p}^{in-plane}_{T,jet} (GeV/#it{c});entries", {HistType::kTH1F, {jetPtAxisRhoAreaSub}}); @@ -382,16 +292,67 @@ struct JetChargedV2 { registry.add("h2_centrality_jet_pt_in_plane_v2_rho", "centrality vs #it{p}^{in-plane}_{T,jet}; centrality; #it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH2F, {{120, -10.0, 110.0}, jetPtAxisRhoAreaSub}}); registry.add("h2_centrality_jet_pt_out_of_plane_v2_rho", "centrality vs #it{p}^{out-of-plane}_{T,jet}; centrality; #it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH2F, {{120, -10.0, 110.0}, jetPtAxisRhoAreaSub}}); - registry.add("h2_centrality_jet_pt_in_plane_v3_rho", "centrality vs #it{p}^{in-plane}_{T,jet}; centrality; #it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH2F, {{120, -10.0, 110.0}, jetPtAxisRhoAreaSub}}); - registry.add("h2_centrality_jet_pt_out_of_plane_v3_rho", "centrality vs #it{p}^{out-of-plane}_{T,jet}; centrality; #it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH2F, {{120, -10.0, 110.0}, jetPtAxisRhoAreaSub}}); registry.add("h2_centrality_jet_pt_rhoareasubtracted", "centrality vs. jet pT;centrality; #it{p}_{T,jet} (GeV/#it{c}); counts", {HistType::kTH2F, {centralityAxis, jetPtAxisRhoAreaSub}}); registry.add("h2_centrality_jet_eta_rhoareasubtracted", "centrality vs. jet eta;centrality; #eta; counts", {HistType::kTH2F, {centralityAxis, jetEtaAxis}}); registry.add("h2_centrality_jet_phi_rhoareasubtracted", "centrality vs. jet phi;centrality; #varphi; counts", {HistType::kTH2F, {centralityAxis, phiAxis}}); - registry.add("h2_jet_pt_jet_area_rhoareasubtracted", "jet #it{p}_{T,jet} vs. Area_{jet}; #it{p}_{T,jet} (GeV/#it{c}); Area_{jet}", {HistType::kTH2F, {jetPtAxis, {150, 0., 1.5}}}); - registry.add("h3_jet_pt_jet_eta_jet_phi_rhoareasubtracted", "jet_pt_eta_phi_rhoareasubtracted", {HistType::kTH3F, {jetPtAxisRhoAreaSub, jetEtaAxis, phiAxis}}); 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}}); } + + if (doprocessSigmaPtMCP) { + 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, {jetEtaAxis}}); + registry.add("h_jet_phi_part_rhoareasubtracted", "part jet #varphi;#varphi^{part}; counts", {HistType::kTH1F, {phiAxis}}); + + registry.add("leadJetPtMCP", "MCP leadJet Pt ", {HistType::kTH1F, {{200, 0., 200.0}}}); + registry.add("leadJetPhiMCP", "MCP leadJet constituent #phi ", {HistType::kTH1F, {{80, -1.0, 7.}}}); + registry.add("leadJetEtaMCP", "MCP leadJet constituent #eta ", {HistType::kTH1F, {{100, -1.0, 1.0}}}); + + registry.add("h2_mcp_phi_rholocal", "#varphi vs #rho(#varphi); #varphi - #Psi_{EP,2}; #rho(#varphi) ", {HistType::kTH2F, {{40, 0., o2::constants::math::TwoPI}, {210, -10.0, 200.0}}}); + registry.add("h2_mcp_centrality_rholocal", "#varphi vs #rho(#varphi); #varphi - #Psi_{EP,2}; #rho(#varphi) ", {HistType::kTH2F, {{120, -10.0, 110.0}, {210, -10.0, 200.0}}}); + registry.add("h_mcp_jet_pt_rholocal", "jet pT rholocal;#it{p}_{T,jet} (GeV/#it{c});entries", {HistType::kTH1F, {jetPtAxisRhoAreaSub}}); + //< MCP fit test >// + registry.add("h_mcp_evtnum_centrlity", "eventNumber vs centrality ; #eventNumber", {HistType::kTH1F, {{1000, 0.0, 1000}}}); + registry.add("h_mcp_v2obs_centrality", "fitparameter v2obs vs centrality ; #centrality", {HistType::kTProfile, {cfgAxisVnCent}}); + registry.add("h_mcp_v3obs_centrality", "fitparameter v3obs vs centrality ; #centrality", {HistType::kTProfile, {cfgAxisVnCent}}); + registry.add("h_mcp_fitparaRho_evtnum", "fitparameter #rho_{0} vs evtnum ; #eventnumber", {HistType::kTH1F, {{1000, 0.0, 1000}}}); + registry.add("h_mcp_fitparaPsi2_evtnum", "fitparameter #Psi_{2} vs evtnum ; #eventnumber", {HistType::kTH1F, {{1000, 0.0, 1000}}}); + registry.add("h_mcp_fitparaPsi3_evtnum", "fitparameter #Psi_{3} vs evtnum ; #eventnumber", {HistType::kTH1F, {{1000, 0.0, 1000}}}); + + registry.add("h_mcp_jet_pt_in_plane_v2_rho", "jet pT;#it{p}^{in-plane}_{T,jet} (GeV/#it{c});entries", {HistType::kTH1F, {jetPtAxisRhoAreaSub}}); + registry.add("h_mcp_jet_pt_out_of_plane_v2_rho", "jet pT;#it{p}^{out-of-plane}_{T,jet} (GeV/#it{c});entries", {HistType::kTH1F, {jetPtAxisRhoAreaSub}}); + registry.add("h_mcp_jet_pt_in_plane_v3_rho", "jet pT;#it{p}^{in-plane}_{T,jet} (GeV/#it{c});entries", {HistType::kTH1F, {jetPtAxisRhoAreaSub}}); + registry.add("h_mcp_jet_pt_out_of_plane_v3_rho", "jet pT;#it{p}^{out-of-plane}_{T,jet} (GeV/#it{c});entries", {HistType::kTH1F, {jetPtAxisRhoAreaSub}}); + + registry.add("h2_mcp_centrality_jet_pt_in_plane_v2_rho", "centrality vs #it{p}^{in-plane}_{T,jet}; centrality; #it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH2F, {{120, -10.0, 110.0}, jetPtAxisRhoAreaSub}}); + registry.add("h2_mcp_centrality_jet_pt_out_of_plane_v2_rho", "centrality vs #it{p}^{out-of-plane}_{T,jet}; centrality; #it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH2F, {{120, -10.0, 110.0}, jetPtAxisRhoAreaSub}}); + registry.add("h2_mcp_centrality_jet_pt_in_plane_v3_rho", "centrality vs #it{p}^{in-plane}_{T,jet}; centrality; #it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH2F, {{120, -10.0, 110.0}, jetPtAxisRhoAreaSub}}); + registry.add("h2_mcp_centrality_jet_pt_out_of_plane_v3_rho", "centrality vs #it{p}^{out-of-plane}_{T,jet}; centrality; #it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH2F, {{120, -10.0, 110.0}, jetPtAxisRhoAreaSub}}); + + registry.add("h3_mcp_centrality_deltapT_RandomCornPhi_localrhovsphi", "centrality; #it{p}_{T,random cone} - #it{area, random cone} * #it{rho}; #Delta#varphi_{jet}", {HistType::kTH3F, {{100, 0.0, 100.0}, {400, -200.0, 200.0}, {100, 0., o2::constants::math::TwoPI}}}); + registry.add("h3_mcp_centrality_deltapT_RandomCornPhi_rhorandomconewithoutleadingjet", "centrality; #it{p}_{T,random cone} - #it{area, random cone} * #it{rho}; #Delta#varphi_{jet}", {HistType::kTH3F, {{100, 0.0, 100.0}, {400, -200.0, 200.0}, {100, 0., o2::constants::math::TwoPI}}}); + registry.add("h3_mcp_centrality_deltapT_RandomCornPhi_localrhovsphiwithoutleadingjet", "centrality; #it{p}_{T,random cone} - #it{area, random cone} * #it{rho}(#varphi); #Delta#varphi_{jet}", {HistType::kTH3F, {{100, 0.0, 100.0}, {400, -200.0, 200.0}, {100, 0., o2::constants::math::TwoPI}}}); + + registry.add("h_mcColl_counts_areasub", " number of mc events; event status; entries", {HistType::kTH1F, {{10, 0, 10}}}); + registry.get(HIST("h_mcColl_counts_areasub"))->GetXaxis()->SetBinLabel(1, "allMcColl"); + registry.get(HIST("h_mcColl_counts_areasub"))->GetXaxis()->SetBinLabel(2, "vertexZ"); + registry.get(HIST("h_mcColl_counts_areasub"))->GetXaxis()->SetBinLabel(3, "noRecoColl"); + registry.get(HIST("h_mcColl_counts_areasub"))->GetXaxis()->SetBinLabel(4, "splitColl"); + registry.get(HIST("h_mcColl_counts_areasub"))->GetXaxis()->SetBinLabel(5, "recoEvtSel"); + registry.get(HIST("h_mcColl_counts_areasub"))->GetXaxis()->SetBinLabel(6, "centralitycut"); + registry.get(HIST("h_mcColl_counts_areasub"))->GetXaxis()->SetBinLabel(7, "occupancycut"); + registry.add("h_mcColl_rho", "mc collision rho;#rho (GeV/#it{c}); counts", {HistType::kTH1F, {{500, 0.0, 500.0}}}); + + //< \sigma p_T at local rho test plot > + registry.add("h_accept_Track", "all and accept track;Track;entries", {HistType::kTH1F, {{10, 0.0, 10.0}}}); + registry.get(HIST("h_accept_Track"))->GetXaxis()->SetBinLabel(1, "acceptTrk"); + registry.get(HIST("h_accept_Track"))->GetXaxis()->SetBinLabel(2, "acceptTrkInFit"); + registry.get(HIST("h_accept_Track"))->GetXaxis()->SetBinLabel(3, "beforeSumptFit"); + registry.get(HIST("h_accept_Track"))->GetXaxis()->SetBinLabel(4, "afterSumptFit"); + registry.get(HIST("h_accept_Track"))->GetXaxis()->SetBinLabel(5, "getNtrk"); + registry.get(HIST("h_accept_Track"))->GetXaxis()->SetBinLabel(6, "getNtrkMCP"); + } + //< track test >// registry.add("h_track_pt", "track #it{p}_{T} ; #it{p}_{T,track} (GeV/#it{c})", {HistType::kTH1F, {trackPtAxis}}); registry.add("h2_track_eta_track_phi", "track eta vs. track phi; #eta; #phi; counts", {HistType::kTH2F, {trackEtaAxis, phiAxis}}); @@ -504,8 +465,8 @@ struct JetChargedV2 { } // fill nTrk plot for fit rho(varphi) - template - void fillNtrkCheck(T const& collision, U const& tracks, J const& jets, TH1F* hPtsumSumptFit, double& leadingJetEta, double& evtnum) + template + void fillNtrkCheck(U const& tracks, J const& jets, TH1F* hPtsumSumptFit, double& leadingJetEta) { if (jets.size() > 0) { for (auto const& trackfit : tracks) { @@ -520,11 +481,6 @@ struct JetChargedV2 { if (jetderiveddatautilities::selectTrack(track, trackSelection) && (std::fabs(track.eta() - leadingJetEta) > jetRadius) && track.pt() >= localRhoFitPtMin && track.pt() <= localRhoFitPtMax) { registry.fill(HIST("h_accept_Track"), 3.5); hPtsumSumptFit->Fill(track.phi(), track.pt()); - registry.fill(HIST("h2_phi_track_eta"), track.eta(), track.phi()); - registry.fill(HIST("h_ptsum_sumpt"), track.phi(), track.pt()); - registry.fill(HIST("h2_centrality_phi_w_pt"), collision.centrality(), track.phi(), track.pt()); - registry.fill(HIST("h2_evtnum_phi_w_pt"), evtnum, track.phi(), track.pt()); - registry.fill(HIST("Thn_evtnum_phi_centrality"), evtnum, track.phi(), collision.centrality()); } } } @@ -606,11 +562,8 @@ struct JetChargedV2 { return; } registry.fill(HIST("h_mcp_fitparaRho_evtnum"), evtnum, temppara[0]); - registry.fill(HIST("h_mcp_fitparav2obs_evtnum"), evtnum, temppara[1]); registry.fill(HIST("h_mcp_fitparaPsi2_evtnum"), evtnum, temppara[2]); - registry.fill(HIST("h_mcp_fitparav3obs_evtnum"), evtnum, temppara[3]); registry.fill(HIST("h_mcp_fitparaPsi3_evtnum"), evtnum, temppara[4]); - registry.fill(HIST("h_mcp_v2obs_centrality"), collision.centrality(), temppara[1]); registry.fill(HIST("h_mcp_v3obs_centrality"), collision.centrality(), temppara[3]); registry.fill(HIST("h_mcp_evtnum_centrlity"), evtnum, collision.centrality()); @@ -632,8 +585,8 @@ struct JetChargedV2 { double integralValue = fFitModulationV2v3P->Integral(jet.phi() - jetRadius, jet.phi() + jetRadius); double rholocal = collision.rho() / (2 * jetRadius * temppara[0]) * integralValue; - registry.fill(HIST("h3_mcp_centrality_localrho_phi"), collision.centrality(), rholocal, jet.phi() - ep2, weight); - + registry.fill(HIST("h2_mcp_phi_rholocal"), jet.phi() - ep2, rholocal, weight); + registry.fill(HIST("h2_mcp_centrality_rholocal"), collision.centrality(), rholocal, weight); if (nmode == cfgNmodA) { registry.fill(HIST("h_mcp_jet_pt_rholocal"), jet.pt() - (rholocal * jet.area()), weight); @@ -642,9 +595,6 @@ struct JetChargedV2 { continue; } phiMinusPsi2 = jet.phi() - ep2; - - registry.fill(HIST("h2_mcp_phi_rholocal"), jet.phi() - ep2, rholocal, weight); - if ((phiMinusPsi2 < o2::constants::math::PIQuarter) || (phiMinusPsi2 >= evtPlnAngleA * o2::constants::math::PIQuarter) || (phiMinusPsi2 >= evtPlnAngleB * o2::constants::math::PIQuarter && phiMinusPsi2 < evtPlnAngleC * o2::constants::math::PIQuarter)) { registry.fill(HIST("h_mcp_jet_pt_in_plane_v2_rho"), jet.pt() - (rholocal * jet.area()), weight); registry.fill(HIST("h2_mcp_centrality_jet_pt_in_plane_v2_rho"), collision.centrality(), jet.pt() - (rholocal * jet.area()), weight); @@ -740,11 +690,9 @@ struct JetChargedV2 { if (jet.r() == round(selectedJetsRadius * 100.0f)) { // fill jet histograms after area-based subtraction registry.fill(HIST("h2_centrality_jet_pt_rhoareasubtracted"), centrality, jetcorrpt, weight); - registry.fill(HIST("h3_jet_pt_jet_eta_jet_phi_rhoareasubtracted"), jetcorrpt, jet.eta(), jet.phi(), weight); if (jetcorrpt > 0) { registry.fill(HIST("h2_centrality_jet_eta_rhoareasubtracted"), centrality, jet.eta(), weight); registry.fill(HIST("h2_centrality_jet_phi_rhoareasubtracted"), centrality, jet.phi(), weight); - registry.fill(HIST("h2_jet_pt_jet_area_rhoareasubtracted"), jetcorrpt, jet.area(), weight); } } @@ -763,11 +711,10 @@ struct JetChargedV2 { if (jet.r() == round(selectedJetsRadius * 100.0f)) { // fill mcp jet histograms double jetcorrpt = jet.pt() - (rho * jet.area()); - registry.fill(HIST("h3_jet_pt_jet_eta_jet_phi_part_rhoareasubtracted"), jetcorrpt, jet.eta(), jet.phi(), weight); + registry.fill(HIST("h_jet_pt_part_rhoareasubtracted"), jetcorrpt, weight); if (jetcorrpt > 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"), jetcorrpt, jet.area(), weight); } } } @@ -886,10 +833,8 @@ struct JetChargedV2 { if ((phiMinusPsi3 < o2::constants::math::PIQuarter) || (phiMinusPsi3 >= evtPlnAngleA * o2::constants::math::PIQuarter) || (phiMinusPsi3 >= evtPlnAngleB * o2::constants::math::PIQuarter && phiMinusPsi3 < evtPlnAngleC * o2::constants::math::PIQuarter)) { registry.fill(HIST("h_jet_pt_in_plane_v3"), jet.pt() - (collision.rho() * jet.area()), 1.0); - registry.fill(HIST("h2_centrality_jet_pt_in_plane_v3"), collision.centrality(), jet.pt() - (collision.rho() * jet.area()), 1.0); } else { registry.fill(HIST("h_jet_pt_out_of_plane_v3"), jet.pt() - (collision.rho() * jet.area()), 1.0); - registry.fill(HIST("h2_centrality_jet_pt_out_of_plane_v3"), collision.centrality(), jet.pt() - (collision.rho() * jet.area()), 1.0); } } } @@ -1002,10 +947,8 @@ struct JetChargedV2 { if ((phiMinusPsi3 < o2::constants::math::PIQuarter) || (phiMinusPsi3 >= evtPlnAngleA * o2::constants::math::PIQuarter) || (phiMinusPsi3 >= evtPlnAngleB * o2::constants::math::PIQuarter && phiMinusPsi3 < evtPlnAngleC * o2::constants::math::PIQuarter)) { registry.fill(HIST("h_jet_pt_in_plane_v3"), jet.pt() - (collision.rho() * jet.area()), 1.0); - registry.fill(HIST("h2_centrality_jet_pt_in_plane_v3"), collision.centrality(), jet.pt() - (collision.rho() * jet.area()), 1.0); } else { registry.fill(HIST("h_jet_pt_out_of_plane_v3"), jet.pt() - (collision.rho() * jet.area()), 1.0); - registry.fill(HIST("h2_centrality_jet_pt_out_of_plane_v3"), collision.centrality(), jet.pt() - (collision.rho() * jet.area()), 1.0); } } } @@ -1039,9 +982,7 @@ struct JetChargedV2 { } hPtsumSumptFit = new TH1F("h_ptsum_sumpt_fit", "h_ptsum_sumpt fit use", TMath::CeilNint(std::sqrt(nTrk)), 0., o2::constants::math::TwoPI); - fillNtrkCheck(collision, tracks, jets, hPtsumSumptFit, leadingJetEta, evtnum); - - registry.fill(HIST("h_ptsum_collnum"), 0.5); + fillNtrkCheck(tracks, jets, hPtsumSumptFit, leadingJetEta); double ep2 = 0.; double ep3 = 0.; @@ -1095,17 +1036,10 @@ struct JetChargedV2 { temppara[2] = fFitModulationV2v3->GetParameter(2); temppara[3] = fFitModulationV2v3->GetParameter(3); temppara[4] = fFitModulationV2v3->GetParameter(4); - int paraNum = 5; - for (int i = 1; i <= paraNum; i++) { - registry.fill(HIST("h2_evt_fitpara"), evtnum, i - 0.5, temppara[i - 1]); - } registry.fill(HIST("h_fitparaRho_evtnum"), evtnum, temppara[0]); - registry.fill(HIST("h_fitparav2obs_evtnum"), evtnum, temppara[1]); registry.fill(HIST("h_fitparaPsi2_evtnum"), evtnum, temppara[2]); - registry.fill(HIST("h_fitparav3obs_evtnum"), evtnum, temppara[3]); registry.fill(HIST("h_fitparaPsi3_evtnum"), evtnum, temppara[4]); - registry.fill(HIST("h_v2obs_centrality"), collision.centrality(), temppara[1]); registry.fill(HIST("h_v3obs_centrality"), collision.centrality(), temppara[3]); registry.fill(HIST("h_evtnum_centrlity"), evtnum, collision.centrality()); @@ -1113,7 +1047,6 @@ struct JetChargedV2 { if (temppara[0] == 0) { return; } - registry.fill(HIST("h2_fitParaZero_cent"), collision.centrality(), temppara[0], 1.0); int nDF = 1; int numOfFreePara = 2; @@ -1133,22 +1066,30 @@ struct JetChargedV2 { chiSqr = chi2; cDF = 1. - chiSquareCDF(nDF, chiSqr); - registry.fill(HIST("h_PvalueCDF_CombinFit"), cDF); - registry.fill(HIST("h2_PvalueCDFCent_CombinFit"), collision.centrality(), cDF); - registry.fill(HIST("h2_Chi2Cent_CombinFit"), collision.centrality(), chiSqr / (static_cast(nDF))); - registry.fill(HIST("h2_PChi2_CombinFit"), cDF, chiSqr / (static_cast(nDF))); - registry.fill(HIST("Thn_PChi2_CombinFitCent"), collision.centrality(), cDF, chiSqr / (static_cast(nDF))); - double evtcent = collision.centrality(); int evtCentAreaMin = 0; int evtCentAreaMax = 5; int evtMidAreaMin = 30; int evtMidAreaMax = 50; - if (evtcent >= evtCentAreaMin && evtcent <= evtCentAreaMax) { - registry.fill(HIST("h2_PChi2_CombinFitA"), cDF, chiSqr / (static_cast(nDF))); + double evtcent = collision.centrality(); + if (cfgChkFitQuality) { + registry.fill(HIST("h_PvalueCDF_CombinFit"), cDF); + registry.fill(HIST("h2_PvalueCDFCent_CombinFit"), collision.centrality(), cDF); + registry.fill(HIST("h2_Chi2Cent_CombinFit"), collision.centrality(), chiSqr / (static_cast(nDF))); + registry.fill(HIST("h2_PChi2_CombinFit"), cDF, chiSqr / (static_cast(nDF))); + if (evtcent >= evtCentAreaMin && evtcent <= evtCentAreaMax) { + registry.fill(HIST("h2_PChi2_CombinFitA"), cDF, chiSqr / (static_cast(nDF))); + + } else if (evtcent >= evtMidAreaMin && evtcent <= evtMidAreaMax) { + registry.fill(HIST("h2_PChi2_CombinFitB"), cDF, chiSqr / (static_cast(nDF))); + } + if (evtcent >= evtCentAreaMin && evtcent <= evtCentAreaMax) { + registry.fill(HIST("h2_PChi2_CombinFitA"), cDF, chiSqr / (static_cast(nDF))); - } else if (evtcent >= evtMidAreaMin && evtcent <= evtMidAreaMax) { - registry.fill(HIST("h2_PChi2_CombinFitB"), cDF, chiSqr / (static_cast(nDF))); + } else if (evtcent >= evtMidAreaMin && evtcent <= evtMidAreaMax) { + registry.fill(HIST("h2_PChi2_CombinFitB"), cDF, chiSqr / (static_cast(nDF))); + } } + for (uint i = 0; i < cfgnMods->size(); i++) { int nmode = cfgnMods->at(i); int detInd = detId * 4 + cfgnTotalSystem * 4 * (nmode - 2); @@ -1166,15 +1107,9 @@ struct JetChargedV2 { double integralValue = fFitModulationV2v3->Integral(jet.phi() - jetRadius, jet.phi() + jetRadius); double rholocal = collision.rho() / (2 * jetRadius * temppara[0]) * integralValue; - registry.fill(HIST("h2_phi_rhophi"), jet.phi() - ep2, fFitModulationV2v3->Eval(jet.phi()), 1.0); - registry.fill(HIST("h3_centrality_rhovsphi_phi"), collision.centrality(), fFitModulationV2v3->Eval(jet.phi()), jet.phi() - ep2); - - registry.fill(HIST("h2_phi_rholocal_cent"), collision.centrality(), rholocal, 1.0); - registry.fill(HIST("h3_centrality_localrho_phi"), collision.centrality(), rholocal, jet.phi() - ep2); + registry.fill(HIST("h2_rholocal_cent"), collision.centrality(), rholocal, 1.0); if (nmode == cfgNmodA) { - registry.fill(HIST("h_jet_pt_rholocal"), jet.pt() - (rholocal * jet.area()), 1.0); - double phiMinusPsi2; if (collision.qvecAmp()[detId] < collQvecAmpDetId) { continue; @@ -1201,10 +1136,8 @@ struct JetChargedV2 { if ((phiMinusPsi3 < o2::constants::math::PIQuarter) || (phiMinusPsi3 >= evtPlnAngleA * o2::constants::math::PIQuarter) || (phiMinusPsi3 >= evtPlnAngleB * o2::constants::math::PIQuarter && phiMinusPsi3 < evtPlnAngleC * o2::constants::math::PIQuarter)) { registry.fill(HIST("h_jet_pt_in_plane_v3_rho"), jet.pt() - (rholocal * jet.area()), 1.0); - registry.fill(HIST("h2_centrality_jet_pt_in_plane_v3_rho"), collision.centrality(), jet.pt() - (rholocal * jet.area()), 1.0); } else { registry.fill(HIST("h_jet_pt_out_of_plane_v3_rho"), jet.pt() - (rholocal * jet.area()), 1.0); - registry.fill(HIST("h2_centrality_jet_pt_out_of_plane_v3_rho"), collision.centrality(), jet.pt() - (rholocal * jet.area()), 1.0); } } } @@ -1307,9 +1240,7 @@ struct JetChargedV2 { } hPtsumSumptFit = new TH1F("h_ptsum_sumpt_fit", "h_ptsum_sumpt fit use", TMath::CeilNint(std::sqrt(nTrk)), 0., o2::constants::math::TwoPI); - fillNtrkCheck(collision, tracks, jets, hPtsumSumptFit, leadingJetEta, evtnum); - - registry.fill(HIST("h_ptsum_collnum"), 0.5); + fillNtrkCheck(tracks, jets, hPtsumSumptFit, leadingJetEta); double ep2 = 0.; double ep3 = 0.; @@ -1363,17 +1294,10 @@ struct JetChargedV2 { temppara[2] = fFitModulationV2v3->GetParameter(2); temppara[3] = fFitModulationV2v3->GetParameter(3); temppara[4] = fFitModulationV2v3->GetParameter(4); - int paraNum = 5; - for (int i = 1; i <= paraNum; i++) { - registry.fill(HIST("h2_evt_fitpara"), evtnum, i - 0.5, temppara[i - 1]); - } registry.fill(HIST("h_fitparaRho_evtnum"), evtnum, temppara[0]); - registry.fill(HIST("h_fitparav2obs_evtnum"), evtnum, temppara[1]); registry.fill(HIST("h_fitparaPsi2_evtnum"), evtnum, temppara[2]); - registry.fill(HIST("h_fitparav3obs_evtnum"), evtnum, temppara[3]); registry.fill(HIST("h_fitparaPsi3_evtnum"), evtnum, temppara[4]); - registry.fill(HIST("h_v2obs_centrality"), collision.centrality(), temppara[1]); registry.fill(HIST("h_v3obs_centrality"), collision.centrality(), temppara[3]); registry.fill(HIST("h_evtnum_centrlity"), evtnum, collision.centrality()); @@ -1381,7 +1305,6 @@ struct JetChargedV2 { if (temppara[0] == 0) { return; } - registry.fill(HIST("h2_fitParaZero_cent"), collision.centrality(), temppara[0], 1.0); int nDF = 1; int numOfFreePara = 2; @@ -1401,22 +1324,24 @@ struct JetChargedV2 { chiSqr = chi2; cDF = 1. - chiSquareCDF(nDF, chiSqr); - registry.fill(HIST("h_PvalueCDF_CombinFit"), cDF); - registry.fill(HIST("h2_PvalueCDFCent_CombinFit"), collision.centrality(), cDF); - registry.fill(HIST("h2_Chi2Cent_CombinFit"), collision.centrality(), chiSqr / (static_cast(nDF))); - registry.fill(HIST("h2_PChi2_CombinFit"), cDF, chiSqr / (static_cast(nDF))); - registry.fill(HIST("Thn_PChi2_CombinFitCent"), collision.centrality(), cDF, chiSqr / (static_cast(nDF))); - double evtcent = collision.centrality(); int evtCentAreaMin = 0; int evtCentAreaMax = 5; int evtMidAreaMin = 30; int evtMidAreaMax = 50; - if (evtcent >= evtCentAreaMin && evtcent <= evtCentAreaMax) { - registry.fill(HIST("h2_PChi2_CombinFitA"), cDF, chiSqr / (static_cast(nDF))); - - } else if (evtcent >= evtMidAreaMin && evtcent <= evtMidAreaMax) { - registry.fill(HIST("h2_PChi2_CombinFitB"), cDF, chiSqr / (static_cast(nDF))); + double evtcent = collision.centrality(); + if (cfgChkFitQuality) { + registry.fill(HIST("h_PvalueCDF_CombinFit"), cDF); + registry.fill(HIST("h2_PvalueCDFCent_CombinFit"), collision.centrality(), cDF); + registry.fill(HIST("h2_Chi2Cent_CombinFit"), collision.centrality(), chiSqr / (static_cast(nDF))); + registry.fill(HIST("h2_PChi2_CombinFit"), cDF, chiSqr / (static_cast(nDF))); + if (evtcent >= evtCentAreaMin && evtcent <= evtCentAreaMax) { + registry.fill(HIST("h2_PChi2_CombinFitA"), cDF, chiSqr / (static_cast(nDF))); + + } else if (evtcent >= evtMidAreaMin && evtcent <= evtMidAreaMax) { + registry.fill(HIST("h2_PChi2_CombinFitB"), cDF, chiSqr / (static_cast(nDF))); + } } + for (uint i = 0; i < cfgnMods->size(); i++) { int nmode = cfgnMods->at(i); int detInd = detId * 4 + cfgnTotalSystem * 4 * (nmode - 2); @@ -1434,15 +1359,9 @@ struct JetChargedV2 { double integralValue = fFitModulationV2v3->Integral(jet.phi() - jetRadius, jet.phi() + jetRadius); double rholocal = collision.rho() / (2 * jetRadius * temppara[0]) * integralValue; - registry.fill(HIST("h2_phi_rhophi"), jet.phi() - ep2, fFitModulationV2v3->Eval(jet.phi()), 1.0); - registry.fill(HIST("h3_centrality_rhovsphi_phi"), collision.centrality(), fFitModulationV2v3->Eval(jet.phi()), jet.phi() - ep2); - - registry.fill(HIST("h2_phi_rholocal_cent"), collision.centrality(), rholocal, 1.0); - registry.fill(HIST("h3_centrality_localrho_phi"), collision.centrality(), rholocal, jet.phi() - ep2); + registry.fill(HIST("h2_rholocal_cent"), collision.centrality(), rholocal, 1.0); if (nmode == cfgNmodA) { - registry.fill(HIST("h_jet_pt_rholocal"), jet.pt() - (rholocal * jet.area()), 1.0); - double phiMinusPsi2; if (collision.qvecAmp()[detId] < collQvecAmpDetId) { continue; @@ -1469,10 +1388,8 @@ struct JetChargedV2 { if ((phiMinusPsi3 < o2::constants::math::PIQuarter) || (phiMinusPsi3 >= evtPlnAngleA * o2::constants::math::PIQuarter) || (phiMinusPsi3 >= evtPlnAngleB * o2::constants::math::PIQuarter && phiMinusPsi3 < evtPlnAngleC * o2::constants::math::PIQuarter)) { registry.fill(HIST("h_jet_pt_in_plane_v3_rho"), jet.pt() - (rholocal * jet.area()), 1.0); - registry.fill(HIST("h2_centrality_jet_pt_in_plane_v3_rho"), collision.centrality(), jet.pt() - (rholocal * jet.area()), 1.0); } else { registry.fill(HIST("h_jet_pt_out_of_plane_v3_rho"), jet.pt() - (rholocal * jet.area()), 1.0); - registry.fill(HIST("h2_centrality_jet_pt_out_of_plane_v3_rho"), collision.centrality(), jet.pt() - (rholocal * jet.area()), 1.0); } } } @@ -1615,23 +1532,20 @@ struct JetChargedV2 { fillMCPAreaSubHistograms(jet, mccollision.rho()); } + double leadingJetPt = -1; + double leadingJetPhi = -1; + double leadingJetEta = -1; + int nTrk = 0; for (auto const& collision : collisions) { auto collTracks = tracks.sliceBy(tracksPerJCollision, collision.globalIndex()); - - double leadingJetPt = -1; - double leadingJetPhi = -1; - double leadingJetEta = -1; fillLeadingJetQAMCP(jets, leadingJetPt, leadingJetPhi, leadingJetEta); - int nTrk = 0; if (jets.size() > 0) { for (auto const& track : collTracks) { if (jetderiveddatautilities::selectTrack(track, trackSelection) && (std::fabs(track.eta() - leadingJetEta) > jetRadius) && track.pt() >= localRhoFitPtMin && track.pt() <= localRhoFitPtMax) { - registry.fill(HIST("h_accept_Track"), 5.5); nTrk += 1; } } - registry.fill(HIST("h_mcp_evtnum_NTrk"), evtnum, nTrk); } if (nTrk <= 0) { return; @@ -1642,13 +1556,9 @@ struct JetChargedV2 { for (auto const& track : collTracks) { if (jetderiveddatautilities::selectTrack(track, trackSelection) && (std::fabs(track.eta() - leadingJetEta) > jetRadius) && track.pt() >= localRhoFitPtMin && track.pt() <= localRhoFitPtMax) { hPtsumSumptFitMCP->Fill(track.phi(), track.pt()); - registry.fill(HIST("h2_mcp_phi_track_eta"), track.eta(), track.phi()); - registry.fill(HIST("h_mcp_ptsum_sumpt"), track.phi(), track.pt()); } } } - - registry.fill(HIST("h_ptsum_collnum"), 0.5); fitFncMCP(collision, tracks, jets, hPtsumSumptFitMCP, leadingJetEta, mcLevelIsParticleLevel); } From c29bb517ce9ad990fe1934d5248192a04c4587f7 Mon Sep 17 00:00:00 2001 From: ddobrigk Date: Tue, 17 Jun 2025 09:17:39 +0200 Subject: [PATCH 100/871] [Common] Prevent CCDB crash -> always captured (#11639) Co-authored-by: ALICE Builder --- Common/TableProducer/multCentTable.cxx | 1 + 1 file changed, 1 insertion(+) diff --git a/Common/TableProducer/multCentTable.cxx b/Common/TableProducer/multCentTable.cxx index 421e813bad4..ab6ec98bc20 100644 --- a/Common/TableProducer/multCentTable.cxx +++ b/Common/TableProducer/multCentTable.cxx @@ -72,6 +72,7 @@ struct MultCentTable { ccdb->setCaching(true); ccdb->setLocalObjectValidityChecking(); ccdb->setURL(ccdburl.value); + ccdb->setFatalWhenNull(false); // please never crash on your own, all exceptions captured (as they always should) // task-specific module.init(opts, initContext); From c2f1bc0d60e8cc49ddc1f3b4e942bbcf7e1d65cd Mon Sep 17 00:00:00 2001 From: ypwangg <142303052+ypwangg@users.noreply.github.com> Date: Tue, 17 Jun 2025 17:19:23 +0800 Subject: [PATCH 101/871] [PWGDQ] Add cent FT0A and FT0M (#11632) Co-authored-by: Yiping Wang Co-authored-by: ALICE Action Bot --- PWGDQ/Core/VarManager.cxx | 6 +++ PWGDQ/Core/VarManager.h | 4 ++ PWGDQ/DataModel/ReducedInfoTables.h | 26 ++++++--- PWGDQ/TableProducer/tableMaker.cxx | 20 +++---- PWGDQ/TableProducer/tableMakerMC.cxx | 20 +++---- .../TableProducer/tableMakerMC_withAssoc.cxx | 10 ++-- PWGDQ/TableProducer/tableMaker_withAssoc.cxx | 10 ++-- PWGDQ/Tasks/CMakeLists.txt | 5 ++ PWGDQ/Tasks/ModelConverterEventExtended.cxx | 53 +++++++++++++++++++ PWGDQ/Tasks/dqFlow.cxx | 2 +- 10 files changed, 121 insertions(+), 35 deletions(-) create mode 100644 PWGDQ/Tasks/ModelConverterEventExtended.cxx diff --git a/PWGDQ/Core/VarManager.cxx b/PWGDQ/Core/VarManager.cxx index 456f4e763dc..a113f0571d3 100644 --- a/PWGDQ/Core/VarManager.cxx +++ b/PWGDQ/Core/VarManager.cxx @@ -202,6 +202,10 @@ void VarManager::SetDefaultVarNames() fgVariableUnits[kCentVZERO] = "%"; fgVariableNames[kCentFT0C] = "Centrality FT0C"; fgVariableUnits[kCentFT0C] = "%"; + fgVariableNames[kCentFT0A] = "Centrality FT0A"; + fgVariableUnits[kCentFT0A] = "%"; + fgVariableNames[kCentFT0M] = "Centrality FT0M"; + fgVariableUnits[kCentFT0M] = "%"; fgVariableNames[kMultTPC] = "Multiplicity TPC"; fgVariableUnits[kMultTPC] = ""; fgVariableNames[kMultFV0A] = "Multiplicity FV0A"; @@ -1109,6 +1113,8 @@ void VarManager::SetDefaultVarNames() fgVarNamesMap["kVtxChi2"] = kVtxChi2; fgVarNamesMap["kCentVZERO"] = kCentVZERO; fgVarNamesMap["kCentFT0C"] = kCentFT0C; + fgVarNamesMap["kCentFT0A"] = kCentFT0A; + fgVarNamesMap["kCentFT0M"] = kCentFT0M; fgVarNamesMap["kMultTPC"] = kMultTPC; fgVarNamesMap["kMultFV0A"] = kMultFV0A; fgVarNamesMap["kMultFV0C"] = kMultFV0C; diff --git a/PWGDQ/Core/VarManager.h b/PWGDQ/Core/VarManager.h index da084fdfb89..26d2732dd45 100644 --- a/PWGDQ/Core/VarManager.h +++ b/PWGDQ/Core/VarManager.h @@ -223,6 +223,8 @@ class VarManager : public TObject kVtxChi2, kCentVZERO, kCentFT0C, + kCentFT0A, + kCentFT0M, kMultTPC, kMultFV0A, kMultFV0C, @@ -1574,6 +1576,8 @@ void VarManager::FillEvent(T const& event, float* values) if constexpr ((fillMap & CollisionCent) > 0 || (fillMap & ReducedEventExtended) > 0) { values[kCentFT0C] = event.centFT0C(); + values[kCentFT0A] = event.centFT0A(); + values[kCentFT0M] = event.centFT0M(); } if constexpr ((fillMap & CollisionMult) > 0 || (fillMap & ReducedEventExtended) > 0) { diff --git a/PWGDQ/DataModel/ReducedInfoTables.h b/PWGDQ/DataModel/ReducedInfoTables.h index 519928665e9..68673e81de2 100644 --- a/PWGDQ/DataModel/ReducedInfoTables.h +++ b/PWGDQ/DataModel/ReducedInfoTables.h @@ -15,18 +15,20 @@ #ifndef PWGDQ_DATAMODEL_REDUCEDINFOTABLES_H_ #define PWGDQ_DATAMODEL_REDUCEDINFOTABLES_H_ -#include -#include -#include "Framework/ASoA.h" -#include "Framework/AnalysisDataModel.h" +#include "PWGHF/Utils/utilsPid.h" + #include "Common/DataModel/Centrality.h" -#include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/Qvectors.h" #include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/Qvectors.h" + +#include "Framework/ASoA.h" +#include "Framework/AnalysisDataModel.h" #include "MathUtils/Utils.h" -#include "PWGHF/Utils/utilsPid.h" +#include +#include namespace o2::aod { @@ -146,12 +148,20 @@ DECLARE_SOA_TABLE_STAGED(ReducedEvents, "REDUCEDEVENT", //! Main event informa collision::PosX, collision::PosY, collision::PosZ, collision::NumContrib, collision::CollisionTime, collision::CollisionTimeRes); -DECLARE_SOA_TABLE(ReducedEventsExtended, "AOD", "REEXTENDED", //! Extended event information +DECLARE_SOA_TABLE(ReducedEventsExtended_000, "AOD", "REEXTENDED", //! Extended event information bc::GlobalBC, evsel::Alias, evsel::Selection, timestamp::Timestamp, cent::CentRun2V0M, mult::MultTPC, mult::MultFV0A, mult::MultFV0C, mult::MultFT0A, mult::MultFT0C, mult::MultFDDA, mult::MultFDDC, mult::MultZNA, mult::MultZNC, mult::MultTracklets, mult::MultNTracksPV, cent::CentFT0C); +DECLARE_SOA_TABLE_VERSIONED(ReducedEventsExtended_001, "AOD", "REEXTENDED", 1, //! Extended event information + bc::GlobalBC, evsel::Alias, evsel::Selection, timestamp::Timestamp, cent::CentRun2V0M, + mult::MultTPC, mult::MultFV0A, mult::MultFV0C, mult::MultFT0A, mult::MultFT0C, + mult::MultFDDA, mult::MultFDDC, mult::MultZNA, mult::MultZNC, mult::MultTracklets, mult::MultNTracksPV, + cent::CentFT0C, cent::CentFT0A, cent::CentFT0M); + +using ReducedEventsExtended = ReducedEventsExtended_001; + DECLARE_SOA_TABLE(ReducedEventsMultPV_000, "AOD", "REMULTPV", //! Multiplicity information for primary vertex mult::MultNTracksHasITS, mult::MultNTracksHasTPC, mult::MultNTracksHasTOF, mult::MultNTracksHasTRD, mult::MultNTracksITSOnly, mult::MultNTracksTPCOnly, mult::MultNTracksITSTPC, diff --git a/PWGDQ/TableProducer/tableMaker.cxx b/PWGDQ/TableProducer/tableMaker.cxx index 6792ba67932..87d1183d385 100644 --- a/PWGDQ/TableProducer/tableMaker.cxx +++ b/PWGDQ/TableProducer/tableMaker.cxx @@ -113,8 +113,8 @@ using MyEvents = soa::Join; using MyEventsWithMults = soa::Join; using MyEventsWithFilter = soa::Join; using MyEventsWithMultsAndFilter = soa::Join; -using MyEventsWithCent = soa::Join; -using MyEventsWithCentAndMults = soa::Join; +using MyEventsWithCent = soa::Join; +using MyEventsWithCentAndMults = soa::Join; using MyMuons = soa::Join; using MyMuonsWithCov = soa::Join; using MyMuonsColl = soa::Join; @@ -481,17 +481,17 @@ struct TableMaker { eventExtended(bc.globalBC(), collision.alias_raw(), collision.selection_raw(), bc.timestamp(), VarManager::fgValues[VarManager::kCentVZERO], collision.multTPC(), collision.multFV0A(), collision.multFV0C(), collision.multFT0A(), collision.multFT0C(), collision.multFDDA(), collision.multFDDC(), collision.multZNA(), collision.multZNC(), collision.multTracklets(), collision.multNTracksPV(), - collision.centFT0C()); + collision.centFT0C(), collision.centFT0A(), collision.centFT0M()); } else if constexpr ((TEventFillMap & VarManager::ObjTypes::CollisionMult) > 0) { eventExtended(bc.globalBC(), collision.alias_raw(), collision.selection_raw(), bc.timestamp(), VarManager::fgValues[VarManager::kCentVZERO], collision.multTPC(), collision.multFV0A(), collision.multFV0C(), collision.multFT0A(), collision.multFT0C(), collision.multFDDA(), collision.multFDDC(), collision.multZNA(), collision.multZNC(), collision.multTracklets(), collision.multNTracksPV(), - -1); + -1, -1, -1); } else if constexpr ((TEventFillMap & VarManager::ObjTypes::CollisionCent) > 0) { eventExtended(bc.globalBC(), collision.alias_raw(), collision.selection_raw(), bc.timestamp(), VarManager::fgValues[VarManager::kCentVZERO], - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, collision.centFT0C()); + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, collision.centFT0C(), collision.centFT0A(), collision.centFT0M()); } else { - eventExtended(bc.globalBC(), collision.alias_raw(), collision.selection_raw(), bc.timestamp(), VarManager::fgValues[VarManager::kCentVZERO], -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1); + eventExtended(bc.globalBC(), collision.alias_raw(), collision.selection_raw(), bc.timestamp(), VarManager::fgValues[VarManager::kCentVZERO], -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1); } eventVtxCov(collision.covXX(), collision.covXY(), collision.covXZ(), collision.covYY(), collision.covYZ(), collision.covZZ(), collision.chi2()); eventInfo(collision.globalIndex()); @@ -953,17 +953,17 @@ struct TableMaker { eventExtended(bc.globalBC(), collision.alias_raw(), collision.selection_raw(), bc.timestamp(), VarManager::fgValues[VarManager::kCentVZERO], collision.multTPC(), collision.multFV0A(), collision.multFV0C(), collision.multFT0A(), collision.multFT0C(), collision.multFDDA(), collision.multFDDC(), collision.multZNA(), collision.multZNC(), collision.multTracklets(), collision.multNTracksPV(), - collision.centFT0C()); + collision.centFT0C(), collision.centFT0A(), collision.centFT0M()); } else if constexpr ((TEventFillMap & VarManager::ObjTypes::CollisionMult) > 0) { eventExtended(bc.globalBC(), collision.alias_raw(), collision.selection_raw(), bc.timestamp(), VarManager::fgValues[VarManager::kCentVZERO], collision.multTPC(), collision.multFV0A(), collision.multFV0C(), collision.multFT0A(), collision.multFT0C(), collision.multFDDA(), collision.multFDDC(), collision.multZNA(), collision.multZNC(), collision.multTracklets(), collision.multNTracksPV(), - -1); + -1, -1, -1); } else if constexpr ((TEventFillMap & VarManager::ObjTypes::CollisionCent) > 0) { eventExtended(bc.globalBC(), collision.alias_raw(), collision.selection_raw(), bc.timestamp(), VarManager::fgValues[VarManager::kCentVZERO], - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, collision.centFT0C()); + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, collision.centFT0C(), collision.centFT0A(), collision.centFT0M()); } else { - eventExtended(bc.globalBC(), collision.alias_raw(), collision.selection_raw(), bc.timestamp(), VarManager::fgValues[VarManager::kCentVZERO], -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1); + eventExtended(bc.globalBC(), collision.alias_raw(), collision.selection_raw(), bc.timestamp(), VarManager::fgValues[VarManager::kCentVZERO], -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1); } eventVtxCov(collision.covXX(), collision.covXY(), collision.covXZ(), collision.covYY(), collision.covYZ(), collision.covZZ(), collision.chi2()); eventInfo(collision.globalIndex()); diff --git a/PWGDQ/TableProducer/tableMakerMC.cxx b/PWGDQ/TableProducer/tableMakerMC.cxx index e8408b3e046..1d43d196f9d 100644 --- a/PWGDQ/TableProducer/tableMakerMC.cxx +++ b/PWGDQ/TableProducer/tableMakerMC.cxx @@ -87,8 +87,8 @@ using MyMftTracks = soa::Join; using MyEvents = soa::Join; using MyEventsWithMults = soa::Join; -using MyEventsWithCent = soa::Join; -using MyEventsWithCentAndMults = soa::Join; +using MyEventsWithCent = soa::Join; +using MyEventsWithCentAndMults = soa::Join; constexpr static uint32_t gkEventFillMap = VarManager::ObjTypes::BC | VarManager::ObjTypes::Collision; constexpr static uint32_t gkEventFillMapWithMults = VarManager::ObjTypes::BC | VarManager::ObjTypes::Collision | VarManager::ObjTypes::CollisionMult; @@ -444,17 +444,17 @@ struct TableMakerMC { eventExtended(bc.globalBC(), collision.alias_raw(), collision.selection_raw(), bc.timestamp(), VarManager::fgValues[VarManager::kCentVZERO], collision.multTPC(), collision.multFV0A(), collision.multFV0C(), collision.multFT0A(), collision.multFT0C(), collision.multFDDA(), collision.multFDDC(), collision.multZNA(), collision.multZNC(), collision.multTracklets(), collision.multNTracksPV(), - collision.centFT0C()); + collision.centFT0C(), collision.centFT0A(), collision.centFT0M()); } else if constexpr ((TEventFillMap & VarManager::ObjTypes::CollisionMult) > 0) { eventExtended(bc.globalBC(), collision.alias_raw(), collision.selection_raw(), bc.timestamp(), VarManager::fgValues[VarManager::kCentVZERO], collision.multTPC(), collision.multFV0A(), collision.multFV0C(), collision.multFT0A(), collision.multFT0C(), collision.multFDDA(), collision.multFDDC(), collision.multZNA(), collision.multZNC(), collision.multTracklets(), collision.multNTracksPV(), - -1); + -1, -1, -1); } else if constexpr ((TEventFillMap & VarManager::ObjTypes::CollisionCent) > 0) { eventExtended(bc.globalBC(), collision.alias_raw(), collision.selection_raw(), bc.timestamp(), VarManager::fgValues[VarManager::kCentVZERO], - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, collision.centFT0C()); + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, collision.centFT0C(), collision.centFT0A(), collision.centFT0M()); } else { - eventExtended(bc.globalBC(), collision.alias_raw(), collision.selection_raw(), bc.timestamp(), VarManager::fgValues[VarManager::kCentVZERO], -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1); + eventExtended(bc.globalBC(), collision.alias_raw(), collision.selection_raw(), bc.timestamp(), VarManager::fgValues[VarManager::kCentVZERO], -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1); } eventVtxCov(collision.covXX(), collision.covXY(), collision.covXZ(), collision.covYY(), collision.covYZ(), collision.covZZ(), collision.chi2()); eventInfo(collision.globalIndex()); @@ -1079,17 +1079,17 @@ struct TableMakerMC { eventExtended(collision.bc().globalBC(), collision.bc().triggerMask(), 0, triggerAliases, VarManager::fgValues[VarManager::kCentVZERO], collision.multTPC(), collision.multFV0A(), collision.multFV0C(), collision.multFT0A(), collision.multFT0C(), collision.multFDDA(), collision.multFDDC(), collision.multZNA(), collision.multZNC(), collision.multTracklets(), collision.multNTracksPV(), - collision.centFT0C()); + collision.centFT0C(), collision.centFT0A(), collision.centFT0M()); } else if constexpr ((TEventFillMap & VarManager::ObjTypes::CollisionMult) > 0) { eventExtended(bc.globalBC(), bc.triggerMask(), bc.timestamp(), triggerAliases, VarManager::fgValues[VarManager::kCentVZERO], collision.multTPC(), collision.multFV0A(), collision.multFV0C(), collision.multFT0A(), collision.multFT0C(), collision.multFDDA(), collision.multFDDC(), collision.multZNA(), collision.multZNC(), collision.multTracklets(), collision.multNTracksPV(), - -1); + -1, -1, -1); } else if constexpr ((TEventFillMap & VarManager::ObjTypes::CollisionCent) > 0) { eventExtended(bc.globalBC(), bc.triggerMask(), bc.timestamp(), triggerAliases, VarManager::fgValues[VarManager::kCentVZERO], - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, collision.centFT0C()); + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, collision.centFT0C(), collision.centFT0A(), collision.centFT0M()); } else { - eventExtended(bc.globalBC(), bc.triggerMask(), bc.timestamp(), triggerAliases, VarManager::fgValues[VarManager::kCentVZERO], -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1); + eventExtended(bc.globalBC(), bc.triggerMask(), bc.timestamp(), triggerAliases, VarManager::fgValues[VarManager::kCentVZERO], -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1); } eventVtxCov(collision.covXX(), collision.covXY(), collision.covXZ(), collision.covYY(), collision.covYZ(), collision.covZZ(), collision.chi2()); eventInfo(collision.globalIndex()); diff --git a/PWGDQ/TableProducer/tableMakerMC_withAssoc.cxx b/PWGDQ/TableProducer/tableMakerMC_withAssoc.cxx index 484ec4873d5..7dc49516e8a 100644 --- a/PWGDQ/TableProducer/tableMakerMC_withAssoc.cxx +++ b/PWGDQ/TableProducer/tableMakerMC_withAssoc.cxx @@ -90,8 +90,8 @@ using MyMuonsRealignWithCov = soa::Join; using MyEventsWithMults = soa::Join; using MyEventsWithMultsAndRapidityGapFilter = soa::Join; -using MyEventsWithCent = soa::Join; -using MyEventsWithCentAndMults = soa::Join; +using MyEventsWithCent = soa::Join; +using MyEventsWithCentAndMults = soa::Join; using MFTTrackLabeled = soa::Join; // Declare bit maps containing information on the table joins content (used as argument in templated functions) @@ -547,6 +547,8 @@ struct TableMakerMC { int multTracklets = -1.0; int multTracksPV = -1.0; float centFT0C = -1.0; + float centFT0A = -1.0; + float centFT0M = -1.0; // Loop over collisions for (const auto& collision : collisions) { @@ -641,9 +643,11 @@ struct TableMakerMC { } if constexpr ((TEventFillMap & VarManager::ObjTypes::CollisionCent) > 0) { centFT0C = collision.centFT0C(); + centFT0A = collision.centFT0A(); + centFT0M = collision.centFT0M(); } eventExtended(bc.globalBC(), collision.alias_raw(), collision.selection_raw(), bc.timestamp(), VarManager::fgValues[VarManager::kCentVZERO], - multTPC, multFV0A, multFV0C, multFT0A, multFT0C, multFDDA, multFDDC, multZNA, multZNC, multTracklets, multTracksPV, centFT0C); + multTPC, multFV0A, multFV0C, multFT0A, multFT0C, multFDDA, multFDDC, multZNA, multZNC, multTracklets, multTracksPV, centFT0C, centFT0A, centFT0M); eventVtxCov(collision.covXX(), collision.covXY(), collision.covXZ(), collision.covYY(), collision.covYZ(), collision.covZZ(), collision.chi2()); eventMClabels(collision.mcCollisionId(), collision.mcMask()); eventInfo(collision.globalIndex()); diff --git a/PWGDQ/TableProducer/tableMaker_withAssoc.cxx b/PWGDQ/TableProducer/tableMaker_withAssoc.cxx index 9c269de06d3..3b3d4c4e0af 100644 --- a/PWGDQ/TableProducer/tableMaker_withAssoc.cxx +++ b/PWGDQ/TableProducer/tableMaker_withAssoc.cxx @@ -104,8 +104,8 @@ using MyEventsWithMults = soa::Join; using MyEventsWithFilter = soa::Join; using MyEventsWithMultsAndFilter = soa::Join; using MyEventsWithMultsAndRapidityGapFilter = soa::Join; -using MyEventsWithCent = soa::Join; -using MyEventsWithCentAndMults = soa::Join; +using MyEventsWithCent = soa::Join; +using MyEventsWithCentAndMults = soa::Join; using MyEventsWithMultsExtra = soa::Join; using MyMuons = soa::Join; using MyMuonsWithCov = soa::Join; @@ -770,6 +770,8 @@ struct TableMaker { int multTracklets = -1.0; int multTracksPV = -1.0; float centFT0C = -1.0; + float centFT0A = -1.0; + float centFT0M = -1.0; for (const auto& collision : collisions) { @@ -898,9 +900,11 @@ struct TableMaker { } if constexpr ((TEventFillMap & VarManager::ObjTypes::CollisionCent) > 0) { centFT0C = collision.centFT0C(); + centFT0A = collision.centFT0A(); + centFT0M = collision.centFT0M(); } eventExtended(bc.globalBC(), collision.alias_raw(), collision.selection_raw(), bc.timestamp(), VarManager::fgValues[VarManager::kCentVZERO], - multTPC, multFV0A, multFV0C, multFT0A, multFT0C, multFDDA, multFDDC, multZNA, multZNC, multTracklets, multTracksPV, centFT0C); + multTPC, multFV0A, multFV0C, multFT0A, multFT0C, multFDDA, multFDDC, multZNA, multZNC, multTracklets, multTracksPV, centFT0C, centFT0A, centFT0M); eventVtxCov(collision.covXX(), collision.covXY(), collision.covXZ(), collision.covYY(), collision.covYZ(), collision.covZZ(), collision.chi2()); eventInfo(collision.globalIndex()); if constexpr ((TEventFillMap & VarManager::ObjTypes::Zdc) > 0) { diff --git a/PWGDQ/Tasks/CMakeLists.txt b/PWGDQ/Tasks/CMakeLists.txt index a10d6bb117d..ad1dd3d1d97 100644 --- a/PWGDQ/Tasks/CMakeLists.txt +++ b/PWGDQ/Tasks/CMakeLists.txt @@ -118,3 +118,8 @@ o2physics_add_dpl_workflow(model-converter-mult-pv SOURCES ModelConverterMultPv.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::PWGDQCore COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(model-converter-event-extended + SOURCES ModelConverterEventExtended.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::PWGDQCore + COMPONENT_NAME Analysis) \ No newline at end of file diff --git a/PWGDQ/Tasks/ModelConverterEventExtended.cxx b/PWGDQ/Tasks/ModelConverterEventExtended.cxx new file mode 100644 index 00000000000..ec0a6a0c4be --- /dev/null +++ b/PWGDQ/Tasks/ModelConverterEventExtended.cxx @@ -0,0 +1,53 @@ +// 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. +// +// Contact: iarsene@cern.ch, i.c.arsene@fys.uio.no +// +// Task used to convert the data model from the old format to the new format. To avoid +// the conflict with the old data model. + +// other includes +#include "PWGDQ/DataModel/ReducedInfoTables.h" + +#include "DataFormatsParameters/GRPObject.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" + +#include +#include +#include + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::aod; + +struct eventExtendedConverter000_001 { + Produces eventExtended_001; + + void process(aod::ReducedEventsExtended_000 const& events) + { + for (const auto& event : events) { + eventExtended_001(event.globalBC(), event.alias_raw(), event.selection_raw(), event.timestamp(), event.centRun2V0M(), + event.multTPC(), event.multFV0A(), event.multFV0C(), event.multFT0A(), event.multFT0C(), + event.multFDDA(), event.multFDDC(), event.multZNA(), event.multZNC(), event.multTracklets(), event.multNTracksPV(), + event.centFT0C(), -1.0f, -1.0f); + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +} diff --git a/PWGDQ/Tasks/dqFlow.cxx b/PWGDQ/Tasks/dqFlow.cxx index cdbee28a8a0..52e3ca8c29c 100644 --- a/PWGDQ/Tasks/dqFlow.cxx +++ b/PWGDQ/Tasks/dqFlow.cxx @@ -66,7 +66,7 @@ using MyBcs = soa::Join; using MyEvents = soa::Join; using MyEventsWithCent = soa::Join; -using MyEventsWithCentRun3 = soa::Join; +using MyEventsWithCentRun3 = soa::Join; // using MyEventsWithCentQvectRun3 = soa::Join; // using MyEventsWithCentQvectRun3 = soa::Join; using MyEventsWithCentQvectRun3 = soa::Join; From 9197931449a0fe1c60a2ef0f39724372ff5f7b44 Mon Sep 17 00:00:00 2001 From: yuanzhe <90246048+wang-yuanzhe@users.noreply.github.com> Date: Tue, 17 Jun 2025 11:27:07 +0200 Subject: [PATCH 102/871] [PWGLF] Avoid unexpected behavior while no matched collisions (#11610) --- PWGLF/Utils/svPoolCreator.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/PWGLF/Utils/svPoolCreator.h b/PWGLF/Utils/svPoolCreator.h index 25da298fe34..c0b32c2574e 100644 --- a/PWGLF/Utils/svPoolCreator.h +++ b/PWGLF/Utils/svPoolCreator.h @@ -129,6 +129,10 @@ class svPoolCreator } firstBC++; } + if (firstCollIdx == -1) { + return; + } + // now loop over all the collisions to make the pool for (int i = firstCollIdx; i < collisions.size(); i++) { const auto& collision = collisions.rawIteratorAt(i); From ca874804cfb0b9ca00b4a070fe2f27d0715652f3 Mon Sep 17 00:00:00 2001 From: alcaliva <32872606+alcaliva@users.noreply.github.com> Date: Tue, 17 Jun 2025 11:53:15 +0200 Subject: [PATCH 103/871] [PWGJE] Fix: make doRhoAreaSub take const reference to avoid unnecesary copy (#11618) --- PWGJE/Core/JetBkgSubUtils.cxx | 2 +- PWGJE/Core/JetBkgSubUtils.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/PWGJE/Core/JetBkgSubUtils.cxx b/PWGJE/Core/JetBkgSubUtils.cxx index fe4a0720347..4cc6d202130 100644 --- a/PWGJE/Core/JetBkgSubUtils.cxx +++ b/PWGJE/Core/JetBkgSubUtils.cxx @@ -160,7 +160,7 @@ std::tuple JetBkgSubUtils::estimateRhoPerpCone(const std::vector return std::make_tuple(perpPtDensity, perpMdDensity); } -fastjet::PseudoJet JetBkgSubUtils::doRhoAreaSub(fastjet::PseudoJet& jet, double rhoParam, double rhoMParam) +fastjet::PseudoJet JetBkgSubUtils::doRhoAreaSub(const fastjet::PseudoJet& jet, double rhoParam, double rhoMParam) { fastjet::Subtractor sub = fastjet::Subtractor(rhoParam, rhoMParam); diff --git a/PWGJE/Core/JetBkgSubUtils.h b/PWGJE/Core/JetBkgSubUtils.h index f3c8fcc987a..81a132c9af9 100644 --- a/PWGJE/Core/JetBkgSubUtils.h +++ b/PWGJE/Core/JetBkgSubUtils.h @@ -79,7 +79,7 @@ class JetBkgSubUtils /// @param rhoParam the underlying evvent density vs pT (to be set) /// @param rhoParam the underlying evvent density vs jet mass (to be set) /// @return jet, background subtracted jet - fastjet::PseudoJet doRhoAreaSub(fastjet::PseudoJet& jet, double rhoParam, double rhoMParam); + fastjet::PseudoJet doRhoAreaSub(const fastjet::PseudoJet& jet, double rhoParam, double rhoMParam); /// @brief method that subtracts the background from the input particles using the event-wise cosntituent subtractor /// @param inputParticles (all the tracks/clusters/particles in the event) From cdd245697aa80af6c4888156d5387eb409461c32 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Tue, 17 Jun 2025 12:00:24 +0200 Subject: [PATCH 104/871] [Infrastructure] Support non-flat KFParticle headers distribution (#11633) --- dependencies/FindKFParticle.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/FindKFParticle.cmake b/dependencies/FindKFParticle.cmake index 7c789c3f937..6821b601c66 100644 --- a/dependencies/FindKFParticle.cmake +++ b/dependencies/FindKFParticle.cmake @@ -17,7 +17,7 @@ #endif() find_path(KFPARTICLE_INCLUDE_DIR KFParticle.h - PATH_SUFFIXES "include" + PATH_SUFFIXES "include" "include/KFParticle" HINTS "$ENV{KFPARTICLE_ROOT}") find_library(KFPARTICLE_LIBPATH "KFParticle" PATH_SUFFIXES "lib" From 8ea52e4998f7298dfd21b9535e35f7d89b562fa7 Mon Sep 17 00:00:00 2001 From: SCHOTTER Romain <47983209+romainschotter@users.noreply.github.com> Date: Tue, 17 Jun 2025 13:19:53 +0200 Subject: [PATCH 105/871] [PWGLF] Fix preselection bitmap check (#11642) --- .../Strangeness/strangenessbuilder.cxx | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/PWGLF/TableProducer/Strangeness/strangenessbuilder.cxx b/PWGLF/TableProducer/Strangeness/strangenessbuilder.cxx index c38c792f5e1..800b1105732 100644 --- a/PWGLF/TableProducer/Strangeness/strangenessbuilder.cxx +++ b/PWGLF/TableProducer/Strangeness/strangenessbuilder.cxx @@ -196,12 +196,12 @@ struct StrangenessBuilder { kCascFoundTags, nTables }; - enum V0PreSelection : uint8_t { selGamma = static_cast(1) << static_cast(0), + enum V0PreSelection : uint8_t { selGamma = 0, selK0Short, selLambda, selAntiLambda }; - enum CascPreSelection : uint8_t { selXiMinus = static_cast(1) << static_cast(0), + enum CascPreSelection : uint8_t { selXiMinus = 0, selXiPlus, selOmegaMinus, selOmegaPlus }; @@ -716,11 +716,6 @@ struct StrangenessBuilder { straHelper.cascadeselections.maxDaughterEta = cascadeBuilderOpts.maxDaughterEta; } - bool verifyMask(uint8_t bitmap, uint8_t mask) - { - return (bitmap & mask) == mask; - } - // for sorting template std::vector sort_indices(const std::vector& v, bool doSorting = false) @@ -1485,10 +1480,7 @@ struct StrangenessBuilder { histos.fill(HIST("hPreselectionV0s"), maskV0Preselection); - if (!verifyMask(maskV0Preselection, selGamma) && - !verifyMask(maskV0Preselection, selK0Short) && - !verifyMask(maskV0Preselection, selLambda) && - !verifyMask(maskV0Preselection, selAntiLambda)) { + if (maskV0Preselection == 0) { products.v0dataLink(-1, -1); continue; } @@ -2048,10 +2040,7 @@ struct StrangenessBuilder { histos.fill(HIST("hPreselectionCascades"), maskCascadePreselection); - if (!verifyMask(maskCascadePreselection, selXiMinus) && - !verifyMask(maskCascadePreselection, selXiPlus) && - !verifyMask(maskCascadePreselection, selOmegaMinus) && - !verifyMask(maskCascadePreselection, selOmegaPlus)) { + if (maskCascadePreselection == 0) { products.cascdataLink(-1); interlinks.cascadeToCascCores.push_back(-1); continue; From 121ef5b3559b79334fd9f686cf5df165f84394a8 Mon Sep 17 00:00:00 2001 From: Rrantu <156880782+Rrantu@users.noreply.github.com> Date: Tue, 17 Jun 2025 20:09:30 +0800 Subject: [PATCH 106/871] [PWGHF] taskFlowCharmHadrons: Fix filter condition (#11641) --- PWGHF/D2H/Tasks/taskFlowCharmHadrons.cxx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/PWGHF/D2H/Tasks/taskFlowCharmHadrons.cxx b/PWGHF/D2H/Tasks/taskFlowCharmHadrons.cxx index 03e475bc7ed..6a090bfd2ed 100644 --- a/PWGHF/D2H/Tasks/taskFlowCharmHadrons.cxx +++ b/PWGHF/D2H/Tasks/taskFlowCharmHadrons.cxx @@ -102,7 +102,7 @@ struct HfTaskFlowCharmHadrons { Filter filterSelectD0Candidates = aod::hf_sel_candidate_d0::isSelD0 >= selectionFlag || aod::hf_sel_candidate_d0::isSelD0bar >= selectionFlag; Filter filterSelectLcCandidates = aod::hf_sel_candidate_lc::isSelLcToPKPi >= selectionFlag || aod::hf_sel_candidate_lc::isSelLcToPiKP >= selectionFlag; Filter filterSelectXicCandidates = aod::hf_sel_candidate_xic::isSelXicToPKPi >= selectionFlag || aod::hf_sel_candidate_xic::isSelXicToPiKP >= selectionFlag; - Filter filterSelectXic0Candidates = aod::hf_sel_toxipi::resultSelections >= selectionFlag; + Filter filterSelectXic0Candidates = aod::hf_sel_toxipi::resultSelections == true; Partition selectedDsToKKPi = aod::hf_sel_candidate_ds::isSelDsToKKPi >= selectionFlag; Partition selectedDsToPiKK = aod::hf_sel_candidate_ds::isSelDsToPiKK >= selectionFlag; @@ -120,8 +120,8 @@ struct HfTaskFlowCharmHadrons { Partition selectedXicToPiKP = aod::hf_sel_candidate_xic::isSelXicToPiKP >= selectionFlag; Partition selectedXicToPKPiWMl = aod::hf_sel_candidate_xic::isSelXicToPKPi >= selectionFlag; Partition selectedXicToPiKPWMl = aod::hf_sel_candidate_xic::isSelXicToPiKP >= selectionFlag; - Partition selectedXic0 = aod::hf_sel_toxipi::resultSelections >= selectionFlag; - Partition selectedXic0WMl = aod::hf_sel_toxipi::resultSelections >= selectionFlag; + Partition selectedXic0 = aod::hf_sel_toxipi::resultSelections == true; + Partition selectedXic0WMl = aod::hf_sel_toxipi::resultSelections == true; ConfigurableAxis thnConfigAxisInvMass{"thnConfigAxisInvMass", {100, 1.78, 2.05}, ""}; ConfigurableAxis thnConfigAxisPt{"thnConfigAxisPt", {10, 0., 10.}, ""}; From a0fef3d7c282fa45747ad20b732bfd95ffe46f7c Mon Sep 17 00:00:00 2001 From: Luca Barioglio Date: Tue, 17 Jun 2025 15:01:34 +0200 Subject: [PATCH 107/871] [PWGLF] Adapt flowQC to higher harmonics for updated ep-tables (#11646) --- PWGLF/TableProducer/QC/flowQC.cxx | 80 +++++++++++++++---------------- 1 file changed, 39 insertions(+), 41 deletions(-) diff --git a/PWGLF/TableProducer/QC/flowQC.cxx b/PWGLF/TableProducer/QC/flowQC.cxx index 1e32b954120..9a120e1afe8 100644 --- a/PWGLF/TableProducer/QC/flowQC.cxx +++ b/PWGLF/TableProducer/QC/flowQC.cxx @@ -19,34 +19,32 @@ // o2-analysis-multiplicity-table, o2-analysis-ft0-corrected-table, o2-analysis-track-propagation, // o2-analysis-trackselection, o2-analysis-qvector-table, o2-analysis-lf-flow-qc -#include - -#include "Math/Vector4D.h" - -#include "CCDB/BasicCCDBManager.h" +#include "PWGLF/DataModel/EPCalibrationTables.h" +#include "Common/Core/EventPlaneHelper.h" #include "Common/Core/trackUtilities.h" #include "Common/DataModel/Centrality.h" -#include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/EventSelection.h" -#include "Common/Core/EventPlaneHelper.h" -#include "PWGLF/DataModel/EPCalibrationTables.h" +#include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/Qvectors.h" +#include "CCDB/BasicCCDBManager.h" #include "DataFormatsParameters/GRPMagField.h" #include "DataFormatsParameters/GRPObject.h" #include "DataFormatsTPC/BetheBlochAleph.h" #include "DetectorsBase/GeometryManager.h" #include "DetectorsBase/Propagator.h" - +#include "Framework/ASoAHelpers.h" #include "Framework/AnalysisDataModel.h" #include "Framework/AnalysisTask.h" -#include "Framework/ASoAHelpers.h" #include "Framework/HistogramRegistry.h" #include "Framework/runDataProcessing.h" +#include "Math/Vector4D.h" #include "TRandom3.h" +#include + using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; @@ -111,7 +109,7 @@ struct flowQC { int mRunNumber = 0; float mBz = 0.f; - Configurable cfgHarmonics{"cfgHarmonics", 2, "Harmonics for flow analysis"}; + Configurable cfgHarmonic{"cfgHarmonic", 2.f, "Harmonics for flow analysis"}; // Flow analysis using CollWithEPandQvec = soa::Joinadd(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}_{%d}^{%s} #upoint #vec{Q}_{%d}^{%s}", cfgHarmonics.value, qVecDetectorNames[iQvecDet].c_str(), cfgHarmonics.value, qVecDetectorNames[jQvecDet].c_str()); + auto spLabel = Form("#vec{Q}_{%.0f}^{%s} #upoint #vec{Q}_{%.0f}^{%s}", cfgHarmonic.value, qVecDetectorNames[iQvecDet].c_str(), 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}_{%d}^{%s} #upoint #vec{Q}_{%d}^{%s}}{||#vec{Q}_{%d}^{%s}|| ||#vec{Q}_{%d}^{%s}||}", cfgHarmonics.value, qVecDetectorNames[iQvecDet].c_str(), cfgHarmonics.value, qVecDetectorNames[jQvecDet].c_str(), cfgHarmonics.value, qVecDetectorNames[iQvecDet].c_str(), cfgHarmonics.value, qVecDetectorNames[jQvecDet].c_str()); + 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()); 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}}); } @@ -263,52 +261,52 @@ struct flowQC { // EP method float QmodFT0A_EP = collision.qFT0A(); float psiFT0A_EP = collision.psiFT0A(); - float QxFT0A_EP = QmodFT0A_EP * std::cos(2 * psiFT0A_EP); - float QyFT0A_EP = QmodFT0A_EP * std::sin(2 * psiFT0A_EP); + 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 psiFT0C_EP = collision.psiFT0C(); - float QxFT0C_EP = QmodFT0C_EP * std::cos(2 * psiFT0C_EP); - float QyFT0C_EP = QmodFT0C_EP * std::sin(2 * psiFT0C_EP); + 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 psiTPCl_EP = collision.psiTPCL(); - float QxTPCl_EP = QmodTPCl_EP * std::cos(2 * psiTPCl_EP); - float QyTPCl_EP = QmodTPCl_EP * std::sin(2 * psiTPCl_EP); + 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 psiTPCr_EP = collision.psiTPCR(); - float QxTPCr_EP = QmodTPCr_EP * std::cos(2 * psiTPCr_EP); - float QyTPCr_EP = QmodTPCr_EP * std::sin(2 * psiTPCr_EP); + 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 psiTPC_EP = collision.psiTPC(); - float QxTPC_EP = QmodTPC_EP * std::cos(2 * psiTPC_EP); - float QyTPC_EP = QmodTPC_EP * std::sin(2 * psiTPC_EP); + 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()[cfgHarmonics - 2]; - float QyFT0A_Qvec = collision.qvecFT0AImVec()[cfgHarmonics - 2]; + float QxFT0A_Qvec = collision.qvecFT0AReVec()[cfgHarmonic.value - 2]; + float QyFT0A_Qvec = collision.qvecFT0AImVec()[cfgHarmonic.value - 2]; float QmodFT0A_Qvec = std::hypot(QxFT0A_Qvec, QyFT0A_Qvec); float psiFT0A_Qvec = computeEventPlane(QyFT0A_Qvec, QxFT0A_Qvec); - float QxFT0C_Qvec = collision.qvecFT0CReVec()[cfgHarmonics - 2]; - float QyFT0C_Qvec = collision.qvecFT0CImVec()[cfgHarmonics - 2]; + float QxFT0C_Qvec = collision.qvecFT0CReVec()[cfgHarmonic.value - 2]; + float QyFT0C_Qvec = collision.qvecFT0CImVec()[cfgHarmonic.value - 2]; float QmodFT0C_Qvec = std::hypot(QxFT0C_Qvec, QyFT0C_Qvec); float psiFT0C_Qvec = computeEventPlane(QyFT0C_Qvec, QxFT0C_Qvec); - float QxTPCl_Qvec = collision.qvecTPCnegReVec()[cfgHarmonics - 2]; - float QyTPCl_Qvec = collision.qvecTPCnegImVec()[cfgHarmonics - 2]; + float QxTPCl_Qvec = collision.qvecTPCnegReVec()[cfgHarmonic.value - 2]; + float QyTPCl_Qvec = collision.qvecTPCnegImVec()[cfgHarmonic.value - 2]; float QmodTPCl_Qvec = std::hypot(QxTPCl_Qvec, QyTPCl_Qvec); float psiTPCl_Qvec = computeEventPlane(QyTPCl_Qvec, QxTPCl_Qvec); - float QxTPCr_Qvec = collision.qvecTPCposReVec()[cfgHarmonics - 2]; - float QyTPCr_Qvec = collision.qvecTPCposImVec()[cfgHarmonics - 2]; + float QxTPCr_Qvec = collision.qvecTPCposReVec()[cfgHarmonic.value - 2]; + float QyTPCr_Qvec = collision.qvecTPCposImVec()[cfgHarmonic.value - 2]; float QmodTPCr_Qvec = std::hypot(QxTPCr_Qvec, QyTPCr_Qvec); float psiTPCr_Qvec = computeEventPlane(QyTPCr_Qvec, QxTPCr_Qvec); - float QxTPC_Qvec = collision.qvecTPCallReVec()[cfgHarmonics - 2]; - float QyTPC_Qvec = collision.qvecTPCallImVec()[cfgHarmonics - 2]; + float QxTPC_Qvec = collision.qvecTPCallReVec()[cfgHarmonic.value - 2]; + float QyTPC_Qvec = collision.qvecTPCallImVec()[cfgHarmonic.value - 2]; float QmodTPC_Qvec = std::hypot(QxTPC_Qvec, QyTPC_Qvec); float psiTPC_Qvec = computeEventPlane(QyTPC_Qvec, QxTPC_Qvec); @@ -340,7 +338,7 @@ struct flowQC { } for (int iQvecDet = 0; iQvecDet < qVecDetectors::kNqVecDetectors; iQvecDet++) { hPsiComp[iQvecDet]->Fill(centrality, vec_Qpsi[methods::kEP][iQvecDet] - vec_Qpsi[methods::kQvec][iQvecDet]); - hCosPsiComp[iQvecDet]->Fill(centrality, std::cos(2 * (vec_Qpsi[methods::kEP][iQvecDet] - vec_Qpsi[methods::kQvec][iQvecDet]))); + hCosPsiComp[iQvecDet]->Fill(centrality, std::cos(cfgHarmonic.value * (vec_Qpsi[methods::kEP][iQvecDet] - vec_Qpsi[methods::kQvec][iQvecDet]))); } } }; From d2d3acdf11545a1f398ffd043095590d8e43ce33 Mon Sep 17 00:00:00 2001 From: Zhenjun Xiong <108917659+zjxiongOvO@users.noreply.github.com> Date: Tue, 17 Jun 2025 15:09:25 +0200 Subject: [PATCH 108/871] [PWGDQ] Update tableReader_withAssoc.cxx (#11644) --- PWGDQ/Tasks/tableReader_withAssoc.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/PWGDQ/Tasks/tableReader_withAssoc.cxx b/PWGDQ/Tasks/tableReader_withAssoc.cxx index 4fcb823cce5..410beb5337a 100644 --- a/PWGDQ/Tasks/tableReader_withAssoc.cxx +++ b/PWGDQ/Tasks/tableReader_withAssoc.cxx @@ -3775,8 +3775,8 @@ struct AnalysisDileptonTrackTrack { // do nothing } - PROCESS_SWITCH(AnalysisDileptonTrackTrack, processJpsiPiPi, "Run barrel pairing of J/psi with pion candidate", true); - PROCESS_SWITCH(AnalysisDileptonTrackTrack, processDummy, "Dummy function", false); + PROCESS_SWITCH(AnalysisDileptonTrackTrack, processJpsiPiPi, "Run barrel pairing of J/psi with pion candidate", false); + PROCESS_SWITCH(AnalysisDileptonTrackTrack, processDummy, "Dummy function", true); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) From 2c33ec04664a403c3c7b2035155f47c186430331 Mon Sep 17 00:00:00 2001 From: smaff92 <33285879+smaff92@users.noreply.github.com> Date: Tue, 17 Jun 2025 22:39:46 +0900 Subject: [PATCH 109/871] =?UTF-8?q?[PWGJE]=20Adding=20MC=20weights=20for?= =?UTF-8?q?=20JEJE=20injections,=20and=20adding=20mask=20for=20s=E2=80=A6?= =?UTF-8?q?=20(#11643)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: ALICE Action Bot --- PWGJE/Tasks/statPromptPhoton.cxx | 144 ++++++++++++++----------------- 1 file changed, 67 insertions(+), 77 deletions(-) diff --git a/PWGJE/Tasks/statPromptPhoton.cxx b/PWGJE/Tasks/statPromptPhoton.cxx index 80ebe23550d..75fdb2ca5bf 100644 --- a/PWGJE/Tasks/statPromptPhoton.cxx +++ b/PWGJE/Tasks/statPromptPhoton.cxx @@ -13,30 +13,43 @@ /// \brief Reconstruction of Phi yield through track-track Minv correlations for resonance hadrochemistry analysis. /// /// -/// \author Adrian Fereydon Nassirpour +/// \author Adrian Fereydon Nassirpour +#include "PWGJE/Core/FastJetUtilities.h" #include "PWGJE/Core/JetDerivedDataUtilities.h" #include "PWGJE/DataModel/EMCALClusters.h" -#include "PWGJE/DataModel/JetReducedData.h" +#include "PWGJE/DataModel/Jet.h" +#include "Common/Core/RecoDecay.h" +#include "Common/Core/TrackSelection.h" +#include "Common/Core/TrackSelectionDefaults.h" +#include "Common/Core/trackUtilities.h" #include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/PIDResponse.h" #include "Common/DataModel/TrackSelectionTables.h" +#include "CommonConstants/PhysicsConstants.h" +#include "CommonDataFormat/InteractionRecord.h" +#include "DataFormatsEMCAL/AnalysisCluster.h" +#include "DataFormatsEMCAL/Cell.h" +#include "DataFormatsEMCAL/Constants.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "DataFormatsParameters/GRPObject.h" +#include "DetectorsBase/Propagator.h" +#include "EMCALBase/Geometry.h" +#include "EMCALCalib/BadChannelMap.h" #include "Framework/ASoA.h" #include "Framework/AnalysisDataModel.h" #include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" -#include -#include -#include -#include -#include +#include "Framework/runDataProcessing.h" +#include "ReconstructionDataFormats/Track.h" +#include #include -#include #include -#include #include #include #include @@ -47,6 +60,7 @@ using namespace o2::framework; using namespace o2::framework::expressions; struct statPromptPhoton { + SliceCache cache; HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; Configurable cfgMaxDCArToPVcut{"cfgMaxDCArToPVcut", 0.5, "Track DCAr cut to PV Maximum"}; @@ -85,8 +99,12 @@ struct statPromptPhoton { Configurable cfgGenHistograms{"cfgGenHistograms", false, "Enables Generated histograms"}; Configurable cfgRecHistograms{"cfgRecHistograms", false, "Enables Reconstructed histograms"}; Configurable cfgDataHistograms{"cfgDataHistograms", false, "Enables Data histograms"}; + Configurable cfgSkimmedTrigger{"cfgSkimmedTrigger", false, "Enables trigger for skimmied datasets (2023 onwards)"}; + Configurable cfgTriggerMasks{"cfgTriggerMasks", "", "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"}; Configurable cfgDebug{"cfgDebug", false, "Enables debug information for local running"}; + int trackFilter = -1; + std::vector triggerMaskBits; // INIT void init(InitContext const&) @@ -94,6 +112,7 @@ struct statPromptPhoton { std::vector ptBinning = {0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.5, 3.0, 4.0, 5.0, 6.0, 8.0, 12.0, 16.0, 20.0, 25.0, 30.0, 40.0, 50.0, 75.0, 100.0, 150.0, 200.0, 300.0, 500.0}; AxisSpec pthadAxis = {ptBinning, "#it{p}_{T}^{had sum} [GeV/c]"}; + triggerMaskBits = jetderiveddatautilities::initialiseTriggerMaskBits(cfgTriggerMasks); if (cfgJETracks) { trackFilter = jetderiveddatautilities::initialiseTrackSelection(static_cast(cfgTrackFilter)); } @@ -235,8 +254,11 @@ struct statPromptPhoton { using jMCClusters = o2::soa::Join; using jClusters = o2::soa::Join; - using jselectedCollisions = soa::Join; + using jselectedCollisions = soa::Join; + using jselectedDataCollisions = soa::Join; + // using jselectedDataCollisions = soa::Join; using jfilteredCollisions = soa::Filtered; + using jfilteredDataCollisions = soa::Filtered; using jfilteredMCClusters = soa::Filtered; using jfilteredClusters = soa::Filtered; @@ -588,7 +610,7 @@ struct statPromptPhoton { PresliceUnsorted EMCTrackPerTrack = aod::jemctrack::trackId; int nEventsRecMC_JE = 0; - void processMCRec_JE(jfilteredCollisions::iterator const& collision, jfilteredMCClusters const& mcclusters, jTrackCandidates const& tracks, soa::Join const&, TrackCandidates const&, aod::JMcParticles const&, BcCandidates const&, jEMCtracks const& emctracks) + void processMCRec_JE(jfilteredCollisions::iterator const& collision, jfilteredMCClusters const& mcclusters, jTrackCandidates const& tracks, soa::Join const&, TrackCandidates const&, aod::JMcParticles const&, BcCandidates const&, jEMCtracks const& emctracks, aod::JetMcCollisions const&) { nEventsRecMC_JE++; @@ -613,6 +635,19 @@ struct statPromptPhoton { } histos.fill(HIST("REC_nEvents"), 2.5); + if (cfgSkimmedTrigger) { + if (!jetderiveddatautilities::selectTrigger(collision, triggerMaskBits)) { + return; + } + } // JE Software Triggers + + histos.fill(HIST("REC_nEvents"), 3.5); + + double weight = 1; + if (collision.has_mcCollision()) { + weight = collision.mcCollision().weight(); + } + bool noTrk = true; for (auto& track : tracks) { if (cfgJETracks) { @@ -828,9 +863,9 @@ struct statPromptPhoton { histos.fill(HIST("REC_Cluster_QA"), 4.5); clustertrigger = true; double pthadsum = GetPtHadSum(tracks, mccluster, cfgMinR, cfgMaxR, false, false, true); - histos.fill(HIST("REC_Trigger_V_PtHadSum_Photon"), mccluster.energy(), pthadsum); - histos.fill(HIST("REC_PtHadSum_Photon"), pthadsum); - histos.fill(HIST("REC_Trigger_Energy"), mccluster.energy()); + histos.fill(HIST("REC_Trigger_V_PtHadSum_Photon"), mccluster.energy(), pthadsum, weight); + histos.fill(HIST("REC_PtHadSum_Photon"), pthadsum, weight); + histos.fill(HIST("REC_Trigger_Energy"), mccluster.energy(), weight); } auto ClusterParticles = mccluster.mcParticles_as(); @@ -839,11 +874,6 @@ struct statPromptPhoton { bool goodgentrigger = true; double chPe = 0; for (auto& clusterparticle : ClusterParticles) { - // double etaP = clusterparticle.eta(); - // double etaC = mccluster.eta(); - // double phiP = clusterparticle.phi(); - // double phiC = mccluster.phi(); - // double ptP = clusterparticle.pt(); int cindex = clusterparticle.globalIndex(); double pdgcode = fabs(clusterparticle.pdgCode()); if (!clusterparticle.isPhysicalPrimary()) { @@ -884,8 +914,6 @@ struct statPromptPhoton { histos.fill(HIST("REC_Cluster_ParticleWITHtrack_Phi"), clusterparticle.phi()); histos.fill(HIST("REC_Cluster_ParticleWITHtrack_Eta"), clusterparticle.eta()); histos.fill(HIST("REC_Cluster_ParticleWITHtrack_Pt_Phi"), clusterparticle.pt(), clusterparticle.phi()); - // if (phiPrimeP > (0.12/ptP + TMath::Pi()/18. + 0.035) || - // phiPrimeP < (0.1/ptP/ptP + TMath::Pi()/18. - 0.025) ) { histos.fill(HIST("REC_Cluster_ParticleWITHtrack_Pt_PhiPrime"), ptP, phiPrimeP); if (photontrigger) { histos.fill(HIST("REC_Impurity_ParticleWITHtrack_Pt_PhiPrime"), ptP, phiPrimeP); @@ -904,8 +932,6 @@ struct statPromptPhoton { histos.fill(HIST("REC_Cluster_ParticleWITHOUTtrack_Phi"), clusterparticle.phi()); histos.fill(HIST("REC_Cluster_ParticleWITHOUTtrack_Eta"), clusterparticle.eta()); histos.fill(HIST("REC_Cluster_ParticleWITHOUTtrack_Pt_Phi"), clusterparticle.pt(), clusterparticle.phi()); - // if (phiPrimeP > (0.12/ptP + TMath::Pi()/18. + 0.035) || - // phiPrimeP < (0.1/ptP/ptP + TMath::Pi()/18. - 0.025) ) { histos.fill(HIST("REC_Cluster_ParticleWITHOUTtrack_Pt_PhiPrime"), ptP, phiPrimeP); if (photontrigger) { histos.fill(HIST("REC_Impurity_ParticleWITHOUTtrack_Pt_PhiPrime"), ptP, phiPrimeP); @@ -964,12 +990,12 @@ struct statPromptPhoton { std::cout << "Photon mom 2: " << mom2 << std::endl; } if (std::abs(clusterparticle.getGenStatusCode()) > 19 && std::abs(clusterparticle.getGenStatusCode()) < 90) { - histos.fill(HIST("REC_True_Prompt_Trigger_Energy"), clusterparticle.e()); + histos.fill(HIST("REC_True_Prompt_Trigger_Energy"), clusterparticle.e(), weight); TLorentzVector lRealPhoton; lRealPhoton.SetPxPyPzE(clusterparticle.px(), clusterparticle.py(), clusterparticle.pz(), clusterparticle.e()); double truepthadsum = GetPtHadSum(tracks, lRealPhoton, cfgMinR, cfgMaxR, false, false, false); truephotonPt = clusterparticle.e(); - histos.fill(HIST("REC_TrueTrigger_V_PtHadSum_Photon"), truephotonPt, truepthadsum); + histos.fill(HIST("REC_TrueTrigger_V_PtHadSum_Photon"), truephotonPt, truepthadsum, weight); } } // photon check } // clusterparticle loop @@ -1000,39 +1026,6 @@ struct statPromptPhoton { } } // cluster loop - // auto bc = collision.bc_as(); - // int rnr = bc.runNumber(); - - // std::string rnrstring = std::to_string(rnr); - // if (runs.find(rnrstring) == std::string::npos) { - // std::cout<<"++++++++++++++++++++++++++++++++"<getForTimeStamp(ccdbpath, bc.timestamp()); - // if(grpmag) { - // bfield = std::lround(5.f * grpmag->getL3Current() / 30000.f); - // std::cout<<"++++++++++++++++++++++++++++++++"<getForTimeStamp(ccdbpath, bc.timestamp()); - // if(!grpo) { - // std::cout<<"WE CAN NEITHER FETCH GRPMAG OR GRPO!!! SHIT IS SCREWED"<getNominalL3Field(); - // } - // bfield = 5; - // runs += rnrstring; - // std::cout << "++++++++++++++++++++++++++++++++" << std::endl; - // std::cout << "Run is now appended to string: " << runs << std::endl; - // std::cout << "++++++++++++++++++++++++++++++++" << std::endl; - - // } // check mag field for current run number: done! - // clusters done, now we do the sternheimer tracks for (auto& track : tracks) { bool sterntrigger = false; @@ -1057,19 +1050,9 @@ struct statPromptPhoton { phiPrime = 2 * TMath::Pi() - phiPrime; } - // if (bfield < 0) { - // phiPrime = 2 * TMath::Pi() - phiPrime; - // } - phiPrime = phiPrime + TMath::Pi() / 18.; phiPrime = fmod(phiPrime, 2 * TMath::Pi() / 18.); - // double pt = track.pt(); - // if (phiPrime > (0.12/pt + TMath::Pi()/18. + 0.035) || - // phiPrime < (0.1/pt/pt + TMath::Pi()/18. - 0.025) ) { histos.fill(HIST("REC_Track_PhiPrime_Pt"), phiPrime, track.pt()); - // }//geo cut - // Done with geometric cuts - histos.fill(HIST("REC_Track_Pt"), track.pt()); histos.fill(HIST("REC_Track_Phi"), track.phi()); if (clustertrigger) { @@ -1083,12 +1066,12 @@ struct statPromptPhoton { } } double pthadsum = GetPtHadSum(tracks, track, cfgMinR, cfgMaxR, true, false, true); - histos.fill(HIST("REC_Trigger_V_PtHadSum_Nch"), sternPt, pthadsum); + histos.fill(HIST("REC_Trigger_V_PtHadSum_Nch"), sternPt, pthadsum, weight); if (sterntrigger) { bool doStern = true; double sterncount = 1.0; while (doStern) { - histos.fill(HIST("REC_Trigger_V_PtHadSum_Stern"), sterncount, pthadsum, 2.0 / sternPt); + histos.fill(HIST("REC_Trigger_V_PtHadSum_Stern"), sterncount, pthadsum, (2.0 / sternPt) * weight); if (sterncount < sternPt) { sterncount++; } else { @@ -1103,9 +1086,8 @@ struct statPromptPhoton { PROCESS_SWITCH(statPromptPhoton, processMCRec_JE, "processJE MC data", false); int nEventsData = 0; - void processData(jfilteredCollisions::iterator const& collision, jfilteredClusters const& clusters, jDataTrackCandidates const& tracks, soa::Join const&, TrackCandidates const&, BcCandidates const&, jEMCtracks const& emctracks) + void processData(jfilteredDataCollisions::iterator const& collision, jfilteredClusters const& clusters, jDataTrackCandidates const& tracks, soa::Join const&, TrackCandidates const&, BcCandidates const&, jEMCtracks const& emctracks) { - nEventsData++; if (cfgDebug) { if (nEventsData == 1) { @@ -1113,8 +1095,12 @@ struct statPromptPhoton { } if ((nEventsData + 1) % 10000 == 0) { std::cout << "Processed Data Events: " << nEventsData << std::endl; + std::cout << "Events Trigger Bit: " << collision.triggerSel() << std::endl; + std::cout << "Trigger Mask Bit: " << triggerMaskBits[0] << std::endl; + std::cout << "Trigger Mask Cfg Line: " << cfgTriggerMasks << std::endl; } } + histos.fill(HIST("DATA_nEvents"), 0.5); // required cuts @@ -1124,13 +1110,21 @@ struct statPromptPhoton { return; histos.fill(HIST("DATA_nEvents"), 1.5); - if (cfgEmcTrigger) { if (!collision.isEmcalReadout()) return; } + histos.fill(HIST("DATA_nEvents"), 2.5); + if (cfgSkimmedTrigger) { + if (!jetderiveddatautilities::selectTrigger(collision, triggerMaskBits)) { + return; + } + } // JE Software Triggers + + histos.fill(HIST("DATA_nEvents"), 3.5); + bool noTrk = true; for (auto& track : tracks) { @@ -1331,10 +1325,6 @@ struct statPromptPhoton { phiPrime = 2 * TMath::Pi() - phiPrime; } - // if (bfield < 0) { - // phiPrime = 2 * TMath::Pi() - phiPrime; - // } - phiPrime = phiPrime + TMath::Pi() / 18.; phiPrime = fmod(phiPrime, 2 * TMath::Pi() / 18.); double pt = track.pt(); From d60eba72f0beb132920eee237d71d7c6686e310a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrea=20Tavira=20Garc=C3=ADa?= <118979672+atavirag@users.noreply.github.com> Date: Tue, 17 Jun 2025 16:06:07 +0200 Subject: [PATCH 110/871] [PWGHF] correlatorDMesonPairs: Add max pt to remove ambiguous candidates (#11637) --- .../TableProducer/correlatorDMesonPairs.cxx | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/PWGHF/HFC/TableProducer/correlatorDMesonPairs.cxx b/PWGHF/HFC/TableProducer/correlatorDMesonPairs.cxx index ee0ab36ce91..96aa7514a40 100644 --- a/PWGHF/HFC/TableProducer/correlatorDMesonPairs.cxx +++ b/PWGHF/HFC/TableProducer/correlatorDMesonPairs.cxx @@ -75,6 +75,7 @@ struct HfCorrelatorDMesonPairs { Configurable massCut{"massCut", 0.05, "Maximum deviation from PDG peak allowed for signal region"}; Configurable daughterTracksCutFlag{"daughterTracksCutFlag", false, "Flag to add cut on daughter tracks"}; Configurable removeAmbiguous{"removeAmbiguous", false, "Flag to remove ambiguous candidates"}; + Configurable ptMaxRemoveAmbiguous{"ptMaxRemoveAmbiguous", 5.0, "Max. pT to remove the ambiguous candidates"}; // ML inference Configurable applyMl{"applyMl", false, "Flag to apply ML selections"}; @@ -612,7 +613,7 @@ struct HfCorrelatorDMesonPairs { } // Remove ambiguous D0 candidates if flag is true - if (removeAmbiguous && (isDCand1 && isDbarCand1)) { + if (removeAmbiguous && (isDCand1 && isDbarCand1) && candidate1.pt() < ptMaxRemoveAmbiguous) { continue; } @@ -687,7 +688,7 @@ struct HfCorrelatorDMesonPairs { } // Remove ambiguous D0 candidates if flag is true - if (removeAmbiguous && (isDCand2 && isDbarCand2)) { + if (removeAmbiguous && (isDCand2 && isDbarCand2) && candidate2.pt() < ptMaxRemoveAmbiguous) { continue; } @@ -776,7 +777,7 @@ struct HfCorrelatorDMesonPairs { } // Remove ambiguous D0 candidates if flag is true - if (removeAmbiguous && (isDCand1 && isDbarCand1)) { + if (removeAmbiguous && (isDCand1 && isDbarCand1) && candidate1.pt() < ptMaxRemoveAmbiguous) { continue; } @@ -803,10 +804,10 @@ struct HfCorrelatorDMesonPairs { registry.fill(HIST("hMass"), hfHelper.invMassD0ToPiK(candidate1), candidate1.pt()); registry.fill(HIST("hPtVsYVsNContribMcRec"), candidate1.pt(), hfHelper.yD0(candidate1), collision.numContrib()); registry.fill(HIST("hNContribMcRec"), collision.numContrib()); - if (originRec1 == 1) { + if (originRec1 == RecoDecay::Prompt) { registry.fill(HIST("hMassMcRecPrompt"), hfHelper.invMassD0ToPiK(candidate1), candidate1.pt()); registry.fill(HIST("hPtVsYVsNContribMcRecPrompt"), candidate1.pt(), hfHelper.yD0(candidate1), collision.numContrib()); - } else if (originRec1 == 2) { + } else if (originRec1 == RecoDecay::NonPrompt) { registry.fill(HIST("hMassMcRecNonPrompt"), hfHelper.invMassD0ToPiK(candidate1), candidate1.pt()); registry.fill(HIST("hPtVsYVsNContribMcRecNonPrompt"), candidate1.pt(), hfHelper.yD0(candidate1), collision.numContrib()); } @@ -824,9 +825,9 @@ struct HfCorrelatorDMesonPairs { registry.fill(HIST("hMass"), hfHelper.invMassD0barToKPi(candidate1), candidate1.pt()); registry.fill(HIST("hPtVsYVsNContribMcRec"), candidate1.pt(), hfHelper.yD0(candidate1), collision.numContrib()); registry.fill(HIST("hNContribMcRec"), collision.numContrib()); - if (originRec1 == 1) { + if (originRec1 == RecoDecay::Prompt) { registry.fill(HIST("hMassMcRecPrompt"), hfHelper.invMassD0barToKPi(candidate1), candidate1.pt()); - } else if (originRec1 == 2) { + } else if (originRec1 == RecoDecay::NonPrompt) { registry.fill(HIST("hMassMcRecNonPrompt"), hfHelper.invMassD0barToKPi(candidate1), candidate1.pt()); } } else if (isTrueDCand1) { @@ -893,7 +894,7 @@ struct HfCorrelatorDMesonPairs { } // Remove ambiguous D0 candidates if flag is true - if (removeAmbiguous && (isDCand2 && isDbarCand2)) { + if (removeAmbiguous && (isDCand2 && isDbarCand2) && candidate2.pt() < ptMaxRemoveAmbiguous) { continue; } @@ -1011,10 +1012,10 @@ struct HfCorrelatorDMesonPairs { } registry.fill(HIST("hPtVsYVsNContribMcGen"), particle1.pt(), particle1.y(), numPvContributorsGen); - if (originGen1 == 1) { + if (originGen1 == RecoDecay::Prompt) { registry.fill(HIST("hPtVsYVsNContribMcGenPrompt"), particle1.pt(), particle1.y(), numPvContributorsGen); } - if (originGen1 == 2) { + if (originGen1 == RecoDecay::NonPrompt) { registry.fill(HIST("hPtVsYVsNContribMcGenNonPrompt"), particle1.pt(), particle1.y(), numPvContributorsGen); } registry.fill(HIST("hNContribMcGen"), numPvContributorsGen); From cf634a6e360c9e2cc9cb28766751d25d9abe46b3 Mon Sep 17 00:00:00 2001 From: "Paul Veen (paveen)" <80593165+ppoava@users.noreply.github.com> Date: Tue, 17 Jun 2025 17:35:42 +0200 Subject: [PATCH 111/871] [Common] Adding pT information to muonQA task (#11647) --- Common/Tasks/qaMuon.cxx | 119 ++++++++++++++++++++++++++++++++++------ 1 file changed, 102 insertions(+), 17 deletions(-) diff --git a/Common/Tasks/qaMuon.cxx b/Common/Tasks/qaMuon.cxx index 7c854935930..2c19b4bff67 100644 --- a/Common/Tasks/qaMuon.cxx +++ b/Common/Tasks/qaMuon.cxx @@ -13,39 +13,39 @@ /// \author Paul Veen /// \author Chi Zhang -#include - -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" -#include "Framework/ASoAHelpers.h" +#include "Common/DataModel/CollisionAssociationTables.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/FwdTrackReAlignTables.h" #include "CCDB/BasicCCDBManager.h" #include "CCDB/CCDBTimeStampUtils.h" -#include "CommonUtils/NameConf.h" #include "CommonUtils/ConfigurableParam.h" +#include "CommonUtils/NameConf.h" #include "DataFormatsMCH/Cluster.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DetectorsBase/GeometryManager.h" #include "DataFormatsParameters/GRPMagField.h" +#include "DataFormatsParameters/GRPObject.h" #include "DetectorsBase/GRPGeomHelper.h" +#include "DetectorsBase/GeometryManager.h" #include "DetectorsBase/Propagator.h" #include "Field/MagneticField.h" -#include "MathUtils/Cartesian.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" +#include "GlobalTracking/MatchGlobalFwd.h" +#include "MCHBase/TrackerParam.h" #include "MCHGeometryTransformer/Transformations.h" #include "MCHTracking/Track.h" #include "MCHTracking/TrackExtrap.h" -#include "MCHTracking/TrackParam.h" #include "MCHTracking/TrackFitter.h" -#include "MCHBase/TrackerParam.h" -#include "GlobalTracking/MatchGlobalFwd.h" +#include "MCHTracking/TrackParam.h" +#include "MathUtils/Cartesian.h" #include "ReconstructionDataFormats/TrackFwd.h" -#include "Common/DataModel/FwdTrackReAlignTables.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/CollisionAssociationTables.h" -#include "TGeoGlobalMagField.h" #include "Math/Vector4D.h" +#include "TGeoGlobalMagField.h" + +#include using namespace std; using namespace o2; @@ -538,11 +538,16 @@ struct muonQa { AxisSpec invMassAxis = {400, 1, 5, "M_{#mu^{+}#mu^{-}} (GeV/c^{2})"}; AxisSpec invMassCorrelationAxis = {80, 0, 8, "M_{#mu^{+}#mu^{-}} (GeV/c^{2})"}; AxisSpec invMassAxisFull = {5000, 0, 100, "M_{#mu^{+}#mu^{-}} (GeV/c^{2})"}; + AxisSpec invMassAxis2D = {750, 0, 15, "M_{#mu^{+}#mu^{-}} (GeV/c^{2})"}; + AxisSpec pTAxis2D = {120, 0, 30, "p_{T} (GeV/c)"}; // MCH-MID tracks with MCH acceptance cuts registryDimuon.add("dimuon/same-event/invariantMass_MuonKine_MuonCuts", "#mu^{+}#mu^{-} invariant mass", {HistType::kTH1F, {invMassAxis}}); registryDimuon.add("dimuon/same-event/invariantMassFull_MuonKine_MuonCuts", "#mu^{+}#mu^{-} invariant mass", {HistType::kTH1F, {invMassAxisFull}}); registryDimuon.add("dimuon/mixed-event/invariantMass_MuonKine_MuonCuts", "#mu^{+}#mu^{-} invariant mass", {HistType::kTH1F, {invMassAxis}}); registryDimuon.add("dimuon/mixed-event/invariantMassFull_MuonKine_MuonCuts", "#mu^{+}#mu^{-} invariant mass", {HistType::kTH1F, {invMassAxisFull}}); + // -- Mass and pT + registryDimuon.add("dimuon/same-event/invariantMass_pT_MuonKine_MuonCuts", "#mu^{+}#mu^{-} invariant mass", {HistType::kTH2F, {invMassAxis2D, pTAxis2D}}); + registryDimuon.add("dimuon/mixed-event/invariantMass_pT_MuonKine_MuonCuts", "#mu^{+}#mu^{-} invariant mass", {HistType::kTH2F, {invMassAxis2D, pTAxis2D}}); // MCH-MID tracks with MCH acceptance cuts and combinations from the top and bottom halfs of MCH registryDimuon.add("dimuon/same-event/invariantMass_MuonKine_MuonCuts_TT", "#mu^{+}#mu^{-} invariant mass, top-top", {HistType::kTH1F, {invMassAxis}}); registryDimuon.add("dimuon/same-event/invariantMassFull_MuonKine_MuonCuts_TT", "#mu^{+}#mu^{-} invariant mass, top-top", {HistType::kTH1F, {invMassAxisFull}}); @@ -556,6 +561,13 @@ struct muonQa { registryDimuon.add("dimuon/mixed-event/invariantMassFull_MuonKine_MuonCuts_TB", "#mu^{+}#mu^{-} invariant mass, top-bottom or bottom-top", {HistType::kTH1F, {invMassAxisFull}}); registryDimuon.add("dimuon/mixed-event/invariantMass_MuonKine_MuonCuts_BB", "#mu^{+}#mu^{-} invariant mass, bottom-bottom", {HistType::kTH1F, {invMassAxis}}); registryDimuon.add("dimuon/mixed-event/invariantMassFull_MuonKine_MuonCuts_BB", "#mu^{+}#mu^{-} invariant mass, bottom-bottom", {HistType::kTH1F, {invMassAxisFull}}); + // -- Mass and pT + registryDimuon.add("dimuon/same-event/invariantMass_pT_MuonKine_MuonCuts_TT", "#mu^{+}#mu^{-} invariant mass, top-top", {HistType::kTH2F, {invMassAxis2D, pTAxis2D}}); + registryDimuon.add("dimuon/same-event/invariantMass_pT_MuonKine_MuonCuts_TB", "#mu^{+}#mu^{-} invariant mass, top-bottom or bottom-top", {HistType::kTH2F, {invMassAxis2D, pTAxis2D}}); + registryDimuon.add("dimuon/same-event/invariantMass_pT_MuonKine_MuonCuts_BB", "#mu^{+}#mu^{-} invariant mass, bottom-bottom", {HistType::kTH2F, {invMassAxis2D, pTAxis2D}}); + registryDimuon.add("dimuon/mixed-event/invariantMass_pT_MuonKine_MuonCuts_TT", "#mu^{+}#mu^{-} invariant mass, top-top", {HistType::kTH2F, {invMassAxis2D, pTAxis2D}}); + registryDimuon.add("dimuon/mixed-event/invariantMass_pT_MuonKine_MuonCuts_TB", "#mu^{+}#mu^{-} invariant mass, top-bottom or bottom-top", {HistType::kTH2F, {invMassAxis2D, pTAxis2D}}); + registryDimuon.add("dimuon/mixed-event/invariantMass_pT_MuonKine_MuonCuts_BB", "#mu^{+}#mu^{-} invariant mass, bottom-bottom", {HistType::kTH2F, {invMassAxis2D, pTAxis2D}}); // MCH-MID tracks with MFT acceptance cuts and combinations from the top and bottom halfs of MCH registryDimuon.add("dimuon/same-event/invariantMass_MuonKine_GlobalMuonCuts_TT", "#mu^{+}#mu^{-} invariant mass, top-top", {HistType::kTH1F, {invMassAxis}}); registryDimuon.add("dimuon/same-event/invariantMassFull_MuonKine_GlobalMuonCuts_TT", "#mu^{+}#mu^{-} invariant mass, top-top", {HistType::kTH1F, {invMassAxisFull}}); @@ -569,6 +581,13 @@ struct muonQa { registryDimuon.add("dimuon/mixed-event/invariantMassFull_MuonKine_GlobalMuonCuts_TB", "#mu^{+}#mu^{-} invariant mass, top-bottom or bottom-top", {HistType::kTH1F, {invMassAxisFull}}); registryDimuon.add("dimuon/mixed-event/invariantMass_MuonKine_GlobalMuonCuts_BB", "#mu^{+}#mu^{-} invariant mass, bottom-bottom", {HistType::kTH1F, {invMassAxis}}); registryDimuon.add("dimuon/mixed-event/invariantMassFull_MuonKine_GlobalMuonCuts_BB", "#mu^{+}#mu^{-} invariant mass, bottom-bottom", {HistType::kTH1F, {invMassAxisFull}}); + // -- Mass and pT + registryDimuon.add("dimuon/same-event/invariantMass_pT_MuonKine_GlobalMuonCuts_TT", "#mu^{+}#mu^{-} invariant mass, top-top", {HistType::kTH2F, {invMassAxis2D, pTAxis2D}}); + registryDimuon.add("dimuon/same-event/invariantMass_pT_MuonKine_GlobalMuonCuts_TB", "#mu^{+}#mu^{-} invariant mass, top-bottom or bottom-top", {HistType::kTH2F, {invMassAxis2D, pTAxis2D}}); + registryDimuon.add("dimuon/same-event/invariantMass_pT_MuonKine_GlobalMuonCuts_BB", "#mu^{+}#mu^{-} invariant mass, bottom-bottom", {HistType::kTH2F, {invMassAxis2D, pTAxis2D}}); + registryDimuon.add("dimuon/mixed-event/invariantMass_pT_MuonKine_GlobalMuonCuts_TT", "#mu^{+}#mu^{-} invariant mass, top-top", {HistType::kTH2F, {invMassAxis2D, pTAxis2D}}); + registryDimuon.add("dimuon/mixed-event/invariantMass_pT_MuonKine_GlobalMuonCuts_TB", "#mu^{+}#mu^{-} invariant mass, top-bottom or bottom-top", {HistType::kTH2F, {invMassAxis2D, pTAxis2D}}); + registryDimuon.add("dimuon/mixed-event/invariantMass_pT_MuonKine_GlobalMuonCuts_BB", "#mu^{+}#mu^{-} invariant mass, bottom-bottom", {HistType::kTH2F, {invMassAxis2D, pTAxis2D}}); // MCH-MID tracks with MCH acceptance cuts and combinations from the left and right halfs of MCH registryDimuon.add("dimuon/same-event/invariantMass_MuonKine_MuonCuts_LL", "#mu^{+}#mu^{-} invariant mass, left-left", {HistType::kTH1F, {invMassAxis}}); registryDimuon.add("dimuon/same-event/invariantMassFull_MuonKine_MuonCuts_LL", "#mu^{+}#mu^{-} invariant mass, left-left", {HistType::kTH1F, {invMassAxisFull}}); @@ -582,11 +601,21 @@ struct muonQa { registryDimuon.add("dimuon/mixed-event/invariantMassFull_MuonKine_MuonCuts_LR", "#mu^{+}#mu^{-} invariant mass, left-right or right-left", {HistType::kTH1F, {invMassAxisFull}}); registryDimuon.add("dimuon/mixed-event/invariantMass_MuonKine_MuonCuts_RR", "#mu^{+}#mu^{-} invariant mass, right-right", {HistType::kTH1F, {invMassAxis}}); registryDimuon.add("dimuon/mixed-event/invariantMassFull_MuonKine_MuonCuts_RR", "#mu^{+}#mu^{-} invariant mass, right-right", {HistType::kTH1F, {invMassAxisFull}}); + // -- Mass and pT + registryDimuon.add("dimuon/same-event/invariantMass_pT_MuonKine_MuonCuts_LL", "#mu^{+}#mu^{-} invariant mass, left-left", {HistType::kTH2F, {invMassAxis2D, pTAxis2D}}); + registryDimuon.add("dimuon/same-event/invariantMass_pT_MuonKine_MuonCuts_LR", "#mu^{+}#mu^{-} invariant mass, left-right or right-left", {HistType::kTH2F, {invMassAxis2D, pTAxis2D}}); + registryDimuon.add("dimuon/same-event/invariantMass_pT_MuonKine_MuonCuts_RR", "#mu^{+}#mu^{-} invariant mass, right-right", {HistType::kTH2F, {invMassAxis2D, pTAxis2D}}); + registryDimuon.add("dimuon/mixed-event/invariantMass_pT_MuonKine_MuonCuts_LL", "#mu^{+}#mu^{-} invariant mass, left-left", {HistType::kTH2F, {invMassAxis2D, pTAxis2D}}); + registryDimuon.add("dimuon/mixed-event/invariantMass_pT_MuonKine_MuonCuts_LR", "#mu^{+}#mu^{-} invariant mass, left-right or left-right", {HistType::kTH2F, {invMassAxis2D, pTAxis2D}}); + registryDimuon.add("dimuon/mixed-event/invariantMass_pT_MuonKine_MuonCuts_RR", "#mu^{+}#mu^{-} invariant mass, right-right", {HistType::kTH2F, {invMassAxis2D, pTAxis2D}}); // MCH-MID tracks with MFT acceptance cuts registryDimuon.add("dimuon/same-event/invariantMass_MuonKine_GlobalMuonCuts", "#mu^{+}#mu^{-} invariant mass", {HistType::kTH1F, {invMassAxis}}); registryDimuon.add("dimuon/same-event/invariantMassFull_MuonKine_GlobalMuonCuts", "#mu^{+}#mu^{-} invariant mass", {HistType::kTH1F, {invMassAxisFull}}); registryDimuon.add("dimuon/mixed-event/invariantMass_MuonKine_GlobalMuonCuts", "#mu^{+}#mu^{-} invariant mass", {HistType::kTH1F, {invMassAxis}}); registryDimuon.add("dimuon/mixed-event/invariantMassFull_MuonKine_GlobalMuonCuts", "#mu^{+}#mu^{-} invariant mass", {HistType::kTH1F, {invMassAxisFull}}); + // -- Mass and pT + registryDimuon.add("dimuon/same-event/invariantMass_pT_MuonKine_GlobalMuonCuts", "#mu^{+}#mu^{-} invariant mass", {HistType::kTH2F, {invMassAxis2D, pTAxis2D}}); + registryDimuon.add("dimuon/mixed-event/invariantMass_pT_MuonKine_GlobalMuonCuts", "#mu^{+}#mu^{-} invariant mass", {HistType::kTH2F, {invMassAxis2D, pTAxis2D}}); // MCH-MID tracks with MFT acceptance cuts and combinations from the left and right halfs of MCH registryDimuon.add("dimuon/same-event/invariantMass_MuonKine_GlobalMuonCuts_LL", "#mu^{+}#mu^{-} invariant mass, left-left", {HistType::kTH1F, {invMassAxis}}); registryDimuon.add("dimuon/same-event/invariantMassFull_MuonKine_GlobalMuonCuts_LL", "#mu^{+}#mu^{-} invariant mass, left-left", {HistType::kTH1F, {invMassAxisFull}}); @@ -600,6 +629,13 @@ struct muonQa { registryDimuon.add("dimuon/mixed-event/invariantMassFull_MuonKine_GlobalMuonCuts_LR", "#mu^{+}#mu^{-} invariant mass, left-right or right-left", {HistType::kTH1F, {invMassAxisFull}}); registryDimuon.add("dimuon/mixed-event/invariantMass_MuonKine_GlobalMuonCuts_RR", "#mu^{+}#mu^{-} invariant mass, right-right", {HistType::kTH1F, {invMassAxis}}); registryDimuon.add("dimuon/mixed-event/invariantMassFull_MuonKine_GlobalMuonCuts_RR", "#mu^{+}#mu^{-} invariant mass right-right", {HistType::kTH1F, {invMassAxisFull}}); + // -- Mass and pT + registryDimuon.add("dimuon/same-event/invariantMass_pT_MuonKine_GlobalMuonCuts_LL", "#mu^{+}#mu^{-} invariant mass, left-left", {HistType::kTH2F, {invMassAxis2D, pTAxis2D}}); + registryDimuon.add("dimuon/same-event/invariantMass_pT_MuonKine_GlobalMuonCuts_LR", "#mu^{+}#mu^{-} invariant mass, left-right or right-left", {HistType::kTH2F, {invMassAxis2D, pTAxis2D}}); + registryDimuon.add("dimuon/same-event/invariantMass_pT_MuonKine_GlobalMuonCuts_RR", "#mu^{+}#mu^{-} invariant mass, right-right", {HistType::kTH2F, {invMassAxis2D, pTAxis2D}}); + registryDimuon.add("dimuon/mixed-event/invariantMass_pT_MuonKine_GlobalMuonCuts_LL", "#mu^{+}#mu^{-} invariant mass, left-left", {HistType::kTH2F, {invMassAxis2D, pTAxis2D}}); + registryDimuon.add("dimuon/mixed-event/invariantMass_pT_MuonKine_GlobalMuonCuts_LR", "#mu^{+}#mu^{-} invariant mass, left-right or right-left", {HistType::kTH2F, {invMassAxis2D, pTAxis2D}}); + registryDimuon.add("dimuon/mixed-event/invariantMass_pT_MuonKine_GlobalMuonCuts_RR", "#mu^{+}#mu^{-} invariant mass, right-right", {HistType::kTH2F, {invMassAxis2D, pTAxis2D}}); // Good MFT-MCH-MID tracks with MCH parameters and MFT acceptance cuts registryDimuon.add("dimuon/same-event/invariantMass_MuonKine_GlobalMatchesCuts", "#mu^{+}#mu^{-} invariant mass", {HistType::kTH1F, {invMassAxis}}); registryDimuon.add("dimuon/same-event/invariantMassFull_MuonKine_GlobalMatchesCuts", "#mu^{+}#mu^{-} invariant mass", {HistType::kTH1F, {invMassAxisFull}}); @@ -965,6 +1001,26 @@ struct muonQa { return dimuon.M(); } + template + double GetMuMuPt(VarT const& track1, VarT const& track2) + { + ROOT::Math::PxPyPzMVector muon1{ + track1.px, + track1.py, + track1.pz, + o2::constants::physics::MassMuon}; + + ROOT::Math::PxPyPzMVector muon2{ + track2.px, + track2.py, + track2.pz, + o2::constants::physics::MassMuon}; + + auto dimuon = muon1 + muon2; + + return dimuon.Pt(); + } + template void GetMuonPairs(TMuons const& muons, TCandidates const& matchingCandidates, const std::map& collisionInfos, std::vector& muonPairs, @@ -2253,58 +2309,73 @@ struct muonQa { bool sameEvent = (collisionIndex1 == collisionIndex2); double mass = GetMuMuInvariantMass(fgValuesMuonPV1, fgValuesMuonPV2); + double pT = GetMuMuPt(fgValuesMuonPV1, fgValuesMuonPV2); if (goodMuonTracks) { if (sameEvent) { // same-event case registryDimuon.get(HIST("dimuon/same-event/invariantMass_MuonKine_MuonCuts"))->Fill(mass); registryDimuon.get(HIST("dimuon/same-event/invariantMassFull_MuonKine_MuonCuts"))->Fill(mass); + registryDimuon.get(HIST("dimuon/same-event/invariantMass_pT_MuonKine_MuonCuts"))->Fill(mass, pT); if (TopBottom1 == 0 && TopBottom2 == 0) { registryDimuon.get(HIST("dimuon/same-event/invariantMass_MuonKine_MuonCuts_TT"))->Fill(mass); registryDimuon.get(HIST("dimuon/same-event/invariantMassFull_MuonKine_MuonCuts_TT"))->Fill(mass); + registryDimuon.get(HIST("dimuon/same-event/invariantMass_pT_MuonKine_MuonCuts_TT"))->Fill(mass, pT); } else if ((TopBottom1 == 0 && TopBottom2 == 1) || (TopBottom1 == 1 && TopBottom2 == 0)) { registryDimuon.get(HIST("dimuon/same-event/invariantMass_MuonKine_MuonCuts_TB"))->Fill(mass); registryDimuon.get(HIST("dimuon/same-event/invariantMassFull_MuonKine_MuonCuts_TB"))->Fill(mass); + registryDimuon.get(HIST("dimuon/same-event/invariantMass_pT_MuonKine_MuonCuts_TB"))->Fill(mass, pT); } else if (TopBottom1 == 1 && TopBottom2 == 1) { registryDimuon.get(HIST("dimuon/same-event/invariantMass_MuonKine_MuonCuts_BB"))->Fill(mass); registryDimuon.get(HIST("dimuon/same-event/invariantMassFull_MuonKine_MuonCuts_BB"))->Fill(mass); + registryDimuon.get(HIST("dimuon/same-event/invariantMass_pT_MuonKine_MuonCuts_BB"))->Fill(mass, pT); } if (LeftRight1 == 0 && LeftRight2 == 0) { registryDimuon.get(HIST("dimuon/same-event/invariantMass_MuonKine_MuonCuts_LL"))->Fill(mass); registryDimuon.get(HIST("dimuon/same-event/invariantMassFull_MuonKine_MuonCuts_LL"))->Fill(mass); + registryDimuon.get(HIST("dimuon/same-event/invariantMass_pT_MuonKine_MuonCuts_LL"))->Fill(mass, pT); } else if ((LeftRight1 == 0 && LeftRight2 == 1) || (LeftRight1 == 1 && LeftRight2 == 0)) { registryDimuon.get(HIST("dimuon/same-event/invariantMass_MuonKine_MuonCuts_LR"))->Fill(mass); registryDimuon.get(HIST("dimuon/same-event/invariantMassFull_MuonKine_MuonCuts_LR"))->Fill(mass); + registryDimuon.get(HIST("dimuon/same-event/invariantMass_pT_MuonKine_MuonCuts_LR"))->Fill(mass, pT); } else if (LeftRight1 == 1 && LeftRight2 == 1) { registryDimuon.get(HIST("dimuon/same-event/invariantMass_MuonKine_MuonCuts_RR"))->Fill(mass); registryDimuon.get(HIST("dimuon/same-event/invariantMassFull_MuonKine_MuonCuts_RR"))->Fill(mass); + registryDimuon.get(HIST("dimuon/same-event/invariantMass_pT_MuonKine_MuonCuts_RR"))->Fill(mass, pT); } } else { // event-mixing case registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_MuonKine_MuonCuts"))->Fill(mass); registryDimuon.get(HIST("dimuon/mixed-event/invariantMassFull_MuonKine_MuonCuts"))->Fill(mass); + registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_pT_MuonKine_MuonCuts"))->Fill(mass, pT); if (TopBottom1 == 0 && TopBottom2 == 0) { registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_MuonKine_MuonCuts_TT"))->Fill(mass); registryDimuon.get(HIST("dimuon/mixed-event/invariantMassFull_MuonKine_MuonCuts_TT"))->Fill(mass); + registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_pT_MuonKine_MuonCuts_TT"))->Fill(mass, pT); } else if ((TopBottom1 == 0 && TopBottom2 == 1) || (TopBottom1 == 1 && TopBottom2 == 0)) { registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_MuonKine_MuonCuts_TB"))->Fill(mass); registryDimuon.get(HIST("dimuon/mixed-event/invariantMassFull_MuonKine_MuonCuts_TB"))->Fill(mass); + registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_pT_MuonKine_MuonCuts_TB"))->Fill(mass, pT); } else if (TopBottom1 == 1 && TopBottom2 == 1) { registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_MuonKine_MuonCuts_BB"))->Fill(mass); registryDimuon.get(HIST("dimuon/mixed-event/invariantMassFull_MuonKine_MuonCuts_BB"))->Fill(mass); + registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_pT_MuonKine_MuonCuts_BB"))->Fill(mass, pT); } if (LeftRight1 == 0 && LeftRight2 == 0) { registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_MuonKine_MuonCuts_LL"))->Fill(mass); registryDimuon.get(HIST("dimuon/mixed-event/invariantMassFull_MuonKine_MuonCuts_LL"))->Fill(mass); + registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_pT_MuonKine_MuonCuts_LL"))->Fill(mass, pT); } else if ((LeftRight1 == 0 && LeftRight2 == 1) || (LeftRight1 == 1 && LeftRight2 == 0)) { registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_MuonKine_MuonCuts_LR"))->Fill(mass); registryDimuon.get(HIST("dimuon/mixed-event/invariantMassFull_MuonKine_MuonCuts_LR"))->Fill(mass); + registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_pT_MuonKine_MuonCuts_LR"))->Fill(mass, pT); } else if (LeftRight1 == 1 && LeftRight2 == 1) { registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_MuonKine_MuonCuts_RR"))->Fill(mass); registryDimuon.get(HIST("dimuon/mixed-event/invariantMassFull_MuonKine_MuonCuts_RR"))->Fill(mass); + registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_pT_MuonKine_MuonCuts_RR"))->Fill(mass, pT); } } } @@ -2314,53 +2385,67 @@ struct muonQa { // same-event case registryDimuon.get(HIST("dimuon/same-event/invariantMass_MuonKine_GlobalMuonCuts"))->Fill(mass); registryDimuon.get(HIST("dimuon/same-event/invariantMassFull_MuonKine_GlobalMuonCuts"))->Fill(mass); + registryDimuon.get(HIST("dimuon/same-event/invariantMass_pT_MuonKine_GlobalMuonCuts"))->Fill(mass, pT); if (TopBottom1 == 0 && TopBottom2 == 0) { registryDimuon.get(HIST("dimuon/same-event/invariantMass_MuonKine_GlobalMuonCuts_TT"))->Fill(mass); registryDimuon.get(HIST("dimuon/same-event/invariantMassFull_MuonKine_GlobalMuonCuts_TT"))->Fill(mass); + registryDimuon.get(HIST("dimuon/same-event/invariantMass_pT_MuonKine_GlobalMuonCuts_TT"))->Fill(mass, pT); } else if ((TopBottom1 == 0 && TopBottom2 == 1) || (TopBottom1 == 1 && TopBottom2 == 0)) { registryDimuon.get(HIST("dimuon/same-event/invariantMass_MuonKine_GlobalMuonCuts_TB"))->Fill(mass); registryDimuon.get(HIST("dimuon/same-event/invariantMassFull_MuonKine_GlobalMuonCuts_TB"))->Fill(mass); + registryDimuon.get(HIST("dimuon/same-event/invariantMass_pT_MuonKine_GlobalMuonCuts_TB"))->Fill(mass, pT); } else if (TopBottom1 == 1 && TopBottom2 == 1) { registryDimuon.get(HIST("dimuon/same-event/invariantMass_MuonKine_GlobalMuonCuts_BB"))->Fill(mass); registryDimuon.get(HIST("dimuon/same-event/invariantMassFull_MuonKine_GlobalMuonCuts_BB"))->Fill(mass); + registryDimuon.get(HIST("dimuon/same-event/invariantMass_pT_MuonKine_GlobalMuonCuts_BB"))->Fill(mass, pT); } if (LeftRight1 == 0 && LeftRight2 == 0) { registryDimuon.get(HIST("dimuon/same-event/invariantMass_MuonKine_GlobalMuonCuts_LL"))->Fill(mass); registryDimuon.get(HIST("dimuon/same-event/invariantMassFull_MuonKine_GlobalMuonCuts_LL"))->Fill(mass); + registryDimuon.get(HIST("dimuon/same-event/invariantMass_pT_MuonKine_GlobalMuonCuts_LL"))->Fill(mass, pT); } else if ((LeftRight1 == 0 && LeftRight2 == 1) || (LeftRight1 == 1 && LeftRight2 == 0)) { registryDimuon.get(HIST("dimuon/same-event/invariantMass_MuonKine_GlobalMuonCuts_LR"))->Fill(mass); registryDimuon.get(HIST("dimuon/same-event/invariantMassFull_MuonKine_GlobalMuonCuts_LR"))->Fill(mass); + registryDimuon.get(HIST("dimuon/same-event/invariantMass_pT_MuonKine_GlobalMuonCuts_LR"))->Fill(mass, pT); } else if (LeftRight1 == 1 && LeftRight2 == 1) { registryDimuon.get(HIST("dimuon/same-event/invariantMass_MuonKine_GlobalMuonCuts_RR"))->Fill(mass); registryDimuon.get(HIST("dimuon/same-event/invariantMassFull_MuonKine_GlobalMuonCuts_RR"))->Fill(mass); + registryDimuon.get(HIST("dimuon/same-event/invariantMass_pT_MuonKine_GlobalMuonCuts_RR"))->Fill(mass, pT); } } else { // event-mixing case registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_MuonKine_GlobalMuonCuts"))->Fill(mass); registryDimuon.get(HIST("dimuon/mixed-event/invariantMassFull_MuonKine_GlobalMuonCuts"))->Fill(mass); + registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_pT_MuonKine_GlobalMuonCuts"))->Fill(mass, pT); if (TopBottom1 == 0 && TopBottom2 == 0) { registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_MuonKine_GlobalMuonCuts_TT"))->Fill(mass); registryDimuon.get(HIST("dimuon/mixed-event/invariantMassFull_MuonKine_GlobalMuonCuts_TT"))->Fill(mass); + registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_pT_MuonKine_GlobalMuonCuts_TT"))->Fill(mass, pT); } else if ((TopBottom1 == 0 && TopBottom2 == 1) || (TopBottom1 == 1 && TopBottom2 == 0)) { registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_MuonKine_GlobalMuonCuts_TB"))->Fill(mass); registryDimuon.get(HIST("dimuon/mixed-event/invariantMassFull_MuonKine_GlobalMuonCuts_TB"))->Fill(mass); + registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_pT_MuonKine_GlobalMuonCuts_TB"))->Fill(mass, pT); } else if (TopBottom1 == 1 && TopBottom2 == 1) { registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_MuonKine_GlobalMuonCuts_BB"))->Fill(mass); registryDimuon.get(HIST("dimuon/mixed-event/invariantMassFull_MuonKine_GlobalMuonCuts_BB"))->Fill(mass); + registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_pT_MuonKine_GlobalMuonCuts_BB"))->Fill(mass, pT); } if (LeftRight1 == 0 && LeftRight2 == 0) { registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_MuonKine_GlobalMuonCuts_LL"))->Fill(mass); registryDimuon.get(HIST("dimuon/mixed-event/invariantMassFull_MuonKine_GlobalMuonCuts_LL"))->Fill(mass); + registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_pT_MuonKine_GlobalMuonCuts_LL"))->Fill(mass, pT); } else if ((LeftRight1 == 0 && LeftRight2 == 1) || (LeftRight1 == 1 && LeftRight2 == 0)) { registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_MuonKine_GlobalMuonCuts_LR"))->Fill(mass); registryDimuon.get(HIST("dimuon/mixed-event/invariantMassFull_MuonKine_GlobalMuonCuts_LR"))->Fill(mass); + registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_pT_MuonKine_GlobalMuonCuts_LR"))->Fill(mass, pT); } else if (LeftRight1 == 1 && LeftRight2 == 1) { registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_MuonKine_GlobalMuonCuts_RR"))->Fill(mass); registryDimuon.get(HIST("dimuon/mixed-event/invariantMassFull_MuonKine_GlobalMuonCuts_RR"))->Fill(mass); + registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_pT_MuonKine_GlobalMuonCuts_RR"))->Fill(mass, pT); } } } From 60ada199b70baf5073845327dbd4ea4680edc9eb Mon Sep 17 00:00:00 2001 From: Rik Spijkers <78484875+rspijkers@users.noreply.github.com> Date: Tue, 17 Jun 2025 17:40:49 +0200 Subject: [PATCH 112/871] [PWGLF] fix missing abs() and config-axes bugs (#11651) --- .../Tasks/Strangeness/cascadecorrelations.cxx | 48 ++++++++++--------- 1 file changed, 25 insertions(+), 23 deletions(-) diff --git a/PWGLF/Tasks/Strangeness/cascadecorrelations.cxx b/PWGLF/Tasks/Strangeness/cascadecorrelations.cxx index 0d6fd6d67cb..4b78f8d6771 100644 --- a/PWGLF/Tasks/Strangeness/cascadecorrelations.cxx +++ b/PWGLF/Tasks/Strangeness/cascadecorrelations.cxx @@ -15,38 +15,40 @@ // Author: Rik Spijkers (rik.spijkers@cern.ch) // -#include -#include -#include -#include -#include -#include +#include "PWGLF/DataModel/LFStrangenessTables.h" +#include "PWGLF/Utils/inelGt.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "ReconstructionDataFormats/Track.h" #include "Common/Core/RecoDecay.h" -#include "Common/Core/trackUtilities.h" -#include "PWGLF/DataModel/LFStrangenessTables.h" #include "Common/Core/TrackSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "Common/DataModel/EventSelection.h" +#include "Common/Core/trackUtilities.h" #include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" #include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/PIDResponse.h" -#include "CCDB/BasicCCDBManager.h" +#include "Common/DataModel/TrackSelectionTables.h" #include "EventFiltering/Zorro.h" -#include "PWGLF/Utils/inelGt.h" +#include "CCDB/BasicCCDBManager.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/O2DatabasePDGPlugin.h" +#include "Framework/runDataProcessing.h" +#include "ReconstructionDataFormats/Track.h" + +#include #include -#include #include -#include +#include #include #include +#include + +#include +#include +#include +#include +#include // #include using namespace o2; @@ -536,8 +538,8 @@ struct CascadeCorrelations { ConfigurableAxis dcaAxis = {"dcaAxis", {100, 0.0f, 2.0f}, "cm"}; ConfigurableAxis multiplicityAxis{"multiplicityAxis", {100, 0, 100}, "Multiplicity (MultFT0M?)"}; ConfigurableAxis invLambdaMassAxis{"invLambdaMassAxis", {100, 1.07f, 1.17f}, "Inv. Mass (GeV/c^{2})"}; - AxisSpec deltaYAxis{40, -2 * maxRapidity, 2 * maxRapidity, "#Delta y"}; - AxisSpec rapidityAxis{100, -maxRapidity, maxRapidity, "y"}; + ConfigurableAxis deltaYAxis{"deltaYAxis", {40, -2.f, 2.f}, "#Delta y"}; + ConfigurableAxis rapidityAxis{"rapidityAxis", {100, -1.f, 1.f}, "y"}; AxisSpec selectionFlagAxis{4, -0.5f, 3.5f, "Selection flag of casc candidate"}; AxisSpec itsClustersAxis{8, -0.5, 7.5, "number of ITS clusters"}; AxisSpec tpcRowsAxis{160, -0.5, 159.5, "TPC crossed rows"}; @@ -1124,7 +1126,7 @@ struct CascadeCorrelations { if (!trigger.isPhysicalPrimary() || !assoc.isPhysicalPrimary()) continue; // require the cascades to be primaries - if (trigger.eta() > etaGenCascades) + if (TMath::Abs(trigger.eta()) > etaGenCascades) continue; // only apply eta cut to trigger - trigger normalization still valid without introducing 2-particle-acceptance effects double dphi = RecoDecay::constrainAngle(trigger.phi() - assoc.phi(), -PIHalf); From 8cc42fac7e1a2928977d4471423e00f69613676f Mon Sep 17 00:00:00 2001 From: Giorgio Alberto Lucia <87222843+GiorgioAlbertoLucia@users.noreply.github.com> Date: Tue, 17 Jun 2025 18:25:43 +0200 Subject: [PATCH 113/871] [PWGLF] added centrality ft0a and ft0c qa histograms (#11653) --- PWGLF/TableProducer/Nuspex/he3HadronFemto.cxx | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/PWGLF/TableProducer/Nuspex/he3HadronFemto.cxx b/PWGLF/TableProducer/Nuspex/he3HadronFemto.cxx index a2e4413854a..78a7246b8c4 100644 --- a/PWGLF/TableProducer/Nuspex/he3HadronFemto.cxx +++ b/PWGLF/TableProducer/Nuspex/he3HadronFemto.cxx @@ -76,8 +76,8 @@ using CollBracket = o2::math_utils::Bracket; using McIter = aod::McParticles::iterator; using CollBracket = o2::math_utils::Bracket; -using CollisionsFull = soa::Join; -using CollisionsFullMC = soa::Join; +using CollisionsFull = soa::Join; +using CollisionsFullMC = soa::Join; using TrackCandidates = soa::Join; using TrackCandidatesMC = soa::Join; @@ -243,7 +243,10 @@ struct he3HadronFemto { HistogramRegistry mQaRegistry{ "QA", { + {"hVtxZBefore", "Vertex distribution in Z before selections;Z (cm)", {HistType::kTH1F, {{400, -20.0, 20.0}}}}, {"hVtxZ", "Vertex distribution in Z;Z (cm)", {HistType::kTH1F, {{400, -20.0, 20.0}}}}, + {"hCentralityFT0A", ";Centrality FT0A", {HistType::kTH1F, {{100, 0, 100.0}}}}, + {"hCentralityFT0C", ";Centrality FT0C", {HistType::kTH1F, {{100, 0, 100.0}}}}, {"hNcontributor", "Number of primary vertex contributor", {HistType::kTH1F, {{2000, 0.0f, 2000.0f}}}}, {"hTrackSel", "Accepted tracks", {HistType::kTH1F, {{Selections::kAll, -0.5, static_cast(Selections::kAll) - 0.5}}}}, {"hEvents", "; Events;", {HistType::kTH1F, {{3, -0.5, 2.5}}}}, @@ -360,6 +363,7 @@ struct he3HadronFemto { bool selectCollision(const Tcollision& collision, const aod::BCsWithTimestamps&) { mQaRegistry.fill(HIST("hEvents"), 0); + mQaRegistry.fill(HIST("hVtxZBefore"), collision.posZ()); if constexpr (isMC) { if (/*!collision.sel8() ||*/ std::abs(collision.posZ()) > settingCutVertex) { @@ -383,6 +387,8 @@ struct he3HadronFemto { mQaRegistry.fill(HIST("hEvents"), 1); mQaRegistry.fill(HIST("hNcontributor"), collision.numContrib()); mQaRegistry.fill(HIST("hVtxZ"), collision.posZ()); + mQaRegistry.fill(HIST("hCentralityFT0A"), collision.centFT0A()); + mQaRegistry.fill(HIST("hCentralityFT0C"), collision.centFT0C()); return true; } From 2f2b00dd90ec5ffa788fafa104f3cb1121199fa9 Mon Sep 17 00:00:00 2001 From: Shirajum Monira <38348689+Eloviyo@users.noreply.github.com> Date: Tue, 17 Jun 2025 19:09:07 +0200 Subject: [PATCH 114/871] [PWGCF] FemtoUniverse cascade task -- Refactored the cascade tables to utilize FDParticle (#11645) Co-authored-by: Shirajum Monira --- PWGCF/FemtoUniverse/DataModel/FemtoDerived.h | 45 ++-- .../femtoUniverseProducerTask.cxx | 241 +++++++----------- ...toUniversePairTaskTrackCascadeExtended.cxx | 36 +-- 3 files changed, 129 insertions(+), 193 deletions(-) diff --git a/PWGCF/FemtoUniverse/DataModel/FemtoDerived.h b/PWGCF/FemtoUniverse/DataModel/FemtoDerived.h index 9a191441f1e..c103b52791e 100644 --- a/PWGCF/FemtoUniverse/DataModel/FemtoDerived.h +++ b/PWGCF/FemtoUniverse/DataModel/FemtoDerived.h @@ -139,23 +139,6 @@ DECLARE_SOA_COLUMN(MKaon, mKaon, float); //! The invariant mass of V } // namespace femtouniverseparticle -/// FemtoUniverseCascadeTrack -namespace femtouniversecascparticle -{ - -DECLARE_SOA_COLUMN(DcaV0daughters, dcaV0daughters, float); //! DCA between V0 daughters -DECLARE_SOA_COLUMN(Cpav0, cpav0, float); //! V0 cos of pointing angle -DECLARE_SOA_COLUMN(V0radius, v0radius, float); //! V0 transverse radius -DECLARE_SOA_COLUMN(CpaCasc, cpaCasc, float); //! cascade cosinus of pointing angle -DECLARE_SOA_COLUMN(Dcacascdaughters, dcacascdaughters, float); //! DCA between cascade daughters -DECLARE_SOA_COLUMN(Cascradius, cascradius, float); //! cascade transverse radius -DECLARE_SOA_COLUMN(Dcapostopv, dcapostopv, float); //! DCA of positive daughter to PV -DECLARE_SOA_COLUMN(Dcanegtopv, dcanegtopv, float); //! DCA of negative daughter to PV -DECLARE_SOA_COLUMN(Dcabachtopv, dcabachtopv, float); //! DCA of bachelor track to PV -DECLARE_SOA_COLUMN(Dcav0topv, dcav0topv, float); //! DCA of V0 to PV - -} // namespace femtouniversecascparticle - DECLARE_SOA_TABLE(FDParticles, "AOD", "FDPARTICLE", o2::soa::Index<>, femtouniverseparticle::FdCollisionId, @@ -176,6 +159,23 @@ DECLARE_SOA_TABLE(FDParticles, "AOD", "FDPARTICLE", femtouniverseparticle::P); using FDParticle = FDParticles::iterator; +/// FemtoUniverseCascadeTrack +namespace femtouniversecascparticle +{ +DECLARE_SOA_INDEX_COLUMN(FDParticle, fdParticle); +DECLARE_SOA_COLUMN(DcaV0daughters, dcaV0daughters, float); //! DCA between V0 daughters +DECLARE_SOA_COLUMN(Cpav0, cpav0, float); //! V0 cos of pointing angle +DECLARE_SOA_COLUMN(V0radius, v0radius, float); //! V0 transverse radius*/ +DECLARE_SOA_COLUMN(CpaCasc, cpaCasc, float); //! cascade cosinus of pointing angle +DECLARE_SOA_COLUMN(Dcacascdaughters, dcacascdaughters, float); //! DCA between cascade daughters +DECLARE_SOA_COLUMN(Cascradius, cascradius, float); //! cascade transverse radius +DECLARE_SOA_COLUMN(Dcapostopv, dcapostopv, float); //! DCA of positive daughter to PV +DECLARE_SOA_COLUMN(Dcanegtopv, dcanegtopv, float); //! DCA of negative daughter to PV +DECLARE_SOA_COLUMN(Dcabachtopv, dcabachtopv, float); //! DCA of bachelor track to PV +DECLARE_SOA_COLUMN(Dcav0topv, dcav0topv, float); //! DCA of V0 to PV + +} // namespace femtouniversecascparticle + DECLARE_SOA_TABLE(FDExtParticles, "AOD", "FDEXTPARTICLE", femtouniverseparticle::Sign, femtouniverseparticle::TpcNClsFound, @@ -221,16 +221,7 @@ using FDFullParticle = FDExtParticles::iterator; DECLARE_SOA_TABLE(FDCascParticles, "AOD", "FDCASCPARTICLE", o2::soa::Index<>, femtouniverseparticle::FdCollisionId, - femtouniverseparticle::Pt, - femtouniverseparticle::Eta, - femtouniverseparticle::Phi, - femtouniverseparticle::PartType, - femtouniverseparticle::Cut, - femtouniverseparticle::PidCut, - femtouniverseparticle::TempFitVar, - femtouniverseparticle::ChildrenIds, - femtouniverseparticle::MLambda, - femtouniverseparticle::MAntiLambda, + femtouniversecascparticle::FDParticleId, femtouniverseparticle::Theta, femtouniverseparticle::Px, femtouniverseparticle::Py, diff --git a/PWGCF/FemtoUniverse/TableProducer/femtoUniverseProducerTask.cxx b/PWGCF/FemtoUniverse/TableProducer/femtoUniverseProducerTask.cxx index e9a07329468..9111f50fa94 100644 --- a/PWGCF/FemtoUniverse/TableProducer/femtoUniverseProducerTask.cxx +++ b/PWGCF/FemtoUniverse/TableProducer/femtoUniverseProducerTask.cxx @@ -1015,24 +1015,15 @@ struct FemtoUniverseProducerTask { auto cutContainer = trackCuts.getCutContainer(track); // now the table is filled - if (!confIsActivateCascade) { - outputParts(outputCollision.lastIndex(), track.pt(), track.eta(), - track.phi(), aod::femtouniverseparticle::ParticleType::kTrack, - cutContainer.at( - femto_universe_track_selection::TrackContainerPosition::kCuts), - cutContainer.at( - femto_universe_track_selection::TrackContainerPosition::kPID), - track.dcaXY(), childIDs, 0, - track.sign()); // sign getter is mAntiLambda() - } else { - outputCascParts(outputCollision.lastIndex(), track.pt(), track.eta(), - track.phi(), aod::femtouniverseparticle::ParticleType::kTrack, - cutContainer.at( - femto_universe_track_selection::TrackContainerPosition::kCuts), - cutContainer.at( - femto_universe_track_selection::TrackContainerPosition::kPID), - track.dcaXY(), childIDs, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); - } + outputParts(outputCollision.lastIndex(), track.pt(), track.eta(), + track.phi(), aod::femtouniverseparticle::ParticleType::kTrack, + cutContainer.at( + femto_universe_track_selection::TrackContainerPosition::kCuts), + cutContainer.at( + femto_universe_track_selection::TrackContainerPosition::kPID), + track.dcaXY(), childIDs, 0, + track.sign()); // sign getter is mAntiLambda() + tmpIDtrack.push_back(track.globalIndex()); if (confIsDebug) { fillDebugParticle(track); @@ -1160,28 +1151,18 @@ struct FemtoUniverseProducerTask { childIDs[1] = 0; // neg childIDs[2] = 0; // bachelor float hasTOF = posTrackCasc.hasTOF() ? 1 : 0; - outputCascParts(outputCollision.lastIndex(), - casc.positivept(), - casc.positiveeta(), - casc.positivephi(), - aod::femtouniverseparticle::ParticleType::kV0Child, - 0, // cutContainerV0.at(femto_universe_v0_selection::V0ContainerPosition::kPosCuts), - 0, // cutContainerV0.at(femto_universe_v0_selection::V0ContainerPosition::kPosPID), - hasTOF, - childIDs, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0); - const int rowOfPosTrack = outputCascParts.lastIndex(); + outputParts(outputCollision.lastIndex(), + casc.positivept(), + casc.positiveeta(), + casc.positivephi(), + aod::femtouniverseparticle::ParticleType::kV0Child, + 0, // cutContainerV0.at(femto_universe_v0_selection::V0ContainerPosition::kPosCuts), + 0, // cutContainerV0.at(femto_universe_v0_selection::V0ContainerPosition::kPosPID), + hasTOF, + childIDs, + 0, + 0); + const int rowOfPosTrack = outputParts.lastIndex(); if constexpr (isMC) { fillMCParticle(posTrackCasc, o2::aod::femtouniverseparticle::ParticleType::kV0Child); } @@ -1192,28 +1173,18 @@ struct FemtoUniverseProducerTask { childIDs[1] = rowInPrimaryTrackTableNeg; // neg childIDs[2] = 0; // bachelor hasTOF = negTrackCasc.hasTOF() ? 1 : 0; - outputCascParts(outputCollision.lastIndex(), - casc.negativept(), - casc.negativeeta(), - casc.negativephi(), - aod::femtouniverseparticle::ParticleType::kV0Child, - 0, // cutContainerV0.at(femto_universe_v0_selection::V0ContainerPosition::kNegCuts), - 0, // cutContainerV0.at(femto_universe_v0_selection::V0ContainerPosition::kNegPID), - hasTOF, - childIDs, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0); - const int rowOfNegTrack = outputCascParts.lastIndex(); + outputParts(outputCollision.lastIndex(), + casc.negativept(), + casc.negativeeta(), + casc.negativephi(), + aod::femtouniverseparticle::ParticleType::kV0Child, + 0, // cutContainerV0.at(femto_universe_v0_selection::V0ContainerPosition::kNegCuts), + 0, // cutContainerV0.at(femto_universe_v0_selection::V0ContainerPosition::kNegPID), + hasTOF, + childIDs, + 0, + 0); + const int rowOfNegTrack = outputParts.lastIndex(); if constexpr (isMC) { fillMCParticle(negTrackCasc, o2::aod::femtouniverseparticle::ParticleType::kV0Child); } @@ -1225,44 +1196,36 @@ struct FemtoUniverseProducerTask { childIDs[1] = 0; // neg childIDs[2] = rowInPrimaryTrackTableBach; // bachelor hasTOF = bachTrackCasc.hasTOF() ? 1 : 0; - outputCascParts(outputCollision.lastIndex(), - casc.bachelorpt(), - casc.bacheloreta(), - casc.bachelorphi(), - aod::femtouniverseparticle::ParticleType::kCascadeBachelor, - 0, // cutContainerV0.at(femto_universe_v0_selection::V0ContainerPosition::kNegCuts), - 0, // cutContainerV0.at(femto_universe_v0_selection::V0ContainerPosition::kNegPID), - hasTOF, - childIDs, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0); - const int rowOfBachTrack = outputCascParts.lastIndex(); + outputParts(outputCollision.lastIndex(), + casc.bachelorpt(), + casc.bacheloreta(), + casc.bachelorphi(), + aod::femtouniverseparticle::ParticleType::kCascadeBachelor, + 0, // cutContainerV0.at(femto_universe_v0_selection::V0ContainerPosition::kNegCuts), + 0, // cutContainerV0.at(femto_universe_v0_selection::V0ContainerPosition::kNegPID), + hasTOF, + childIDs, + 0, + 0); + const int rowOfBachTrack = outputParts.lastIndex(); if constexpr (isMC) { fillMCParticle(bachTrackCasc, o2::aod::femtouniverseparticle::ParticleType::kCascadeBachelor); } // cascade std::vector indexCascChildID = {rowOfPosTrack, rowOfNegTrack, rowOfBachTrack}; + outputParts(outputCollision.lastIndex(), + casc.pt(), + casc.eta(), + casc.phi(), + aod::femtouniverseparticle::ParticleType::kCascade, + 0, // cutContainerV0.at(femto_universe_v0_selection::V0ContainerPosition::kV0), + 0, + 0, + indexCascChildID, + casc.mXi(), + casc.mOmega()); outputCascParts(outputCollision.lastIndex(), - casc.pt(), - casc.eta(), - casc.phi(), - aod::femtouniverseparticle::ParticleType::kCascade, - 0, // cutContainerV0.at(femto_universe_v0_selection::V0ContainerPosition::kV0), - 0, - 0, - indexCascChildID, - casc.mXi(), - casc.mOmega(), + outputParts.lastIndex(), casc.dcaV0daughters(), casc.v0cosPA(col.posX(), col.posY(), col.posZ()), casc.v0radius(), @@ -1725,30 +1688,21 @@ struct FemtoUniverseProducerTask { tmpIDtrack.push_back(particle.globalIndex()); continue; } - if (!confIsActivateCascade) { - outputParts(outputCollision.lastIndex(), - particle.pt(), - particle.eta(), - particle.phi(), - aod::femtouniverseparticle::ParticleType::kMCTruthTrack, - 0, - pdgCode, - variablePDG, - childIDs, - 0, - 0); - } else { + + if (confIsActivateCascade) childIDs.push_back(0); - outputCascParts(outputCollision.lastIndex(), - particle.pt(), - particle.eta(), - particle.phi(), - aod::femtouniverseparticle::ParticleType::kMCTruthTrack, - 0, - pdgCode, - pdgCode, - childIDs, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); - } + outputParts(outputCollision.lastIndex(), + particle.pt(), + particle.eta(), + particle.phi(), + aod::femtouniverseparticle::ParticleType::kMCTruthTrack, + 0, + pdgCode, + variablePDG, + childIDs, + 0, + 0); + if (confIsDebug) { fillDebugParticle(particle); } @@ -1782,29 +1736,18 @@ struct FemtoUniverseProducerTask { int32_t variablePDG = confStoreMCmothers ? getMotherPDG(particle) : particle.pdgCode(); - if (!confIsActivateCascade) { - outputParts(outputCollision.lastIndex(), - particle.pt(), - particle.eta(), - particle.phi(), - aod::femtouniverseparticle::ParticleType::kMCTruthTrack, - 0, - static_cast(particle.pdgCode()), - variablePDG, - childIDs, - 0, - 0); - } else { - outputCascParts(outputCollision.lastIndex(), - particle.pt(), - particle.eta(), - particle.phi(), - aod::femtouniverseparticle::ParticleType::kMCTruthTrack, - 0, - static_cast(particle.pdgCode()), - particle.pdgCode(), - childIDs, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); - } + outputParts(outputCollision.lastIndex(), + particle.pt(), + particle.eta(), + particle.phi(), + aod::femtouniverseparticle::ParticleType::kMCTruthTrack, + 0, + static_cast(particle.pdgCode()), + variablePDG, + childIDs, + 0, + 0); + if (confIsDebug) { fillDebugParticle(particle); } @@ -1890,15 +1833,15 @@ struct FemtoUniverseProducerTask { ptGenB); // pT of the B hadron (mother particle, only when non-prompt D0) } } else { - outputCascParts(outputCollision.lastIndex(), - particle.pt(), - particle.eta(), - particle.phi(), - aod::femtouniverseparticle::ParticleType::kMCTruthTrack, - 0, - pdgCode, - pdgCode, - childIDs, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + outputParts(outputCollision.lastIndex(), + particle.pt(), + particle.eta(), + particle.phi(), + aod::femtouniverseparticle::ParticleType::kMCTruthTrack, + 0, + pdgCode, + pdgCode, + childIDs, 0, 0); } if (confIsDebug) { fillDebugParticle(particle); diff --git a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackCascadeExtended.cxx b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackCascadeExtended.cxx index 026cabb1367..d17cabb1f50 100644 --- a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackCascadeExtended.cxx +++ b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackCascadeExtended.cxx @@ -42,10 +42,10 @@ struct femtoUniversePairTaskTrackCascadeExtended { Service pdgMC; SliceCache cache; - using FemtoFullParticles = soa::Join; + using FemtoFullParticles = soa::Join; Preslice perCol = aod::femtouniverseparticle::fdCollisionId; - using FemtoRecoParticles = soa::Join; + using FemtoRecoParticles = soa::Join; Preslice perColReco = aod::femtouniverseparticle::fdCollisionId; ConfigurableAxis confChildTempFitVarpTBins{"confChildTempFitVarpTBins", {20, 0.5, 4.05}, "V0 child: pT binning of the pT vs. TempFitVar plot"}; @@ -290,20 +290,21 @@ struct femtoUniversePairTaskTrackCascadeExtended { } } - void processCascades(const FilteredFDCollision& col, const FemtoFullParticles& parts) + void processCascades([[maybe_unused]] const FilteredFDCollision& col, const FemtoFullParticles& parts, const aod::FDCascParticles& fdcascs) { - auto groupCascs = cascs->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); - // const int multCol = col.multNtr(); + // auto groupCascs = cascs->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); + // const int multCol = col.multNtr(); - for (const auto& casc : groupCascs) { - rXiQA.fill(HIST("hMassXi"), casc.mLambda()); + for (const auto& casc : fdcascs) { + const auto& part = casc.fdParticle_as(); + rXiQA.fill(HIST("hMassXi"), part.mLambda()); // if (!invMCascade(casc.mLambda(), casc.mAntiLambda())) // continue; - const auto& posChild = parts.iteratorAt(casc.index() - 3); - const auto& negChild = parts.iteratorAt(casc.index() - 2); - const auto& bachelor = parts.iteratorAt(casc.index() - 1); + const auto& posChild = parts.iteratorAt(part.globalIndex() - 3 - parts.begin().globalIndex()); + const auto& negChild = parts.iteratorAt(part.globalIndex() - 2 - parts.begin().globalIndex()); + const auto& bachelor = parts.iteratorAt(part.globalIndex() - 1 - parts.begin().globalIndex()); // if (casc.transRadius() < confCascTranRad) // continue; @@ -311,7 +312,8 @@ struct femtoUniversePairTaskTrackCascadeExtended { // std::cout<<"TYPE:"< confNSigmaTPCProton) { continue; } @@ -330,10 +332,10 @@ struct femtoUniversePairTaskTrackCascadeExtended { continue; } - rXiQA.fill(HIST("hPtXi"), casc.pt()); - rXiQA.fill(HIST("hEtaXi"), casc.eta()); - rXiQA.fill(HIST("hPhiXi"), casc.phi()); - rXiQA.fill(HIST("hMassXiSelected"), casc.mLambda()); + rXiQA.fill(HIST("hPtXi"), part.pt()); + rXiQA.fill(HIST("hEtaXi"), part.eta()); + rXiQA.fill(HIST("hPhiXi"), part.phi()); + rXiQA.fill(HIST("hMassXiSelected"), part.mLambda()); rXiQA.fill(HIST("hDCAV0Daughters"), casc.dcaV0daughters()); rXiQA.fill(HIST("hV0CosPA"), casc.cpav0()); rXiQA.fill(HIST("hV0TranRad"), casc.v0radius()); @@ -344,7 +346,7 @@ struct femtoUniversePairTaskTrackCascadeExtended { rXiQA.fill(HIST("hDcaNegtoPV"), casc.dcanegtopv()); rXiQA.fill(HIST("hDcaBachtoPV"), casc.dcabachtopv()); rXiQA.fill(HIST("hDcaV0toPV"), casc.dcav0topv()); - rXiQA.fill(HIST("hInvMpT"), casc.pt(), casc.mLambda()); + rXiQA.fill(HIST("hInvMpT"), part.pt(), part.mLambda()); posChildHistos.fillQA(posChild); negChildHistos.fillQA(negChild); @@ -702,7 +704,7 @@ struct femtoUniversePairTaskTrackCascadeExtended { PROCESS_SWITCH(femtoUniversePairTaskTrackCascadeExtended, processMixedEventMCgen, "Enable processing mixed event MC truth for track - cascade", false); /// This function fills MC truth particles from derived MC table - void processMCgen(aod::FDCascParticles const& parts) + void processMCgen(aod::FDParticles const& parts) { for (const auto& part : parts) { if (part.partType() != uint8_t(aod::femtouniverseparticle::ParticleType::kMCTruthTrack)) From a844b185c2129fbffb7fb7e68a585de44dcd6921 Mon Sep 17 00:00:00 2001 From: Fabrizio Date: Tue, 17 Jun 2025 19:11:25 +0200 Subject: [PATCH 115/871] [PWGHF] Add exceptions for HF MC TOF recalibration to avoid human mistakes (#11655) --- PWGHF/TableProducer/mcPidTof.cxx | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/PWGHF/TableProducer/mcPidTof.cxx b/PWGHF/TableProducer/mcPidTof.cxx index 52ae2e2ebf4..6738cab46b9 100644 --- a/PWGHF/TableProducer/mcPidTof.cxx +++ b/PWGHF/TableProducer/mcPidTof.cxx @@ -737,6 +737,10 @@ struct mcPidTof { Configurable ccdbPath{"ccdbPath", "Users/f/fgrosa/RecalibmcPidTof/", "path for MC recalibration objects in CCDB"}; } mcRecalib; + // list of productions for which the postcalibrations must be turned off (FT0 digitisation fixed) + const std::vector prodNoPostCalib = {"LHC24h1c"}; + bool enableMcRecalib{false}; + HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; // Running variables @@ -793,6 +797,8 @@ struct mcPidTof { } hnSigmaFull[iSpecie] = histos.add(Form("nSigmaFull/%s", particleNames[iSpecie].c_str()), Form("N_{#sigma}^{TOF}(%s)", particleNames[iSpecie].c_str()), kTH2F, {pAxis, nSigmaAxis}); } + + enableMcRecalib = mcRecalib.enable; } // Reserves an empty table for the given particle ID with size of the given track table @@ -870,6 +876,10 @@ struct mcPidTof { std::map metadata; if (metadataInfo.isFullyDefined()) { metadata["RecoPassName"] = metadataInfo.get("AnchorPassName"); + if (std::find(prodNoPostCalib.begin(), prodNoPostCalib.end(), metadataInfo.get("LPMProductionTag")) != prodNoPostCalib.end()) { + enableMcRecalib = false; + LOGP(warn, "Nsigma postcalibrations turned off for {} (new MC productions have FT0 digitisation fixed)", metadataInfo.get("LPMProductionTag")); + } } else { LOGP(error, "Impossible to read metadata! Using default calibrations (2022 apass7)"); metadata["RecoPassName"] = ""; @@ -956,7 +966,7 @@ struct mcPidTof { continue; } - if (mcRecalib.enable) { + if (enableMcRecalib) { auto runNumber = trk.collision().bc_as().runNumber(); if (runNumber != currentRun) { // update postcalibration files @@ -970,7 +980,7 @@ struct mcPidTof { switch (pidId) { case idxPi: { nSigma = responsePi.GetSeparation(mRespParamsV3, trk); - if (mcRecalib.enable && trk.has_mcParticle()) { + if (enableMcRecalib && trk.has_mcParticle()) { if (std::abs(trk.mcParticle().pdgCode()) == kPiPlus) { // we rescale only true signal nSigma = applyMcRecalib(pidId, trk.pt(), nSigma); } @@ -980,7 +990,7 @@ struct mcPidTof { } case idxKa: { nSigma = responseKa.GetSeparation(mRespParamsV3, trk); - if (mcRecalib.enable && trk.has_mcParticle()) { + if (enableMcRecalib && trk.has_mcParticle()) { if (std::abs(trk.mcParticle().pdgCode()) == kKPlus) { // we rescale only true signal nSigma = applyMcRecalib(pidId, trk.pt(), nSigma); } @@ -990,7 +1000,7 @@ struct mcPidTof { } case idxPr: { nSigma = responsePr.GetSeparation(mRespParamsV3, trk); - if (mcRecalib.enable && trk.has_mcParticle()) { + if (enableMcRecalib && trk.has_mcParticle()) { if (std::abs(trk.mcParticle().pdgCode()) == kProton) { // we rescale only true signal nSigma = applyMcRecalib(pidId, trk.pt(), nSigma); } @@ -1012,7 +1022,7 @@ struct mcPidTof { case idxPi: { resolution = responsePi.GetExpectedSigma(mRespParamsV3, trk); nSigma = responsePi.GetSeparation(mRespParamsV3, trk); - if (mcRecalib.enable && trk.has_mcParticle()) { + if (enableMcRecalib && trk.has_mcParticle()) { if (std::abs(trk.mcParticle().pdgCode()) == kPiPlus) { // we rescale only true signal nSigma = applyMcRecalib(pidId, trk.pt(), nSigma); } @@ -1023,7 +1033,7 @@ struct mcPidTof { case idxKa: { resolution = responseKa.GetExpectedSigma(mRespParamsV3, trk); nSigma = responseKa.GetSeparation(mRespParamsV3, trk, resolution); - if (mcRecalib.enable && trk.has_mcParticle()) { + if (enableMcRecalib && trk.has_mcParticle()) { if (std::abs(trk.mcParticle().pdgCode()) == kKPlus) { // we rescale only true signal nSigma = applyMcRecalib(pidId, trk.pt(), nSigma); } @@ -1034,7 +1044,7 @@ struct mcPidTof { case idxPr: { resolution = responsePr.GetExpectedSigma(mRespParamsV3, trk); nSigma = responsePr.GetSeparation(mRespParamsV3, trk, resolution); - if (mcRecalib.enable && trk.has_mcParticle()) { + if (enableMcRecalib && trk.has_mcParticle()) { if (std::abs(trk.mcParticle().pdgCode()) == kProton) { // we rescale only true signal nSigma = applyMcRecalib(pidId, trk.pt(), nSigma); } From adc45e9c5d662a31020f04fe42b7cc0dcbc4c8d9 Mon Sep 17 00:00:00 2001 From: cterrevo Date: Tue, 17 Jun 2025 21:00:49 +0200 Subject: [PATCH 116/871] [PWGHF] removing check in accept. for recMC (#11649) Co-authored-by: Fabrizio --- PWGHF/D2H/Tasks/taskXic.cxx | 46 +++++++++++-------------------------- 1 file changed, 13 insertions(+), 33 deletions(-) diff --git a/PWGHF/D2H/Tasks/taskXic.cxx b/PWGHF/D2H/Tasks/taskXic.cxx index 3ef874240ec..ab5bf69738c 100644 --- a/PWGHF/D2H/Tasks/taskXic.cxx +++ b/PWGHF/D2H/Tasks/taskXic.cxx @@ -19,7 +19,10 @@ /// \author Himanshu Sharma , University and INFN Padova /// \author Cristina Terrevoli , INFN Bari -#include +#include "PWGHF/Core/HfHelper.h" +#include "PWGHF/Core/SelectorCuts.h" +#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "PWGHF/DataModel/CandidateSelectionTables.h" #include "CommonConstants/PhysicsConstants.h" #include "Framework/AnalysisTask.h" @@ -27,10 +30,7 @@ #include "Framework/O2DatabasePDGPlugin.h" #include "Framework/runDataProcessing.h" -#include "PWGHF/Core/HfHelper.h" -#include "PWGHF/Core/SelectorCuts.h" -#include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" +#include using namespace o2; using namespace o2::analysis; @@ -234,9 +234,9 @@ struct HfTaskXic { const AxisSpec thnAxisMCAllProngAccepted{2, -0.5, 1.5, "All MC prongs accepted"}; if (doprocessDataWithMl || doprocessMcWithMl) { // with ML - registry.add("hnXicVarsWithBdt", "THn for Xic candidates with BDT scores", HistType::kTHnSparseF, {thnAxisMass, thnAxisPt, thnAxisBdtScoreXicBkg, thnAxisBdtScoreXicPrompt, thnAxisBdtScoreXicNonPrompt, thnAxisMcOrigin, thnAxisPtMC, thnAxisYMC, thnAxisMCAllProngAccepted}); + registry.add("hnXicVarsWithBdt", "THn for Xic candidates with BDT scores", HistType::kTHnSparseF, {thnAxisMass, thnAxisPt, thnAxisBdtScoreXicBkg, thnAxisBdtScoreXicPrompt, thnAxisBdtScoreXicNonPrompt, thnAxisMcOrigin}); } else { - registry.add("hnXicVars", "THn for Xic candidates", HistType::kTHnSparseF, {thnAxisMass, thnAxisPt, thnAxisChi2PCA, thnAxisDecLength, thnAxisDecLengthXY, thnAxisCPA, thnAxisMcOrigin, thnAxisPtMC, thnAxisYMC, thnAxisMCAllProngAccepted}); + registry.add("hnXicVars", "THn for Xic candidates", HistType::kTHnSparseF, {thnAxisMass, thnAxisPt, thnAxisChi2PCA, thnAxisDecLength, thnAxisDecLengthXY, thnAxisCPA, thnAxisMcOrigin}); } } } // end init @@ -430,9 +430,6 @@ struct HfTaskXic { // Get the corresponding MC particle. auto mcParticleProng0 = candidate.template prong0_as().template mcParticle_as>(); auto pdgCodeProng0 = std::abs(mcParticleProng0.pdgCode()); - auto yProng0 = RecoDecay::y(mcParticleProng0.pVector(), o2::constants::physics::MassXiCPlus); - std::array ptProngs; - std::array etaProngs; // Signal registry.fill(HIST("MC/reconstructed/signal/hPtRecSig"), ptCandidate); // rec. level pT @@ -464,7 +461,8 @@ struct HfTaskXic { registry.fill(HIST("MC/reconstructed/signal/hEtaVsPtRecSig"), candidate.eta(), ptCandidate); /// reconstructed signal prompt - if (candidate.originMcRec() == RecoDecay::OriginType::Prompt) { + int origin = candidate.originMcRec(); + if (origin == RecoDecay::OriginType::Prompt) { if ((candidate.isSelXicToPKPi() >= selectionFlagXic) && pdgCodeProng0 == kProton) { registry.fill(HIST("MC/reconstructed/prompt/hMassRecSigPrompt"), massXicToPKPi); registry.fill(HIST("MC/reconstructed/prompt/hMassVsPtRecSigPrompt"), massXicToPKPi, ptCandidate); @@ -489,19 +487,9 @@ struct HfTaskXic { } if (enableTHn) { - double massXic(-1); double outputBkg(-1), outputPrompt(-1), outputFD(-1); const int ternaryCl = 3; - bool allProngsInAcceptance = false; if ((candidate.isSelXicToPKPi() >= selectionFlagXic) && pdgCodeProng0 == kProton) { - massXic = hfHelper.invMassXicToPKPi(candidate); - int counter = 0; - for (const auto& daught : mcParticleProng0.template daughters_as>()) { - ptProngs[counter] = daught.pt(); - etaProngs[counter] = daught.eta(); - counter++; - } - allProngsInAcceptance = isProngInAcceptance(etaProngs[0], ptProngs[0]) && isProngInAcceptance(etaProngs[1], ptProngs[1]) && isProngInAcceptance(etaProngs[2], ptProngs[2]); if constexpr (useMl) { if (candidate.mlProbXicToPKPi().size() == ternaryCl) { outputBkg = candidate.mlProbXicToPKPi()[0]; /// bkg score @@ -509,20 +497,12 @@ struct HfTaskXic { outputFD = candidate.mlProbXicToPKPi()[2]; /// non-prompt score } /// Fill the ML outputScores and variables of candidate (todo: add multiplicity) - registry.get(HIST("hnXicVarsWithBdt"))->Fill(massXic, ptCandidate, outputBkg, outputPrompt, outputFD, candidate.originMcRec(), mcParticleProng0.pt(), yProng0, allProngsInAcceptance); + registry.get(HIST("hnXicVarsWithBdt"))->Fill(massXicToPKPi, ptCandidate, outputBkg, outputPrompt, outputFD, origin); } else { - registry.get(HIST("hnXicVars"))->Fill(massXic, ptCandidate, candidate.chi2PCA(), candidate.decayLength(), candidate.decayLengthXY(), candidate.cpa(), candidate.originMcRec(), mcParticleProng0.pt(), yProng0, allProngsInAcceptance); + registry.get(HIST("hnXicVars"))->Fill(massXicToPKPi, ptCandidate, candidate.chi2PCA(), candidate.decayLength(), candidate.decayLengthXY(), candidate.cpa(), origin); } } if ((candidate.isSelXicToPiKP() >= selectionFlagXic) && pdgCodeProng0 == kPiPlus) { - massXic = hfHelper.invMassXicToPiKP(candidate); - int counter = 0; - for (const auto& daught : mcParticleProng0.template daughters_as>()) { - ptProngs[counter] = daught.pt(); - etaProngs[counter] = daught.eta(); - counter++; - } - allProngsInAcceptance = isProngInAcceptance(etaProngs[0], ptProngs[0]) && isProngInAcceptance(etaProngs[1], ptProngs[1]) && isProngInAcceptance(etaProngs[2], ptProngs[2]); if constexpr (useMl) { if (candidate.mlProbXicToPiKP().size() == ternaryCl) { outputBkg = candidate.mlProbXicToPiKP()[0]; /// bkg score @@ -531,9 +511,9 @@ struct HfTaskXic { } /// Fill the ML outputScores and variables of candidate (todo: add multiplicity) // add here the pT_Mother, y_Mother, level (reco, Gen, Gen + Acc) - registry.get(HIST("hnXicVarsWithBdt"))->Fill(massXic, ptCandidate, outputBkg, outputPrompt, outputFD, candidate.originMcRec(), mcParticleProng0.pt(), yProng0, allProngsInAcceptance); + registry.get(HIST("hnXicVarsWithBdt"))->Fill(massXicToPiKP, ptCandidate, outputBkg, outputPrompt, outputFD, origin); } else { - registry.get(HIST("hnXicVars"))->Fill(massXic, ptCandidate, candidate.chi2PCA(), candidate.decayLength(), candidate.decayLengthXY(), candidate.cpa(), candidate.originMcRec(), mcParticleProng0.pt(), yProng0, allProngsInAcceptance); + registry.get(HIST("hnXicVars"))->Fill(massXicToPiKP, ptCandidate, candidate.chi2PCA(), candidate.decayLength(), candidate.decayLengthXY(), candidate.cpa(), origin); } } } // enable THn From 93dfe3e8dd726632180654c42033d5156b716876 Mon Sep 17 00:00:00 2001 From: Daiki Sekihata Date: Tue, 17 Jun 2025 22:04:47 +0200 Subject: [PATCH 117/871] [PWGEM/Dilepton] quick fix in dimuon analysis (#11656) --- PWGEM/Dilepton/Core/DimuonCut.cxx | 5 +- PWGEM/Dilepton/Core/DimuonCut.h | 4 +- PWGEM/Dilepton/Core/SingleTrackQC.h | 14 +- PWGEM/Dilepton/Core/SingleTrackQCMC.h | 14 +- .../TableProducer/skimmerPrimaryMuon.cxx | 25 +-- .../treeCreatorElectronMLDDA.cxx | 166 +++++++++++++++--- PWGEM/Dilepton/Tasks/eventQC.cxx | 55 ++++-- PWGEM/Dilepton/Utils/EMTrackUtilities.h | 1 + 8 files changed, 212 insertions(+), 72 deletions(-) diff --git a/PWGEM/Dilepton/Core/DimuonCut.cxx b/PWGEM/Dilepton/Core/DimuonCut.cxx index 96f00f8b7a5..ef5e44123aa 100644 --- a/PWGEM/Dilepton/Core/DimuonCut.cxx +++ b/PWGEM/Dilepton/Core/DimuonCut.cxx @@ -13,9 +13,12 @@ // Class for dimuon Cut // -#include "Framework/Logger.h" #include "PWGEM/Dilepton/Core/DimuonCut.h" +#include "Framework/Logger.h" + +#include + ClassImp(DimuonCut); void DimuonCut::SetMassRange(float min, float max) diff --git a/PWGEM/Dilepton/Core/DimuonCut.h b/PWGEM/Dilepton/Core/DimuonCut.h index bc638c5a7b6..9e97f7c5859 100644 --- a/PWGEM/Dilepton/Core/DimuonCut.h +++ b/PWGEM/Dilepton/Core/DimuonCut.h @@ -194,10 +194,10 @@ class DimuonCut : public TNamed return track.nClusters() >= mMinNClustersMCHMID; case DimuonCuts::kChi2: - return track.chi2() < mMaxChi2; + return track.chi2() / (2.f * (track.nClusters() + track.nClustersMFT()) - 5.f) < mMaxChi2; case DimuonCuts::kMatchingChi2MCHMFT: - return track.chi2MatchMCHMFT() / (2.f * (track.nClusters() + track.nClustersMFT()) - 5.f) < mMaxMatchingChi2MCHMFT; + return track.chi2MatchMCHMFT() < mMaxMatchingChi2MCHMFT; case DimuonCuts::kMatchingChi2MCHMID: return track.chi2MatchMCHMID() < mMaxMatchingChi2MCHMID; diff --git a/PWGEM/Dilepton/Core/SingleTrackQC.h b/PWGEM/Dilepton/Core/SingleTrackQC.h index fddb2f1fb11..0f6da8285dd 100644 --- a/PWGEM/Dilepton/Core/SingleTrackQC.h +++ b/PWGEM/Dilepton/Core/SingleTrackQC.h @@ -300,9 +300,9 @@ struct SingleTrackQC { fRegistry.add("Track/positive/hNclsMCH", "number of MCH clusters", kTH1F, {{21, -0.5, 20.5}}, false); fRegistry.add("Track/positive/hNclsMFT", "number of MFT clusters", kTH1F, {{11, -0.5, 10.5}}, false); fRegistry.add("Track/positive/hPDCA", "pDCA;R at absorber end (cm);p #times DCA (GeV/c #upoint cm)", kTH2F, {{100, 0, 100}, {100, 0.0f, 1000}}, false); - fRegistry.add("Track/positive/hChi2", "chi2;chi2", kTH1F, {{100, 0.0f, 100}}, false); - fRegistry.add("Track/positive/hChi2MatchMCHMID", "chi2 match MCH-MID;chi2", kTH1F, {{100, 0.0f, 10}}, false); - fRegistry.add("Track/positive/hChi2MatchMCHMFT", "chi2 match MCH-MFT;chi2/ndf", kTH1F, {{100, 0.0f, 10}}, false); + fRegistry.add("Track/positive/hChi2", "chi2;chi2/ndf", kTH1F, {{100, 0.0f, 10}}, false); + fRegistry.add("Track/positive/hChi2MatchMCHMID", "chi2 match MCH-MID;chi2", kTH1F, {{100, 0.0f, 100}}, false); + fRegistry.add("Track/positive/hChi2MatchMCHMFT", "chi2 match MCH-MFT;chi2", kTH1F, {{100, 0.0f, 100}}, false); fRegistry.add("Track/positive/hMFTClusterMap", "MFT cluster map", kTH1F, {{1024, -0.5, 1023.5}}, false); fRegistry.addClone("Track/positive/", "Track/negative/"); } @@ -590,9 +590,9 @@ struct SingleTrackQC { fRegistry.fill(HIST("Track/positive/hNclsMCH"), track.nClusters()); fRegistry.fill(HIST("Track/positive/hNclsMFT"), track.nClustersMFT()); fRegistry.fill(HIST("Track/positive/hPDCA"), track.rAtAbsorberEnd(), track.pDca()); - fRegistry.fill(HIST("Track/positive/hChi2"), track.chi2()); + fRegistry.fill(HIST("Track/positive/hChi2"), track.trackType() == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) ? track.chi2() / (2.f * (track.nClusters() + track.nClustersMFT()) - 5.f) : track.chi2()); fRegistry.fill(HIST("Track/positive/hChi2MatchMCHMID"), track.chi2MatchMCHMID()); - fRegistry.fill(HIST("Track/positive/hChi2MatchMCHMFT"), track.chi2MatchMCHMFT() / (2 * (track.nClusters() + track.nClustersMFT()) - 5)); + fRegistry.fill(HIST("Track/positive/hChi2MatchMCHMFT"), track.chi2MatchMCHMFT()); fRegistry.fill(HIST("Track/positive/hMFTClusterMap"), track.mftClusterMap()); } else { fRegistry.fill(HIST("Track/negative/hs"), track.pt(), track.eta(), track.phi(), dca_xy, weight); @@ -608,9 +608,9 @@ struct SingleTrackQC { fRegistry.fill(HIST("Track/negative/hNclsMCH"), track.nClusters()); fRegistry.fill(HIST("Track/negative/hNclsMFT"), track.nClustersMFT()); fRegistry.fill(HIST("Track/negative/hPDCA"), track.rAtAbsorberEnd(), track.pDca()); - fRegistry.fill(HIST("Track/negative/hChi2"), track.chi2()); + fRegistry.fill(HIST("Track/negative/hChi2"), track.trackType() == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) ? track.chi2() / (2.f * (track.nClusters() + track.nClustersMFT()) - 5.f) : track.chi2()); fRegistry.fill(HIST("Track/negative/hChi2MatchMCHMID"), track.chi2MatchMCHMID()); - fRegistry.fill(HIST("Track/negative/hChi2MatchMCHMFT"), track.chi2MatchMCHMFT() / (2 * (track.nClusters() + track.nClustersMFT()) - 5)); + fRegistry.fill(HIST("Track/negative/hChi2MatchMCHMFT"), track.chi2MatchMCHMFT()); fRegistry.fill(HIST("Track/negative/hMFTClusterMap"), track.mftClusterMap()); } } diff --git a/PWGEM/Dilepton/Core/SingleTrackQCMC.h b/PWGEM/Dilepton/Core/SingleTrackQCMC.h index 5fdd69036a8..dfcc80d32d2 100644 --- a/PWGEM/Dilepton/Core/SingleTrackQCMC.h +++ b/PWGEM/Dilepton/Core/SingleTrackQCMC.h @@ -357,9 +357,9 @@ struct SingleTrackQCMC { fRegistry.add("Track/lf/positive/hNclsMCH", "number of MCH clusters", kTH1F, {{21, -0.5, 20.5}}, false); fRegistry.add("Track/lf/positive/hNclsMFT", "number of MFT clusters", kTH1F, {{11, -0.5, 10.5}}, false); fRegistry.add("Track/lf/positive/hPDCA", "pDCA;R at absorber (cm);p #times DCA (GeV/c #upoint cm)", kTH2F, {{100, 0, 100}, {100, 0.0f, 1000}}, false); - fRegistry.add("Track/lf/positive/hChi2", "chi2;chi2", kTH1F, {{100, 0.0f, 100}}, false); - fRegistry.add("Track/lf/positive/hChi2MatchMCHMID", "chi2 match MCH-MID;chi2", kTH1F, {{100, 0.0f, 10}}, false); - fRegistry.add("Track/lf/positive/hChi2MatchMCHMFT", "chi2 match MCH-MFT;chi2/ndf", kTH1F, {{100, 0.0f, 10}}, false); + fRegistry.add("Track/lf/positive/hChi2", "chi2;chi2/ndf", kTH1F, {{100, 0.0f, 10}}, false); + fRegistry.add("Track/lf/positive/hChi2MatchMCHMID", "chi2 match MCH-MID;chi2", kTH1F, {{100, 0.0f, 100}}, false); + fRegistry.add("Track/lf/positive/hChi2MatchMCHMFT", "chi2 match MCH-MFT;chi2", kTH1F, {{100, 0.0f, 100}}, false); fRegistry.add("Track/lf/positive/hMFTClusterMap", "MFT cluster map", kTH1F, {{1024, -0.5, 1023.5}}, false); fRegistry.add("Track/lf/positive/hPtGen_DeltaPtOverPtGen", "muon p_{T} resolution;p_{T}^{gen} (GeV/c);(p_{T}^{rec} - p_{T}^{gen})/p_{T}^{gen}", kTH2F, {{200, 0, 10}, {200, -1.0f, 1.0f}}, true); fRegistry.add("Track/lf/positive/hPtGen_DeltaEta", "muon #eta resolution;p_{T}^{gen} (GeV/c);#eta^{rec} - #eta^{gen}", kTH2F, {{200, 0, 10}, {100, -0.05f, 0.05f}}, true); @@ -706,9 +706,9 @@ struct SingleTrackQCMC { fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hNclsMCH"), track.nClusters()); fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hNclsMFT"), track.nClustersMFT()); fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hPDCA"), track.rAtAbsorberEnd(), track.pDca()); - fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hChi2"), track.chi2()); + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hChi2"), track.trackType() == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) ? track.chi2() / (2.f * (track.nClusters() + track.nClustersMFT()) - 5.f) : track.chi2()); fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hChi2MatchMCHMID"), track.chi2MatchMCHMID()); - fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hChi2MatchMCHMFT"), track.chi2MatchMCHMFT() / (2 * (track.nClusters() + track.nClustersMFT() - 5))); + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hChi2MatchMCHMFT"), track.chi2MatchMCHMFT()); fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hMFTClusterMap"), track.mftClusterMap()); fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hPtGen_DeltaPtOverPtGen"), mctrack.pt(), (track.pt() - mctrack.pt()) / mctrack.pt()); fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hPtGen_DeltaEta"), mctrack.pt(), track.eta() - mctrack.eta()); @@ -729,9 +729,9 @@ struct SingleTrackQCMC { fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hNclsMCH"), track.nClusters()); fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hNclsMFT"), track.nClustersMFT()); fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hPDCA"), track.rAtAbsorberEnd(), track.pDca()); - fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hChi2"), track.chi2()); + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hChi2"), track.trackType() == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) ? track.chi2() / (2.f * (track.nClusters() + track.nClustersMFT()) - 5.f) : track.chi2()); fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hChi2MatchMCHMID"), track.chi2MatchMCHMID()); - fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hChi2MatchMCHMFT"), track.chi2MatchMCHMFT() / (2 * (track.nClusters() + track.nClustersMFT() - 5))); + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hChi2MatchMCHMFT"), track.chi2MatchMCHMFT()); fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hMFTClusterMap"), track.mftClusterMap()); fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hPtGen_DeltaPtOverPtGen"), mctrack.pt(), (track.pt() - mctrack.pt()) / mctrack.pt()); fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hPtGen_DeltaEta"), mctrack.pt(), track.eta() - mctrack.eta()); diff --git a/PWGEM/Dilepton/TableProducer/skimmerPrimaryMuon.cxx b/PWGEM/Dilepton/TableProducer/skimmerPrimaryMuon.cxx index 03189bf3f4b..47ba2a3c4ea 100644 --- a/PWGEM/Dilepton/TableProducer/skimmerPrimaryMuon.cxx +++ b/PWGEM/Dilepton/TableProducer/skimmerPrimaryMuon.cxx @@ -85,7 +85,7 @@ struct skimmerPrimaryMuon { Configurable maxPDCAforSmallR{"maxPDCAforSmallR", 594.f, "max. pDCA for small R at absorber end"}; Configurable maxMatchingChi2MCHMFT{"maxMatchingChi2MCHMFT", 50.f, "max. chi2 for MCH-MFT matching"}; Configurable maxChi2SA{"maxChi2SA", 1e+6, "max. chi2 for standalone muon"}; - Configurable maxChi2GL{"maxChi2GL", 50.f, "max. chi2 for global muon"}; + Configurable maxChi2GL{"maxChi2GL", 1e+6, "max. chi2 for global muon"}; Configurable refitGlobalMuon{"refitGlobalMuon", true, "flag to refit global muon"}; o2::ccdb::CcdbApi ccdbApi; @@ -147,11 +147,10 @@ struct skimmerPrimaryMuon { fRegistry.add("MFTMCHMID/hNclustersMFT", "NclustersMFT;Nclusters MFT", kTH1F, {{11, -0.5f, 10.5}}, false); fRegistry.add("MFTMCHMID/hRatAbsorberEnd", "R at absorber end;R at absorber end (cm)", kTH1F, {{100, 0.0f, 100}}, false); fRegistry.add("MFTMCHMID/hPDCA_Rabs", "pDCA vs. Rabs;R at absorber end (cm);p #times DCA (GeV/c #upoint cm)", kTH2F, {{100, 0, 100}, {100, 0.0f, 1000}}, false); - fRegistry.add("MFTMCHMID/hChi2", "chi2;chi2", kTH1F, {{100, 0.0f, 100}}, false); - fRegistry.add("MFTMCHMID/hChi2MFT", "chi2 MFT;chi2 MFT/ndf", kTH1F, {{100, 0.0f, 100}}, false); - fRegistry.add("MFTMCHMID/hChi2MatchMCHMID", "chi2 match MCH-MID;chi2", kTH1F, {{100, 0.0f, 10}}, false); - fRegistry.add("MFTMCHMID/hChi2MatchMCHMFT", "chi2 match MCH-MFT;chi2/ndf", kTH1F, {{100, 0.0f, 10}}, false); - fRegistry.add("MFTMCHMID/hMatchScoreMCHMFT", "match score MCH-MFT;score", kTH1F, {{100, 0.0f, 100}}, false); + fRegistry.add("MFTMCHMID/hChi2", "chi2;chi2/ndf", kTH1F, {{100, 0.0f, 10}}, false); + fRegistry.add("MFTMCHMID/hChi2MFT", "chi2 MFT;chi2 MFT/ndf", kTH1F, {{100, 0.0f, 10}}, false); + fRegistry.add("MFTMCHMID/hChi2MatchMCHMID", "chi2 match MCH-MID;chi2", kTH1F, {{100, 0.0f, 100}}, false); + fRegistry.add("MFTMCHMID/hChi2MatchMCHMFT", "chi2 match MCH-MFT;chi2", kTH1F, {{100, 0.0f, 100}}, false); fRegistry.add("MFTMCHMID/hDCAxy2D", "DCA x vs. y;DCA_{x} (cm);DCA_{y} (cm)", kTH2F, {{200, -1, 1}, {200, -1, +1}}, false); fRegistry.add("MFTMCHMID/hDCAxy2DinSigma", "DCA x vs. y in sigma;DCA_{x} (#sigma);DCA_{y} (#sigma)", kTH2F, {{200, -10, 10}, {200, -10, +10}}, false); fRegistry.add("MFTMCHMID/hDCAxy", "DCAxy;DCA_{xy} (cm);", kTH1F, {{100, 0, 1}}, false); @@ -207,7 +206,7 @@ struct skimmerPrimaryMuon { template void fillFwdTrackTable(TCollision const& collision, TFwdTrack fwdtrack, TFwdTracks const&, TMFTTracks const&, const bool isAmbiguous) { - if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && fwdtrack.chi2() > maxChi2GL) { + if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && fwdtrack.chi2MatchMCHMFT() > maxMatchingChi2MCHMFT) { return; } // Users have to decide the best match between MFT and MCH-MID at analysis level. The same global muon is repeatedly stored. @@ -274,10 +273,6 @@ struct skimmerPrimaryMuon { chi2mft = mfttrack.chi2() / (2.f * nClustersMFT - 5.f); ndf_mchmft = 2.f * (mchtrack.nClusters() + nClustersMFT) - 5.f; - if (fwdtrack.chi2MatchMCHMFT() / ndf_mchmft > maxMatchingChi2MCHMFT) { - return; - } - if (refitGlobalMuon) { eta = mfttrack.eta(); phi = mfttrack.phi(); @@ -346,11 +341,10 @@ struct skimmerPrimaryMuon { fRegistry.fill(HIST("MFTMCHMID/hNclustersMFT"), nClustersMFT); fRegistry.fill(HIST("MFTMCHMID/hPDCA_Rabs"), rAtAbsorberEnd, pDCA); fRegistry.fill(HIST("MFTMCHMID/hRatAbsorberEnd"), rAtAbsorberEnd); - fRegistry.fill(HIST("MFTMCHMID/hChi2"), fwdtrack.chi2()); + fRegistry.fill(HIST("MFTMCHMID/hChi2"), fwdtrack.chi2() / ndf_mchmft); fRegistry.fill(HIST("MFTMCHMID/hChi2MFT"), chi2mft); fRegistry.fill(HIST("MFTMCHMID/hChi2MatchMCHMID"), fwdtrack.chi2MatchMCHMID()); - fRegistry.fill(HIST("MFTMCHMID/hChi2MatchMCHMFT"), fwdtrack.chi2MatchMCHMFT() / ndf_mchmft); - fRegistry.fill(HIST("MFTMCHMID/hMatchScoreMCHMFT"), fwdtrack.matchScoreMCHMFT()); + fRegistry.fill(HIST("MFTMCHMID/hChi2MatchMCHMFT"), fwdtrack.chi2MatchMCHMFT()); fRegistry.fill(HIST("MFTMCHMID/hDCAxy2D"), dcaX, dcaY); fRegistry.fill(HIST("MFTMCHMID/hDCAxy2DinSigma"), dcaX / std::sqrt(cXXatDCA), dcaY / std::sqrt(cYYatDCA)); fRegistry.fill(HIST("MFTMCHMID/hDCAxy"), dcaXY); @@ -373,8 +367,7 @@ struct skimmerPrimaryMuon { fRegistry.fill(HIST("MCHMID/hChi2"), fwdtrack.chi2()); fRegistry.fill(HIST("MCHMID/hChi2MFT"), chi2mft); fRegistry.fill(HIST("MCHMID/hChi2MatchMCHMID"), fwdtrack.chi2MatchMCHMID()); - fRegistry.fill(HIST("MCHMID/hChi2MatchMCHMFT"), 0.f); - fRegistry.fill(HIST("MCHMID/hMatchScoreMCHMFT"), 0.f); + fRegistry.fill(HIST("MCHMID/hChi2MatchMCHMFT"), fwdtrack.chi2MatchMCHMFT()); fRegistry.fill(HIST("MCHMID/hDCAxy2D"), dcaX, dcaY); fRegistry.fill(HIST("MCHMID/hDCAxy2DinSigma"), dcaX / std::sqrt(cXXatDCA), dcaY / std::sqrt(cYYatDCA)); fRegistry.fill(HIST("MCHMID/hDCAxy"), dcaXY); diff --git a/PWGEM/Dilepton/TableProducer/treeCreatorElectronMLDDA.cxx b/PWGEM/Dilepton/TableProducer/treeCreatorElectronMLDDA.cxx index a0c7b6362f7..b94716a5fda 100644 --- a/PWGEM/Dilepton/TableProducer/treeCreatorElectronMLDDA.cxx +++ b/PWGEM/Dilepton/TableProducer/treeCreatorElectronMLDDA.cxx @@ -14,36 +14,40 @@ // This code will create data table for inputs to machine learning for electrons. // Please write to: daiki.sekihata@cern.ch -#include -#include -#include -#include -#include "Math/Vector4D.h" -#include "DCAFitter/DCAFitterN.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.h" -#include "ReconstructionDataFormats/Track.h" -#include "Common/Core/trackUtilities.h" -#include "Common/Core/TrackSelection.h" +#include "PWGEM/Dilepton/DataModel/lmeeMLTables.h" +#include "PWGEM/Dilepton/Utils/PairUtilities.h" +#include "PWGEM/PhotonMeson/Utils/PCMUtilities.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" + +#include "Common/CCDB/RCTSelectionFlags.h" #include "Common/Core/RecoDecay.h" -#include "Common/DataModel/TrackSelectionTables.h" +#include "Common/Core/TrackSelection.h" +#include "Common/Core/trackUtilities.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/PIDResponse.h" -#include "Common/CCDB/RCTSelectionFlags.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include "CCDB/BasicCCDBManager.h" #include "CommonConstants/PhysicsConstants.h" -#include "DetectorsBase/Propagator.h" -#include "DetectorsBase/GeometryManager.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DataFormatsParameters/GRPMagField.h" +#include "DCAFitter/DCAFitterN.h" #include "DataFormatsCalibration/MeanVertexObject.h" -#include "CCDB/BasicCCDBManager.h" -#include "PWGEM/Dilepton/DataModel/lmeeMLTables.h" -#include "PWGEM/Dilepton/Utils/PairUtilities.h" -#include "PWGEM/PhotonMeson/Utils/PCMUtilities.h" -#include "PWGLF/DataModel/LFStrangenessTables.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "DataFormatsParameters/GRPObject.h" +#include "DetectorsBase/GeometryManager.h" +#include "DetectorsBase/Propagator.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" +#include "ReconstructionDataFormats/Track.h" + +#include "Math/Vector4D.h" + +#include +#include +#include +#include using namespace o2; using namespace o2::framework; @@ -131,6 +135,32 @@ struct TreeCreatorElectronMLDDA { Configurable max_pin_for_downscaling_proton{"max_pin_for_downscaling_proton", 2.0, "max pin 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"}; + struct : ConfigurableGroup { + std::string prefix = "eventcut_group"; + Configurable cfgZvtxMin{"cfgZvtxMin", -10.f, "min. Zvtx"}; + Configurable cfgZvtxMax{"cfgZvtxMax", 10.f, "max. Zvtx"}; + Configurable cfgRequireSel8{"cfgRequireSel8", true, "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 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"}; + Configurable cfgRequireGoodZvtxFT0vsPV{"cfgRequireGoodZvtxFT0vsPV", false, "require good Zvtx between FT0 vs. PV in event cut"}; + Configurable cfgTrackOccupancyMin{"cfgTrackOccupancyMin", -2, "min. track occupancy"}; + Configurable cfgTrackOccupancyMax{"cfgTrackOccupancyMax", 1000000000, "max. track occupancy"}; + Configurable cfgFT0COccupancyMin{"cfgFT0COccupancyMin", -2, "min. FT0C occupancy"}; + Configurable cfgFT0COccupancyMax{"cfgFT0COccupancyMax", 1000000000, "max. FT0C occupancy"}; + Configurable cfgRequireNoCollInTimeRangeStandard{"cfgRequireNoCollInTimeRangeStandard", false, "require no collision in time range standard"}; + Configurable cfgRequireNoCollInTimeRangeStrict{"cfgRequireNoCollInTimeRangeStrict", false, "require no collision in time range strict"}; + Configurable cfgRequirekNoCollInRofStandard{"cfgRequirekNoCollInRofStandard", false, "require no other collisions in this Readout Frame with per-collision multiplicity above threshold"}; + Configurable cfgRequirekNoCollInRofStrict{"cfgRequirekNoCollInRofStrict", false, "require no other collisions in this Readout Frame"}; + Configurable cfgRequirekNoHighMultCollInPrevRof{"cfgRequirekNoHighMultCollInPrevRof", false, "require no HM collision in previous ITS ROF"}; + Configurable cfgRequireGoodITSLayer3{"cfgRequireGoodITSLayer3", false, "number of inactive chips on ITS layer 3 are below threshold "}; + Configurable cfgRequireGoodITSLayer0123{"cfgRequireGoodITSLayer0123", false, "number of inactive chips on ITS layers 0-3 are below threshold "}; + Configurable cfgRequireGoodITSLayersAll{"cfgRequireGoodITSLayersAll", false, "number of inactive chips on all ITS layers are below threshold "}; + } eventcuts; + struct : ConfigurableGroup { std::string prefix = "trackcut_group"; Configurable cfg_min_pt{"cfg_min_pt", 0.05, "min pt for v0 legs"}; @@ -543,6 +573,88 @@ struct TreeCreatorElectronMLDDA { } } + template + bool isSelectedEvent(TCollision const& collision) + { + if (eventcuts.cfgRequireSel8 && !collision.sel8()) { + return false; + } + + if (collision.posZ() < eventcuts.cfgZvtxMin || eventcuts.cfgZvtxMax < collision.posZ()) { + return false; + } + + if (eventcuts.cfgRequireFT0AND && !collision.selection_bit(o2::aod::evsel::kIsTriggerTVX)) { + return false; + } + + if (eventcuts.cfgRequireNoTFB && !collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)) { + return false; + } + + if (eventcuts.cfgRequireNoITSROFB && !collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { + return false; + } + + if (eventcuts.cfgRequireVertexITSTPC && !collision.selection_bit(o2::aod::evsel::kIsVertexITSTPC)) { + return false; + } + + if (eventcuts.cfgRequireVertexTOFmatched && !collision.selection_bit(o2::aod::evsel::kIsVertexTOFmatched)) { + return false; + } + + if (eventcuts.cfgRequireNoSameBunchPileup && !collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { + return false; + } + + if (eventcuts.cfgRequireGoodZvtxFT0vsPV && !collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { + return false; + } + + if (eventcuts.cfgRequireNoCollInTimeRangeStandard && !collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { + return false; + } + + if (eventcuts.cfgRequireNoCollInTimeRangeStrict && !collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStrict)) { + return false; + } + + if (eventcuts.cfgRequirekNoCollInRofStandard && !collision.selection_bit(o2::aod::evsel::kNoCollInRofStandard)) { + return false; + } + + if (eventcuts.cfgRequirekNoCollInRofStrict && !collision.selection_bit(o2::aod::evsel::kNoCollInRofStrict)) { + return false; + } + + if (eventcuts.cfgRequirekNoHighMultCollInPrevRof && !collision.selection_bit(o2::aod::evsel::kNoHighMultCollInPrevRof)) { + return false; + } + + if (eventcuts.cfgRequireGoodITSLayer3 && !collision.selection_bit(o2::aod::evsel::kIsGoodITSLayer3)) { + return false; + } + + if (eventcuts.cfgRequireGoodITSLayer0123 && !collision.selection_bit(o2::aod::evsel::kIsGoodITSLayer0123)) { + return false; + } + + if (eventcuts.cfgRequireGoodITSLayersAll && !collision.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { + return false; + } + + if (!(eventcuts.cfgTrackOccupancyMin <= collision.trackOccupancyInTimeRange() && collision.trackOccupancyInTimeRange() < eventcuts.cfgTrackOccupancyMax)) { + return false; + } + + if (!(eventcuts.cfgFT0COccupancyMin <= collision.ft0cOccupancyInTimeRange() && collision.ft0cOccupancyInTimeRange() < eventcuts.cfgFT0COccupancyMax)) { + return false; + } + + return true; + } + //! type of V0. 0: built solely for cascades (does not pass standard V0 cuts), 1: standard 2, 3: photon-like with TPC-only use. Regular analysis should always use type 1. Filter v0Filter = o2::aod::v0data::v0Type == uint8_t(1) && o2::aod::v0data::v0cosPA > v0cuts.cfg_min_cospa.value&& o2::aod::v0data::dcaV0daughters v0cuts.cfg_min_dcaxy_v0leg&& nabs(o2::aod::v0data::dcanegtopv) > v0cuts.cfg_min_dcaxy_v0leg; using filteredV0s = soa::Filtered; @@ -550,6 +662,8 @@ struct TreeCreatorElectronMLDDA { Filter cascadeFilter = o2::aod::cascdata::dcacascdaughters < cascadecuts.cfg_max_dcadau.value && nabs(o2::aod::cascdata::dcanegtopv) > cascadecuts.cfg_min_dcaxy_v0leg&& nabs(o2::aod::cascdata::dcanegtopv) > cascadecuts.cfg_min_dcaxy_v0leg&& nabs(o2::aod::cascdata::dcabachtopv) > cascadecuts.cfg_min_dcaxy_bachelor; using filteredCascades = soa::Filtered; + Filter collisionFilter_track_occupancy = eventcuts.cfgTrackOccupancyMin <= o2::aod::evsel::trackOccupancyInTimeRange && o2::aod::evsel::trackOccupancyInTimeRange < eventcuts.cfgTrackOccupancyMax; + Filter collisionFilter_ft0c_occupancy = eventcuts.cfgFT0COccupancyMin <= o2::aod::evsel::ft0cOccupancyInTimeRange && o2::aod::evsel::ft0cOccupancyInTimeRange < eventcuts.cfgFT0COccupancyMax; Filter collisionFilter_common = nabs(o2::aod::collision::posZ) < 10.f && o2::aod::evsel::sel8 == true; using filteredMyCollisions = soa::Filtered; @@ -570,6 +684,10 @@ struct TreeCreatorElectronMLDDA { auto bc = collision.template foundBC_as(); initCCDB(bc); + if (!isSelectedEvent(collision)) { + continue; + } + if (cfgRequireGoodRCT && !rctChecker.checkTable(collision)) { continue; } diff --git a/PWGEM/Dilepton/Tasks/eventQC.cxx b/PWGEM/Dilepton/Tasks/eventQC.cxx index afd65dbbe7e..062d9cb0577 100644 --- a/PWGEM/Dilepton/Tasks/eventQC.cxx +++ b/PWGEM/Dilepton/Tasks/eventQC.cxx @@ -14,29 +14,32 @@ // This code is for event QC for PWG-EM. // Please write to: daiki.sekihata@cern.ch -#include -#include -#include -#include -#include +#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" -#include "TString.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/ASoAHelpers.h" #include "Common/Core/RecoDecay.h" -#include "MathUtils/Utils.h" -#include "Framework/AnalysisDataModel.h" +#include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/Centrality.h" -#include "Common/DataModel/Qvectors.h" #include "Common/DataModel/PIDResponse.h" #include "Common/DataModel/PIDResponseITS.h" +#include "Common/DataModel/Qvectors.h" #include "Common/DataModel/TrackSelectionTables.h" + #include "CCDB/BasicCCDBManager.h" -#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" -#include "PWGLF/DataModel/LFStrangenessTables.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" +#include "MathUtils/Utils.h" + +#include "TString.h" + +#include +#include +#include +#include +#include using namespace o2; using namespace o2::aod; @@ -80,6 +83,8 @@ struct eventQC { 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 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"}; Configurable cfgRequireGoodZvtxFT0vsPV{"cfgRequireGoodZvtxFT0vsPV", false, "require good Zvtx between FT0 vs. PV in event cut"}; Configurable cfgTrackOccupancyMin{"cfgTrackOccupancyMin", -2, "min. track occupancy"}; @@ -152,6 +157,13 @@ struct eventQC { Configurable cfg_max_TOFNsigmaPi{"cfg_max_TOFNsigmaPi", +2, "max n sigma pi in TOF"}; } v0cuts; + // for RCT + Configurable cfgRequireGoodRCT{"cfgRequireGoodRCT", false, "require good detector flag in run condtion table"}; + Configurable cfgRCTLabel{"cfgRCTLabel", "CBT_hadron", "select 1 [CBT, CBT_hadron, CBT_muon_glo] see O2Physics/Common/CCDB/RCTSelectionFlags.h"}; + Configurable cfgCheckZDC{"cfgCheckZDC", false, "set ZDC flag for PbPb"}; + Configurable cfgTreatLimitedAcceptanceAsBad{"cfgTreatLimitedAcceptanceAsBad", false, "reject all events where the detectors relevant for the specified Runlist are flagged as LimitedAcceptance"}; + o2::aod::rctsel::RCTFlagsChecker rctChecker; + Service ccdb; HistogramRegistry fRegistry{"output", {}, OutputObjHandlingPolicy::AnalysisObject, false, false}; @@ -163,6 +175,8 @@ struct eventQC { ccdb->setCaching(true); ccdb->setLocalObjectValidityChecking(); ccdb->setFatalWhenNull(false); + rctChecker.init(cfgRCTLabel.value, cfgCheckZDC.value, cfgTreatLimitedAcceptanceAsBad.value); + addhistograms(); if (doprocessEventQC_V0_PID) { addV0histograms(); @@ -795,6 +809,14 @@ struct eventQC { return false; } + if (eventcuts.cfgRequireVertexITSTPC && !collision.selection_bit(o2::aod::evsel::kIsVertexITSTPC)) { + return false; + } + + if (eventcuts.cfgRequireVertexTOFmatched && !collision.selection_bit(o2::aod::evsel::kIsVertexTOFmatched)) { + return false; + } + if (eventcuts.cfgRequireNoSameBunchPileup && !collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { return false; } @@ -873,6 +895,9 @@ struct eventQC { if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) { continue; } + if (cfgRequireGoodRCT && !rctChecker.checkTable(collision)) { + continue; + } if (cfgFillEvent) { fillEventInfo<0>(collision); } diff --git a/PWGEM/Dilepton/Utils/EMTrackUtilities.h b/PWGEM/Dilepton/Utils/EMTrackUtilities.h index b3712d9e45d..d698bdbf68c 100644 --- a/PWGEM/Dilepton/Utils/EMTrackUtilities.h +++ b/PWGEM/Dilepton/Utils/EMTrackUtilities.h @@ -16,6 +16,7 @@ #define PWGEM_DILEPTON_UTILS_EMTRACKUTILITIES_H_ #include "Framework/DataTypes.h" +#include "Framework/Logger.h" #include #include From fb549b33065f79d8a67ae0c511c7fa7c01cf3e68 Mon Sep 17 00:00:00 2001 From: Fabrizio Chinu <91954233+fchinu@users.noreply.github.com> Date: Tue, 17 Jun 2025 23:33:59 +0200 Subject: [PATCH 118/871] [PWGHF] Fix sparses filling in B reduced tasks (#11648) --- PWGHF/D2H/Tasks/taskB0Reduced.cxx | 29 ++++++++++++++++++++++------- PWGHF/D2H/Tasks/taskBsReduced.cxx | 29 ++++++++++++++++++++++------- 2 files changed, 44 insertions(+), 14 deletions(-) diff --git a/PWGHF/D2H/Tasks/taskB0Reduced.cxx b/PWGHF/D2H/Tasks/taskB0Reduced.cxx index 87138a813bc..c917abb8776 100644 --- a/PWGHF/D2H/Tasks/taskB0Reduced.cxx +++ b/PWGHF/D2H/Tasks/taskB0Reduced.cxx @@ -15,16 +15,31 @@ /// \author Alexandre Bigot , IPHC Strasbourg /// \author Fabrizio Grosa , CERN +#include "PWGHF/Core/HfHelper.h" +#include "PWGHF/D2H/DataModel/ReducedDataModel.h" +#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "PWGHF/DataModel/CandidateSelectionTables.h" + +#include "Common/Core/RecoDecay.h" + #include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" #include "Framework/runDataProcessing.h" -#include "Common/Core/RecoDecay.h" +#include +#include +#include +#include +#include +#include -#include "PWGHF/Core/HfHelper.h" -#include "PWGHF/Core/SelectorCuts.h" -#include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" -#include "PWGHF/D2H/DataModel/ReducedDataModel.h" +#include +#include + +#include + +#include +#include +#include using namespace o2; using namespace o2::aod; @@ -506,7 +521,7 @@ struct HfTaskB0Reduced { } } if (fillSparses) { - if constexpr (withDmesMl) { + if constexpr (doMc) { if (isSignal) { if constexpr (withDmesMl) { registry.fill(HIST("hMassPtCutVarsRecSig"), invMassB0, ptCandB0, candidate.decayLength(), candidate.decayLengthXY() / candidate.errorDecayLengthXY(), candidate.impactParameterProduct(), candidate.cpa(), invMassD, ptD, candidate.prong0MlScoreBkg(), candidate.prong0MlScoreNonprompt()); diff --git a/PWGHF/D2H/Tasks/taskBsReduced.cxx b/PWGHF/D2H/Tasks/taskBsReduced.cxx index e892a526831..9a41a7a40d2 100644 --- a/PWGHF/D2H/Tasks/taskBsReduced.cxx +++ b/PWGHF/D2H/Tasks/taskBsReduced.cxx @@ -14,16 +14,31 @@ /// /// \author Fabio Catalano , CERN +#include "PWGHF/Core/HfHelper.h" +#include "PWGHF/D2H/DataModel/ReducedDataModel.h" +#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "PWGHF/DataModel/CandidateSelectionTables.h" + +#include "Common/Core/RecoDecay.h" + #include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" #include "Framework/runDataProcessing.h" -#include "Common/Core/RecoDecay.h" +#include +#include +#include +#include +#include +#include -#include "PWGHF/Core/HfHelper.h" -#include "PWGHF/Core/SelectorCuts.h" -#include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" -#include "PWGHF/D2H/DataModel/ReducedDataModel.h" +#include +#include + +#include + +#include +#include +#include using namespace o2; using namespace o2::aod; @@ -453,7 +468,7 @@ struct HfTaskBsReduced { } } if (fillSparses) { - if constexpr (withDmesMl) { + if constexpr (doMc) { if (isSignal) { if constexpr (withDmesMl) { registry.fill(HIST("hMassPtCutVarsRecSig"), invMassBs, ptCandBs, candidate.decayLength(), candidate.decayLengthXY() / candidate.errorDecayLengthXY(), candidate.impactParameterProduct(), candidate.cpa(), invMassDs, ptDs, candidate.prong0MlScoreBkg(), candidate.prong0MlScoreNonprompt()); From 64ea85fb1aaf68febfce9e572c3f2ba6611489be Mon Sep 17 00:00:00 2001 From: omvazque Date: Tue, 17 Jun 2025 17:07:17 -0500 Subject: [PATCH 119/871] [PWGLF] Update on Nch-dependet corrections (#11662) --- PWGLF/Tasks/GlobalEventProperties/uccZdc.cxx | 114 +++++++++++-------- 1 file changed, 65 insertions(+), 49 deletions(-) diff --git a/PWGLF/Tasks/GlobalEventProperties/uccZdc.cxx b/PWGLF/Tasks/GlobalEventProperties/uccZdc.cxx index 02874f91014..12dd8e34fa6 100644 --- a/PWGLF/Tasks/GlobalEventProperties/uccZdc.cxx +++ b/PWGLF/Tasks/GlobalEventProperties/uccZdc.cxx @@ -173,7 +173,7 @@ struct UccZdc { // define axes you want to use const AxisSpec axisZpos{48, -12., 12., "Vtx_{z} (cm)"}; const AxisSpec axisEvent{18, 0.5, 18.5, ""}; - const AxisSpec axisEta{30, -1.05, +1.05, "#eta"}; + const AxisSpec axisEta{40, -1., +1., "#eta"}; const AxisSpec axisPt{binsPt, "#it{p}_{T} (GeV/#it{c})"}; const AxisSpec axisDeltaPt{100, -1.0, +1.0, "#Delta(p_{T})"}; const AxisSpec axisCent{binsCent, "T0C centrality"}; @@ -245,27 +245,25 @@ struct UccZdc { registry.add("NchVsThreeParCorr", "MC closure;#it{N}_{ch} (|#eta| < 0.8, Corrected);#LT[#it{p}_{T}^{(3)}]#GT", kTProfile, {{nBinsNch, minNch, maxNch}}); registry.add("NchVsFourParCorr", "MC closure;#it{N}_{ch} (|#eta| < 0.8, Corrected);#LT[#it{p}_{T}^{(4)}]#GT", kTProfile, {{nBinsNch, minNch, maxNch}}); // Corrections - registry.add("NchRec", "Corrections;#it{N}_{ch} (|#eta| < 0.8);Entries;", kTH1F, {{nBinsNch, minNch, maxNch}}); - registry.add("NchTrue", "Corrections;#it{N}_{ch} (|#eta| < 0.8);Entries;", kTH1F, {{nBinsNch, minNch, maxNch}}); - registry.add("zPosMC", "Filled at MC closure + Corrections;;Entries;", kTH1F, {axisZpos}); registry.add("hEventCounterMC", "Event counter", kTH1F, {axisEvent}); registry.add("nRecColvsCent", "", kTH2F, {{6, -0.5, 5.5}, {{axisCent}}}); - registry.add("Pt_all_ch", "Corrections;;;", kTH2F, {{axisCent}, {axisPt}}); - registry.add("Pt_ch", "Corrections;;;", kTH2F, {{axisCent}, {axisPt}}); - registry.add("Pt_pi", "Corrections;;;", kTH2F, {{axisCent}, {axisPt}}); - registry.add("Pt_ka", "Corrections;;;", kTH2F, {{axisCent}, {axisPt}}); - registry.add("Pt_pr", "Corrections;;;", kTH2F, {{axisCent}, {axisPt}}); - registry.add("Pt_sigpos", "Corrections;;;", kTH2F, {{axisCent}, {axisPt}}); - registry.add("Pt_signeg", "Corrections;;;", kTH2F, {{axisCent}, {axisPt}}); - registry.add("Pt_re", "Corrections;;;", kTH2F, {{axisCent}, {axisPt}}); - registry.add("PtMC_ch", "Corrections;;;", kTH2F, {{axisCent}, {axisPt}}); - registry.add("PtMC_pi", "Corrections;;;", kTH2F, {{axisCent}, {axisPt}}); - registry.add("PtMC_ka", "Corrections;;;", kTH2F, {{axisCent}, {axisPt}}); - registry.add("PtMC_pr", "Corrections;;;", kTH2F, {{axisCent}, {axisPt}}); - registry.add("PtMC_sigpos", "Corrections;;;", kTH2F, {{axisCent}, {axisPt}}); - registry.add("PtMC_signeg", "Corrections;;;", kTH2F, {{axisCent}, {axisPt}}); - registry.add("PtMC_re", "Corrections;;;", kTH2F, {{axisCent}, {axisPt}}); + registry.add("Pt_all_ch", "Corrections;#it{N}_{ch} (|#eta|<0.8);;", kTH2F, {{nBinsNch, minNch, maxNch}, {axisPt}}); + registry.add("Pt_ch", "Corrections;#it{N}_{ch} (|#eta|<0.8);;", kTH2F, {{nBinsNch, minNch, maxNch}, {axisPt}}); + registry.add("Pt_pi", "Corrections;#it{N}_{ch} (|#eta|<0.8);;", kTH2F, {{nBinsNch, minNch, maxNch}, {axisPt}}); + registry.add("Pt_ka", "Corrections;#it{N}_{ch} (|#eta|<0.8);;", kTH2F, {{nBinsNch, minNch, maxNch}, {axisPt}}); + registry.add("Pt_pr", "Corrections;#it{N}_{ch} (|#eta|<0.8);;", kTH2F, {{nBinsNch, minNch, maxNch}, {axisPt}}); + registry.add("Pt_sigpos", "Corrections;;;", kTH2F, {{nBinsNch, minNch, maxNch}, {axisPt}}); + registry.add("Pt_signeg", "Corrections;;;", kTH2F, {{nBinsNch, minNch, maxNch}, {axisPt}}); + registry.add("Pt_re", "Corrections;;;", kTH2F, {{nBinsNch, minNch, maxNch}, {axisPt}}); + registry.add("PtMC_ch", "Corrections;;;", kTH2F, {{nBinsNch, minNch, maxNch}, {axisPt}}); + registry.add("PtMC_pi", "Corrections;;;", kTH2F, {{nBinsNch, minNch, maxNch}, {axisPt}}); + registry.add("PtMC_ka", "Corrections;;;", kTH2F, {{nBinsNch, minNch, maxNch}, {axisPt}}); + registry.add("PtMC_pr", "Corrections;;;", kTH2F, {{nBinsNch, minNch, maxNch}, {axisPt}}); + registry.add("PtMC_sigpos", "Corrections;;;", kTH2F, {{nBinsNch, minNch, maxNch}, {axisPt}}); + registry.add("PtMC_signeg", "Corrections;;;", kTH2F, {{nBinsNch, minNch, maxNch}, {axisPt}}); + registry.add("PtMC_re", "Corrections;;;", kTH2F, {{nBinsNch, minNch, maxNch}, {axisPt}}); + registry.add("McNchVsFT0M", ";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., maxAmpFT0}, {nBinsNch, minNch, maxNch}}}); auto hECMC = registry.get(HIST("hEventCounterMC")); auto* x = hECMC->GetXaxis(); @@ -818,7 +816,7 @@ struct UccZdc { // Preslice perMCCollision = aod::mcparticle::mcCollisionId; Preslice perCollision = aod::track::collisionId; TRandom* randPointer = new TRandom(); - void processMCclosure(aod::McCollisions::iterator const& mccollision, soa::SmallGroups const& collisions, o2::aod::BCsRun3 const& /*bcs*/, aod::McParticles const& mcParticles, TheFilteredSimTracks const& simTracks) + void processMCclosure(aod::McCollisions::iterator const& mccollision, soa::SmallGroups const& collisions, o2::aod::BCsRun3 const& /*bcs*/, aod::FT0s const& /*ft0s*/, aod::McParticles const& mcParticles, TheFilteredSimTracks const& simTracks) { float rndNum = randPointer->Uniform(0.0, 1.0); registry.fill(HIST("RandomNumber"), rndNum); @@ -840,6 +838,25 @@ struct UccZdc { continue; } + const auto& foundBC = collision.foundBC_as(); + + float aT0A = 0., aT0C = 0.; + if (foundBC.has_ft0()) { + for (const auto& amplitude : foundBC.ft0().amplitudeA()) { + aT0A += amplitude; + } + for (const auto& amplitude : foundBC.ft0().amplitudeC()) { + aT0C += amplitude; + } + } else { + return; + } + + double nchRaw{0.}; + double nchMult{0.}; + double normT0M{0.}; + normT0M = (aT0A + aT0C) / 100.; + registry.fill(HIST("zPos"), collision.posZ()); registry.fill(HIST("zPosMC"), mccollision.posZ()); registry.fill(HIST("hEventCounterMC"), EvCutLabel::VtxZ); @@ -853,13 +870,11 @@ struct UccZdc { registry.fill(HIST("EvtsDivided"), 0); // To use run-by-run efficiency - const auto& foundBC = collision.foundBC_as(); auto efficiency = ccdb->getForTimeStamp(paTHEff.value, foundBC.timestamp()); if (!efficiency) { return; } - int nchRaw{0}; std::vector pTs; std::vector vecFD; std::vector vecOneOverEff; @@ -876,6 +891,7 @@ struct UccZdc { float effValue{1.}; float fdValue{1.}; nchRaw++; + if (applyEff) { effValue = efficiency->GetBinContent(efficiency->FindBin(pt)); fdValue = fd->GetBinContent(fd->FindBin(pt)); @@ -887,7 +903,6 @@ struct UccZdc { } } - double nchMult{0.}; nchMult = std::accumulate(vecOneOverEff.begin(), vecOneOverEff.end(), 0); if (nchMult < minNchSel) { return; @@ -969,9 +984,18 @@ struct UccZdc { } else { // Correction with the remaining half of the sample registry.fill(HIST("EvtsDivided"), 1); //----- MC reconstructed -----// - int nchTrue{0}; - int nchRec{0}; const auto& groupedTracks{simTracks.sliceBy(perCollision, collision.globalIndex())}; + for (const auto& track : groupedTracks) { + // Track Selection + if (!track.isGlobalTrack()) { + continue; + } + registry.fill(HIST("ZposVsEta"), collision.posZ(), track.eta()); + registry.fill(HIST("EtaVsPhi"), track.eta(), track.phi()); + registry.fill(HIST("dcaXYvspT"), track.dcaXY(), track.pt()); + nchRaw++; + } + for (const auto& track : groupedTracks) { // Track Selection if (!track.isGlobalTrack()) { @@ -981,31 +1005,26 @@ struct UccZdc { if (!track.has_mcParticle()) { continue; } + registry.fill(HIST("Pt_all_ch"), nchRaw, track.pt()); const auto& particle{track.mcParticle()}; - registry.fill(HIST("Pt_all_ch"), cent, track.pt()); - registry.fill(HIST("ZposVsEta"), collision.posZ(), track.eta()); - registry.fill(HIST("EtaVsPhi"), track.eta(), track.phi()); - registry.fill(HIST("dcaXYvspT"), track.dcaXY(), track.pt()); - if (!particle.isPhysicalPrimary()) { continue; } - nchRec++; - registry.fill(HIST("Pt_ch"), cent, track.pt()); + registry.fill(HIST("Pt_ch"), nchRaw, track.pt()); if (particle.pdgCode() == PDG_t::kPiPlus || particle.pdgCode() == PDG_t::kPiMinus) { - registry.fill(HIST("Pt_pi"), cent, track.pt()); + registry.fill(HIST("Pt_pi"), nchRaw, track.pt()); } else if (particle.pdgCode() == PDG_t::kKPlus || particle.pdgCode() == PDG_t::kKMinus) { - registry.fill(HIST("Pt_ka"), cent, track.pt()); + registry.fill(HIST("Pt_ka"), nchRaw, track.pt()); } else if (particle.pdgCode() == PDG_t::kProton || particle.pdgCode() == PDG_t::kProtonBar) { - registry.fill(HIST("Pt_pr"), cent, track.pt()); + registry.fill(HIST("Pt_pr"), nchRaw, track.pt()); } else if (particle.pdgCode() == PDG_t::kSigmaPlus || particle.pdgCode() == PDG_t::kSigmaBarMinus) { - registry.fill(HIST("Pt_sigpos"), cent, track.pt()); + registry.fill(HIST("Pt_sigpos"), nchRaw, track.pt()); } else if (particle.pdgCode() == PDG_t::kSigmaMinus || particle.pdgCode() == PDG_t::kSigmaBarPlus) { - registry.fill(HIST("Pt_signeg"), cent, track.pt()); + registry.fill(HIST("Pt_signeg"), nchRaw, track.pt()); } else { - registry.fill(HIST("Pt_re"), cent, track.pt()); + registry.fill(HIST("Pt_re"), nchRaw, track.pt()); } } @@ -1021,26 +1040,23 @@ struct UccZdc { continue; } - nchTrue++; - registry.fill(HIST("PtMC_ch"), cent, particle.pt()); + registry.fill(HIST("PtMC_ch"), nchRaw, particle.pt()); if (particle.pdgCode() == PDG_t::kPiPlus || particle.pdgCode() == PDG_t::kPiMinus) { // pion - registry.fill(HIST("PtMC_pi"), cent, particle.pt()); + registry.fill(HIST("PtMC_pi"), nchRaw, particle.pt()); } else if (particle.pdgCode() == PDG_t::kKPlus || particle.pdgCode() == PDG_t::kKMinus) { // kaon - registry.fill(HIST("PtMC_ka"), cent, particle.pt()); + registry.fill(HIST("PtMC_ka"), nchRaw, particle.pt()); } else if (particle.pdgCode() == PDG_t::kProton || particle.pdgCode() == PDG_t::kProtonBar) { // proton - registry.fill(HIST("PtMC_pr"), cent, particle.pt()); + registry.fill(HIST("PtMC_pr"), nchRaw, particle.pt()); } else if (particle.pdgCode() == PDG_t::kSigmaPlus || particle.pdgCode() == PDG_t::kSigmaBarMinus) { // positive sigma - registry.fill(HIST("PtMC_sigpos"), cent, particle.pt()); + registry.fill(HIST("PtMC_sigpos"), nchRaw, particle.pt()); } else if (particle.pdgCode() == PDG_t::kSigmaMinus || particle.pdgCode() == PDG_t::kSigmaBarPlus) { // negative sigma - registry.fill(HIST("PtMC_signeg"), cent, particle.pt()); + registry.fill(HIST("PtMC_signeg"), nchRaw, particle.pt()); } else { // rest - registry.fill(HIST("PtMC_re"), cent, particle.pt()); + registry.fill(HIST("PtMC_re"), nchRaw, particle.pt()); } } - - registry.fill(HIST("NchRec"), nchRec); - registry.fill(HIST("NchTrue"), nchTrue); } // Half of statistics for corrections + registry.fill(HIST("McNchVsFT0M"), normT0M, nchRaw); } // Collisions } PROCESS_SWITCH(UccZdc, processMCclosure, "Process MC closure", false); From 55b21d9fe827169d7dbe8fef5f7ecaeebc061c09 Mon Sep 17 00:00:00 2001 From: sgaretti <129837066+sgaretti@users.noreply.github.com> Date: Wed, 18 Jun 2025 01:40:23 +0200 Subject: [PATCH 120/871] [PWGDQ] Add centrality info to MC generated events mini tree (#11650) --- PWGDQ/DataModel/ReducedInfoTables.h | 2 +- PWGDQ/Tasks/dqEfficiency_withAssoc.cxx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/PWGDQ/DataModel/ReducedInfoTables.h b/PWGDQ/DataModel/ReducedInfoTables.h index 68673e81de2..2b087c2b3f1 100644 --- a/PWGDQ/DataModel/ReducedInfoTables.h +++ b/PWGDQ/DataModel/ReducedInfoTables.h @@ -864,7 +864,7 @@ DECLARE_SOA_TABLE(DileptonsMiniTree, "AOD", "RTDILEPTMTREE", //! dilepton_track_index::Pt2, dilepton_track_index::Eta2, dilepton_track_index::Phi2); DECLARE_SOA_TABLE(DileptonsMiniTreeGen, "AOD", "RTDILMTREEGEN", //! - reducedpair::McDecision, mccollision::ImpactParameter, + reducedpair::McDecision, mccollision::ImpactParameter, reducedpair::CentFT0C, dilepton_track_index::PtMC1, dilepton_track_index::EtaMC1, dilepton_track_index::PhiMC1, dilepton_track_index::PtMC2, dilepton_track_index::EtaMC2, dilepton_track_index::PhiMC2); diff --git a/PWGDQ/Tasks/dqEfficiency_withAssoc.cxx b/PWGDQ/Tasks/dqEfficiency_withAssoc.cxx index cb44ae1d935..cc4cba21d79 100644 --- a/PWGDQ/Tasks/dqEfficiency_withAssoc.cxx +++ b/PWGDQ/Tasks/dqEfficiency_withAssoc.cxx @@ -2011,7 +2011,7 @@ struct AnalysisSameEventPairing { fHistMan->FillHistClass(Form("MCTruthGen_%s", sig->GetName()), VarManager::fgValues); if (useMiniTree.fConfigMiniTree) { auto mcEvent = mcEvents.rawIteratorAt(mctrack.reducedMCeventId()); - dileptonMiniTreeGen(mcDecision, mcEvent.impactParameter(), mctrack.pt(), mctrack.eta(), mctrack.phi(), -999, -999, -999); + dileptonMiniTreeGen(mcDecision, mcEvent.impactParameter(), VarManager::fgValues[VarManager::kCentFT0C], mctrack.pt(), mctrack.eta(), mctrack.phi(), -999, -999, -999); } } } From 6e9e60f4301429c6efd7927a35bd99a57109889d Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Wed, 18 Jun 2025 06:57:09 +0200 Subject: [PATCH 121/871] [Common,PWGHF,PWGJE,Trigger,Tutorial] Drop support for old ONNXRuntime API (#11654) --- Common/TableProducer/mftmchMatchingML.cxx | 21 ------------- .../PWGHF/HFFilterPrepareMLSamples.cxx | 4 --- .../candidateSelectorLcPidMl.cxx | 4 --- PWGJE/Core/MlResponseHfTagging.h | 12 -------- Tools/ML/MlResponse.h | 4 --- Tools/ML/model.cxx | 13 +------- Tools/ML/model.h | 30 ------------------- Tools/PIDML/pidOnnxModel.h | 27 ----------------- Tutorials/src/reweighting.cxx | 20 ------------- 9 files changed, 1 insertion(+), 134 deletions(-) diff --git a/Common/TableProducer/mftmchMatchingML.cxx b/Common/TableProducer/mftmchMatchingML.cxx index 4c813316275..4df90bbfdd1 100644 --- a/Common/TableProducer/mftmchMatchingML.cxx +++ b/Common/TableProducer/mftmchMatchingML.cxx @@ -10,11 +10,7 @@ // or submit itself to any jurisdiction. #include -#if __has_include() -#include -#else #include -#endif #include #include #include @@ -77,11 +73,7 @@ struct mftmchMatchingML { Ort::Env env{ORT_LOGGING_LEVEL_WARNING, "model-explorer"}; Ort::SessionOptions session_options; -#if __has_include() - std::shared_ptr onnx_session = nullptr; -#else std::shared_ptr onnx_session = nullptr; -#endif OnnxModel model; template @@ -158,12 +150,6 @@ struct mftmchMatchingML { std::vector output_names; std::vector> output_shapes; -#if __has_include() - input_names = onnx_session->GetInputNames(); - input_shapes = onnx_session->GetInputShapes(); - output_names = onnx_session->GetOutputNames(); - output_shapes = onnx_session->GetOutputShapes(); -#else Ort::AllocatorWithDefaultOptions tmpAllocator; for (size_t i = 0; i < onnx_session->GetInputCount(); ++i) { input_names.push_back(onnx_session->GetInputNameAllocated(i, tmpAllocator).get()); @@ -177,7 +163,6 @@ struct mftmchMatchingML { for (size_t i = 0; i < onnx_session->GetOutputCount(); ++i) { output_shapes.emplace_back(onnx_session->GetOutputTypeInfo(i).GetTensorTypeAndShapeInfo().GetShape()); } -#endif auto input_shape = input_shapes[0]; input_shape[0] = 1; @@ -187,11 +172,6 @@ struct mftmchMatchingML { if (input_tensor_values[8] < cfgXYWindow) { std::vector input_tensors; -#if __has_include() - input_tensors.push_back(Ort::Experimental::Value::CreateTensor(input_tensor_values.data(), input_tensor_values.size(), input_shape)); - - std::vector output_tensors = onnx_session->Run(input_names, input_tensors, output_names); -#else Ort::MemoryInfo mem_info = Ort::MemoryInfo::CreateCpu(OrtAllocatorType::OrtArenaAllocator, OrtMemType::OrtMemTypeDefault); input_tensors.push_back(Ort::Value::CreateTensor(mem_info, input_tensor_values.data(), input_tensor_values.size(), input_shape.data(), input_shape.size())); @@ -206,7 +186,6 @@ struct mftmchMatchingML { [&](const std::string& str) { return str.c_str(); }); std::vector output_tensors = onnx_session->Run(runOptions, inputNamesChar.data(), input_tensors.data(), input_tensors.size(), outputNamesChar.data(), outputNamesChar.size()); -#endif const float* output_value = output_tensors[0].GetTensorData(); diff --git a/EventFiltering/PWGHF/HFFilterPrepareMLSamples.cxx b/EventFiltering/PWGHF/HFFilterPrepareMLSamples.cxx index 6a5f50eb158..b7a9637ba10 100644 --- a/EventFiltering/PWGHF/HFFilterPrepareMLSamples.cxx +++ b/EventFiltering/PWGHF/HFFilterPrepareMLSamples.cxx @@ -28,11 +28,7 @@ #include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/TrackSelectionTables.h" -#if __has_include() -#include // needed for HFFilterHelpers, to be fixed -#else #include -#endif #include #include diff --git a/PWGHF/TableProducer/candidateSelectorLcPidMl.cxx b/PWGHF/TableProducer/candidateSelectorLcPidMl.cxx index 9f74fd9c583..b30ebec439a 100644 --- a/PWGHF/TableProducer/candidateSelectorLcPidMl.cxx +++ b/PWGHF/TableProducer/candidateSelectorLcPidMl.cxx @@ -127,15 +127,11 @@ struct HfCandidateSelectorLcPidMl { } if (retrieveSuccess) { auto session = model.getSession(); -#if __has_include() - auto inputShapes = session->GetInputShapes(); -#else std::vector> inputShapes; Ort::AllocatorWithDefaultOptions tmpAllocator; for (size_t i = 0; i < session->GetInputCount(); ++i) { inputShapes.emplace_back(session->GetInputTypeInfo(i).GetTensorTypeAndShapeInfo().GetShape()); } -#endif if (inputShapes[0][0] < 0) { LOGF(warning, "Model for Lc with negative input shape likely because converted with hummingbird, setting it to 1."); inputShapes[0][0] = 1; diff --git a/PWGJE/Core/MlResponseHfTagging.h b/PWGJE/Core/MlResponseHfTagging.h index 87da7a282e0..2b07e1c1c25 100644 --- a/PWGJE/Core/MlResponseHfTagging.h +++ b/PWGJE/Core/MlResponseHfTagging.h @@ -18,11 +18,7 @@ #include "Tools/ML/MlResponse.h" -#if __has_include() -#include -#else #include -#endif #include @@ -333,25 +329,17 @@ class MlResponseHfTagging : public MlResponse class TensorAllocator { protected: -#if !__has_include() Ort::MemoryInfo memInfo; -#endif public: TensorAllocator() -#if !__has_include() : memInfo(Ort::MemoryInfo::CreateCpu(OrtAllocatorType::OrtArenaAllocator, OrtMemType::OrtMemTypeDefault)) -#endif { } ~TensorAllocator() = default; template Ort::Value createTensor(std::vector& input, std::vector& inputShape) { -#if __has_include() - return Ort::Experimental::Value::CreateTensor(input.data(), input.size(), inputShape); -#else return Ort::Value::CreateTensor(memInfo, input.data(), input.size(), inputShape.data(), inputShape.size()); -#endif } }; diff --git a/Tools/ML/MlResponse.h b/Tools/ML/MlResponse.h index 2d16a67bf18..b8c192fd386 100644 --- a/Tools/ML/MlResponse.h +++ b/Tools/ML/MlResponse.h @@ -17,11 +17,7 @@ #ifndef TOOLS_ML_MLRESPONSE_H_ #define TOOLS_ML_MLRESPONSE_H_ -#if __has_include() -#include -#else #include -#endif #include #include diff --git a/Tools/ML/model.cxx b/Tools/ML/model.cxx index 0c29808c73c..7e2e099aa3b 100644 --- a/Tools/ML/model.cxx +++ b/Tools/ML/model.cxx @@ -75,18 +75,8 @@ void OnnxModel::initModel(std::string localPath, bool enableOptimizations, int t } mEnv = std::make_shared(ORT_LOGGING_LEVEL_WARNING, "onnx-model"); -#if __has_include() - mSession = std::make_shared(*mEnv, modelPath, sessionOptions); -#else mSession = std::make_shared(*mEnv, modelPath.c_str(), sessionOptions); -#endif - -#if __has_include() - mInputNames = mSession->GetInputNames(); - mInputShapes = mSession->GetInputShapes(); - mOutputNames = mSession->GetOutputNames(); - mOutputShapes = mSession->GetOutputShapes(); -#else + Ort::AllocatorWithDefaultOptions tmpAllocator; for (size_t i = 0; i < mSession->GetInputCount(); ++i) { mInputNames.push_back(mSession->GetInputNameAllocated(i, tmpAllocator).get()); @@ -100,7 +90,6 @@ void OnnxModel::initModel(std::string localPath, bool enableOptimizations, int t for (size_t i = 0; i < mSession->GetOutputCount(); ++i) { mOutputShapes.emplace_back(mSession->GetOutputTypeInfo(i).GetTensorTypeAndShapeInfo().GetShape()); } -#endif LOG(info) << "Input Nodes:"; for (size_t i = 0; i < mInputNames.size(); i++) { LOG(info) << "\t" << mInputNames[i] << " : " << printShape(mInputShapes[i]); diff --git a/Tools/ML/model.h b/Tools/ML/model.h index 84872224104..1fef9154c9b 100644 --- a/Tools/ML/model.h +++ b/Tools/ML/model.h @@ -21,11 +21,7 @@ #define TOOLS_ML_MODEL_H_ // C++ and system includes -#if __has_include() -#include -#else #include -#endif #include #include #include @@ -62,9 +58,6 @@ class OnnxModel // assert(input[0].GetTensorTypeAndShapeInfo().GetShape() == getNumInputNodes()); --> Fails build in debug mode, TODO: assertion should be checked somehow try { -#if __has_include() - auto outputTensors = mSession->Run(mInputNames, input, mOutputNames); -#else Ort::RunOptions runOptions; std::vector inputNamesChar(mInputNames.size(), nullptr); std::transform(std::begin(mInputNames), std::end(mInputNames), std::begin(inputNamesChar), @@ -74,7 +67,6 @@ class OnnxModel std::transform(std::begin(mOutputNames), std::end(mOutputNames), std::begin(outputNamesChar), [&](const std::string& str) { return str.c_str(); }); auto outputTensors = mSession->Run(runOptions, inputNamesChar.data(), input.data(), input.size(), outputNamesChar.data(), outputNamesChar.size()); -#endif LOG(debug) << "Number of output tensors: " << outputTensors.size(); if (outputTensors.size() != mOutputNames.size()) { LOG(fatal) << "Number of output tensors: " << outputTensors.size() << " does not agree with the model specified size: " << mOutputNames.size(); @@ -100,13 +92,9 @@ class OnnxModel assert(size % mInputShapes[0][1] == 0); std::vector inputShape{size / mInputShapes[0][1], mInputShapes[0][1]}; std::vector inputTensors; -#if __has_include() - inputTensors.emplace_back(Ort::Experimental::Value::CreateTensor(input.data(), size, inputShape)); -#else Ort::MemoryInfo memInfo = Ort::MemoryInfo::CreateCpu(OrtAllocatorType::OrtArenaAllocator, OrtMemType::OrtMemTypeDefault); inputTensors.emplace_back(Ort::Value::CreateTensor(memInfo, input.data(), size, inputShape.data(), inputShape.size())); -#endif LOG(debug) << "Input shape calculated from vector: " << printShape(inputShape); return evalModel(inputTensors); } @@ -117,9 +105,7 @@ class OnnxModel { std::vector inputTensors; -#if !__has_include() Ort::MemoryInfo memInfo = Ort::MemoryInfo::CreateCpu(OrtAllocatorType::OrtArenaAllocator, OrtMemType::OrtMemTypeDefault); -#endif for (size_t iinput = 0; iinput < input.size(); iinput++) { [[maybe_unused]] int totalSize = 1; @@ -134,36 +120,24 @@ class OnnxModel inputShape.push_back(mInputShapes[iinput][idim]); } -#if __has_include() - inputTensors.emplace_back(Ort::Experimental::Value::CreateTensor(input[iinput].data(), size, inputShape)); -#else inputTensors.emplace_back(Ort::Value::CreateTensor(memInfo, input[iinput].data(), size, inputShape.data(), inputShape.size())); -#endif } return evalModel(inputTensors); } // Reset session -#if __has_include() - void resetSession() { mSession.reset(new Ort::Experimental::Session{*mEnv, modelPath, sessionOptions}); } -#else void resetSession() { mSession.reset(new Ort::Session{*mEnv, modelPath.c_str(), sessionOptions}); } -#endif // Getters & Setters Ort::SessionOptions* getSessionOptions() { return &sessionOptions; } // For optimizations in post -#if __has_include() - std::shared_ptr getSession() { return mSession; } -#else std::shared_ptr getSession() { return mSession; } -#endif int getNumInputNodes() const { return mInputShapes[0][1]; } std::vector> getInputShapes() const { return mInputShapes; } int getNumOutputNodes() const { return mOutputShapes[0][1]; } @@ -174,11 +148,7 @@ class OnnxModel private: // Environment variables for the ONNX runtime std::shared_ptr mEnv = nullptr; -#if __has_include() - std::shared_ptr mSession = nullptr; -#else std::shared_ptr mSession = nullptr; -#endif Ort::SessionOptions sessionOptions; // Input & Output specifications of the loaded network diff --git a/Tools/PIDML/pidOnnxModel.h b/Tools/PIDML/pidOnnxModel.h index 1c48a84f2b8..212f0ed8e9d 100644 --- a/Tools/PIDML/pidOnnxModel.h +++ b/Tools/PIDML/pidOnnxModel.h @@ -31,11 +31,7 @@ #include #include #include -#if __has_include() -#include -#else #include -#endif #include "rapidjson/document.h" #include "rapidjson/filereadstream.h" @@ -93,19 +89,9 @@ struct PidONNXModel { Ort::SessionOptions sessionOptions; mEnv = std::make_shared(ORT_LOGGING_LEVEL_WARNING, "pid-onnx-inferer"); LOG(info) << "Loading ONNX model from file: " << modelFile; -#if __has_include() - mSession.reset(new Ort::Experimental::Session{*mEnv, modelFile, sessionOptions}); -#else mSession.reset(new Ort::Session{*mEnv, modelFile.c_str(), sessionOptions}); -#endif LOG(info) << "ONNX model loaded"; -#if __has_include() - mInputNames = mSession->GetInputNames(); - mInputShapes = mSession->GetInputShapes(); - mOutputNames = mSession->GetOutputNames(); - mOutputShapes = mSession->GetOutputShapes(); -#else Ort::AllocatorWithDefaultOptions tmpAllocator; for (size_t i = 0; i < mSession->GetInputCount(); ++i) { mInputNames.push_back(mSession->GetInputNameAllocated(i, tmpAllocator).get()); @@ -119,7 +105,6 @@ struct PidONNXModel { for (size_t i = 0; i < mSession->GetOutputCount(); ++i) { mOutputShapes.emplace_back(mSession->GetOutputTypeInfo(i).GetTensorTypeAndShapeInfo().GetShape()); } -#endif LOG(debug) << "Input Node Name/Shape (" << mInputNames.size() << "):"; for (size_t i = 0; i < mInputNames.size(); i++) { @@ -274,12 +259,8 @@ struct PidONNXModel { std::vector inputTensorValues = getValues(track); std::vector inputTensors; -#if __has_include() - inputTensors.emplace_back(Ort::Experimental::Value::CreateTensor(inputTensorValues.data(), inputTensorValues.size(), inputShape)); -#else Ort::MemoryInfo memInfo = Ort::MemoryInfo::CreateCpu(OrtAllocatorType::OrtArenaAllocator, OrtMemType::OrtMemTypeDefault); inputTensors.emplace_back(Ort::Value::CreateTensor(memInfo, inputTensorValues.data(), inputTensorValues.size(), inputShape.data(), inputShape.size())); -#endif // Double-check the dimensions of the input tensor assert(inputTensors[0].IsTensor() && @@ -287,9 +268,6 @@ struct PidONNXModel { LOG(debug) << "input tensor shape: " << printShape(inputTensors[0].GetTensorTypeAndShapeInfo().GetShape()); try { -#if __has_include() - auto outputTensors = mSession->Run(mInputNames, inputTensors, mOutputNames); -#else Ort::RunOptions runOptions; std::vector inputNamesChar(mInputNames.size(), nullptr); std::transform(std::begin(mInputNames), std::end(mInputNames), std::begin(inputNamesChar), @@ -299,7 +277,6 @@ struct PidONNXModel { std::transform(std::begin(mOutputNames), std::end(mOutputNames), std::begin(outputNamesChar), [&](const std::string& str) { return str.c_str(); }); auto outputTensors = mSession->Run(runOptions, inputNamesChar.data(), inputTensors.data(), inputTensors.size(), outputNamesChar.data(), outputNamesChar.size()); -#endif // Double-check the dimensions of the output tensors // The number of output tensors is equal to the number of output nodes specified in the Run() call @@ -331,11 +308,7 @@ struct PidONNXModel { std::shared_ptr mEnv = nullptr; // No empty constructors for Session, we need a pointer -#if __has_include() - std::shared_ptr mSession = nullptr; -#else std::shared_ptr mSession = nullptr; -#endif std::vector mPLimits; std::vector mInputNames; diff --git a/Tutorials/src/reweighting.cxx b/Tutorials/src/reweighting.cxx index 72c17a1cb29..17a4ad4bf33 100644 --- a/Tutorials/src/reweighting.cxx +++ b/Tutorials/src/reweighting.cxx @@ -28,11 +28,7 @@ // This workflow is used to create a flat tree for model training // Use o2-aod-merger to combine dataframes in output AnalysisResults_trees.root -#if __has_include() -#include -#else #include -#endif #include "Framework/runDataProcessing.h" #include "Framework/AnalysisTask.h" #include "Common/DataModel/Multiplicity.h" @@ -82,11 +78,7 @@ struct CreateWeights { Filter centralTracks = nabs(aod::track::eta) < centralEtaCut; /// onnx runtime session handle -#if __has_include() - std::shared_ptr onnxSession = nullptr; -#else std::shared_ptr onnxSession = nullptr; -#endif /// onnx runtime session options Ort::SessionOptions sessionOptions; /// input vectore @@ -98,17 +90,11 @@ struct CreateWeights { { auto path = (std::string)onnxModel; /// create session -#if __has_include() - onnxSession = std::make_shared(env, path, sessionOptions); - /// adjust input shape to use row-by-row model application - inputShapes = onnxSession->GetInputShapes(); -#else onnxSession = std::make_shared(env, path.c_str(), sessionOptions); /// adjust input shape to use row-by-row model application for (size_t i = 0; i < onnxSession->GetInputCount(); ++i) { inputShapes.emplace_back(onnxSession->GetInputTypeInfo(i).GetTensorTypeAndShapeInfo().GetShape()); } -#endif if (inputShapes[0][0] < 0) { LOG(warning) << "Model with negative input shape, setting it to 1."; inputShapes[0][0] = 1; @@ -120,11 +106,6 @@ struct CreateWeights { /// get the input variables auto features = collect(collision, tracks); /// add an entry in input vector -#if __has_include() - inputML.push_back(Ort::Experimental::Value::CreateTensor(features.data(), features.size(), inputShapes[0])); - /// run inference - auto result = onnxSession->Run(onnxSession->GetInputNames(), inputML, onnxSession->GetOutputNames()); -#else Ort::MemoryInfo mem_info = Ort::MemoryInfo::CreateCpu(OrtAllocatorType::OrtArenaAllocator, OrtMemType::OrtMemTypeDefault); inputML.push_back(Ort::Value::CreateTensor(mem_info, features.data(), features.size(), inputShapes[0].data(), inputShapes[0].size())); @@ -142,7 +123,6 @@ struct CreateWeights { outputNamesChar.push_back(onnxSession->GetOutputNameAllocated(i, tmpAllocator).get()); } auto result = onnxSession->Run(runOptions, inputNamesChar.data(), inputML.data(), inputML.size(), outputNamesChar.data(), outputNamesChar.size()); -#endif /// extract scores auto scores = result[1].GetTensorMutableData(); LOGP(info, "Col {}: scores ({}, {})", collision.globalIndex(), scores[0], scores[1]); From b857757badfc04ffde0b2ad4269019f424a4b315 Mon Sep 17 00:00:00 2001 From: alcaliva <32872606+alcaliva@users.noreply.github.com> Date: Wed, 18 Jun 2025 07:26:34 +0200 Subject: [PATCH 122/871] [PWGLF] added 2nd order reweighting + some refactoring (#11658) --- PWGLF/Tasks/Nuspex/antinucleiInJets.cxx | 554 +++++++++++++----------- 1 file changed, 310 insertions(+), 244 deletions(-) diff --git a/PWGLF/Tasks/Nuspex/antinucleiInJets.cxx b/PWGLF/Tasks/Nuspex/antinucleiInJets.cxx index 5ddaa882de8..44dc27260a7 100644 --- a/PWGLF/Tasks/Nuspex/antinucleiInJets.cxx +++ b/PWGLF/Tasks/Nuspex/antinucleiInJets.cxx @@ -15,52 +15,55 @@ /// \author Alberto Caliva (alberto.caliva@cern.ch), Chiara Pinto (chiara.pinto@cern.ch) /// \since February 13, 2025 -#include -#include -#include -#include -#include -#include -#include -#include -#include "TGrid.h" -#include -#include +#include "PWGJE/Core/JetBkgSubUtils.h" +#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" + +#include "Common/Core/TrackSelection.h" +#include "Common/Core/trackUtilities.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/PIDResponseITS.h" +#include "Common/DataModel/TrackSelectionTables.h" #include "CCDB/BasicCCDBManager.h" #include "CCDB/CcdbApi.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" #include "Framework/ASoA.h" #include "Framework/ASoAHelpers.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/RunningWorkflowInfo.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" #include "Framework/DataTypes.h" +#include "Framework/HistogramRegistry.h" #include "Framework/Logger.h" -#include "ReconstructionDataFormats/Track.h" -#include "ReconstructionDataFormats/PID.h" +#include "Framework/RunningWorkflowInfo.h" +#include "Framework/runDataProcessing.h" #include "ReconstructionDataFormats/DCA.h" -#include "Common/Core/trackUtilities.h" -#include "Common/Core/TrackSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/Centrality.h" -#include "Common/DataModel/PIDResponse.h" -#include "Common/DataModel/PIDResponseITS.h" +#include "ReconstructionDataFormats/PID.h" +#include "ReconstructionDataFormats/Track.h" + +#include "TGrid.h" +#include +#include +#include +#include +#include +#include #include #include +#include +#include +#include #include #include -#include -#include -#include -#include -#include "PWGJE/Core/JetBkgSubUtils.h" -#include "PWGJE/Core/JetDerivedDataUtilities.h" -#include "PWGJE/DataModel/JetReducedData.h" -#include "PWGJE/DataModel/Jet.h" + +#include +#include +#include +#include +#include using namespace std; using namespace o2; @@ -118,7 +121,6 @@ struct AntinucleiInJets { Configurable nSigmaItsMax{"nSigmaItsMax", +2.0, "nSigmaITS max"}; // reweighting - Configurable applyReweighting{"applyReweighting", true, "apply reweighting"}; Configurable urlToCcdb{"urlToCcdb", "http://alice-ccdb.cern.ch", "url of the personal ccdb"}; Configurable pathToFile{"pathToFile", "", "path to file with reweighting"}; Configurable histoNameWeightAntipJet{"histoNameWeightAntipJet", "", "reweighting histogram: antip in jet"}; @@ -146,12 +148,7 @@ struct AntinucleiInJets { ccdb->setCreatedNotAfter(std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count()); ccdb->setFatalWhenNull(false); - if (applyReweighting) { - getReweightingHistograms(ccdb, TString(pathToFile), TString(histoNameWeightAntipJet), TString(histoNameWeightAntipUe)); - } else { - twoDweightsAntipJet = nullptr; - twoDweightsAntipUe = nullptr; - } + getReweightingHistograms(ccdb, TString(pathToFile), TString(histoNameWeightAntipJet), TString(histoNameWeightAntipUe)); if (applyPtUnfolding) { getPtUnfoldingHistogram(ccdb, TString(pathToFilePtUnfolding), TString(histoNamePtUnfolding)); @@ -223,52 +220,69 @@ struct AntinucleiInJets { // event counter MC registryMC.add("number_of_events_mc", "number of events in mc", HistType::kTH1F, {{10, 0, 10, "counter"}}); - // generated spectra - registryMC.add("antiproton_incl_gen", "antiproton_incl_gen", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); + // generated spectra (antiprotons) + registryMC.add("antiproton_gen_jet_unweighted", "antiproton_gen_jet_unweighted", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("antiproton_gen_ue_unweighted", "antiproton_gen_ue_unweighted", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("antiproton_gen_jet_weighted2d", "antiproton_gen_jet_weighted2d", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("antiproton_gen_ue_weighted2d", "antiproton_gen_ue_weighted2d", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("antiproton_gen_jet_weightedFinal", "antiproton_gen_jet_weightedFinal", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("antiproton_gen_ue_weightedFinal", "antiproton_gen_ue_weightedFinal", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("antiproton_gen_jet_antikt", "antiproton_gen_jet_antikt", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("antiproton_gen_ue_antikt", "antiproton_gen_ue_antikt", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); + + // generated spectra (antinuclei) registryMC.add("deuteron_incl_gen", "deuteron_incl_gen", HistType::kTH1F, {{nbins, 2 * min, 2 * max, "#it{p}_{T} (GeV/#it{c})"}}); registryMC.add("antideuteron_incl_gen", "antideuteron_incl_gen", HistType::kTH1F, {{nbins, 2 * min, 2 * max, "#it{p}_{T} (GeV/#it{c})"}}); registryMC.add("helium3_incl_gen", "helium3_incl_gen", HistType::kTH1F, {{nbins, 3 * min, 3 * max, "#it{p}_{T} (GeV/#it{c})"}}); registryMC.add("antihelium3_incl_gen", "antihelium3_incl_gen", HistType::kTH1F, {{nbins, 3 * min, 3 * max, "#it{p}_{T} (GeV/#it{c})"}}); - // reconstructed TPC - registryMC.add("antiproton_incl_rec_tpc", "antiproton_incl_rec_tpc", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); + // reconstructed TPC (antiprotons) + registryMC.add("antiproton_recTpc_jet_unweighted", "antiproton_recTpc_jet_unweighted", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("antiproton_recTpc_ue_unweighted", "antiproton_recTpc_ue_unweighted", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("antiproton_recTpc_jet_weighted2d", "antiproton_recTpc_jet_weighted2d", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("antiproton_recTpc_ue_weighted2d", "antiproton_recTpc_ue_weighted2d", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("antiproton_recTpc_jet_weightedFinal", "antiproton_recTpc_jet_weightedFinal", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("antiproton_recTpc_ue_weightedFinal", "antiproton_recTpc_ue_weightedFinal", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("antiproton_recTpc_jet_antikt", "antiproton_recTpc_jet_antikt", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("antiproton_recTpc_ue_antikt", "antiproton_recTpc_ue_antikt", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); + + // reconstructed TPC (antinuclei) registryMC.add("antideuteron_incl_rec_tpc", "antideuteron_incl_rec_tpc", HistType::kTH1F, {{nbins, 2 * min, 2 * max, "#it{p}_{T} (GeV/#it{c})"}}); registryMC.add("deuteron_incl_rec_tpc", "deuteron_incl_rec_tpc", HistType::kTH1F, {{nbins, 2 * min, 2 * max, "#it{p}_{T} (GeV/#it{c})"}}); registryMC.add("antihelium3_incl_rec_tpc", "antihelium3_incl_rec_tpc", HistType::kTH1F, {{nbins, 3 * min, 3 * max, "#it{p}_{T} (GeV/#it{c})"}}); registryMC.add("helium3_incl_rec_tpc", "helium3_incl_rec_tpc", HistType::kTH1F, {{nbins, 3 * min, 3 * max, "#it{p}_{T} (GeV/#it{c})"}}); - // reconstructed TOF - registryMC.add("antiproton_incl_rec_tof", "antiproton_incl_rec_tof", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); + // reconstructed TOF (antiprotons) + registryMC.add("antiproton_recTof_jet_unweighted", "antiproton_recTof_jet_unweighted", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("antiproton_recTof_ue_unweighted", "antiproton_recTof_ue_unweighted", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("antiproton_recTof_jet_weighted2d", "antiproton_recTof_jet_weighted2d", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("antiproton_recTof_ue_weighted2d", "antiproton_recTof_ue_weighted2d", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("antiproton_recTof_jet_weightedFinal", "antiproton_recTof_jet_weightedFinal", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("antiproton_recTof_ue_weightedFinal", "antiproton_recTof_ue_weightedFinal", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("antiproton_recTof_jet_antikt", "antiproton_recTof_jet_antikt", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("antiproton_recTof_ue_antikt", "antiproton_recTof_ue_antikt", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); + + // reconstructed TOF (antinuclei) registryMC.add("antideuteron_incl_rec_tof", "antideuteron_incl_rec_tof", HistType::kTH1F, {{nbins, 2 * min, 2 * max, "#it{p}_{T} (GeV/#it{c})"}}); registryMC.add("deuteron_incl_rec_tof", "deuteron_incl_rec_tof", HistType::kTH1F, {{nbins, 2 * min, 2 * max, "#it{p}_{T} (GeV/#it{c})"}}); - // fraction of primary antiprotons from MC - registryMC.add("antiproton_incl_prim", "antiproton_incl_prim", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); - registryMC.add("antiproton_incl_all", "antiproton_incl_all", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); + // fraction of primary antiprotons from MC (all unweighted for now) + registryMC.add("antiproton_prim_jet", "antiproton_prim_jet", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("antiproton_incl_jet", "antiproton_incl_jet", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("antiproton_prim_ue", "antiproton_prim_ue", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("antiproton_incl_ue", "antiproton_incl_ue", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); // antiproton reweighting registryMC.add("antiproton_eta_pt_pythia", "antiproton_eta_pt_pythia", HistType::kTH2F, {{200, 0.0, 10.0, "#it{p}_{T} (GeV/#it{c})"}, {20, -1.0, 1.0, "#it{#eta}"}}); - } - - if (doprocessJetsMCgen) { - registryMC.add("antiproton_jet_gen", "antiproton_jet_gen", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); - registryMC.add("antiproton_ue_gen", "antiproton_ue_gen", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); registryMC.add("antiproton_eta_pt_jet", "antiproton_eta_pt_jet", HistType::kTH2F, {{200, 0.0, 10.0, "#it{p}_{T} (GeV/#it{c})"}, {20, -1.0, 1.0, "#it{#eta}"}}); registryMC.add("antiproton_eta_pt_ue", "antiproton_eta_pt_ue", HistType::kTH2F, {{200, 0.0, 10.0, "#it{p}_{T} (GeV/#it{c})"}, {20, -1.0, 1.0, "#it{#eta}"}}); + registryMC.add("antiproton_forReweighting_jet_weighted2d", "antiproton_forReweighting_jet_weighted2d", HistType::kTH1F, {{5000, 0.0, 5.0, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("antiproton_forReweighting_ue_weighted2d", "antiproton_forReweighting_ue_weighted2d", HistType::kTH1F, {{5000, 0.0, 5.0, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("antiproton_forReweighting_jet_weightedFinal", "antiproton_forReweighting_jet_weightedFinal", HistType::kTH1F, {{5000, 0.0, 5.0, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("antiproton_forReweighting_ue_weightedFinal", "antiproton_forReweighting_ue_weightedFinal", HistType::kTH1F, {{5000, 0.0, 5.0, "#it{p}_{T} (GeV/#it{c})"}}); } if (doprocessJetsMCrec) { - registryMC.add("antiproton_jet_prim", "antiproton_jet_prim", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); - registryMC.add("antiproton_jet_all", "antiproton_jet_all", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); - registryMC.add("antiproton_ue_prim", "antiproton_ue_prim", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); - registryMC.add("antiproton_ue_all", "antiproton_all_ue", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); - registryMC.add("antiproton_jet_rec_tpc", "antiproton_jet_rec_tpc", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); - registryMC.add("antiproton_ue_rec_tpc", "antiproton_ue_rec_tpc", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); - registryMC.add("antiproton_jet_rec_tof", "antiproton_jet_rec_tof", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); - registryMC.add("antiproton_ue_rec_tof", "antiproton_ue_rec_tof", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); - registryMC.add("antiproton_jet_tpc_rec_vs_generatedptjet", "antiproton_jet_tpc_rec_vs_generatedptjet", HistType::kTH2F, {{nbins, min, max, "#it{p}_{T, antiproton}^{rec} (GeV/#it{c})"}, {1000, 0., 100., "#it{p}_{T, jet}^{gen} (GeV/#it{c})"}}); - registryMC.add("antiproton_jet_tof_rec_vs_generatedptjet", "antiproton_jet_tof_rec_vs_generatedptjet", HistType::kTH2F, {{nbins, min, max, "#it{p}_{T, antiproton}^{rec} (GeV/#it{c})"}, {1000, 0., 100., "#it{p}_{T, jet}^{gen} (GeV/#it{c})"}}); - // detector response matrix registryMC.add("detectorResponseMatrix", "detectorResponseMatrix", HistType::kTH2F, {{1000, 0.0, 100.0, "#it{p}_{T}^{rec} (GeV/#it{c})"}, {2000, -20.0, 20.0, "#it{p}_{T}^{gen} - #it{p}_{T}^{rec} (GeV/#it{c})"}}); registryMC.add("generatedVsReconstructedPt", "generatedVsReconstructedPt", HistType::kTH2F, {{1000, 0.0, 100.0, "#it{p}_{T}^{rec} (GeV/#it{c})"}, {1000, 0.0, 100.0, "#it{p}_{T}^{gen} (GeV/#it{c})"}}); @@ -632,28 +646,21 @@ struct AntinucleiInJets { if (std::fabs(dcaxy) > maxDcaxy || std::fabs(dcaz) > maxDcaz) continue; - // particle identification using the ITS cluster size - bool passedItsPidProt(false), passedItsPidDeut(false), passedItsPidHel(false); - if (itsResponse.nSigmaITS(track) > nSigmaItsMin && itsResponse.nSigmaITS(track) < nSigmaItsMax) { - passedItsPidProt = true; - } - if (itsResponse.nSigmaITS(track) > nSigmaItsMin && itsResponse.nSigmaITS(track) < nSigmaItsMax) { - passedItsPidDeut = true; + // Particle identification using the ITS cluster size + bool passedItsPidProt(true), passedItsPidDeut(true), passedItsPidHel(true); + double nSigmaITSprot = static_cast(itsResponse.nSigmaITS(track)); + double nSigmaITSdeut = static_cast(itsResponse.nSigmaITS(track)); + double nSigmaITShel3 = static_cast(itsResponse.nSigmaITS(track)); + + if (applyItsPid && pt < ptMaxItsPidProt && (nSigmaITSprot < nSigmaItsMin || nSigmaITSprot > nSigmaItsMax)) { + passedItsPidProt = false; } - if (itsResponse.nSigmaITS(track) > nSigmaItsMin && itsResponse.nSigmaITS(track) < nSigmaItsMax) { - passedItsPidHel = true; + if (applyItsPid && pt < ptMaxItsPidDeut && (nSigmaITSdeut < nSigmaItsMin || nSigmaITSdeut > nSigmaItsMax)) { + passedItsPidDeut = false; } - if (!applyItsPid) { - passedItsPidProt = true; - passedItsPidDeut = true; - passedItsPidHel = true; + if (applyItsPid && (2.0 * pt) < ptMaxItsPidHel && (nSigmaITShel3 < nSigmaItsMin || nSigmaITShel3 > nSigmaItsMax)) { + passedItsPidHel = false; } - if (pt > ptMaxItsPidProt) - passedItsPidProt = true; - if (pt > ptMaxItsPidDeut) - passedItsPidDeut = true; - if ((2.0 * pt) > ptMaxItsPidHel) - passedItsPidHel = true; // antimatter if (track.sign() < 0) { @@ -717,28 +724,21 @@ struct AntinucleiInJets { if (std::fabs(dcaxy) > maxDcaxy || std::fabs(dcaz) > maxDcaz) continue; - // particle identification using the ITS cluster size - bool passedItsPidProt(false), passedItsPidDeut(false), passedItsPidHel(false); - if (itsResponse.nSigmaITS(track) > nSigmaItsMin && itsResponse.nSigmaITS(track) < nSigmaItsMax) { - passedItsPidProt = true; - } - if (itsResponse.nSigmaITS(track) > nSigmaItsMin && itsResponse.nSigmaITS(track) < nSigmaItsMax) { - passedItsPidDeut = true; + // Particle identification using the ITS cluster size + bool passedItsPidProt(true), passedItsPidDeut(true), passedItsPidHel(true); + double nSigmaITSprot = static_cast(itsResponse.nSigmaITS(track)); + double nSigmaITSdeut = static_cast(itsResponse.nSigmaITS(track)); + double nSigmaITShel3 = static_cast(itsResponse.nSigmaITS(track)); + + if (applyItsPid && pt < ptMaxItsPidProt && (nSigmaITSprot < nSigmaItsMin || nSigmaITSprot > nSigmaItsMax)) { + passedItsPidProt = false; } - if (itsResponse.nSigmaITS(track) > nSigmaItsMin && itsResponse.nSigmaITS(track) < nSigmaItsMax) { - passedItsPidHel = true; + if (applyItsPid && pt < ptMaxItsPidDeut && (nSigmaITSdeut < nSigmaItsMin || nSigmaITSdeut > nSigmaItsMax)) { + passedItsPidDeut = false; } - if (!applyItsPid) { - passedItsPidProt = true; - passedItsPidDeut = true; - passedItsPidHel = true; + if (applyItsPid && (2.0 * pt) < ptMaxItsPidHel && (nSigmaITShel3 < nSigmaItsMin || nSigmaITShel3 > nSigmaItsMax)) { + passedItsPidHel = false; } - if (pt > ptMaxItsPidProt) - passedItsPidProt = true; - if (pt > ptMaxItsPidDeut) - passedItsPidDeut = true; - if ((2.0 * pt) > ptMaxItsPidHel) - passedItsPidHel = true; // antimatter if (track.sign() < 0) { @@ -882,35 +882,76 @@ struct AntinucleiInJets { void processEfficiency(SimCollisions const& collisions, MCTracks const& mcTracks, aod::McParticles const& mcParticles) { + // Loop over all simulated collision events for (const auto& collision : collisions) { - // event counter before event selection + // Count all generated events before applying any event selection criteria registryMC.fill(HIST("number_of_events_mc"), 0.5); - // event selection + // Apply event selection: require sel8 and vertex position within the allowed z range if (!collision.sel8() || std::fabs(collision.posZ()) > zVtx) continue; - // event counter after event selection + // Count events that pass the selection criteria registryMC.fill(HIST("number_of_events_mc"), 1.5); - // generated + // Loop over all generated Monte Carlo particles for the selected event for (const auto& particle : mcParticles) { + // primary particles if (!particle.isPhysicalPrimary()) continue; + // Fill (eta, pT) distribution of generated antiprotons if (particle.pdgCode() == kProtonBar) { registryMC.fill(HIST("antiproton_eta_pt_pythia"), particle.pt(), particle.eta()); } + // Select particles within the specified pseudorapidity interval if (particle.eta() < minEta || particle.eta() > maxEta) continue; + // Initialize weights for antiproton reweighting in Jet and UE cones + double wAntipJet2d(1.0), wAntipUe2d(1.0); + int ix = twoDweightsAntipJet->GetXaxis()->FindBin(particle.pt()); + int iy = twoDweightsAntipJet->GetYaxis()->FindBin(particle.eta()); + + // Retrieve 2D weights from histograms based on particle's (pT, eta) + wAntipJet2d = twoDweightsAntipJet->GetBinContent(ix, iy); + wAntipUe2d = twoDweightsAntipUe->GetBinContent(ix, iy); + + // Sanity checks: if (pT, eta) is out of histogram bounds, set default weight to 1.0 + if (ix == 0 || ix > twoDweightsAntipJet->GetNbinsX()) { + wAntipJet2d = 1.0; + wAntipUe2d = 1.0; + } + if (iy == 0 || iy > twoDweightsAntipJet->GetNbinsY()) { + wAntipJet2d = 1.0; + wAntipUe2d = 1.0; + } + + // Placeholder for 1D weight factors (e.g., for further corrections, still to be implemented) + double wAntipJetFinal(1.0), wAntipUeFinal(1.0); + + // Process different particle species based on PDG code switch (particle.pdgCode()) { case kProtonBar: - registryMC.fill(HIST("antiproton_incl_gen"), particle.pt()); + // Fill histograms with unweighted and weighted (2D and final) pT spectra for antiprotons + registryMC.fill(HIST("antiproton_gen_jet_unweighted"), particle.pt()); + registryMC.fill(HIST("antiproton_gen_ue_unweighted"), particle.pt()); + registryMC.fill(HIST("antiproton_gen_jet_weighted2d"), particle.pt(), wAntipJet2d); + registryMC.fill(HIST("antiproton_gen_ue_weighted2d"), particle.pt(), wAntipUe2d); + registryMC.fill(HIST("antiproton_gen_jet_weightedFinal"), particle.pt(), wAntipJetFinal); + registryMC.fill(HIST("antiproton_gen_ue_weightedFinal"), particle.pt(), wAntipUeFinal); + + // Fill additional histograms used for deriving or validating reweighting corrections + registryMC.fill(HIST("antiproton_forReweighting_jet_weighted2d"), particle.pt(), wAntipJet2d); + registryMC.fill(HIST("antiproton_forReweighting_ue_weighted2d"), particle.pt(), wAntipUe2d); + registryMC.fill(HIST("antiproton_forReweighting_jet_weightedFinal"), particle.pt(), wAntipJetFinal); + registryMC.fill(HIST("antiproton_forReweighting_ue_weightedFinal"), particle.pt(), wAntipUeFinal); break; + + // Generated spectra for other light nuclei case o2::constants::physics::Pdg::kDeuteron: registryMC.fill(HIST("deuteron_incl_gen"), particle.pt()); break; @@ -926,70 +967,93 @@ struct AntinucleiInJets { } } - // ITS pid using cluster size + // ITS PID response utility o2::aod::ITSResponse itsResponse; - // Reconstructed Tracks + // Loop over all reconstructed MC tracks for (auto const& track : mcTracks) { - // Track Selection + // Apply standard track selection criteria if (!passedTrackSelection(track)) continue; + + // Cut on transverse and longitudinal distance of closest approach if (std::fabs(track.dcaXY()) > maxDcaxy) continue; if (std::fabs(track.dcaZ()) > maxDcaz) continue; - // Get MC Particle + // Skip tracks that are not associated with a true MC particle if (!track.has_mcParticle()) continue; const auto particle = track.mcParticle(); - // Variables + // select only physical primary particles + if (!particle.isPhysicalPrimary()) + continue; + + // Retrieve PID responses from TPC and TOF detectors for proton, deuteron, helium-3 double nsigmaTPCPr = track.tpcNSigmaPr(); double nsigmaTOFPr = track.tofNSigmaPr(); double nsigmaTPCDe = track.tpcNSigmaDe(); double nsigmaTOFDe = track.tofNSigmaDe(); double nsigmaTPCHe = track.tpcNSigmaHe(); + double pt = track.pt(); // particle identification using the ITS cluster size - bool passedItsPidProt(false), passedItsPidDeut(false), passedItsPidHel(false); - if (itsResponse.nSigmaITS(track) > nSigmaItsMin && itsResponse.nSigmaITS(track) < nSigmaItsMax) { - passedItsPidProt = true; - } - if (itsResponse.nSigmaITS(track) > nSigmaItsMin && itsResponse.nSigmaITS(track) < nSigmaItsMax) { - passedItsPidDeut = true; + bool passedItsPidProt(true), passedItsPidDeut(true), passedItsPidHel(true); + double nSigmaITSprot = static_cast(itsResponse.nSigmaITS(track)); + double nSigmaITSdeut = static_cast(itsResponse.nSigmaITS(track)); + double nSigmaITShel3 = static_cast(itsResponse.nSigmaITS(track)); + + if (applyItsPid && pt < ptMaxItsPidProt && (nSigmaITSprot < nSigmaItsMin || nSigmaITSprot > nSigmaItsMax)) { + passedItsPidProt = false; } - if (itsResponse.nSigmaITS(track) > nSigmaItsMin && itsResponse.nSigmaITS(track) < nSigmaItsMax) { - passedItsPidHel = true; + if (applyItsPid && pt < ptMaxItsPidDeut && (nSigmaITSdeut < nSigmaItsMin || nSigmaITSdeut > nSigmaItsMax)) { + passedItsPidDeut = false; } - if (!applyItsPid) { - passedItsPidProt = true; - passedItsPidDeut = true; - passedItsPidHel = true; + if (applyItsPid && (2.0 * pt) < ptMaxItsPidHel && (nSigmaITShel3 < nSigmaItsMin || nSigmaITShel3 > nSigmaItsMax)) { + passedItsPidHel = false; } - if (track.pt() > ptMaxItsPidProt) - passedItsPidProt = true; - if (track.pt() > ptMaxItsPidDeut) - passedItsPidDeut = true; - if ((2.0 * track.pt()) > ptMaxItsPidHel) - passedItsPidHel = true; - if (particle.pdgCode() == kProtonBar) - registryMC.fill(HIST("antiproton_incl_all"), track.pt()); - - if (!particle.isPhysicalPrimary()) - continue; + // Get correction weights as a function of (pt, eta) from external histograms + double wAntipJet2d(1.0), wAntipUe2d(1.0); + int ix = twoDweightsAntipJet->GetXaxis()->FindBin(particle.pt()); + int iy = twoDweightsAntipJet->GetYaxis()->FindBin(particle.eta()); + wAntipJet2d = twoDweightsAntipJet->GetBinContent(ix, iy); + wAntipUe2d = twoDweightsAntipUe->GetBinContent(ix, iy); + + // Edge protection: reset weights to 1 if out of histogram range + if (ix == 0 || ix > twoDweightsAntipJet->GetNbinsX()) { + wAntipJet2d = 1.0; + wAntipUe2d = 1.0; + } + if (iy == 0 || iy > twoDweightsAntipJet->GetNbinsY()) { + wAntipJet2d = 1.0; + wAntipUe2d = 1.0; + } - if (particle.pdgCode() == kProtonBar) - registryMC.fill(HIST("antiproton_incl_prim"), track.pt()); + // 1d weights (to be implemented) + double wAntipJetFinal(1.0), wAntipUeFinal(1.0); // antiprotons - if (particle.pdgCode() == kProtonBar && passedItsPidProt) { - if (nsigmaTPCPr > minNsigmaTpc && nsigmaTPCPr < maxNsigmaTpc) { - registryMC.fill(HIST("antiproton_incl_rec_tpc"), track.pt()); - if (track.hasTOF() && nsigmaTOFPr > minNsigmaTof && nsigmaTOFPr < maxNsigmaTof) - registryMC.fill(HIST("antiproton_incl_rec_tof"), track.pt()); + if (particle.pdgCode() == kProtonBar) { + if (passedItsPidProt && nsigmaTPCPr > minNsigmaTpc && nsigmaTPCPr < maxNsigmaTpc) { + registryMC.fill(HIST("antiproton_recTpc_jet_unweighted"), track.pt()); + registryMC.fill(HIST("antiproton_recTpc_ue_unweighted"), track.pt()); + registryMC.fill(HIST("antiproton_recTpc_jet_weighted2d"), track.pt(), wAntipJet2d); + registryMC.fill(HIST("antiproton_recTpc_ue_weighted2d"), track.pt(), wAntipUe2d); + registryMC.fill(HIST("antiproton_recTpc_jet_weightedFinal"), track.pt(), wAntipJetFinal); + registryMC.fill(HIST("antiproton_recTpc_ue_weightedFinal"), track.pt(), wAntipUeFinal); + + if (track.hasTOF() && nsigmaTOFPr > minNsigmaTof && nsigmaTOFPr < maxNsigmaTof) { + registryMC.fill(HIST("antiproton_recTof_jet_unweighted"), track.pt()); + registryMC.fill(HIST("antiproton_recTof_ue_unweighted"), track.pt()); + registryMC.fill(HIST("antiproton_recTof_jet_weighted2d"), track.pt(), wAntipJet2d); + registryMC.fill(HIST("antiproton_recTof_ue_weighted2d"), track.pt(), wAntipUe2d); + registryMC.fill(HIST("antiproton_recTof_jet_weightedFinal"), track.pt(), wAntipJetFinal); + registryMC.fill(HIST("antiproton_recTof_ue_weightedFinal"), track.pt(), wAntipUeFinal); + } } } @@ -1031,91 +1095,99 @@ struct AntinucleiInJets { void processJetsMCgen(SimCollisions const& collisions, aod::McParticles const& mcParticles) { + // Loop over all simulated collision events for (const auto& collision : collisions) { - // event selection + // Apply event selection: require sel8 and vertex position within the allowed z range if (!collision.sel8() || std::fabs(collision.posZ()) > zVtx) continue; + // Loop over all MC particles and select physical primaries within acceptance std::vector fjParticles; for (const auto& particle : mcParticles) { - if (!particle.isPhysicalPrimary()) continue; double minPtParticle = 0.1; if (particle.eta() < minEta || particle.eta() > maxEta || particle.pt() < minPtParticle) continue; + // Build 4-momentum assuming charged pion mass double energy = std::sqrt(particle.p() * particle.p() + MassPionCharged * MassPionCharged); fastjet::PseudoJet fourMomentum(particle.px(), particle.py(), particle.pz(), energy); fourMomentum.set_user_index(particle.pdgCode()); fjParticles.emplace_back(fourMomentum); } - // reject empty events + + // Skip events with no particles if (fjParticles.size() < 1) continue; - // cluster particles using the anti-kt algorithm + // Cluster MC particles into jets using anti-kt algorithm fastjet::JetDefinition jetDef(fastjet::antikt_algorithm, rJet); - fastjet::AreaDefinition areaDef(fastjet::active_area, fastjet::GhostedAreaSpec(1.0)); // active_area_explicit_ghosts + fastjet::AreaDefinition areaDef(fastjet::active_area, fastjet::GhostedAreaSpec(1.0)); 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] = backgroundSub.estimateRhoPerpCone(fjParticles, jets); - // loop over jets + // Loop over clustered jets for (const auto& jet : jets) { - // jet must be fully contained in the acceptance + // Jet must be fully contained in acceptance if ((std::fabs(jet.eta()) + rJet) > (maxEta - deltaEtaEdge)) continue; - // jet pt must be larger than threshold + // 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; - // jet properties and perpendicular cone + // Analyze jet constituents and search for antiprotons 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); - TVector3 ueAxis2(0, 0, 0); - getPerpendicularAxis(jetAxis, ueAxis1, +1); - getPerpendicularAxis(jetAxis, ueAxis2, -1); - - // loop over jet constituents for (const auto& particle : jetConstituents) { - if (particle.user_index() != kProtonBar) continue; - registryMC.fill(HIST("antiproton_jet_gen"), particle.pt()); registryMC.fill(HIST("antiproton_eta_pt_jet"), particle.pt(), particle.eta()); + registryMC.fill(HIST("antiproton_gen_jet_antikt"), particle.pt()); } - // loop over underlying-event - for (const auto& particle : mcParticles) { + // 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); + getPerpendicularAxis(jetAxis, ueAxis1, +1); + getPerpendicularAxis(jetAxis, ueAxis2, -1); + // Loop over MC particles to analyze underlying event region + for (const auto& particle : mcParticles) { if (!particle.isPhysicalPrimary()) continue; double minPtParticle = 0.1; if (particle.eta() < minEta || particle.eta() > maxEta || particle.pt() < minPtParticle) continue; + // Compute distance of particle from both perpendicular cone axes double deltaEtaUe1 = particle.eta() - ueAxis1.Eta(); double deltaPhiUe1 = getDeltaPhi(particle.phi(), ueAxis1.Phi()); double deltaRUe1 = std::sqrt(deltaEtaUe1 * deltaEtaUe1 + deltaPhiUe1 * deltaPhiUe1); double deltaEtaUe2 = particle.eta() - ueAxis2.Eta(); double deltaPhiUe2 = getDeltaPhi(particle.phi(), ueAxis2.Phi()); double deltaRUe2 = std::sqrt(deltaEtaUe2 * deltaEtaUe2 + deltaPhiUe2 * deltaPhiUe2); + + // Select particles inside one of the perpendicular cones if (deltaRUe1 > coneRadius && deltaRUe2 > coneRadius) continue; + // Select antiprotons based on PDG if (particle.pdgCode() != kProtonBar) continue; - registryMC.fill(HIST("antiproton_ue_gen"), particle.pt()); registryMC.fill(HIST("antiproton_eta_pt_ue"), particle.pt(), particle.eta()); + registryMC.fill(HIST("antiproton_gen_ue_antikt"), particle.pt()); } } } @@ -1124,13 +1196,17 @@ struct AntinucleiInJets { void processJetsMCrec(SimCollisions const& collisions, MCTracks const& mcTracks, McParticles const&) { + // Initialize ITS PID response tool + o2::aod::ITSResponse itsResponse; + + // Loop over all simulated collision events for (const auto& collision : collisions) { - // event selection + // Apply event selection: require sel8 and vertex position within the allowed z range if (!collision.sel8() || std::fabs(collision.posZ()) > zVtx) - return; + continue; - // loop over reconstructed tracks + // Prepare particle list for jet clustering int id(-1); std::vector fjParticles; for (auto const& track : mcTracks) { @@ -1138,161 +1214,151 @@ struct AntinucleiInJets { if (!passedTrackSelectionForJetReconstruction(track)) continue; - // 4-momentum representations of a particle + // Build 4-momentum assuming charged pion mass fastjet::PseudoJet fourMomentum(track.px(), track.py(), track.pz(), track.energy(MassPionCharged)); fourMomentum.set_user_index(id); fjParticles.emplace_back(fourMomentum); } - // reject empty events + + // Skip events with no particles if (fjParticles.size() < 1) continue; - // cluster particles using the anti-kt algorithm + // Perform jet clustering using anti-kT algorithm with active area correction fastjet::JetDefinition jetDef(fastjet::antikt_algorithm, rJet); fastjet::AreaDefinition areaDef(fastjet::active_area, fastjet::GhostedAreaSpec(1.0)); 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] = backgroundSub.estimateRhoPerpCone(fjParticles, jets); - // loop over reconstructed jets + // Loop over reconstructed jets for (const auto& jet : jets) { - // get jet constituents + // Retrieve constituents of the current jet std::vector jetConstituents = jet.constituents(); - // calculate generated jet pt + // Estimate generator-level jet pT by summing pT of matched MC particles double jetPtGen(0); for (const auto& particle : jetConstituents) { - - // get corresponding track auto const& track = mcTracks.iteratorAt(particle.user_index()); if (!track.has_mcParticle()) continue; const auto mcparticle = track.mcParticle(); - jetPtGen = jetPtGen + mcparticle.pt(); + jetPtGen += mcparticle.pt(); } - // jet must be fully contained in the acceptance + // Jet must be fully contained in acceptance if ((std::fabs(jet.eta()) + rJet) > (maxEta - deltaEtaEdge)) continue; - // fill detector response matrix - registryMC.fill(HIST("detectorResponseMatrix"), jet.pt(), jetPtGen - jet.pt()); // maybe it should be filled after bkg sub + // Fill detector response matrix + registryMC.fill(HIST("detectorResponseMatrix"), jet.pt(), jetPtGen - jet.pt()); registryMC.fill(HIST("generatedVsReconstructedPt"), jet.pt(), jetPtGen); - // jet pt must be larger than threshold + // Subtract estimated background contribution from jet 4-momentum auto jetForSub = jet; fastjet::PseudoJet jetMinusBkg = backgroundSub.doRhoAreaSub(jetForSub, rhoPerp, rhoMPerp); + + // Apply jet pT threshold if (getCorrectedPt(jetMinusBkg.pt(), responseMatrix) < minJetPt) continue; - // perpendicular cone + // 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); - TVector3 ueAxis2(0, 0, 0); + TVector3 ueAxis1(0, 0, 0), ueAxis2(0, 0, 0); getPerpendicularAxis(jetAxis, ueAxis1, +1); getPerpendicularAxis(jetAxis, ueAxis2, -1); - o2::aod::ITSResponse itsResponse; // to be implemented - - // loop over jet constituents + // Analyze antiproton candidates among jet constituents for (const auto& particle : jetConstituents) { - - // get corresponding track and apply track selection criteria auto const& track = mcTracks.iteratorAt(particle.user_index()); - if (!passedTrackSelection(track)) - continue; - if (std::fabs(track.dcaXY()) > maxDcaxy || std::fabs(track.dcaZ()) > maxDcaz) - continue; - if (track.sign() > 0) - continue; if (!track.has_mcParticle()) continue; + + // Apply standard track quality and PID selection + if (!passedTrackSelection(track) || std::fabs(track.dcaXY()) > maxDcaxy || std::fabs(track.dcaZ()) > maxDcaz) + continue; const auto mcparticle = track.mcParticle(); - if (mcparticle.pdgCode() != kProtonBar) + if (track.sign() > 0 || mcparticle.pdgCode() != kProtonBar) continue; - // variables + // PID variables double nsigmaTPCPr = track.tpcNSigmaPr(); double nsigmaTOFPr = track.tofNSigmaPr(); - registryMC.fill(HIST("antiproton_jet_all"), track.pt()); + // particle identification using the ITS cluster size + double pt = track.pt(); + bool passedItsPidProt(true); + double nSigmaITSprot = static_cast(itsResponse.nSigmaITS(track)); + if (applyItsPid && pt < ptMaxItsPidProt && (nSigmaITSprot < nSigmaItsMin || nSigmaITSprot > nSigmaItsMax)) { + passedItsPidProt = false; + } + + // Inclusive antiproton spectrum + registryMC.fill(HIST("antiproton_incl_jet"), track.pt()); + // Select physical primary antiprotons if (!mcparticle.isPhysicalPrimary()) continue; + registryMC.fill(HIST("antiproton_prim_jet"), track.pt()); - registryMC.fill(HIST("antiproton_jet_prim"), track.pt()); - - // particle identification using the ITS cluster size - bool passedItsPidProt(false); - if (itsResponse.nSigmaITS(track) > nSigmaItsMin && itsResponse.nSigmaITS(track) < nSigmaItsMax) { - passedItsPidProt = true; - } - if (!applyItsPid) - passedItsPidProt = true; - if (track.pt() > ptMaxItsPidProt) - passedItsPidProt = true; - - if (passedItsPidProt) { - registryMC.fill(HIST("antiproton_jet_rec_tpc"), track.pt(), nsigmaTPCPr); - registryMC.fill(HIST("antiproton_jet_tpc_rec_vs_generatedptjet"), track.pt(), jetPtGen); - if (nsigmaTPCPr > minNsigmaTpc && nsigmaTPCPr < maxNsigmaTpc && track.hasTOF()) - registryMC.fill(HIST("antiproton_jet_rec_tof"), track.pt(), nsigmaTOFPr); - registryMC.fill(HIST("antiproton_jet_tof_rec_vs_generatedptjet"), track.pt(), jetPtGen); + // Fill histograms (TPC and TOF) only for selected candidates + if (passedItsPidProt && nsigmaTPCPr > minNsigmaTpc && nsigmaTPCPr < maxNsigmaTpc) { + registryMC.fill(HIST("antiproton_recTpc_jet_antikt"), track.pt()); + if (track.hasTOF() && nsigmaTOFPr > minNsigmaTof && nsigmaTOFPr < maxNsigmaTof) { + registryMC.fill(HIST("antiproton_recTof_jet_antikt"), track.pt()); + } } } - // underlying event + // Analyze antiprotons in the Underlying Event (UE) using perpendicular cones for (auto const& track : mcTracks) { - - // get corresponding track and apply track selection criteria - if (!passedTrackSelection(track)) - continue; - if (std::fabs(track.dcaXY()) > maxDcaxy || std::fabs(track.dcaZ()) > maxDcaz) - continue; - if (track.sign() > 0) + if (!passedTrackSelection(track) || std::fabs(track.dcaXY()) > maxDcaxy || std::fabs(track.dcaZ()) > maxDcaz) continue; - if (!track.has_mcParticle()) continue; + const auto mcparticle = track.mcParticle(); - if (mcparticle.pdgCode() != kProtonBar) + if (track.sign() > 0 || mcparticle.pdgCode() != kProtonBar) continue; + // Compute distance from UE cones double deltaEtaUe1 = track.eta() - ueAxis1.Eta(); double deltaPhiUe1 = getDeltaPhi(track.phi(), ueAxis1.Phi()); double deltaRUe1 = std::sqrt(deltaEtaUe1 * deltaEtaUe1 + deltaPhiUe1 * deltaPhiUe1); double deltaEtaUe2 = track.eta() - ueAxis2.Eta(); double deltaPhiUe2 = getDeltaPhi(track.phi(), ueAxis2.Phi()); double deltaRUe2 = std::sqrt(deltaEtaUe2 * deltaEtaUe2 + deltaPhiUe2 * deltaPhiUe2); + + // Require particle to be within at least one UE cone if (deltaRUe1 > coneRadius && deltaRUe2 > coneRadius) continue; - // variables + // PID variables double nsigmaTPCPr = track.tpcNSigmaPr(); double nsigmaTOFPr = track.tofNSigmaPr(); - registryMC.fill(HIST("antiproton_ue_all"), track.pt()); - if (!mcparticle.isPhysicalPrimary()) - continue; - registryMC.fill(HIST("antiproton_ue_prim"), track.pt()); - // particle identification using the ITS cluster size - bool passedItsPidProt(false); - if (itsResponse.nSigmaITS(track) > nSigmaItsMin && itsResponse.nSigmaITS(track) < nSigmaItsMax) { - passedItsPidProt = true; + double pt = track.pt(); + bool passedItsPidProt(true); + double nSigmaITSprot = static_cast(itsResponse.nSigmaITS(track)); + if (applyItsPid && pt < ptMaxItsPidProt && (nSigmaITSprot < nSigmaItsMin || nSigmaITSprot > nSigmaItsMax)) { + passedItsPidProt = false; } - if (!applyItsPid) - passedItsPidProt = true; - if (track.pt() > ptMaxItsPidProt) - passedItsPidProt = true; - if (passedItsPidProt) { - if (nsigmaTPCPr > minNsigmaTpc && nsigmaTPCPr < maxNsigmaTpc) { - registryMC.fill(HIST("antiproton_ue_rec_tpc"), track.pt()); - if (track.hasTOF() && nsigmaTOFPr > minNsigmaTof && nsigmaTOFPr < maxNsigmaTof) - registryMC.fill(HIST("antiproton_ue_rec_tof"), track.pt()); + registryMC.fill(HIST("antiproton_incl_ue"), track.pt()); + if (!mcparticle.isPhysicalPrimary()) + continue; + registryMC.fill(HIST("antiproton_prim_ue"), track.pt()); + + // Fill histograms in UE + if (passedItsPidProt && nsigmaTPCPr > minNsigmaTpc && nsigmaTPCPr < maxNsigmaTpc) { + registryMC.fill(HIST("antiproton_recTpc_ue_antikt"), track.pt()); + if (track.hasTOF() && nsigmaTOFPr > minNsigmaTof && nsigmaTOFPr < maxNsigmaTof) { + registryMC.fill(HIST("antiproton_recTof_ue_antikt"), track.pt()); } } } From 35e5481adddd907c4a1e7d4db313d93f5b51e79a Mon Sep 17 00:00:00 2001 From: smaff92 <33285879+smaff92@users.noreply.github.com> Date: Wed, 18 Jun 2025 15:51:25 +0900 Subject: [PATCH 123/871] [PWGJE] Removal of config for skimmed trigger (#11664) --- PWGJE/Tasks/statPromptPhoton.cxx | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/PWGJE/Tasks/statPromptPhoton.cxx b/PWGJE/Tasks/statPromptPhoton.cxx index 75fdb2ca5bf..977b94741c5 100644 --- a/PWGJE/Tasks/statPromptPhoton.cxx +++ b/PWGJE/Tasks/statPromptPhoton.cxx @@ -99,7 +99,6 @@ struct statPromptPhoton { Configurable cfgGenHistograms{"cfgGenHistograms", false, "Enables Generated histograms"}; Configurable cfgRecHistograms{"cfgRecHistograms", false, "Enables Reconstructed histograms"}; Configurable cfgDataHistograms{"cfgDataHistograms", false, "Enables Data histograms"}; - Configurable cfgSkimmedTrigger{"cfgSkimmedTrigger", false, "Enables trigger for skimmied datasets (2023 onwards)"}; Configurable cfgTriggerMasks{"cfgTriggerMasks", "", "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"}; Configurable cfgDebug{"cfgDebug", false, "Enables debug information for local running"}; @@ -635,11 +634,9 @@ struct statPromptPhoton { } histos.fill(HIST("REC_nEvents"), 2.5); - if (cfgSkimmedTrigger) { - if (!jetderiveddatautilities::selectTrigger(collision, triggerMaskBits)) { - return; - } - } // JE Software Triggers + if (!jetderiveddatautilities::selectTrigger(collision, triggerMaskBits)) { + return; + } histos.fill(HIST("REC_nEvents"), 3.5); @@ -1117,11 +1114,9 @@ struct statPromptPhoton { histos.fill(HIST("DATA_nEvents"), 2.5); - if (cfgSkimmedTrigger) { if (!jetderiveddatautilities::selectTrigger(collision, triggerMaskBits)) { return; } - } // JE Software Triggers histos.fill(HIST("DATA_nEvents"), 3.5); From 5a1aa28f18edce50573e2663fcdbe01b0504f69e Mon Sep 17 00:00:00 2001 From: feisenhu <53603353+feisenhu@users.noreply.github.com> Date: Wed, 18 Jun 2025 09:18:32 +0200 Subject: [PATCH 124/871] [PWGEM] SingleTrackQC update to THnSparse Data and MC (#11640) --- PWGEM/Dilepton/Core/SingleTrackQC.h | 35 +++++++++++--------------- PWGEM/Dilepton/Core/SingleTrackQCMC.h | 36 ++++++++++++--------------- 2 files changed, 31 insertions(+), 40 deletions(-) diff --git a/PWGEM/Dilepton/Core/SingleTrackQC.h b/PWGEM/Dilepton/Core/SingleTrackQC.h index 0f6da8285dd..f97890e68e5 100644 --- a/PWGEM/Dilepton/Core/SingleTrackQC.h +++ b/PWGEM/Dilepton/Core/SingleTrackQC.h @@ -81,10 +81,9 @@ struct SingleTrackQC { // Configurable cfgNtracksPV08Min{"cfgNtracksPV08Min", -1, "min. multNTracksPV"}; // Configurable cfgNtracksPV08Max{"cfgNtracksPV08Max", static_cast(1e+9), "max. multNTracksPV"}; Configurable cfgApplyWeightTTCA{"cfgApplyWeightTTCA", false, "flag to apply weighting by 1/N"}; - Configurable cfgDCAType{"cfgDCAType", 0, "type of DCA for output. 0:3D, 1:XY, 2:Z, else:3D"}; ConfigurableAxis ConfPtlBins{"ConfPtlBins", {VARIABLE_WIDTH, 0.00, 0.05, 0.10, 0.15, 0.20, 0.30, 0.40, 0.50, 0.60, 0.70, 0.80, 0.90, 1.00, 1.10, 1.20, 1.30, 1.40, 1.50, 1.60, 1.70, 1.80, 1.90, 2.00, 2.50, 3.00, 3.50, 4.00, 4.50, 5.00, 6.00, 7.00, 8.00, 9.00, 10.00}, "pTl bins for output histograms"}; - ConfigurableAxis ConfDCABins{"ConfDCABins", {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.5, 3.0, 3.5, 4.0, 4.5, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0}, "DCA bins for output histograms"}; + ConfigurableAxis ConfDCABins{"ConfDCABins", {VARIABLE_WIDTH, -10.0, -9.0, -8.0, -7.0, -6.0, -5.0, -4.5, -4.0, -3.5, -3.0, -2.5, -2.0, -1.9, -1.8, -1.7, -1.6, -1.5, -1.4, -1.3, -1.2, -1.1, -1.0, -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, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0}, "DCA bins for output histograms"}; EMEventCut fEMEventCut; struct : ConfigurableGroup { @@ -228,16 +227,15 @@ struct SingleTrackQC { const AxisSpec axis_pt{ConfPtlBins, "p_{T,e} (GeV/c)"}; const AxisSpec axis_eta{20, -1.0, +1.0, "#eta_{e}"}; const AxisSpec axis_phi{36, 0.0, 2 * M_PI, "#varphi_{e} (rad.)"}; - std::string dca_axis_title = "DCA_{e}^{3D} (#sigma)"; - if (cfgDCAType == 1) { - dca_axis_title = "DCA_{e}^{XY} (#sigma)"; - } else if (cfgDCAType == 2) { - dca_axis_title = "DCA_{e}^{Z} (#sigma)"; - } - const AxisSpec axis_dca{ConfDCABins, dca_axis_title}; + std::string dca3D_axis_title = "DCA_{e}^{3D} (#sigma)"; + std::string dcaXY_axis_title = "DCA_{e}^{XY} (#sigma)"; + std::string dcaZ_axis_title = "DCA_{e}^{Z} (#sigma)"; + const AxisSpec axis_dca3D{ConfDCABins, dca3D_axis_title}; + const AxisSpec axis_dcaXY{ConfDCABins, dcaXY_axis_title}; + const AxisSpec axis_dcaZ{ConfDCABins, dcaZ_axis_title}; // track info - fRegistry.add("Track/positive/hs", "rec. single electron", kTHnSparseD, {axis_pt, axis_eta, axis_phi, axis_dca}, true); + fRegistry.add("Track/positive/hs", "rec. single electron", kTHnSparseD, {axis_pt, axis_eta, axis_phi, axis_dca3D, axis_dcaXY, axis_dcaZ}, true); fRegistry.add("Track/positive/hQoverPt", "q/pT;q/p_{T} (GeV/c)^{-1}", kTH1F, {{2000, -5, 5}}, false); fRegistry.add("Track/positive/hDCAxyz", "DCA xy vs. z;DCA_{xy} (cm);DCA_{z} (cm)", kTH2F, {{200, -1.0f, 1.0f}, {700, -3.5f, 3.5f}}, false); fRegistry.add("Track/positive/hDCAxyzSigma", "DCA xy vs. z;DCA_{xy} (#sigma);DCA_{z} (#sigma)", kTH2F, {{400, -20.0f, 20.0f}, {400, -20.0f, 20.0f}}, false); @@ -473,18 +471,15 @@ struct SingleTrackQC { weight = map_weight[track.globalIndex()]; } - float dca = dca3DinSigma(track); - if (cfgDCAType == 1) { - dca = dcaXYinSigma(track); - } else if (cfgDCAType == 2) { - dca = dcaZinSigma(track); - } + float dca3D = dca3DinSigma(track); + float dcaXY = dcaXYinSigma(track); + float dcaZ = dcaZinSigma(track); if (track.sign() > 0) { - fRegistry.fill(HIST("Track/positive/hs"), track.pt(), track.eta(), track.phi(), dca, weight); + fRegistry.fill(HIST("Track/positive/hs"), track.pt(), track.eta(), track.phi(), dca3D, dcaXY, dcaZ, weight); fRegistry.fill(HIST("Track/positive/hQoverPt"), track.sign() / track.pt()); fRegistry.fill(HIST("Track/positive/hDCAxyz"), track.dcaXY(), track.dcaZ()); - fRegistry.fill(HIST("Track/positive/hDCAxyzSigma"), track.dcaXY() / std::sqrt(track.cYY()), track.dcaZ() / std::sqrt(track.cZZ())); + fRegistry.fill(HIST("Track/positive/hDCAxyzSigma"), dcaXY, dcaZ); fRegistry.fill(HIST("Track/positive/hDCAxyRes_Pt"), track.pt(), std::sqrt(track.cYY()) * 1e+4); // convert cm to um fRegistry.fill(HIST("Track/positive/hDCAzRes_Pt"), track.pt(), std::sqrt(track.cZZ()) * 1e+4); // convert cm to um fRegistry.fill(HIST("Track/positive/hDCA3dRes_Pt"), track.pt(), sigmaDca3D(track) * 1e+4); // convert cm to um @@ -521,10 +516,10 @@ struct SingleTrackQC { fRegistry.fill(HIST("Track/positive/hITSNsigmaKa"), track.p(), track.itsNSigmaKa()); fRegistry.fill(HIST("Track/positive/hITSNsigmaPr"), track.p(), track.itsNSigmaPr()); } else { - fRegistry.fill(HIST("Track/negative/hs"), track.pt(), track.eta(), track.phi(), dca, weight); + fRegistry.fill(HIST("Track/negative/hs"), track.pt(), track.eta(), track.phi(), dca3D, dcaXY, dcaZ, weight); fRegistry.fill(HIST("Track/negative/hQoverPt"), track.sign() / track.pt()); fRegistry.fill(HIST("Track/negative/hDCAxyz"), track.dcaXY(), track.dcaZ()); - fRegistry.fill(HIST("Track/negative/hDCAxyzSigma"), track.dcaXY() / std::sqrt(track.cYY()), track.dcaZ() / std::sqrt(track.cZZ())); + fRegistry.fill(HIST("Track/negative/hDCAxyzSigma"), dcaXY, dcaZ); fRegistry.fill(HIST("Track/negative/hDCAxyRes_Pt"), track.pt(), std::sqrt(track.cYY()) * 1e+4); // convert cm to um fRegistry.fill(HIST("Track/negative/hDCAzRes_Pt"), track.pt(), std::sqrt(track.cZZ()) * 1e+4); // convert cm to um fRegistry.fill(HIST("Track/negative/hDCA3dRes_Pt"), track.pt(), sigmaDca3D(track) * 1e+4); // convert cm to um diff --git a/PWGEM/Dilepton/Core/SingleTrackQCMC.h b/PWGEM/Dilepton/Core/SingleTrackQCMC.h index dfcc80d32d2..c452483b3ea 100644 --- a/PWGEM/Dilepton/Core/SingleTrackQCMC.h +++ b/PWGEM/Dilepton/Core/SingleTrackQCMC.h @@ -88,11 +88,10 @@ struct SingleTrackQCMC { // Configurable cfgNtracksPV08Max{"cfgNtracksPV08Max", static_cast(1e+9), "max. multNTracksPV"}; Configurable cfgFillQA{"cfgFillQA", false, "flag to fill QA histograms"}; Configurable cfgApplyWeightTTCA{"cfgApplyWeightTTCA", false, "flag to apply weighting by 1/N"}; - Configurable cfgDCAType{"cfgDCAType", 0, "type of DCA for output. 0:3D, 1:XY, 2:Z, else:3D"}; Configurable cfgRequireTrueAssociation{"cfgRequireTrueAssociation", false, "flag to require true mc collision association"}; ConfigurableAxis ConfPtlBins{"ConfPtlBins", {VARIABLE_WIDTH, 0.00, 0.05, 0.10, 0.15, 0.20, 0.30, 0.40, 0.50, 0.60, 0.70, 0.80, 0.90, 1.00, 1.10, 1.20, 1.30, 1.40, 1.50, 1.60, 1.70, 1.80, 1.90, 2.00, 2.50, 3.00, 3.50, 4.00, 4.50, 5.00, 6.00, 7.00, 8.00, 9.00, 10.00}, "pTl bins for output histograms"}; - ConfigurableAxis ConfDCABins{"ConfDCABins", {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.5, 3.0, 3.5, 4.0, 4.5, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0}, "DCA bins for output histograms"}; + ConfigurableAxis ConfDCABins{"ConfDCABins", {VARIABLE_WIDTH, -10.0, -9.0, -8.0, -7.0, -6.0, -5.0, -4.5, -4.0, -3.5, -3.0, -2.5, -2.0, -1.9, -1.8, -1.7, -1.6, -1.5, -1.4, -1.3, -1.2, -1.1, -1.0, -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, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0}, "DCA bins for output histograms"}; EMEventCut fEMEventCut; struct : ConfigurableGroup { @@ -247,13 +246,13 @@ struct SingleTrackQCMC { const AxisSpec axis_eta{20, -1.0, +1.0, "#eta_{e}"}; const AxisSpec axis_phi{36, 0.0, 2 * M_PI, "#varphi_{e} (rad.)"}; const AxisSpec axis_charge_gen{3, -1.5, +1.5, "true charge"}; - std::string dca_axis_title = "DCA_{e}^{3D} (#sigma)"; - if (cfgDCAType == 1) { - dca_axis_title = "DCA_{e}^{XY} (#sigma)"; - } else if (cfgDCAType == 2) { - dca_axis_title = "DCA_{e}^{Z} (#sigma)"; - } - const AxisSpec axis_dca{ConfDCABins, dca_axis_title}; + std::string dca3D_axis_title = "DCA_{e}^{3D} (#sigma)"; + std::string dcaXY_axis_title = "DCA_{e}^{XY} (#sigma)"; + std::string dcaZ_axis_title = "DCA_{e}^{Z} (#sigma)"; + + const AxisSpec axis_dca3D{ConfDCABins, dca3D_axis_title}; + const AxisSpec axis_dcaXY{ConfDCABins, dcaXY_axis_title}; + const AxisSpec axis_dcaZ{ConfDCABins, dcaZ_axis_title}; // generated info fRegistry.add("Generated/lf/hs", "gen. single electron", kTHnSparseD, {axis_pt, axis_eta, axis_phi, axis_charge_gen}, true); @@ -267,7 +266,7 @@ struct SingleTrackQCMC { fRegistry.addClone("Generated/lf/", "Generated/b2c2l/"); // track info - fRegistry.add("Track/lf/positive/hs", "rec. single electron", kTHnSparseD, {axis_pt, axis_eta, axis_phi, axis_dca, axis_charge_gen}, true); + fRegistry.add("Track/lf/positive/hs", "rec. single electron", kTHnSparseD, {axis_pt, axis_eta, axis_phi, axis_dca3D, axis_dcaXY, axis_dcaZ, axis_charge_gen}, true); if (cfgFillQA) { fRegistry.add("Track/lf/positive/hQoverPt", "q/pT;q/p_{T} (GeV/c)^{-1}", kTH1F, {{400, -20, 20}}, false); fRegistry.add("Track/lf/positive/hDCAxyz", "DCA xy vs. z;DCA_{xy} (cm);DCA_{z} (cm)", kTH2F, {{200, -1.0f, 1.0f}, {700, -3.5f, 3.5f}}, false); @@ -570,12 +569,9 @@ struct SingleTrackQCMC { void fillElectronInfo(TTrack const& track) { auto mctrack = track.template emmcparticle_as(); - float dca = dca3DinSigma(track); - if (cfgDCAType == 1) { - dca = dcaXYinSigma(track); - } else if (cfgDCAType == 2) { - dca = dcaZinSigma(track); - } + float dca3D = dca3DinSigma(track); + float dcaXY = dcaXYinSigma(track); + float dcaZ = dcaZinSigma(track); float weight = 1.f; if (cfgApplyWeightTTCA) { @@ -584,11 +580,11 @@ struct SingleTrackQCMC { // LOGF(info, "map_weight[%d] = %f", track.globalIndex(), weight); if (track.sign() > 0) { - fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hs"), track.pt(), track.eta(), track.phi(), dca, -mctrack.pdgCode() / pdg_lepton, weight); + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hs"), track.pt(), track.eta(), track.phi(), dca3D, dcaXY, dcaZ, -mctrack.pdgCode() / pdg_lepton, weight); if (cfgFillQA) { fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hQoverPt"), track.sign() / track.pt()); fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hDCAxyz"), track.dcaXY(), track.dcaZ()); - fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hDCAxyzSigma"), track.dcaXY() / std::sqrt(track.cYY()), track.dcaZ() / std::sqrt(track.cZZ())); + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hDCAxyzSigma"), dcaXY, dcaZ); fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hDCAxyRes_Pt"), track.pt(), std::sqrt(track.cYY()) * 1e+4); // convert cm to um fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hDCAzRes_Pt"), track.pt(), std::sqrt(track.cZZ()) * 1e+4); // convert cm to um fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hDCA3dRes_Pt"), track.pt(), sigmaDca3D(track) * 1e+4); // convert cm to um @@ -629,11 +625,11 @@ struct SingleTrackQCMC { fRegistry.fill(HIST("Track/PID/positive/hITSNsigmaPr"), track.p(), track.itsNSigmaPr()); } } else { - fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hs"), track.pt(), track.eta(), track.phi(), dca, -mctrack.pdgCode() / pdg_lepton, weight); + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hs"), track.pt(), track.eta(), track.phi(), dca3D, dcaXY, dcaZ, -mctrack.pdgCode() / pdg_lepton, weight); if (cfgFillQA) { fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hQoverPt"), track.sign() / track.pt()); fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hDCAxyz"), track.dcaXY(), track.dcaZ()); - fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hDCAxyzSigma"), track.dcaXY() / std::sqrt(track.cYY()), track.dcaZ() / std::sqrt(track.cZZ())); + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hDCAxyzSigma"), dcaXY, dcaZ); fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hDCAxyRes_Pt"), track.pt(), std::sqrt(track.cYY()) * 1e+4); // convert cm to um fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hDCAzRes_Pt"), track.pt(), std::sqrt(track.cZZ()) * 1e+4); // convert cm to um fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hDCA3dRes_Pt"), track.pt(), sigmaDca3D(track) * 1e+4); // convert cm to um From f1eef1b5da886f14d935a56aed136374c36ea5e8 Mon Sep 17 00:00:00 2001 From: Daiki Sekihata Date: Wed, 18 Jun 2025 10:33:15 +0200 Subject: [PATCH 125/871] [PWGEM/Dilepton] fix for dimuon again (#11663) --- PWGEM/Dilepton/Tasks/matchingMFT.cxx | 63 ++++++++++++++-------------- 1 file changed, 32 insertions(+), 31 deletions(-) diff --git a/PWGEM/Dilepton/Tasks/matchingMFT.cxx b/PWGEM/Dilepton/Tasks/matchingMFT.cxx index 2275956d3dd..428dcd2aaf6 100644 --- a/PWGEM/Dilepton/Tasks/matchingMFT.cxx +++ b/PWGEM/Dilepton/Tasks/matchingMFT.cxx @@ -13,32 +13,33 @@ /// \brief a task to study matching MFT-[MCH-MID] in MC /// \author daiki.sekihata@cern.ch -#include -#include -#include -#include - -#include "Framework/DataTypes.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" #include "TableHelper.h" + +#include "Common/CCDB/RCTSelectionFlags.h" +#include "Common/Core/fwdtrackUtilities.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/CollisionAssociationTables.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Multiplicity.h" + #include "CCDB/BasicCCDBManager.h" #include "DataFormatsParameters/GRPMagField.h" -#include "TGeoGlobalMagField.h" -#include "Field/MagneticField.h" - #include "DetectorsBase/Propagator.h" +#include "Field/MagneticField.h" +#include "Framework/AnalysisTask.h" +#include "Framework/DataTypes.h" +#include "Framework/runDataProcessing.h" #include "GlobalTracking/MatchGlobalFwd.h" #include "MCHTracking/TrackExtrap.h" #include "MCHTracking/TrackParam.h" #include "ReconstructionDataFormats/TrackFwd.h" -#include "Common/DataModel/CollisionAssociationTables.h" -#include "Common/Core/fwdtrackUtilities.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/Centrality.h" -#include "Common/CCDB/RCTSelectionFlags.h" +#include "TGeoGlobalMagField.h" + +#include +#include +#include +#include using namespace o2; using namespace o2::soa; @@ -172,10 +173,10 @@ struct matchingMFT { fRegistry.add("MFTMCHMID/primary/correct/hMFTClusterMap", "MFT cluster map", kTH1F, {{1024, -0.5, 1023.5}}, false); fRegistry.add("MFTMCHMID/primary/correct/hRatAbsorberEnd", "R at absorber end;R at absorber end (cm)", kTH1F, {{100, 0.0f, 100}}, false); fRegistry.add("MFTMCHMID/primary/correct/hPDCA_Rabs", "pDCA vs. Rabs;R at absorber end (cm);p #times DCA (GeV/c #upoint cm)", kTH2F, {{100, 0, 100}, {100, 0.0f, 1000}}, false); - fRegistry.add("MFTMCHMID/primary/correct/hChi2", "chi2;chi2", kTH1F, {{100, 0.0f, 100}}, false); + fRegistry.add("MFTMCHMID/primary/correct/hChi2", "chi2;chi2/ndf", kTH1F, {{100, 0.0f, 10}}, false); fRegistry.add("MFTMCHMID/primary/correct/hChi2MFT", "chi2 MFT/ndf;chi2 MFT/ndf", kTH1F, {{100, 0.0f, 10}}, false); - fRegistry.add("MFTMCHMID/primary/correct/hChi2MatchMCHMID", "chi2 match MCH-MID;chi2", kTH1F, {{100, 0.0f, 10}}, false); - fRegistry.add("MFTMCHMID/primary/correct/hChi2MatchMCHMFT", "chi2 match MCH-MFT;chi2/ndf", kTH1F, {{100, 0.0f, 10}}, false); + fRegistry.add("MFTMCHMID/primary/correct/hChi2MatchMCHMID", "chi2 match MCH-MID;chi2", kTH1F, {{100, 0.0f, 100}}, false); + fRegistry.add("MFTMCHMID/primary/correct/hChi2MatchMCHMFT", "chi2 match MCH-MFT;chi2", kTH1F, {{100, 0.0f, 100}}, false); fRegistry.add("MFTMCHMID/primary/correct/hDCAxy2D", "DCA x vs. y;DCA_{x} (cm);DCA_{y} (cm)", kTH2F, {{200, -0.5, 0.5}, {200, -0.5, +0.5}}, false); fRegistry.add("MFTMCHMID/primary/correct/hDCAz", "DCA z;DCA_{z} (cm);", kTH1F, {{1000, 0, 10}}, false); fRegistry.add("MFTMCHMID/primary/correct/hDCAxy2DinSigma", "DCA x vs. y in sigma;DCA_{x} (#sigma);DCA_{y} (#sigma)", kTH2F, {{200, -10, 10}, {200, -10, +10}}, false); @@ -198,7 +199,7 @@ struct matchingMFT { fRegistry.addClone("MFTMCHMID/primary/", "MFTMCHMID/secondary/"); } - bool isSelected(const float pt, const float eta, const float rAtAbsorberEnd, const float pDCA, const float chi2, const uint8_t trackType, const float dcaXY) + bool isSelected(const float pt, const float eta, const float rAtAbsorberEnd, const float pDCA, const float chi2_per_ndf, const uint8_t trackType, const float dcaXY) { if (pt < minPt || maxPt < pt) { return false; @@ -217,14 +218,14 @@ struct matchingMFT { if (maxDCAxy < dcaXY) { return false; } - if (chi2 < 0.f || maxChi2GL < chi2) { + if (chi2_per_ndf < 0.f || maxChi2GL < chi2_per_ndf) { return false; } } else if (trackType == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack)) { if (eta < minEtaSA || maxEtaSA < eta) { return false; } - if (chi2 < 0.f || maxChi2SA < chi2) { + if (chi2_per_ndf < 0.f || maxChi2SA < chi2_per_ndf) { return false; } } else { @@ -305,11 +306,11 @@ struct matchingMFT { return; } - if (fwdtrack.chi2MatchMCHMFT() > maxMatchingChi2MCHMFT / (2.f * (mchtrack.nClusters() + nClustersMFT) - 5.f)) { + if (fwdtrack.chi2MatchMCHMFT() > maxMatchingChi2MCHMFT) { return; } - if (fwdtrack.chi2() < 0.f || maxChi2GL < fwdtrack.chi2()) { + if (fwdtrack.chi2() < 0.f || maxChi2GL < fwdtrack.chi2() / (2.f * (mchtrack.nClusters() + nClustersMFT) - 5.f)) { return; } @@ -387,7 +388,7 @@ struct matchingMFT { return; } - if (!isSelected(pt, eta, rAtAbsorberEnd, pDCA, fwdtrack.chi2(), fwdtrack.trackType(), dcaXY)) { + if (!isSelected(pt, eta, rAtAbsorberEnd, pDCA, fwdtrack.chi2() / (2.f * (mchtrack.nClusters() + nClustersMFT) - 5.f), fwdtrack.trackType(), dcaXY)) { return; } @@ -414,10 +415,10 @@ struct matchingMFT { fRegistry.fill(HIST("MFTMCHMID/primary/correct/hMFTClusterMap"), mftClusterMap(mfttrack)); fRegistry.fill(HIST("MFTMCHMID/primary/correct/hPDCA_Rabs"), rAtAbsorberEnd, pDCA); fRegistry.fill(HIST("MFTMCHMID/primary/correct/hRatAbsorberEnd"), rAtAbsorberEnd); - fRegistry.fill(HIST("MFTMCHMID/primary/correct/hChi2"), fwdtrack.chi2()); + fRegistry.fill(HIST("MFTMCHMID/primary/correct/hChi2"), fwdtrack.chi2() / (2.f * (fwdtrack.nClusters() + nClustersMFT) - 5.f)); fRegistry.fill(HIST("MFTMCHMID/primary/correct/hChi2MFT"), chi2mft); fRegistry.fill(HIST("MFTMCHMID/primary/correct/hChi2MatchMCHMID"), fwdtrack.chi2MatchMCHMID()); - fRegistry.fill(HIST("MFTMCHMID/primary/correct/hChi2MatchMCHMFT"), fwdtrack.chi2MatchMCHMFT() / (2 * (fwdtrack.nClusters() + nClustersMFT) - 5)); + fRegistry.fill(HIST("MFTMCHMID/primary/correct/hChi2MatchMCHMFT"), fwdtrack.chi2MatchMCHMFT()); fRegistry.fill(HIST("MFTMCHMID/primary/correct/hDCAxy2D"), dcaX, dcaY); fRegistry.fill(HIST("MFTMCHMID/primary/correct/hDCAz"), dcaZ); fRegistry.fill(HIST("MFTMCHMID/primary/correct/hDCAxy2DinSigma"), dcaX / std::sqrt(cXXatDCA), dcaY / std::sqrt(cYYatDCA)); @@ -451,7 +452,7 @@ struct matchingMFT { fRegistry.fill(HIST("MFTMCHMID/primary/wrong/hMFTClusterMap"), mftClusterMap(mfttrack)); fRegistry.fill(HIST("MFTMCHMID/primary/wrong/hPDCA_Rabs"), rAtAbsorberEnd, pDCA); fRegistry.fill(HIST("MFTMCHMID/primary/wrong/hRatAbsorberEnd"), rAtAbsorberEnd); - fRegistry.fill(HIST("MFTMCHMID/primary/wrong/hChi2"), fwdtrack.chi2()); + fRegistry.fill(HIST("MFTMCHMID/primary/wrong/hChi2"), fwdtrack.chi2() / (2.f * (fwdtrack.nClusters() + nClustersMFT) - 5.f)); fRegistry.fill(HIST("MFTMCHMID/primary/wrong/hChi2MFT"), chi2mft); fRegistry.fill(HIST("MFTMCHMID/primary/wrong/hChi2MatchMCHMID"), fwdtrack.chi2MatchMCHMID()); fRegistry.fill(HIST("MFTMCHMID/primary/wrong/hChi2MatchMCHMFT"), fwdtrack.chi2MatchMCHMFT()); @@ -489,7 +490,7 @@ struct matchingMFT { fRegistry.fill(HIST("MFTMCHMID/secondary/correct/hMFTClusterMap"), mftClusterMap(mfttrack)); fRegistry.fill(HIST("MFTMCHMID/secondary/correct/hPDCA_Rabs"), rAtAbsorberEnd, pDCA); fRegistry.fill(HIST("MFTMCHMID/secondary/correct/hRatAbsorberEnd"), rAtAbsorberEnd); - fRegistry.fill(HIST("MFTMCHMID/secondary/correct/hChi2"), fwdtrack.chi2()); + fRegistry.fill(HIST("MFTMCHMID/secondary/correct/hChi2"), fwdtrack.chi2() / (2.f * (fwdtrack.nClusters() + nClustersMFT) - 5.f)); fRegistry.fill(HIST("MFTMCHMID/secondary/correct/hChi2MFT"), chi2mft); fRegistry.fill(HIST("MFTMCHMID/secondary/correct/hChi2MatchMCHMID"), fwdtrack.chi2MatchMCHMID()); fRegistry.fill(HIST("MFTMCHMID/secondary/correct/hChi2MatchMCHMFT"), fwdtrack.chi2MatchMCHMFT()); @@ -525,7 +526,7 @@ struct matchingMFT { fRegistry.fill(HIST("MFTMCHMID/secondary/wrong/hMFTClusterMap"), mftClusterMap(mfttrack)); fRegistry.fill(HIST("MFTMCHMID/secondary/wrong/hPDCA_Rabs"), rAtAbsorberEnd, pDCA); fRegistry.fill(HIST("MFTMCHMID/secondary/wrong/hRatAbsorberEnd"), rAtAbsorberEnd); - fRegistry.fill(HIST("MFTMCHMID/secondary/wrong/hChi2"), fwdtrack.chi2()); + fRegistry.fill(HIST("MFTMCHMID/secondary/wrong/hChi2"), fwdtrack.chi2() / (2.f * (fwdtrack.nClusters() + nClustersMFT) - 5.f)); fRegistry.fill(HIST("MFTMCHMID/secondary/wrong/hChi2MFT"), chi2mft); fRegistry.fill(HIST("MFTMCHMID/secondary/wrong/hChi2MatchMCHMID"), fwdtrack.chi2MatchMCHMID()); fRegistry.fill(HIST("MFTMCHMID/secondary/wrong/hChi2MatchMCHMFT"), fwdtrack.chi2MatchMCHMFT()); From ae014d3120ebd7d4ba6e7e2f619e54e6fbdcaeac Mon Sep 17 00:00:00 2001 From: prottayCMT <61418725+prottayCMT@users.noreply.github.com> Date: Wed, 18 Jun 2025 10:51:31 +0200 Subject: [PATCH 126/871] [PWGLF] added phi v1 and costhetastar for SA (#11592) Co-authored-by: Prottay Das --- PWGLF/Tasks/Resonances/kstarpbpb.cxx | 115 ++-- PWGLF/Tasks/Resonances/phipbpb.cxx | 816 +++++++++++++++++++++------ 2 files changed, 707 insertions(+), 224 deletions(-) diff --git a/PWGLF/Tasks/Resonances/kstarpbpb.cxx b/PWGLF/Tasks/Resonances/kstarpbpb.cxx index a8ad0497647..e650e1f8d91 100644 --- a/PWGLF/Tasks/Resonances/kstarpbpb.cxx +++ b/PWGLF/Tasks/Resonances/kstarpbpb.cxx @@ -10,50 +10,51 @@ // or submit itself to any jurisdiction. // sourav.kundu@cern.ch , sarjeeta.gami@cern.ch -#include +#include "PWGLF/DataModel/EPCalibrationTables.h" +#include "PWGMM/Mult/DataModel/Index.h" // for Particles2Tracks table + +#include "Common/Core/TrackSelection.h" +#include "Common/Core/trackUtilities.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/PIDResponseITS.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include "CCDB/BasicCCDBManager.h" +#include "CCDB/CcdbApi.h" +#include "CommonConstants/PhysicsConstants.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "DataFormatsParameters/GRPObject.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/StepTHn.h" +#include "Framework/runDataProcessing.h" +#include "ReconstructionDataFormats/Track.h" + +#include "Math/GenVector/Boost.h" +#include "Math/Vector3D.h" +#include "Math/Vector4D.h" +#include "TF1.h" +#include "TRandom3.h" #include +#include +#include +#include #include #include #include #include -#include -#include -#include #include -#include + #include +#include #include -#include #include - -#include "TRandom3.h" -#include "Math/Vector3D.h" -#include "Math/Vector4D.h" -#include "Math/GenVector/Boost.h" -#include "TF1.h" - -#include "PWGLF/DataModel/EPCalibrationTables.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/StepTHn.h" -#include "Common/DataModel/PIDResponse.h" -#include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/Centrality.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/Core/trackUtilities.h" -#include "CommonConstants/PhysicsConstants.h" -#include "Common/Core/TrackSelection.h" -#include "Framework/ASoAHelpers.h" -#include "ReconstructionDataFormats/Track.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "CCDB/BasicCCDBManager.h" -#include "CCDB/CcdbApi.h" -#include "Common/DataModel/PIDResponseITS.h" -#include "PWGMM/Mult/DataModel/Index.h" // for Particles2Tracks table +#include using namespace o2; using namespace o2::framework; @@ -101,6 +102,7 @@ struct kstarpbpb { Configurable cfgCutDCAxy{"cfgCutDCAxy", 2.0f, "DCAxy range for tracks"}; Configurable cfgCutDCAz{"cfgCutDCAz", 2.0f, "DCAz range for tracks"}; Configurable useGlobalTrack{"useGlobalTrack", true, "use Global track"}; + Configurable usepolar{"usepolar", true, "flag to fill type of SA"}; Configurable nsigmaCutTOF{"nsigmacutTOF", 3.0, "Value of the TOF Nsigma cut"}; Configurable nsigmaCutTPC{"nsigmacutTPC", 3.0, "Value of the TPC Nsigma cut"}; Configurable isTOFOnly{"isTOFOnly", false, "use TOF only PID"}; @@ -159,8 +161,8 @@ struct kstarpbpb { Preslice perCollision = aod::track::collisionId; SliceCache cache; - Partition posTracks = aod::track::signed1Pt > cfgCutCharge; - Partition negTracks = aod::track::signed1Pt < cfgCutCharge; + // Partition posTracks = aod::track::signed1Pt > cfgCutCharge; + // Partition negTracks = aod::track::signed1Pt < cfgCutCharge; HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; @@ -183,8 +185,8 @@ struct kstarpbpb { AxisSpec resAxis = {6000, -30, 30, "Res"}; AxisSpec centAxis = {8, 0, 80, "V0M (%)"}; AxisSpec occupancyAxis = {occupancyBinning, "Occupancy"}; + histos.add("hEvtSelInfo", "hEvtSelInfo", kTH1F, {{10, 0, 10.0}}); if (!fillSA) { - histos.add("hEvtSelInfo", "hEvtSelInfo", kTH1F, {{10, 0, 10.0}}); if (same) { histos.add("hSparseV2SASameEvent_V2", "hSparseV2SASameEvent_V2", HistType::kTHnSparseF, {configThnAxisInvMass, configThnAxisPt, configThnAxisV2, configThnAxisCentrality}); } @@ -663,15 +665,25 @@ struct kstarpbpb { threeVecDauCM = fourVecDauCM.Vect(); threeVecDauCMXY = ROOT::Math::XYZVector(threeVecDauCM.X(), threeVecDauCM.Y(), 0.); eventplaneVec = ROOT::Math::XYZVector(std::cos(2.0 * psiFT0C), std::sin(2.0 * psiFT0C), 0); + eventplaneVecNorm = ROOT::Math::XYZVector(std::sin(2.0 * psiFT0C), -std::cos(2.0 * psiFT0C), 0); auto cosPhistarminuspsi = GetPhiInRange(fourVecDauCM.Phi() - psiFT0C); auto SA = TMath::Cos(2.0 * cosPhistarminuspsi); + auto cosThetaStar = eventplaneVecNorm.Dot(threeVecDauCM) / std::sqrt(threeVecDauCM.Mag2()) / std::sqrt(eventplaneVecNorm.Mag2()); - if (track1Sign * track2Sign < 0) - histos.fill(HIST("hSparseSAvsrapsameunlike"), KstarMother.M(), KstarMother.Pt(), SA, KstarMother.Rapidity(), centrality); - else if (track1Sign * track2Sign > 0) - histos.fill(HIST("hSparseSAvsrapsamelike"), KstarMother.M(), KstarMother.Pt(), SA, KstarMother.Rapidity(), centrality); + if (track1Sign * track2Sign < 0) { + if (usepolar) { + histos.fill(HIST("hSparseSAvsrapsameunlike"), KstarMother.M(), KstarMother.Pt(), cosThetaStar, KstarMother.Rapidity(), centrality); + } else { + histos.fill(HIST("hSparseSAvsrapsameunlike"), KstarMother.M(), KstarMother.Pt(), SA, KstarMother.Rapidity(), centrality); + } + } else if (track1Sign * track2Sign > 0) { + if (usepolar) { + histos.fill(HIST("hSparseSAvsrapsamelike"), KstarMother.M(), KstarMother.Pt(), cosThetaStar, KstarMother.Rapidity(), centrality); + } else { + histos.fill(HIST("hSparseSAvsrapsamelike"), KstarMother.M(), KstarMother.Pt(), SA, KstarMother.Rapidity(), centrality); + } + } } - if (fillRotation) { for (int nrotbkg = 0; nrotbkg < nBkgRotations; nrotbkg++) { auto anglestart = confMinRot; @@ -707,8 +719,12 @@ struct kstarpbpb { threeVecDauCMXYrot = ROOT::Math::XYZVector(threeVecDauCMrot.X(), threeVecDauCMrot.Y(), 0.); auto cosPhistarminuspsirot = GetPhiInRange(fourVecDauCMrot.Phi() - psiFT0C); auto SArot = TMath::Cos(2.0 * cosPhistarminuspsirot); - - histos.fill(HIST("hSparseSAvsraprot"), kstarrot.M(), kstarrot.Pt(), SArot, kstarrot.Rapidity(), centrality); + auto cosThetaStarrot = eventplaneVecNorm.Dot(threeVecDauCMrot) / std::sqrt(threeVecDauCMrot.Mag2()) / std::sqrt(eventplaneVecNorm.Mag2()); + if (usepolar) { + histos.fill(HIST("hSparseSAvsraprot"), kstarrot.M(), kstarrot.Pt(), cosThetaStarrot, kstarrot.Rapidity(), centrality); + } else { + histos.fill(HIST("hSparseSAvsraprot"), kstarrot.M(), kstarrot.Pt(), SArot, kstarrot.Rapidity(), centrality); + } } } } @@ -1203,10 +1219,15 @@ struct kstarpbpb { threeVecDauCM = fourVecDauCM.Vect(); threeVecDauCMXY = ROOT::Math::XYZVector(threeVecDauCM.X(), threeVecDauCM.Y(), 0.); eventplaneVec = ROOT::Math::XYZVector(std::cos(2.0 * psiFT0C), std::sin(2.0 * psiFT0C), 0); + eventplaneVecNorm = ROOT::Math::XYZVector(std::sin(2.0 * psiFT0C), -std::cos(2.0 * psiFT0C), 0); auto cosPhistarminuspsi = GetPhiInRange(fourVecDauCM.Phi() - psiFT0C); auto SA = TMath::Cos(2.0 * cosPhistarminuspsi); - - histos.fill(HIST("hSparseSAvsrapmix"), KstarMother.M(), KstarMother.Pt(), SA, KstarMother.Rapidity(), centrality); + auto cosThetaStar = eventplaneVecNorm.Dot(threeVecDauCM) / std::sqrt(threeVecDauCM.Mag2()) / std::sqrt(eventplaneVecNorm.Mag2()); + if (usepolar) { + histos.fill(HIST("hSparseSAvsrapmix"), KstarMother.M(), KstarMother.Pt(), cosThetaStar, KstarMother.Rapidity(), centrality); + } else { + histos.fill(HIST("hSparseSAvsrapmix"), KstarMother.M(), KstarMother.Pt(), SA, KstarMother.Rapidity(), centrality); + } } } } diff --git a/PWGLF/Tasks/Resonances/phipbpb.cxx b/PWGLF/Tasks/Resonances/phipbpb.cxx index 7ab2dd9aa39..521e505ebd2 100644 --- a/PWGLF/Tasks/Resonances/phipbpb.cxx +++ b/PWGLF/Tasks/Resonances/phipbpb.cxx @@ -11,52 +11,54 @@ // Phi meson spin alignment task // sourav.kundu@cern.ch -#include +#include "PWGLF/DataModel/EPCalibrationTables.h" +#include "PWGLF/DataModel/SPCalibrationTables.h" +#include "PWGMM/Mult/DataModel/Index.h" // for Particles2Tracks table + +#include "Common/Core/TrackSelection.h" +#include "Common/Core/trackUtilities.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/PIDResponseITS.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include "CCDB/BasicCCDBManager.h" +#include "CCDB/CcdbApi.h" +#include "CommonConstants/PhysicsConstants.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "DataFormatsParameters/GRPObject.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/O2DatabasePDGPlugin.h" +#include "Framework/StepTHn.h" +#include "Framework/runDataProcessing.h" +#include "ReconstructionDataFormats/Track.h" + +#include "Math/GenVector/Boost.h" +#include "Math/Vector3D.h" +#include "Math/Vector4D.h" +#include "TF1.h" +#include "TRandom3.h" +#include #include +#include +#include +#include #include #include #include #include -#include -#include -#include #include -#include -#include + #include +#include #include -#include #include - -#include "TRandom3.h" -#include "Math/Vector3D.h" -#include "Math/Vector4D.h" -#include "Math/GenVector/Boost.h" -#include "TF1.h" - -#include "PWGLF/DataModel/EPCalibrationTables.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/StepTHn.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "Common/DataModel/PIDResponse.h" -#include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/Centrality.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/Core/trackUtilities.h" -#include "CommonConstants/PhysicsConstants.h" -#include "Common/Core/TrackSelection.h" -#include "Framework/ASoAHelpers.h" -#include "ReconstructionDataFormats/Track.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "CCDB/BasicCCDBManager.h" -#include "CCDB/CcdbApi.h" -#include "Common/DataModel/PIDResponseITS.h" -#include "PWGMM/Mult/DataModel/Index.h" // for Particles2Tracks table +#include using namespace o2; using namespace o2::framework; @@ -92,6 +94,9 @@ struct phipbpb { Configurable cfgCutCentrality{"cfgCutCentrality", 80.0f, "Accepted maximum Centrality"}; Configurable cfgCutOccupancy{"cfgCutOccupancy", 3000, "Occupancy cut"}; // track + Configurable cqvas{"cqvas", false, "change q vectors after shift correction"}; + Configurable fillv1{"fillv1", false, "flag to fill v1 histograms"}; + Configurable fillLOCC{"fillLOCC", false, "flag to fill LOCC histograms"}; Configurable useSP{"useSP", false, "use SP"}; Configurable useDcaSyst{"useDcaSyst", false, "useDcaSyst"}; Configurable additionalEvsel{"additionalEvsel", false, "Additional event selcection"}; @@ -117,15 +122,17 @@ struct phipbpb { Configurable checkAllCharge{"checkAllCharge", true, "check all charge for MC weight"}; Configurable cfgDeepAngle{"cfgDeepAngle", 0.04, "Deep Angle cut value"}; Configurable confRapidity{"confRapidity", 0.5, "Rapidity cut"}; - ConfigurableAxis configThnAxisInvMass{"configThnAxisInvMass", {120, 0.98, 1.1}, "#it{M} (GeV/#it{c}^{2})"}; - ConfigurableAxis configThnAxisPt{"configThnAxisPt", {100, 0.0, 10.}, "#it{p}_{T} (GeV/#it{c})"}; - ConfigurableAxis configThnAxisCosThetaStar{"configThnAxisCosThetaStar", {10, -1.0, 1.}, "cos(#vartheta)"}; - ConfigurableAxis configThnAxisCentrality{"configThnAxisCentrality", {8, 0., 80}, "Centrality"}; - ConfigurableAxis configThnAxisPhiminusPsi{"configThnAxisPhiminusPsi", {6, 0.0, TMath::Pi()}, "#phi - #psi"}; - ConfigurableAxis configThnAxisV2{"configThnAxisV2", {200, -6, 6}, "V2"}; - ConfigurableAxis configThnAxisRapidity{"configThnAxisRapidity", {8, 0, 0.8}, "Rapidity"}; - ConfigurableAxis configThnAxisSA{"configThnAxisSA", {200, -1, 1}, "SA"}; - ConfigurableAxis configThnAxiscosthetaSA{"configThnAxiscosthetaSA", {200, 0, 1}, "costhetaSA"}; + struct : ConfigurableGroup { + ConfigurableAxis configThnAxisInvMass{"configThnAxisInvMass", {120, 0.98, 1.1}, "#it{M} (GeV/#it{c}^{2})"}; + ConfigurableAxis configThnAxisPt{"configThnAxisPt", {100, 0.0, 10.}, "#it{p}_{T} (GeV/#it{c})"}; + ConfigurableAxis configThnAxisCosThetaStar{"configThnAxisCosThetaStar", {10, -1.0, 1.}, "cos(#vartheta)"}; + ConfigurableAxis configThnAxisCentrality{"configThnAxisCentrality", {8, 0., 80}, "Centrality"}; + ConfigurableAxis configThnAxisPhiminusPsi{"configThnAxisPhiminusPsi", {6, 0.0, TMath::Pi()}, "#phi - #psi"}; + ConfigurableAxis configThnAxisV2{"configThnAxisV2", {200, -6, 6}, "V2"}; + ConfigurableAxis configThnAxisRapidity{"configThnAxisRapidity", {8, 0, 0.8}, "Rapidity"}; + ConfigurableAxis configThnAxisSA{"configThnAxisSA", {200, -1, 1}, "SA"}; + ConfigurableAxis configThnAxiscosthetaSA{"configThnAxiscosthetaSA", {200, 0, 1}, "costhetaSA"}; + } cnfgaxis; ConfigurableAxis axisPtKaonWeight{"axisPtKaonWeight", {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}, "pt axis"}; Configurable isMC{"isMC", false, "use MC"}; Configurable genacceptancecut{"genacceptancecut", true, "use acceptance cut for generated"}; @@ -133,6 +140,9 @@ struct phipbpb { Configurable islike{"islike", false, "use like"}; Configurable useWeight{"useWeight", true, "use EP dep effi weight"}; Configurable ConfWeightPath{"ConfWeightPath", "Users/s/skundu/My/Object/mcweight", "Path to gain calibration"}; + Configurable spNbins{"spNbins", 2000, "Number of bins in sp"}; + Configurable lbinsp{"lbinsp", -1.0, "lower bin value in sp histograms"}; + Configurable hbinsp{"hbinsp", 1.0, "higher bin value in sp histograms"}; Filter collisionFilter = nabs(aod::collision::posZ) < cfgCutVertex; Filter centralityFilter = nabs(aod::cent::centFT0C) < cfgCutCentrality; @@ -141,6 +151,7 @@ struct phipbpb { Filter PIDcutFilter = nabs(aod::pidtpc::tpcNSigmaKa) < nsigmaCutTPC; using EventCandidates = soa::Filtered>; + using EventCandidatesv1 = soa::Filtered>; using TrackCandidates = soa::Filtered>; using CollisionMCTrueTable = aod::McCollisions; @@ -168,13 +179,13 @@ struct phipbpb { { // std::vector occupancyBinning = {0.0, 500.0, 1000.0, 3000.0, 6000.0, 50000.0}; std::vector occupancyBinning = {-0.5, 500.0, 1000.0, 1500.0, 2000.0, 3000.0, 4000.0, 5000.0, 50000.0}; - const AxisSpec thnAxisInvMass{configThnAxisInvMass, "#it{M} (GeV/#it{c}^{2})"}; - const AxisSpec thnAxisPt{configThnAxisPt, "#it{p}_{T} (GeV/#it{c})"}; - const AxisSpec thnAxisCosThetaStar{configThnAxisCosThetaStar, "cos(#vartheta_{OP})"}; - const AxisSpec thnAxisCentrality{configThnAxisCentrality, "Centrality (%)"}; - const AxisSpec thnAxisV2{configThnAxisV2, "V2"}; - const AxisSpec thnAxisRapidity{configThnAxisRapidity, "Rapidity"}; - const AxisSpec thnAxisSA{configThnAxisSA, "SA"}; + const AxisSpec thnAxisInvMass{cnfgaxis.configThnAxisInvMass, "#it{M} (GeV/#it{c}^{2})"}; + const AxisSpec thnAxisPt{cnfgaxis.configThnAxisPt, "#it{p}_{T} (GeV/#it{c})"}; + const AxisSpec thnAxisCosThetaStar{cnfgaxis.configThnAxisCosThetaStar, "cos(#vartheta_{OP})"}; + const AxisSpec thnAxisCentrality{cnfgaxis.configThnAxisCentrality, "Centrality (%)"}; + const AxisSpec thnAxisV2{cnfgaxis.configThnAxisV2, "V2"}; + const AxisSpec thnAxisRapidity{cnfgaxis.configThnAxisRapidity, "Rapidity"}; + const AxisSpec thnAxisSA{cnfgaxis.configThnAxisSA, "SA"}; AxisSpec cumulantAxis = {200, -1, 1, "phi"}; AxisSpec itsAxis = {8, -0.5, 7.5, "its"}; AxisSpec tpcAxis = {130, 69.5, 199.5, "its"}; @@ -184,133 +195,166 @@ struct phipbpb { AxisSpec resAxisSquare = {800, -1, 1, "Res"}; AxisSpec centAxis = {8, 0, 80, "V0M (%)"}; AxisSpec occupancyAxis = {occupancyBinning, "Occupancy"}; + AxisSpec spAxis = {spNbins, lbinsp, hbinsp, "Sp"}; + + if (fillv1) { + histos.add("hpQxtQxpvscent", "hpQxtQxpvscent", HistType::kTHnSparseF, {cnfgaxis.configThnAxisCentrality, spAxis}, true); + histos.add("hpQytQypvscent", "hpQytQypvscent", HistType::kTHnSparseF, {cnfgaxis.configThnAxisCentrality, spAxis}, true); + histos.add("hpQxytpvscent", "hpQxytpvscent", HistType::kTHnSparseF, {cnfgaxis.configThnAxisCentrality, spAxis}, true); + histos.add("hpQxtQypvscent", "hpQxtQypvscent", HistType::kTHnSparseF, {cnfgaxis.configThnAxisCentrality, spAxis}, true); + histos.add("hpQxpQytvscent", "hpQxpQytvscent", HistType::kTHnSparseF, {cnfgaxis.configThnAxisCentrality, spAxis}, true); + + histos.add("hpQxpvscent", "hpQxpvscent", HistType::kTHnSparseF, {cnfgaxis.configThnAxisCentrality, spAxis}, true); + histos.add("hpQxtvscent", "hpQxtvscent", HistType::kTHnSparseF, {cnfgaxis.configThnAxisCentrality, spAxis}, true); + histos.add("hpQypvscent", "hpQypvscent", HistType::kTHnSparseF, {cnfgaxis.configThnAxisCentrality, spAxis}, true); + histos.add("hpQytvscent", "hpQytvscent", HistType::kTHnSparseF, {cnfgaxis.configThnAxisCentrality, spAxis}, true); + + histos.add("hpoddvscentpteta", "hpoddvscentpteta", HistType::kTHnSparseF, {cnfgaxis.configThnAxisInvMass, cnfgaxis.configThnAxisCentrality, cnfgaxis.configThnAxisPt, cnfgaxis.configThnAxisRapidity, spAxis}, true); + histos.add("hpuxyQxypvscentpteta", "hpuxyQxypvscentpteta", HistType::kTHnSparseF, {cnfgaxis.configThnAxisInvMass, cnfgaxis.configThnAxisCentrality, cnfgaxis.configThnAxisPt, cnfgaxis.configThnAxisRapidity, spAxis}, true); + histos.add("hpuxyQxytvscentpteta", "hpuxyQxytvscentpteta", HistType::kTHnSparseF, {cnfgaxis.configThnAxisInvMass, cnfgaxis.configThnAxisCentrality, cnfgaxis.configThnAxisPt, cnfgaxis.configThnAxisRapidity, spAxis}, true); + histos.add("hpuxvscentpteta", "hpuxvscentpteta", HistType::kTHnSparseF, {cnfgaxis.configThnAxisInvMass, cnfgaxis.configThnAxisCentrality, cnfgaxis.configThnAxisPt, cnfgaxis.configThnAxisRapidity, spAxis}, true); + histos.add("hpuyvscentpteta", "hpuyvscentpteta", HistType::kTHnSparseF, {cnfgaxis.configThnAxisInvMass, cnfgaxis.configThnAxisCentrality, cnfgaxis.configThnAxisPt, cnfgaxis.configThnAxisRapidity, spAxis}, true); + histos.add("hpoddvscentptetamixacc", "hpoddvscentptetamixacc", HistType::kTHnSparseF, {cnfgaxis.configThnAxisInvMass, cnfgaxis.configThnAxisCentrality, cnfgaxis.configThnAxisPt, cnfgaxis.configThnAxisRapidity, spAxis}, true); + histos.add("hpuxyQxypvscentptetamixacc", "hpuxyQxypvscentptetamixacc", HistType::kTHnSparseF, {cnfgaxis.configThnAxisInvMass, cnfgaxis.configThnAxisCentrality, cnfgaxis.configThnAxisPt, cnfgaxis.configThnAxisRapidity, spAxis}, true); + histos.add("hpuxyQxytvscentptetamixacc", "hpuxyQxytvscentptetamixacc", HistType::kTHnSparseF, {cnfgaxis.configThnAxisInvMass, cnfgaxis.configThnAxisCentrality, cnfgaxis.configThnAxisPt, cnfgaxis.configThnAxisRapidity, spAxis}, true); + histos.add("hpuxvscentptetamixacc", "hpuxvscentptetamixacc", HistType::kTHnSparseF, {cnfgaxis.configThnAxisInvMass, cnfgaxis.configThnAxisCentrality, cnfgaxis.configThnAxisPt, cnfgaxis.configThnAxisRapidity, spAxis}, true); + histos.add("hpuyvscentptetamixacc", "hpuyvscentptetamixacc", HistType::kTHnSparseF, {cnfgaxis.configThnAxisInvMass, cnfgaxis.configThnAxisCentrality, cnfgaxis.configThnAxisPt, cnfgaxis.configThnAxisRapidity, spAxis}, true); + histos.add("hpoddvscentptetamixopti", "hpoddvscentptetamixopti", HistType::kTHnSparseF, {cnfgaxis.configThnAxisInvMass, cnfgaxis.configThnAxisCentrality, cnfgaxis.configThnAxisPt, cnfgaxis.configThnAxisRapidity, spAxis}, true); + histos.add("hpuxyQxypvscentptetamixopti", "hpuxyQxypvscentptetamixopti", HistType::kTHnSparseF, {cnfgaxis.configThnAxisInvMass, cnfgaxis.configThnAxisCentrality, cnfgaxis.configThnAxisPt, cnfgaxis.configThnAxisRapidity, spAxis}, true); + histos.add("hpuxyQxytvscentptetamixopti", "hpuxyQxytvscentptetamixopti", HistType::kTHnSparseF, {cnfgaxis.configThnAxisInvMass, cnfgaxis.configThnAxisCentrality, cnfgaxis.configThnAxisPt, cnfgaxis.configThnAxisRapidity, spAxis}, true); + histos.add("hpuxvscentptetamixopti", "hpuxvscentptetamixopti", HistType::kTHnSparseF, {cnfgaxis.configThnAxisInvMass, cnfgaxis.configThnAxisCentrality, cnfgaxis.configThnAxisPt, cnfgaxis.configThnAxisRapidity, spAxis}, true); + histos.add("hpuyvscentptetamixopti", "hpuyvscentptetamixopti", HistType::kTHnSparseF, {cnfgaxis.configThnAxisInvMass, cnfgaxis.configThnAxisCentrality, cnfgaxis.configThnAxisPt, cnfgaxis.configThnAxisRapidity, spAxis}, true); + } - histos.add("hTPCglobalmomcorr", "Momentum correlation", kTH3F, {{200, -10.0f, 10.0f}, {200, -10.0f, 10.0f}, {8, 0.0f, 80.0f}}); - histos.add("hpTvsRapidity", "pT vs Rapidity", kTH2F, {{100, 0.0f, 10.0f}, {300, -1.5f, 1.5f}}); - histos.add("hFTOCvsTPCNoCut", "Mult correlation FT0C vs. TPC without any cut", kTH2F, {{80, 0.0f, 80.0f}, {100, -0.5f, 5999.5f}}); - histos.add("hFTOCvsTPC", "Mult correlation FT0C vs. TPC", kTH2F, {{80, 0.0f, 80.0f}, {100, -0.5f, 5999.5f}}); - histos.add("hFTOCvsTPCSelected", "Mult correlation FT0C vs. TPC after selection", kTH2F, {{80, 0.0f, 80.0f}, {100, -0.5f, 5999.5f}}); histos.add("hCentrality", "Centrality distribution", kTH1F, {{200, 0.0, 200.0}}); histos.add("hVtxZ", "Vertex distribution in Z;Z (cm)", kTH1F, {{400, -20.0, 20.0}}); - histos.add("hEta", "Eta distribution", kTH1F, {{200, -1.0f, 1.0f}}); - histos.add("hDcaxy", "Dcaxy distribution", kTH1F, {{200, -1.0f, 1.0f}}); - histos.add("hDcaz", "Dcaz distribution", kTH1F, {{200, -1.0f, 1.0f}}); - - histos.add("hITS", "ITS cluster", kTH2F, {{10, -0.5f, 9.5f}, {200, -1.0, 1.0}}); - histos.add("hTPC", "TPC crossed rows", kTH2F, {{90, 69.5f, 159.5f}, {200, -1.0, 1.0}}); - histos.add("hTPCScls", "TPC Shared cluster", kTH2F, {{16, -0.5f, 159.5f}, {200, -1.0, 1.0}}); - histos.add("hTPCSclsFrac", "Fraction of TPC Shared cluster", kTH2F, {{100, -0.0f, 2.0f}, {200, -1.0, 1.0}}); - - histos.add("hNsigmaKaonTPC", "NsigmaKaon TPC distribution", kTH1F, {{200, -10.0f, 10.0f}}); - histos.add("hNsigmaKaonTOF", "NsigmaKaon TOF distribution", kTH1F, {{200, -10.0f, 10.0f}}); - histos.add("hPsiFT0C", "PsiFT0C", kTH3F, {centAxis, occupancyAxis, phiAxis}); - histos.add("hPsiFT0A", "PsiFT0A", kTH3F, {centAxis, occupancyAxis, phiAxis}); - histos.add("hPsiTPC", "PsiTPC", kTH3F, {centAxis, occupancyAxis, phiAxis}); - histos.add("hPsiTPCR", "PsiTPCR", kTH3F, {centAxis, occupancyAxis, phiAxis}); - histos.add("hPsiTPCL", "PsiTPCL", kTH3F, {centAxis, occupancyAxis, phiAxis}); - - histos.add("hSparseV2SameEventCosPhi", "hSparseV2SameEventCosPhi", HistType::kTHnSparseD, {thnAxisInvMass, thnAxisPt, cumulantAxis, thnAxisCentrality}); - histos.add("hSparseV2SameEventSinPhi", "hSparseV2SameEventSinPhi", HistType::kTHnSparseD, {thnAxisInvMass, thnAxisPt, cumulantAxis, thnAxisCentrality}); - histos.add("hSparseV2SameEventCosPsi", "hSparseV2SameEventCosPsi", HistType::kTHnSparseD, {thnAxisInvMass, thnAxisPt, cumulantAxis, thnAxisCentrality}); - histos.add("hSparseV2SameEventSinPsi", "hSparseV2SameEventSinPsi", HistType::kTHnSparseD, {thnAxisInvMass, thnAxisPt, cumulantAxis, thnAxisCentrality}); - - histos.add("hSparseV2SameEventCosDeltaPhi", "hSparseV2SameEventCosDeltaPhi", HistType::kTHnSparseD, {thnAxisInvMass, thnAxisPt, thnAxisV2, thnAxisCentrality}); - histos.add("hSparseV2MixedEventCosDeltaPhi", "hSparseV2MixedEventCosDeltaPhi", HistType::kTHnSparseD, {thnAxisInvMass, thnAxisPt, thnAxisV2, thnAxisCentrality}); - histos.add("hSparseV2MixEPAngleCosDeltaPhi", "hSparseV2MixEPAngleCosDeltaPhi", HistType::kTHnSparseD, {thnAxisInvMass, thnAxisPt, thnAxisV2, thnAxisCentrality}); - - histos.add("hSparseV2SameEventCos2DeltaPhi", "hSparseV2SameEventCos2DeltaPhi", HistType::kTHnSparseD, {thnAxisInvMass, thnAxisPt, thnAxisV2, thnAxisCentrality}); - histos.add("hSparseV2MixedEventCos2DeltaPhi", "hSparseV2MixedEventCos2DeltaPhi", HistType::kTHnSparseD, {thnAxisInvMass, thnAxisPt, thnAxisV2, thnAxisCentrality}); - - histos.add("hSparseV2SameEventCosDeltaPhiSquare", "hSparseV2SameEventCosDeltaPhiSquare", HistType::kTHnSparseD, {thnAxisInvMass, thnAxisPt, squareAxis, thnAxisCentrality}); - histos.add("hSparseV2SameEventCosDeltaPhiCube", "hSparseV2SameEventCosDeltaPhiCube", HistType::kTHnSparseD, {thnAxisInvMass, thnAxisPt, thnAxisV2, thnAxisCentrality}); - histos.add("hSparseV2MixedEventCosDeltaPhiSquare", "hSparseV2MixedEventCosDeltaPhiSquare", HistType::kTHnSparseD, {thnAxisInvMass, thnAxisPt, squareAxis, thnAxisCentrality}); - - histos.add("hSparseV2SameEventSinDeltaPhi", "hSparseV2SameEventSinDeltaPhi", HistType::kTHnSparseD, {thnAxisInvMass, thnAxisPt, thnAxisV2, thnAxisCentrality}); - histos.add("hSparseV2MixedEventSinDeltaPhi", "hSparseV2MixedEventSinDeltaPhi", HistType::kTHnSparseD, {thnAxisInvMass, thnAxisPt, thnAxisV2, thnAxisCentrality}); - - if (fillSA) { - histos.add("hSparseV2SameEventSA", "hSparseV2SameEventSA", HistType::kTHnSparseD, {thnAxisInvMass, thnAxisPt, thnAxisSA, thnAxisRapidity, thnAxisCentrality}); - histos.add("hSparseV2MixedEventSA", "hSparseV2MixedEventSA", HistType::kTHnSparseD, {thnAxisInvMass, thnAxisPt, thnAxisSA, thnAxisRapidity, thnAxisCentrality}); - histos.add("hSparseV2SameEventCosThetaStar", "hSparseV2SameEventCosThetaStar", HistType::kTHnSparseD, {thnAxisInvMass, thnAxisPt, thnAxisCosThetaStar, thnAxisRapidity, thnAxisCentrality}); - histos.add("hSparseV2MixedEventCosThetaStar", "hSparseV2MixedEventCosThetaStar", HistType::kTHnSparseD, {thnAxisInvMass, thnAxisPt, thnAxisCosThetaStar, thnAxisRapidity, thnAxisCentrality}); - } - // histogram for resolution - histos.add("ResFT0CTPC", "ResFT0CTPC", kTH3F, {centAxis, occupancyAxis, resAxis}); - histos.add("ResFT0CTPCR", "ResFT0CTPCR", kTH3F, {centAxis, occupancyAxis, resAxis}); - histos.add("ResFT0CTPCL", "ResFT0CTPCL", kTH3F, {centAxis, occupancyAxis, resAxis}); - histos.add("ResTPCRTPCL", "ResTPCRTPCL", kTH3F, {centAxis, occupancyAxis, resAxis}); - histos.add("ResFT0CFT0A", "ResFT0CFT0A", kTH3F, {centAxis, occupancyAxis, resAxis}); - histos.add("ResFT0ATPC", "ResFT0ATPC", kTH3F, {centAxis, occupancyAxis, resAxis}); - - histos.add("Res4FT0CTPC", "Res4FT0CTPC", kTH3F, {centAxis, occupancyAxis, resAxis}); - histos.add("Res4FT0CTPCR", "Res4FT0CTPCR", kTH3F, {centAxis, occupancyAxis, resAxis}); - histos.add("Res4FT0CTPCL", "Res4FT0CTPCL", kTH3F, {centAxis, occupancyAxis, resAxis}); - histos.add("Res4TPCRTPCL", "Res4TPCRTPCL", kTH3F, {centAxis, occupancyAxis, resAxis}); - histos.add("Res4FT0CFT0A", "Res4FT0CFT0A", kTH3F, {centAxis, occupancyAxis, resAxis}); - histos.add("Res4FT0ATPC", "Res4FT0ATPC", kTH3F, {centAxis, occupancyAxis, resAxis}); - - histos.add("ResFT0CTPCSquare", "ResFT0CTPCSquare", kTH3F, {centAxis, occupancyAxis, resAxisSquare}); - histos.add("ResFT0CTPCRSquare", "ResFT0CTPCRSquare", kTH3F, {centAxis, occupancyAxis, resAxisSquare}); - histos.add("ResFT0CTPCLSquare", "ResFT0CTPCLSquare", kTH3F, {centAxis, occupancyAxis, resAxisSquare}); - histos.add("ResTPCRTPCLSquare", "ResTPCRTPCLSquare", kTH3F, {centAxis, occupancyAxis, resAxisSquare}); - histos.add("ResFT0CFT0ASquare", "ResFT0CFT0ASquare", kTH3F, {centAxis, occupancyAxis, resAxisSquare}); - histos.add("ResFT0ATPCSquare", "ResFT0ATPCSquare", kTH3F, {centAxis, occupancyAxis, resAxisSquare}); - - histos.add("ResSPFT0CTPC", "ResSPFT0CTPC", kTH3F, {centAxis, occupancyAxis, resAxis}); - histos.add("ResSPFT0CTPCR", "ResSPFT0CTPCR", kTH3F, {centAxis, occupancyAxis, resAxis}); - histos.add("ResSPFT0CTPCL", "ResSPFT0CTPCL", kTH3F, {centAxis, occupancyAxis, resAxis}); - histos.add("ResSPTPCRTPCL", "ResSPTPCRTPCL", kTH3F, {centAxis, occupancyAxis, resAxis}); - histos.add("ResSPFT0CFT0A", "ResSPFT0CFT0A", kTH3F, {centAxis, occupancyAxis, resAxis}); - histos.add("ResSPFT0ATPC", "ResSPFT0ATPC", kTH3F, {centAxis, occupancyAxis, resAxis}); - - histos.add("Res4SPFT0CTPC", "Res4SPFT0CTPC", kTH3F, {centAxis, occupancyAxis, resAxis}); - histos.add("Res4SPFT0CTPCR", "Res4SPFT0CTPCR", kTH3F, {centAxis, occupancyAxis, resAxis}); - histos.add("Res4SPFT0CTPCL", "Res4SPFT0CTPCL", kTH3F, {centAxis, occupancyAxis, resAxis}); - histos.add("Res4SPTPCRTPCL", "Res4SPTPCRTPCL", kTH3F, {centAxis, occupancyAxis, resAxis}); - histos.add("Res4SPFT0CFT0A", "Res4SPFT0CFT0A", kTH3F, {centAxis, occupancyAxis, resAxis}); - histos.add("Res4SPFT0ATPC", "Res4SPFT0ATPC", kTH3F, {centAxis, occupancyAxis, resAxis}); - - histos.add("ResTrackSPFT0CTPC", "ResTrackSPFT0CTPC", kTH3F, {centAxis, occupancyAxis, resAxis}); - histos.add("ResTrackSPFT0CTPCR", "ResTrackSPFT0CTPCR", kTH3F, {centAxis, occupancyAxis, resAxis}); - histos.add("ResTrackSPFT0CTPCL", "ResTrackSPFT0CTPCL", kTH3F, {centAxis, occupancyAxis, resAxis}); - histos.add("ResTrackSPTPCRTPCL", "ResTrackSPTPCRTPCL", kTH3F, {centAxis, occupancyAxis, resAxis}); - histos.add("ResTrackSPFT0CFT0A", "ResTrackSPFT0CFT0A", kTH3F, {centAxis, occupancyAxis, resAxis}); - histos.add("ResTrackSPFT0ATPC", "ResTrackSPFT0ATPC", kTH3F, {centAxis, occupancyAxis, resAxis}); - - // MC histogram - if (isMC) { - histos.add("hMC", "MC Event statistics", kTH1F, {{10, 0.0f, 10.0f}}); - histos.add("h1PhiRecsplit", "Phi meson Rec split", kTH1F, {{100, 0.0f, 10.0f}}); - histos.add("CentPercentileMCRecHist", "MC Centrality", kTH1F, {{100, 0.0f, 100.0f}}); - - histos.add("hSparseV2MCGenSA", "hSparseV2SameEventSA", HistType::kTHnSparseD, {thnAxisInvMass, thnAxisPt, thnAxisSA, thnAxisRapidity, thnAxisCentrality}); - histos.add("hSparseV2MCGenCosThetaStar_effy", "hSparseV2SameEventCosThetaStar_effy", HistType::kTHnSparseD, {thnAxisInvMass, thnAxisPt, thnAxisCosThetaStar, thnAxisRapidity, thnAxisCentrality}); - - histos.add("hSparseV2MCRecSA", "hSparseV2SameEventSA", HistType::kTHnSparseD, {thnAxisInvMass, thnAxisPt, thnAxisSA, thnAxisRapidity, thnAxisCentrality}); - histos.add("hSparseV2MCRecCosThetaStar_effy", "hSparseV2SameEventCosThetaStar_effy", HistType::kTHnSparseD, {thnAxisInvMass, thnAxisPt, thnAxisCosThetaStar, thnAxisRapidity, thnAxisCentrality}); - - // weight - - histos.add("hSparsePhiMCGenWeight", "hSparsePhiMCGenWeight", HistType::kTHnSparseD, {thnAxisCentrality, {36, 0.0f, TMath::Pi()}, {400, -1.0, 1}, thnAxisPt, {8, -0.8, 0.8}}); - histos.add("hSparsePhiMCRecWeight", "hSparsePhiMCRecWeight", HistType::kTHnSparseD, {thnAxisCentrality, {36, 0.0f, TMath::Pi()}, {400, -1.0, 1}, thnAxisPt, {8, -0.8, 0.8}}); - histos.add("hSparsePhiMCGenKaonWeight", "hSparsePhiMCGenKaonWeight", HistType::kTHnSparseD, {thnAxisCentrality, {36, 0.0f, TMath::Pi()}, {400, -1.0, 1}, axisPtKaonWeight, {8, -0.8, 0.8}}); - histos.add("hSparsePhiMCRecKaonWeight", "hSparsePhiMCRecKaonWeight", HistType::kTHnSparseD, {thnAxisCentrality, {36, 0.0f, TMath::Pi()}, {400, -1.0, 1}, axisPtKaonWeight, {8, -0.8, 0.8}}); - histos.add("hSparsePhiMCRecKaonMissMatchWeight", "hSparsePhiMCRecKaonMissMatchWeight", HistType::kTHnSparseD, {thnAxisCentrality, {36, 0.0f, TMath::Pi()}, {400, -1.0, 1}, axisPtKaonWeight, {8, -0.8, 0.8}}); - - histos.add("hSparseMCGenWeight", "hSparseMCGenWeight", HistType::kTHnSparseD, {thnAxisCentrality, {36, 0.0f, TMath::Pi()}, {400, -1.0, 1}, axisPtKaonWeight, {8, -0.8, 0.8}}); - histos.add("hSparseMCRecWeight", "hSparseMCRecWeight", HistType::kTHnSparseD, {thnAxisCentrality, {36, 0.0f, TMath::Pi()}, {400, -1.0, 1}, axisPtKaonWeight, {8, -0.8, 0.8}}); - histos.add("hSparseMCRecAllTrackWeight", "hSparseMCRecAllTrackWeight", HistType::kTHnSparseD, {thnAxisCentrality, {36, 0.0, TMath::Pi()}, {400, -1.0, 1}, axisPtKaonWeight, {8, -0.8, 0.8}}); - - histos.add("hImpactParameter", "Impact parameter", kTH1F, {{200, 0.0f, 20.0f}}); - histos.add("hEventPlaneAngle", "hEventPlaneAngle", kTH1F, {{200, -2.0f * TMath::Pi(), 2.0f * TMath::Pi()}}); - histos.add("hEventPlaneAngleRec", "hEventPlaneAngleRec", kTH1F, {{200, -2.0f * TMath::Pi(), 2.0f * TMath::Pi()}}); - histos.add("hNchVsImpactParameter", "hNchVsImpactParameter", kTH2F, {{200, 0.0f, 20.0f}, {500, -0.5f, 5000.5f}}); - histos.add("hSparseMCGenV2", "hSparseMCGenV2", HistType::kTHnSparseD, {thnAxisCentrality, {200, -1.0, 1.0}, axisPtKaonWeight}); - histos.add("hSparseMCRecV2", "hSparseMCRecV2", HistType::kTHnSparseD, {thnAxisCentrality, {200, -1.0, 1.0}, axisPtKaonWeight}); - // histos.add("hSparseMCGenV2Square", "hSparseMCGenV2Square", HistType::kTHnSparseD, {thnAxisCentrality, {1000, 0.0, 1.0}, axisPtKaonWeight}); - // histos.add("hSparseMCRecV2Square", "hSparseMCRecV2Square", HistType::kTHnSparseD, {thnAxisCentrality, {1000, 0.0, 1.0}, axisPtKaonWeight}); - histos.add("hSparseMCGenV2Square", "hSparseMCGenV2Square", HistType::kTH3D, {thnAxisCentrality, {1000, 0.0, 1.0}, axisPtKaonWeight}); - histos.add("hSparseMCRecV2Square", "hSparseMCRecV2Square", HistType::kTH3D, {thnAxisCentrality, {1000, 0.0, 1.0}, axisPtKaonWeight}); + + if (!fillv1) { + histos.add("hTPCglobalmomcorr", "Momentum correlation", kTH3F, {{200, -10.0f, 10.0f}, {200, -10.0f, 10.0f}, {8, 0.0f, 80.0f}}); + histos.add("hpTvsRapidity", "pT vs Rapidity", kTH2F, {{100, 0.0f, 10.0f}, {300, -1.5f, 1.5f}}); + histos.add("hFTOCvsTPCNoCut", "Mult correlation FT0C vs. TPC without any cut", kTH2F, {{80, 0.0f, 80.0f}, {100, -0.5f, 5999.5f}}); + histos.add("hFTOCvsTPC", "Mult correlation FT0C vs. TPC", kTH2F, {{80, 0.0f, 80.0f}, {100, -0.5f, 5999.5f}}); + histos.add("hFTOCvsTPCSelected", "Mult correlation FT0C vs. TPC after selection", kTH2F, {{80, 0.0f, 80.0f}, {100, -0.5f, 5999.5f}}); + histos.add("hEta", "Eta distribution", kTH1F, {{200, -1.0f, 1.0f}}); + histos.add("hDcaxy", "Dcaxy distribution", kTH1F, {{200, -1.0f, 1.0f}}); + histos.add("hDcaz", "Dcaz distribution", kTH1F, {{200, -1.0f, 1.0f}}); + + histos.add("hITS", "ITS cluster", kTH2F, {{10, -0.5f, 9.5f}, {200, -1.0, 1.0}}); + histos.add("hTPC", "TPC crossed rows", kTH2F, {{90, 69.5f, 159.5f}, {200, -1.0, 1.0}}); + histos.add("hTPCScls", "TPC Shared cluster", kTH2F, {{16, -0.5f, 159.5f}, {200, -1.0, 1.0}}); + histos.add("hTPCSclsFrac", "Fraction of TPC Shared cluster", kTH2F, {{100, -0.0f, 2.0f}, {200, -1.0, 1.0}}); + + histos.add("hNsigmaKaonTPC", "NsigmaKaon TPC distribution", kTH1F, {{200, -10.0f, 10.0f}}); + histos.add("hNsigmaKaonTOF", "NsigmaKaon TOF distribution", kTH1F, {{200, -10.0f, 10.0f}}); + histos.add("hPsiFT0C", "PsiFT0C", kTH3F, {centAxis, occupancyAxis, phiAxis}); + histos.add("hPsiFT0A", "PsiFT0A", kTH3F, {centAxis, occupancyAxis, phiAxis}); + histos.add("hPsiTPC", "PsiTPC", kTH3F, {centAxis, occupancyAxis, phiAxis}); + histos.add("hPsiTPCR", "PsiTPCR", kTH3F, {centAxis, occupancyAxis, phiAxis}); + histos.add("hPsiTPCL", "PsiTPCL", kTH3F, {centAxis, occupancyAxis, phiAxis}); + + histos.add("hSparseV2SameEventCosPhi", "hSparseV2SameEventCosPhi", HistType::kTHnSparseD, {thnAxisInvMass, thnAxisPt, cumulantAxis, thnAxisCentrality}); + histos.add("hSparseV2SameEventSinPhi", "hSparseV2SameEventSinPhi", HistType::kTHnSparseD, {thnAxisInvMass, thnAxisPt, cumulantAxis, thnAxisCentrality}); + histos.add("hSparseV2SameEventCosPsi", "hSparseV2SameEventCosPsi", HistType::kTHnSparseD, {thnAxisInvMass, thnAxisPt, cumulantAxis, thnAxisCentrality}); + histos.add("hSparseV2SameEventSinPsi", "hSparseV2SameEventSinPsi", HistType::kTHnSparseD, {thnAxisInvMass, thnAxisPt, cumulantAxis, thnAxisCentrality}); + + histos.add("hSparseV2SameEventCosDeltaPhi", "hSparseV2SameEventCosDeltaPhi", HistType::kTHnSparseD, {thnAxisInvMass, thnAxisPt, thnAxisV2, thnAxisCentrality}); + histos.add("hSparseV2MixedEventCosDeltaPhi", "hSparseV2MixedEventCosDeltaPhi", HistType::kTHnSparseD, {thnAxisInvMass, thnAxisPt, thnAxisV2, thnAxisCentrality}); + histos.add("hSparseV2MixEPAngleCosDeltaPhi", "hSparseV2MixEPAngleCosDeltaPhi", HistType::kTHnSparseD, {thnAxisInvMass, thnAxisPt, thnAxisV2, thnAxisCentrality}); + + histos.add("hSparseV2SameEventCos2DeltaPhi", "hSparseV2SameEventCos2DeltaPhi", HistType::kTHnSparseD, {thnAxisInvMass, thnAxisPt, thnAxisV2, thnAxisCentrality}); + histos.add("hSparseV2MixedEventCos2DeltaPhi", "hSparseV2MixedEventCos2DeltaPhi", HistType::kTHnSparseD, {thnAxisInvMass, thnAxisPt, thnAxisV2, thnAxisCentrality}); + + histos.add("hSparseV2SameEventCosDeltaPhiSquare", "hSparseV2SameEventCosDeltaPhiSquare", HistType::kTHnSparseD, {thnAxisInvMass, thnAxisPt, squareAxis, thnAxisCentrality}); + histos.add("hSparseV2SameEventCosDeltaPhiCube", "hSparseV2SameEventCosDeltaPhiCube", HistType::kTHnSparseD, {thnAxisInvMass, thnAxisPt, thnAxisV2, thnAxisCentrality}); + histos.add("hSparseV2MixedEventCosDeltaPhiSquare", "hSparseV2MixedEventCosDeltaPhiSquare", HistType::kTHnSparseD, {thnAxisInvMass, thnAxisPt, squareAxis, thnAxisCentrality}); + + histos.add("hSparseV2SameEventSinDeltaPhi", "hSparseV2SameEventSinDeltaPhi", HistType::kTHnSparseD, {thnAxisInvMass, thnAxisPt, thnAxisV2, thnAxisCentrality}); + histos.add("hSparseV2MixedEventSinDeltaPhi", "hSparseV2MixedEventSinDeltaPhi", HistType::kTHnSparseD, {thnAxisInvMass, thnAxisPt, thnAxisV2, thnAxisCentrality}); + + if (fillSA) { + histos.add("hSparseV2SameEventSA", "hSparseV2SameEventSA", HistType::kTHnSparseD, {thnAxisInvMass, thnAxisPt, thnAxisSA, thnAxisRapidity, thnAxisCentrality}); + histos.add("hSparseV2MixedEventSA", "hSparseV2MixedEventSA", HistType::kTHnSparseD, {thnAxisInvMass, thnAxisPt, thnAxisSA, thnAxisRapidity, thnAxisCentrality}); + histos.add("hSparseV2SameEventCosThetaStar", "hSparseV2SameEventCosThetaStar", HistType::kTHnSparseD, {thnAxisInvMass, thnAxisPt, thnAxisCosThetaStar, thnAxisRapidity, thnAxisCentrality}); + histos.add("hSparseV2MixedEventCosThetaStar", "hSparseV2MixedEventCosThetaStar", HistType::kTHnSparseD, {thnAxisInvMass, thnAxisPt, thnAxisCosThetaStar, thnAxisRapidity, thnAxisCentrality}); + } + // histogram for resolution + histos.add("ResFT0CTPC", "ResFT0CTPC", kTH3F, {centAxis, occupancyAxis, resAxis}); + histos.add("ResFT0CTPCR", "ResFT0CTPCR", kTH3F, {centAxis, occupancyAxis, resAxis}); + histos.add("ResFT0CTPCL", "ResFT0CTPCL", kTH3F, {centAxis, occupancyAxis, resAxis}); + histos.add("ResTPCRTPCL", "ResTPCRTPCL", kTH3F, {centAxis, occupancyAxis, resAxis}); + histos.add("ResFT0CFT0A", "ResFT0CFT0A", kTH3F, {centAxis, occupancyAxis, resAxis}); + histos.add("ResFT0ATPC", "ResFT0ATPC", kTH3F, {centAxis, occupancyAxis, resAxis}); + + histos.add("Res4FT0CTPC", "Res4FT0CTPC", kTH3F, {centAxis, occupancyAxis, resAxis}); + histos.add("Res4FT0CTPCR", "Res4FT0CTPCR", kTH3F, {centAxis, occupancyAxis, resAxis}); + histos.add("Res4FT0CTPCL", "Res4FT0CTPCL", kTH3F, {centAxis, occupancyAxis, resAxis}); + histos.add("Res4TPCRTPCL", "Res4TPCRTPCL", kTH3F, {centAxis, occupancyAxis, resAxis}); + histos.add("Res4FT0CFT0A", "Res4FT0CFT0A", kTH3F, {centAxis, occupancyAxis, resAxis}); + histos.add("Res4FT0ATPC", "Res4FT0ATPC", kTH3F, {centAxis, occupancyAxis, resAxis}); + + histos.add("ResFT0CTPCSquare", "ResFT0CTPCSquare", kTH3F, {centAxis, occupancyAxis, resAxisSquare}); + histos.add("ResFT0CTPCRSquare", "ResFT0CTPCRSquare", kTH3F, {centAxis, occupancyAxis, resAxisSquare}); + histos.add("ResFT0CTPCLSquare", "ResFT0CTPCLSquare", kTH3F, {centAxis, occupancyAxis, resAxisSquare}); + histos.add("ResTPCRTPCLSquare", "ResTPCRTPCLSquare", kTH3F, {centAxis, occupancyAxis, resAxisSquare}); + histos.add("ResFT0CFT0ASquare", "ResFT0CFT0ASquare", kTH3F, {centAxis, occupancyAxis, resAxisSquare}); + histos.add("ResFT0ATPCSquare", "ResFT0ATPCSquare", kTH3F, {centAxis, occupancyAxis, resAxisSquare}); + + histos.add("ResSPFT0CTPC", "ResSPFT0CTPC", kTH3F, {centAxis, occupancyAxis, resAxis}); + histos.add("ResSPFT0CTPCR", "ResSPFT0CTPCR", kTH3F, {centAxis, occupancyAxis, resAxis}); + histos.add("ResSPFT0CTPCL", "ResSPFT0CTPCL", kTH3F, {centAxis, occupancyAxis, resAxis}); + histos.add("ResSPTPCRTPCL", "ResSPTPCRTPCL", kTH3F, {centAxis, occupancyAxis, resAxis}); + histos.add("ResSPFT0CFT0A", "ResSPFT0CFT0A", kTH3F, {centAxis, occupancyAxis, resAxis}); + histos.add("ResSPFT0ATPC", "ResSPFT0ATPC", kTH3F, {centAxis, occupancyAxis, resAxis}); + + histos.add("Res4SPFT0CTPC", "Res4SPFT0CTPC", kTH3F, {centAxis, occupancyAxis, resAxis}); + histos.add("Res4SPFT0CTPCR", "Res4SPFT0CTPCR", kTH3F, {centAxis, occupancyAxis, resAxis}); + histos.add("Res4SPFT0CTPCL", "Res4SPFT0CTPCL", kTH3F, {centAxis, occupancyAxis, resAxis}); + histos.add("Res4SPTPCRTPCL", "Res4SPTPCRTPCL", kTH3F, {centAxis, occupancyAxis, resAxis}); + histos.add("Res4SPFT0CFT0A", "Res4SPFT0CFT0A", kTH3F, {centAxis, occupancyAxis, resAxis}); + histos.add("Res4SPFT0ATPC", "Res4SPFT0ATPC", kTH3F, {centAxis, occupancyAxis, resAxis}); + + histos.add("ResTrackSPFT0CTPC", "ResTrackSPFT0CTPC", kTH3F, {centAxis, occupancyAxis, resAxis}); + histos.add("ResTrackSPFT0CTPCR", "ResTrackSPFT0CTPCR", kTH3F, {centAxis, occupancyAxis, resAxis}); + histos.add("ResTrackSPFT0CTPCL", "ResTrackSPFT0CTPCL", kTH3F, {centAxis, occupancyAxis, resAxis}); + histos.add("ResTrackSPTPCRTPCL", "ResTrackSPTPCRTPCL", kTH3F, {centAxis, occupancyAxis, resAxis}); + histos.add("ResTrackSPFT0CFT0A", "ResTrackSPFT0CFT0A", kTH3F, {centAxis, occupancyAxis, resAxis}); + histos.add("ResTrackSPFT0ATPC", "ResTrackSPFT0ATPC", kTH3F, {centAxis, occupancyAxis, resAxis}); + + // MC histogram + if (isMC) { + histos.add("hMC", "MC Event statistics", kTH1F, {{10, 0.0f, 10.0f}}); + histos.add("h1PhiRecsplit", "Phi meson Rec split", kTH1F, {{100, 0.0f, 10.0f}}); + histos.add("CentPercentileMCRecHist", "MC Centrality", kTH1F, {{100, 0.0f, 100.0f}}); + + histos.add("hSparseV2MCGenSA", "hSparseV2SameEventSA", HistType::kTHnSparseD, {thnAxisInvMass, thnAxisPt, thnAxisSA, thnAxisRapidity, thnAxisCentrality}); + histos.add("hSparseV2MCGenCosThetaStar_effy", "hSparseV2SameEventCosThetaStar_effy", HistType::kTHnSparseD, {thnAxisInvMass, thnAxisPt, thnAxisCosThetaStar, thnAxisRapidity, thnAxisCentrality}); + + histos.add("hSparseV2MCRecSA", "hSparseV2SameEventSA", HistType::kTHnSparseD, {thnAxisInvMass, thnAxisPt, thnAxisSA, thnAxisRapidity, thnAxisCentrality}); + histos.add("hSparseV2MCRecCosThetaStar_effy", "hSparseV2SameEventCosThetaStar_effy", HistType::kTHnSparseD, {thnAxisInvMass, thnAxisPt, thnAxisCosThetaStar, thnAxisRapidity, thnAxisCentrality}); + + // weight + + histos.add("hSparsePhiMCGenWeight", "hSparsePhiMCGenWeight", HistType::kTHnSparseD, {thnAxisCentrality, {36, 0.0f, TMath::Pi()}, {400, -1.0, 1}, thnAxisPt, {8, -0.8, 0.8}}); + histos.add("hSparsePhiMCRecWeight", "hSparsePhiMCRecWeight", HistType::kTHnSparseD, {thnAxisCentrality, {36, 0.0f, TMath::Pi()}, {400, -1.0, 1}, thnAxisPt, {8, -0.8, 0.8}}); + histos.add("hSparsePhiMCGenKaonWeight", "hSparsePhiMCGenKaonWeight", HistType::kTHnSparseD, {thnAxisCentrality, {36, 0.0f, TMath::Pi()}, {400, -1.0, 1}, axisPtKaonWeight, {8, -0.8, 0.8}}); + histos.add("hSparsePhiMCRecKaonWeight", "hSparsePhiMCRecKaonWeight", HistType::kTHnSparseD, {thnAxisCentrality, {36, 0.0f, TMath::Pi()}, {400, -1.0, 1}, axisPtKaonWeight, {8, -0.8, 0.8}}); + histos.add("hSparsePhiMCRecKaonMissMatchWeight", "hSparsePhiMCRecKaonMissMatchWeight", HistType::kTHnSparseD, {thnAxisCentrality, {36, 0.0f, TMath::Pi()}, {400, -1.0, 1}, axisPtKaonWeight, {8, -0.8, 0.8}}); + + histos.add("hSparseMCGenWeight", "hSparseMCGenWeight", HistType::kTHnSparseD, {thnAxisCentrality, {36, 0.0f, TMath::Pi()}, {400, -1.0, 1}, axisPtKaonWeight, {8, -0.8, 0.8}}); + histos.add("hSparseMCRecWeight", "hSparseMCRecWeight", HistType::kTHnSparseD, {thnAxisCentrality, {36, 0.0f, TMath::Pi()}, {400, -1.0, 1}, axisPtKaonWeight, {8, -0.8, 0.8}}); + histos.add("hSparseMCRecAllTrackWeight", "hSparseMCRecAllTrackWeight", HistType::kTHnSparseD, {thnAxisCentrality, {36, 0.0, TMath::Pi()}, {400, -1.0, 1}, axisPtKaonWeight, {8, -0.8, 0.8}}); + + histos.add("hImpactParameter", "Impact parameter", kTH1F, {{200, 0.0f, 20.0f}}); + histos.add("hEventPlaneAngle", "hEventPlaneAngle", kTH1F, {{200, -2.0f * TMath::Pi(), 2.0f * TMath::Pi()}}); + histos.add("hEventPlaneAngleRec", "hEventPlaneAngleRec", kTH1F, {{200, -2.0f * TMath::Pi(), 2.0f * TMath::Pi()}}); + histos.add("hNchVsImpactParameter", "hNchVsImpactParameter", kTH2F, {{200, 0.0f, 20.0f}, {500, -0.5f, 5000.5f}}); + histos.add("hSparseMCGenV2", "hSparseMCGenV2", HistType::kTHnSparseD, {thnAxisCentrality, {200, -1.0, 1.0}, axisPtKaonWeight}); + histos.add("hSparseMCRecV2", "hSparseMCRecV2", HistType::kTHnSparseD, {thnAxisCentrality, {200, -1.0, 1.0}, axisPtKaonWeight}); + // histos.add("hSparseMCGenV2Square", "hSparseMCGenV2Square", HistType::kTHnSparseD, {thnAxisCentrality, {1000, 0.0, 1.0}, axisPtKaonWeight}); + // histos.add("hSparseMCRecV2Square", "hSparseMCRecV2Square", HistType::kTHnSparseD, {thnAxisCentrality, {1000, 0.0, 1.0}, axisPtKaonWeight}); + histos.add("hSparseMCGenV2Square", "hSparseMCGenV2Square", HistType::kTH3D, {thnAxisCentrality, {1000, 0.0, 1.0}, axisPtKaonWeight}); + histos.add("hSparseMCRecV2Square", "hSparseMCRecV2Square", HistType::kTH3D, {thnAxisCentrality, {1000, 0.0, 1.0}, axisPtKaonWeight}); + } } // Event selection cut additional - Alex if (additionalEvsel) { @@ -460,10 +504,12 @@ struct phipbpb { ConfigurableAxis axisVertex{"axisVertex", {20, -10, 10}, "vertex axis for bin"}; ConfigurableAxis axisMultiplicityClass{"axisMultiplicityClass", {20, 0, 100}, "multiplicity percentile for bin"}; ConfigurableAxis axisEPAngle{"axisEPAngle", {6, -TMath::Pi() / 2, TMath::Pi() / 2}, "event plane angle"}; + ConfigurableAxis axisSPAngle{"axisSPAngle", {6, -TMath::Pi(), TMath::Pi()}, "spectator plane angle"}; ConfigurableAxis axisOccup{"axisOccup", {20, -0.5, 40000.0}, "occupancy axis"}; // using BinningTypeVertexContributor = ColumnBinningPolicy; using BinningTypeVertexContributor = ColumnBinningPolicy; + using BinningTypeVertexContributorv1 = ColumnBinningPolicy; ROOT::Math::PxPyPzMVector PhiMesonMother, KaonPlus, KaonMinus, fourVecDauCM; ROOT::Math::XYZVector threeVecDauCM, threeVecDauCMXY, eventplaneVec, eventplaneVecNorm, beamvector; int currentRunNumber = -999; @@ -557,6 +603,7 @@ struct phipbpb { hweight = ccdb->getForTimeStamp(ConfWeightPath.value, bc.timestamp()); } lastRunNumber = currentRunNumber; + int Npostrack = 0; float weight1 = 1.0; float weight2 = 1.0; @@ -653,6 +700,7 @@ struct phipbpb { if (totalweight <= 0.0000005) { totalweight = 1.0; } + // LOGF(info, Form("weight %f %f",weight1, weight2)); if (TMath::Abs(PhiMesonMother.Rapidity()) < confRapidity) { histos.fill(HIST("ResTrackSPFT0CTPC"), centrality, occupancy, QFT0C * QTPC * TMath::Cos(2.0 * (psiFT0C - psiTPC))); @@ -690,6 +738,7 @@ struct phipbpb { histos.fill(HIST("hSparseV2SameEventSinPsi"), PhiMesonMother.M(), PhiMesonMother.Pt(), TMath::Sin(2.0 * psiFT0C), centrality); } } + if (fillSA) { ROOT::Math::Boost boost{PhiMesonMother.BoostToCM()}; fourVecDauCM = boost(KaonMinus); @@ -714,7 +763,153 @@ struct phipbpb { } PROCESS_SWITCH(phipbpb, processSameEvent, "Process Same event", true); + void processSameEventv1(EventCandidatesv1::iterator const& collision, TrackCandidates const& /*tracks, aod::BCs const&*/, aod::BCsWithTimestamps const&) + { + if (!collision.sel8() || !collision.triggereventsp() || !collision.selection_bit(aod::evsel::kNoSameBunchPileup)) { + return; + } + auto centrality = collision.centFT0C(); + auto posThisColl = posTracks->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); + auto negThisColl = negTracks->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); + int occupancy = collision.trackOccupancyInTimeRange(); + o2::aod::ITSResponse itsResponse; + if (occupancy > cfgCutOccupancy) { + return; + } + if (additionalEvsel && !collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { + return; + } + if (additionalEvselITS && !collision.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { + return; + } + + histos.fill(HIST("hCentrality"), centrality); + histos.fill(HIST("hVtxZ"), collision.posZ()); + + auto qxZDCA = collision.qxZDCA(); + auto qxZDCC = collision.qxZDCC(); + auto qyZDCA = collision.qyZDCA(); + auto qyZDCC = collision.qyZDCC(); + auto psiZDCC = collision.psiZDCC(); + auto psiZDCA = collision.psiZDCA(); + + double modqxZDCA; + double modqyZDCA; + double modqxZDCC; + double modqyZDCC; + + if (cqvas) { + modqxZDCA = TMath::Sqrt((qxZDCA * qxZDCA) + (qyZDCA * qyZDCA)) * TMath::Cos(psiZDCA); + modqyZDCA = TMath::Sqrt((qxZDCA * qxZDCA) + (qyZDCA * qyZDCA)) * TMath::Sin(psiZDCA); + modqxZDCC = TMath::Sqrt((qxZDCC * qxZDCC) + (qyZDCC * qyZDCC)) * TMath::Cos(psiZDCC); + modqyZDCC = TMath::Sqrt((qxZDCC * qxZDCC) + (qyZDCC * qyZDCC)) * TMath::Sin(psiZDCC); + } else { + modqxZDCA = qxZDCA; + modqyZDCA = qyZDCA; + modqxZDCC = qxZDCC; + modqyZDCC = qyZDCC; + } + + auto QxtQxp = modqxZDCA * modqxZDCC; + auto QytQyp = modqyZDCA * modqyZDCC; + auto Qxytp = QxtQxp + QytQyp; + auto QxpQyt = modqxZDCA * modqyZDCC; + auto QxtQyp = modqxZDCC * modqyZDCA; + + if (fillv1) { + histos.fill(HIST("hpQxtQxpvscent"), centrality, QxtQxp); + histos.fill(HIST("hpQytQypvscent"), centrality, QytQyp); + histos.fill(HIST("hpQxytpvscent"), centrality, Qxytp); + histos.fill(HIST("hpQxpQytvscent"), centrality, QxpQyt); + histos.fill(HIST("hpQxtQypvscent"), centrality, QxtQyp); + histos.fill(HIST("hpQxpvscent"), centrality, modqxZDCA); + histos.fill(HIST("hpQxtvscent"), centrality, modqxZDCC); + histos.fill(HIST("hpQypvscent"), centrality, modqyZDCA); + histos.fill(HIST("hpQytvscent"), centrality, modqyZDCC); + } + + int Npostrack = 0; + for (auto track1 : posThisColl) { + // track selection + if (!selectionTrack(track1)) { + continue; + } + // PID check + if (ispTdepPID && !isTOFOnly && !selectionPIDpTdependent(track1)) { + continue; + } + if (!ispTdepPID && !isTOFOnly && !selectionPID(track1)) { + continue; + } + if (isTOFOnly && !selectionPID2(track1)) { + continue; + } + if (useGlobalTrack && track1.p() < 1.0 && !(itsResponse.nSigmaITS(track1) > -2.5 && itsResponse.nSigmaITS(track1) < 2.5)) { + continue; + } + auto track1ID = track1.globalIndex(); + for (auto track2 : negThisColl) { + // track selection + if (!selectionTrack(track2)) { + continue; + } + // PID check + if (ispTdepPID && !isTOFOnly && !selectionPIDpTdependent(track2)) { + continue; + } + if (!ispTdepPID && !isTOFOnly && !selectionPID(track2)) { + continue; + } + if (isTOFOnly && !selectionPID2(track2)) { + continue; + } + auto track2ID = track2.globalIndex(); + if (track2ID == track1ID) { + continue; + } + if (!selectionPair(track1, track2)) { + continue; + } + if (removefaketrak && isFakeKaon(track1)) { + continue; + } + if (removefaketrak && isFakeKaon(track2)) { + continue; + } + if (useGlobalTrack && track2.p() < 1.0 && !(itsResponse.nSigmaITS(track2) > -2.5 && itsResponse.nSigmaITS(track2) < 2.5)) { + continue; + } + KaonPlus = ROOT::Math::PxPyPzMVector(track1.px(), track1.py(), track1.pz(), massKa); + KaonMinus = ROOT::Math::PxPyPzMVector(track2.px(), track2.py(), track2.pz(), massKa); + PhiMesonMother = KaonPlus + KaonMinus; + + if (fillv1) { + auto ux = TMath::Cos(GetPhiInRange(PhiMesonMother.Phi())); + auto uy = TMath::Sin(GetPhiInRange(PhiMesonMother.Phi())); + auto uxQxp = ux * modqxZDCA; + auto uyQyp = uy * modqyZDCA; // correlations of particle and ZDC q vectors + auto uxyQxyp = uxQxp + uyQyp; + auto uxQxt = ux * modqxZDCC; + auto uyQyt = uy * modqyZDCC; + auto uxyQxyt = uxQxt + uyQyt; + auto oddv1 = ux * (modqxZDCA - modqxZDCC) + uy * (modqyZDCA - modqyZDCC); + + histos.fill(HIST("hpoddvscentpteta"), PhiMesonMother.M(), centrality, PhiMesonMother.Pt(), PhiMesonMother.Rapidity(), oddv1); + if (fillLOCC) { + histos.fill(HIST("hpuxyQxypvscentpteta"), PhiMesonMother.M(), centrality, PhiMesonMother.Pt(), PhiMesonMother.Rapidity(), uxyQxyp); + histos.fill(HIST("hpuxyQxytvscentpteta"), PhiMesonMother.M(), centrality, PhiMesonMother.Pt(), PhiMesonMother.Rapidity(), uxyQxyt); + histos.fill(HIST("hpuxvscentpteta"), PhiMesonMother.M(), centrality, PhiMesonMother.Pt(), PhiMesonMother.Rapidity(), ux); + histos.fill(HIST("hpuyvscentpteta"), PhiMesonMother.M(), centrality, PhiMesonMother.Pt(), PhiMesonMother.Rapidity(), uy); + } + } + } + Npostrack = Npostrack + 1; + } + } + PROCESS_SWITCH(phipbpb, processSameEventv1, "Process Same event for v1", false); + BinningTypeVertexContributor binningOnEPAngle{{axisVertex, axisMultiplicityClass, axisEPAngle}, true}; + BinningTypeVertexContributorv1 binningOnSPAngle{{axisVertex, axisMultiplicityClass, axisSPAngle}, true}; Preslice tracksPerCollision = aod::track::collisionId; void processMEAcc(EventCandidates const& collisions, TrackCandidates const& tracks) { @@ -749,6 +944,7 @@ struct phipbpb { auto centrality = collision1.centFT0C(); auto psiFT0C = collision1.psiFT0C(); auto QFT0C = collision1.qFT0C(); + o2::aod::ITSResponse itsResponse; auto grouptrack1 = tracks.sliceBy(tracksPerCollision, collision2.globalIndex()); auto grouptrack2 = tracks.sliceBy(tracksPerCollision, collision2.globalIndex()); @@ -809,6 +1005,7 @@ struct phipbpb { if (TMath::Abs(PhiMesonMother.Rapidity()) > confRapidity) { continue; } + if (useSP) { histos.fill(HIST("hSparseV2MixEPAngleCosDeltaPhi"), PhiMesonMother.M(), PhiMesonMother.Pt(), v2 * QFT0C, centrality); } else { @@ -818,6 +1015,143 @@ struct phipbpb { } } PROCESS_SWITCH(phipbpb, processMEAcc, "Process ME Acceptance", true); + + void processMEAccv1(EventCandidatesv1 const& collisions, TrackCandidates const& tracks) + { + for (auto& [collision1, collision2] : selfCombinations(binningOnSPAngle, cfgNoMixedEvents, -1, collisions, collisions)) { + + if (!collision1.sel8() || !collision1.triggereventsp() || !collision1.selection_bit(aod::evsel::kNoSameBunchPileup)) { + continue; + } + if (!collision2.sel8() || !collision2.triggereventsp() || !collision2.selection_bit(aod::evsel::kNoSameBunchPileup)) { + continue; + } + int occupancy1 = collision1.trackOccupancyInTimeRange(); + int occupancy2 = collision2.trackOccupancyInTimeRange(); + if (occupancy1 > cfgCutOccupancy) { + continue; + } + if (occupancy2 > cfgCutOccupancy) { + continue; + } + if (additionalEvsel && !collision1.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { + continue; + } + if (additionalEvsel && !collision2.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { + continue; + } + if (additionalEvselITS && !collision1.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { + continue; + } + if (additionalEvselITS && !collision2.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { + continue; + } + auto centrality = collision1.centFT0C(); + + auto qxZDCA = collision1.qxZDCA(); + auto qxZDCC = collision1.qxZDCC(); + auto qyZDCA = collision1.qyZDCA(); + auto qyZDCC = collision1.qyZDCC(); + auto psiZDCC = collision1.psiZDCC(); + auto psiZDCA = collision1.psiZDCA(); + + double modqxZDCA; + double modqyZDCA; + double modqxZDCC; + double modqyZDCC; + + if (cqvas) { + modqxZDCA = TMath::Sqrt((qxZDCA * qxZDCA) + (qyZDCA * qyZDCA)) * TMath::Cos(psiZDCA); + modqyZDCA = TMath::Sqrt((qxZDCA * qxZDCA) + (qyZDCA * qyZDCA)) * TMath::Sin(psiZDCA); + modqxZDCC = TMath::Sqrt((qxZDCC * qxZDCC) + (qyZDCC * qyZDCC)) * TMath::Cos(psiZDCC); + modqyZDCC = TMath::Sqrt((qxZDCC * qxZDCC) + (qyZDCC * qyZDCC)) * TMath::Sin(psiZDCC); + } else { + modqxZDCA = qxZDCA; + modqyZDCA = qyZDCA; + modqxZDCC = qxZDCC; + modqyZDCC = qyZDCC; + } + + o2::aod::ITSResponse itsResponse; + auto grouptrack1 = tracks.sliceBy(tracksPerCollision, collision1.globalIndex()); + auto grouptrack2 = tracks.sliceBy(tracksPerCollision, collision2.globalIndex()); + for (auto& [t1, t2] : soa::combinations(o2::soa::CombinationsFullIndexPolicy(grouptrack1, grouptrack2))) { + if (t2.index() <= t1.index()) { + continue; + } + if (t1.sign() * t2.sign() > 0) { + continue; + } + if (!selectionTrack(t1)) { + continue; + } + if (ispTdepPID && !isTOFOnly && !selectionPIDpTdependent(t1)) { + continue; + } + if (!ispTdepPID && !isTOFOnly && !selectionPID(t1)) { + continue; + } + if (isTOFOnly && !selectionPID2(t1)) { + continue; + } + if (useGlobalTrack && t1.p() < 1.0 && !(itsResponse.nSigmaITS(t1) > -2.5 && itsResponse.nSigmaITS(t1) < 2.5)) { + continue; + } + + if (!selectionTrack(t2)) { + continue; + } + if (ispTdepPID && !isTOFOnly && !selectionPIDpTdependent(t2)) { + continue; + } + if (!ispTdepPID && !isTOFOnly && !selectionPID(t2)) { + continue; + } + if (isTOFOnly && !selectionPID2(t2)) { + continue; + } + if (useGlobalTrack && t2.p() < 1.0 && !(itsResponse.nSigmaITS(t2) > -2.5 && itsResponse.nSigmaITS(t2) < 2.5)) { + continue; + } + + if (!selectionPair(t1, t2)) { + continue; + } + if (removefaketrak && isFakeKaon(t1)) { + continue; + } + if (removefaketrak && isFakeKaon(t2)) { + continue; + } + + KaonPlus = ROOT::Math::PxPyPzMVector(t1.px(), t1.py(), t1.pz(), massKa); + KaonMinus = ROOT::Math::PxPyPzMVector(t2.px(), t2.py(), t2.pz(), massKa); + PhiMesonMother = KaonPlus + KaonMinus; + + if (fillv1) { + auto ux = TMath::Cos(GetPhiInRange(PhiMesonMother.Phi())); + auto uy = TMath::Sin(GetPhiInRange(PhiMesonMother.Phi())); + auto uxQxp = ux * modqxZDCA; + auto uyQyp = uy * modqyZDCA; // correlations of particle and ZDC q vectors + auto uxyQxyp = uxQxp + uyQyp; + auto uxQxt = ux * modqxZDCC; + auto uyQyt = uy * modqyZDCC; + auto uxyQxyt = uxQxt + uyQyt; + auto oddv1 = ux * (modqxZDCA - modqxZDCC) + uy * (modqyZDCA - modqyZDCC); + + histos.fill(HIST("hpoddvscentptetamixacc"), PhiMesonMother.M(), centrality, PhiMesonMother.Pt(), PhiMesonMother.Rapidity(), oddv1); + if (fillLOCC) { + histos.fill(HIST("hpuxyQxypvscentptetamixacc"), PhiMesonMother.M(), centrality, PhiMesonMother.Pt(), PhiMesonMother.Rapidity(), uxyQxyp); + histos.fill(HIST("hpuxyQxytvscentptetamixacc"), PhiMesonMother.M(), centrality, PhiMesonMother.Pt(), PhiMesonMother.Rapidity(), uxyQxyt); + histos.fill(HIST("hpuxvscentptetamixacc"), PhiMesonMother.M(), centrality, PhiMesonMother.Pt(), PhiMesonMother.Rapidity(), ux); + histos.fill(HIST("hpuyvscentptetamixacc"), PhiMesonMother.M(), centrality, PhiMesonMother.Pt(), PhiMesonMother.Rapidity(), uy); + } + } + } + } + } + PROCESS_SWITCH(phipbpb, processMEAccv1, "Process ME Acceptance v1", false); + void processMixedEventOpti(EventCandidates const& collisions, TrackCandidates const& tracks) { auto tracksTuple = std::make_tuple(tracks); @@ -864,6 +1198,7 @@ struct phipbpb { if (additionalEvselITS && !collision2.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { continue; } + for (auto& [track1, track2] : o2::soa::combinations(o2::soa::CombinationsFullIndexPolicy(tracks1, tracks2))) { if (track1.sign() * track2.sign() > 0) { continue; @@ -909,6 +1244,7 @@ struct phipbpb { auto v2acc = TMath::Cos(4.0 * phiminuspsi); auto v2sin = TMath::Sin(2.0 * phiminuspsi); histos.fill(HIST("hpTvsRapidity"), PhiMesonMother.Pt(), PhiMesonMother.Rapidity()); + if (TMath::Abs(PhiMesonMother.Rapidity()) < confRapidity) { if (useSP) { histos.fill(HIST("hSparseV2MixedEventCosDeltaPhi"), PhiMesonMother.M(), PhiMesonMother.Pt(), v2 * QFT0C, centrality); @@ -937,6 +1273,132 @@ struct phipbpb { } } PROCESS_SWITCH(phipbpb, processMixedEventOpti, "Process Mixed event new", true); + + void processMixedEventOptiv1(EventCandidatesv1 const& collisions, TrackCandidates const& tracks) + { + auto tracksTuple = std::make_tuple(tracks); + BinningTypeVertexContributorv1 binningOnPositions{{axisVertex, axisMultiplicityClass, axisSPAngle}, true}; + SameKindPair pair{binningOnPositions, cfgNoMixedEvents, -1, collisions, tracksTuple, &cache}; + for (auto& [collision1, tracks1, collision2, tracks2] : pair) { + if (!collision1.sel8() || !collision1.triggereventsp() || !collision1.selection_bit(aod::evsel::kNoSameBunchPileup)) { + continue; + } + if (!collision2.sel8() || !collision2.triggereventsp() || !collision2.selection_bit(aod::evsel::kNoSameBunchPileup)) { + continue; + } + o2::aod::ITSResponse itsResponse; + int occupancy1 = collision1.trackOccupancyInTimeRange(); + int occupancy2 = collision2.trackOccupancyInTimeRange(); + if (occupancy1 > cfgCutOccupancy) { + continue; + } + if (occupancy2 > cfgCutOccupancy) { + continue; + } + auto centrality = collision1.centFT0C(); + + if (additionalEvsel && !collision1.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { + continue; + } + if (additionalEvsel && !collision2.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { + continue; + } + if (additionalEvselITS && !collision1.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { + continue; + } + if (additionalEvselITS && !collision2.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { + continue; + } + + auto qxZDCA = collision1.qxZDCA(); + auto qxZDCC = collision1.qxZDCC(); + auto qyZDCA = collision1.qyZDCA(); + auto qyZDCC = collision1.qyZDCC(); + auto psiZDCC = collision1.psiZDCC(); + auto psiZDCA = collision1.psiZDCA(); + + double modqxZDCA; + double modqyZDCA; + double modqxZDCC; + double modqyZDCC; + + if (cqvas) { + modqxZDCA = TMath::Sqrt((qxZDCA * qxZDCA) + (qyZDCA * qyZDCA)) * TMath::Cos(psiZDCA); + modqyZDCA = TMath::Sqrt((qxZDCA * qxZDCA) + (qyZDCA * qyZDCA)) * TMath::Sin(psiZDCA); + modqxZDCC = TMath::Sqrt((qxZDCC * qxZDCC) + (qyZDCC * qyZDCC)) * TMath::Cos(psiZDCC); + modqyZDCC = TMath::Sqrt((qxZDCC * qxZDCC) + (qyZDCC * qyZDCC)) * TMath::Sin(psiZDCC); + } else { + modqxZDCA = qxZDCA; + modqyZDCA = qyZDCA; + modqxZDCC = qxZDCC; + modqyZDCC = qyZDCC; + } + + for (auto& [track1, track2] : o2::soa::combinations(o2::soa::CombinationsFullIndexPolicy(tracks1, tracks2))) { + if (track1.sign() * track2.sign() > 0) { + continue; + } + if (useGlobalTrack && track1.p() < 1.0 && !(itsResponse.nSigmaITS(track1) > -2.5 && itsResponse.nSigmaITS(track1) < 2.5)) { + continue; + } + if (useGlobalTrack && track2.p() < 1.0 && !(itsResponse.nSigmaITS(track2) > -2.5 && itsResponse.nSigmaITS(track2) < 2.5)) { + continue; + } + if (!selectionTrack(track1) || !selectionTrack(track2)) { + continue; + } + // PID check + if (ispTdepPID && !isTOFOnly && (!selectionPIDpTdependent(track1) || !selectionPIDpTdependent(track2))) { + continue; + } + if (!ispTdepPID && !isTOFOnly && (!selectionPID(track1) || !selectionPID(track2))) { + continue; + } + if (isTOFOnly && (!selectionPID2(track1) || !selectionPID2(track2))) { + continue; + } + if (!selectionPair(track1, track2)) { + continue; + } + if (removefaketrak && isFakeKaon(track1)) { + continue; + } + if (removefaketrak && isFakeKaon(track2)) { + continue; + } + if (track1.sign() > 0 && track2.sign() < 0) { + KaonPlus = ROOT::Math::PxPyPzMVector(track1.px(), track1.py(), track1.pz(), massKa); + KaonMinus = ROOT::Math::PxPyPzMVector(track2.px(), track2.py(), track2.pz(), massKa); + } else if (track1.sign() < 0 && track2.sign() > 0) { + KaonMinus = ROOT::Math::PxPyPzMVector(track1.px(), track1.py(), track1.pz(), massKa); + KaonPlus = ROOT::Math::PxPyPzMVector(track2.px(), track2.py(), track2.pz(), massKa); + } + PhiMesonMother = KaonPlus + KaonMinus; + + if (fillv1) { + auto ux = TMath::Cos(GetPhiInRange(PhiMesonMother.Phi())); + auto uy = TMath::Sin(GetPhiInRange(PhiMesonMother.Phi())); + auto uxQxp = ux * modqxZDCA; + auto uyQyp = uy * modqyZDCA; // correlations of particle and ZDC q vectors + auto uxyQxyp = uxQxp + uyQyp; + auto uxQxt = ux * modqxZDCC; + auto uyQyt = uy * modqyZDCC; + auto uxyQxyt = uxQxt + uyQyt; + auto oddv1 = ux * (modqxZDCA - modqxZDCC) + uy * (modqyZDCA - modqyZDCC); + + histos.fill(HIST("hpoddvscentptetamixopti"), PhiMesonMother.M(), centrality, PhiMesonMother.Pt(), PhiMesonMother.Rapidity(), oddv1); + if (fillLOCC) { + histos.fill(HIST("hpuxyQxypvscentptetamixopti"), PhiMesonMother.M(), centrality, PhiMesonMother.Pt(), PhiMesonMother.Rapidity(), uxyQxyp); + histos.fill(HIST("hpuxyQxytvscentptetamixopti"), PhiMesonMother.M(), centrality, PhiMesonMother.Pt(), PhiMesonMother.Rapidity(), uxyQxyt); + histos.fill(HIST("hpuxvscentptetamixopti"), PhiMesonMother.M(), centrality, PhiMesonMother.Pt(), PhiMesonMother.Rapidity(), ux); + histos.fill(HIST("hpuyvscentptetamixopti"), PhiMesonMother.M(), centrality, PhiMesonMother.Pt(), PhiMesonMother.Rapidity(), uy); + } + } + } + } + } + PROCESS_SWITCH(phipbpb, processMixedEventOptiv1, "Process Mixed event new v1", false); + void processMC(CollisionMCTrueTable::iterator const& /*TrueCollision*/, CollisionMCRecTableCentFT0C const& RecCollisions, TrackMCTrueTable const& GenParticles, FilTrackMCRecTable const& RecTracks) { histos.fill(HIST("hMC"), 0); From 8014bedef80d928d2c5bb36ba771ac27d97468aa Mon Sep 17 00:00:00 2001 From: ypwangg <142303052+ypwangg@users.noreply.github.com> Date: Wed, 18 Jun 2025 19:38:04 +0800 Subject: [PATCH 127/871] [PWGDQ] Fixed a bug in dilepton track track vertexing using KFP (#11668) --- PWGDQ/Core/VarManager.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PWGDQ/Core/VarManager.h b/PWGDQ/Core/VarManager.h index 26d2732dd45..83b8df8906f 100644 --- a/PWGDQ/Core/VarManager.h +++ b/PWGDQ/Core/VarManager.h @@ -5301,7 +5301,7 @@ void VarManager::FillDileptonTrackTrackVertexing(C const& collision, T1 const& l values[VarManager::kPairPt] = KFGeoTwoLeptons.GetPt(); } - KFGeoFourProng.SetConstructMethod(3); + KFGeoFourProng.SetConstructMethod(2); KFGeoFourProng.AddDaughter(KFGeoTwoLeptons); KFGeoFourProng.AddDaughter(trk1KF); KFGeoFourProng.AddDaughter(trk2KF); From a120f19a1bfcd22e5a15a48f3477d48278830b23 Mon Sep 17 00:00:00 2001 From: Mattia Faggin Date: Wed, 18 Jun 2025 16:51:45 +0200 Subject: [PATCH 128/871] [DPG] Split processes with and w/o PID info. (#11672) Co-authored-by: Mattia Faggin --- DPG/Tasks/AOTTrack/qaImpPar.cxx | 100 ++++++++++++++++++++++---------- 1 file changed, 70 insertions(+), 30 deletions(-) diff --git a/DPG/Tasks/AOTTrack/qaImpPar.cxx b/DPG/Tasks/AOTTrack/qaImpPar.cxx index 2ff3ca3761c..45f66123aee 100644 --- a/DPG/Tasks/AOTTrack/qaImpPar.cxx +++ b/DPG/Tasks/AOTTrack/qaImpPar.cxx @@ -10,33 +10,32 @@ // or submit itself to any jurisdiction. /// \author Mattia Faggin , Padova University and INFN -#include - -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "ReconstructionDataFormats/DCA.h" +#include "Common/Core/TrackSelection.h" #include "Common/Core/trackUtilities.h" // for propagation to primary vertex - #include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" #include "Common/DataModel/PIDResponse.h" -#include "DetectorsBase/Propagator.h" -#include "DetectorsBase/GeometryManager.h" -#include "CommonUtils/NameConf.h" -#include "Framework/AnalysisDataModel.h" -#include "Common/Core/TrackSelection.h" -#include "DetectorsVertexing/PVertexer.h" -#include "ReconstructionDataFormats/Vertex.h" +#include "Common/DataModel/TrackSelectionTables.h" + #include "CCDB/BasicCCDBManager.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "Framework/RunningWorkflowInfo.h" #include "CCDB/CcdbApi.h" -#include "DataFormatsCalibration/MeanVertexObject.h" #include "CommonConstants/GeomConstants.h" +#include "CommonUtils/NameConf.h" +#include "DataFormatsCalibration/MeanVertexObject.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "DetectorsBase/GeometryManager.h" +#include "DetectorsBase/Propagator.h" +#include "DetectorsVertexing/PVertexer.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/RunningWorkflowInfo.h" +#include "ReconstructionDataFormats/DCA.h" +#include "ReconstructionDataFormats/Vertex.h" #include -#include #include +#include +#include using namespace o2::framework; using namespace o2::framework::expressions; @@ -153,28 +152,47 @@ struct QaImpactPar { /// Data using CollisionRecoTable = o2::soa::Join; using TrackTable = o2::soa::Join; - using TrackFullTable = o2::soa::Join; + using TrackFullTable = o2::soa::Join; using TrackTableIU = o2::soa::Join; + /// + /// @brief process function in data, without the usage of PID info void processData(o2::soa::Filtered::iterator const& collision, const TrackTable& tracksUnfiltered, - const o2::soa::Filtered& tracks, + const o2::soa::Filtered& tracks, const TrackTableIU& tracksIU, o2::aod::BCsWithTimestamps const&) { /// here call the template processReco function auto bc = collision.bc_as(); - processReco(collision, tracksUnfiltered, tracks, tracksIU, 0, bc); + processReco(collision, tracksUnfiltered, tracks, tracksIU, 0, bc); } PROCESS_SWITCH(QaImpactPar, processData, "process data", true); + /// + /// @brief process function in data, with the possibility to use PID info + void processDataWithPid(o2::soa::Filtered::iterator const& collision, + const TrackTable& tracksUnfiltered, + const o2::soa::Filtered& tracks, + const TrackTableIU& tracksIU, + o2::aod::BCsWithTimestamps const&) + { + /// here call the template processReco function + auto bc = collision.bc_as(); + processReco(collision, tracksUnfiltered, tracks, tracksIU, 0, bc); + } + PROCESS_SWITCH(QaImpactPar, processDataWithPid, "process data with PID", false); /// MC using CollisionMCRecoTable = o2::soa::Join; + using TrackMCFullTableNoPid = o2::soa::Join; using TrackMCFullTable = o2::soa::Join; + /// + /// @brief process function in MC, without the usage of PID info void processMC(o2::soa::Filtered::iterator const& collision, TrackTable const& tracksUnfiltered, - o2::soa::Filtered const& tracks, + o2::soa::Filtered const& tracks, const TrackTableIU& tracksIU, const o2::aod::McParticles& mcParticles, const o2::aod::McCollisions&, @@ -182,9 +200,24 @@ struct QaImpactPar { { /// here call the template processReco function auto bc = collision.bc_as(); - processReco(collision, tracksUnfiltered, tracks, tracksIU, mcParticles, bc); + processReco(collision, tracksUnfiltered, tracks, tracksIU, mcParticles, bc); } PROCESS_SWITCH(QaImpactPar, processMC, "process MC", false); + /// + /// @brief process function in MC,with the possibility to use PID info + void processMCWithPid(o2::soa::Filtered::iterator const& collision, + TrackTable const& tracksUnfiltered, + o2::soa::Filtered const& tracks, + const TrackTableIU& tracksIU, + const o2::aod::McParticles& mcParticles, + const o2::aod::McCollisions&, + o2::aod::BCsWithTimestamps const&) + { + /// here call the template processReco function + auto bc = collision.bc_as(); + processReco(collision, tracksUnfiltered, tracks, tracksIU, mcParticles, bc); + } + PROCESS_SWITCH(QaImpactPar, processMCWithPid, "process MC with PID", false); /// core template process function /// template @@ -197,6 +230,11 @@ struct QaImpactPar { /// init function - declare and define histograms void init(InitContext&) { + std::array processes = {doprocessData, doprocessDataWithPid, doprocessMC, doprocessMCWithPid}; + if (std::accumulate(processes.begin(), processes.end(), 0) != 1) { + LOGP(fatal, "One and only one process function for collision study must be enabled at a time."); + } + // Primary vertex const AxisSpec collisionXAxis{100, -20.f, 20.f, "X (cm)"}; const AxisSpec collisionYAxis{100, -20.f, 20.f, "Y (cm)"}; @@ -367,7 +405,7 @@ struct QaImpactPar { } /// core template process function - template + template void processReco(const C& collision, const TrackTable& unfilteredTracks, const T& tracks, const TrackTableIU& tracksIU, const T_MC& /*mcParticles*/, o2::aod::BCsWithTimestamps::iterator const& bc) @@ -596,12 +634,14 @@ struct QaImpactPar { pt = track.pt(); p = track.p(); - tpcNSigmaPion = track.tpcNSigmaPi(); - tpcNSigmaKaon = track.tpcNSigmaKa(); - tpcNSigmaProton = track.tpcNSigmaPr(); - tofNSigmaPion = track.tofNSigmaPi(); - tofNSigmaKaon = track.tofNSigmaKa(); - tofNSigmaProton = track.tofNSigmaPr(); + if constexpr (USE_PID) { + tpcNSigmaPion = track.tpcNSigmaPi(); + tpcNSigmaKaon = track.tpcNSigmaKa(); + tpcNSigmaProton = track.tpcNSigmaPr(); + tofNSigmaPion = track.tofNSigmaPi(); + tofNSigmaKaon = track.tofNSigmaKa(); + tofNSigmaProton = track.tofNSigmaPr(); + } histograms.fill(HIST("Reco/pt"), pt); histograms.fill(HIST("Reco/hNSigmaTPCPion"), pt, tpcNSigmaPion); From 6d87f15c4c7e635c9ac4151b61730a2f13afa4cf Mon Sep 17 00:00:00 2001 From: Fabrizio Date: Wed, 18 Jun 2025 17:05:15 +0200 Subject: [PATCH 129/871] [Common] Add missing metadata keys (#11669) --- Common/Core/MetadataHelper.cxx | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Common/Core/MetadataHelper.cxx b/Common/Core/MetadataHelper.cxx index bdcb7e2e8a4..9df370449e6 100644 --- a/Common/Core/MetadataHelper.cxx +++ b/Common/Core/MetadataHelper.cxx @@ -22,11 +22,14 @@ MetadataHelper::MetadataHelper() { - const std::array keyList = {"DataType", + const std::array keyList = {"DataType", "RecoPassName", "Run", "AnchorPassName", - "AnchorProduction"}; + "AnchorProduction", + "ROOTVersion", + "LPMProductionTag", + "O2Version"}; for (const auto& key : keyList) { mMetadata[key] = "undefined"; } From 8f1266ac79a1a218b75779770e17ee8b29ee8947 Mon Sep 17 00:00:00 2001 From: Paola Vargas Torres <88360333+PaolaVT@users.noreply.github.com> Date: Wed, 18 Jun 2025 09:30:37 -0600 Subject: [PATCH 130/871] [PWGLF] Two histograms were added (#11667) --- PWGMM/UE/Tasks/dedxAnalysis.cxx | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/PWGMM/UE/Tasks/dedxAnalysis.cxx b/PWGMM/UE/Tasks/dedxAnalysis.cxx index 34999be4f7e..21a90b0dd50 100644 --- a/PWGMM/UE/Tasks/dedxAnalysis.cxx +++ b/PWGMM/UE/Tasks/dedxAnalysis.cxx @@ -14,20 +14,23 @@ /// \file dedxAnalysis.cxx /// \brief Analysis to do PID +#include "PWGLF/DataModel/LFStrangenessTables.h" + #include "Common/Core/RecoDecay.h" #include "Common/Core/TrackSelection.h" +#include "Common/Core/TrackSelectionDefaults.h" #include "Common/Core/trackUtilities.h" #include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/PIDResponse.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "Common/DataModel/Multiplicity.h" + #include "Framework/ASoAHelpers.h" #include "Framework/AnalysisDataModel.h" #include "Framework/AnalysisTask.h" #include "Framework/runDataProcessing.h" -#include "PWGLF/DataModel/LFStrangenessTables.h" #include "ReconstructionDataFormats/Track.h" -#include "Common/Core/TrackSelectionDefaults.h" + #include "TF1.h" using namespace o2; @@ -59,7 +62,7 @@ struct DedxAnalysis { float pionTofCut = 1.0; float invMassCut = 0.01; float invMassCutGamma = 0.0015; - float magField = 1.0; + float magField = 1; float pTcut = 2.0; // Configurable Parameters @@ -96,8 +99,8 @@ struct DedxAnalysis { "Minimum Mass Gamma"}; Configurable maxMassGamma{"maxMassGamma", 0.002022f, "Maximum Mass Gamma"}; - Configurable calibrationMode{"calibrationMode", false, "calibration mode"}; - Configurable additionalCuts{"additionalCuts", false, "additional cuts"}; + Configurable calibrationMode{"calibrationMode", true, "calibration mode"}; + Configurable additionalCuts{"additionalCuts", true, "additional cuts"}; // Histograms names static constexpr std::string_view kDedxvsMomentumPos[kParticlesType] = {"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 kDedxvsMomentumNeg[kParticlesType] = {"dEdx_vs_Momentum_all_Neg", "dEdx_vs_Momentum_Pi_v0_Neg", "dEdx_vs_Momentum_Pr_v0_Neg", "dEdx_vs_Momentum_El_v0_Neg"}; @@ -213,9 +216,14 @@ struct DedxAnalysis { // phi cut registryDeDx.add( - "hpt_vs_phi", "phi cut", HistType::kTH2F, - {{ptAxis}, {100, 0.0, 6.4, "#phi"}}); + "hpt_vs_phi_Ncl_After", "phi cut", HistType::kTH3F, + {{ptAxis}, {100, 0.0, 0.4, "#varphi^{'}"}, {100, 0, 160, "N_{cl}"}}); + + registryDeDx.add( + "hpt_vs_phi_Ncl_Before", "phi cut", HistType::kTH3F, + {{ptAxis}, {100, 0.0, 0.4, "#varphi^{'}"}, {100, 0, 160, "N_{cl}"}}); + // beta plot registryDeDx.add( "hbeta_vs_p_Neg", "beta", HistType::kTH2F, {{pAxis}, {100, 0.0, 1.1, "#beta"}}); @@ -223,6 +231,7 @@ struct DedxAnalysis { registryDeDx.add( "hbeta_vs_p_Pos", "beta", HistType::kTH2F, {{pAxis}, {100, 0.0, 1.1, "#beta"}}); + // Event Counter registryDeDx.add("histRecVtxZData", "collision z position", HistType::kTH1F, {{100, -20.0, +20.0, "z_{vtx} (cm)"}}); @@ -396,11 +405,12 @@ struct DedxAnalysis { float pt = trk.pt(); float phi = trk.phi(); int charge = trk.sign(); + auto nTPCCl = trk.tpcNClsFindable() - trk.tpcNClsFindableMinusFound(); if (pt < pTcut) return true; - if (magField < 0.) // for negatve polarity field + if (magField < 0) // for negatve polarity field phi = o2::constants::math::TwoPI - phi; if (charge < 0) // for negatve charge phi = o2::constants::math::TwoPI - phi; @@ -409,10 +419,12 @@ struct DedxAnalysis { phi += o2::constants::math::PI / 18.0f; phi = std::fmod(phi, o2::constants::math::PI / 9.0f); + registryDeDx.fill(HIST("hpt_vs_phi_Ncl_Before"), pt, phi, nTPCCl); + if (phi < fphiCutHigh.Eval(pt) && phi > fphiCutLow.Eval(pt)) return false; // reject track - registryDeDx.fill(HIST("hpt_vs_phi"), pt, phi); + registryDeDx.fill(HIST("hpt_vs_phi_Ncl_After"), pt, phi, nTPCCl); return true; } From 0df4bc3dcc4a46445dc8aad2d38a6e2af042a698 Mon Sep 17 00:00:00 2001 From: Daiki Sekihata Date: Wed, 18 Jun 2025 19:12:20 +0200 Subject: [PATCH 131/871] [PWGEM/Dilepton] fix chi2 in global muon (#11673) --- PWGEM/Dilepton/Core/SingleTrackQC.h | 17 ++++++++--------- PWGEM/Dilepton/Core/SingleTrackQCMC.h | 18 ++++++++---------- .../TableProducer/skimmerPrimaryMuon.cxx | 10 +++++----- 3 files changed, 21 insertions(+), 24 deletions(-) diff --git a/PWGEM/Dilepton/Core/SingleTrackQC.h b/PWGEM/Dilepton/Core/SingleTrackQC.h index f97890e68e5..799e276d790 100644 --- a/PWGEM/Dilepton/Core/SingleTrackQC.h +++ b/PWGEM/Dilepton/Core/SingleTrackQC.h @@ -83,7 +83,9 @@ struct SingleTrackQC { Configurable cfgApplyWeightTTCA{"cfgApplyWeightTTCA", false, "flag to apply weighting by 1/N"}; ConfigurableAxis ConfPtlBins{"ConfPtlBins", {VARIABLE_WIDTH, 0.00, 0.05, 0.10, 0.15, 0.20, 0.30, 0.40, 0.50, 0.60, 0.70, 0.80, 0.90, 1.00, 1.10, 1.20, 1.30, 1.40, 1.50, 1.60, 1.70, 1.80, 1.90, 2.00, 2.50, 3.00, 3.50, 4.00, 4.50, 5.00, 6.00, 7.00, 8.00, 9.00, 10.00}, "pTl bins for output histograms"}; - ConfigurableAxis ConfDCABins{"ConfDCABins", {VARIABLE_WIDTH, -10.0, -9.0, -8.0, -7.0, -6.0, -5.0, -4.5, -4.0, -3.5, -3.0, -2.5, -2.0, -1.9, -1.8, -1.7, -1.6, -1.5, -1.4, -1.3, -1.2, -1.1, -1.0, -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, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0}, "DCA bins for output histograms"}; + ConfigurableAxis ConfDCA3DBins{"ConfDCA3DBins", {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.5, 3.0, 3.5, 4.0, 4.5, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0}, "DCA3d bins in sigma for output histograms"}; + ConfigurableAxis ConfDCAXYBins{"ConfDCAXYBins", {VARIABLE_WIDTH, -10.0, -9.0, -8.0, -7.0, -6.0, -5.0, -4.5, -4.0, -3.5, -3.0, -2.5, -2.0, -1.9, -1.8, -1.7, -1.6, -1.5, -1.4, -1.3, -1.2, -1.1, -1.0, -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, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0}, "DCAxy bins in sigma for output histograms"}; + ConfigurableAxis ConfDCAZBins{"ConfDCAZBins", {VARIABLE_WIDTH, -10.0, -9.0, -8.0, -7.0, -6.0, -5.0, -4.5, -4.0, -3.5, -3.0, -2.5, -2.0, -1.9, -1.8, -1.7, -1.6, -1.5, -1.4, -1.3, -1.2, -1.1, -1.0, -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, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0}, "DCAz bins in sigma for output histograms"}; EMEventCut fEMEventCut; struct : ConfigurableGroup { @@ -227,17 +229,14 @@ struct SingleTrackQC { const AxisSpec axis_pt{ConfPtlBins, "p_{T,e} (GeV/c)"}; const AxisSpec axis_eta{20, -1.0, +1.0, "#eta_{e}"}; const AxisSpec axis_phi{36, 0.0, 2 * M_PI, "#varphi_{e} (rad.)"}; - std::string dca3D_axis_title = "DCA_{e}^{3D} (#sigma)"; - std::string dcaXY_axis_title = "DCA_{e}^{XY} (#sigma)"; - std::string dcaZ_axis_title = "DCA_{e}^{Z} (#sigma)"; - const AxisSpec axis_dca3D{ConfDCABins, dca3D_axis_title}; - const AxisSpec axis_dcaXY{ConfDCABins, dcaXY_axis_title}; - const AxisSpec axis_dcaZ{ConfDCABins, dcaZ_axis_title}; + const AxisSpec axis_dca3D{ConfDCA3DBins, "DCA_{e}^{3D} (#sigma)"}; + const AxisSpec axis_dcaXY{ConfDCAXYBins, "DCA_{e}^{XY} (#sigma)"}; + const AxisSpec axis_dcaZ{ConfDCAZBins, "DCA_{e}^{Z} (#sigma)"}; // track info fRegistry.add("Track/positive/hs", "rec. single electron", kTHnSparseD, {axis_pt, axis_eta, axis_phi, axis_dca3D, axis_dcaXY, axis_dcaZ}, true); fRegistry.add("Track/positive/hQoverPt", "q/pT;q/p_{T} (GeV/c)^{-1}", kTH1F, {{2000, -5, 5}}, false); - fRegistry.add("Track/positive/hDCAxyz", "DCA xy vs. z;DCA_{xy} (cm);DCA_{z} (cm)", kTH2F, {{200, -1.0f, 1.0f}, {700, -3.5f, 3.5f}}, false); + fRegistry.add("Track/positive/hDCAxyz", "DCA xy vs. z;DCA_{xy} (cm);DCA_{z} (cm)", kTH2F, {{200, -1.0f, 1.0f}, {200, -1.f, 1.f}}, false); fRegistry.add("Track/positive/hDCAxyzSigma", "DCA xy vs. z;DCA_{xy} (#sigma);DCA_{z} (#sigma)", kTH2F, {{400, -20.0f, 20.0f}, {400, -20.0f, 20.0f}}, false); fRegistry.add("Track/positive/hDCAxyRes_Pt", "DCA_{xy} resolution vs. pT;p_{T} (GeV/c);DCA_{xy} resolution (#mum)", kTH2F, {{200, 0, 10}, {500, 0., 500}}, false); fRegistry.add("Track/positive/hDCAzRes_Pt", "DCA_{z} resolution vs. pT;p_{T} (GeV/c);DCA_{z} resolution (#mum)", kTH2F, {{200, 0, 10}, {500, 0., 400}}, false); @@ -282,7 +281,7 @@ struct SingleTrackQC { const AxisSpec axis_pt{ConfPtlBins, "p_{T,#mu} (GeV/c)"}; const AxisSpec axis_eta{50, -6, -1, "#eta_{#mu}"}; const AxisSpec axis_phi{36, 0, 2 * M_PI, "#varphi_{#mu} (rad.)"}; - const AxisSpec axis_dca{ConfDCABins, "DCA_{#mu}^{XY} (#sigma)"}; + const AxisSpec axis_dca{ConfDCAXYBins, "DCA_{#mu}^{XY} (#sigma)"}; // track info fRegistry.add("Track/positive/hs", "rec. single muon", kTHnSparseD, {axis_pt, axis_eta, axis_phi, axis_dca}, true); diff --git a/PWGEM/Dilepton/Core/SingleTrackQCMC.h b/PWGEM/Dilepton/Core/SingleTrackQCMC.h index c452483b3ea..e817e1b30fd 100644 --- a/PWGEM/Dilepton/Core/SingleTrackQCMC.h +++ b/PWGEM/Dilepton/Core/SingleTrackQCMC.h @@ -91,7 +91,9 @@ struct SingleTrackQCMC { Configurable cfgRequireTrueAssociation{"cfgRequireTrueAssociation", false, "flag to require true mc collision association"}; ConfigurableAxis ConfPtlBins{"ConfPtlBins", {VARIABLE_WIDTH, 0.00, 0.05, 0.10, 0.15, 0.20, 0.30, 0.40, 0.50, 0.60, 0.70, 0.80, 0.90, 1.00, 1.10, 1.20, 1.30, 1.40, 1.50, 1.60, 1.70, 1.80, 1.90, 2.00, 2.50, 3.00, 3.50, 4.00, 4.50, 5.00, 6.00, 7.00, 8.00, 9.00, 10.00}, "pTl bins for output histograms"}; - ConfigurableAxis ConfDCABins{"ConfDCABins", {VARIABLE_WIDTH, -10.0, -9.0, -8.0, -7.0, -6.0, -5.0, -4.5, -4.0, -3.5, -3.0, -2.5, -2.0, -1.9, -1.8, -1.7, -1.6, -1.5, -1.4, -1.3, -1.2, -1.1, -1.0, -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, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0}, "DCA bins for output histograms"}; + ConfigurableAxis ConfDCA3DBins{"ConfDCA3DBins", {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.5, 3.0, 3.5, 4.0, 4.5, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0}, "DCA3d bins in sigma for output histograms"}; + ConfigurableAxis ConfDCAXYBins{"ConfDCAXYBins", {VARIABLE_WIDTH, -10.0, -9.0, -8.0, -7.0, -6.0, -5.0, -4.5, -4.0, -3.5, -3.0, -2.5, -2.0, -1.9, -1.8, -1.7, -1.6, -1.5, -1.4, -1.3, -1.2, -1.1, -1.0, -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, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0}, "DCAxy bins in sigma for output histograms"}; + ConfigurableAxis ConfDCAZBins{"ConfDCAZBins", {VARIABLE_WIDTH, -10.0, -9.0, -8.0, -7.0, -6.0, -5.0, -4.5, -4.0, -3.5, -3.0, -2.5, -2.0, -1.9, -1.8, -1.7, -1.6, -1.5, -1.4, -1.3, -1.2, -1.1, -1.0, -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, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0}, "DCAz bins in sigma for output histograms"}; EMEventCut fEMEventCut; struct : ConfigurableGroup { @@ -246,13 +248,9 @@ struct SingleTrackQCMC { const AxisSpec axis_eta{20, -1.0, +1.0, "#eta_{e}"}; const AxisSpec axis_phi{36, 0.0, 2 * M_PI, "#varphi_{e} (rad.)"}; const AxisSpec axis_charge_gen{3, -1.5, +1.5, "true charge"}; - std::string dca3D_axis_title = "DCA_{e}^{3D} (#sigma)"; - std::string dcaXY_axis_title = "DCA_{e}^{XY} (#sigma)"; - std::string dcaZ_axis_title = "DCA_{e}^{Z} (#sigma)"; - - const AxisSpec axis_dca3D{ConfDCABins, dca3D_axis_title}; - const AxisSpec axis_dcaXY{ConfDCABins, dcaXY_axis_title}; - const AxisSpec axis_dcaZ{ConfDCABins, dcaZ_axis_title}; + const AxisSpec axis_dca3D{ConfDCA3DBins, "DCA_{e}^{3D} (#sigma)"}; + const AxisSpec axis_dcaXY{ConfDCAXYBins, "DCA_{e}^{XY} (#sigma)"}; + const AxisSpec axis_dcaZ{ConfDCAZBins, "DCA_{e}^{Z} (#sigma)"}; // generated info fRegistry.add("Generated/lf/hs", "gen. single electron", kTHnSparseD, {axis_pt, axis_eta, axis_phi, axis_charge_gen}, true); @@ -269,7 +267,7 @@ struct SingleTrackQCMC { fRegistry.add("Track/lf/positive/hs", "rec. single electron", kTHnSparseD, {axis_pt, axis_eta, axis_phi, axis_dca3D, axis_dcaXY, axis_dcaZ, axis_charge_gen}, true); if (cfgFillQA) { fRegistry.add("Track/lf/positive/hQoverPt", "q/pT;q/p_{T} (GeV/c)^{-1}", kTH1F, {{400, -20, 20}}, false); - fRegistry.add("Track/lf/positive/hDCAxyz", "DCA xy vs. z;DCA_{xy} (cm);DCA_{z} (cm)", kTH2F, {{200, -1.0f, 1.0f}, {700, -3.5f, 3.5f}}, false); + fRegistry.add("Track/lf/positive/hDCAxyz", "DCA xy vs. z;DCA_{xy} (cm);DCA_{z} (cm)", kTH2F, {{200, -1.0f, 1.0f}, {200, -1.f, 1.f}}, false); fRegistry.add("Track/lf/positive/hDCAxyzSigma", "DCA xy vs. z;DCA_{xy} (#sigma);DCA_{z} (#sigma)", kTH2F, {{400, -20.0f, 20.0f}, {400, -20.0f, 20.0f}}, false); fRegistry.add("Track/lf/positive/hDCAxyRes_Pt", "DCA_{xy} resolution vs. pT;p_{T} (GeV/c);DCA_{xy} resolution (#mum)", kTH2F, {{200, 0, 10}, {500, 0., 500}}, false); fRegistry.add("Track/lf/positive/hDCAzRes_Pt", "DCA_{z} resolution vs. pT;p_{T} (GeV/c);DCA_{z} resolution (#mum)", kTH2F, {{200, 0, 10}, {500, 0., 500}}, false); @@ -327,7 +325,7 @@ struct SingleTrackQCMC { const AxisSpec axis_pt{ConfPtlBins, "p_{T,#mu} (GeV/c)"}; const AxisSpec axis_eta{50, -6, -1, "#eta_{#mu}"}; const AxisSpec axis_phi{36, 0.0, 2 * M_PI, "#varphi_{#mu} (rad.)"}; - const AxisSpec axis_dca{ConfDCABins, "DCA_{#mu}^{XY} (#sigma)"}; + const AxisSpec axis_dca{ConfDCAXYBins, "DCA_{#mu}^{XY} (#sigma)"}; const AxisSpec axis_charge_gen{3, -1.5, +1.5, "true charge"}; // generated info diff --git a/PWGEM/Dilepton/TableProducer/skimmerPrimaryMuon.cxx b/PWGEM/Dilepton/TableProducer/skimmerPrimaryMuon.cxx index 47ba2a3c4ea..4d66821e2b6 100644 --- a/PWGEM/Dilepton/TableProducer/skimmerPrimaryMuon.cxx +++ b/PWGEM/Dilepton/TableProducer/skimmerPrimaryMuon.cxx @@ -164,7 +164,7 @@ struct skimmerPrimaryMuon { fRegistry.add("MCHMID/hDCAxyResolutionvsPt", "DCA_{xy} vs. p_{T};p_{T} (GeV/c);DCA_{y} resolution (#mum);", kTH2F, {{100, 0, 10.f}, {500, 0, 5e+5}}, false); } - bool isSelected(const float pt, const float eta, const float rAtAbsorberEnd, const float pDCA, const float chi2, const uint8_t trackType, const float dcaXY) + bool isSelected(const float pt, const float eta, const float rAtAbsorberEnd, const float pDCA, const float chi2_per_ndf, const uint8_t trackType, const float dcaXY) { if (pt < minPt || maxPt < pt) { return false; @@ -183,7 +183,7 @@ struct skimmerPrimaryMuon { if (maxDCAxy < dcaXY) { return false; } - if (chi2 < 0.f || maxChi2GL < chi2) { + if (chi2_per_ndf < 0.f || maxChi2GL < chi2_per_ndf) { return false; } if (rAtAbsorberEnd < minRabsGL || maxRabs < rAtAbsorberEnd) { @@ -193,7 +193,7 @@ struct skimmerPrimaryMuon { if (eta < minEtaSA || maxEtaSA < eta) { return false; } - if (chi2 < 0.f || maxChi2SA < chi2) { + if (chi2_per_ndf < 0.f || maxChi2SA < chi2_per_ndf) { return false; } } else { @@ -252,7 +252,7 @@ struct skimmerPrimaryMuon { // float tgl = fwdtrack.tgl(); float chi2mft = 0.f; uint64_t mftClusterSizesAndTrackFlags = 0; - int ndf_mchmft = 999; + int ndf_mchmft = 1; if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) { const auto& mchtrack = fwdtrack.template matchMCHTrack_as(); // MCH-MID @@ -293,7 +293,7 @@ struct skimmerPrimaryMuon { return; } - if (!isSelected(pt, eta, rAtAbsorberEnd, pDCA, fwdtrack.chi2(), fwdtrack.trackType(), dcaXY)) { + if (!isSelected(pt, eta, rAtAbsorberEnd, pDCA, fwdtrack.chi2() / ndf_mchmft, fwdtrack.trackType(), dcaXY)) { return; } From 6cddd4f23a7923b0ce4df18ea9d47aecc4e0253f Mon Sep 17 00:00:00 2001 From: Jesper Gumprecht <113693781+jesgum@users.noreply.github.com> Date: Wed, 18 Jun 2025 19:47:29 +0200 Subject: [PATCH 132/871] [ALICE3] Need double precision for regularization (#11671) --- ALICE3/Core/FastTracker.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ALICE3/Core/FastTracker.cxx b/ALICE3/Core/FastTracker.cxx index fe89fcd80fd..72ead40e12d 100644 --- a/ALICE3/Core/FastTracker.cxx +++ b/ALICE3/Core/FastTracker.cxx @@ -516,7 +516,7 @@ int FastTracker::FastTrack(o2::track::TrackParCov inputTrack, o2::track::TrackPa for (int ii = 0; ii < o2::track::kCovMatSize; ii++) covMat[ii] = outputTrack.getCov()[ii]; TMatrixDSym m(5); - float fcovm[5][5]; + double fcovm[5][5]; // double precision is needed for regularisation for (int ii = 0, k = 0; ii < 5; ++ii) { for (int j = 0; j < ii + 1; ++j, ++k) { From e80dcd5912a5534f495b6fee00c8162defd7b33d Mon Sep 17 00:00:00 2001 From: Francesca Ercolessi Date: Wed, 18 Jun 2025 19:58:04 +0200 Subject: [PATCH 133/871] [PWGLF] deuteron-proton correlation: add config axis for phi (#11674) --- PWGLF/Tasks/Nuspex/hadronnucleicorrelation.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PWGLF/Tasks/Nuspex/hadronnucleicorrelation.cxx b/PWGLF/Tasks/Nuspex/hadronnucleicorrelation.cxx index f90d12d75b1..d851ba206c5 100644 --- a/PWGLF/Tasks/Nuspex/hadronnucleicorrelation.cxx +++ b/PWGLF/Tasks/Nuspex/hadronnucleicorrelation.cxx @@ -107,6 +107,7 @@ struct hadronnucleicorrelation { Configurable> pTBins{"pTBins", {0.6f, 1.0f, 1.2f, 2.f}, "p_{T} bins"}; ConfigurableAxis AxisNSigma{"AxisNSigma", {35, -7.f, 7.f}, "n#sigma"}; + ConfigurableAxis DeltaPhiAxis = {"DeltaPhiAxis", {46, -1 * o2::constants::math::PIHalf, 3 * o2::constants::math::PIHalf}, "#Delta#phi (rad)"}; using FilteredCollisions = soa::Filtered; using SimCollisions = aod::McCollisions; @@ -206,7 +207,6 @@ struct hadronnucleicorrelation { AxisSpec pTAxis_small = {100, -5.f, 5.f, "p_{T} GeV/c"}; AxisSpec DeltaEtaAxis = {100, -1.5, 1.5, "#Delta#eta"}; - AxisSpec DeltaPhiAxis = {60, -1 * o2::constants::math::PIHalf, 3 * o2::constants::math::PIHalf, "#Delta#phi (rad)"}; registry.add("hNEvents", "hNEvents", {HistType::kTH1D, {{7, 0.f, 7.f}}}); registry.get(HIST("hNEvents"))->GetXaxis()->SetBinLabel(1, "Selected"); From d193178073cf46df58d7af56d01dc9b787d1b55b Mon Sep 17 00:00:00 2001 From: Zhengqing Wang Date: Thu, 19 Jun 2025 02:42:28 +0800 Subject: [PATCH 134/871] [PWGCF] updates on ESETask (#11675) --- PWGCF/Flow/Tasks/flowEsePHe3.cxx | 133 +++++++++++++++++++++++++------ 1 file changed, 109 insertions(+), 24 deletions(-) diff --git a/PWGCF/Flow/Tasks/flowEsePHe3.cxx b/PWGCF/Flow/Tasks/flowEsePHe3.cxx index 624043a2d31..1a68cbdbd93 100644 --- a/PWGCF/Flow/Tasks/flowEsePHe3.cxx +++ b/PWGCF/Flow/Tasks/flowEsePHe3.cxx @@ -191,12 +191,54 @@ constexpr double ITSnSigmaCutDefault[5][2]{ {-3., 3.}, {-3., 3.}, {-3., 3.}}; -constexpr double PtPreselection[5][2]{ +constexpr double POverZPreselection[5][2]{ {0.15, 99.}, {0.15, 99.}, {0.15, 99.}, {0.15, 99.}, {0.15, 99.}}; +constexpr double EtaPreselection[5][2]{ + {0.9}, + {0.9}, + {0.9}, + {0.8}, + {0.9}}; +constexpr double TPCNclsPreselection[5][2]{ + {50, 160}, + {50, 160}, + {50, 160}, + {100, 160}, + {50, 160}}; +constexpr double ITSNclsPreselection[5][2]{ + {5, 7}, + {5, 7}, + {5, 7}, + {5, 7}, + {5, 7}}; +constexpr double TPCChi2Preselection[5][2]{ + {0, 10}, + {0, 10}, + {0, 10}, + {0.5, 4}, + {0, 10}}; +constexpr double ITSChi2Preselection[5][2]{ + {0, 36}, + {0, 36}, + {0, 36}, + {0, 36}, + {0, 36}}; +constexpr double DCAxyPreselection[5][2]{ + {1}, + {1}, + {1}, + {0.1}, + {1}}; +constexpr double DCAzPreselection[5][2]{ + {5}, + {5}, + {5}, + {1}, + {5}}; static const std::vector names{"proton", "deuteron", "triton", "He3", "alpha"}; static const std::vector chargeLabelNames{"Positive", "Negative"}; static const std::vector betheBlochParNames{"p0", "p1", "p2", "p3", "p4", "resolution"}; @@ -208,7 +250,14 @@ static const std::vector openEventSelConfigNames{"Open related even static const std::vector openTrackSelConfigNames{"Open track selection from TrackSelection table"}; static const std::vector pidTPCnSigmaNames{"n#sigma_{TPC} Low", "n#sigma_{TPC} High"}; static const std::vector pidITSnSigmaNames{"n#sigma_{ITS} Low", "n#sigma_{ITS} High"}; -static const std::vector pidPtNames{"p_{T} Low", "p_{T} High"}; +static const std::vector pidPOverZNames{"p/z Low", "p/z High"}; +static const std::vector pidEtaNames{"Abs Eta Max"}; +static const std::vector pidTPCNclsNames{"TPCNcls Low", "TPCNcls High"}; +static const std::vector pidITSNclsNames{"ITSNcls Low", "ITSNcls High"}; +static const std::vector pidTPCChi2Names{"TPCChi2 Low", "TPCChi2 High"}; +static const std::vector pidITSChi2Names{"ITSChi2 Low", "ITSChi2 High"}; +static const std::vector pidDCAxyNames{"Abs DCAxy Max"}; +static const std::vector pidDCAzNames{"Abs DCAz Max"}; std::vector eseCandidates; // Tar ptr std::shared_ptr hPIDQATar1D[12]; @@ -238,7 +287,7 @@ struct FlowEsePHe3 { Configurable cfgTarName{"cfgTarName", "kHe3", "Name of the v2 particle: kProton, kDeuteron, kTriton, kHe3, kAlpha"}; Configurable cfgRefName{"cfgRefName", "kProton", "Name of the q2 reference particle: kProton, kDeuteron, kTriton, kHe3, kAlpha"}; // total control config - Configurable cfgOpenAllowCrossTrack{"cfgOpenAllowCrossTrack", false, "Allow one track to be identified as different kind of PID particles"}; + Configurable cfgOpenAllowCrossTrack{"cfgOpenAllowCrossTrack", true, "Allow one track to be identified as different kind of PID particles"}; Configurable cfgOpenFullEventQA{"cfgOpenFullEventQA", true, "Open full QA plots for event QA"}; Configurable cfgOpenPIDQA{"cfgOpenPIDQA", true, "Open PID QA plots"}; Configurable cfgOpenv2{"cfgOpenv2", true, "Open v2(EP)and q calculation for Proton and He3"}; @@ -262,7 +311,7 @@ struct FlowEsePHe3 { Configurable> cfgOpenTrackSel{"cfgOpenTrackSel", {ese_parameters::OpenTrackSel[0], 7, 1, ese_parameters::openTrackSelNames, ese_parameters::openTrackSelConfigNames}, "Track selection switch configuration"}; Configurable cfgMinPtPID{"cfgMinPtPID", 0.15, "Minimum track #P_{t} for PID"}; Configurable cfgMaxPtPID{"cfgMaxPtPID", 99.9, "Maximum track #P_{t} for PID"}; - Configurable cfgMaxEtaPID{"cfgMaxEtaPID", 0.8, "Maximum track #eta for PID"}; + Configurable cfgMaxEtaPID{"cfgMaxEtaPID", 0.9, "Maximum track #eta for PID"}; Configurable cfgMinTPCChi2NCl{"cfgMinTPCChi2NCl", 0, "Minimum chi2 per cluster TPC for PID if not use costom track cuts"}; Configurable cfgMinChi2NClITS{"cfgMinChi2NClITS", 0, "Minimum chi2 per cluster ITS for PID if not use costom track cuts"}; Configurable cfgMaxTPCChi2NCl{"cfgMaxTPCChi2NCl", 4, "Maximum chi2 per cluster TPC for PID if not use costom track cuts"}; @@ -275,10 +324,18 @@ struct FlowEsePHe3 { Configurable cfgMaxDCAz{"cfgMaxDCAz", 2, "Maxium DCAz for standard PID tracking"}; Configurable cfgPtMaxforTPCOnlyPIDPrton{"cfgPtMaxforTPCOnlyPIDPrton", 0.4, "Maxmium track pt for TPC only PID, at RMS PID mode for proton"}; // PID configs - Configurable> cfgPtPreselection{"cfgPtPreselection", {ese_parameters::PtPreselection[0], 5, 2, ese_parameters::names, ese_parameters::pidPtNames}, "Pt preselection for light nuclei"}; + Configurable cfgOpenITSPreselection{"cfgOpenITSPreselection", false, "Use nSigma ITS preselection for light nuclei"}; + Configurable> cfgPOverZPreselection{"cfgPOverZPreselection", {ese_parameters::POverZPreselection[0], 5, 2, ese_parameters::names, ese_parameters::pidPOverZNames}, "P/Z preselection for light nuclei"}; + Configurable> cfgEtaPreselection{"cfgEtaPreselection", {ese_parameters::EtaPreselection[0], 5, 1, ese_parameters::names, ese_parameters::pidEtaNames}, "Eta preselection for light nuclei"}; + Configurable> cfgTPCNclsPreselection{"cfgTPCNclsPreselection", {ese_parameters::TPCNclsPreselection[0], 5, 2, ese_parameters::names, ese_parameters::pidTPCNclsNames}, "TPCNcls preselection for light nuclei"}; + Configurable> cfgITSNclsPreselection{"cfgITSNclsPreselection", {ese_parameters::ITSNclsPreselection[0], 5, 2, ese_parameters::names, ese_parameters::pidITSNclsNames}, "ITSNcls preselection for light nuclei"}; + Configurable> cfgTPCChi2Preselection{"cfgTPCChi2Preselection", {ese_parameters::TPCChi2Preselection[0], 5, 2, ese_parameters::names, ese_parameters::pidTPCChi2Names}, "TPCChi2 preselection for light nuclei"}; + Configurable> cfgITSChi2Preselection{"cfgITSChi2Preselection", {ese_parameters::ITSChi2Preselection[0], 5, 2, ese_parameters::names, ese_parameters::pidITSChi2Names}, "ITSChi2 preselection for light nuclei"}; + Configurable> cfgDCAxyPreselection{"cfgDCAxyPreselection", {ese_parameters::DCAxyPreselection[0], 5, 1, ese_parameters::names, ese_parameters::pidDCAxyNames}, "DCAxy preselection for light nuclei"}; + Configurable> cfgDCAzPreselection{"cfgDCAzPreselection", {ese_parameters::DCAzPreselection[0], 5, 1, ese_parameters::names, ese_parameters::pidDCAzNames}, "DCAz preselection for light nuclei"}; Configurable> cfgnSigmaCutTOFProton{"cfgnSigmaCutTOFProton", {-1.5, 1.5}, "TOF nsigma cut limit for Proton"}; Configurable> cfgnSigmaCutRMSProton{"cfgnSigmaCutRMSProton", {-3, 3}, "RMS nsigma cut limit for Proton"}; - Configurable cfgUseSelfnSigmaTPCProton{"cfgUseSelfnSigmaTPCProton", false, "Use self nSigma TPC for Proton PID"}; + Configurable cfgUseSelfnSigmaTPCProton{"cfgUseSelfnSigmaTPCProton", true, "Use self nSigma TPC for Proton PID"}; Configurable cfgProtonPIDMode{"cfgProtonPIDMode", 2, "Proton PID mode: 0 for TPC + RMS(TPC,TOF), 1 for TPC only, 2 for TOF only"}; Configurable> cfgnSigmaTPC{"cfgnSigmaTPC", {ese_parameters::TPCnSigmaCutDefault[0], 5, 2, ese_parameters::names, ese_parameters::pidTPCnSigmaNames}, "TPC nSigma selection for light nuclei"}; Configurable> cfgnSigmaITS{"cfgnSigmaITS", {ese_parameters::ITSnSigmaCutDefault[0], 5, 2, ese_parameters::names, ese_parameters::pidITSnSigmaNames}, "ITS nSigma selection for light nuclei"}; @@ -656,9 +713,6 @@ struct FlowEsePHe3 { template void fillHistosQvec(const CollType& collision) { - int detInd = detId * 4 + cfgnTotalSystem * 4 * (2 - 2); - int refAInd = refAId * 4 + cfgnTotalSystem * 4 * (2 - 2); - int refBInd = refBId * 4 + cfgnTotalSystem * 4 * (2 - 2); if (collision.qvecAmp()[detId] > ese_parameters::Amplitudelow) { histsESE.fill(HIST("PlanQA/histQvec_CorrL0_V2"), collision.qvecRe()[detInd], collision.qvecIm()[detInd], collision.centFT0C()); histsESE.fill(HIST("PlanQA/histQvec_CorrL1_V2"), collision.qvecRe()[detInd + 1], collision.qvecIm()[detInd + 1], collision.centFT0C()); @@ -679,7 +733,30 @@ struct FlowEsePHe3 { template bool pidSel(const TrackType& track, uint8_t POI) { - if (track.pt() < cfgPtPreselection->get(POI, 0u) || track.pt() > cfgPtPreselection->get(POI, 1u)) { + bool heliumPID = track.pidForTracking() == o2::track::PID::Helium3 || track.pidForTracking() == o2::track::PID::Alpha; + float correctedTpcInnerParam = (heliumPID && cfgCompensatePIDinTracking) ? track.tpcInnerParam() / 2 : track.tpcInnerParam(); + if (correctedTpcInnerParam < cfgPOverZPreselection->get(POI, 0u) || correctedTpcInnerParam > cfgPOverZPreselection->get(POI, 1u)) { + return false; + } + if (std::abs(track.eta()) > cfgEtaPreselection->get(POI)) { + return false; + } + if (track.tpcNClsFound() < cfgTPCNclsPreselection->get(POI, 0u) || track.tpcNClsFound() > cfgTPCNclsPreselection->get(POI, 1u)) { + return false; + } + if (track.itsNCls() < cfgITSNclsPreselection->get(POI, 0u) || track.itsNCls() > cfgITSNclsPreselection->get(POI, 1u)) { + return false; + } + if (track.tpcChi2NCl() < cfgTPCChi2Preselection->get(POI, 0u) || track.tpcChi2NCl() > cfgTPCChi2Preselection->get(POI, 1u)) { + return false; + } + if (track.itsChi2NCl() < cfgITSChi2Preselection->get(POI, 0u) || track.itsChi2NCl() > cfgITSChi2Preselection->get(POI, 1u)) { + return false; + } + if (std::abs(track.dcaXY()) > cfgDCAxyPreselection->get(POI)) { + return false; + } + if (std::abs(track.dcaZ()) > cfgDCAzPreselection->get(POI)) { return false; } float nSigmaTPC = 0.f; @@ -700,27 +777,32 @@ struct FlowEsePHe3 { return false; } } - nSigmaITS = itsResponse.nSigmaITS(track); + if (cfgOpenITSPreselection) + nSigmaITS = itsResponse.nSigmaITS(track); break; case ese_parameters::kDeuteron: nSigmaTPC = getNSigmaTPCSelfBB(track, ese_parameters::kDeuteron); - nSigmaITS = itsResponse.nSigmaITS(track); + if (cfgOpenITSPreselection) + nSigmaITS = itsResponse.nSigmaITS(track); break; case ese_parameters::kTriton: nSigmaTPC = getNSigmaTPCSelfBB(track, ese_parameters::kTriton); - nSigmaITS = itsResponse.nSigmaITS(track); + if (cfgOpenITSPreselection) + nSigmaITS = itsResponse.nSigmaITS(track); break; case ese_parameters::kHe3: nSigmaTPC = getNSigmaTPCSelfBB(track, ese_parameters::kHe3); - nSigmaITS = itsResponse.nSigmaITS(track); + if (cfgOpenITSPreselection) + nSigmaITS = itsResponse.nSigmaITS(track); break; case ese_parameters::kAlpha: nSigmaTPC = getNSigmaTPCSelfBB(track, ese_parameters::kAlpha); - nSigmaITS = itsResponse.nSigmaITS(track); + if (cfgOpenITSPreselection) + nSigmaITS = itsResponse.nSigmaITS(track); break; default: @@ -730,8 +812,10 @@ struct FlowEsePHe3 { if (nSigmaTPC < cfgnSigmaTPC->get(POI, 0u) || nSigmaTPC > cfgnSigmaTPC->get(POI, 1u)) { return false; } - if (nSigmaITS < cfgnSigmaITS->get(POI, 0u) || nSigmaITS > cfgnSigmaITS->get(POI, 1u)) { - return false; + if (cfgOpenITSPreselection) { + if (nSigmaITS < cfgnSigmaITS->get(POI, 0u) || nSigmaITS > cfgnSigmaITS->get(POI, 1u)) { + return false; + } } return true; } @@ -782,9 +866,9 @@ struct FlowEsePHe3 { ese_parameters::hPIDQATar1D[10]->Fill(nSigmaTOFTar); ese_parameters::hPIDQATar1D[11]->Fill(nSigmaITSTar); ese_parameters::hPIDQATar2D[0]->Fill(track.sign() * correctedTpcInnerParam, track.tpcSignal()); - ese_parameters::hPIDQATar2D[1]->Fill(nSigmaTPCTar, track.pt()); - ese_parameters::hPIDQATar2D[2]->Fill(nSigmaTOFTar, track.pt()); - ese_parameters::hPIDQATar2D[3]->Fill(nSigmaITSTar, track.pt()); + ese_parameters::hPIDQATar2D[1]->Fill(track.pt(), nSigmaTPCTar); + ese_parameters::hPIDQATar2D[2]->Fill(track.pt(), nSigmaTOFTar); + ese_parameters::hPIDQATar2D[3]->Fill(track.pt(), nSigmaITSTar); if (cfgOpen3DPIDPlots->get(0u)) { ese_parameters::hPIDQATar3D[0]->Fill(nSigmaTOFTar, nSigmaITSTar, track.pt()); } @@ -830,9 +914,9 @@ struct FlowEsePHe3 { ese_parameters::hPIDQARef1D[10]->Fill(nSigmaTOFRef); ese_parameters::hPIDQARef1D[11]->Fill(nSigmaITSRef); ese_parameters::hPIDQARef2D[0]->Fill(track.sign() * correctedTpcInnerParam, track.tpcSignal()); - ese_parameters::hPIDQARef2D[1]->Fill(nSigmaTPCRef, track.pt()); - ese_parameters::hPIDQARef2D[2]->Fill(nSigmaTOFRef, track.pt()); - ese_parameters::hPIDQARef2D[3]->Fill(nSigmaITSRef, track.pt()); + ese_parameters::hPIDQARef2D[1]->Fill(track.pt(), nSigmaTPCRef); + ese_parameters::hPIDQARef2D[2]->Fill(track.pt(), nSigmaTOFRef); + ese_parameters::hPIDQARef2D[3]->Fill(track.pt(), nSigmaITSRef); if (cfgOpen3DPIDPlots->get(0u)) { ese_parameters::hPIDQARef3D[0]->Fill(nSigmaTOFRef, nSigmaITSRef, track.pt()); } @@ -891,7 +975,7 @@ struct FlowEsePHe3 { AxisSpec axisCentForQA = {100, 0, 100}; AxisSpec axisCharge = {4, -2, 2, "Charge"}; // hists for event level QA - histsESE.add("EventQA/histEventCount", ";Event Count;Counts", {HistType::kTH1F, {{100, 0, 100}}}); + histsESE.add("EventQA/histEventCount", ";Event Count;Counts", {HistType::kTH1F, {{11, 0, 11}}}); histsESE.get(HIST("EventQA/histEventCount"))->GetXaxis()->SetBinLabel(1, "after sel8"); histsESE.get(HIST("EventQA/histEventCount"))->GetXaxis()->SetBinLabel(2, "kIsGoodZvtxFT0vsPV"); histsESE.get(HIST("EventQA/histEventCount"))->GetXaxis()->SetBinLabel(3, "kNoSameBunchPileup"); @@ -1029,6 +1113,7 @@ struct FlowEsePHe3 { float q2Refy{0.}; int multiTar{0}; int multiRef{0}; + fillHistosQvec(collision); fillESECandidates(collision, tracks, q2Tarx, q2Tary, multiTar, q2Refx, q2Refy, multiRef); float q2Tar{calculateq2(q2Tarx, q2Tary, multiTar)}; float q2Ref{calculateq2(q2Refx, q2Refy, multiRef)}; From cad9bd91bfbc00b4c4fd4d35e67e0380508e32e5 Mon Sep 17 00:00:00 2001 From: JStaa <39123272+JStaa@users.noreply.github.com> Date: Wed, 18 Jun 2025 21:27:42 +0200 Subject: [PATCH 135/871] [PWGCF] Added V0 cuts and changed the RD method & V0 MC efficiency (#11677) Co-authored-by: ALICE Action Bot --- .../Tasks/threeParticleCorrelations.cxx | 301 ++++++++---------- 1 file changed, 133 insertions(+), 168 deletions(-) diff --git a/PWGCF/MultiparticleCorrelations/Tasks/threeParticleCorrelations.cxx b/PWGCF/MultiparticleCorrelations/Tasks/threeParticleCorrelations.cxx index 2d35169f9e8..33020769355 100644 --- a/PWGCF/MultiparticleCorrelations/Tasks/threeParticleCorrelations.cxx +++ b/PWGCF/MultiparticleCorrelations/Tasks/threeParticleCorrelations.cxx @@ -43,14 +43,24 @@ struct ThreeParticleCorrelations { float trackPtMin = 0.2, trackPtMax = 3.0; float trackEtaMax = 0.8; + // Track PID parameters double pionID = 0.0, kaonID = 1.0, protonID = 2.0; - float nSigma0 = 0.0, nSigma2 = 2.0, nSigma4 = 4.0; + float nSigma0 = 0.0, nSigma2 = 2.0, nSigma4 = 4.0, nSigma5 = 5.0; + // V0 filter parameters + float tpcNCrossedRowsMin = 70.0; + float decayRMin = 1.2, ctauMax = 30.0; + float cosPAMin = 0.995; + float dcaProtonMin = 0.05, dcaPionMin = 0.2; + int dcaV0DauMax = 1; + + // Track filter parameters float pionPtMin = 0.3, pionPtMax = 2.3, kaonPtMin = 0.5, kaonPtMax = 2.5, protonPtMin = 0.5, protonPtMax = 2.5; float pionPtMid = 1.5, kaonPtMid1 = 1.5, kaonPtMid2 = 2.0, protonPtMid = 0.7; - float dEtaMax = 0.05, dEtaMin = 0.022; - float dPhiStarMinOS = 0.075, dPhiStarMinSS = 0.12; + // RD filter parameters + float dEtaMax = 0.05, dEtaMin = 0.023; + float dPhiStarMinOS = 0.09, dPhiStarMinSS = 0.095; float rMin = 0.8, rMax = 2.5; // Lambda invariant mass fit @@ -156,8 +166,8 @@ struct ThreeParticleCorrelations { // QA & PID rQARegistry.add("hNEvents", "hNEvents", {HistType::kTH1D, {{3, 0, 3}}}); rQARegistry.get(HIST("hNEvents"))->GetXaxis()->SetBinLabel(1, "All"); - rQARegistry.get(HIST("hNEvents"))->GetXaxis()->SetBinLabel(2, "kNoSameBunchPileup"); - rQARegistry.get(HIST("hNEvents"))->GetXaxis()->SetBinLabel(3, "kIsGoodZvtxFT0vsPV"); + rQARegistry.get(HIST("hNEvents"))->GetXaxis()->SetBinLabel(2, "kIsGoodZvtxFT0vsPV"); + rQARegistry.get(HIST("hNEvents"))->GetXaxis()->SetBinLabel(3, "kNoSameBunchPileup"); rQARegistry.add("hEventCentrality", "hEventCentrality", {HistType::kTH1D, {{centralityAxis}}}); rQARegistry.add("hEventCentrality_MC", "hEventCentrality_MC", {HistType::kTH1D, {{centralityAxis}}}); @@ -198,27 +208,19 @@ struct ThreeParticleCorrelations { rQARegistry.add("hInvMassAntiLambda_MC", "hInvMassAntiLambda_MC", {HistType::kTH3D, {{lambdaInvMassAxis}, {v0PtAxis}, {centralityAxis}}}); // PhiStar - rPhiStarRegistry.add("hSEProtonPreCut_OS", "hSEProtonPreCut_OS", {HistType::kTH2D, {{121, -0.3025, 0.3025}, {101, -0.0505, 0.0505}}}); - rPhiStarRegistry.add("hSEProtonPreCut_SS", "hSEProtonPreCut_SS", {HistType::kTH2D, {{121, -0.3025, 0.3025}, {101, -0.0505, 0.0505}}}); - rPhiStarRegistry.add("hSEProtonPreCut_SSP", "hSEProtonPreCut_SSP", {HistType::kTH2D, {{121, -0.3025, 0.3025}, {101, -0.0505, 0.0505}}}); - rPhiStarRegistry.add("hSEProtonPreCut_SSN", "hSEProtonPreCut_SSN", {HistType::kTH2D, {{121, -0.3025, 0.3025}, {101, -0.0505, 0.0505}}}); - rPhiStarRegistry.add("hSEProtonPostCut_OS", "hSEProtonPostCut_OS", {HistType::kTH2D, {{121, -0.3025, 0.3025}, {101, -0.0505, 0.0505}}}); - rPhiStarRegistry.add("hSEProtonPostCut_SS", "hSEProtonPostCut_SS", {HistType::kTH2D, {{121, -0.3025, 0.3025}, {101, -0.0505, 0.0505}}}); - rPhiStarRegistry.add("hSEProtonPostCut_SSP", "hSEProtonPostCut_SSP", {HistType::kTH2D, {{121, -0.3025, 0.3025}, {101, -0.0505, 0.0505}}}); - rPhiStarRegistry.add("hSEProtonPostCut_SSN", "hSEProtonPostCut_SSN", {HistType::kTH2D, {{121, -0.3025, 0.3025}, {101, -0.0505, 0.0505}}}); + rPhiStarRegistry.add("hSEPhiStarIR_OS", "hSEPhiStarIR_OS", {HistType::kTH2D, {{121, -0.3025, 0.3025}, {101, -0.0505, 0.0505}}}); + rPhiStarRegistry.add("hSEPhiStarIR_SS", "hSEPhiStarIR_SS", {HistType::kTH2D, {{121, -0.3025, 0.3025}, {101, -0.0505, 0.0505}}}); + rPhiStarRegistry.add("hSEPhiStarIR_SSP", "hSEPhiStarIR_SSP", {HistType::kTH2D, {{121, -0.3025, 0.3025}, {101, -0.0505, 0.0505}}}); + rPhiStarRegistry.add("hSEPhiStarIR_SSN", "hSEPhiStarIR_SSN", {HistType::kTH2D, {{121, -0.3025, 0.3025}, {101, -0.0505, 0.0505}}}); rPhiStarRegistry.add("hSEPhiStarMean_OS", "hSEPhiStarMean_OS", {HistType::kTH2D, {{121, -0.3025, 0.3025}, {101, -0.0505, 0.0505}}}); rPhiStarRegistry.add("hSEPhiStarMean_SS", "hSEPhiStarMean_SS", {HistType::kTH2D, {{121, -0.3025, 0.3025}, {101, -0.0505, 0.0505}}}); rPhiStarRegistry.add("hSEPhiStarMean_SSP", "hSEPhiStarMean_SSP", {HistType::kTH2D, {{121, -0.3025, 0.3025}, {101, -0.0505, 0.0505}}}); rPhiStarRegistry.add("hSEPhiStarMean_SSN", "hSEPhiStarMean_SSN", {HistType::kTH2D, {{121, -0.3025, 0.3025}, {101, -0.0505, 0.0505}}}); - rPhiStarRegistry.add("hMEProtonPreCut_OS", "hMEProtonPreCut_OS", {HistType::kTH2D, {{121, -0.3025, 0.3025}, {101, -0.0505, 0.0505}}}); - rPhiStarRegistry.add("hMEProtonPreCut_SS", "hMEProtonPreCut_SS", {HistType::kTH2D, {{121, -0.3025, 0.3025}, {101, -0.0505, 0.0505}}}); - rPhiStarRegistry.add("hMEProtonPreCut_SSP", "hMEProtonPreCut_SSP", {HistType::kTH2D, {{121, -0.3025, 0.3025}, {101, -0.0505, 0.0505}}}); - rPhiStarRegistry.add("hMEProtonPreCut_SSN", "hMEProtonPreCut_SSN", {HistType::kTH2D, {{121, -0.3025, 0.3025}, {101, -0.0505, 0.0505}}}); - rPhiStarRegistry.add("hMEProtonPostCut_OS", "hMEProtonPostCut_OS", {HistType::kTH2D, {{121, -0.3025, 0.3025}, {101, -0.0505, 0.0505}}}); - rPhiStarRegistry.add("hMEProtonPostCut_SS", "hMEProtonPostCut_SS", {HistType::kTH2D, {{121, -0.3025, 0.3025}, {101, -0.0505, 0.0505}}}); - rPhiStarRegistry.add("hMEProtonPostCut_SSP", "hMEProtonPostCut_SSP", {HistType::kTH2D, {{121, -0.3025, 0.3025}, {101, -0.0505, 0.0505}}}); - rPhiStarRegistry.add("hMEProtonPostCut_SSN", "hMEProtonPostCut_SSN", {HistType::kTH2D, {{121, -0.3025, 0.3025}, {101, -0.0505, 0.0505}}}); + rPhiStarRegistry.add("hMEPhiStarIR_OS", "hMEPhiStarIR_OS", {HistType::kTH2D, {{121, -0.3025, 0.3025}, {101, -0.0505, 0.0505}}}); + rPhiStarRegistry.add("hMEPhiStarIR_SS", "hMEPhiStarIR_SS", {HistType::kTH2D, {{121, -0.3025, 0.3025}, {101, -0.0505, 0.0505}}}); + rPhiStarRegistry.add("hMEPhiStarIR_SSP", "hMEPhiStarIR_SSP", {HistType::kTH2D, {{121, -0.3025, 0.3025}, {101, -0.0505, 0.0505}}}); + rPhiStarRegistry.add("hMEPhiStarIR_SSN", "hMEPhiStarIR_SSN", {HistType::kTH2D, {{121, -0.3025, 0.3025}, {101, -0.0505, 0.0505}}}); rPhiStarRegistry.add("hMEPhiStarMean_OS", "hMEPhiStarMean_OS", {HistType::kTH2D, {{121, -0.3025, 0.3025}, {101, -0.0505, 0.0505}}}); rPhiStarRegistry.add("hMEPhiStarMean_SS", "hMEPhiStarMean_SS", {HistType::kTH2D, {{121, -0.3025, 0.3025}, {101, -0.0505, 0.0505}}}); rPhiStarRegistry.add("hMEPhiStarMean_SSP", "hMEPhiStarMean_SSP", {HistType::kTH2D, {{121, -0.3025, 0.3025}, {101, -0.0505, 0.0505}}}); @@ -250,10 +252,6 @@ struct ThreeParticleCorrelations { rMCRegistry.add("hPIDKaonN", "hPIDKaonN", {HistType::kTH3D, {{trackPtAxis}, {trackEtaAxis}, {centralityAxis}}}); rMCRegistry.add("hPIDProtonP", "hPIDProtonP", {HistType::kTH3D, {{trackPtAxis}, {trackEtaAxis}, {centralityAxis}}}); rMCRegistry.add("hPIDProtonN", "hPIDProtonN", {HistType::kTH3D, {{trackPtAxis}, {trackEtaAxis}, {centralityAxis}}}); - rMCRegistry.add("hPIDLambdaP_SGNL", "hPIDLambdaP_SGNL", {HistType::kTH3D, {{v0PtAxis}, {v0EtaAxis}, {centralityAxis}}}); - rMCRegistry.add("hPIDLambdaP_SB", "hPIDLambdaP_SB", {HistType::kTH3D, {{v0PtAxis}, {v0EtaAxis}, {centralityAxis}}}); - rMCRegistry.add("hPIDLambdaN_SGNL", "hPIDLambdaN_SGNL", {HistType::kTH3D, {{v0PtAxis}, {v0EtaAxis}, {centralityAxis}}}); - rMCRegistry.add("hPIDLambdaN_SB", "hPIDLambdaN_SB", {HistType::kTH3D, {{v0PtAxis}, {v0EtaAxis}, {centralityAxis}}}); // Purity rMCRegistry.add("hSelectPionP", "hSelectPionP", {HistType::kTH1D, {trackPtAxis}}); @@ -366,7 +364,7 @@ struct ThreeParticleCorrelations { // Start of the Same-Event correlations for (const auto& trigger : v0s) { - if (v0Filters(trigger, false)) { + if (v0Filters(collision, trigger, tracks)) { rQARegistry.fill(HIST("hPtV0"), trigger.pt(), collision.centFT0C()); triggSign = v0Sign(trigger); @@ -429,7 +427,7 @@ struct ThreeParticleCorrelations { // End of the Same-Event correlations } - void processMixed(MyFilteredCollisions const&, aod::V0Datas const&, MyFilteredTracks const&, aod::BCsWithTimestamps const&) + void processMixed(MyFilteredCollisions const&, aod::V0Datas const&, MyFilteredTracks const& tracks, aod::BCsWithTimestamps const&) { // Start of the Mixed-Event correlations @@ -441,7 +439,7 @@ struct ThreeParticleCorrelations { auto bc = coll_1.bc_as(); auto bField = getMagneticField(bc.timestamp()); for (const auto& [trigger, associate] : soa::combinations(soa::CombinationsFullIndexPolicy(v0_1, track_2))) { - if (v0Filters(trigger, false) && trackFilters(associate)) { + if (v0Filters(coll_1, trigger, tracks) && trackFilters(associate)) { if (radialDistanceFilter(trigger, associate, bField, true) && fakeV0Filter(trigger, associate)) { triggSign = v0Sign(trigger); @@ -758,42 +756,22 @@ struct ThreeParticleCorrelations { for (const auto& v0 : v0s) { - if (!v0.has_mcParticle() || v0.pt() < v0PtMin || v0.pt() > v0PtMax || std::abs(v0.eta()) > v0EtaMax) { + if (!v0.has_mcParticle()) { continue; } - auto particle = v0.mcParticle(); - if (particle.isPhysicalPrimary()) { + if (v0Filters(collision, v0, tracks)) { // V0 efficiency - Reconstructed - if (particle.pdgCode() == kLambda0) { // Lambdas + if (v0Sign(v0) == 1) { // Lambdas + candMass = v0.mLambda(); + rQARegistry.fill(HIST("hInvMassLambda_MC"), v0.mLambda(), v0.pt(), collision.centFT0C()); rMCRegistry.fill(HIST("hRecLambdaP"), v0.pt(), v0.eta(), collision.centFT0C()); - } else if (particle.pdgCode() == kLambda0Bar) { // AntiLambdas + } else if (v0Sign(v0) == -1) { // AntiLambdas + candMass = v0.mAntiLambda(); + rQARegistry.fill(HIST("hInvMassAntiLambda_MC"), v0.mAntiLambda(), v0.pt(), collision.centFT0C()); rMCRegistry.fill(HIST("hRecLambdaN"), v0.pt(), v0.eta(), collision.centFT0C()); } - - if (v0Filters(v0, true)) { - - // V0 efficiency - Reconstructed - if (v0Sign(v0) == 1) { // Lambdas - candMass = v0.mLambda(); - rQARegistry.fill(HIST("hInvMassLambda_MC"), v0.mLambda(), v0.pt(), collision.centFT0C()); - if (candMass >= MassLambda0 - 4 * dGaussSigma && candMass <= MassLambda0 + 4 * dGaussSigma) { - rMCRegistry.fill(HIST("hPIDLambdaP_SGNL"), v0.pt(), v0.eta(), collision.centFT0C()); - } else if (candMass >= MassLambda0 - 8 * dGaussSigma && candMass <= MassLambda0 + 8 * dGaussSigma) { - rMCRegistry.fill(HIST("hPIDLambdaP_SB"), v0.pt(), v0.eta(), collision.centFT0C()); - } - - } else if (v0Sign(v0) == -1) { // AntiLambdas - candMass = v0.mAntiLambda(); - rQARegistry.fill(HIST("hInvMassAntiLambda_MC"), v0.mAntiLambda(), v0.pt(), collision.centFT0C()); - if (candMass >= MassLambda0 - 4 * dGaussSigma && candMass <= MassLambda0 + 4 * dGaussSigma) { - rMCRegistry.fill(HIST("hPIDLambdaN_SGNL"), v0.pt(), v0.eta(), collision.centFT0C()); - } else if (candMass >= MassLambda0 - 8 * dGaussSigma && candMass <= MassLambda0 + 8 * dGaussSigma) { - rMCRegistry.fill(HIST("hPIDLambdaN_SB"), v0.pt(), v0.eta(), collision.centFT0C()); - } - } - } } } // End of the Monte-Carlo reconstructed QA @@ -887,67 +865,81 @@ struct ThreeParticleCorrelations { //========================================================================================================================================================================================================================================================================== - template - bool acceptEvent(const CollCand& collision, bool FillHist) // Event filter + template + bool acceptEvent(const Col& col, bool FillHist) // Event filter { if (FillHist) { rQARegistry.fill(HIST("hNEvents"), 0.5); } - if (!collision.selection_bit(aod::evsel::kNoSameBunchPileup)) { // kNoSameBunchPileup - return kFALSE; + if (!col.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV)) { // kIsGoodZvtxFT0vsPV + return false; } if (FillHist) { rQARegistry.fill(HIST("hNEvents"), 1.5); } - if (!collision.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV)) { // kIsGoodZvtxFT0vsPV - return kFALSE; + if (!col.selection_bit(aod::evsel::kNoSameBunchPileup)) { // kNoSameBunchPileup + return false; } if (FillHist) { rQARegistry.fill(HIST("hNEvents"), 2.5); } - return kTRUE; + return true; } - template - bool v0Filters(const V0Cand& v0, bool MCRec) // V0 filter + template + bool v0Filters(const Col& col, const V0Cand& v0, T const&) // V0 filter { - if (v0.pt() < v0PtMin || v0.pt() > v0PtMax) - return kFALSE; - if (std::abs(v0.eta()) > v0EtaMax) - return kFALSE; + // Kinematic cuts + if (v0.pt() <= v0PtMin || v0.pt() >= v0PtMax || std::abs(v0.eta()) >= v0EtaMax) { + return false; + } - if (!MCRec) { // Data - if (v0Sign(v0) == 1) { - const auto& posDaughter = v0.template posTrack_as(); - if (std::abs(posDaughter.tpcNSigmaPr()) > nSigma4) { - return kFALSE; - } - } else if (v0Sign(v0) == -1) { - const auto& negDaughter = v0.template negTrack_as(); - if (std::abs(negDaughter.tpcNSigmaPr()) > nSigma4) { - return kFALSE; - } + // Daughter cuts + auto posDaughter = v0.template posTrack_as(); + auto negDaughter = v0.template negTrack_as(); + if (std::abs(posDaughter.eta()) >= trackEtaMax || std::abs(negDaughter.eta()) >= trackEtaMax) { + return false; + } + if (posDaughter.tpcNClsCrossedRows() <= tpcNCrossedRowsMin || negDaughter.tpcNClsCrossedRows() <= tpcNCrossedRowsMin) { + return false; + } + if (v0Sign(v0) == 1) { + if (std::abs(posDaughter.tpcNSigmaPr()) >= nSigma5 || std::abs(negDaughter.tpcNSigmaPi()) >= nSigma5) { + return false; } - } else { // MC Reconstructed - if (v0Sign(v0) == 1) { - const auto& posDaughter = v0.template posTrack_as(); - if (std::abs(posDaughter.tpcNSigmaPr()) > nSigma4) { - return kFALSE; - } - } else if (v0Sign(v0) == -1) { - const auto& negDaughter = v0.template negTrack_as(); - if (std::abs(negDaughter.tpcNSigmaPr()) > nSigma4) { - return kFALSE; - } + if (std::abs(v0.dcapostopv()) <= dcaProtonMin || std::abs(v0.dcanegtopv()) <= dcaPionMin) { + return false; + } + } else if (v0Sign(v0) == -1) { + if (std::abs(posDaughter.tpcNSigmaPi()) >= nSigma5 || std::abs(negDaughter.tpcNSigmaPr()) >= nSigma5) { + return false; } + if (std::abs(v0.dcapostopv()) <= dcaPionMin || std::abs(v0.dcanegtopv()) <= dcaProtonMin) { + return false; + } + } + + // Topological cuts + float ctau = v0.distovertotmom(col.posX(), col.posY(), col.posZ()) * MassLambda0; + if (v0.v0radius() <= decayRMin) { + return false; + } + if (ctau >= ctauMax) { + return false; + } + if (v0.v0cosPA() <= cosPAMin) { + return false; + } + if (v0.dcaV0daughters() >= dcaV0DauMax) { + return false; } - return kTRUE; + return true; } template @@ -955,71 +947,71 @@ struct ThreeParticleCorrelations { { if (!track.hasTOF()) { - return kFALSE; + return false; } if (trackPID(track)[0] == pionID) { // Pions - if (std::abs(track.tpcNSigmaPi()) > nSigma4) { - return kFALSE; + if (std::abs(track.tpcNSigmaPi()) >= nSigma4) { + return false; } if (track.pt() < pionPtMin) { - return kFALSE; + return false; } else if (track.pt() > pionPtMin && track.pt() < pionPtMid) { - if (std::abs(track.tofNSigmaPi()) > nSigma4) { - return kFALSE; + if (std::abs(track.tofNSigmaPi()) >= nSigma4) { + return false; } } else if (track.pt() > pionPtMid && track.pt() < pionPtMax) { - if (track.tofNSigmaPi() < -nSigma4 || track.tofNSigmaPi() > nSigma0) { - return kFALSE; + if (track.tofNSigmaPi() <= -nSigma4 || track.tofNSigmaPi() >= nSigma0) { + return false; } } else if (track.pt() > pionPtMax) { - return kFALSE; + return false; } } else if (trackPID(track)[0] == kaonID) { // Kaons - if (std::abs(track.tpcNSigmaKa()) > nSigma4) { - return kFALSE; + if (std::abs(track.tpcNSigmaKa()) >= nSigma4) { + return false; } if (track.pt() < kaonPtMin) { - return kFALSE; + return false; } else if (track.pt() > kaonPtMin && track.pt() < kaonPtMid1) { - if (std::abs(track.tofNSigmaKa()) > nSigma4) { - return kFALSE; + if (std::abs(track.tofNSigmaKa()) >= nSigma4) { + return false; } } else if (track.pt() > kaonPtMid1 && track.pt() < kaonPtMid2) { - if (track.tofNSigmaKa() < -nSigma2 || track.tofNSigmaKa() > nSigma4) { - return kFALSE; + if (track.tofNSigmaKa() <= -nSigma2 || track.tofNSigmaKa() >= nSigma4) { + return false; } } else if (track.pt() > kaonPtMid2 && track.pt() < kaonPtMax) { - if (track.tofNSigmaKa() < nSigma0 || track.tofNSigmaKa() > nSigma4) { - return kFALSE; + if (track.tofNSigmaKa() <= nSigma0 || track.tofNSigmaKa() >= nSigma4) { + return false; } } else if (track.pt() > kaonPtMax) { - return kFALSE; + return false; } } else if (trackPID(track)[0] == protonID) { // Protons - if (std::abs(track.tpcNSigmaPr()) > nSigma4) { - return kFALSE; + if (std::abs(track.tpcNSigmaPr()) >= nSigma4) { + return false; } if (track.pt() < protonPtMin) { - return kFALSE; + return false; } else if (track.pt() > protonPtMin && track.pt() < protonPtMid) { - if (track.tofNSigmaPr() < -nSigma2 || track.tofNSigmaPr() > nSigma4) { - return kFALSE; + if (track.tofNSigmaPr() <= -nSigma2 || track.tofNSigmaPr() >= nSigma4) { + return false; } } else if (track.pt() > protonPtMid && track.pt() < protonPtMax) { - if (std::abs(track.tofNSigmaPr()) > nSigma4) { - return kFALSE; + if (std::abs(track.tofNSigmaPr()) >= nSigma4) { + return false; } } else if (track.pt() > protonPtMax) { - if (track.tofNSigmaPr() < -nSigma2 || track.tofNSigmaPr() > nSigma4) { - return kFALSE; + if (track.tofNSigmaPr() <= -nSigma2 || track.tofNSigmaPr() >= nSigma4) { + return false; } } } - return kTRUE; + return true; } template @@ -1027,10 +1019,10 @@ struct ThreeParticleCorrelations { { if (track.globalIndex() == v0.posTrackId() || track.globalIndex() == v0.negTrackId()) { - return kFALSE; + return false; } - return kTRUE; + return true; } template @@ -1040,7 +1032,7 @@ struct ThreeParticleCorrelations { if (confFakeV0Switch) { if (trackPID(track)[0] == kaonID) { // Kaons - return kTRUE; + return true; } std::array massArray; @@ -1070,11 +1062,11 @@ struct ThreeParticleCorrelations { double invMass = RecoDecay::m(std::array{dMomArray, aMomArray}, massArray); if (invMass >= MassLambda0 - 4 * dGaussSigma && invMass <= MassLambda0 + 4 * dGaussSigma) { - return kFALSE; + return false; } } - return kTRUE; + return true; } template @@ -1108,69 +1100,36 @@ struct ThreeParticleCorrelations { if (r == rMin) { if (!Mix) { // Same-event if (proton.sign() * track.sign() == -1) { // OS (Electric charge) - rPhiStarRegistry.fill(HIST("hSEProtonPreCut_OS"), dPhiStar, dEta); + rPhiStarRegistry.fill(HIST("hSEPhiStarIR_OS"), dPhiStar, dEta); } else if (proton.sign() * track.sign() == 1) { // SS (Electric charge) - rPhiStarRegistry.fill(HIST("hSEProtonPreCut_SS"), dPhiStar, dEta); + rPhiStarRegistry.fill(HIST("hSEPhiStarIR_SS"), dPhiStar, dEta); if (proton.sign() == 1) { // Positive - rPhiStarRegistry.fill(HIST("hSEProtonPreCut_SSP"), dPhiStar, dEta); + rPhiStarRegistry.fill(HIST("hSEPhiStarIR_SSP"), dPhiStar, dEta); } else if (proton.sign() == -1) { // Negative - rPhiStarRegistry.fill(HIST("hSEProtonPreCut_SSN"), dPhiStar, dEta); + rPhiStarRegistry.fill(HIST("hSEPhiStarIR_SSN"), dPhiStar, dEta); } } } else { // Mixed-event if (proton.sign() * track.sign() == -1) { // OS (Electric charge) - rPhiStarRegistry.fill(HIST("hMEProtonPreCut_OS"), dPhiStar, dEta); + rPhiStarRegistry.fill(HIST("hMEPhiStarIR_OS"), dPhiStar, dEta); } else if (proton.sign() * track.sign() == 1) { // SS (Electric charge) - rPhiStarRegistry.fill(HIST("hMEProtonPreCut_SS"), dPhiStar, dEta); + rPhiStarRegistry.fill(HIST("hMEPhiStarIR_SS"), dPhiStar, dEta); if (proton.sign() == 1) { // Positive - rPhiStarRegistry.fill(HIST("hMEProtonPreCut_SSP"), dPhiStar, dEta); + rPhiStarRegistry.fill(HIST("hMEPhiStarIR_SSP"), dPhiStar, dEta); } else if (proton.sign() == -1) { // Negative - rPhiStarRegistry.fill(HIST("hMEProtonPreCut_SSN"), dPhiStar, dEta); + rPhiStarRegistry.fill(HIST("hMEPhiStarIR_SSN"), dPhiStar, dEta); } } } - } - if (std::abs(dEta) < dEtaMin) { if (proton.sign() * track.sign() == -1) { // OS (Electric charge) - if (std::abs(dPhiStar) < dPhiStarMinOS) { - pass = false; - } - } else if (proton.sign() * track.sign() == 1) { // SS (Electric charge) - if (std::abs(dPhiStar) < dPhiStarMinSS) { + if (std::abs(dEta) < dEtaMin && std::abs(dPhiStar) < dPhiStarMinOS) { pass = false; } } } - if (r == rMin && pass) { - if (!Mix) { // Same-event - if (proton.sign() * track.sign() == -1) { // OS (Electric charge) - rPhiStarRegistry.fill(HIST("hSEProtonPostCut_OS"), dPhiStar, dEta); - } else if (proton.sign() * track.sign() == 1) { // SS (Electric charge) - rPhiStarRegistry.fill(HIST("hSEProtonPostCut_SS"), dPhiStar, dEta); - if (proton.sign() == 1) { // Positive - rPhiStarRegistry.fill(HIST("hSEProtonPostCut_SSP"), dPhiStar, dEta); - } else if (proton.sign() == -1) { // Negative - rPhiStarRegistry.fill(HIST("hSEProtonPostCut_SSN"), dPhiStar, dEta); - } - } - - } else { // Mixed-event - if (proton.sign() * track.sign() == -1) { // OS (Electric charge) - rPhiStarRegistry.fill(HIST("hMEProtonPostCut_OS"), dPhiStar, dEta); - } else if (proton.sign() * track.sign() == 1) { // SS (Electric charge) - rPhiStarRegistry.fill(HIST("hMEProtonPostCut_SS"), dPhiStar, dEta); - if (proton.sign() == 1) { // Positive - rPhiStarRegistry.fill(HIST("hMEProtonPostCut_SSP"), dPhiStar, dEta); - } else if (proton.sign() == -1) { // Negative - rPhiStarRegistry.fill(HIST("hMEProtonPostCut_SSN"), dPhiStar, dEta); - } - } - } - } - dPhiStarMean += (dPhiStar / 170); } // End of the TPC radius loop @@ -1199,6 +1158,12 @@ struct ThreeParticleCorrelations { } } } + + if (proton.sign() * track.sign() == 1) { // SS (Electric charge) + if (std::abs(dEta) < dEtaMin && std::abs(dPhiStarMean) < dPhiStarMinSS) { + pass = false; + } + } } return pass; From fa49c2650d3837f741e311e4fb15ebc88acae474 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Jacazio?= Date: Wed, 18 Jun 2025 22:12:04 +0200 Subject: [PATCH 136/871] [Common] Enclose Metadata and CollisionType Helper in o2 namespace (#11657) --- Common/Core/CollisionTypeHelper.cxx | 9 ++++++--- Common/Core/CollisionTypeHelper.h | 9 ++++++++- Common/Core/MetadataHelper.cxx | 2 ++ Common/Core/MetadataHelper.h | 12 ++++++++++-- 4 files changed, 26 insertions(+), 6 deletions(-) diff --git a/Common/Core/CollisionTypeHelper.cxx b/Common/Core/CollisionTypeHelper.cxx index c22510ec82e..2396a217215 100644 --- a/Common/Core/CollisionTypeHelper.cxx +++ b/Common/Core/CollisionTypeHelper.cxx @@ -16,11 +16,14 @@ /// #include "Common/Core/CollisionTypeHelper.h" + +#include "DataFormatsParameters/GRPLHCIFData.h" + #include + #include -#include "DataFormatsParameters/GRPLHCIFData.h" -std::string CollisionSystemType::getCollisionSystemName(collType collSys) +std::string o2::common::core::CollisionSystemType::getCollisionSystemName(collType collSys) { switch (collSys) { case kCollSyspp: @@ -36,7 +39,7 @@ std::string CollisionSystemType::getCollisionSystemName(collType collSys) } } -int CollisionSystemType::getCollisionTypeFromGrp(o2::parameters::GRPLHCIFData* grplhcif) +int o2::common::core::CollisionSystemType::getCollisionTypeFromGrp(o2::parameters::GRPLHCIFData* grplhcif) { const int ZBeamA = grplhcif->getBeamZ(o2::constants::lhc::BeamDirection::BeamA); const int ZBeamC = grplhcif->getBeamZ(o2::constants::lhc::BeamDirection::BeamC); diff --git a/Common/Core/CollisionTypeHelper.h b/Common/Core/CollisionTypeHelper.h index 0196fdc03bb..523d3d049c4 100644 --- a/Common/Core/CollisionTypeHelper.h +++ b/Common/Core/CollisionTypeHelper.h @@ -18,9 +18,12 @@ #ifndef COMMON_CORE_COLLISIONTYPEHELPER_H_ #define COMMON_CORE_COLLISIONTYPEHELPER_H_ -#include #include "DataFormatsParameters/GRPLHCIFData.h" +#include + +namespace o2::common::core +{ // Container for the collision system type struct CollisionSystemType { // Enum type for the collision system @@ -38,4 +41,8 @@ struct CollisionSystemType { static int getCollisionTypeFromGrp(o2::parameters::GRPLHCIFData* grplhcif); }; +} // namespace o2::common::core + +using CollisionSystemType = o2::common::core::CollisionSystemType; + #endif // COMMON_CORE_COLLISIONTYPEHELPER_H_ diff --git a/Common/Core/MetadataHelper.cxx b/Common/Core/MetadataHelper.cxx index 9df370449e6..b8c2fe6ad22 100644 --- a/Common/Core/MetadataHelper.cxx +++ b/Common/Core/MetadataHelper.cxx @@ -20,6 +20,8 @@ #include "Framework/InitContext.h" #include "Framework/RunningWorkflowInfo.h" +using namespace o2::common::core; + MetadataHelper::MetadataHelper() { const std::array keyList = {"DataType", diff --git a/Common/Core/MetadataHelper.h b/Common/Core/MetadataHelper.h index 8519c25bc88..45eb4e8651c 100644 --- a/Common/Core/MetadataHelper.h +++ b/Common/Core/MetadataHelper.h @@ -18,10 +18,14 @@ #ifndef COMMON_CORE_METADATAHELPER_H_ #define COMMON_CORE_METADATAHELPER_H_ -#include -#include #include "Framework/ConfigContext.h" +#include +#include + +namespace o2::common::core +{ + struct MetadataHelper { /// @brief Constructor for the MetadataHelper. Defines the all the metadata keys that will be looked for and accessible MetadataHelper(); @@ -64,4 +68,8 @@ struct MetadataHelper { bool mIsInitialized = false; /// < Flag to check if the metadata has been initialized }; +} // namespace o2::common::core + +using MetadataHelper = o2::common::core::MetadataHelper; // Alias for the MetadataHelper + #endif // COMMON_CORE_METADATAHELPER_H_ From e62eb26441e79bf4844f709e305df87b7f35dcaf Mon Sep 17 00:00:00 2001 From: skundu692 <86804743+skundu692@users.noreply.github.com> Date: Thu, 19 Jun 2025 00:16:10 +0200 Subject: [PATCH 137/871] [PWGLF] Derived data producer for lambda spin correlation study (#11676) --- PWGLF/DataModel/LFSpincorrelationTables.h | 84 +++++ .../TableProducer/Strangeness/CMakeLists.txt | 7 +- .../Strangeness/lambdaspincorrelation.cxx | 345 ++++++++++++++++++ 3 files changed, 435 insertions(+), 1 deletion(-) create mode 100644 PWGLF/DataModel/LFSpincorrelationTables.h create mode 100644 PWGLF/TableProducer/Strangeness/lambdaspincorrelation.cxx diff --git a/PWGLF/DataModel/LFSpincorrelationTables.h b/PWGLF/DataModel/LFSpincorrelationTables.h new file mode 100644 index 00000000000..40a823da48c --- /dev/null +++ b/PWGLF/DataModel/LFSpincorrelationTables.h @@ -0,0 +1,84 @@ +// 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 Sourav Kundu + +#ifndef PWGLF_DATAMODEL_LFSPINCORRELATIONTABLES_H_ +#define PWGLF_DATAMODEL_LFSPINCORRELATIONTABLES_H_ + +#include "Common/Core/RecoDecay.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include "Framework/ASoA.h" +#include "Framework/AnalysisDataModel.h" + +#include + +namespace o2::aod +{ +namespace lambdaspincorrevent +{ +DECLARE_SOA_COLUMN(Cent, cent, float); +DECLARE_SOA_COLUMN(Posz, posz, float); +} // namespace lambdaspincorrevent +DECLARE_SOA_TABLE(LambdaSpinCorrEvents, "AOD", "LAMBDASPINCOREVENT", + o2::soa::Index<>, + lambdaspincorrevent::Cent, + lambdaspincorrevent::Posz) +using LambdaSpinCorrEvent = LambdaSpinCorrEvents::iterator; + +namespace lambdaspincorrpair +{ +DECLARE_SOA_INDEX_COLUMN(LambdaSpinCorrEvent, lambdaspincorrevent); +DECLARE_SOA_COLUMN(V0Status, v0Status, float); //! Lambda or Anti-Lambda status +DECLARE_SOA_COLUMN(DoubleStatus, doubleStatus, bool); //! Double status +DECLARE_SOA_COLUMN(V0Cospa, v0Cospa, float); //! V0 Cospa +DECLARE_SOA_COLUMN(V0Radius, v0Radius, float); //! V0 Radius +DECLARE_SOA_COLUMN(DcaPositive, dcaPositive, float); //! DCA Positive +DECLARE_SOA_COLUMN(DcaNegative, dcaNegative, float); //! DCA Negative +DECLARE_SOA_COLUMN(DcaBetweenDaughter, dcaBetweenDaughter, float); //! DCA between daughters +DECLARE_SOA_COLUMN(LambdaPt, lambdaPt, float); //! Lambda Pt +DECLARE_SOA_COLUMN(LambdaEta, lambdaEta, float); //! Lambda Eta +DECLARE_SOA_COLUMN(LambdaPhi, lambdaPhi, float); //! Lambda Phi +DECLARE_SOA_COLUMN(LambdaMass, lambdaMass, float); //! Lambda Mass +DECLARE_SOA_COLUMN(ProtonPt, protonPt, float); //! Proton Pt +DECLARE_SOA_COLUMN(ProtonEta, protonEta, float); //! Proton Eta +DECLARE_SOA_COLUMN(ProtonPhi, protonPhi, float); //! Proton Phi +DECLARE_SOA_COLUMN(ProtonIndex, protonIndex, int); //! Proton index +DECLARE_SOA_COLUMN(PionIndex, pionIndex, int); //! Pion index +} // namespace lambdaspincorrpair +DECLARE_SOA_TABLE(LambdaSpinCorrPairs, "AOD", "LAMBDAPAIR", + o2::soa::Index<>, + lambdaspincorrpair::LambdaSpinCorrEventId, + lambdaspincorrpair::V0Status, + lambdaspincorrpair::DoubleStatus, + lambdaspincorrpair::V0Cospa, + lambdaspincorrpair::V0Radius, + lambdaspincorrpair::DcaPositive, + lambdaspincorrpair::DcaNegative, + lambdaspincorrpair::DcaBetweenDaughter, + lambdaspincorrpair::LambdaPt, + lambdaspincorrpair::LambdaEta, + lambdaspincorrpair::LambdaPhi, + lambdaspincorrpair::LambdaMass, + lambdaspincorrpair::ProtonPt, + lambdaspincorrpair::ProtonEta, + lambdaspincorrpair::ProtonPhi, + lambdaspincorrpair::ProtonIndex, + lambdaspincorrpair::PionIndex); + +using LambdaSpinCorrPair = LambdaSpinCorrPairs::iterator; +} // namespace o2::aod +#endif // PWGLF_DATAMODEL_LFSPINCORRELATIONTABLES_H_ diff --git a/PWGLF/TableProducer/Strangeness/CMakeLists.txt b/PWGLF/TableProducer/Strangeness/CMakeLists.txt index 6d9f2c04646..2591c9f06a7 100644 --- a/PWGLF/TableProducer/Strangeness/CMakeLists.txt +++ b/PWGLF/TableProducer/Strangeness/CMakeLists.txt @@ -160,4 +160,9 @@ o2physics_add_dpl_workflow(lambdajetpolarizationbuilder o2physics_add_dpl_workflow(stracents SOURCES stracents.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore - COMPONENT_NAME Analysis) \ No newline at end of file + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(lambdaspincorrelation + SOURCES lambdaspincorrelation.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) diff --git a/PWGLF/TableProducer/Strangeness/lambdaspincorrelation.cxx b/PWGLF/TableProducer/Strangeness/lambdaspincorrelation.cxx new file mode 100644 index 00000000000..7f60348230e --- /dev/null +++ b/PWGLF/TableProducer/Strangeness/lambdaspincorrelation.cxx @@ -0,0 +1,345 @@ +// 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 taskLambdaSpinCorr.cxx +/// \brief Analysis task for Lambda spin spin correlation +/// +/// \author prottay.das@cern.ch +/// \author sourav.kundu@cern.ch + +#include "PWGLF/DataModel/LFSpincorrelationTables.h" +#include "PWGLF/DataModel/LFStrangenessPIDTables.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" +#include "PWGMM/Mult/DataModel/Index.h" // for Particles2Tracks table + +#include "Common/Core/TrackSelection.h" +#include "Common/Core/trackUtilities.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/FT0Corrected.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include "CCDB/BasicCCDBManager.h" +#include "CommonConstants/PhysicsConstants.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/StepTHn.h" +#include "Framework/runDataProcessing.h" +#include "ReconstructionDataFormats/Track.h" + +#include "Math/GenVector/Boost.h" +#include "Math/Vector2D.h" +#include "Math/Vector3D.h" +#include "Math/Vector4D.h" + +#include + +#include +#include +#include + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using std::array; +using namespace o2::aod::rctsel; + +struct lambdaspincorrelation { + + Produces spinCorrEvent; + Produces spinCorrPair; + + Service ccdb; + + struct : ConfigurableGroup { + Configurable requireRCTFlagChecker{"requireRCTFlagChecker", true, "Check event quality in run condition table"}; + 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"}; + } rctCut; + // mixing + // Produce derived tables + Configurable cfgCutOccupancy{"cfgCutOccupancy", 2000, "Occupancy cut"}; + ConfigurableAxis axisVertex{"axisVertex", {5, -10, 10}, "vertex axis for bin"}; + ConfigurableAxis axisMultiplicityClass{"axisMultiplicityClass", {8, 0, 80}, "multiplicity percentile for bin"}; + + // events + 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"}; + + // Configs for track + Configurable cfgCutPt{"cfgCutPt", 0.2, "Pt cut on daughter track"}; + Configurable cfgCutEta{"cfgCutEta", 0.8, "Eta cut on daughter track"}; + + // Configs for V0 + Configurable confV0PtMin{"confV0PtMin", 0.f, "Minimum transverse momentum of V0"}; + Configurable confV0PtMax{"confV0PtMax", 1000.f, "Maximum transverse momentum of V0"}; + Configurable confV0Rap{"confV0Rap", 0.8f, "Rapidity range of V0"}; + Configurable confV0DCADaughMax{"confV0DCADaughMax", 1.0f, "Maximum DCA between the V0 daughters"}; + Configurable confV0CPAMin{"confV0CPAMin", 0.9998f, "Minimum CPA of V0"}; + Configurable confV0TranRadV0Min{"confV0TranRadV0Min", 1.5f, "Minimum transverse radius"}; + Configurable confV0TranRadV0Max{"confV0TranRadV0Max", 100.f, "Maximum transverse radius"}; + Configurable cMaxV0DCA{"cMaxV0DCA", 1.2, "Maximum V0 DCA to PV"}; + Configurable cMinV0DCAPr{"cMinV0DCAPr", 0.05, "Minimum V0 daughters DCA to PV for Pr"}; + Configurable cMinV0DCAPi{"cMinV0DCAPi", 0.05, "Minimum V0 daughters DCA to PV for Pi"}; + Configurable cMaxV0LifeTime{"cMaxV0LifeTime", 50, "Maximum V0 life time"}; + + // config for V0 daughters + Configurable confDaughEta{"confDaughEta", 0.8f, "V0 Daugh sel: max eta"}; + Configurable cfgDaughPrPt{"cfgDaughPrPt", 0.2, "minimum daughter proton pt"}; + Configurable cfgDaughPiPt{"cfgDaughPiPt", 0.2, "minimum daughter pion pt"}; + Configurable confDaughTPCnclsMin{"confDaughTPCnclsMin", 50.f, "V0 Daugh sel: Min. nCls TPC"}; + Configurable confDaughPIDCuts{"confDaughPIDCuts", 3, "PID selections for Lambda daughters"}; + + Configurable iMNbins{"iMNbins", 50, "Number of bins in invariant mass"}; + Configurable lbinIM{"lbinIM", 1.09, "lower bin value in IM histograms"}; + Configurable hbinIM{"hbinIM", 1.14, "higher bin value in IM histograms"}; + + HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + RCTFlagsChecker rctChecker; + void init(o2::framework::InitContext&) + { + 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("hLambdaMass", "hLambdaMass", kTH1F, {thnAxisInvMass}); + histos.add("hV0Info", "hV0Info", kTH1F, {{5, 0, 5.0}}); + } + + template + bool selectionV0(Collision const& collision, V0 const& candidate) + { + if (std::abs(candidate.dcav0topv()) > cMaxV0DCA) { + return false; + } + const float pT = candidate.pt(); + const float tranRad = candidate.v0radius(); + const float dcaDaughv0 = std::abs(candidate.dcaV0daughters()); + const float cpav0 = candidate.v0cosPA(); + float ctauLambda = candidate.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * (o2::constants::physics::MassLambda); + + if (pT < confV0PtMin) { + return false; + } + if (pT > confV0PtMax) { + return false; + } + if (dcaDaughv0 > confV0DCADaughMax) { + return false; + } + if (cpav0 < confV0CPAMin) { + return false; + } + if (tranRad < confV0TranRadV0Min) { + return false; + } + if (tranRad > confV0TranRadV0Max) { + return false; + } + if (std::abs(ctauLambda) > cMaxV0LifeTime) { + return false; + } + if (std::abs(candidate.yLambda()) > confV0Rap) { + return false; + } + return true; + } + + template + bool isSelectedV0Daughter(V0 const& candidate, T const& track, int pid) + { + const auto tpcNClsF = track.tpcNClsFound(); + const auto ncr = 70; + const auto ncrfc = 0.8; + + if (track.tpcNClsCrossedRows() < ncr) { + return false; + } + if (tpcNClsF < confDaughTPCnclsMin) { + return false; + } + if (track.tpcCrossedRowsOverFindableCls() < ncrfc) { + return false; + } + + if (pid == 0 && std::abs(track.tpcNSigmaPr()) > confDaughPIDCuts) { + return false; + } + if (pid == 1 && std::abs(track.tpcNSigmaPi()) > confDaughPIDCuts) { + return false; + } + if (pid == 0 && (candidate.positivept() < cfgDaughPrPt || candidate.negativept() < cfgDaughPiPt)) { + return false; + } + if (pid == 1 && (candidate.positivept() < cfgDaughPiPt || candidate.negativept() < cfgDaughPrPt)) { + return false; + } + if (std::abs(candidate.positiveeta()) > confDaughEta || std::abs(candidate.negativeeta()) > confDaughEta) { + return false; + } + + if (pid == 0 && (std::abs(candidate.dcapostopv()) < cMinV0DCAPr || std::abs(candidate.dcanegtopv()) < cMinV0DCAPi)) { + return false; + } + if (pid == 1 && (std::abs(candidate.dcapostopv()) < cMinV0DCAPi || std::abs(candidate.dcanegtopv()) < cMinV0DCAPr)) { + return false; + } + + return true; + } + + std::tuple getLambdaTags(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}; // Invalid candidate + } + + 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}; // No valid tags + } + + if (!selectionV0(collision, v0)) { + return {0, 0, false}; // Fails selection + } + + return {lambdaTag, aLambdaTag, true}; // Valid candidate + } + + ROOT::Math::PxPyPzMVector lambda, antiLambda, proton, pion, antiProton, antiPion; + ROOT::Math::PxPyPzMVector lambdaDummy, pionDummy, protonDummy; + + Filter collisionFilter = nabs(aod::collision::posZ) < cfgCutVertex; + Filter centralityFilter = (nabs(aod::cent::centFT0C) < cfgCutCentralityMax && nabs(aod::cent::centFT0C) > cfgCutCentralityMin); + + using EventCandidates = soa::Filtered>; + using AllTrackCandidates = soa::Join; + using ResoV0s = aod::V0Datas; + + void processData(EventCandidates::iterator const& collision, AllTrackCandidates const&, ResoV0s const& V0s) + { + // LOGF(info, "event collisions: (%d)", collision.index()); + auto centrality = collision.centFT0C(); + int occupancy = collision.trackOccupancyInTimeRange(); + histos.fill(HIST("hEvtSelInfo"), 0.5); + if ((rctCut.requireRCTFlagChecker && rctChecker(collision)) && collision.selection_bit(aod::evsel::kNoSameBunchPileup) && collision.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV) && collision.selection_bit(aod::evsel::kNoTimeFrameBorder) && collision.selection_bit(aod::evsel::kNoITSROFrameBorder) && collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard) && collision.sel8() && collision.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll) && occupancy < cfgCutOccupancy) { + histos.fill(HIST("hEvtSelInfo"), 1.5); + 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 = {}; + for (const auto& v0 : V0s) { + // LOGF(info, "v0 index 0 : (%d)", v0.index()); + auto [lambdaTag, aLambdaTag, isValid] = getLambdaTags(v0, collision); + if (isValid) { + // LOGF(info, "v0 index 1 : (%d)", v0.index()); + 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() - 1.1154) < std::abs(v0.mAntiLambda() - 1.1154)) { + 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); + } + // LOGF(info, "v0 index2: (%d)", v0.index()); + auto postrack1 = v0.template posTrack_as(); + auto negtrack1 = v0.template negTrack_as(); + 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"), lambda.M()); + } + } + } + if (v0Status.size() > 1) { + histos.fill(HIST("hEvtSelInfo"), 2.5); + spinCorrEvent(centrality, collision.posZ()); + auto indexEvent = spinCorrEvent.lastIndex(); + //// Fill track table for V0////////////////// + 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); + spinCorrPair(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, processData, "Process data", true); +}; +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} From a832ad89ac0181fc2ac8ce7603f9750a4f28f411 Mon Sep 17 00:00:00 2001 From: Marcello Di Costanzo <96481191+Marcellocosti@users.noreply.github.com> Date: Thu, 19 Jun 2025 01:46:24 +0200 Subject: [PATCH 138/871] [PWGHF] Implement gen and reco MC matching for correlated bkg decays (#11418) Co-authored-by: ALICE Action Bot --- PWGHF/Core/DecayChannels.h | 18 +- .../DataModel/CandidateReconstructionTables.h | 5 + .../TableProducer/candidateCreator2Prong.cxx | 177 ++++++--- .../TableProducer/candidateCreator3Prong.cxx | 356 +++++++++++------- PWGHF/TableProducer/candidateCreatorMcGen.cxx | 7 +- PWGHF/TableProducer/treeCreatorD0ToKPi.cxx | 35 +- .../TableProducer/treeCreatorDplusToPiKPi.cxx | 17 +- PWGHF/Utils/utilsMcGen.h | 273 ++++++++++---- PWGHF/Utils/utilsMcMatching.h | 268 +++++++++++++ 9 files changed, 865 insertions(+), 291 deletions(-) create mode 100644 PWGHF/Utils/utilsMcMatching.h diff --git a/PWGHF/Core/DecayChannels.h b/PWGHF/Core/DecayChannels.h index 44fefb4eeff..986ad0b0c88 100644 --- a/PWGHF/Core/DecayChannels.h +++ b/PWGHF/Core/DecayChannels.h @@ -71,7 +71,13 @@ enum DecayChannelMain : int8_t { DsToPiPiPi, // π+ π− π+ DsToPiPiPiPi0, // π+ π− π+ π0 // D*+ - DstarToPiKPi, // π+ K− π+ (from [(D0 → π+ K−) π+]) + DstarToPiKPi, // π+ K− π+ (from [(D0 → π+ K−) π+]) + DstarToPiKPiPi0, // π+ K− π+ π0 + DstarToPiKPiPi0Pi0, // π+ K− π+ π0 π0 + DstarToPiKK, // π+ K− K+ + DstarToPiKKPi0, // π+ K− K+ π0 + DstarToPiPiPi, // π+ π− π+ + DstarToPiPiPiPi0, // π+ π− π+ π0 // Λc+ LcToPKPi, // p K− π+ LcToPKPiPi0, // p K− π+ π0 @@ -102,6 +108,16 @@ enum DecayChannelResonant : int8_t { DsToF2_1270Pi, // f2(1270) π+ DsToF0_1370K, // f0(1370) K+ DsToEtaPi, // η π+ + // D*+ + DstarToD0ToRhoplusPi, // ρ+ π− + DstarToD0ToRhoplusK, // ρ+ K− + DstarToD0ToKstar0Pi0, // anti-K*0 π0 + DstarToD0ToKstarPi, // K*− π+ + DstarToDplusToPhiPi, // φ π+ + DstarToDplusToKstar0K, // anti-K*0 K+ + DstarToDplusToKstar1430_0K, // anti-K*0(1430) K+ + DstarToDplusToRho0Pi, // ρ0 π+ + DstarToDplusToF2_1270Pi, // f2(1270) π+ // Λc+ LcToPKstar0, // p K*0(892) LcToDeltaplusplusK, // Δ++ K− diff --git a/PWGHF/DataModel/CandidateReconstructionTables.h b/PWGHF/DataModel/CandidateReconstructionTables.h index a32a88e1d12..0365c5333d9 100644 --- a/PWGHF/DataModel/CandidateReconstructionTables.h +++ b/PWGHF/DataModel/CandidateReconstructionTables.h @@ -641,6 +641,9 @@ DECLARE_SOA_COLUMN(FlagMcMatchRec, flagMcMatchRec, int8_t); //! reconstruction l DECLARE_SOA_COLUMN(FlagMcMatchGen, flagMcMatchGen, int8_t); //! generator level DECLARE_SOA_COLUMN(OriginMcRec, originMcRec, int8_t); //! particle origin, reconstruction level DECLARE_SOA_COLUMN(OriginMcGen, originMcGen, int8_t); //! particle origin, generator level +DECLARE_SOA_COLUMN(FlagMcDecayChanRec, flagMcDecayChanRec, int8_t); //! resonant decay channel flag, reconstruction level +DECLARE_SOA_COLUMN(FlagMcDecayChanGen, flagMcDecayChanGen, int8_t); //! resonant decay channel flag, reconstruction level + // KF related properties DECLARE_SOA_COLUMN(KfGeoMassD0, kfGeoMassD0, float); //! mass of the D0 candidate from the KFParticle geometric fit DECLARE_SOA_COLUMN(KfGeoMassD0bar, kfGeoMassD0bar, float); //! mass of the D0bar candidate from the KFParticle geometric fit @@ -754,6 +757,7 @@ DECLARE_SOA_TABLE(HfCand2ProngKF, "AOD", "HFCAND2PKF", DECLARE_SOA_TABLE(HfCand2ProngMcRec, "AOD", "HFCAND2PMCREC", //! hf_cand_2prong::FlagMcMatchRec, hf_cand_2prong::OriginMcRec, + hf_cand_2prong::FlagMcDecayChanRec, hf_cand::PtBhadMotherPart, hf_cand::PdgBhadMotherPart, hf_cand::NTracksDecayed, @@ -763,6 +767,7 @@ DECLARE_SOA_TABLE(HfCand2ProngMcRec, "AOD", "HFCAND2PMCREC", //! DECLARE_SOA_TABLE(HfCand2ProngMcGen, "AOD", "HFCAND2PMCGEN", //! hf_cand_2prong::FlagMcMatchGen, hf_cand_2prong::OriginMcGen, + hf_cand_2prong::FlagMcDecayChanGen, hf_cand::IdxBhadMotherPart); // cascade decay candidate table diff --git a/PWGHF/TableProducer/candidateCreator2Prong.cxx b/PWGHF/TableProducer/candidateCreator2Prong.cxx index d551922b7d5..7396a0b6f0f 100644 --- a/PWGHF/TableProducer/candidateCreator2Prong.cxx +++ b/PWGHF/TableProducer/candidateCreator2Prong.cxx @@ -20,45 +20,48 @@ #define HomogeneousField // o2-linter: disable=name/macro (required by KFParticle) #endif -#include -#include -#include - -#include -#include -#include -#include -#include +#include "PWGHF/Core/CentralityEstimation.h" +#include "PWGHF/Core/DecayChannels.h" +#include "PWGHF/Core/SelectorCuts.h" +#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "PWGHF/Utils/utilsBfieldCCDB.h" +#include "PWGHF/Utils/utilsEvSelHf.h" +#include "PWGHF/Utils/utilsMcGen.h" +#include "PWGHF/Utils/utilsMcMatching.h" +#include "PWGHF/Utils/utilsPid.h" +#include "PWGHF/Utils/utilsTrkCandHf.h" +#include "PWGLF/DataModel/mcCentrality.h" -#include +#include "Common/Core/trackUtilities.h" +#include "Tools/KFparticle/KFUtilities.h" #include "CommonConstants/PhysicsConstants.h" #include "DCAFitter/DCAFitterN.h" #include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" #include "Framework/RunningWorkflowInfo.h" +#include "Framework/runDataProcessing.h" #include "ReconstructionDataFormats/DCA.h" -#include "Common/Core/trackUtilities.h" -#include "Tools/KFparticle/KFUtilities.h" +#include -#include "PWGLF/DataModel/mcCentrality.h" +#include +#include +#include +#include +#include -#include "PWGHF/Core/CentralityEstimation.h" -#include "PWGHF/Core/SelectorCuts.h" -#include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/Utils/utilsBfieldCCDB.h" -#include "PWGHF/Utils/utilsEvSelHf.h" -#include "PWGHF/Utils/utilsMcGen.h" -#include "PWGHF/Utils/utilsPid.h" -#include "PWGHF/Utils/utilsTrkCandHf.h" +#include +#include +#include using namespace o2; using namespace o2::analysis; using namespace o2::hf_evsel; using namespace o2::hf_trkcandsel; using namespace o2::aod::hf_cand_2prong; +using namespace o2::hf_decay; +using namespace o2::hf_decay::hf_cand_2prong; using namespace o2::hf_centrality; using namespace o2::hf_occupancy; using namespace o2::constants::physics; @@ -691,6 +694,7 @@ struct HfCandidateCreator2ProngExpressions { Configurable rejectBackground{"rejectBackground", true, "Reject particles from background events"}; Configurable matchKinkedDecayTopology{"matchKinkedDecayTopology", false, "Match also candidates with tracks that decay with kinked topology"}; Configurable matchInteractionsWithMaterial{"matchInteractionsWithMaterial", false, "Match also candidates with tracks that interact with material"}; + Configurable matchCorrelatedBackgrounds{"matchCorrelatedBackgrounds", false, "Match correlated background candidates"}; HfEventSelectionMc hfEvSelMc; // mc event selection and monitoring @@ -738,15 +742,18 @@ struct HfCandidateCreator2ProngExpressions { int indexRec = -1; int8_t sign = 0; int8_t flag = 0; + int8_t channel = 0; int8_t origin = 0; int8_t nKinkedTracks = 0; int8_t nInteractionsWithMaterial = 0; + constexpr std::size_t NDaughtersResonant{2u}; // Match reconstructed candidates. // Spawned table can be used directly for (const auto& candidate : *rowCandidateProng2) { flag = 0; origin = 0; + channel = 0; auto arrayDaughters = std::array{candidate.prong0_as(), candidate.prong1_as()}; // Check whether the particle is from background events. If so, reject it. @@ -762,47 +769,107 @@ struct HfCandidateCreator2ProngExpressions { } } if (fromBkg) { - rowMcMatchRec(flag, origin, -1.f, 0, 0, 0); + rowMcMatchRec(flag, origin, channel, -1.f, 0, 0, 0); continue; } } std::vector idxBhadMothers{}; - // D0(bar) → π± K∓ - if (matchKinkedDecayTopology && matchInteractionsWithMaterial) { - indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kD0, std::array{+kPiPlus, -kKPlus}, true, &sign, 1, &nKinkedTracks, &nInteractionsWithMaterial); - } else if (matchKinkedDecayTopology && !matchInteractionsWithMaterial) { - indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kD0, std::array{+kPiPlus, -kKPlus}, true, &sign, 1, &nKinkedTracks); - } else if (!matchKinkedDecayTopology && matchInteractionsWithMaterial) { - indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kD0, std::array{+kPiPlus, -kKPlus}, true, &sign, 1, nullptr, &nInteractionsWithMaterial); - } else { - indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kD0, std::array{+kPiPlus, -kKPlus}, true, &sign); - } - if (indexRec > -1) { - flag = sign * (1 << DecayType::D0ToPiK); - } + if (matchCorrelatedBackgrounds) { + indexRec = -1; // Index of the matched reconstructed candidate + constexpr int FinalStateDepth = 2; + constexpr int ResoDepth = 1; + + // D0(bar) → π+ K−, π+ K− π0, π+ π−, π+ π− π0, K+ K− + for (const auto& [chn, finalState] : hf_cand_2prong::daughtersD0Main) { + std::array finalStateParts2Prong = std::array{finalState[0], finalState[1]}; + if (finalState.size() == 3) { // o2-linter: disable=magic-number (Partly Reco 3-prong decays) + if (matchKinkedDecayTopology && matchInteractionsWithMaterial) { + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kD0, finalStateParts2Prong, true, &sign, FinalStateDepth, &nKinkedTracks, &nInteractionsWithMaterial); + } else if (matchKinkedDecayTopology && !matchInteractionsWithMaterial) { + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kD0, finalStateParts2Prong, true, &sign, FinalStateDepth, &nKinkedTracks); + } else if (!matchKinkedDecayTopology && matchInteractionsWithMaterial) { + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kD0, finalStateParts2Prong, true, &sign, FinalStateDepth, nullptr, &nInteractionsWithMaterial); + } else { + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kD0, finalStateParts2Prong, true, &sign, FinalStateDepth); + } - // J/ψ → e+ e− - if (flag == 0) { - if (matchInteractionsWithMaterial) { - indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kJPsi, std::array{+kElectron, -kElectron}, true, &sign, 1, nullptr, &nInteractionsWithMaterial); + if (indexRec > -1) { + auto motherParticle = mcParticles.rawIteratorAt(indexRec); + std::array finalStateParts2ProngAll = std::array{finalState[0], finalState[1], finalState[2]}; + changeFinalStatePdgSign(motherParticle.pdgCode(), +kPi0, finalStateParts2ProngAll); + if (!RecoDecay::isMatchedMCGen(mcParticles, motherParticle, Pdg::kD0, finalStateParts2ProngAll, true, &sign, FinalStateDepth)) { + indexRec = -1; // Reset indexRec if the generated decay does not match the reconstructed one does not match the reconstructed one + } + } + } else if (finalState.size() == 2) { // o2-linter: disable=magic-number (Fully Reco 2-prong decays) + if (matchKinkedDecayTopology && matchInteractionsWithMaterial) { + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kD0, finalStateParts2Prong, true, &sign, FinalStateDepth, &nKinkedTracks, &nInteractionsWithMaterial); + } else if (matchKinkedDecayTopology && !matchInteractionsWithMaterial) { + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kD0, finalStateParts2Prong, true, &sign, FinalStateDepth, &nKinkedTracks); + } else if (!matchKinkedDecayTopology && matchInteractionsWithMaterial) { + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kD0, finalStateParts2Prong, true, &sign, FinalStateDepth, nullptr, &nInteractionsWithMaterial); + } else { + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kD0, finalStateParts2Prong, true, &sign, FinalStateDepth); + } + } else { + LOG(fatal) << "Final state size not supported: " << finalState.size(); + continue; + } + if (indexRec > -1) { + flag = sign * (1 << chn); + + // Flag the resonant decay channel + std::vector arrResoDaughIndex = {}; + RecoDecay::getDaughters(mcParticles.rawIteratorAt(indexRec), &arrResoDaughIndex, std::array{0}, ResoDepth); + std::array arrPDGDaugh = {}; + if (arrResoDaughIndex.size() == NDaughtersResonant) { + for (auto iProng = 0u; iProng < arrResoDaughIndex.size(); ++iProng) { + auto daughI = mcParticles.rawIteratorAt(arrResoDaughIndex[iProng]); + arrPDGDaugh[iProng] = daughI.pdgCode(); + } + channel = flagResonantDecay(Pdg::kD0, arrPDGDaugh); + } + break; + } + } + } else { + // D0(bar) → π± K∓ + if (matchKinkedDecayTopology && matchInteractionsWithMaterial) { + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kD0, std::array{+kPiPlus, -kKPlus}, true, &sign, 1, &nKinkedTracks, &nInteractionsWithMaterial); + } else if (matchKinkedDecayTopology && !matchInteractionsWithMaterial) { + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kD0, std::array{+kPiPlus, -kKPlus}, true, &sign, 1, &nKinkedTracks); + } else if (!matchKinkedDecayTopology && matchInteractionsWithMaterial) { + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kD0, std::array{+kPiPlus, -kKPlus}, true, &sign, 1, nullptr, &nInteractionsWithMaterial); } else { - indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kJPsi, std::array{+kElectron, -kElectron}, true); + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kD0, std::array{+kPiPlus, -kKPlus}, true, &sign); } if (indexRec > -1) { - flag = 1 << DecayType::JpsiToEE; + flag = sign * (1 << DecayType::D0ToPiK); } - } - // J/ψ → μ+ μ− - if (flag == 0) { - if (matchInteractionsWithMaterial) { - indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kJPsi, std::array{+kMuonPlus, -kMuonPlus}, true, &sign, 1, nullptr, &nInteractionsWithMaterial); - } else { - indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kJPsi, std::array{+kMuonPlus, -kMuonPlus}, true); + // J/ψ → e+ e− + if (flag == 0) { + if (matchInteractionsWithMaterial) { + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kJPsi, std::array{+kElectron, -kElectron}, true, &sign, 1, nullptr, &nInteractionsWithMaterial); + } else { + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kJPsi, std::array{+kElectron, -kElectron}, true); + } + if (indexRec > -1) { + flag = 1 << DecayType::JpsiToEE; + } } - if (indexRec > -1) { - flag = 1 << DecayType::JpsiToMuMu; + + // J/ψ → μ+ μ− + if (flag == 0) { + if (matchInteractionsWithMaterial) { + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kJPsi, std::array{+kMuonPlus, -kMuonPlus}, true, &sign, 1, nullptr, &nInteractionsWithMaterial); + } else { + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kJPsi, std::array{+kMuonPlus, -kMuonPlus}, true); + } + if (indexRec > -1) { + flag = 1 << DecayType::JpsiToMuMu; + } } } @@ -813,9 +880,9 @@ struct HfCandidateCreator2ProngExpressions { } if (origin == RecoDecay::OriginType::NonPrompt) { auto bHadMother = mcParticles.rawIteratorAt(idxBhadMothers[0]); - rowMcMatchRec(flag, origin, bHadMother.pt(), bHadMother.pdgCode(), nKinkedTracks, nInteractionsWithMaterial); + rowMcMatchRec(flag, origin, channel, bHadMother.pt(), bHadMother.pdgCode(), nKinkedTracks, nInteractionsWithMaterial); } else { - rowMcMatchRec(flag, origin, -1.f, 0, nKinkedTracks, nInteractionsWithMaterial); + rowMcMatchRec(flag, origin, channel, -1.f, 0, nKinkedTracks, nInteractionsWithMaterial); } } @@ -842,11 +909,11 @@ struct HfCandidateCreator2ProngExpressions { if (rejectionMask != 0) { // at least one event selection not satisfied --> reject all particles from this collision for (unsigned int i = 0; i < mcParticlesPerMcColl.size(); ++i) { - rowMcMatchGen(0, 0, -1); + rowMcMatchGen(0, 0, 0, -1); } continue; } - hf_mc_gen::fillMcMatchGen2Prong(mcParticles, mcParticlesPerMcColl, rowMcMatchGen, rejectBackground); + hf_mc_gen::fillMcMatchGen2Prong(mcParticles, mcParticlesPerMcColl, rowMcMatchGen, rejectBackground, matchCorrelatedBackgrounds); } } diff --git a/PWGHF/TableProducer/candidateCreator3Prong.cxx b/PWGHF/TableProducer/candidateCreator3Prong.cxx index 145e84513db..3460ff0a8a3 100644 --- a/PWGHF/TableProducer/candidateCreator3Prong.cxx +++ b/PWGHF/TableProducer/candidateCreator3Prong.cxx @@ -19,45 +19,46 @@ #define HomogeneousField // o2-linter: disable=name/macro (required by KFParticle) #endif -#include -#include -#include -#include - -#include -#include -#include -#include -#include +#include "PWGHF/Core/CentralityEstimation.h" +#include "PWGHF/Core/DecayChannels.h" +#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "PWGHF/Utils/utilsBfieldCCDB.h" +#include "PWGHF/Utils/utilsEvSelHf.h" +#include "PWGHF/Utils/utilsMcGen.h" +#include "PWGHF/Utils/utilsMcMatching.h" +#include "PWGHF/Utils/utilsPid.h" +#include "PWGHF/Utils/utilsTrkCandHf.h" +#include "PWGLF/DataModel/mcCentrality.h" -#include +#include "Common/Core/trackUtilities.h" +#include "Tools/KFparticle/KFUtilities.h" #include "CommonConstants/PhysicsConstants.h" #include "DCAFitter/DCAFitterN.h" #include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" #include "Framework/RunningWorkflowInfo.h" +#include "Framework/runDataProcessing.h" #include "ReconstructionDataFormats/DCA.h" -#include "Common/Core/trackUtilities.h" -#include "Tools/KFparticle/KFUtilities.h" +#include -#include "PWGLF/DataModel/mcCentrality.h" +#include +#include +#include +#include +#include -#include "PWGHF/Core/CentralityEstimation.h" -#include "PWGHF/Core/DecayChannels.h" -#include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/Utils/utilsBfieldCCDB.h" -#include "PWGHF/Utils/utilsEvSelHf.h" -#include "PWGHF/Utils/utilsMcGen.h" -#include "PWGHF/Utils/utilsPid.h" -#include "PWGHF/Utils/utilsTrkCandHf.h" +#include +#include +#include +#include using namespace o2; using namespace o2::hf_evsel; using namespace o2::hf_trkcandsel; using namespace o2::aod::hf_cand_3prong; +using namespace o2::hf_decay; using namespace o2::hf_decay::hf_cand_3prong; using namespace o2::hf_centrality; using namespace o2::hf_occupancy; @@ -850,6 +851,8 @@ struct HfCandidateCreator3ProngExpressions { Configurable rejectBackground{"rejectBackground", true, "Reject particles from background events"}; Configurable matchKinkedDecayTopology{"matchKinkedDecayTopology", false, "Match also candidates with tracks that decay with kinked topology"}; Configurable matchInteractionsWithMaterial{"matchInteractionsWithMaterial", false, "Match also candidates with tracks that interact with material"}; + Configurable matchCorrelatedBackgrounds{"matchCorrelatedBackgrounds", false, "Match correlated background candidates"}; + Configurable> mothersCorrBkgsPdgs{"mothersCorrBkgsPdgs", {Pdg::kDPlus, Pdg::kDS, Pdg::kDStar, Pdg::kLambdaCPlus, Pdg::kXiCPlus}, "PDG codes of the mother particles of correlated background candidates"}; constexpr static std::size_t NDaughtersResonant{2u}; @@ -904,13 +907,14 @@ struct HfCandidateCreator3ProngExpressions { int8_t channel = 0; int8_t nKinkedTracks = 0; int8_t nInteractionsWithMaterial = 0; + constexpr std::size_t NDaughtersResonant{2u}; std::vector arrDaughIndex; - std::array arrPDGDaugh; - std::array arrPDGResonant1 = {kProton, 313}; // Λc± → p± K* - std::array arrPDGResonant2 = {2224, kKPlus}; // Λc± → Δ(1232)±± K∓ - std::array arrPDGResonant3 = {102134, kPiPlus}; // Λc± → Λ(1520) π± - std::array arrPDGResonantDPhiPi = {333, kPiPlus}; // Ds± → Phi π± and D± → Phi π± - std::array arrPDGResonantDKstarK = {313, kKPlus}; // Ds± → K*(892)0bar K± and D± → K*(892)0bar K± + std::array arrPDGDaugh; + std::array arrPDGResonant1 = {kProton, 313}; // Λc± → p± K* + std::array arrPDGResonant2 = {2224, kKPlus}; // Λc± → Δ(1232)±± K∓ + std::array arrPDGResonant3 = {102134, kPiPlus}; // Λc± → Λ(1520) π± + std::array arrPDGResonantDPhiPi = {333, kPiPlus}; // Ds± → Phi π± and D± → Phi π± + std::array arrPDGResonantDKstarK = {313, kKPlus}; // Ds± → K*(892)0bar K± and D± → K*(892)0bar K± // Match reconstructed candidates. // Spawned table can be used directly @@ -919,6 +923,7 @@ struct HfCandidateCreator3ProngExpressions { origin = 0; swapping = 0; channel = 0; + indexRec = -1; arrDaughIndex.clear(); std::vector idxBhadMothers{}; auto arrayDaughters = std::array{candidate.prong0_as(), candidate.prong1_as(), candidate.prong2_as()}; @@ -941,129 +946,218 @@ struct HfCandidateCreator3ProngExpressions { } } - // D± → π± K∓ π± - if (flag == 0) { - if (matchKinkedDecayTopology && matchInteractionsWithMaterial) { - indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kDPlus, std::array{+kPiPlus, -kKPlus, +kPiPlus}, true, &sign, 2, &nKinkedTracks, &nInteractionsWithMaterial); - } else if (matchKinkedDecayTopology && !matchInteractionsWithMaterial) { - indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kDPlus, std::array{+kPiPlus, -kKPlus, +kPiPlus}, true, &sign, 2, &nKinkedTracks); - } else if (!matchKinkedDecayTopology && matchInteractionsWithMaterial) { - indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kDPlus, std::array{+kPiPlus, -kKPlus, +kPiPlus}, true, &sign, 2, nullptr, &nInteractionsWithMaterial); - } else { - indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kDPlus, std::array{+kPiPlus, -kKPlus, +kPiPlus}, true, &sign, 2); - } - if (indexRec > -1) { - flag = sign * DecayChannelMain::DplusToPiKPi; - } - } + if (matchCorrelatedBackgrounds) { + indexRec = -1; // Index of the matched reconstructed candidate + constexpr int MaxDepth = 2; // Depth for final state matching + constexpr int ResoMaxDepth = 1; // Depth for resonant decay matching - // Ds± → K± K∓ π± and D± → K± K∓ π± - if (flag == 0) { - bool isDplus = false; - if (matchKinkedDecayTopology && matchInteractionsWithMaterial) { - indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kDS, std::array{+kKPlus, -kKPlus, +kPiPlus}, true, &sign, 2, &nKinkedTracks, &nInteractionsWithMaterial); - } else if (matchKinkedDecayTopology && !matchInteractionsWithMaterial) { - indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kDS, std::array{+kKPlus, -kKPlus, +kPiPlus}, true, &sign, 2, &nKinkedTracks); - } else if (!matchKinkedDecayTopology && matchInteractionsWithMaterial) { - indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kDS, std::array{+kKPlus, -kKPlus, +kPiPlus}, true, &sign, 2, nullptr, &nInteractionsWithMaterial); - } else { - indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kDS, std::array{+kKPlus, -kKPlus, +kPiPlus}, true, &sign, 2); + for (const auto& pdg : mothersCorrBkgsPdgs.value) { + int depth = MaxDepth; + if (pdg == Pdg::kDStar) { + depth = MaxDepth + 1; // D0 resonant decays are active + } + auto finalStates = getDecayChannelMain(pdg); + for (const auto& [chn, finalState] : finalStates) { + std::array finalStateParts3Prong = std::array{finalState[0], finalState[1], finalState[2]}; + if (finalState.size() > 3) { // o2-linter: disable=magic-number (Partly Reco decays with 4 or 5 final state particles) + if (matchKinkedDecayTopology && matchInteractionsWithMaterial) { + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, pdg, finalStateParts3Prong, true, &sign, depth, &nKinkedTracks, &nInteractionsWithMaterial); + } else if (matchKinkedDecayTopology && !matchInteractionsWithMaterial) { + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, pdg, finalStateParts3Prong, true, &sign, depth, &nKinkedTracks); + } else if (!matchKinkedDecayTopology && matchInteractionsWithMaterial) { + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, pdg, finalStateParts3Prong, true, &sign, depth, nullptr, &nInteractionsWithMaterial); + } else { + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, pdg, finalStateParts3Prong, true, &sign, depth); + } + + if (indexRec > -1) { + auto motherParticle = mcParticles.rawIteratorAt(indexRec); + if (finalState.size() == 4) { // o2-linter: disable=magic-number (Check if the final state has 4 particles) + std::array finalStateParts3ProngAll = std::array{finalState[0], finalState[1], finalState[2], finalState[3]}; + changeFinalStatePdgSign(motherParticle.pdgCode(), +kPi0, finalStateParts3ProngAll); + if (!RecoDecay::isMatchedMCGen(mcParticles, motherParticle, pdg, finalStateParts3ProngAll, true, &sign, depth)) { + indexRec = -1; // Reset indexRec if the generated decay does not match the reconstructed one is not matched + } + } else if (finalState.size() == 5) { // o2-linter: disable=magic-number (Check if the final state has 5 particles) + std::array finalStateParts3ProngAll = std::array{finalState[0], finalState[1], finalState[2], finalState[3], finalState[4]}; + changeFinalStatePdgSign(motherParticle.pdgCode(), +kPi0, finalStateParts3ProngAll); + if (!RecoDecay::isMatchedMCGen(mcParticles, motherParticle, pdg, finalStateParts3ProngAll, true, &sign, depth)) { + indexRec = -1; // Reset indexRec if the generated decay does not match the reconstructed one is not matched + } + } + } + } else if (finalState.size() == 3) { // o2-linter: disable=magic-number(Fully Reco 3-prong decays) + if (matchKinkedDecayTopology && matchInteractionsWithMaterial) { + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, pdg, finalStateParts3Prong, true, &sign, depth, &nKinkedTracks, &nInteractionsWithMaterial); + } else if (matchKinkedDecayTopology && !matchInteractionsWithMaterial) { + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, pdg, finalStateParts3Prong, true, &sign, depth, &nKinkedTracks); + } else if (!matchKinkedDecayTopology && matchInteractionsWithMaterial) { + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, pdg, finalStateParts3Prong, true, &sign, depth, nullptr, &nInteractionsWithMaterial); + } else { + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, pdg, finalStateParts3Prong, true, &sign, depth); + } + } else { + LOG(fatal) << "Final state size not supported: " << finalState.size(); + continue; // Skip unsupported final states + } + if (indexRec > -1) { + flag = sign * chn; + + // Flag the resonant decay channel + std::vector arrResoDaughIndex = {}; + if (pdg == Pdg::kDStar) { + std::vector arrResoDaughIndexDStar = {}; + RecoDecay::getDaughters(mcParticles.rawIteratorAt(indexRec), &arrResoDaughIndexDStar, std::array{0}, ResoMaxDepth); + for (size_t iDaug = 0; iDaug < arrResoDaughIndexDStar.size(); iDaug++) { + auto daughDstar = mcParticles.rawIteratorAt(arrResoDaughIndexDStar[iDaug]); + if (std::abs(daughDstar.pdgCode()) == Pdg::kD0 || std::abs(daughDstar.pdgCode()) == Pdg::kDPlus) { + RecoDecay::getDaughters(daughDstar, &arrResoDaughIndex, std::array{0}, ResoMaxDepth); + break; + } + } + } else { + RecoDecay::getDaughters(mcParticles.rawIteratorAt(indexRec), &arrResoDaughIndex, std::array{0}, ResoMaxDepth); + } + std::array arrPDGDaugh = {}; + if (arrResoDaughIndex.size() == NDaughtersResonant) { + for (auto iProng = 0u; iProng < NDaughtersResonant; ++iProng) { + auto daughI = mcParticles.rawIteratorAt(arrResoDaughIndex[iProng]); + arrPDGDaugh[iProng] = daughI.pdgCode(); + } + channel = flagResonantDecay(pdg, arrPDGDaugh); + } + break; // Exit loop if a match is found + } + } + if (indexRec > -1) { + break; // Exit loop if a match is found + } } - if (indexRec == -1) { - isDplus = true; + } else { + // D± → π± K∓ π± + if (flag == 0) { if (matchKinkedDecayTopology && matchInteractionsWithMaterial) { - indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kDPlus, std::array{+kKPlus, -kKPlus, +kPiPlus}, true, &sign, 2, &nKinkedTracks, &nInteractionsWithMaterial); + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kDPlus, std::array{+kPiPlus, -kKPlus, +kPiPlus}, true, &sign, 2, &nKinkedTracks, &nInteractionsWithMaterial); } else if (matchKinkedDecayTopology && !matchInteractionsWithMaterial) { - indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kDPlus, std::array{+kKPlus, -kKPlus, +kPiPlus}, true, &sign, 2, &nKinkedTracks); + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kDPlus, std::array{+kPiPlus, -kKPlus, +kPiPlus}, true, &sign, 2, &nKinkedTracks); } else if (!matchKinkedDecayTopology && matchInteractionsWithMaterial) { - indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kDPlus, std::array{+kKPlus, -kKPlus, +kPiPlus}, true, &sign, 2, nullptr, &nInteractionsWithMaterial); + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kDPlus, std::array{+kPiPlus, -kKPlus, +kPiPlus}, true, &sign, 2, nullptr, &nInteractionsWithMaterial); } else { - indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kDPlus, std::array{+kKPlus, -kKPlus, +kPiPlus}, true, &sign, 2); + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kDPlus, std::array{+kPiPlus, -kKPlus, +kPiPlus}, true, &sign, 2); + } + if (indexRec > -1) { + flag = sign * DecayChannelMain::DplusToPiKPi; } } - if (indexRec > -1) { - flag = sign * (isDplus ? DecayChannelMain::DplusToPiKK : DecayChannelMain::DsToPiKK); - if (arrayDaughters[0].has_mcParticle()) { - swapping = int8_t(std::abs(arrayDaughters[0].mcParticle().pdgCode()) == kPiPlus); + + // Ds± → K± K∓ π± and D± → K± K∓ π± + if (flag == 0) { + bool isDplus = false; + if (matchKinkedDecayTopology && matchInteractionsWithMaterial) { + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kDS, std::array{+kKPlus, -kKPlus, +kPiPlus}, true, &sign, 2, &nKinkedTracks, &nInteractionsWithMaterial); + } else if (matchKinkedDecayTopology && !matchInteractionsWithMaterial) { + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kDS, std::array{+kKPlus, -kKPlus, +kPiPlus}, true, &sign, 2, &nKinkedTracks); + } else if (!matchKinkedDecayTopology && matchInteractionsWithMaterial) { + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kDS, std::array{+kKPlus, -kKPlus, +kPiPlus}, true, &sign, 2, nullptr, &nInteractionsWithMaterial); + } else { + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kDS, std::array{+kKPlus, -kKPlus, +kPiPlus}, true, &sign, 2); + } + if (indexRec == -1) { + isDplus = true; + if (matchKinkedDecayTopology && matchInteractionsWithMaterial) { + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kDPlus, std::array{+kKPlus, -kKPlus, +kPiPlus}, true, &sign, 2, &nKinkedTracks, &nInteractionsWithMaterial); + } else if (matchKinkedDecayTopology && !matchInteractionsWithMaterial) { + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kDPlus, std::array{+kKPlus, -kKPlus, +kPiPlus}, true, &sign, 2, &nKinkedTracks); + } else if (!matchKinkedDecayTopology && matchInteractionsWithMaterial) { + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kDPlus, std::array{+kKPlus, -kKPlus, +kPiPlus}, true, &sign, 2, nullptr, &nInteractionsWithMaterial); + } else { + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kDPlus, std::array{+kKPlus, -kKPlus, +kPiPlus}, true, &sign, 2); + } } - RecoDecay::getDaughters(mcParticles.rawIteratorAt(indexRec), &arrDaughIndex, std::array{0}, 1); - if (arrDaughIndex.size() == NDaughtersResonant) { - for (auto iProng = 0u; iProng < arrDaughIndex.size(); ++iProng) { - auto daughI = mcParticles.rawIteratorAt(arrDaughIndex[iProng]); - arrPDGDaugh[iProng] = std::abs(daughI.pdgCode()); + if (indexRec > -1) { + flag = sign * (isDplus ? DecayChannelMain::DplusToPiKK : DecayChannelMain::DsToPiKK); + if (arrayDaughters[0].has_mcParticle()) { + swapping = int8_t(std::abs(arrayDaughters[0].mcParticle().pdgCode()) == kPiPlus); } - if ((arrPDGDaugh[0] == arrPDGResonantDPhiPi[0] && arrPDGDaugh[1] == arrPDGResonantDPhiPi[1]) || (arrPDGDaugh[0] == arrPDGResonantDPhiPi[1] && arrPDGDaugh[1] == arrPDGResonantDPhiPi[0])) { - channel = isDplus ? DecayChannelResonant::DplusToPhiPi : DecayChannelResonant::DsToPhiPi; - } else if ((arrPDGDaugh[0] == arrPDGResonantDKstarK[0] && arrPDGDaugh[1] == arrPDGResonantDKstarK[1]) || (arrPDGDaugh[0] == arrPDGResonantDKstarK[1] && arrPDGDaugh[1] == arrPDGResonantDKstarK[0])) { - channel = isDplus ? DecayChannelResonant::DplusToKstar0K : DecayChannelResonant::DsToKstar0K; + RecoDecay::getDaughters(mcParticles.rawIteratorAt(indexRec), &arrDaughIndex, std::array{0}, 1); + if (arrDaughIndex.size() == NDaughtersResonant) { + for (auto iProng = 0u; iProng < arrDaughIndex.size(); ++iProng) { + auto daughI = mcParticles.rawIteratorAt(arrDaughIndex[iProng]); + arrPDGDaugh[iProng] = std::abs(daughI.pdgCode()); + } + if ((arrPDGDaugh[0] == arrPDGResonantDPhiPi[0] && arrPDGDaugh[1] == arrPDGResonantDPhiPi[1]) || (arrPDGDaugh[0] == arrPDGResonantDPhiPi[1] && arrPDGDaugh[1] == arrPDGResonantDPhiPi[0])) { + channel = isDplus ? DecayChannelResonant::DplusToPhiPi : DecayChannelResonant::DsToPhiPi; + } else if ((arrPDGDaugh[0] == arrPDGResonantDKstarK[0] && arrPDGDaugh[1] == arrPDGResonantDKstarK[1]) || (arrPDGDaugh[0] == arrPDGResonantDKstarK[1] && arrPDGDaugh[1] == arrPDGResonantDKstarK[0])) { + channel = isDplus ? DecayChannelResonant::DplusToKstar0K : DecayChannelResonant::DsToKstar0K; + } } } } - } - - // D* → D0π → Kππ - if (flag == 0) { - if (matchKinkedDecayTopology) { - indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kDStar, std::array{+kPiPlus, +kPiPlus, -kKPlus}, true, &sign, 2, &nKinkedTracks); - } else { - indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kDStar, std::array{+kPiPlus, +kPiPlus, -kKPlus}, true, &sign, 2); - } - if (indexRec > -1) { - flag = sign * DecayChannelMain::DstarToPiKPi; - channel = 1; - } - } - // Λc± → p± K∓ π± - if (flag == 0) { - if (matchKinkedDecayTopology && matchInteractionsWithMaterial) { - indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kLambdaCPlus, std::array{+kProton, -kKPlus, +kPiPlus}, true, &sign, 2, &nKinkedTracks, &nInteractionsWithMaterial); - } else if (matchKinkedDecayTopology && !matchInteractionsWithMaterial) { - indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kLambdaCPlus, std::array{+kProton, -kKPlus, +kPiPlus}, true, &sign, 2, &nKinkedTracks); - } else if (!matchKinkedDecayTopology && matchInteractionsWithMaterial) { - indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kLambdaCPlus, std::array{+kProton, -kKPlus, +kPiPlus}, true, &sign, 2, nullptr, &nInteractionsWithMaterial); - } else { - indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kLambdaCPlus, std::array{+kProton, -kKPlus, +kPiPlus}, true, &sign, 2); + // D* → D0π → Kππ + if (flag == 0) { + if (matchKinkedDecayTopology) { + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kDStar, std::array{+kPiPlus, +kPiPlus, -kKPlus}, true, &sign, 2, &nKinkedTracks); + } else { + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kDStar, std::array{+kPiPlus, +kPiPlus, -kKPlus}, true, &sign, 2); + } + if (indexRec > -1) { + flag = sign * DecayChannelMain::DstarToPiKPi; + channel = 1; + } } - if (indexRec > -1) { - flag = sign * DecayChannelMain::LcToPKPi; - // Flagging the different Λc± → p± K∓ π± decay channels - if (arrayDaughters[0].has_mcParticle()) { - swapping = int8_t(std::abs(arrayDaughters[0].mcParticle().pdgCode()) == kPiPlus); + // Λc± → p± K∓ π± + if (flag == 0) { + if (matchKinkedDecayTopology && matchInteractionsWithMaterial) { + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kLambdaCPlus, std::array{+kProton, -kKPlus, +kPiPlus}, true, &sign, 2, &nKinkedTracks, &nInteractionsWithMaterial); + } else if (matchKinkedDecayTopology && !matchInteractionsWithMaterial) { + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kLambdaCPlus, std::array{+kProton, -kKPlus, +kPiPlus}, true, &sign, 2, &nKinkedTracks); + } else if (!matchKinkedDecayTopology && matchInteractionsWithMaterial) { + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kLambdaCPlus, std::array{+kProton, -kKPlus, +kPiPlus}, true, &sign, 2, nullptr, &nInteractionsWithMaterial); + } else { + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kLambdaCPlus, std::array{+kProton, -kKPlus, +kPiPlus}, true, &sign, 2); } - RecoDecay::getDaughters(mcParticles.rawIteratorAt(indexRec), &arrDaughIndex, std::array{0}, 1); - if (arrDaughIndex.size() == NDaughtersResonant) { - for (auto iProng = 0u; iProng < arrDaughIndex.size(); ++iProng) { - auto daughI = mcParticles.rawIteratorAt(arrDaughIndex[iProng]); - arrPDGDaugh[iProng] = std::abs(daughI.pdgCode()); + if (indexRec > -1) { + flag = sign * DecayChannelMain::LcToPKPi; + + // Flagging the different Λc± → p± K∓ π± decay channels + if (arrayDaughters[0].has_mcParticle()) { + swapping = int8_t(std::abs(arrayDaughters[0].mcParticle().pdgCode()) == kPiPlus); } - if ((arrPDGDaugh[0] == arrPDGResonant1[0] && arrPDGDaugh[1] == arrPDGResonant1[1]) || (arrPDGDaugh[0] == arrPDGResonant1[1] && arrPDGDaugh[1] == arrPDGResonant1[0])) { - channel = 1; - } else if ((arrPDGDaugh[0] == arrPDGResonant2[0] && arrPDGDaugh[1] == arrPDGResonant2[1]) || (arrPDGDaugh[0] == arrPDGResonant2[1] && arrPDGDaugh[1] == arrPDGResonant2[0])) { - channel = 2; - } else if ((arrPDGDaugh[0] == arrPDGResonant3[0] && arrPDGDaugh[1] == arrPDGResonant3[1]) || (arrPDGDaugh[0] == arrPDGResonant3[1] && arrPDGDaugh[1] == arrPDGResonant3[0])) { - channel = 3; + RecoDecay::getDaughters(mcParticles.rawIteratorAt(indexRec), &arrDaughIndex, std::array{0}, 1); + if (arrDaughIndex.size() == NDaughtersResonant) { + for (auto iProng = 0u; iProng < arrDaughIndex.size(); ++iProng) { + auto daughI = mcParticles.rawIteratorAt(arrDaughIndex[iProng]); + arrPDGDaugh[iProng] = std::abs(daughI.pdgCode()); + } + if ((arrPDGDaugh[0] == arrPDGResonant1[0] && arrPDGDaugh[1] == arrPDGResonant1[1]) || (arrPDGDaugh[0] == arrPDGResonant1[1] && arrPDGDaugh[1] == arrPDGResonant1[0])) { + channel = 1; + } else if ((arrPDGDaugh[0] == arrPDGResonant2[0] && arrPDGDaugh[1] == arrPDGResonant2[1]) || (arrPDGDaugh[0] == arrPDGResonant2[1] && arrPDGDaugh[1] == arrPDGResonant2[0])) { + channel = 2; + } else if ((arrPDGDaugh[0] == arrPDGResonant3[0] && arrPDGDaugh[1] == arrPDGResonant3[1]) || (arrPDGDaugh[0] == arrPDGResonant3[1] && arrPDGDaugh[1] == arrPDGResonant3[0])) { + channel = 3; + } } } } - } - // Ξc± → p± K∓ π± - if (flag == 0) { - if (matchKinkedDecayTopology && matchInteractionsWithMaterial) { - indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kXiCPlus, std::array{+kProton, -kKPlus, +kPiPlus}, true, &sign, 2, &nKinkedTracks, &nInteractionsWithMaterial); - } else if (matchKinkedDecayTopology && !matchInteractionsWithMaterial) { - indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kXiCPlus, std::array{+kProton, -kKPlus, +kPiPlus}, true, &sign, 2, &nKinkedTracks); - } else if (!matchKinkedDecayTopology && matchInteractionsWithMaterial) { - indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kXiCPlus, std::array{+kProton, -kKPlus, +kPiPlus}, true, &sign, 2, nullptr, &nInteractionsWithMaterial); - } else { - indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kXiCPlus, std::array{+kProton, -kKPlus, +kPiPlus}, true, &sign, 2); - } - if (indexRec > -1) { - flag = sign * DecayChannelMain::XicToPKPi; - if (arrayDaughters[0].has_mcParticle()) { - swapping = int8_t(std::abs(arrayDaughters[0].mcParticle().pdgCode()) == kPiPlus); + // Ξc± → p± K∓ π± + if (flag == 0) { + if (matchKinkedDecayTopology && matchInteractionsWithMaterial) { + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kXiCPlus, std::array{+kProton, -kKPlus, +kPiPlus}, true, &sign, 2, &nKinkedTracks, &nInteractionsWithMaterial); + } else if (matchKinkedDecayTopology && !matchInteractionsWithMaterial) { + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kXiCPlus, std::array{+kProton, -kKPlus, +kPiPlus}, true, &sign, 2, &nKinkedTracks); + } else if (!matchKinkedDecayTopology && matchInteractionsWithMaterial) { + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kXiCPlus, std::array{+kProton, -kKPlus, +kPiPlus}, true, &sign, 2, nullptr, &nInteractionsWithMaterial); + } else { + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kXiCPlus, std::array{+kProton, -kKPlus, +kPiPlus}, true, &sign, 2); + } + if (indexRec > -1) { + flag = sign * DecayChannelMain::XicToPKPi; + if (arrayDaughters[0].has_mcParticle()) { + swapping = int8_t(std::abs(arrayDaughters[0].mcParticle().pdgCode()) == kPiPlus); + } } } } @@ -1108,7 +1202,7 @@ struct HfCandidateCreator3ProngExpressions { } continue; } - hf_mc_gen::fillMcMatchGen3Prong(mcParticles, mcParticlesPerMcColl, rowMcMatchGen, rejectBackground); + hf_mc_gen::fillMcMatchGen3Prong(mcParticles, mcParticlesPerMcColl, rowMcMatchGen, rejectBackground, matchCorrelatedBackgrounds ? mothersCorrBkgsPdgs : std::vector{}); } } diff --git a/PWGHF/TableProducer/candidateCreatorMcGen.cxx b/PWGHF/TableProducer/candidateCreatorMcGen.cxx index 3c5f7a2c3c1..8da97722b8b 100644 --- a/PWGHF/TableProducer/candidateCreatorMcGen.cxx +++ b/PWGHF/TableProducer/candidateCreatorMcGen.cxx @@ -31,6 +31,7 @@ using namespace o2; using namespace o2::framework; +using namespace o2::constants::physics; /// Reconstruction of heavy-flavour 2-prong decay candidates struct HfCandidateCreatorMcGen { @@ -41,6 +42,8 @@ struct HfCandidateCreatorMcGen { Produces rowMcMatchGenB0; Configurable fill2Prong{"fill2Prong", false, "fill table for 2 prong candidates"}; Configurable fill3Prong{"fill3Prong", false, "fill table for 3 prong candidates"}; + Configurable matchCorrelatedBackgrounds{"matchCorrelatedBackgrounds", false, "Match correlated background candidates"}; + Configurable> mothersCorrBkgsPdgs{"mothersCorrBkgsPdgs", {Pdg::kDPlus, Pdg::kDS, Pdg::kDStar, Pdg::kLambdaCPlus, Pdg::kXiCPlus}, "PDG codes of the mother particles of correlated background candidates"}; Configurable fillBplus{"fillBplus", false, "fill table for for B+ candidates"}; Configurable fillB0{"fillB0", false, "fill table for B0 candidates"}; Configurable rejectBackground2Prong{"rejectBackground2Prong", false, "Reject particles from PbPb background for 2 prong candidates"}; @@ -55,10 +58,10 @@ struct HfCandidateCreatorMcGen { for (const auto& mcCollision : mcCollisions) { const auto mcParticlesPerMcColl = mcParticles.sliceBy(mcParticlesPerMcCollision, mcCollision.globalIndex()); if (fill2Prong) { - hf_mc_gen::fillMcMatchGen2Prong(mcParticles, mcParticlesPerMcColl, rowMcMatchGen2Prong, rejectBackground2Prong); + hf_mc_gen::fillMcMatchGen2Prong(mcParticles, mcParticlesPerMcColl, rowMcMatchGen2Prong, rejectBackground2Prong, matchCorrelatedBackgrounds); } if (fill3Prong) { - hf_mc_gen::fillMcMatchGen3Prong(mcParticles, mcParticlesPerMcColl, rowMcMatchGen3Prong, rejectBackground3Prong); + hf_mc_gen::fillMcMatchGen3Prong(mcParticles, mcParticlesPerMcColl, rowMcMatchGen3Prong, rejectBackground3Prong, matchCorrelatedBackgrounds ? mothersCorrBkgsPdgs : std::vector{}); } } if (fillBplus) { diff --git a/PWGHF/TableProducer/treeCreatorD0ToKPi.cxx b/PWGHF/TableProducer/treeCreatorD0ToKPi.cxx index 233b1055ea6..59bf26581c5 100644 --- a/PWGHF/TableProducer/treeCreatorD0ToKPi.cxx +++ b/PWGHF/TableProducer/treeCreatorD0ToKPi.cxx @@ -72,6 +72,8 @@ DECLARE_SOA_COLUMN(Ct, ct, float); DECLARE_SOA_COLUMN(ImpactParameterProduct, impactParameterProduct, float); DECLARE_SOA_COLUMN(CosThetaStar, cosThetaStar, float); DECLARE_SOA_COLUMN(FlagMc, flagMc, int8_t); +DECLARE_SOA_COLUMN(FlagMcDecayChanRec, flagMcDecayChanRec, int8_t); +DECLARE_SOA_COLUMN(FlagMcDecayChanGen, flagMcDecayChanGen, int8_t); DECLARE_SOA_COLUMN(OriginMcRec, originMcRec, int8_t); // is prompt or non-prompt, reco level DECLARE_SOA_COLUMN(OriginMcGen, originMcGen, int8_t); // is prompt or non-prompt, Gen level DECLARE_SOA_INDEX_COLUMN_FULL(Candidate, candidate, int, HfCand2Prong, "_0"); @@ -123,6 +125,7 @@ DECLARE_SOA_TABLE(HfCandD0Lites, "AOD", "HFCANDD0LITE", full::Phi, full::Y, full::FlagMc, + full::FlagMcDecayChanRec, full::OriginMcRec) DECLARE_SOA_TABLE(HfCandD0Fulls, "AOD", "HFCANDD0FULL", @@ -185,6 +188,7 @@ DECLARE_SOA_TABLE(HfCandD0Fulls, "AOD", "HFCANDD0FULL", full::Y, full::E, full::FlagMc, + full::FlagMcDecayChanRec, full::OriginMcRec, full::CandidateId); @@ -204,6 +208,7 @@ DECLARE_SOA_TABLE(HfCandD0FullPs, "AOD", "HFCANDD0FULLP", full::Phi, full::Y, full::FlagMc, + full::FlagMcDecayChanGen, full::OriginMcGen, full::McParticleId); @@ -226,6 +231,7 @@ struct HfTreeCreatorD0ToKPi { // parameters for production of training samples 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 fillCorrBkgs{"fillCorrBkgs", false, "Flag to fill derived tables with correlated background candidates"}; HfHelper hfHelper; @@ -237,16 +243,16 @@ struct HfTreeCreatorD0ToKPi { using MatchedGenCandidatesMc = soa::Filtered>; Filter filterSelectCandidates = aod::hf_sel_candidate_d0::isSelD0 >= 1 || aod::hf_sel_candidate_d0::isSelD0bar >= 1; - Filter filterMcGenMatching = nabs(aod::hf_cand_2prong::flagMcMatchGen) == static_cast(BIT(aod::hf_cand_2prong::DecayType::D0ToPiK)); + Filter filterMcGenMatching = nabs(aod::hf_cand_2prong::flagMcMatchGen) == static_cast(BIT(aod::hf_cand_2prong::DecayType::D0ToPiK)) || (fillCorrBkgs && (nabs(aod::hf_cand_2prong::flagMcMatchGen) != 0)); - Partition reconstructedCandSig = nabs(aod::hf_cand_2prong::flagMcMatchRec) == static_cast(BIT(aod::hf_cand_2prong::DecayType::D0ToPiK)); + Partition reconstructedCandSig = nabs(aod::hf_cand_2prong::flagMcMatchRec) == static_cast(BIT(aod::hf_cand_2prong::DecayType::D0ToPiK)) || (fillCorrBkgs && nabs(aod::hf_cand_2prong::flagMcMatchRec) != 0); Partition reconstructedCandBkg = nabs(aod::hf_cand_2prong::flagMcMatchRec) != static_cast(BIT(aod::hf_cand_2prong::DecayType::D0ToPiK)); - Partition reconstructedCandSigKF = nabs(aod::hf_cand_2prong::flagMcMatchRec) == static_cast(BIT(aod::hf_cand_2prong::DecayType::D0ToPiK)); + Partition reconstructedCandSigKF = nabs(aod::hf_cand_2prong::flagMcMatchRec) == static_cast(BIT(aod::hf_cand_2prong::DecayType::D0ToPiK)) || (fillCorrBkgs && nabs(aod::hf_cand_2prong::flagMcMatchRec) != 0); Partition reconstructedCandBkgKF = nabs(aod::hf_cand_2prong::flagMcMatchRec) != static_cast(BIT(aod::hf_cand_2prong::DecayType::D0ToPiK)); - Partition reconstructedCandSigMl = nabs(aod::hf_cand_2prong::flagMcMatchRec) == static_cast(BIT(aod::hf_cand_2prong::DecayType::D0ToPiK)); + Partition reconstructedCandSigMl = nabs(aod::hf_cand_2prong::flagMcMatchRec) == static_cast(BIT(aod::hf_cand_2prong::DecayType::D0ToPiK)) || (fillCorrBkgs && nabs(aod::hf_cand_2prong::flagMcMatchRec) != 0); Partition reconstructedCandBkgMl = nabs(aod::hf_cand_2prong::flagMcMatchRec) != static_cast(BIT(aod::hf_cand_2prong::DecayType::D0ToPiK)); - Partition reconstructedCandSigKFMl = nabs(aod::hf_cand_2prong::flagMcMatchRec) == static_cast(BIT(aod::hf_cand_2prong::DecayType::D0ToPiK)); + Partition reconstructedCandSigKFMl = nabs(aod::hf_cand_2prong::flagMcMatchRec) == static_cast(BIT(aod::hf_cand_2prong::DecayType::D0ToPiK)) || (fillCorrBkgs && nabs(aod::hf_cand_2prong::flagMcMatchRec) != 0); Partition reconstructedCandBkgKFMl = nabs(aod::hf_cand_2prong::flagMcMatchRec) != static_cast(BIT(aod::hf_cand_2prong::DecayType::D0ToPiK)); void init(InitContext const&) @@ -275,7 +281,7 @@ struct HfTreeCreatorD0ToKPi { template auto fillTable(const T& candidate, int candFlag, double invMass, double topoChi2, - double ct, double y, double e, int8_t flagMc, int8_t origin) + double ct, double y, double e, int8_t flagMc, int8_t flagMcDecay, int8_t origin) { if (fillCandidateLiteTable) { rowCandidateLite( @@ -313,6 +319,7 @@ struct HfTreeCreatorD0ToKPi { candidate.phi(), y, flagMc, + flagMcDecay, origin); } else { double cosThetaStar = candFlag == 0 ? hfHelper.cosThetaStarD0(candidate) : hfHelper.cosThetaStarD0bar(candidate); @@ -376,6 +383,7 @@ struct HfTreeCreatorD0ToKPi { y, e, flagMc, + flagMcDecay, origin, candidate.globalIndex()); } @@ -435,10 +443,10 @@ struct HfTreeCreatorD0ToKPi { massD0bar = hfHelper.invMassD0barToKPi(candidate); } if (candidate.isSelD0()) { - fillTable(candidate, 0, massD0, topolChi2PerNdf, ctD, yD, eD, 0, 0); + fillTable(candidate, 0, massD0, topolChi2PerNdf, ctD, yD, eD, 0, 0, 0); } if (candidate.isSelD0bar()) { - fillTable(candidate, 1, massD0bar, topolChi2PerNdf, ctD, yD, eD, 0, 0); + fillTable(candidate, 1, massD0bar, topolChi2PerNdf, ctD, yD, eD, 0, 0, 0); } } } @@ -504,7 +512,7 @@ struct HfTreeCreatorD0ToKPi { } for (const auto& candidate : candidates) { if constexpr (onlyBkg) { - if (TESTBIT(std::abs(candidate.flagMcMatchRec()), aod::hf_cand_2prong::DecayType::D0ToPiK)) { + if (TESTBIT(std::abs(candidate.flagMcMatchRec()), aod::hf_cand_2prong::DecayType::D0ToPiK) || (fillCorrBkgs && (candidate.flagMcMatchRec() != 0))) { continue; } if (downSampleBkgFactor < 1.) { @@ -515,7 +523,7 @@ struct HfTreeCreatorD0ToKPi { } } if constexpr (onlySig) { - if (!TESTBIT(std::abs(candidate.flagMcMatchRec()), aod::hf_cand_2prong::DecayType::D0ToPiK)) { + if (!(TESTBIT(std::abs(candidate.flagMcMatchRec()), aod::hf_cand_2prong::DecayType::D0ToPiK)) || (fillCorrBkgs && (candidate.flagMcMatchRec() != 0))) { continue; } } @@ -533,17 +541,17 @@ struct HfTreeCreatorD0ToKPi { massD0bar = hfHelper.invMassD0barToKPi(candidate); } if (candidate.isSelD0()) { - fillTable(candidate, 0, massD0, topolChi2PerNdf, ctD, yD, eD, candidate.flagMcMatchRec(), candidate.originMcRec()); + fillTable(candidate, 0, massD0, topolChi2PerNdf, ctD, yD, eD, candidate.flagMcMatchRec(), candidate.flagMcDecayChanRec(), candidate.originMcRec()); } if (candidate.isSelD0bar()) { - fillTable(candidate, 1, massD0bar, topolChi2PerNdf, ctD, yD, eD, candidate.flagMcMatchRec(), candidate.originMcRec()); + fillTable(candidate, 1, massD0bar, topolChi2PerNdf, ctD, yD, eD, candidate.flagMcMatchRec(), candidate.flagMcDecayChanRec(), candidate.originMcRec()); } } // Filling particle properties rowCandidateFullParticles.reserve(mcParticles.size()); for (const auto& particle : mcParticles) { - if (TESTBIT(std::abs(particle.flagMcMatchGen()), aod::hf_cand_2prong::DecayType::D0ToPiK)) { + if (TESTBIT(std::abs(particle.flagMcMatchGen()), aod::hf_cand_2prong::DecayType::D0ToPiK) || (fillCorrBkgs && particle.flagMcMatchGen() != 0)) { rowCandidateFullParticles( particle.mcCollisionId(), particle.pt(), @@ -551,6 +559,7 @@ struct HfTreeCreatorD0ToKPi { particle.phi(), RecoDecay::y(particle.pVector(), o2::constants::physics::MassD0), particle.flagMcMatchGen(), + particle.flagMcDecayChanGen(), particle.originMcGen(), particle.globalIndex()); } diff --git a/PWGHF/TableProducer/treeCreatorDplusToPiKPi.cxx b/PWGHF/TableProducer/treeCreatorDplusToPiKPi.cxx index 3d23c0b30ca..eb861f1b626 100644 --- a/PWGHF/TableProducer/treeCreatorDplusToPiKPi.cxx +++ b/PWGHF/TableProducer/treeCreatorDplusToPiKPi.cxx @@ -236,7 +236,8 @@ DECLARE_SOA_TABLE(HfCandDpFullPs, "AOD", "HFCANDDPFULLP", full::Eta, full::Phi, full::Y, - hf_cand_3prong::FlagMcMatchRec, + hf_cand_3prong::FlagMcMatchGen, + hf_cand_3prong::FlagMcDecayChanGen, hf_cand_3prong::OriginMcGen); } // namespace o2::aod @@ -252,6 +253,7 @@ struct HfTreeCreatorDplusToPiKPi { Configurable fillCandidateLiteTable{"fillCandidateLiteTable", false, "Switch to fill lite table with candidate properties"}; // parameters for production of training samples Configurable fillOnlySignal{"fillOnlySignal", false, "Flag to fill derived tables with signal for ML trainings"}; + Configurable fillCorrBkgs{"fillCorrBkgs", false, "Flag to fill derived tables with correlated background candidates"}; Configurable fillOnlyBackground{"fillOnlyBackground", false, "Flag to fill derived tables with background for ML trainings"}; 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"}; @@ -268,11 +270,11 @@ struct HfTreeCreatorDplusToPiKPi { using CollisionsCent = soa::Join; Filter filterSelectCandidates = aod::hf_sel_candidate_dplus::isSelDplusToPiKPi >= selectionFlagDplus; - Filter filterMcGenMatching = nabs(o2::aod::hf_cand_3prong::flagMcMatchGen) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi); + Filter filterMcGenMatching = (nabs(o2::aod::hf_cand_3prong::flagMcMatchGen) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi)) || (fillCorrBkgs && (nabs(o2::aod::hf_cand_3prong::flagMcMatchGen) != 0)); - Partition reconstructedCandSig = nabs(aod::hf_cand_3prong::flagMcMatchRec) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi) || nabs(aod::hf_cand_3prong::flagMcMatchRec) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DsToPiKK) || nabs(aod::hf_cand_3prong::flagMcMatchRec) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKK); + Partition reconstructedCandSig = (nabs(aod::hf_cand_3prong::flagMcMatchRec) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi)) || (fillCorrBkgs && (nabs(o2::aod::hf_cand_3prong::flagMcMatchRec) != 0)); Partition reconstructedCandBkg = nabs(aod::hf_cand_3prong::flagMcMatchRec) != static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi); - Partition reconstructedCandSigMl = nabs(aod::hf_cand_3prong::flagMcMatchRec) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi) || nabs(aod::hf_cand_3prong::flagMcMatchRec) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DsToPiKK) || nabs(aod::hf_cand_3prong::flagMcMatchRec) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKK) || nabs(aod::hf_cand_3prong::flagMcMatchRec) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DstarToPiKPi); + Partition reconstructedCandSigMl = (nabs(aod::hf_cand_3prong::flagMcMatchRec) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi)) || (fillCorrBkgs && (nabs(o2::aod::hf_cand_3prong::flagMcMatchRec) != 0)); void init(InitContext const&) { @@ -509,11 +511,11 @@ struct HfTreeCreatorDplusToPiKPi { PROCESS_SWITCH(HfTreeCreatorDplusToPiKPi, processDataWCent, "Process data with cent", false); - template + template void fillMcTables(CollType const& collisions, aod::McCollisions const&, - CandType const& candidates, - MatchedGenCandidatesMc const& particles, + CandTypeMcRec const& candidates, + CandTypeMcGen const& particles, TracksWPid const&) { // Filling event properties @@ -548,6 +550,7 @@ struct HfTreeCreatorDplusToPiKPi { particle.phi(), RecoDecay::y(particle.pVector(), o2::constants::physics::MassDPlus), particle.flagMcMatchGen(), + particle.flagMcDecayChanGen(), particle.originMcGen()); } } diff --git a/PWGHF/Utils/utilsMcGen.h b/PWGHF/Utils/utilsMcGen.h index 73dac888c8e..6f9ed6f4fed 100644 --- a/PWGHF/Utils/utilsMcGen.h +++ b/PWGHF/Utils/utilsMcGen.h @@ -17,56 +17,95 @@ #ifndef PWGHF_UTILS_UTILSMCGEN_H_ #define PWGHF_UTILS_UTILSMCGEN_H_ -#include -#include +#include "PWGHF/Core/DecayChannels.h" +#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "PWGHF/Utils/utilsMcMatching.h" + +#include "Common/Core/RecoDecay.h" #include +#include + +#include + #include #include #include -#include "Common/Core/RecoDecay.h" - -#include "PWGHF/Core/DecayChannels.h" -#include "PWGHF/DataModel/CandidateReconstructionTables.h" - namespace hf_mc_gen { template -void fillMcMatchGen2Prong(T const& mcParticles, U const& mcParticlesPerMcColl, V& rowMcMatchGen, bool rejectBackground) +void fillMcMatchGen2Prong(T const& mcParticles, U const& mcParticlesPerMcColl, V& rowMcMatchGen, bool rejectBackground, bool matchCorrelatedBackgrounds) { using namespace o2::constants::physics; + constexpr std::size_t NDaughtersResonant{2u}; // Match generated particles. for (const auto& particle : mcParticlesPerMcColl) { int8_t flag = 0; int8_t origin = 0; + int8_t channel = 0; int8_t sign = 0; std::vector idxBhadMothers{}; // Reject particles from background events if (particle.fromBackgroundEvent() && rejectBackground) { - rowMcMatchGen(flag, origin, -1); + rowMcMatchGen(flag, origin, channel, -1); continue; } + if (matchCorrelatedBackgrounds) { + constexpr int MaxDepth = 2; // Depth for final state matching + constexpr int ResoMaxDepth = 1; // Depth for resonant decay matching + bool matched = false; - // D0(bar) → π± K∓ - if (RecoDecay::isMatchedMCGen(mcParticles, particle, Pdg::kD0, std::array{+kPiPlus, -kKPlus}, true, &sign)) { - flag = sign * (1 << o2::aod::hf_cand_2prong::DecayType::D0ToPiK); - } + for (const auto& [chn, finalState] : o2::hf_decay::hf_cand_2prong::daughtersD0Main) { + if (finalState.size() == 3) { // o2-linter: disable=magic-number (Partly Reco 3-prong decays) + std::array finalStateParts = std::array{finalState[0], finalState[1], finalState[2]}; + o2::hf_decay::changeFinalStatePdgSign(particle.pdgCode(), +kPi0, finalStateParts); + matched = RecoDecay::isMatchedMCGen(mcParticles, particle, Pdg::kD0, finalStateParts, true, &sign, MaxDepth); + } else if (finalState.size() == 2) { // o2-linter: disable=magic-number (Fully Reco 2-prong decays) + std::array finalStateParts = std::array{finalState[0], finalState[1]}; + matched = RecoDecay::isMatchedMCGen(mcParticles, particle, Pdg::kD0, finalStateParts, true, &sign, MaxDepth); + } else { + LOG(info) << "Final state size not supported: " << finalState.size(); + continue; + } + if (matched) { + flag = sign * (1 << chn); - // J/ψ → e+ e− - if (flag == 0) { - if (RecoDecay::isMatchedMCGen(mcParticles, particle, Pdg::kJPsi, std::array{+kElectron, -kElectron}, true)) { - flag = 1 << o2::aod::hf_cand_2prong::DecayType::JpsiToEE; + // Flag the resonant decay channel + std::vector arrResoDaughIndex = {}; + RecoDecay::getDaughters(particle, &arrResoDaughIndex, std::array{0}, ResoMaxDepth); + std::array arrPDGDaugh = {}; + if (arrResoDaughIndex.size() == NDaughtersResonant) { + for (auto iProng = 0u; iProng < arrResoDaughIndex.size(); ++iProng) { + auto daughI = mcParticles.rawIteratorAt(arrResoDaughIndex[iProng]); + arrPDGDaugh[iProng] = daughI.pdgCode(); + } + channel = o2::hf_decay::flagResonantDecay(Pdg::kD0, arrPDGDaugh); + } + break; + } + } + } else { + // D0(bar) → π± K∓ + if (RecoDecay::isMatchedMCGen(mcParticles, particle, Pdg::kD0, std::array{+kPiPlus, -kKPlus}, true, &sign)) { + flag = sign * (1 << o2::aod::hf_cand_2prong::DecayType::D0ToPiK); } - } - // J/ψ → μ+ μ− - if (flag == 0) { - if (RecoDecay::isMatchedMCGen(mcParticles, particle, Pdg::kJPsi, std::array{+kMuonPlus, -kMuonPlus}, true)) { - flag = 1 << o2::aod::hf_cand_2prong::DecayType::JpsiToMuMu; + // J/ψ → e+ e− + if (flag == 0) { + if (RecoDecay::isMatchedMCGen(mcParticles, particle, Pdg::kJPsi, std::array{+kElectron, -kElectron}, true)) { + flag = 1 << o2::aod::hf_cand_2prong::DecayType::JpsiToEE; + } + } + + // J/ψ → μ+ μ− + if (flag == 0) { + if (RecoDecay::isMatchedMCGen(mcParticles, particle, Pdg::kJPsi, std::array{+kMuonPlus, -kMuonPlus}, true)) { + flag = 1 << o2::aod::hf_cand_2prong::DecayType::JpsiToMuMu; + } } } @@ -75,15 +114,15 @@ void fillMcMatchGen2Prong(T const& mcParticles, U const& mcParticlesPerMcColl, V origin = RecoDecay::getCharmHadronOrigin(mcParticles, particle, false, &idxBhadMothers); } if (origin == RecoDecay::OriginType::NonPrompt) { - rowMcMatchGen(flag, origin, idxBhadMothers[0]); + rowMcMatchGen(flag, origin, channel, idxBhadMothers[0]); } else { - rowMcMatchGen(flag, origin, -1); + rowMcMatchGen(flag, origin, channel, -1); } } } template -void fillMcMatchGen3Prong(T const& mcParticles, U const& mcParticlesPerMcColl, V& rowMcMatchGen, bool rejectBackground) +void fillMcMatchGen3Prong(T const& mcParticles, U const& mcParticlesPerMcColl, V& rowMcMatchGen, bool rejectBackground, std::vector const& corrBkgMothersPdgs = {}) { using namespace o2::constants::physics; constexpr std::size_t NDaughtersResonant{2u}; @@ -108,76 +147,146 @@ void fillMcMatchGen3Prong(T const& mcParticles, U const& mcParticlesPerMcColl, V continue; } - // D± → π± K∓ π± - if (flag == 0) { - if (RecoDecay::isMatchedMCGen(mcParticles, particle, Pdg::kDPlus, std::array{+kPiPlus, -kKPlus, +kPiPlus}, true, &sign, 2)) { - flag = sign * o2::hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi; - } - } + if (corrBkgMothersPdgs.size() > 0) { + for (const auto& motherPdgCode : corrBkgMothersPdgs) { + if (std::abs(particle.pdgCode()) != motherPdgCode) { + continue; // Skip if the particle PDG code does not match the mother PDG code + } + auto finalStates = o2::hf_decay::hf_cand_3prong::getDecayChannelMain(motherPdgCode); + constexpr int MaxDepth = 2; // Depth for final state matching + constexpr int ResoMaxDepth = 1; // Depth for resonant decay matching - // Ds± → K± K∓ π± and D± → K± K∓ π± - if (flag == 0) { - bool isDplus = false; - if (RecoDecay::isMatchedMCGen(mcParticles, particle, Pdg::kDS, std::array{+kKPlus, -kKPlus, +kPiPlus}, true, &sign, 2)) { - // DecayType::DsToKKPi is used to flag both Ds± → K± K∓ π± and D± → K± K∓ π± - // TODO: move to different and explicit flags - flag = sign * o2::hf_decay::hf_cand_3prong::DecayChannelMain::DsToPiKK; - } else if (RecoDecay::isMatchedMCGen(mcParticles, particle, Pdg::kDPlus, std::array{+kKPlus, -kKPlus, +kPiPlus}, true, &sign, 2)) { - // DecayType::DsToKKPi is used to flag both Ds± → K± K∓ π± and D± → K± K∓ π± - // TODO: move to different and explicit flags - flag = sign * o2::hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKK; - isDplus = true; - } - if (flag != 0) { - RecoDecay::getDaughters(particle, &arrDaughIndex, std::array{0}, 1); - if (arrDaughIndex.size() == NDaughtersResonant) { - for (auto jProng = 0u; jProng < arrDaughIndex.size(); ++jProng) { - auto daughJ = mcParticles.rawIteratorAt(arrDaughIndex[jProng]); - arrPDGDaugh[jProng] = std::abs(daughJ.pdgCode()); + int maxDepth = MaxDepth; + bool matched = false; + if (motherPdgCode == Pdg::kDStar) { + maxDepth = MaxDepth + 1; // D0 resonant decays are switched on + } + + std::vector arrAllDaughtersIndex; + for (const auto& [chn, finalState] : finalStates) { + if (finalState.size() == 5) { // o2-linter: disable=magic-number (Partly Reco 3-prong decays from 5-prong decays) + std::array finalStateParts = std::array{finalState[0], finalState[1], finalState[2], finalState[3], finalState[4]}; + o2::hf_decay::changeFinalStatePdgSign(particle.pdgCode(), +kPi0, finalStateParts); + RecoDecay::getDaughters(particle, &arrAllDaughtersIndex, finalStateParts, maxDepth); + matched = RecoDecay::isMatchedMCGen(mcParticles, particle, motherPdgCode, finalStateParts, true, &sign, -1); + } else if (finalState.size() == 4) { // o2-linter: disable=magic-number (Partly Reco 3-prong decays from 4-prong decays) + std::array finalStateParts = std::array{finalState[0], finalState[1], finalState[2], finalState[3]}; + o2::hf_decay::changeFinalStatePdgSign(particle.pdgCode(), +kPi0, finalStateParts); + RecoDecay::getDaughters(particle, &arrAllDaughtersIndex, finalStateParts, maxDepth); + matched = RecoDecay::isMatchedMCGen(mcParticles, particle, motherPdgCode, finalStateParts, true, &sign, -1); + } else if (finalState.size() == 3) { // o2-linter: disable=magic-number (Fully Reco 3-prong decays) + std::array finalStateParts = std::array{finalState[0], finalState[1], finalState[2]}; + RecoDecay::getDaughters(particle, &arrAllDaughtersIndex, finalStateParts, maxDepth); + matched = RecoDecay::isMatchedMCGen(mcParticles, particle, motherPdgCode, finalStateParts, true, &sign, maxDepth); + } else { + LOG(info) << "Final state size not supported: " << finalState.size(); + continue; } - if ((arrPDGDaugh[0] == arrPDGResonantDPhiPi[0] && arrPDGDaugh[1] == arrPDGResonantDPhiPi[1]) || (arrPDGDaugh[0] == arrPDGResonantDPhiPi[1] && arrPDGDaugh[1] == arrPDGResonantDPhiPi[0])) { - channel = isDplus ? o2::hf_decay::hf_cand_3prong::DecayChannelResonant::DplusToPhiPi : o2::hf_decay::hf_cand_3prong::DecayChannelResonant::DsToPhiPi; - } else if ((arrPDGDaugh[0] == arrPDGResonantDKstarK[0] && arrPDGDaugh[1] == arrPDGResonantDKstarK[1]) || (arrPDGDaugh[0] == arrPDGResonantDKstarK[1] && arrPDGDaugh[1] == arrPDGResonantDKstarK[0])) { - channel = isDplus ? o2::hf_decay::hf_cand_3prong::DecayChannelResonant::DplusToKstar0K : o2::hf_decay::hf_cand_3prong::DecayChannelResonant::DsToKstar0K; + if (matched) { + flag = sign * chn; + // Flag the resonant decay channel + std::vector arrResoDaughIndex = {}; + if (std::abs(motherPdgCode) == Pdg::kDStar) { + std::vector arrResoDaughIndexDStar = {}; + RecoDecay::getDaughters(particle, &arrResoDaughIndexDStar, std::array{0}, ResoMaxDepth); + for (size_t iDaug = 0; iDaug < arrResoDaughIndexDStar.size(); iDaug++) { + auto daughDstar = mcParticles.rawIteratorAt(arrResoDaughIndexDStar[iDaug]); + if (std::abs(daughDstar.pdgCode()) == Pdg::kD0 || std::abs(daughDstar.pdgCode()) == Pdg::kDPlus) { + RecoDecay::getDaughters(daughDstar, &arrResoDaughIndex, std::array{0}, ResoMaxDepth); + break; + } + } + } else { + RecoDecay::getDaughters(particle, &arrResoDaughIndex, std::array{0}, ResoMaxDepth); + } + std::array arrPDGDaugh = {}; + if (arrResoDaughIndex.size() == NDaughtersResonant) { + for (auto iProng = 0u; iProng < NDaughtersResonant; ++iProng) { + auto daughI = mcParticles.rawIteratorAt(arrResoDaughIndex[iProng]); + arrPDGDaugh[iProng] = daughI.pdgCode(); + } + channel = o2::hf_decay::flagResonantDecay(motherPdgCode, arrPDGDaugh); + } + break; // Exit loop if a match is found } } + if (matched) { + break; // Exit loop if a match is found + } } - } + } else { - // D*± → D0(bar) π± - if (flag == 0) { - if (RecoDecay::isMatchedMCGen(mcParticles, particle, Pdg::kDStar, std::array{+kPiPlus, +kPiPlus, -kKPlus}, true, &sign, 2)) { - flag = sign * o2::hf_decay::hf_cand_3prong::DecayChannelMain::DstarToPiKPi; + // D± → π± K∓ π± + if (flag == 0) { + if (RecoDecay::isMatchedMCGen(mcParticles, particle, Pdg::kDPlus, std::array{+kPiPlus, -kKPlus, +kPiPlus}, true, &sign, 2)) { + flag = sign * (1 << o2::aod::hf_cand_3prong::DecayType::DplusToPiKPi); + } } - } - // Λc± → p± K∓ π± - if (flag == 0) { - if (RecoDecay::isMatchedMCGen(mcParticles, particle, Pdg::kLambdaCPlus, std::array{+kProton, -kKPlus, +kPiPlus}, true, &sign, 2)) { - flag = sign * o2::hf_decay::hf_cand_3prong::DecayChannelMain::LcToPKPi; - - // Flagging the different Λc± → p± K∓ π± decay channels - RecoDecay::getDaughters(particle, &arrDaughIndex, std::array{0}, 1); - if (arrDaughIndex.size() == NDaughtersResonant) { - for (auto jProng = 0u; jProng < arrDaughIndex.size(); ++jProng) { - auto daughJ = mcParticles.rawIteratorAt(arrDaughIndex[jProng]); - arrPDGDaugh[jProng] = std::abs(daughJ.pdgCode()); + // Ds± → K± K∓ π± and D± → K± K∓ π± + if (flag == 0) { + bool isDplus = false; + if (RecoDecay::isMatchedMCGen(mcParticles, particle, Pdg::kDS, std::array{+kKPlus, -kKPlus, +kPiPlus}, true, &sign, 2)) { + // DecayType::DsToKKPi is used to flag both Ds± → K± K∓ π± and D± → K± K∓ π± + // TODO: move to different and explicit flags + flag = sign * (1 << o2::aod::hf_cand_3prong::DecayType::DsToKKPi); + } else if (RecoDecay::isMatchedMCGen(mcParticles, particle, Pdg::kDPlus, std::array{+kKPlus, -kKPlus, +kPiPlus}, true, &sign, 2)) { + // DecayType::DsToKKPi is used to flag both Ds± → K± K∓ π± and D± → K± K∓ π± + // TODO: move to different and explicit flags + flag = sign * (1 << o2::aod::hf_cand_3prong::DecayType::DsToKKPi); + isDplus = true; + } + if (flag != 0) { + RecoDecay::getDaughters(particle, &arrDaughIndex, std::array{0}, 1); + if (arrDaughIndex.size() == NDaughtersResonant) { + for (auto jProng = 0u; jProng < arrDaughIndex.size(); ++jProng) { + auto daughJ = mcParticles.rawIteratorAt(arrDaughIndex[jProng]); + arrPDGDaugh[jProng] = std::abs(daughJ.pdgCode()); + } + if ((arrPDGDaugh[0] == arrPDGResonantDPhiPi[0] && arrPDGDaugh[1] == arrPDGResonantDPhiPi[1]) || (arrPDGDaugh[0] == arrPDGResonantDPhiPi[1] && arrPDGDaugh[1] == arrPDGResonantDPhiPi[0])) { + channel = isDplus ? o2::aod::hf_cand_3prong::DecayChannelDToKKPi::DplusToPhiPi : o2::aod::hf_cand_3prong::DecayChannelDToKKPi::DsToPhiPi; + } else if ((arrPDGDaugh[0] == arrPDGResonantDKstarK[0] && arrPDGDaugh[1] == arrPDGResonantDKstarK[1]) || (arrPDGDaugh[0] == arrPDGResonantDKstarK[1] && arrPDGDaugh[1] == arrPDGResonantDKstarK[0])) { + channel = isDplus ? o2::aod::hf_cand_3prong::DecayChannelDToKKPi::DplusToK0starK : o2::aod::hf_cand_3prong::DecayChannelDToKKPi::DsToK0starK; + } } - if ((arrPDGDaugh[0] == arrPDGResonant1[0] && arrPDGDaugh[1] == arrPDGResonant1[1]) || (arrPDGDaugh[0] == arrPDGResonant1[1] && arrPDGDaugh[1] == arrPDGResonant1[0])) { - channel = 1; - } else if ((arrPDGDaugh[0] == arrPDGResonant2[0] && arrPDGDaugh[1] == arrPDGResonant2[1]) || (arrPDGDaugh[0] == arrPDGResonant2[1] && arrPDGDaugh[1] == arrPDGResonant2[0])) { - channel = 2; - } else if ((arrPDGDaugh[0] == arrPDGResonant3[0] && arrPDGDaugh[1] == arrPDGResonant3[1]) || (arrPDGDaugh[0] == arrPDGResonant3[1] && arrPDGDaugh[1] == arrPDGResonant3[0])) { - channel = 3; + } + } + + // D*± → D0(bar) π± + if (flag == 0) { + if (RecoDecay::isMatchedMCGen(mcParticles, particle, Pdg::kDStar, std::array{+kPiPlus, +kPiPlus, -kKPlus}, true, &sign, 2)) { + flag = sign * o2::hf_decay::hf_cand_3prong::DecayChannelMain::DstarToPiKPi; + } + } + + // Λc± → p± K∓ π± + if (flag == 0) { + if (RecoDecay::isMatchedMCGen(mcParticles, particle, Pdg::kLambdaCPlus, std::array{+kProton, -kKPlus, +kPiPlus}, true, &sign, 2)) { + flag = sign * o2::hf_decay::hf_cand_3prong::DecayChannelMain::LcToPKPi; + + // Flagging the different Λc± → p± K∓ π± decay channels + RecoDecay::getDaughters(particle, &arrDaughIndex, std::array{0}, 1); + if (arrDaughIndex.size() == NDaughtersResonant) { + for (auto jProng = 0u; jProng < arrDaughIndex.size(); ++jProng) { + auto daughJ = mcParticles.rawIteratorAt(arrDaughIndex[jProng]); + arrPDGDaugh[jProng] = std::abs(daughJ.pdgCode()); + } + if ((arrPDGDaugh[0] == arrPDGResonant1[0] && arrPDGDaugh[1] == arrPDGResonant1[1]) || (arrPDGDaugh[0] == arrPDGResonant1[1] && arrPDGDaugh[1] == arrPDGResonant1[0])) { + channel = 1; + } else if ((arrPDGDaugh[0] == arrPDGResonant2[0] && arrPDGDaugh[1] == arrPDGResonant2[1]) || (arrPDGDaugh[0] == arrPDGResonant2[1] && arrPDGDaugh[1] == arrPDGResonant2[0])) { + channel = 2; + } else if ((arrPDGDaugh[0] == arrPDGResonant3[0] && arrPDGDaugh[1] == arrPDGResonant3[1]) || (arrPDGDaugh[0] == arrPDGResonant3[1] && arrPDGDaugh[1] == arrPDGResonant3[0])) { + channel = 3; + } } } } - } - // Ξc± → p± K∓ π± - if (flag == 0) { - if (RecoDecay::isMatchedMCGen(mcParticles, particle, Pdg::kXiCPlus, std::array{+kProton, -kKPlus, +kPiPlus}, true, &sign, 2)) { - flag = sign * o2::hf_decay::hf_cand_3prong::DecayChannelMain::XicToPKPi; + // Ξc± → p± K∓ π± + if (flag == 0) { + if (RecoDecay::isMatchedMCGen(mcParticles, particle, Pdg::kXiCPlus, std::array{+kProton, -kKPlus, +kPiPlus}, true, &sign, 2)) { + flag = sign * o2::hf_decay::hf_cand_3prong::DecayChannelMain::XicToPKPi; + } } } diff --git a/PWGHF/Utils/utilsMcMatching.h b/PWGHF/Utils/utilsMcMatching.h new file mode 100644 index 00000000000..5736e6ab278 --- /dev/null +++ b/PWGHF/Utils/utilsMcMatching.h @@ -0,0 +1,268 @@ +// 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 utilsMcMatching.h +/// \brief Mapping of MC flags contained in DecayChannels.h +/// \author Marcello Di Costanzo , Polytechnic University of Turin and INFN + +#ifndef PWGHF_UTILS_UTILSMCMATCHING_H_ +#define PWGHF_UTILS_UTILSMCMATCHING_H_ + +#include "PWGHF/Core/DecayChannels.h" + +#include +#include + +#include + +#include +#include +#include +#include +#include + +namespace o2::hf_decay +{ + +namespace hf_cand_2prong +{ + +static const std::unordered_map> daughtersD0Main{ + {DecayChannelMain::D0ToPiK, {+kKMinus, +kPiPlus}}, + {DecayChannelMain::D0ToPiKPi0, {+kKMinus, +kPiPlus, +kPi0}}, + {DecayChannelMain::D0ToPiPi, {+kPiMinus, +kPiPlus}}, + {DecayChannelMain::D0ToPiPiPi0, {+kPiMinus, +kPiPlus, +kPi0}}, + {DecayChannelMain::D0ToKK, {+kKMinus, +kKPlus}}, +}; + +static const std::unordered_map> daughtersD0Resonant{ + {DecayChannelResonant::D0ToRhoplusPi, {+kRho770Plus, +kPiMinus}}, + {DecayChannelResonant::D0ToRhoplusK, {+kRho770Plus, +kKMinus}}, + {DecayChannelResonant::D0ToKstar0Pi0, {-o2::constants::physics::kK0Star892, +kPi0}}, + {DecayChannelResonant::D0ToKstarPi, {-o2::constants::physics::kKPlusStar892, +kPiPlus}}, +}; + +} // namespace hf_cand_2prong + +namespace hf_cand_3prong +{ + +// D± +static const std::unordered_map> daughtersDplusMain{ + {DecayChannelMain::DplusToPiKPi, {+kKMinus, +kKPlus, +kPiPlus}}, + {DecayChannelMain::DplusToPiKK, {+kKMinus, +kPiPlus, +kPiPlus}}, + {DecayChannelMain::DplusToPiKPiPi0, {+kKMinus, +kPiPlus, +kPiPlus, +kPi0}}, + {DecayChannelMain::DplusToPiPiPi, {+kPiMinus, +kPiPlus, +kPiPlus}}, +}; + +static const std::unordered_map> daughtersDplusResonant{ + {DecayChannelResonant::DplusToPhiPi, {+o2::constants::physics::kPhi, +kPiPlus}}, + {DecayChannelResonant::DplusToKstar0K, {-o2::constants::physics::kK0Star892, +kKPlus}}, + {DecayChannelResonant::DplusToKstar1430_0K, {+10311, +kKPlus}}, + {DecayChannelResonant::DplusToRho0Pi, {+kRho770_0, +kPiPlus}}, + {DecayChannelResonant::DplusToF2_1270Pi, {+225, +kPiPlus}}, +}; + +// Ds± +static const std::unordered_map> daughtersDsMain{ + {DecayChannelMain::DsToPiKK, {+kKMinus, +kKPlus, +kPiPlus}}, + {DecayChannelMain::DsToPiKKPi0, {+kKMinus, +kKPlus, +kPiPlus, +kPi0}}, + {DecayChannelMain::DsToPiPiK, {+kKPlus, +kPiPlus, +kPiMinus}}, + {DecayChannelMain::DsToPiPiPi, {+kPiMinus, +kPiPlus, +kPiPlus}}, + {DecayChannelMain::DsToPiPiPiPi0, {+kPiMinus, +kPiPlus, +kPiPlus, +kPi0}}, +}; + +static const std::unordered_map> daughtersDsResonant{ + {DecayChannelResonant::DsToPhiPi, {+o2::constants::physics::kPhi, +kPiPlus}}, + {DecayChannelResonant::DsToPhiRhoplus, {+o2::constants::physics::kPhi, +kRho770Plus}}, + {DecayChannelResonant::DsToKstar0K, {-o2::constants::physics::kK0Star892, +kKPlus}}, + {DecayChannelResonant::DsToKstar0Pi, {+o2::constants::physics::kK0Star892, +kPiPlus}}, + {DecayChannelResonant::DsToRho0Pi, {+kRho770_0, +kPiPlus}}, + {DecayChannelResonant::DsToRho0K, {+kRho770_0, +kKPlus}}, + {DecayChannelResonant::DsToF2_1270Pi, {225, +kPiPlus}}, + {DecayChannelResonant::DsToF0_1370K, {10221, +kKPlus}}, + {DecayChannelResonant::DsToEtaPi, {221, +kPiPlus}}, +}; + +// Dstar +static const std::unordered_map> daughtersDstarMain{ + {DecayChannelMain::DstarToPiKPi, {+kKMinus, +kPiPlus, +kPiPlus}}, + {DecayChannelMain::DstarToPiKPiPi0, {+kKMinus, +kPiPlus, +kPiPlus, +kPi0}}, + {DecayChannelMain::DstarToPiKPiPi0Pi0, {+kKMinus, +kPiPlus, +kPiPlus, +kPi0, +kPi0}}, + {DecayChannelMain::DstarToPiKK, {+kKMinus, +kKPlus, +kPiPlus}}, + {DecayChannelMain::DstarToPiKKPi0, {+kKMinus, +kKPlus, +kPiPlus, +kPi0}}, + {DecayChannelMain::DstarToPiPiPi, {+kPiMinus, +kPiPlus, +kPiPlus}}, + {DecayChannelMain::DstarToPiPiPiPi0, {+kPiMinus, +kPiPlus, +kPiPlus, +kPi0}}, +}; + +static const std::unordered_map> daughtersDstarResonant{ + {DecayChannelResonant::DstarToD0ToRhoplusPi, {+kRho770Plus, +kPiMinus}}, + {DecayChannelResonant::DstarToD0ToRhoplusK, {+kRho770Plus, +kKMinus}}, + {DecayChannelResonant::DstarToD0ToKstar0Pi0, {-o2::constants::physics::kK0Star892, +kPi0}}, + {DecayChannelResonant::DstarToD0ToKstarPi, {-o2::constants::physics::kKPlusStar892, +kPiPlus}}, + {DecayChannelResonant::DstarToDplusToPhiPi, {+o2::constants::physics::kPhi, +kPiPlus}}, + {DecayChannelResonant::DstarToDplusToKstar0K, {-o2::constants::physics::kK0Star892, +kKPlus}}, + {DecayChannelResonant::DstarToDplusToKstar1430_0K, {+10311, +kKPlus}}, + {DecayChannelResonant::DstarToDplusToRho0Pi, {+kRho770_0, +kPiPlus}}, + {DecayChannelResonant::DstarToDplusToF2_1270Pi, {+225, +kPiPlus}}, +}; + +// Lc +static const std::unordered_map> daughtersLcMain{ + {DecayChannelMain::LcToPKPi, {+kProton, +kKMinus, +kPiPlus}}, + {DecayChannelMain::LcToPKPiPi0, {+kProton, +kKMinus, +kPiPlus, +kPi0}}, + {DecayChannelMain::LcToPPiPi, {+kProton, +kPiMinus, +kPiPlus}}, + {DecayChannelMain::LcToPKK, {+kProton, +kKMinus, +kKPlus}}}; + +static const std::unordered_map> daughtersLcResonant{ + {DecayChannelResonant::LcToPKstar0, {+o2::constants::physics::kK0Star892, +kProton}}, + {DecayChannelResonant::LcToDeltaplusplusK, {+2224, +kKMinus}}, + {DecayChannelResonant::LcToL1520Pi, {+102134, +kPiPlus}}, +}; + +// Xic +static const std::unordered_map> daughtersXicMain{ + {DecayChannelMain::XicToPKPi, {+kProton, +kKMinus, +kPiPlus}}, + {DecayChannelMain::XicToPKK, {+kProton, +kKMinus, +kKPlus}}, + {DecayChannelMain::XicToSPiPi, {+kSigmaPlus, +kPiMinus, +kPiPlus}}, +}; + +static const std::unordered_map> daughtersXicResonant{ + {DecayChannelResonant::XicToPKstar0, {-o2::constants::physics::kK0Star892, +kProton}}, + {DecayChannelResonant::XicToPPhi, {+kProton, +o2::constants::physics::kPhi}}, +}; + +/// Returns a map of the possible final states for a specific 3-prong particle specie +/// \param pdgMother PDG code of the mother particle +/// \return a map of final states with their corresponding PDG codes +inline std::unordered_map> getDecayChannelMain(int pdgMother) +{ + switch (pdgMother) { + case o2::constants::physics::Pdg::kDPlus: + return daughtersDplusMain; + case o2::constants::physics::Pdg::kDS: + return daughtersDsMain; + case o2::constants::physics::Pdg::kDStar: + return daughtersDstarMain; + case o2::constants::physics::Pdg::kLambdaCPlus: + return daughtersLcMain; + case o2::constants::physics::Pdg::kXiCPlus: + return daughtersXicMain; + default: + LOG(fatal) << "Unknown PDG code for 3-prong final states: " << pdgMother; + return {}; + } +} +} // namespace hf_cand_3prong + +/// Compare an array of PDG codes with an expected array +/// \tparam N size of the arrays to be compared +/// \param arrPdgTested array of PDG codes to be tested +/// \param arrPdgExpected array of the expected PDG codes +/// \return true if the arrays are equal, false otherwise +template +inline bool checkDecayChannel(std::array const& arrPdgTested, std::array arrPdgExpected) +{ + for (std::size_t i = 0; i < N; i++) { + bool foundPdg = false; + for (std::size_t j = 0; j < N; j++) { + if (std::abs(arrPdgTested[i]) == std::abs(arrPdgExpected[j])) { + arrPdgExpected[j] = -1; // Mark as found + foundPdg = true; + break; + } + } + if (!foundPdg) { + return false; + } + } + return true; +} + +/// Flag the resonant decays +/// \tparam N size of the array of daughter PDG codes +/// \param motherPdg PDG code of the mother particle +/// \param arrDaughPdgs array of daughter PDG codes +/// \return the flag for the matched resonant decay channel +template +inline int8_t flagResonantDecay(const int motherPdg, std::array const& arrDaughPdgs) +{ + switch (motherPdg) { + case o2::constants::physics::Pdg::kD0: + for (const auto& [flag, pdgCodes] : o2::hf_decay::hf_cand_2prong::daughtersD0Resonant) { + if (o2::hf_decay::checkDecayChannel(arrDaughPdgs, pdgCodes)) { + return flag; + } + } + break; + case o2::constants::physics::Pdg::kDPlus: + for (const auto& [flag, pdgCodes] : o2::hf_decay::hf_cand_3prong::daughtersDplusResonant) { + if (o2::hf_decay::checkDecayChannel(arrDaughPdgs, pdgCodes)) { + return flag; + } + } + break; + case o2::constants::physics::Pdg::kDS: + for (const auto& [flag, pdgCodes] : o2::hf_decay::hf_cand_3prong::daughtersDsResonant) { + if (o2::hf_decay::checkDecayChannel(arrDaughPdgs, pdgCodes)) { + return flag; + } + } + break; + case o2::constants::physics::Pdg::kDStar: + for (const auto& [flag, pdgCodes] : o2::hf_decay::hf_cand_3prong::daughtersDstarResonant) { + if (o2::hf_decay::checkDecayChannel(arrDaughPdgs, pdgCodes)) { + return flag; + } + } + break; + case o2::constants::physics::Pdg::kLambdaCPlus: + for (const auto& [flag, pdgCodes] : o2::hf_decay::hf_cand_3prong::daughtersLcResonant) { + if (o2::hf_decay::checkDecayChannel(arrDaughPdgs, pdgCodes)) { + return flag; + } + } + break; + case o2::constants::physics::Pdg::kXiCPlus: + for (const auto& [flag, pdgCodes] : o2::hf_decay::hf_cand_3prong::daughtersXicResonant) { + if (o2::hf_decay::checkDecayChannel(arrDaughPdgs, pdgCodes)) { + return flag; + } + } + break; + default: + LOG(fatal) << "Unknown PDG code for 3-prong final states: " << motherPdg; + return -1; + } + return 0; +} + +/// Flip the sign of a specific PDG code in an array +/// of PDG codes associated to an antiparticle. +/// \tparam N size of the array of PDG codes +/// \param motherPdgCode PDG code of the mother particle +/// \param partPdgCode PDG code to be flipped +/// \param arrFinalStatePdgs array of PDG codes to be modified +template +inline void changeFinalStatePdgSign(const int motherPdgCode, const int partPdgCode, std::array& arrFinalStatePdgs) +{ + if (motherPdgCode >= 0) { + return; + } + for (auto& part : arrFinalStatePdgs) { // o2-linter: disable=const-ref-in-for-loop (arrFinalStatePdgs entries are modified) + if (part == partPdgCode) { + part = -part; + } + } +} +} // namespace o2::hf_decay + +#endif // PWGHF_UTILS_UTILSMCMATCHING_H_ From 81b1300330298446bc995d7df1041087f4ecc4a4 Mon Sep 17 00:00:00 2001 From: sashingo Date: Thu, 19 Jun 2025 15:15:27 +0900 Subject: [PATCH 139/871] [PWGHF] Add EMC eta cut in taskElectronWeakBoson (#11665) --- PWGHF/HFL/Tasks/taskElectronWeakBoson.cxx | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/PWGHF/HFL/Tasks/taskElectronWeakBoson.cxx b/PWGHF/HFL/Tasks/taskElectronWeakBoson.cxx index 72ff0ccdf8d..cbe388235bb 100644 --- a/PWGHF/HFL/Tasks/taskElectronWeakBoson.cxx +++ b/PWGHF/HFL/Tasks/taskElectronWeakBoson.cxx @@ -52,8 +52,9 @@ struct HfTaskElectronWeakBoson { Configurable vtxZ{"vtxZ", 10.f, ""}; - Configurable etaTrLow{"etaTrLow", -0.6f, "minimun track eta"}; - Configurable etaTrUp{"etaTrUp", 0.6f, "maximum track eta"}; + Configurable etaTrLow{"etaTrLow", -1.0f, "minimun track eta"}; + Configurable etaTrUp{"etaTrUp", 1.0f, "maximum track eta"}; + Configurable etaEmcAcc{"etaEmcAcc", 0.6f, "maximum track eta"}; Configurable dcaxyMax{"dcaxyMax", 2.0f, "mximum DCA xy"}; Configurable chi2ItsMax{"chi2ItsMax", 15.0f, "its chi2 cut"}; Configurable ptMin{"ptMin", 3.0f, "minimum pT cut"}; @@ -362,6 +363,8 @@ struct HfTaskElectronWeakBoson { // continue; if (track.phi() < phiEmcMin || track.phi() > phiEmcMax) continue; + if (std::abs(track.eta()) > etaEmcAcc) + continue; auto tracksofcluster = matchedtracks.sliceBy(perClusterMatchedTracks, track.globalIndex()); // LOGF(info, "Number of matched track: %d", tracksofcluster.size()); @@ -434,7 +437,7 @@ struct HfTaskElectronWeakBoson { if (eop > eopMin && eop < eopMax && trackCount < trackIsolationMax) isIsolatedTr = true; - if (isIsolated) { + if (isIsolated && isIsolatedTr) { registry.fill(HIST("hEopIsolation"), match.track_as().pt(), eop); if (match.track_as().pt() > ptZeeMin) { From 3b373a90d29746a992b7f21924a4d8c02679a0af Mon Sep 17 00:00:00 2001 From: sawan <124118453+sawankumawat@users.noreply.github.com> Date: Thu, 19 Jun 2025 12:48:31 +0530 Subject: [PATCH 140/871] [PWGLF] added polar angle in helicity frame in MC (#11661) Co-authored-by: Sawan Sawan --- .../Tasks/Resonances/higherMassResonances.cxx | 137 +++++++++++------- 1 file changed, 87 insertions(+), 50 deletions(-) diff --git a/PWGLF/Tasks/Resonances/higherMassResonances.cxx b/PWGLF/Tasks/Resonances/higherMassResonances.cxx index fad39aaf963..edb1c0dae08 100644 --- a/PWGLF/Tasks/Resonances/higherMassResonances.cxx +++ b/PWGLF/Tasks/Resonances/higherMassResonances.cxx @@ -51,12 +51,14 @@ #include #include #include +#include #include using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; using namespace o2::soa; +using namespace o2::aod::rctsel; // using namespace o2::constants::physics; using std::array; @@ -67,6 +69,16 @@ struct HigherMassResonances { HistogramRegistry hglue{"hglueball", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; HistogramRegistry hMChists{"hMChists", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + struct RCTCut : ConfigurableGroup { + Configurable requireRCTFlagChecker{"requireRCTFlagChecker", true, "Check event quality in run condition table"}; + 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"}; + + RCTFlagsChecker rctChecker; + }; + RCTCut rctCut; + struct : ConfigurableGroup { // PID and QA Configurable qAv0{"qAv0", false, "qAv0"}; @@ -123,6 +135,7 @@ struct HigherMassResonances { ConfigurableAxis binsCent{"binsCent", {VARIABLE_WIDTH, 0., 5., 10., 30., 50., 70., 100., 110., 150.}, "Binning of the centrality axis"}; // Configurable for MC + Configurable isMC{"isMC", false, "Is MC"}; Configurable allGenCollisions{"allGenCollisions", true, "To fill all generated collisions for the signal loss calculations"}; Configurable cTVXEvsel{"cTVXEvsel", true, "Triggger selection"}; Configurable avoidsplitrackMC{"avoidsplitrackMC", false, "avoid split track in MC"}; @@ -145,23 +158,16 @@ struct HigherMassResonances { Configurable tpcCrossedrows{"tpcCrossedrows", 70, "TPC crossed rows"}; Configurable tpcCrossedrowsOverfcls{"tpcCrossedrowsOverfcls", 0.8, "TPC crossed rows over findable clusters"}; - // Mass and pT axis as configurables - Configurable cPtMin{"cPtMin", 0.0f, "Minimum pT"}; - Configurable cPtMax{"cPtMax", 30.0f, "Maximum pT"}; - Configurable cPtBins{"cPtBins", 300, "Number of pT bins"}; - Configurable cMassMin{"cMassMin", 0.9f, "Minimum mass of glueball"}; - Configurable cMassMax{"cMassMax", 3.0f, "Maximum mass of glueball"}; - Configurable cMassBins{"cMassBins", 210, "Number of mass bins for glueball"}; - Configurable ksMassMin{"ksMassMin", 0.45f, "Minimum mass of K0s"}; - Configurable ksMassMax{"ksMassMax", 0.55f, "Maximum mass of K0s"}; - Configurable ksMassBins{"ksMassBins", 200, "Number of mass bins for K0s"}; + // // Mass and pT axis as configurables Configurable rotationalCut{"rotationalCut", 10, "Cut value (Rotation angle pi - pi/cut and pi + pi/cut)"}; ConfigurableAxis configThnAxisPOL{"configThnAxisPOL", {20, -1.0, 1.0}, "Costheta axis"}; ConfigurableAxis configThnAxisPhi{"configThnAxisPhi", {70, 0.0f, 7.0f}, "Phi axis"}; // 0 to 2pi + ConfigurableAxis ksMassBins{"ksMassBins", {200, 0.45f, 0.55f}, "K0s invariant mass axis"}; + ConfigurableAxis cMassBins{"cMassBins", {200, 0.9f, 3.0f}, "Glueball invariant mass axis"}; + ConfigurableAxis cPtBins{"cPtBins", {200, 0.0f, 20.0f}, "Glueball pT axis"}; // ConfigurableAxis axisdEdx{"axisdEdx", {20000, 0.0f, 200.0f}, "dE/dx (a.u.)"}; // ConfigurableAxis axisPtfordEbydx{"axisPtfordEbydx", {2000, 0, 20}, "pT (GeV/c)"}; // ConfigurableAxis axisMultdist{"axisMultdist", {3500, 0, 70000}, "Multiplicity distribution"}; - // 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}, "Binning: occupancy axis"}; } config; // Service PDGdatabase; @@ -180,16 +186,19 @@ struct HigherMassResonances { void init(InitContext const&) { + rctCut.rctChecker.init( + rctCut.cfgEvtRCTFlagCheckerLabel, + rctCut.cfgEvtRCTFlagCheckerZDCCheck, + rctCut.cfgEvtRCTFlagCheckerLimitAcceptAsBad); + // Axes - AxisSpec k0ShortMassAxis = {config.ksMassBins, config.ksMassMin, config.ksMassMax, "#it{M}_{inv} [GeV/#it{c}^{2}]"}; - AxisSpec glueballMassAxis = {config.cMassBins, config.cMassMin, config.cMassMax, "#it{M}_{inv} [GeV/#it{c}^{2}]"}; + AxisSpec k0ShortMassAxis = {config.ksMassBins, "#it{M}_{inv} [GeV/#it{c}^{2}]"}; + AxisSpec glueballMassAxis = {config.ksMassBins, "#it{M}_{inv} [GeV/#it{c}^{2}]"}; AxisSpec vertexZAxis = {60, -15.f, 15.f, "vrtx_{Z} [cm]"}; // for histogram - AxisSpec ptAxis = {config.cPtBins, config.cPtMin, config.cPtMax, "#it{p}_{T} (GeV/#it{c})"}; - // AxisSpec multiplicityAxis = {110, 0.0f, 150.0f, "Multiplicity Axis"}; + AxisSpec ptAxis = {config.cPtBins, "#it{p}_{T} (GeV/#it{c})"}; AxisSpec multiplicityAxis = {config.binsCent, "Multiplicity Axis"}; AxisSpec thnAxisPOL{config.configThnAxisPOL, "Configurabel theta axis"}; AxisSpec thnAxisPhi = {config.configThnAxisPhi, "Configurabel phi axis"}; // 0 to 2pi - // AxisSpec occupancyAxis = {occupancyBins, "Occupancy [-40,100]"}; // THnSparses std::array sparses = {config.activateTHnSparseCosThStarHelicity, config.activateTHnSparseCosThStarProduction, config.activateTHnSparseCosThStarBeam, config.activateTHnSparseCosThStarRandom}; @@ -293,27 +302,28 @@ struct HigherMassResonances { // } // For MC - hMChists.add("events_check", "No. of events in the generated MC", kTH1I, {{20, 0, 20}}); - hMChists.add("events_checkrec", "No. of events in the reconstructed MC", kTH1I, {{20, 0, 20}}); - hMChists.add("Genf1710", "Gen f_{0}(1710)", kTHnSparseF, {multiplicityAxis, ptAxis}); - hMChists.add("Recf1710_pt1", "Rec f_{0}(1710) p_{T}", kTHnSparseF, {multiplicityAxis, ptAxis, glueballMassAxis}); - hMChists.add("Recf1710_pt2", "Rec f_{0}(1710) p_{T}", kTHnSparseF, {multiplicityAxis, ptAxis, glueballMassAxis}); - hMChists.add("Recf1710_p", "Rec f_{0}(1710) p", kTH1F, {ptAxis}); - hMChists.add("h1Recsplit", "Rec p_{T}2", kTH1F, {ptAxis}); - - hMChists.add("Recf1710_mass", "Rec f_{0}(1710) mass", kTH1F, {glueballMassAxis}); - hMChists.add("Genf1710_mass", "Gen f_{0}(1710) mass", kTH1F, {glueballMassAxis}); - hMChists.add("GenEta", "Gen Eta", kTHnSparseF, {ptAxis, {100, -1.0f, 1.0f}}); - hMChists.add("GenPhi", "Gen Phi", kTH1F, {{70, -3.5f, 3.5f}}); - hMChists.add("GenRapidity", "Gen Rapidity", kTHnSparseF, {ptAxis, {100, -1.0f, 1.0f}}); - hMChists.add("RecEta", "Rec Eta", kTH1F, {{100, -1.0f, 1.0f}}); - hMChists.add("RecPhi", "Rec Phi", kTH1F, {{70, 0.0f, 7.0f}}); - hMChists.add("RecRapidity", "Rec Rapidity", kTH1F, {{100, -1.0f, 1.0f}}); - hMChists.add("MC_mult", "Multiplicity in MC", kTH1F, {multiplicityAxis}); - hMChists.add("MC_mult_after_event_sel", "Multiplicity in MC", kTH1F, {multiplicityAxis}); - // hMChists.add("GenPx", "Gen Px", kTH1F, {{100, -10.0f, 10.0f}}); - // hMChists.add("GenPy", "Gen Py", kTH1F, {{100, -10.0f, 10.0f}}); - // hMChists.add("GenPz", "Gen Pz", kTH1F, {{100, -10.0f, 10.0f}}); + if (config.isMC) { + hMChists.add("events_check", "No. of events in the generated MC", kTH1I, {{20, 0, 20}}); + hMChists.add("events_checkrec", "No. of events in the reconstructed MC", kTH1I, {{20, 0, 20}}); + hMChists.add("Genf1710", "Gen f_{0}(1710)", kTHnSparseF, {multiplicityAxis, ptAxis, glueballMassAxis, thnAxisPOL}); + hMChists.add("Recf1710_pt1", "Rec f_{0}(1710) p_{T}", kTHnSparseF, {multiplicityAxis, ptAxis, glueballMassAxis, thnAxisPOL}); + hMChists.add("Recf1710_pt2", "Rec f_{0}(1710) p_{T}", kTHnSparseF, {multiplicityAxis, ptAxis, glueballMassAxis, thnAxisPOL}); + // hMChists.add("Recf1710_p", "Rec f_{0}(1710) p", kTH1F, {ptAxis}); + hMChists.add("h1Recsplit", "Rec p_{T}2", kTH1F, {ptAxis}); + // hMChists.add("Recf1710_mass", "Rec f_{0}(1710) mass", kTH1F, {glueballMassAxis}); + // hMChists.add("Genf1710_mass", "Gen f_{0}(1710) mass", kTH1F, {glueballMassAxis}); + hMChists.add("GenEta", "Gen Eta", kTHnSparseF, {ptAxis, {100, -1.0f, 1.0f}}); + hMChists.add("GenPhi", "Gen Phi", kTH1F, {{70, -3.5f, 3.5f}}); + hMChists.add("GenRapidity", "Gen Rapidity", kTHnSparseF, {ptAxis, {100, -1.0f, 1.0f}}); + hMChists.add("RecEta", "Rec Eta", kTH1F, {{100, -1.0f, 1.0f}}); + hMChists.add("RecPhi", "Rec Phi", kTH1F, {{70, 0.0f, 7.0f}}); + hMChists.add("RecRapidity", "Rec Rapidity", kTH1F, {{100, -1.0f, 1.0f}}); + hMChists.add("MC_mult", "Multiplicity in MC", kTH1F, {multiplicityAxis}); + hMChists.add("MC_mult_after_event_sel", "Multiplicity in MC", kTH1F, {multiplicityAxis}); + // hMChists.add("GenPx", "Gen Px", kTH1F, {{100, -10.0f, 10.0f}}); + // hMChists.add("GenPy", "Gen Py", kTH1F, {{100, -10.0f, 10.0f}}); + // hMChists.add("GenPz", "Gen Pz", kTH1F, {{100, -10.0f, 10.0f}}); + } } template @@ -699,6 +709,10 @@ struct HigherMassResonances { return; } + if (rctCut.requireRCTFlagChecker && !rctCut.rctChecker(collision)) { + return; + } + // auto occupancyNumber = collision.trackOccupancyInTimeRange(); // if (applyOccupancyCut && occupancyNumber < occupancyCut) { // return; @@ -839,6 +853,13 @@ struct HigherMassResonances { // return; // } + if (rctCut.requireRCTFlagChecker && !rctCut.rctChecker(c1)) { + return; + } + if (rctCut.requireRCTFlagChecker && !rctCut.rctChecker(c2)) { + return; + } + for (const auto& [t1, t2] : o2::soa::combinations(o2::soa::CombinationsFullIndexPolicy(tracks1, tracks2))) { if (t1.size() == 0 || t2.size() == 0) { @@ -963,7 +984,10 @@ struct HigherMassResonances { float multiplicityGen = 0.0; void processGen(aod::McCollision const& mcCollision, aod::McParticles const& mcParticles, const soa::SmallGroups& collisions) { - TLorentzVector genvec; + if (config.isMC == false) { + return; + } + TLorentzVector lResonance_gen; hMChists.fill(HIST("events_check"), 0.5); if (std::abs(mcCollision.posZ()) < config.cutzvertex) { hMChists.fill(HIST("events_check"), 1.5); @@ -1049,12 +1073,19 @@ struct HigherMassResonances { if (std::abs(kCurrentDaughter.pdgCode()) == 310) { passKs = true; hMChists.fill(HIST("events_check"), 9.5); + fourVecDau1 = ROOT::Math::PxPyPzMVector(kCurrentDaughter.px(), kCurrentDaughter.py(), kCurrentDaughter.pz(), o2::constants::physics::MassK0Short); } } if (passKs) { - genvec.SetPtEtaPhiE(mcParticle.pt(), mcParticle.eta(), mcParticle.phi(), mcParticle.e()); - hMChists.fill(HIST("Genf1710_mass"), genvec.M()); - hMChists.fill(HIST("Genf1710"), multiplicityGen, mcParticle.pt()); + lResonance_gen.SetPtEtaPhiE(mcParticle.pt(), mcParticle.eta(), mcParticle.phi(), mcParticle.e()); + fourVecMother = ROOT::Math::PxPyPzMVector(lResonance_gen.Px(), lResonance_gen.Py(), lResonance_gen.Pz(), lResonance_gen.M()); + ROOT::Math::Boost boost{fourVecMother.BoostToCM()}; + fourVecDauCM = boost(fourVecDau1); // boost the frame of daughter to the center of mass frame + + auto helicity_gen = fourVecDau1.Vect().Dot(fourVecDauCM.Vect()) / (std::sqrt(fourVecDauCM.Vect().Mag2()) * std::sqrt(fourVecDau1.Vect().Mag2())); + + hMChists.fill(HIST("Genf1710"), multiplicityGen, mcParticle.pt(), lResonance_gen.M(), helicity_gen); + // hMChists.fill(HIST("Genf1710_mass"), lResonance_gen.M()); } } } @@ -1065,11 +1096,11 @@ struct HigherMassResonances { std::vector gindex1, gindex2; void processRec(EventCandidatesMC::iterator const& collision, TrackCandidatesMC const&, V0TrackCandidatesMC const& V0s, aod::McParticles const&, aod::McCollisions const& /*mcCollisions*/) { + if (config.isMC == false) { + return; + } TLorentzVector lDecayDaughter1, lDecayDaughter2, lResonance; - // lDecayDaughter1.SetXYZM(0.0,0.0,0.0,0.0); - // lDecayDaughter2.SetXYZM(0.0,0.0,0.0,0.0); - // lDecayDaughter1.SetXYZM(0.0,0.0,0.0,0.0); auto multiplicity = collision.centFT0C(); hMChists.fill(HIST("MC_mult"), multiplicity); @@ -1226,7 +1257,7 @@ struct HigherMassResonances { pvec0 = std::array{v01.px(), v01.py(), v01.pz()}; pvec1 = std::array{v02.px(), v02.py(), v02.pz()}; auto arrMomrec = std::array{pvec0, pvec1}; - auto motherP = mothertrack1.p(); + // auto motherP = mothertrack1.p(); // auto motherE = mothertrack1.e(); // auto genMass = std::sqrt(motherE * motherE - motherP * motherP); auto recMass = RecoDecay::m(arrMomrec, std::array{o2::constants::physics::MassK0Short, o2::constants::physics::MassK0Short}); @@ -1235,12 +1266,18 @@ struct HigherMassResonances { lDecayDaughter1.SetXYZM(v01.px(), v01.py(), v01.pz(), o2::constants::physics::MassK0Short); lDecayDaughter2.SetXYZM(v02.px(), v02.py(), v02.pz(), o2::constants::physics::MassK0Short); lResonance = lDecayDaughter1 + lDecayDaughter2; - - hMChists.fill(HIST("Recf1710_p"), motherP); - hMChists.fill(HIST("Recf1710_mass"), recMass); - hMChists.fill(HIST("Recf1710_pt1"), multiplicity, mothertrack1.pt(), recMass); + // fourVecDau1, fourVecMother, fourVecDauCM + fourVecMother = ROOT::Math::PxPyPzMVector(lResonance.Px(), lResonance.Py(), lResonance.Pz(), lResonance.M()); + fourVecDau1 = ROOT::Math::PxPyPzMVector(lDecayDaughter1.Px(), lDecayDaughter1.Py(), lDecayDaughter1.Pz(), o2::constants::physics::MassK0Short); + ROOT::Math::Boost boost{fourVecMother.BoostToCM()}; + fourVecDauCM = boost(fourVecDau1); // boost the frame of daughter to the center of mass frame + auto helicity_rec = fourVecDau1.Vect().Dot(fourVecDauCM.Vect()) / (std::sqrt(fourVecDauCM.Vect().Mag2()) * std::sqrt(fourVecDau1.Vect().Mag2())); + + // hMChists.fill(HIST("Recf1710_p"), motherP); + // hMChists.fill(HIST("Recf1710_mass"), recMass); + hMChists.fill(HIST("Recf1710_pt1"), multiplicity, mothertrack1.pt(), recMass, helicity_rec); // hMChists.fill(HIST("Genf1710_mass"), genMass); - hMChists.fill(HIST("Recf1710_pt2"), multiplicity, lResonance.Pt(), recMass); + hMChists.fill(HIST("Recf1710_pt2"), multiplicity, lResonance.Pt(), recMass, helicity_rec); hMChists.fill(HIST("RecRapidity"), mothertrack1.y()); hMChists.fill(HIST("RecPhi"), mothertrack1.phi()); From 71297b197545db77146201928425aaed82deb3a0 Mon Sep 17 00:00:00 2001 From: Mattia Faggin Date: Thu, 19 Jun 2025 11:19:28 +0200 Subject: [PATCH 141/871] [PWGHF] add soft-pi dcaXY, dcaZ to SigmaC THnSparse. (#11584) Co-authored-by: Mattia Faggin --- PWGHF/D2H/Tasks/taskSigmac.cxx | 112 +++++++++++++++--- .../DataModel/CandidateReconstructionTables.h | 3 + .../candidateCreatorSigmac0plusplus.cxx | 59 ++++----- 3 files changed, 130 insertions(+), 44 deletions(-) diff --git a/PWGHF/D2H/Tasks/taskSigmac.cxx b/PWGHF/D2H/Tasks/taskSigmac.cxx index dff39af4c28..0a259ea6347 100644 --- a/PWGHF/D2H/Tasks/taskSigmac.cxx +++ b/PWGHF/D2H/Tasks/taskSigmac.cxx @@ -15,16 +15,16 @@ /// /// \author Mattia Faggin , University and INFN PADOVA -#include +#include "PWGHF/Core/HfHelper.h" +#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "PWGHF/DataModel/CandidateSelectionTables.h" #include "CommonConstants/PhysicsConstants.h" #include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" #include "Framework/runDataProcessing.h" -#include "PWGHF/Core/HfHelper.h" -#include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" +#include using namespace o2; using namespace o2::analysis; @@ -42,6 +42,7 @@ struct HfTaskSigmac { Configurable yCandGenMax{"yCandGenMax", -1, "Maximum generated Sc rapidity"}; Configurable yCandRecoMax{"yCandRecoMax", -1, "Maximum Sc candidate rapidity"}; Configurable enableTHn{"enableTHn", false, "enable the usage of THn for Λc+ and Σc0,++"}; + Configurable addSoftPiDcaToSigmacSparse{"addSoftPiDcaToSigmacSparse", false, "enable the filling of sof-pion dcaXY, dcaZ in the Σc0,++ THnSparse"}; HfHelper hfHelper; bool isMc; @@ -61,6 +62,7 @@ struct HfTaskSigmac { ConfigurableAxis configAxisDeltaMassSigmaC{"configAxisDeltaMassSigmaC", {200, 0.13, 0.23}, ""}; ConfigurableAxis thnConfigAxisBdtScoreLcBkg{"thnConfigAxisBdtScoreLcBkg", {100, 0., 1.}, ""}; ConfigurableAxis thnConfigAxisBdtScoreLcNonPrompt{"thnConfigAxisBdtScoreLcNonPrompt", {100, 0., 1.}, ""}; + ConfigurableAxis thnConfigAxisSoftPiAbsDca{"thnConfigAxisSoftPiAbsDca", {14, 0., 0.07}, ""}; 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})"}; const AxisSpec thnAxisPtSigmaC{thnConfigAxisPt, "#it{p}_{T}(#Sigma_{c}^{0,++}) (GeV/#it{c})"}; @@ -77,6 +79,8 @@ struct HfTaskSigmac { const AxisSpec thnAxisGenPtSigmaC{thnConfigAxisGenPt, "#it{p}_{T}^{gen}(#Sigma_{c}^{0,++}) (GeV/#it{c})"}; const AxisSpec thnAxisGenPtLambdaCBMother{thnConfigAxisGenPtB, "#it{p}_{T}^{gen}(#Lambda_{c}^{+} B mother) (GeV/#it{c})"}; const AxisSpec thnAxisGenPtSigmaCBMother{thnConfigAxisGenPtB, "#it{p}_{T}^{gen}(#Sigma_{c}^{0,++} B mother) (GeV/#it{c})"}; + const AxisSpec thnAxisSoftPiAbsDcaXY{thnConfigAxisSoftPiAbsDca, "|dca_{xy}|(#pi^{-,+} #leftarrow #Sigma_{c}^{0,++}) (cm)"}; + const AxisSpec thnAxisSoftPiAbsDcaZ{thnConfigAxisSoftPiAbsDca, "|dca_{z}|(#pi^{-,+} #leftarrow #Sigma_{c}^{0,++}) (cm)"}; const AxisSpec thnAxisGenSigmaCSpecies = {o2::aod::hf_cand_sigmac::Species::NSpecies, -0.5f, +o2::aod::hf_cand_sigmac::Species::NSpecies - 0.5f, "bin 1: #Sigma_{c}(2455), bin 2: #Sigma_{c}(2520)"}; 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"}; @@ -278,6 +282,10 @@ struct HfTaskSigmac { axesSigmaCWithMl.push_back(thnAxisGenPtSigmaCBMother); axesSigmaCWithMl.push_back(thnAxisGenSigmaCSpecies); axesSigmaCWithMl.push_back(thnAxisSigmaCParticleAntiparticle); + if (addSoftPiDcaToSigmacSparse) { + axesSigmaCWithMl.push_back(thnAxisSoftPiAbsDcaXY); + axesSigmaCWithMl.push_back(thnAxisSoftPiAbsDcaZ); + } registry.add("hnLambdaC", "THn for Lambdac", HistType::kTHnSparseF, axesLambdaCWithMl); registry.add("hnSigmaC", "THn for Sigmac", HistType::kTHnSparseF, axesSigmaCWithMl); } else { @@ -285,14 +293,26 @@ struct HfTaskSigmac { axesSigmaCWoMl.push_back(thnAxisGenPtSigmaCBMother); axesSigmaCWoMl.push_back(thnAxisGenSigmaCSpecies); axesSigmaCWoMl.push_back(thnAxisSigmaCParticleAntiparticle); + if (addSoftPiDcaToSigmacSparse) { + axesSigmaCWoMl.push_back(thnAxisSoftPiAbsDcaXY); + axesSigmaCWoMl.push_back(thnAxisSoftPiAbsDcaZ); + } registry.add("hnLambdaC", "THn for Lambdac", HistType::kTHnSparseF, axesLambdaCWoMl); registry.add("hnSigmaC", "THn for Sigmac", HistType::kTHnSparseF, axesSigmaCWoMl); } } else { if (doprocessDataWithMl) { + if (addSoftPiDcaToSigmacSparse) { + axesSigmaCWithMl.push_back(thnAxisSoftPiAbsDcaXY); + axesSigmaCWithMl.push_back(thnAxisSoftPiAbsDcaZ); + } registry.add("hnLambdaC", "THn for Lambdac", HistType::kTHnSparseF, axesLambdaCWithMl); registry.add("hnSigmaC", "THn for Sigmac", HistType::kTHnSparseF, axesSigmaCWithMl); } else { + if (addSoftPiDcaToSigmacSparse) { + axesSigmaCWoMl.push_back(thnAxisSoftPiAbsDcaXY); + axesSigmaCWoMl.push_back(thnAxisSoftPiAbsDcaZ); + } registry.add("hnLambdaC", "THn for Lambdac", HistType::kTHnSparseF, axesLambdaCWoMl); registry.add("hnSigmaC", "THn for Sigmac", HistType::kTHnSparseF, axesSigmaCWoMl); } @@ -412,6 +432,8 @@ struct HfTaskSigmac { if (enableTHn) { if (!isMc) { /// fill it only if no MC operations are enabled, otherwise fill it in the processMC with the right origin and channel! + const float softPiAbsDcaXY = std::abs(candSc.softPiDcaXY()); + const float softPiAbsDcaZ = std::abs(candSc.softPiDcaZ()); if constexpr (useMl) { /// fill with ML information /// BDT index 0: bkg score; BDT index 2: non-prompt score @@ -420,10 +442,18 @@ struct HfTaskSigmac { outputMl.at(0) = candidateLc.mlProbLcToPKPi()[0]; /// bkg score outputMl.at(1) = candidateLc.mlProbLcToPKPi()[2]; /// non-prompt score } - registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), 0, 0, ptSc, std::abs(chargeSc)); + if (addSoftPiDcaToSigmacSparse) { + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), 0, 0, ptSc, std::abs(chargeSc), softPiAbsDcaXY, softPiAbsDcaZ); + } else { + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), 0, 0, ptSc, std::abs(chargeSc)); + } } else { /// fill w/o BDT information - registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, decLengthLc, decLengthXYLc, cpaLc, cpaXYLc, 0, 0, ptSc, std::abs(chargeSc)); + if (addSoftPiDcaToSigmacSparse) { + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, decLengthLc, decLengthXYLc, cpaLc, cpaXYLc, 0, 0, ptSc, std::abs(chargeSc), softPiAbsDcaXY, softPiAbsDcaZ); + } else { + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, decLengthLc, decLengthXYLc, cpaLc, cpaXYLc, 0, 0, ptSc, std::abs(chargeSc)); + } } } } @@ -485,6 +515,8 @@ struct HfTaskSigmac { if (enableTHn) { if (!isMc) { /// fill it only if no MC operations are enabled, otherwise fill it in the processMC with the right origin and channel! + const float softPiAbsDcaXY = std::abs(candSc.softPiDcaXY()); + const float softPiAbsDcaZ = std::abs(candSc.softPiDcaZ()); if constexpr (useMl) { /// fill with ML information /// BDT index 0: bkg score; BDT index 2: non-prompt score @@ -493,10 +525,18 @@ struct HfTaskSigmac { outputMl.at(0) = candidateLc.mlProbLcToPiKP()[0]; /// bkg score outputMl.at(1) = candidateLc.mlProbLcToPiKP()[2]; /// non-prompt score } - registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), 0, 0, ptSc, std::abs(chargeSc)); + if (addSoftPiDcaToSigmacSparse) { + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), 0, 0, ptSc, std::abs(chargeSc), softPiAbsDcaXY, softPiAbsDcaZ); + } else { + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), 0, 0, ptSc, std::abs(chargeSc)); + } } else { /// fill w/o BDT information - registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, decLengthLc, decLengthXYLc, cpaLc, cpaXYLc, 0, 0, ptSc, std::abs(chargeSc)); + if (addSoftPiDcaToSigmacSparse) { + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, decLengthLc, decLengthXYLc, cpaLc, cpaXYLc, 0, 0, ptSc, std::abs(chargeSc), softPiAbsDcaXY, softPiAbsDcaZ); + } else { + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, decLengthLc, decLengthXYLc, cpaLc, cpaXYLc, 0, 0, ptSc, std::abs(chargeSc)); + } } } } @@ -866,6 +906,8 @@ struct HfTaskSigmac { /// THn for candidate Σc0,++ cut variation if (enableTHn) { int8_t particleAntiparticle = candSc.particleAntiparticle(); + const float softPiAbsDcaXY = std::abs(candSc.softPiDcaXY()); + const float softPiAbsDcaZ = std::abs(candSc.softPiDcaZ()); if constexpr (useMl) { /// fill with ML information /// BDT index 0: bkg score; BDT index 2: non-prompt score @@ -874,10 +916,18 @@ struct HfTaskSigmac { outputMl.at(0) = candidateLc.mlProbLcToPKPi()[0]; /// bkg score outputMl.at(1) = candidateLc.mlProbLcToPKPi()[2]; /// non-prompt score } - registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle); + if (addSoftPiDcaToSigmacSparse) { + 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 { + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle); + } } else { /// fill w/o BDT information - registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, decLengthLc, decLengthXYLc, cpaLc, cpaXYLc, origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle); + if (addSoftPiDcaToSigmacSparse) { + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, decLengthLc, decLengthXYLc, cpaLc, cpaXYLc, origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle, softPiAbsDcaXY, softPiAbsDcaZ); + } else { + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, decLengthLc, decLengthXYLc, cpaLc, cpaXYLc, origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle); + } } } @@ -941,6 +991,8 @@ struct HfTaskSigmac { /// THn for candidate Σc0,++ cut variation if (enableTHn) { int8_t particleAntiparticle = candSc.particleAntiparticle(); + const float softPiAbsDcaXY = std::abs(candSc.softPiDcaXY()); + const float softPiAbsDcaZ = std::abs(candSc.softPiDcaZ()); if constexpr (useMl) { /// fill with ML information /// BDT index 0: bkg score; BDT index 2: non-prompt score @@ -949,10 +1001,18 @@ struct HfTaskSigmac { outputMl.at(0) = candidateLc.mlProbLcToPiKP()[0]; /// bkg score outputMl.at(1) = candidateLc.mlProbLcToPiKP()[2]; /// non-prompt score } - registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle); + if (addSoftPiDcaToSigmacSparse) { + 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 { + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle); + } } else { /// fill w/o BDT information - registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, decLengthLc, decLengthXYLc, cpaLc, cpaXYLc, origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle); + if (addSoftPiDcaToSigmacSparse) { + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, decLengthLc, decLengthXYLc, cpaLc, cpaXYLc, origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle, softPiAbsDcaXY, softPiAbsDcaZ); + } else { + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, decLengthLc, decLengthXYLc, cpaLc, cpaXYLc, origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle); + } } } @@ -1052,6 +1112,8 @@ struct HfTaskSigmac { /// THn for candidate Σc0,++ cut variation if (enableTHn) { int8_t particleAntiparticle = candSc.particleAntiparticle(); + const float softPiAbsDcaXY = std::abs(candSc.softPiDcaXY()); + const float softPiAbsDcaZ = std::abs(candSc.softPiDcaZ()); if constexpr (useMl) { /// fill with ML information /// BDT index 0: bkg score; BDT index 2: non-prompt score @@ -1060,10 +1122,18 @@ struct HfTaskSigmac { outputMl.at(0) = candidateLc.mlProbLcToPKPi()[0]; /// bkg score outputMl.at(1) = candidateLc.mlProbLcToPKPi()[2]; /// non-prompt score } - registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle); + if (addSoftPiDcaToSigmacSparse) { + 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 { + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle); + } } else { /// fill w/o BDT information - registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, decLengthLc, decLengthXYLc, cpaLc, cpaXYLc, origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle); + if (addSoftPiDcaToSigmacSparse) { + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, decLengthLc, decLengthXYLc, cpaLc, cpaXYLc, origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle, softPiAbsDcaXY, softPiAbsDcaZ); + } else { + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, decLengthLc, decLengthXYLc, cpaLc, cpaXYLc, origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle); + } } } @@ -1125,6 +1195,8 @@ struct HfTaskSigmac { /// THn for candidate Σc0,++ cut variation if (enableTHn) { int8_t particleAntiparticle = candSc.particleAntiparticle(); + const float softPiAbsDcaXY = std::abs(candSc.softPiDcaXY()); + const float softPiAbsDcaZ = std::abs(candSc.softPiDcaZ()); if constexpr (useMl) { /// fill with ML information /// BDT index 0: bkg score; BDT index 2: non-prompt score @@ -1133,10 +1205,18 @@ struct HfTaskSigmac { outputMl.at(0) = candidateLc.mlProbLcToPiKP()[0]; /// bkg score outputMl.at(1) = candidateLc.mlProbLcToPiKP()[2]; /// non-prompt score } - registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle); + if (addSoftPiDcaToSigmacSparse) { + 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 { + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle); + } } else { /// fill w/o BDT information - registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, decLengthLc, decLengthXYLc, cpaLc, cpaXYLc, origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle); + if (addSoftPiDcaToSigmacSparse) { + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, decLengthLc, decLengthXYLc, cpaLc, cpaXYLc, origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle, softPiAbsDcaXY, softPiAbsDcaZ); + } else { + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, decLengthLc, decLengthXYLc, cpaLc, cpaXYLc, origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle); + } } } diff --git a/PWGHF/DataModel/CandidateReconstructionTables.h b/PWGHF/DataModel/CandidateReconstructionTables.h index 0365c5333d9..83b9a594912 100644 --- a/PWGHF/DataModel/CandidateReconstructionTables.h +++ b/PWGHF/DataModel/CandidateReconstructionTables.h @@ -2314,6 +2314,8 @@ DECLARE_SOA_INDEX_COLUMN_FULL(ProngLc, prongLc, int, HfCand3Prong, ""); DECLARE_SOA_COLUMN(Charge, charge, int8_t); //! // Σc charge(either 0 or ++) DECLARE_SOA_COLUMN(StatusSpreadLcMinvPKPiFromPDG, statusSpreadLcMinvPKPiFromPDG, int); //! // Λc Minv(pKpi) spread from PDG Λc mass DECLARE_SOA_COLUMN(StatusSpreadLcMinvPiKPFromPDG, statusSpreadLcMinvPiKPFromPDG, int); //! // Λc Minv(piKp) spread from PDG Λc mass +DECLARE_SOA_COLUMN(SoftPiDcaXY, softPiDcaXY, float); //! soft-pion impact parameter in xy +DECLARE_SOA_COLUMN(SoftPiDcaZ, softPiDcaZ, float); //! soft-pion impact parameter in z DECLARE_SOA_INDEX_COLUMN_FULL(Prong0, prong0, int, HfCand3Prong, "_0"); //! Λc index // MC matching result: DECLARE_SOA_COLUMN(FlagMcMatchRec, flagMcMatchRec, int8_t); //! reconstruction level @@ -2357,6 +2359,7 @@ DECLARE_SOA_TABLE(HfCandScBase, "AOD", "HFCANDSCBASE", /* Σc0,++ specific columns */ hf_cand_sigmac::Charge, hf_cand_sigmac::StatusSpreadLcMinvPKPiFromPDG, hf_cand_sigmac::StatusSpreadLcMinvPiKPFromPDG, + hf_cand_sigmac::SoftPiDcaXY, hf_cand_sigmac::SoftPiDcaZ, /* prong 0 */ // hf_cand::ImpactParameterNormalised0, hf_cand::PtProng0, diff --git a/PWGHF/TableProducer/candidateCreatorSigmac0plusplus.cxx b/PWGHF/TableProducer/candidateCreatorSigmac0plusplus.cxx index c8dbbf04b2b..3e9bf3fe4f5 100644 --- a/PWGHF/TableProducer/candidateCreatorSigmac0plusplus.cxx +++ b/PWGHF/TableProducer/candidateCreatorSigmac0plusplus.cxx @@ -15,9 +15,17 @@ /// /// \author Mattia Faggin , University and INFN PADOVA -#include -#include -#include +#include "PWGHF/Core/HfHelper.h" +#include "PWGHF/Core/SelectorCuts.h" +#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "PWGHF/Utils/utilsBfieldCCDB.h" // for dca recalculation +#include "PWGHF/Utils/utilsEvSelHf.h" + +#include "Common/Core/TrackSelection.h" +#include "Common/Core/TrackSelectionDefaults.h" +#include "Common/Core/trackUtilities.h" +#include "Common/DataModel/CollisionAssociationTables.h" #include "CCDB/BasicCCDBManager.h" // for dca recalculation #include "CommonConstants/PhysicsConstants.h" @@ -27,20 +35,12 @@ #include "DetectorsBase/Propagator.h" // for dca recalculation #include "DetectorsVertexing/PVertexer.h" // for dca recalculation #include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" #include "Framework/RunningWorkflowInfo.h" +#include "Framework/runDataProcessing.h" -#include "Common/Core/TrackSelection.h" -#include "Common/Core/trackUtilities.h" -#include "Common/DataModel/CollisionAssociationTables.h" -#include "Common/Core/TrackSelectionDefaults.h" - -#include "PWGHF/Core/HfHelper.h" -#include "PWGHF/Core/SelectorCuts.h" -#include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" -#include "PWGHF/Utils/utilsBfieldCCDB.h" // for dca recalculation -#include "PWGHF/Utils/utilsEvSelHf.h" +#include +#include +#include using namespace o2; using namespace o2::analysis; @@ -172,7 +172,7 @@ struct HfCandidateCreatorSigmac0plusplus { /// @param candidates are 3-prong candidates satisfying the analysis selections for Λc+ → pK-π+ (and charge conj.) /// @param tracks are the tracks (with dcaXY, dcaZ information) → soft-pion candidate tracks template - void makeSoftPiLcPair(TRK const& trackSoftPi, CAND const& candidatesThisColl, aod::TracksWDcaExtra const&) + void makeSoftPiLcPair(const std::array softPiDca, TRK const& trackSoftPi, CAND const& candidatesThisColl, aod::TracksWDcaExtra const&) { /// loop over Λc+ → pK-π+ (and charge conj.) candidates @@ -253,7 +253,8 @@ struct HfCandidateCreatorSigmac0plusplus { candLc.hfflag(), /* Σc0,++ specific columns */ chargeSigmac, - statusSpreadMinvPKPiFromPDG, statusSpreadMinvPiKPFromPDG); + statusSpreadMinvPKPiFromPDG, statusSpreadMinvPiKPFromPDG, + softPiDca[0], softPiDca[1]); } /// end loop over Λc+ → pK-π+ (and charge conj.) candidates } /// end makeSoftPiLcPair @@ -278,6 +279,7 @@ struct HfCandidateCreatorSigmac0plusplus { if (!softPiCuts.IsSelected(trackSoftPi)) { return; } + std::array softPiDca = {-999.f, -999.f}; if constexpr (withTimeAssoc) { /// dcaXY, dcaZ selections /// To be done separately from the others, because for reassigned tracks the dca must be recalculated @@ -285,9 +287,8 @@ struct HfCandidateCreatorSigmac0plusplus { if (trackSoftPi.collisionId() == thisCollId) { /// this is a track originally assigned to the current collision /// therefore, the dcaXY, dcaZ are those already calculated in the track-propagation workflow - if (std::abs(trackSoftPi.dcaXY()) > softPiDcaXYMax || std::abs(trackSoftPi.dcaZ()) > softPiDcaZMax) { - return; - } + softPiDca[0] = trackSoftPi.dcaXY(); + softPiDca[1] = trackSoftPi.dcaZ(); } else { /// this is a reassigned track /// therefore we need to calculate the dcaXY, dcaZ with respect to this new primary vertex @@ -296,17 +297,19 @@ struct HfCandidateCreatorSigmac0plusplus { auto trackParSoftPi = getTrackPar(trackSoftPi); std::array dcaInfo{-999., -999.}; o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, trackParSoftPi, 2.f, noMatCorr, &dcaInfo); - if (std::abs(dcaInfo[0]) > softPiDcaXYMax || std::abs(dcaInfo[1]) > softPiDcaZMax) { - return; - } + softPiDca[0] = dcaInfo[0]; + softPiDca[1] = dcaInfo[1]; } } else { /// this is a track originally assigned to the current collision /// therefore, the dcaXY, dcaZ are those already calculated in the track-propagation workflow /// No need to consider the time-reassociated tracks, since withTimeAssoc == false here - if (std::abs(trackSoftPi.dcaXY()) > softPiDcaXYMax || std::abs(trackSoftPi.dcaZ()) > softPiDcaZMax) { - return; - } + softPiDca[0] = trackSoftPi.dcaXY(); + softPiDca[1] = trackSoftPi.dcaZ(); + } + if (std::abs(softPiDca[0]) > softPiDcaXYMax || std::abs(softPiDca[1]) > softPiDcaZMax) { + /// soft-pion dca too large, reject the candidate + return; } histos.fill(HIST("hCounter"), 3); @@ -314,10 +317,10 @@ struct HfCandidateCreatorSigmac0plusplus { if constexpr (withTimeAssoc) { /// need to group candidates manually auto candidatesThisColl = candidates.sliceBy(hf3ProngPerCollision, thisCollId); - makeSoftPiLcPair(trackSoftPi, candidatesThisColl, tracks); + makeSoftPiLcPair(softPiDca, trackSoftPi, candidatesThisColl, tracks); } else { /// tracks and candidates already grouped by collision at the level of process function - makeSoftPiLcPair(trackSoftPi, candidates, tracks); + makeSoftPiLcPair(softPiDca, trackSoftPi, candidates, tracks); } } /// end createSigmaC From 503597df87d66e08a3284088a6cff75f7a4bdf3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADt=20Ku=C4=8Dera?= Date: Thu, 19 Jun 2025 12:38:32 +0200 Subject: [PATCH 142/871] [PWGHF] Hard-code values of decay channels (#11682) --- PWGHF/Core/DecayChannels.h | 206 ++++++++++++++++++------------------- 1 file changed, 103 insertions(+), 103 deletions(-) diff --git a/PWGHF/Core/DecayChannels.h b/PWGHF/Core/DecayChannels.h index 986ad0b0c88..4b5abd12735 100644 --- a/PWGHF/Core/DecayChannels.h +++ b/PWGHF/Core/DecayChannels.h @@ -35,23 +35,23 @@ namespace hf_cand_2prong /// @brief 2-prong candidates: main channels enum DecayChannelMain : int8_t { // D0 - D0ToPiK = 1, // π+ K− - D0ToPiKPi0, // π+ K− π0 - D0ToPiPi, // π+ π− - D0ToPiPiPi0, // π+ π− π0 - D0ToKK, // K+ K− + D0ToPiK = 1, // π+ K− + D0ToPiKPi0 = 2, // π+ K− π0 + D0ToPiPi = 3, // π+ π− + D0ToPiPiPi0 = 4, // π+ π− π0 + D0ToKK = 5, // K+ K− // - LastChannelMain + NChannelsMain = D0ToKK // last channel }; /// @brief 2-prong candidates: resonant channels enum DecayChannelResonant : int8_t { // D0 D0ToRhoplusPi = 1, // ρ+ π− - D0ToRhoplusK, // ρ+ K− - D0ToKstar0Pi0, // anti-K*0 π0 - D0ToKstarPi, // K*− π+ + D0ToRhoplusK = 2, // ρ+ K− + D0ToKstar0Pi0 = 3, // anti-K*0 π0 + D0ToKstarPi = 4, // K*− π+ // - LastChannelResonant + NChannelsResonant = D0ToKstarPi // last channel }; } // namespace hf_cand_2prong @@ -60,73 +60,73 @@ namespace hf_cand_3prong /// @brief 3-prong candidates: main channels enum DecayChannelMain : int8_t { // D+ - DplusToPiKPi = 1, // π+ K− π+ - DplusToPiKPiPi0, // π+ K− π+ π0 - DplusToPiPiPi, // π+ π− π+ - DplusToPiKK, // π+ K− K+ + DplusToPiKPi = 1, // π+ K− π+ + DplusToPiKPiPi0 = 2, // π+ K− π+ π0 + DplusToPiPiPi = 3, // π+ π− π+ + DplusToPiKK = 4, // π+ K− K+ // Ds+ - DsToPiKK, // π+ K− K+ - DsToPiKKPi0, // π+ K− K+ π0 - DsToPiPiK, // π+ π− K+ - DsToPiPiPi, // π+ π− π+ - DsToPiPiPiPi0, // π+ π− π+ π0 + DsToPiKK = 5, // π+ K− K+ + DsToPiKKPi0 = 6, // π+ K− K+ π0 + DsToPiPiK = 7, // π+ π− K+ + DsToPiPiPi = 8, // π+ π− π+ + DsToPiPiPiPi0 = 9, // π+ π− π+ π0 // D*+ - DstarToPiKPi, // π+ K− π+ (from [(D0 → π+ K−) π+]) - DstarToPiKPiPi0, // π+ K− π+ π0 - DstarToPiKPiPi0Pi0, // π+ K− π+ π0 π0 - DstarToPiKK, // π+ K− K+ - DstarToPiKKPi0, // π+ K− K+ π0 - DstarToPiPiPi, // π+ π− π+ - DstarToPiPiPiPi0, // π+ π− π+ π0 + DstarToPiKPi = 10, // π+ K− π+ (from [(D0 → π+ K−) π+]) + DstarToPiKPiPi0 = 11, // π+ K− π+ π0 + DstarToPiKPiPi0Pi0 = 12, // π+ K− π+ π0 π0 + DstarToPiKK = 13, // π+ K− K+ + DstarToPiKKPi0 = 14, // π+ K− K+ π0 + DstarToPiPiPi = 15, // π+ π− π+ + DstarToPiPiPiPi0 = 16, // π+ π− π+ π0 // Λc+ - LcToPKPi, // p K− π+ - LcToPKPiPi0, // p K− π+ π0 - LcToPPiPi, // p π− π+ - LcToPKK, // p K− K+ + LcToPKPi = 17, // p K− π+ + LcToPKPiPi0 = 18, // p K− π+ π0 + LcToPPiPi = 19, // p π− π+ + LcToPKK = 20, // p K− K+ // Ξc+ - XicToPKPi, // p K− π+ - XicToPKK, // p K− K+ - XicToSPiPi, // Σ+ π− π+ + XicToPKPi = 21, // p K− π+ + XicToPKK = 22, // p K− K+ + XicToSPiPi = 23, // Σ+ π− π+ // - LastChannelMain + NChannelsMain = XicToSPiPi // last channel }; /// @brief 3-prong candidates: resonant channels enum DecayChannelResonant : int8_t { // D+ - DplusToPhiPi = 1, // φ π+ - DplusToKstar0K, // anti-K*0 K+ - DplusToKstar1430_0K, // anti-K*0(1430) K+ - DplusToRho0Pi, // ρ0 π+ - DplusToF2_1270Pi, // f2(1270) π+ + DplusToPhiPi = 1, // φ π+ + DplusToKstar0K = 2, // anti-K*0 K+ + DplusToKstar1430_0K = 3, // anti-K*0(1430) K+ + DplusToRho0Pi = 4, // ρ0 π+ + DplusToF2_1270Pi = 5, // f2(1270) π+ // Ds+ - DsToPhiPi, // φ π+ - DsToPhiRhoplus, // φ ρ+ - DsToKstar0K, // anti-K*0 K+ - DsToKstar0Pi, // anti-K*0 π+ - DsToRho0Pi, // ρ0 π+ - DsToRho0K, // ρ0 K+ - DsToF2_1270Pi, // f2(1270) π+ - DsToF0_1370K, // f0(1370) K+ - DsToEtaPi, // η π+ + DsToPhiPi = 6, // φ π+ + DsToPhiRhoplus = 7, // φ ρ+ + DsToKstar0K = 8, // anti-K*0 K+ + DsToKstar0Pi = 9, // anti-K*0 π+ + DsToRho0Pi = 10, // ρ0 π+ + DsToRho0K = 11, // ρ0 K+ + DsToF2_1270Pi = 12, // f2(1270) π+ + DsToF0_1370K = 13, // f0(1370) K+ + DsToEtaPi = 14, // η π+ // D*+ - DstarToD0ToRhoplusPi, // ρ+ π− - DstarToD0ToRhoplusK, // ρ+ K− - DstarToD0ToKstar0Pi0, // anti-K*0 π0 - DstarToD0ToKstarPi, // K*− π+ - DstarToDplusToPhiPi, // φ π+ - DstarToDplusToKstar0K, // anti-K*0 K+ - DstarToDplusToKstar1430_0K, // anti-K*0(1430) K+ - DstarToDplusToRho0Pi, // ρ0 π+ - DstarToDplusToF2_1270Pi, // f2(1270) π+ + DstarToD0ToRhoplusPi = 15, // ρ+ π− + DstarToD0ToRhoplusK = 16, // ρ+ K− + DstarToD0ToKstar0Pi0 = 17, // anti-K*0 π0 + DstarToD0ToKstarPi = 18, // K*− π+ + DstarToDplusToPhiPi = 19, // φ π+ + DstarToDplusToKstar0K = 20, // anti-K*0 K+ + DstarToDplusToKstar1430_0K = 21, // anti-K*0(1430) K+ + DstarToDplusToRho0Pi = 22, // ρ0 π+ + DstarToDplusToF2_1270Pi = 23, // f2(1270) π+ // Λc+ - LcToPKstar0, // p K*0(892) - LcToDeltaplusplusK, // Δ++ K− - LcToL1520Pi, // Λ(1520) π+ + LcToPKstar0 = 24, // p K*0(892) + LcToDeltaplusplusK = 25, // Δ++ K− + LcToL1520Pi = 26, // Λ(1520) π+ // Ξc+ - XicToPKstar0, // p anti-K*0(892) - XicToPPhi, // p φ + XicToPKstar0 = 27, // p anti-K*0(892) + XicToPPhi = 28, // p φ // - LastChannelResonant + NChannelsResonant = XicToPPhi // last channel }; } // namespace hf_cand_3prong @@ -135,10 +135,10 @@ namespace hf_cand_dstar /// @brief D*+ candidates: main channels enum DecayChannelMain : int8_t { // D*+ - DstarToPiKPi = 1, // π+ K− π+ (from [(D0 → π+ K−) π+]) - DstarToPiKPiPi0, // π+ K− π+ π0 (from [(D0 → π+ K− π0) π+] or [(D+ → π+ K− π+) π0]) + DstarToPiKPi = 1, // π+ K− π+ (from [(D0 → π+ K−) π+]) + DstarToPiKPiPi0 = 2, // π+ K− π+ π0 (from [(D0 → π+ K− π0) π+] or [(D+ → π+ K− π+) π0]) // - LastChannelMain + NChannelsMain = DstarToPiKPiPi0 // last channel }; } // namespace hf_cand_dstar @@ -147,72 +147,72 @@ namespace hf_cand_beauty /// @brief beauty candidates: main channels enum DecayChannelMain : int8_t { // B0 - B0ToDminusPi = 1, // D− π+ - B0ToDminusPiPi0, // D− π+ π0 - B0ToDminusPiGamma, // D− π+ γ0 - B0ToDminusK, // D− K+ - B0ToD0PiPi, // anti-D0 π+ π− + B0ToDminusPi = 1, // D− π+ + B0ToDminusPiPi0 = 2, // D− π+ π0 + B0ToDminusPiGamma = 3, // D− π+ γ0 + B0ToDminusK = 4, // D− K+ + B0ToD0PiPi = 5, // anti-D0 π+ // Bs0 - BsToDsPi, // Ds− π+ - BsToDsPiPi0, // Ds− π+ π0 - BsToDsPiGamma, // Ds− π+ γ0 - BsToDsK, // Ds− K+ + BsToDsPi = 6, // Ds− π+ + BsToDsPiPi0 = 7, // Ds− π+ π0 + BsToDsPiGamma = 8, // Ds− π+ γ0 + BsToDsK = 9, // Ds− K+ // Λb0 - LbToLcPi, // Λc+ π− - LbToLcPiPi0, // Λc+ π− π0 - LbToLcPiGamma, // Λc+ π− γ0 - LbToLcK, // Λc+ K− - LbToLcKPi0, // Λc+ K− π0 + LbToLcPi = 10, // Λc+ π− + LbToLcPiPi0 = 11, // Λc+ π− π0 + LbToLcPiGamma = 12, // Λc+ π− γ0 + LbToLcK = 13, // Λc+ K− + LbToLcKPi0 = 14, // Λc+ K− π0 // B+ - BplusToD0Pi, // anti-D0 π+ - BplusToD0PiPi0, // anti-D0 π+ π0 - BplusToD0PiGamma, // anti-D0 π+ γ0 - BplusToD0K, // anti-D0 K+ + BplusToD0Pi = 15, // anti-D0 π+ + BplusToD0PiPi0 = 16, // anti-D0 π+ π0 + BplusToD0PiGamma = 17, // anti-D0 π+ γ0 + BplusToD0K = 18, // anti-D0 K+ // - LastChannelMain + NChannelsMain = BplusToD0K // last channel }; /// @brief beauty candidates: resonant channels enum DecayChannelResonant : int8_t { // B0 B0ToDminusRhoplus = 1, // D− ρ+ - B0ToDstarminusPi, // D*− π+ + B0ToDstarminusPi = 2, // D*− π+ // Bs0 - BsToDsRhoplus, // Ds− ρ+ - BsToDsstarPi, // Ds*− π+ + BsToDsRhoplus = 3, // Ds− ρ+ + BsToDsstarPi = 4, // Ds*− π+ // Λb0 - LbToLcRhoplus, // Λc+ ρ− - LbToScPi, // Σc+ π− - LbToScK, // Σc+ K− - LbToSc0Pi0, // Σc0 π0 + LbToLcRhoplus = 5, // Λc+ ρ− + LbToScPi = 6, // Σc+ π− + LbToScK = 7, // Σc+ K− + LbToSc0Pi0 = 8, // Σc0 π0 // B+ - BplusToD0Rhoplus, // anti-D0 ρ+ - BplusToDstar0Pi, // anti-D*0 π+ + BplusToD0Rhoplus = 9, // anti-D0 ρ+ + BplusToDstar0Pi = 10, // anti-D*0 π+ // - LastChannelResonant + NChannelsResonant = BplusToDstar0Pi // last channel }; /// @brief beauty candidates: beauty to J/ψ decay channels enum DecayChannelToJpsiMain : int8_t { // B0 - B0ToJpsiPiK = 1, // J/ψ π- K+ + B0ToJpsiPiK = 1, // J/ψ π− K+ // Bs0 - BsToJpsiKK, // J/ψ K+ K- + BsToJpsiKK = 2, // J/ψ K+ K− // Λb0 - LbToJpsiPK, // J/ψ p K- + LbToJpsiPK = 3, // J/ψ p K− // B+ - BplusToJpsiK, // J/ψ K+ + BplusToJpsiK = 4, // J/ψ K+ // Bc+ - BcToJpsiPi, // J/ψ π+ + BcToJpsiPi = 5, // J/ψ π+ // - LastChannelToJpsiMain + NChannelsToJpsiMain = BcToJpsiPi // last channel }; /// @brief beauty candidates: beauty to J/ψ resonant decay channels enum DecayChannelToJpsiResonant : int8_t { // B0 B0ToJpsiKstar0 = 1, // J/ψ K*0(892) // Bs0 - BsToJpsiPhi, // J/ψ φ + BsToJpsiPhi = 2, // J/ψ φ // - LastChannelToJpsiResonant + NChannelsToJpsiResonant = BsToJpsiPhi // last channel }; } // namespace hf_cand_beauty } // namespace o2::hf_decay From ee37b1e6b68ab4e54a427a6dad6a4e72ac359a3d Mon Sep 17 00:00:00 2001 From: Jan Fiete Date: Thu, 19 Jun 2025 14:04:47 +0200 Subject: [PATCH 143/871] [PWGCF] efficiency species bin for extra particle (#11679) --- PWGCF/Core/CorrelationContainer.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PWGCF/Core/CorrelationContainer.cxx b/PWGCF/Core/CorrelationContainer.cxx index 4a68f667350..22918f98b0d 100644 --- a/PWGCF/Core/CorrelationContainer.cxx +++ b/PWGCF/Core/CorrelationContainer.cxx @@ -115,7 +115,7 @@ CorrelationContainer::CorrelationContainer(const char* name, const char* objTitl triggerAxis.insert(triggerAxis.end(), userAxis.begin(), userAxis.end()); mTriggerHist = HistFactory::createHist({"mTriggerHist", "d^{2}N_{ch}/d#varphid#eta", {HistType::kStepTHnF, triggerAxis, fgkCFSteps}}).release(); - mTrackHistEfficiency = HistFactory::createHist({"mTrackHistEfficiency", "Tracking efficiency", {HistType::kStepTHnD, {efficiencyAxis[0], efficiencyAxis[1], {4, -0.5, 3.5, "species"}, correlationAxis[3], efficiencyAxis[2]}, fgkCFSteps}}).release(); + mTrackHistEfficiency = HistFactory::createHist({"mTrackHistEfficiency", "Tracking efficiency", {HistType::kStepTHnD, {efficiencyAxis[0], efficiencyAxis[1], {5, -0.5, 4.5, "species"}, correlationAxis[3], efficiencyAxis[2]}, fgkCFSteps}}).release(); mEventCount = HistFactory::createHist({"mEventCount", ";step;centrality;count", {HistType::kTH2F, {{fgkCFSteps + 2, -2.5, -0.5 + fgkCFSteps, "step"}, correlationAxis[3]}}}).release(); } From 9fe70f3d8442c0b892e33a710426a039b3e52a6b Mon Sep 17 00:00:00 2001 From: Ida Storehaug <38440296+torkjellsdatter@users.noreply.github.com> Date: Thu, 19 Jun 2025 15:35:01 +0200 Subject: [PATCH 144/871] [PWGDQ] Tasks/dqEfficiency_withAssoc: Extended B meson table (#11685) Co-authored-by: Ida Torkjellsdatter Storehaug Co-authored-by: ALICE Action Bot --- PWGDQ/Tasks/dqEfficiency_withAssoc.cxx | 70 +++++++++++++++++++++++--- PWGDQ/Tasks/tableReader_withAssoc.cxx | 12 ++--- 2 files changed, 68 insertions(+), 14 deletions(-) diff --git a/PWGDQ/Tasks/dqEfficiency_withAssoc.cxx b/PWGDQ/Tasks/dqEfficiency_withAssoc.cxx index cc4cba21d79..397502ed020 100644 --- a/PWGDQ/Tasks/dqEfficiency_withAssoc.cxx +++ b/PWGDQ/Tasks/dqEfficiency_withAssoc.cxx @@ -84,7 +84,42 @@ DECLARE_SOA_COLUMN(TauxyBcandidate, tauxyBcandidate, float); DECLARE_SOA_COLUMN(TauzBcandidate, tauzBcandidate, float); DECLARE_SOA_COLUMN(CosPBcandidate, cosPBcandidate, float); DECLARE_SOA_COLUMN(Chi2Bcandidate, chi2Bcandidate, float); -DECLARE_SOA_COLUMN(DCAxyzBetweenProngs, dcaxyzBetweenProngs, float); +DECLARE_SOA_COLUMN(PINassoc, pINassoc, float); +DECLARE_SOA_COLUMN(Etaassoc, etaassoc, float); +DECLARE_SOA_COLUMN(Ptpair, ptpair, float); +DECLARE_SOA_COLUMN(Etapair, etapair, float); +DECLARE_SOA_COLUMN(PINleg1, pINleg1, float); +DECLARE_SOA_COLUMN(Etaleg1, etaleg1, float); +DECLARE_SOA_COLUMN(PINleg2, pINleg2, float); +DECLARE_SOA_COLUMN(Etaleg2, etaleg2, float); +DECLARE_SOA_COLUMN(TPCnsigmaKaassoc, tpcnsigmaKaassoc, float); +DECLARE_SOA_COLUMN(TPCnsigmaPiassoc, tpcnsigmaPiassoc, float); +DECLARE_SOA_COLUMN(TPCnsigmaPrassoc, tpcnsigmaPrassoc, float); +DECLARE_SOA_COLUMN(TOFnsigmaKaassoc, tofnsigmaKaassoc, float); +DECLARE_SOA_COLUMN(TPCnsigmaElleg1, tpcnsigmaElleg1, float); +DECLARE_SOA_COLUMN(TPCnsigmaPileg1, tpcnsigmaPileg1, float); +DECLARE_SOA_COLUMN(TPCnsigmaPrleg1, tpcnsigmaPrleg1, float); +DECLARE_SOA_COLUMN(TPCnsigmaElleg2, tpcnsigmaElleg2, float); +DECLARE_SOA_COLUMN(TPCnsigmaPileg2, tpcnsigmaPileg2, float); +DECLARE_SOA_COLUMN(TPCnsigmaPrleg2, tpcnsigmaPrleg2, float); +DECLARE_SOA_COLUMN(DCAXYassoc, dcaXYassoc, float); +DECLARE_SOA_COLUMN(DCAZassoc, dcaZassoc, float); +DECLARE_SOA_COLUMN(DCAXYleg1, dcaXYleg1, float); +DECLARE_SOA_COLUMN(DCAZleg1, dcaZleg1, float); +DECLARE_SOA_COLUMN(DCAXYleg2, dcaXYleg2, float); +DECLARE_SOA_COLUMN(DCAZleg2, dcaZleg2, float); +DECLARE_SOA_COLUMN(ITSClusterMapassoc, itsClusterMapassoc, uint8_t); +DECLARE_SOA_COLUMN(ITSClusterMapleg1, itsClusterMapleg1, uint8_t); +DECLARE_SOA_COLUMN(ITSClusterMapleg2, itsClusterMapleg2, uint8_t); +DECLARE_SOA_COLUMN(ITSChi2assoc, itsChi2assoc, float); +DECLARE_SOA_COLUMN(ITSChi2leg1, itsChi2leg1, float); +DECLARE_SOA_COLUMN(ITSChi2leg2, itsChi2leg2, float); +DECLARE_SOA_COLUMN(TPCNclsassoc, tpcNclsassoc, float); +DECLARE_SOA_COLUMN(TPCNclsleg1, tpcNclsleg1, float); +DECLARE_SOA_COLUMN(TPCNclsleg2, tpcNclsleg2, float); +DECLARE_SOA_COLUMN(TPCChi2assoc, tpcChi2assoc, float); +DECLARE_SOA_COLUMN(TPCChi2leg1, tpcChi2leg1, float); +DECLARE_SOA_COLUMN(TPCChi2leg2, tpcChi2leg2, float); DECLARE_SOA_COLUMN(McFlag, mcFlag, int8_t); DECLARE_SOA_BITMAP_COLUMN(IsJpsiFromBSelected, isJpsiFromBSelected, 32); // Candidate columns for prompt-non-prompt JPsi separation @@ -107,8 +142,17 @@ DECLARE_SOA_TABLE(Prefilter, "AOD", "DQPREFILTER", dqanalysisflags::IsBarrelSele DECLARE_SOA_TABLE(BmesonCandidates, "AOD", "DQBMESONS", dqanalysisflags::massBcandidate, dqanalysisflags::MassDileptonCandidate, dqanalysisflags::deltaMassBcandidate, dqanalysisflags::pTBcandidate, dqanalysisflags::LxyBcandidate, dqanalysisflags::LxyzBcandidate, dqanalysisflags::LzBcandidate, - dqanalysisflags::TauxyBcandidate, dqanalysisflags::TauzBcandidate, dqanalysisflags::DCAxyzBetweenProngs, - dqanalysisflags::CosPBcandidate, dqanalysisflags::Chi2Bcandidate, + dqanalysisflags::TauxyBcandidate, dqanalysisflags::TauzBcandidate, dqanalysisflags::CosPBcandidate, dqanalysisflags::Chi2Bcandidate, + dqanalysisflags::PINassoc, dqanalysisflags::Etaassoc, dqanalysisflags::Ptpair, dqanalysisflags::Etapair, + dqanalysisflags::PINleg1, dqanalysisflags::Etaleg1, dqanalysisflags::PINleg2, dqanalysisflags::Etaleg2, + dqanalysisflags::TPCnsigmaKaassoc, dqanalysisflags::TPCnsigmaPiassoc, dqanalysisflags::TPCnsigmaPrassoc, dqanalysisflags::TOFnsigmaKaassoc, + dqanalysisflags::TPCnsigmaElleg1, dqanalysisflags::TPCnsigmaPileg1, dqanalysisflags::TPCnsigmaPrleg1, + dqanalysisflags::TPCnsigmaElleg2, dqanalysisflags::TPCnsigmaPileg2, dqanalysisflags::TPCnsigmaPrleg2, + dqanalysisflags::DCAXYassoc, dqanalysisflags::DCAZassoc, dqanalysisflags::DCAXYleg1, dqanalysisflags::DCAZleg1, dqanalysisflags::DCAXYleg2, dqanalysisflags::DCAZleg2, + dqanalysisflags::ITSClusterMapassoc, dqanalysisflags::ITSClusterMapleg1, dqanalysisflags::ITSClusterMapleg2, + dqanalysisflags::ITSChi2assoc, dqanalysisflags::ITSChi2leg1, dqanalysisflags::ITSChi2leg2, + dqanalysisflags::TPCNclsassoc, dqanalysisflags::TPCNclsleg1, dqanalysisflags::TPCNclsleg2, + dqanalysisflags::TPCChi2assoc, dqanalysisflags::TPCChi2leg1, dqanalysisflags::TPCChi2leg2, dqanalysisflags::IsJpsiFromBSelected, dqanalysisflags::IsBarrelSelected, dqanalysisflags::McFlag); DECLARE_SOA_TABLE(JPsieeCandidates, "AOD", "DQPSEUDOPROPER", dqanalysisflags::Massee, dqanalysisflags::Ptee, dqanalysisflags::Lxyee, dqanalysisflags::LxyeePoleMass, dqanalysisflags::Lzee, dqanalysisflags::AmbiguousInBunchPairs, dqanalysisflags::AmbiguousOutOfBunchPairs, dqanalysisflags::Corrassoc); } // namespace o2::aod @@ -3630,6 +3674,21 @@ struct AnalysisDileptonTrack { mcDecision |= (static_cast(1) << isig); } } + // table to be written out for ML analysis + BmesonsTable(fValuesHadron[VarManager::kPairMass], dilepton.mass(), fValuesHadron[VarManager::kDeltaMass], fValuesHadron[VarManager::kPairPt], + fValuesHadron[VarManager::kVertexingLxy], fValuesHadron[VarManager::kVertexingLxyz], fValuesHadron[VarManager::kVertexingLz], + fValuesHadron[VarManager::kVertexingTauxy], fValuesHadron[VarManager::kVertexingTauz], fValuesHadron[VarManager::kCosPointingAngle], + fValuesHadron[VarManager::kVertexingChi2PCA], + track.tpcInnerParam(), track.eta(), dilepton.pt(), dilepton.eta(), lepton1.tpcInnerParam(), lepton1.eta(), lepton2.tpcInnerParam(), lepton2.eta(), + track.tpcNSigmaKa(), track.tpcNSigmaPi(), track.tpcNSigmaPr(), track.tofNSigmaKa(), + lepton1.tpcNSigmaEl(), lepton1.tpcNSigmaPi(), lepton1.tpcNSigmaPr(), + lepton2.tpcNSigmaEl(), lepton2.tpcNSigmaPi(), lepton2.tpcNSigmaPr(), + track.dcaXY(), track.dcaZ(), lepton1.dcaXY(), lepton1.dcaZ(), lepton2.dcaXY(), lepton2.dcaZ(), + track.itsClusterMap(), lepton1.itsClusterMap(), lepton2.itsClusterMap(), + track.itsChi2NCl(), lepton1.itsChi2NCl(), lepton2.itsChi2NCl(), + track.tpcNClsFound(), lepton1.tpcNClsFound(), lepton2.tpcNClsFound(), + track.tpcChi2NCl(), lepton1.tpcChi2NCl(), lepton2.tpcChi2NCl(), + dilepton.filterMap_raw(), trackSelection, mcDecision); } if constexpr (TCandidateType == VarManager::kDstarToD0KPiPi) { @@ -3739,11 +3798,6 @@ struct AnalysisDileptonTrack { } } // end loop over track cuts } // end loop over dilepton cuts - // table to be written out for ML analysis - BmesonsTable(fValuesHadron[VarManager::kPairMass], dilepton.mass(), fValuesHadron[VarManager::kDeltaMass], fValuesHadron[VarManager::kPairPt], - fValuesHadron[VarManager::kVertexingLxy], fValuesHadron[VarManager::kVertexingLxyz], fValuesHadron[VarManager::kVertexingLz], - fValuesHadron[VarManager::kVertexingTauxy], fValuesHadron[VarManager::kVertexingTauz], fValuesHadron[VarManager::kKFDCAxyzBetweenProngs], - fValuesHadron[VarManager::kCosPointingAngle], fValuesHadron[VarManager::kVertexingChi2PCA], dilepton.filterMap_raw(), trackSelection, mcDecision); } // end loop over associations } // end loop over dileptons } diff --git a/PWGDQ/Tasks/tableReader_withAssoc.cxx b/PWGDQ/Tasks/tableReader_withAssoc.cxx index 410beb5337a..af6ea738a60 100644 --- a/PWGDQ/Tasks/tableReader_withAssoc.cxx +++ b/PWGDQ/Tasks/tableReader_withAssoc.cxx @@ -94,13 +94,13 @@ DECLARE_SOA_COLUMN(TauxyBcandidate, tauxyBcandidate, float); DECLARE_SOA_COLUMN(TauzBcandidate, tauzBcandidate, float); DECLARE_SOA_COLUMN(CosPBcandidate, cosPBcandidate, float); DECLARE_SOA_COLUMN(Chi2Bcandidate, chi2Bcandidate, float); -DECLARE_SOA_COLUMN(Ptassoc, ptassoc, float); +DECLARE_SOA_COLUMN(PINassoc, pINassoc, float); DECLARE_SOA_COLUMN(Etaassoc, etaassoc, float); DECLARE_SOA_COLUMN(Ptpair, ptpair, float); DECLARE_SOA_COLUMN(Etapair, etapair, float); -DECLARE_SOA_COLUMN(Ptleg1, ptleg1, float); +DECLARE_SOA_COLUMN(PINleg1, pINleg1, float); DECLARE_SOA_COLUMN(Etaleg1, etaleg1, float); -DECLARE_SOA_COLUMN(Ptleg2, ptleg2, float); +DECLARE_SOA_COLUMN(PINleg2, pINleg2, float); DECLARE_SOA_COLUMN(Etaleg2, etaleg2, float); DECLARE_SOA_COLUMN(TPCnsigmaKaassoc, tpcnsigmaKaassoc, float); DECLARE_SOA_COLUMN(TPCnsigmaPiassoc, tpcnsigmaPiassoc, float); @@ -152,8 +152,8 @@ DECLARE_SOA_TABLE(BmesonCandidates, "AOD", "DQBMESONSA", dqanalysisflags::massBcandidate, dqanalysisflags::MassDileptonCandidate, dqanalysisflags::deltamassBcandidate, dqanalysisflags::pTBcandidate, dqanalysisflags::EtaBcandidate, dqanalysisflags::LxyBcandidate, dqanalysisflags::LxyzBcandidate, dqanalysisflags::LzBcandidate, dqanalysisflags::TauxyBcandidate, dqanalysisflags::TauzBcandidate, dqanalysisflags::CosPBcandidate, dqanalysisflags::Chi2Bcandidate, - dqanalysisflags::Ptassoc, dqanalysisflags::Etaassoc, dqanalysisflags::Ptpair, dqanalysisflags::Etapair, - dqanalysisflags::Ptleg1, dqanalysisflags::Etaleg1, dqanalysisflags::Ptleg2, dqanalysisflags::Etaleg2, + dqanalysisflags::PINassoc, dqanalysisflags::Etaassoc, dqanalysisflags::Ptpair, dqanalysisflags::Etapair, + dqanalysisflags::PINleg1, dqanalysisflags::Etaleg1, dqanalysisflags::PINleg2, dqanalysisflags::Etaleg2, dqanalysisflags::TPCnsigmaKaassoc, dqanalysisflags::TPCnsigmaPiassoc, dqanalysisflags::TPCnsigmaPrassoc, dqanalysisflags::TOFnsigmaKaassoc, dqanalysisflags::TPCnsigmaElleg1, dqanalysisflags::TPCnsigmaPileg1, dqanalysisflags::TPCnsigmaPrleg1, dqanalysisflags::TPCnsigmaElleg2, dqanalysisflags::TPCnsigmaPileg2, dqanalysisflags::TPCnsigmaPrleg2, @@ -3268,7 +3268,7 @@ struct AnalysisDileptonTrack { fValuesHadron[VarManager::kVertexingLxy], fValuesHadron[VarManager::kVertexingLxyz], fValuesHadron[VarManager::kVertexingLz], fValuesHadron[VarManager::kVertexingTauxy], fValuesHadron[VarManager::kVertexingTauz], fValuesHadron[VarManager::kCosPointingAngle], fValuesHadron[VarManager::kVertexingChi2PCA], - track.pt(), track.eta(), dilepton.pt(), dilepton.eta(), lepton1.pt(), lepton1.eta(), lepton2.pt(), lepton2.eta(), + track.tpcInnerParam(), track.eta(), dilepton.pt(), dilepton.eta(), lepton1.tpcInnerParam(), lepton1.eta(), lepton2.tpcInnerParam(), lepton2.eta(), track.tpcNSigmaKa(), track.tpcNSigmaPi(), track.tpcNSigmaPr(), track.tofNSigmaKa(), lepton1.tpcNSigmaEl(), lepton1.tpcNSigmaPi(), lepton1.tpcNSigmaPr(), lepton2.tpcNSigmaEl(), lepton2.tpcNSigmaPi(), lepton2.tpcNSigmaPr(), From 638065ecb274f030db83f33920de0842b4381491 Mon Sep 17 00:00:00 2001 From: Noor Koster <82090643+cnkoster@users.noreply.github.com> Date: Thu, 19 Jun 2025 16:04:32 +0200 Subject: [PATCH 145/871] [PWGCF] fixed double filling of QA plots and changed multiplicity cuts to config (#11680) Co-authored-by: ALICE Action Bot --- PWGCF/Flow/TableProducer/zdcQVectors.cxx | 9 +- PWGCF/Flow/Tasks/flowSP.cxx | 241 ++++++++--------------- 2 files changed, 85 insertions(+), 165 deletions(-) diff --git a/PWGCF/Flow/TableProducer/zdcQVectors.cxx b/PWGCF/Flow/TableProducer/zdcQVectors.cxx index f8ba2cbb0b7..eda3fb76aef 100644 --- a/PWGCF/Flow/TableProducer/zdcQVectors.cxx +++ b/PWGCF/Flow/TableProducer/zdcQVectors.cxx @@ -560,6 +560,7 @@ struct ZdcQVectors { runnumber = foundBC.runNumber(); // load new calibrations for new runs only + // UPLOAD Energy calibration and vmean in 1 histogram! if (runnumber != lastRunNumber) { cal.calibfilesLoaded[2] = false; cal.calibList[2] = nullptr; @@ -587,11 +588,9 @@ struct ZdcQVectors { // load the calibrations for the mean v loadCalibrations(foundBC.timestamp(), cfgMeanv.value); - if (!cal.calibfilesLoaded[1]) { - registry.get(HIST("vmean/hvertex_vx"))->Fill(Form("%d", runnumber), v[0]); - registry.get(HIST("vmean/hvertex_vy"))->Fill(Form("%d", runnumber), v[1]); - registry.get(HIST("vmean/hvertex_vz"))->Fill(Form("%d", runnumber), v[2]); - } + registry.get(HIST("vmean/hvertex_vx"))->Fill(Form("%d", runnumber), v[0]); + registry.get(HIST("vmean/hvertex_vy"))->Fill(Form("%d", runnumber), v[1]); + registry.get(HIST("vmean/hvertex_vz"))->Fill(Form("%d", runnumber), v[2]); bool isZNAhit = true; bool isZNChit = true; diff --git a/PWGCF/Flow/Tasks/flowSP.cxx b/PWGCF/Flow/Tasks/flowSP.cxx index db8bb0df404..b8e6a4781db 100644 --- a/PWGCF/Flow/Tasks/flowSP.cxx +++ b/PWGCF/Flow/Tasks/flowSP.cxx @@ -52,18 +52,18 @@ using namespace o2::framework::expressions; struct FlowSP { // QA Plots - O2_DEFINE_CONFIGURABLE(cfgFillEventQA, bool, true, "Fill histograms for event QA"); - O2_DEFINE_CONFIGURABLE(cfgFillTrackQA, bool, true, "Fill histograms for track QA"); - O2_DEFINE_CONFIGURABLE(cfgFillPIDQA, bool, true, "Fill histograms for PID QA"); - O2_DEFINE_CONFIGURABLE(cfgFillEventPlaneQA, bool, true, "Fill histograms for Event Plane QA"); - O2_DEFINE_CONFIGURABLE(cfgFillGeneralV1Histos, bool, true, "Fill histograms for vn analysis"); - O2_DEFINE_CONFIGURABLE(cfgFillQABefore, bool, true, "Fill QA histograms before cuts, only for processData"); + 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"); // 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, true, "Flag to make and fill histos with Event Plane"); - O2_DEFINE_CONFIGURABLE(cfgFillXandYterms, bool, true, "Flag to make and fill histos for with separate x and y terms for SPM"); + 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(cfgFillPID, bool, true, "Flag to make and fill histos for PID 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"); @@ -93,10 +93,6 @@ struct FlowSP { O2_DEFINE_CONFIGURABLE(cfgTrackSelsPIDNsigma, float, 2.0, "nSigma cut for PID"); // Additional event selections O2_DEFINE_CONFIGURABLE(cfgEvSelsUseAdditionalEventCut, bool, true, "Bool to enable Additional Event Cut"); - O2_DEFINE_CONFIGURABLE(cfgEvSelsnSigmaMultCuts, int, 3, "Sigma cut on Additional event cut: 1, 2 or 3 (default) sigma available"); - O2_DEFINE_CONFIGURABLE(cfgEvSelsManualEventParameters, bool, false, "Use manual event parameters for the pile up fits. Needed for Cent estimaters other than FT0C"); - O2_DEFINE_CONFIGURABLE(cfgEvSelsMultPv, std::vector, {}, "Multiplicity cuts for PV first 5 parameters cutLOW last 5 cutHIGH"); - O2_DEFINE_CONFIGURABLE(cfgEvSelsMult, std::vector, {}, "Multiplicity cuts for T0C first 5 parameters cutLOW last 5 cutHIGH"); O2_DEFINE_CONFIGURABLE(cfgEvSelsMaxOccupancy, int, 10000, "Maximum occupancy of selected events"); O2_DEFINE_CONFIGURABLE(cfgEvSelsNoSameBunchPileupCut, bool, true, "kNoSameBunchPileupCut"); O2_DEFINE_CONFIGURABLE(cfgEvSelsIsGoodZvtxFT0vsPV, bool, true, "kIsGoodZvtxFT0vsPV"); @@ -110,13 +106,18 @@ struct FlowSP { O2_DEFINE_CONFIGURABLE(cfgHarmMixed1, int, 2, "Flow harmonic n for ux and uy in mixed harmonics (MH): (Cos(n*phi), Sin(n*phi))"); O2_DEFINE_CONFIGURABLE(cfgHarmMixed2, int, 3, "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, "", "ccdb dir for average QQ values in 1% centrality bins"); + O2_DEFINE_CONFIGURABLE(cfgCCDBdir_QQ, std::string, "Users/c/ckoster/ZDC/LHC23_PbPb_pass4/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, "", "ccdb dir for NUA corrections"); - O2_DEFINE_CONFIGURABLE(cfgCCDB_NUE, std::string, "", "ccdb dir for NUE corrections"); + O2_DEFINE_CONFIGURABLE(cfgCCDB_NUA, std::string, "Users/c/ckoster/flowSP/LHC23_PbPb_pass4/Default", "ccdb dir for NUA corrections"); + O2_DEFINE_CONFIGURABLE(cfgCCDB_NUE, std::string, "Users/c/ckoster/flowSP/LHC23_PbPb_pass4/NUE/Default", "ccdb dir for NUE corrections"); O2_DEFINE_CONFIGURABLE(cfgCCDBdir_centrality, std::string, "", "ccdb dir for Centrality corrections"); // Confogirable axis ConfigurableAxis axisCentrality{"axisCentrality", {10, 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{2389.99, -83.8483, 1.11062, -0.00672263, 1.54725e-05, 4067.4, -145.485, 2.27273, -0.0186308, 6.5501e-05}, "Multiplicity cuts (PV) first 5 parameters cutLOW last 5 cutHIGH (Default is +-3sigma pass4) "}; + Configurable> cfgEvSelsMult{"cfgEvSelsMult", std::vector{1048.48, -31.4568, 0.287794, -0.00046847, -3.5909e-06, 2610.98, -83.3983, 1.0893, -0.00735094, 2.26929e-05}, "Multiplicity cuts (Global) first 5 parameters cutLOW last 5 cutHIGH (Default is +-3sigma pass4) "}; 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; @@ -253,11 +254,9 @@ struct FlowSP { AxisSpec axisVz = {40, -10, 10, "v_{z}"}; AxisSpec axisCent = {90, 0, 90, "Centrality(%)"}; AxisSpec axisPhiPlane = {100, -constants::math::PI, constants::math::PI, "#Psi"}; - AxisSpec axisNch = {40, 0, 40000, "N_{ch}"}; AxisSpec axisT0c = {70, 0, 100000, "N_{ch} (T0C)"}; AxisSpec axisT0a = {70, 0, 200000, "N_{ch} (T0A)"}; AxisSpec axisV0a = {70, 0, 200000, "N_{ch} (V0A)"}; - AxisSpec axisMultpv = {40, 0, 4000, "N_{ch} (PV)"}; AxisSpec axisShCl = {40, 0, 1, "Fraction shared cl. TPC"}; AxisSpec axisCl = {80, 0, 160, "Number of cl. TPC"}; AxisSpec axisNsigma = {100, -10, 10, "Nsigma for TPC and TOF"}; @@ -278,7 +277,7 @@ struct FlowSP { 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_MultCuts + 1, "Mult cuts (Alex)"); + registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(evSel_MultCuts + 1, "Multiplicity cuts"); registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(evSel_kIsGoodITSLayersAll + 1, "kkIsGoodITSLayersAll"); registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(evSel_isSelectedZDC + 1, "isSelected"); registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(evSel_CentCuts + 1, "Cenrality range"); @@ -312,9 +311,9 @@ struct FlowSP { registry.add("QA/after/hCentFV0A", "; Cent FV0A (%); ", {HistType::kTH1D, {axisCent}}); registry.add("QA/after/hCentNGlobal", "; Cent NGlobal (%); ", {HistType::kTH1D, {axisCent}}); registry.add("QA/after/globalTracks_centT0C", "", {HistType::kTH2D, {axisCent, axisNch}}); - registry.add("QA/after/globalTracks_centNGlobal", "", {HistType::kTH2D, {axisCent, axisNch}}); + // registry.add("QA/after/globalTracks_centNGlobal", "", {HistType::kTH2D, {axisCent, axisNch}}); registry.add("QA/after/PVTracks_centT0C", "", {HistType::kTH2D, {axisCent, axisMultpv}}); - registry.add("QA/after/PVTracks_centNGlobal", "", {HistType::kTH2D, {axisCent, axisMultpv}}); + // registry.add("QA/after/PVTracks_centNGlobal", "", {HistType::kTH2D, {axisCent, axisMultpv}}); registry.add("QA/after/globalTracks_PVTracks", "", {HistType::kTH2D, {axisMultpv, axisNch}}); registry.add("QA/after/globalTracks_multT0A", "", {HistType::kTH2D, {axisT0a, axisNch}}); registry.add("QA/after/globalTracks_multV0A", "", {HistType::kTH2D, {axisV0a, axisNch}}); @@ -343,8 +342,10 @@ struct FlowSP { if (cfgFillTrackQA) { registry.add("incl/pion/QA/after/hPt", "", kTH1D, {axisPt}); registry.add("incl/pion/QA/after/hPhi", "", kTH1D, {axisPhi}); + registry.add("incl/pion/QA/after/hPhi_uncorrected", "", kTH1D, {axisPhi}); registry.add("incl/pion/QA/after/hEta", "", kTH1D, {axisEta}); registry.add("incl/pion/QA/after/hPhi_Eta_vz", "", kTH3D, {axisPhi, axisEta, axisVz}); + registry.add("incl/pion/QA/after/hPhi_Eta_vz_corrected", "", kTH3D, {axisPhi, axisEta, axisVz}); registry.add("incl/pion/QA/after/hDCAxy_pt", "", kTH2D, {axisPt, axisDCAxy}); registry.add("incl/pion/QA/after/hDCAz_pt", "", kTH2D, {axisPt, axisDCAz}); registry.add("incl/pion/QA/after/hSharedClusters_pt", "", {HistType::kTH2D, {axisPt, axisShCl}}); @@ -354,20 +355,24 @@ struct FlowSP { if (cfgFillQABefore) registry.addClone("incl/pion/QA/after/", "incl/pion/QA/before/"); } + if (cfgFillTrackQA) { registry.add("QA/after/pt_phi", "", {HistType::kTH2D, {axisPt, axisPhiMod}}); registry.add("incl/QA/after/hPt", "", kTH1D, {axisPt}); registry.add("incl/QA/after/hPhi", "", kTH1D, {axisPhi}); + registry.add("incl/QA/after/hPhi_uncorrected", "", kTH1D, {axisPhi}); registry.add("incl/QA/after/hEta", "", kTH1D, {axisEta}); registry.add("incl/QA/after/hPhi_Eta_vz", "", kTH3D, {axisPhi, axisEta, axisVz}); + registry.add("incl/QA/after/hPhi_Eta_vz_corrected", "", kTH3D, {axisPhi, axisEta, axisVz}); registry.add("incl/QA/after/hDCAxy_pt", "", kTH2D, {axisPt, axisDCAxy}); registry.add("incl/QA/after/hDCAz_pt", "", kTH2D, {axisPt, axisDCAz}); registry.add("incl/QA/after/hSharedClusters_pt", "", {HistType::kTH2D, {axisPt, axisShCl}}); registry.add("incl/QA/after/hCrossedRows_pt", "", {HistType::kTH2D, {axisPt, axisCl}}); registry.add("incl/QA/after/hCrossedRows_vs_SharedClusters", "", {HistType::kTH2D, {axisCl, axisShCl}}); + + if (cfgFillQABefore) + registry.addClone("incl/QA/after/", "incl/QA/before/"); } - if (cfgFillQABefore && (cfgFillTrackQA || cfgFillPIDQA)) - registry.addClone("incl/QA/after/", "incl/QA/before/"); if (doprocessMCReco) { registry.add("trackMCReco/after/hIsPhysicalPrimary", "", {HistType::kTH1D, {{2, 0, 2}}}); @@ -536,111 +541,26 @@ struct FlowSP { } if (cfgEvSelsUseAdditionalEventCut) { - - int twoSigma = 2; - int threeSigma = 3; - // Fitted for LHC23zzh_pass4 fMultPVCutLow = new TF1("fMultPVCutLow", "[0]+[1]*x+[2]*x*x+[3]*x*x*x+[4]*x*x*x*x", 0, 100); - - // Variables from fitting distribution with mean+1sigma - double fitParamLowPV1 = 2942.55; - double fitParamLowPV2 = -103.111; - double fitParamLowPV3 = 1.4397; - double fitParamLowPV4 = -0.00974862; - double fitParamLowPV5 = 2.71433e-05; - - if (cfgEvSelsnSigmaMultCuts == twoSigma) { - fitParamLowPV1 = 2665.68; - fitParamLowPV2 = -93.3784; - fitParamLowPV3 = 1.27137; - fitParamLowPV4 = -0.00818936; - fitParamLowPV5 = 2.115e-05; - } else if (cfgEvSelsnSigmaMultCuts == threeSigma) { - fitParamLowPV1 = 2389.99; - fitParamLowPV2 = -83.8483; - fitParamLowPV3 = 1.11062; - fitParamLowPV4 = -0.00672263; - fitParamLowPV5 = 1.54725e-05; - } - - fMultPVCutLow->SetParameters(fitParamLowPV1, fitParamLowPV2, fitParamLowPV3, fitParamLowPV4, fitParamLowPV5); - fMultPVCutHigh = new TF1("fMultPVCutHigh", "[0]+[1]*x+[2]*x*x+[3]*x*x*x+[4]*x*x*x*x", 0, 100); - - // Variables from fitting distribution with mean+1sigma - double fitParamHighPV1 = 3508.13; - double fitParamHighPV2 = -124.831; - double fitParamHighPV3 = 1.87871; - double fitParamHighPV4 = -0.0145343; - double fitParamHighPV5 = 4.80688e-05; - - if (cfgEvSelsnSigmaMultCuts == twoSigma) { - fitParamHighPV1 = 3787.93; - fitParamHighPV2 = -135.184; - fitParamHighPV3 = 2.07683; - fitParamHighPV4 = -0.0165997; - fitParamHighPV5 = 5.68725e-05; - } else if (cfgEvSelsnSigmaMultCuts == threeSigma) { - fitParamHighPV1 = 4067.4; - fitParamHighPV2 = -145.485; - fitParamHighPV3 = 2.27273; - fitParamHighPV4 = -0.0186308; - fitParamHighPV5 = 6.5501e-05; - } - fMultPVCutHigh->SetParameters(fitParamHighPV1, fitParamHighPV2, fitParamHighPV3, fitParamHighPV4, fitParamHighPV5); - fMultCutLow = new TF1("fMultCutLow", "[0]+[1]*x+[2]*x*x+[3]*x*x*x+[4]*x*x*x*x", 0, 100); - - double fitParamLow1 = 1566.5; - double fitParamLow2 = -48.2114; - double fitParamLow3 = 0.529522; - double fitParamLow4 = -0.00235284; - double fitParamLow5 = 3.01132e-06; - - if (cfgEvSelsnSigmaMultCuts == twoSigma) { - fitParamLow1 = 1307.92; - fitParamLow2 = -39.9168; - fitParamLow3 = 0.412675; - fitParamLow4 = -0.00148081; - fitParamLow5 = 1.10868e-07; - } else if (cfgEvSelsnSigmaMultCuts == threeSigma) { - fitParamLow1 = 1048.48; - fitParamLow2 = -31.4568; - fitParamLow3 = 0.287794; - fitParamLow4 = -0.00046847; - fitParamLow5 = -3.5909e-06; - } - fMultCutLow->SetParameters(fitParamLow1, fitParamLow2, fitParamLow3, fitParamLow4, fitParamLow5); - fMultCutHigh = new TF1("fMultCutHigh", "[0]+[1]*x+[2]*x*x+[3]*x*x*x+[4]*x*x*x*x", 0, 100); - double fitParamHigh1 = 2089.73; - double fitParamHigh2 = -65.9772; - double fitParamHigh3 = 0.816781; - double fitParamHigh4 = -0.00496563; - double fitParamHigh5 = 1.34314e-05; - - if (cfgEvSelsnSigmaMultCuts == twoSigma) { - fitParamHigh1 = 2350.39; - fitParamHigh2 = -74.6939; - fitParamHigh3 = 0.953287; - fitParamHigh4 = -0.006162; - fitParamHigh5 = 1.80808e-05; - } else if (cfgEvSelsnSigmaMultCuts == threeSigma) { - fitParamHigh1 = 2610.98; - fitParamHigh2 = -83.3983; - fitParamHigh3 = 1.0893; - fitParamHigh4 = -0.00735094; - fitParamHigh5 = 2.26929e-05; - } + std::vector paramsMultPVCut = cfgEvSelsMultPv; + std::vector paramsMultCut = cfgEvSelsMult; - fMultCutHigh->SetParameters(fitParamHigh1, fitParamHigh2, fitParamHigh3, fitParamHigh4, fitParamHigh5); + // number of parameters required in cfgEvSelsMultPv and cfgEvSelsMult. (5 Low + 5 High) + uint64_t nParams = 10; - if (cfgEvSelsManualEventParameters) { - fMultPVCutLow->SetParameters((cfgEvSelsMultPv.value)[0], (cfgEvSelsMultPv.value)[1], (cfgEvSelsMultPv.value)[2], (cfgEvSelsMultPv.value)[3], (cfgEvSelsMultPv.value)[4]); - fMultPVCutHigh->SetParameters((cfgEvSelsMultPv.value)[5], (cfgEvSelsMultPv.value)[6], (cfgEvSelsMultPv.value)[7], (cfgEvSelsMultPv.value)[8], (cfgEvSelsMultPv.value)[9]); - fMultCutLow->SetParameters((cfgEvSelsMult.value)[0], (cfgEvSelsMult.value)[1], (cfgEvSelsMult.value)[2], (cfgEvSelsMult.value)[3], (cfgEvSelsMult.value)[4]); - fMultCutHigh->SetParameters((cfgEvSelsMult.value)[5], (cfgEvSelsMult.value)[6], (cfgEvSelsMult.value)[7], (cfgEvSelsMult.value)[8], (cfgEvSelsMult.value)[9]); + if (paramsMultPVCut.size() < nParams) { + LOGF(fatal, "cfgEvSelsMultPv 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()); + } 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]); + fMultCutLow->SetParameters(paramsMultCut[0], paramsMultCut[1], paramsMultCut[2], paramsMultCut[3], paramsMultCut[4]); + fMultCutHigh->SetParameters(paramsMultCut[5], paramsMultCut[6], paramsMultCut[7], paramsMultCut[8], paramsMultCut[9]); } } @@ -732,7 +652,7 @@ struct FlowSP { cfg.mAcceptance.push_back(reinterpret_cast(listCorrections->FindObject("weights_negative"))); int sizeAcc = cfg.mAcceptance.size(); if (sizeAcc < nWeights) - LOGF(warning, "Could not load acceptance weights from %s", cfgCCDB_NUA.value.c_str()); + LOGF(fatal, "Could not load acceptance weights from %s", cfgCCDB_NUA.value.c_str()); else LOGF(info, "Loaded acceptance weights from %s", cfgCCDB_NUA.value.c_str()); } else { @@ -767,10 +687,11 @@ struct FlowSP { return false; weight_nue = 1. / eff; int sizeAcc = cfg.mAcceptance.size(); - if (sizeAcc > pID) + if (sizeAcc > pID) { weight_nua = cfg.mAcceptance[pID]->getNUA(phi, eta, vtxz); - else + } else { weight_nua = 1; + } return true; } @@ -1089,10 +1010,13 @@ struct FlowSP { return; static constexpr std::string_view Time[] = {"before/", "after/"}; + // NOTE: species[kUnidentified] = "" (when no PID) registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("QA/") + HIST(Time[ft]) + HIST("hPt"), track.pt(), wacc * weff); - registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("QA/") + HIST(Time[ft]) + HIST("hPhi"), track.phi(), wacc * weff); - registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("QA/") + HIST(Time[ft]) + HIST("hEta"), track.eta(), wacc * weff); - registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("QA/") + HIST(Time[ft]) + HIST("hPhi_Eta_vz"), track.phi(), track.eta(), vz, wacc * weff); + registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("QA/") + HIST(Time[ft]) + HIST("hPhi"), track.phi(), wacc); + registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("QA/") + HIST(Time[ft]) + HIST("hPhi_uncorrected"), track.phi()); + registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("QA/") + HIST(Time[ft]) + HIST("hEta"), track.eta(), wacc); + registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("QA/") + HIST(Time[ft]) + HIST("hPhi_Eta_vz"), track.phi(), track.eta(), vz); + registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("QA/") + HIST(Time[ft]) + HIST("hPhi_Eta_vz_corrected"), track.phi(), track.eta(), vz, wacc); registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("QA/") + HIST(Time[ft]) + HIST("hDCAxy_pt"), track.pt(), track.dcaXY(), wacc * weff); registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("QA/") + HIST(Time[ft]) + HIST("hDCAz_pt"), track.pt(), track.dcaZ(), wacc * weff); registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("QA/") + HIST(Time[ft]) + HIST("hSharedClusters_pt"), track.pt(), track.tpcFractionSharedCls(), wacc * weff); @@ -1167,15 +1091,15 @@ struct FlowSP { } template - void fillAllQA(TrackObject track, double vtxz, bool pos) + void fillAllQA(TrackObject track, double vtxz, bool pos, float wacc = 1, float weff = 1, float waccP = 1, float weffP = 1, float waccN = 1, float weffN = 1) { - fillTrackQA(track, vtxz); + fillTrackQA(track, vtxz, wacc, weff); fillPIDQA(track); if (pos) { - fillTrackQA(track, vtxz); + fillTrackQA(track, vtxz, waccP, weffP); fillPIDQA(track); } else { - fillTrackQA(track, vtxz); + fillTrackQA(track, vtxz, waccN, weffN); fillPIDQA(track); } } @@ -1188,10 +1112,11 @@ struct FlowSP { auto field = (cfgMagField == standardMagField) ? getMagneticField(bc.timestamp()) : cfgMagField; if (bc.runNumber() != cfg.lastRunNumber) { - // load corrections again for new run! 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()); } if (cfgFillQABefore) @@ -1333,46 +1258,46 @@ struct FlowSP { if (!trackSelected(track, field)) continue; - switch (trackPID) { - case kUnidentified: - fillAllQA(track, vtxz, pos); - break; - case kPion: - fillAllQA(track, vtxz, pos); - break; - case kKaon: - fillAllQA(track, vtxz, pos); - break; - case kProton: - fillAllQA(track, vtxz, pos); - break; - } + // constrain angle to 0 -> [0,0+2pi] + auto phi = RecoDecay::constrainAngle(track.phi(), 0); - // Fill NUA weights + // Fill NUA weights (last 0 is for Data see GFWWeights class (not a weight)) if (cfgFillWeights) { - fWeights->fill(track.phi(), track.eta(), vtxz, track.pt(), centrality, 0); + fWeights->fill(phi, track.eta(), vtxz, track.pt(), centrality, 0); } if (cfgFillWeightsPOS) { if (pos) - fWeightsPOS->fill(track.phi(), track.eta(), vtxz, track.pt(), centrality, 0); + fWeightsPOS->fill(phi, track.eta(), vtxz, track.pt(), centrality, 0); } if (cfgFillWeightsNEG) { if (!pos) - fWeightsNEG->fill(track.phi(), track.eta(), vtxz, track.pt(), centrality, 0); + fWeightsNEG->fill(phi, track.eta(), vtxz, track.pt(), centrality, 0); } - // Set weff and wacc for inclusice, negative and positive hadrons - if (!setCurrentParticleWeights(kInclusive, weff, wacc, track.phi(), track.eta(), track.pt(), vtxz)) + // Set weff and wacc for inclusive, negative and positive hadrons + if (!setCurrentParticleWeights(kInclusive, weff, wacc, phi, track.eta(), track.pt(), vtxz)) continue; - if (pos && !setCurrentParticleWeights(kPositive, weffP, waccP, track.phi(), track.eta(), track.pt(), vtxz)) + if (pos && !setCurrentParticleWeights(kPositive, weffP, waccP, phi, track.eta(), track.pt(), vtxz)) continue; - if (!pos && !setCurrentParticleWeights(kNegative, weffN, waccN, track.phi(), track.eta(), track.pt(), vtxz)) + if (!pos && !setCurrentParticleWeights(kNegative, weffN, waccN, phi, track.eta(), track.pt(), vtxz)) continue; registry.fill(HIST("hTrackCount"), trackSel_ParticleWeights); - // constrain angle to 0 -> [0,0+2pi] - auto phi = RecoDecay::constrainAngle(track.phi(), 0); + switch (trackPID) { + case kUnidentified: + fillAllQA(track, vtxz, pos, wacc, weff, waccP, weffP, waccN, weffN); + break; + case kPion: + fillAllQA(track, vtxz, pos, wacc, weff, waccP, weffP, waccN, weffN); + break; + case kKaon: + fillAllQA(track, vtxz, pos, wacc, weff, waccP, weffP, waccN, weffN); + break; + case kProton: + fillAllQA(track, vtxz, pos, wacc, weff, waccP, weffP, waccN, weffN); + break; + } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - auto ux = std::cos(cfgHarm * phi); @@ -1390,15 +1315,11 @@ struct FlowSP { double vnFull = std::cos(cfgHarm * (phi - psiFull)) / evPlaneRes; fillHistograms(track, wacc, weff, centWeight, ux, uy, uxMH, uyMH, uxMH2, uyMH2, qxA, qyA, qxC, qyC, corrQQx, corrQQy, corrQQ, vnA, vnC, vnFull, centrality); - fillTrackQA(track, vtxz, wacc, weff); - if (cfgFillChargeDependence) { if (pos) { fillHistograms(track, waccP, weffP, centWeight, ux, uy, uxMH, uyMH, uxMH2, uyMH2, qxA, qyA, qxC, qyC, corrQQx, corrQQy, corrQQ, vnA, vnC, vnFull, centrality); - fillTrackQA(track, vtxz, waccP, weffP); } else { fillHistograms(track, waccN, weffN, centWeight, ux, uy, uxMH, uyMH, uxMH2, uyMH2, qxA, qyA, qxC, qyC, corrQQx, corrQQy, corrQQ, vnA, vnC, vnFull, centrality); - fillTrackQA(track, vtxz, waccN, weffN); } } } // end of track loop From 63a7c29c28147737d9ba8abcf330a709f38d9925 Mon Sep 17 00:00:00 2001 From: jaelpark Date: Thu, 19 Jun 2025 16:06:38 +0200 Subject: [PATCH 146/871] [PWGCF] Check MC HF decay and use dedicated efficiency bin (#11681) --- PWGCF/DataModel/CorrelationsDerived.h | 12 +++++++++--- PWGCF/TableProducer/filter2Prong.cxx | 12 +++++++----- PWGCF/Tasks/correlations.cxx | 27 +++++++++++++++------------ 3 files changed, 31 insertions(+), 20 deletions(-) diff --git a/PWGCF/DataModel/CorrelationsDerived.h b/PWGCF/DataModel/CorrelationsDerived.h index fcaf300c2f3..c6b96b77466 100644 --- a/PWGCF/DataModel/CorrelationsDerived.h +++ b/PWGCF/DataModel/CorrelationsDerived.h @@ -11,11 +11,12 @@ #ifndef PWGCF_DATAMODEL_CORRELATIONSDERIVED_H_ #define PWGCF_DATAMODEL_CORRELATIONSDERIVED_H_ -#include +#include "Common/DataModel/Centrality.h" #include "Framework/ASoA.h" #include "Framework/AnalysisDataModel.h" -#include "Common/DataModel/Centrality.h" + +#include namespace o2::aod { @@ -150,11 +151,16 @@ namespace cf2prongmcpart { DECLARE_SOA_INDEX_COLUMN_FULL(CFParticleDaugh0, cfParticleDaugh0, int, CFMcParticles, "_0"); //! Index to prong 1 CFMcParticle DECLARE_SOA_INDEX_COLUMN_FULL(CFParticleDaugh1, cfParticleDaugh1, int, CFMcParticles, "_1"); //! Index to prong 2 CFMcParticle +DECLARE_SOA_COLUMN(Decay, decay, uint8_t); //! Particle decay and flags +enum ParticleDecayFlags { + Prompt = 0x80 +}; } // namespace cf2prongmcpart DECLARE_SOA_TABLE(CF2ProngMcParts, "AOD", "CF2PRONGMCPART", //! Table for the daughter particles of a 2-prong particle, to be joined with CFMcParticles o2::soa::Index<>, cf2prongmcpart::CFParticleDaugh0Id, - cf2prongmcpart::CFParticleDaugh1Id) + cf2prongmcpart::CFParticleDaugh1Id, + cf2prongmcpart::Decay) using CF2ProngMcPart = CF2ProngMcParts::iterator; } // namespace o2::aod diff --git a/PWGCF/TableProducer/filter2Prong.cxx b/PWGCF/TableProducer/filter2Prong.cxx index 4d86c4deda5..2ee72e9b923 100644 --- a/PWGCF/TableProducer/filter2Prong.cxx +++ b/PWGCF/TableProducer/filter2Prong.cxx @@ -141,13 +141,14 @@ struct Filter2Prong { } PROCESS_SWITCH(Filter2Prong, processData, "Process data D0 candidates", true); - void processMC(aod::McCollisions::iterator const&, aod::CFMcParticleRefs const& cfmcparticles, [[maybe_unused]] aod::McParticles const& mcparticles) + using HFMCTrack = soa::Join; + void processMC(aod::McCollisions::iterator const&, aod::CFMcParticleRefs const& cfmcparticles, [[maybe_unused]] HFMCTrack const& mcparticles) { // The main filter outputs the primary MC particles. Here we just resolve the daughter indices that are needed for the efficiency matching. for (const auto& r : cfmcparticles) { - const auto& mcParticle = r.mcParticle(); - if (mcParticle.daughtersIds().size() != 2) { - output2ProngMcParts(-1, -1); + const auto& mcParticle = r.mcParticle_as(); + if ((mcParticle.flagMcMatchGen() & (1 << aod::hf_cand_2prong::DecayType::D0ToPiK)) == 0 || mcParticle.daughtersIds().size() != 2) { + output2ProngMcParts(-1, -1, aod::cf2prongtrack::Generic2Prong); continue; } int prongCFId[2] = {-1, -1}; @@ -159,7 +160,8 @@ struct Filter2Prong { } } } - output2ProngMcParts(prongCFId[0], prongCFId[1]); + output2ProngMcParts(prongCFId[0], prongCFId[1], + (mcParticle.pdgCode() >= 0 ? aod::cf2prongtrack::D0ToPiK : aod::cf2prongtrack::D0barToKPi) | ((mcParticle.originMcGen() & RecoDecay::OriginType::Prompt) ? aod::cf2prongmcpart::Prompt : 0)); } } PROCESS_SWITCH(Filter2Prong, processMC, "Process MC 2-prong daughters", false); diff --git a/PWGCF/Tasks/correlations.cxx b/PWGCF/Tasks/correlations.cxx index 1e079482284..b73ca2971f2 100644 --- a/PWGCF/Tasks/correlations.cxx +++ b/PWGCF/Tasks/correlations.cxx @@ -987,9 +987,11 @@ struct CorrelationTask { case 2212: // proton case -2212: return 2; - default: // NOTE. The efficiency histogram is hardcoded to contain 4 species. Anything special will have the last slot. - return 3; } + if (std::find(cfgMcTriggerPDGs->begin(), cfgMcTriggerPDGs->end(), pdgCode) != cfgMcTriggerPDGs->end()) + return 4; // NOTE - if changed, the number in processMCEfficiency2Prong needs to be changed too since we skip the getSpecies call + else // The efficiency histogram is hardcoded to contain 5 species. Anything special will have the 4th slot. + return 3; } // NOTE SmallGroups includes soa::Filtered always @@ -1054,10 +1056,12 @@ struct CorrelationTask { // Primaries p2indexCache.clear(); for (const auto& mcParticle : mcParticles) { - if (mcParticle.isPhysicalPrimary() && std::find(cfgMcTriggerPDGs->begin(), cfgMcTriggerPDGs->end(), mcParticle.pdgCode()) != cfgMcTriggerPDGs->end()) { - same->getTrackHistEfficiency()->Fill(CorrelationContainer::MC, mcParticle.eta(), mcParticle.pt(), getSpecies(mcParticle.pdgCode()), multiplicity, mcCollision.posZ()); + if (std::find(cfgMcTriggerPDGs->begin(), cfgMcTriggerPDGs->end(), mcParticle.pdgCode()) != cfgMcTriggerPDGs->end()) { + if (mcParticle.decay() != aod::cf2prongtrack::D0ToPiK || mcParticle.decay() != aod::cf2prongtrack::D0barToKPi) + continue; // wrong decay channel + same->getTrackHistEfficiency()->Fill(CorrelationContainer::MC, mcParticle.eta(), mcParticle.pt(), 4, multiplicity, mcCollision.posZ()); if (mcParticle.cfParticleDaugh0Id() < 0 || mcParticle.cfParticleDaugh1Id() < 0) - continue; + continue; // daughters not found p2indexCache.push_back(mcParticle.globalIndex()); } } @@ -1068,7 +1072,8 @@ struct CorrelationTask { // Check if the mc particles of the prongs are found. if (p2track.cfTrackProng0Id() < 0 || p2track.cfTrackProng1Id() < 0) { // fake track - same->getTrackHistEfficiency()->Fill(CorrelationContainer::Fake, p2track.eta(), p2track.pt(), 0, multiplicity, mcCollision.posZ()); + same->getTrackHistEfficiency()->Fill(CorrelationContainer::Fake, p2track.eta(), p2track.pt(), 4, multiplicity, mcCollision.posZ()); + continue; } const auto& p0 = p2track.cfTrackProng0_as(); const auto& p1 = p2track.cfTrackProng1_as(); @@ -1076,18 +1081,16 @@ struct CorrelationTask { // find the 2-prong MC particle by the daughter MC particle IDs auto m = std::find_if(p2indexCache.begin(), p2indexCache.end(), [&](const auto& t) -> bool { const auto& mcParticle = mcParticles.iteratorAt(t - mcParticles.begin().globalIndex()); - return p0.cfMCParticleId() == mcParticle.cfParticleDaugh0Id() && p1.cfMCParticleId() == mcParticle.cfParticleDaugh1Id(); + return (p0.cfMCParticleId() == mcParticle.cfParticleDaugh0Id() && p1.cfMCParticleId() == mcParticle.cfParticleDaugh1Id()) || (p0.cfMCParticleId() == mcParticle.cfParticleDaugh1Id() && p1.cfMCParticleId() == mcParticle.cfParticleDaugh0Id()); }); if (m == p2indexCache.end()) continue; const auto& mcParticle = mcParticles.iteratorAt(*m - mcParticles.begin().globalIndex()); - if (mcParticle.isPhysicalPrimary()) { - same->getTrackHistEfficiency()->Fill(CorrelationContainer::RecoPrimaries, mcParticle.eta(), mcParticle.pt(), getSpecies(mcParticle.pdgCode()), multiplicity, mcCollision.posZ()); - } - same->getTrackHistEfficiency()->Fill(CorrelationContainer::RecoAll, mcParticle.eta(), mcParticle.pt(), getSpecies(mcParticle.pdgCode()), multiplicity, mcCollision.posZ()); + same->getTrackHistEfficiency()->Fill(CorrelationContainer::RecoPrimaries, mcParticle.eta(), mcParticle.pt(), 4, multiplicity, mcCollision.posZ()); + same->getTrackHistEfficiency()->Fill(CorrelationContainer::RecoAll, mcParticle.eta(), mcParticle.pt(), 4, multiplicity, mcCollision.posZ()); } else { // fake track - same->getTrackHistEfficiency()->Fill(CorrelationContainer::Fake, p2track.eta(), p2track.pt(), 0, multiplicity, mcCollision.posZ()); + same->getTrackHistEfficiency()->Fill(CorrelationContainer::Fake, p2track.eta(), p2track.pt(), 4, multiplicity, mcCollision.posZ()); } } } From 8e5bb1e843e7554aca967ebf4ba873d2affb94ad Mon Sep 17 00:00:00 2001 From: Hirak Koley Date: Thu, 19 Jun 2025 21:20:43 +0530 Subject: [PATCH 147/871] [PWGLF] update MC process (#11683) --- PWGLF/Tasks/Resonances/lstaranalysis.cxx | 289 ++++++++++++----------- 1 file changed, 148 insertions(+), 141 deletions(-) diff --git a/PWGLF/Tasks/Resonances/lstaranalysis.cxx b/PWGLF/Tasks/Resonances/lstaranalysis.cxx index 816761609b6..2e871bdae5a 100644 --- a/PWGLF/Tasks/Resonances/lstaranalysis.cxx +++ b/PWGLF/Tasks/Resonances/lstaranalysis.cxx @@ -21,30 +21,28 @@ #include // 4. Other includes: O2 framework, ROOT, etc. -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" - -#include - -#include "Framework/O2DatabasePDGPlugin.h" -#include "Framework/HistogramRegistry.h" - #include "PWGLF/Utils/collisionCuts.h" -#include "Common/DataModel/TrackSelectionTables.h" #include "Common/DataModel/Centrality.h" #include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/O2DatabasePDGPlugin.h" +#include "Framework/runDataProcessing.h" -#include "TRandom.h" -#include "TVector3.h" #include "Math/Vector4D.h" #include "TPDGCode.h" +#include "TRandom.h" +#include "TVector3.h" 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 LorentzVectorPtEtaPhiMass = ROOT::Math::PtEtaPhiMVector; @@ -53,24 +51,15 @@ struct Lstaranalysis { // Define slice per Resocollision SliceCache cache; Preslice perCollision = o2::aod::track::collisionId; - - using EventCandidates = soa::Join; - using TrackCandidates = soa::Join; - - using MCEventCandidates = soa::Join; - using MCTrackCandidates = soa::Join; + Preslice perMcCollision = o2::aod::mcparticle::mcCollisionId; HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; - Service ccdb; Service pdg; - ccdb::CcdbApi ccdbApi; - - Configurable cfgURL{"cfgURL", "http://alice-ccdb.cern.ch", "Address of the CCDB to browse"}; - Configurable noLaterThan{"noLaterThan", std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(), "Latest acceptable timestamp of creation for the object"}; /// Event cuts o2::analysis::CollisonCuts colCuts; + Configurable cfgEvtZvtx{"cfgEvtZvtx", 10.f, "Evt sel: Max. z-Vertex (cm)"}; Configurable cfgEvtOccupancyInTimeRangeMax{"cfgEvtOccupancyInTimeRangeMax", -1, "Evt sel: maximum track occupancy"}; Configurable cfgEvtOccupancyInTimeRangeMin{"cfgEvtOccupancyInTimeRangeMin", -1, "Evt sel: minimum track occupancy"}; @@ -89,8 +78,10 @@ struct Lstaranalysis { // Configurables // 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"}; // DCA Selections // DCAr to PV @@ -150,6 +141,8 @@ struct Lstaranalysis { // MC selection cut Configurable cZvertCutMC{"cZvertCutMC", 10.0, "MC Z-vertex cut"}; Configurable cEtacutMC{"cEtacutMC", 0.5, "MC eta cut"}; + Configurable cUseRapcutMC{"cUseRapcutMC", true, "MC eta cut"}; + Configurable cUseEtacutMC{"cUseEtacutMC", true, "MC eta cut"}; // cuts on mother Configurable cfgCutsOnMother{"cfgCutsOnMother", false, "Enable additional cuts on mother"}; @@ -169,6 +162,23 @@ struct Lstaranalysis { TRandom* rn = new TRandom(); + // Pre-filters for efficient process + // Filter tofPIDFilter = aod::track::tofExpMom < 0.f || ((aod::track::tofExpMom > 0.f) && ((nabs(aod::pidtof::tofNSigmaPi) < pidnSigmaPreSelectionCut) || (nabs(aod::pidtof::tofNSigmaKa) < pidnSigmaPreSelectionCut) || (nabs(aod::pidtof::tofNSigmaPr) < pidnSigmaPreSelectionCut))); // TOF + // Filter tpcPIDFilter = nabs(aod::pidtpc::tpcNSigmaPi) < pidnSigmaPreSelectionCut || nabs(aod::pidtpc::tpcNSigmaKa) < pidnSigmaPreSelectionCut || nabs(aod::pidtpc::tpcNSigmaPr) < pidnSigmaPreSelectionCut; // TPC + /* Filter trackFilter = (trackSelection == 0) || + ((trackSelection == 1) && requireGlobalTrackInFilter()) || + ((trackSelection == 2) && requireGlobalTrackWoPtEtaInFilter()) || + ((trackSelection == 3) && requireGlobalTrackWoDCAInFilter()) || + ((trackSelection == 4) && requireQualityTracksInFilter()) || + ((trackSelection == 5) && requireTrackCutInFilter(TrackSelectionFlags::kInAcceptanceTracks)); */ + Filter trackEtaFilter = nabs(aod::track::eta) < cfgCutEta; // Eta cut + + using EventCandidates = soa::Join; + using TrackCandidates = soa::Filtered>; + + using MCEventCandidates = soa::Join; + using MCTrackCandidates = soa::Filtered>; + /// Figures ConfigurableAxis binsPt{"binsPt", {VARIABLE_WIDTH, 0.0, 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.25, 1.3, 1.4, 1.5, 1.6, 1.7, 1.75, 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.6, 3.7, 3.8, 3.9, 4.0, 4.1, 4.2, 4.5, 4.6, 4.8, 4.9, 5.0, 5.5, 5.6, 6.0, 6.4, 6.5, 7.0, 7.2, 8.0, 9.0, 9.5, 9.6, 10.0, 11.0, 11.5, 12.0, 13.0, 14.0, 14.4, 15.0, 16.0, 18.0, 19.2, 20.}, "Binning of the pT axis"}; ConfigurableAxis binsPtQA{"binsPtQA", {VARIABLE_WIDTH, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0, 3.2, 3.4, 3.6, 3.8, 4.0, 4.2, 4.4, 4.6, 4.8, 5.0, 5.2, 5.4, 5.6, 5.8, 6.0, 6.2, 6.4, 6.6, 6.8, 7.0, 7.2, 7.4, 7.6, 7.8, 8.0, 8.2, 8.4, 8.6, 8.8, 9.0, 9.2, 9.4, 9.6, 9.8, 10.0, 10.2, 10.4, 10.6, 10.8, 11, 11.2, 11.4, 11.6, 11.8, 12, 12.2, 12.4, 12.6, 12.8, 13, 13.2, 13.4, 13.6, 13.8, 14, 14.2, 14.4, 14.6, 14.8, 15, 15.2, 15.4, 15.6, 15.8, 16, 16.2, 16.4, 16.6, 16.8, 17, 17.2, 17.4, 17.6, 17.8, 18, 18.2, 18.4, 18.6, 18.8, 19, 19.2, 19.4, 19.6, 19.8, 20}, "Binning of the pT axis"}; @@ -189,6 +199,7 @@ struct Lstaranalysis { centrality = -999; colCuts.setCuts(cfgEvtZvtx, cfgEvtTriggerCheck, cfgEvtOfflineCheck, /*checkRun3*/ true, /*triggerTVXsel*/ false, cfgEvtOccupancyInTimeRangeMax, cfgEvtOccupancyInTimeRangeMin); + colCuts.init(&histos); colCuts.setTriggerTVX(cfgEvtTriggerTVXSel); colCuts.setApplyTFBorderCut(cfgEvtTFBorderCut); @@ -197,11 +208,13 @@ struct Lstaranalysis { colCuts.setApplyPileupRejection(cfgEvtPileupRejection); colCuts.setApplyNoITSROBorderCut(cfgEvtNoITSROBorderCut); colCuts.setApplyCollInTimeRangeStandard(cfgEvtCollInTimeRangeStandard); + colCuts.printCuts(); // 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 axisMassLambda1520{binsMass, "Invariant Mass (GeV/#it{c}^2)"}; AxisSpec axisMult{binsMult, "mult_{V0M}"}; AxisSpec axisDCAz{binsDCAz, "DCA_{z}"}; @@ -209,9 +222,9 @@ struct Lstaranalysis { AxisSpec axisTPCXrow{binsTPCXrows, "#Xrows_{TPC}"}; AxisSpec axisPIDQA{binsnSigma, "#sigma"}; AxisSpec axisTPCSignal{binsnTPCSignal, ""}; - AxisSpec axisMClabel{5, -0.5, 5.5, "MC Label"}; + AxisSpec axisMClabel{6, -1.5, 5.5, "MC Label"}; AxisSpec axisEtaPhi{binsEtaPhi, ""}; - AxisSpec axisPhi{350, -3.5, 3.5, "#Phi"}; + AxisSpec axisPhi{350, 0, 7, "#Phi"}; AxisSpec axisMultMix{cfgMultBins, "Multiplicity"}; AxisSpec axisVtxMix{cfgVtxBins, "Vertex Z (cm)"}; @@ -336,22 +349,22 @@ struct Lstaranalysis { histos.add("Result/Data/h3lambda1520invmassME_DSAnti", "Invariant mass of #Lambda(1520) mixed event DSAnti", kTHnSparseF, {axisMult, axisPt, axisMassLambda1520}); } } - + histos.add("QAMC", "all Lambda", kTH1F, {{1000, -0.5, 999.5}}); // MC QA if (doprocessMCTrue) { histos.add("QA/MC/h2GenEtaPt_beforeanycut", " #eta-#it{p}_{T} distribution of Generated #Lambda(1520); #eta; #it{p}_{T}; Counts;", HistType::kTHnSparseF, {axisEta, axisPtQA}); - histos.add("QA/MC/h2GenPhiRapidity_beforeanycut", " #phi-y distribution of Generated #Lambda(1520); #phi; y; Counts;", HistType::kTHnSparseF, {axisPhi, axisEta}); - histos.add("QA/MC/h2GenEtaPt_beforeEtacut", " #eta-#it{p}_{T} distribution of Generated #Lambda(1520); #eta; #it{p}_{T}; Counts;", HistType::kTHnSparseF, {axisEta, axisPtQA}); - histos.add("QA/MC/h2GenPhiRapidity_beforeEtacut", " #phi-y distribution of Generated #Lambda(1520); #phi; y; Counts;", HistType::kTHnSparseF, {axisPhi, axisEta}); - histos.add("QA/MC/h2GenEtaPt_afterEtacut", " #phi-#it{p}_{T} distribution of Generated #Lambda(1520); #eta; #it{p}_{T}; Counts;", HistType::kTHnSparseF, {axisEta, axisPtQA}); - histos.add("QA/MC/h2GenPhiRapidity_afterEtacut", " #phi-y distribution of Generated #Lambda(1520); #phi; y; Counts;", HistType::kTHnSparseF, {axisPhi, axisEta}); + histos.add("QA/MC/h2GenPhiRapidity_beforeanycut", " #phi-y distribution of Generated #Lambda(1520); #phi; y; Counts;", HistType::kTHnSparseF, {axisPhi, axisRap}); + histos.add("QA/MC/h2GenEtaPt_afterEtaRapCut", " #eta-#it{p}_{T} distribution of Generated #Lambda(1520); #eta; #it{p}_{T}; Counts;", HistType::kTHnSparseF, {axisEta, axisPtQA}); + histos.add("QA/MC/h2GenPhiRapidity_afterEtaRapCut", " #phi-y distribution of Generated #Lambda(1520); #phi; y; Counts;", HistType::kTHnSparseF, {axisPhi, axisRap}); + histos.add("QA/MC/h2GenEtaPt_afterRapcut", " #phi-#it{p}_{T} distribution of Generated #Lambda(1520); #eta; #it{p}_{T}; Counts;", HistType::kTHnSparseF, {axisEta, axisPtQA}); + histos.add("QA/MC/h2GenPhiRapidity_afterRapcut", " #phi-y distribution of Generated #Lambda(1520); #phi; y; Counts;", HistType::kTHnSparseF, {axisPhi, axisRap}); histos.add("Result/MC/Genlambda1520pt", "pT distribution of True MC #Lambda(1520)0", kTHnSparseF, {axisMClabel, axisPt, axisMult}); histos.add("Result/MC/Genantilambda1520pt", "pT distribution of True MC Anti-#Lambda(1520)0", kTHnSparseF, {axisMClabel, axisPt, axisMult}); } if (doprocessMC) { histos.add("QA/MC/h2RecoEtaPt_after", " #eta-#it{p}_{T} distribution of Reconstructed #Lambda(1520); #eta; #it{p}_{T}; Counts;", HistType::kTHnSparseF, {axisEta, axisPt}); - histos.add("QA/MC/h2RecoPhiRapidity_after", " #phi-y distribution of Reconstructed #Lambda(1520); #phi; y; Counts;", HistType::kTHnSparseF, {axisPhi, axisEta}); + histos.add("QA/MC/h2RecoPhiRapidity_after", " #phi-y distribution of Reconstructed #Lambda(1520); #phi; y; Counts;", HistType::kTHnSparseF, {axisPhi, axisRap}); histos.add("QA/MC/trkDCAxy_pr", "DCAxy distribution of proton track candidates", HistType::kTHnSparseF, {axisPt, axisDCAxy}); histos.add("QA/MC/trkDCAxy_ka", "DCAxy distribution of kaon track candidates", HistType::kTHnSparseF, {axisPt, axisDCAxy}); @@ -364,16 +377,10 @@ struct Lstaranalysis { histos.add("Result/MC/h3lambda1520Recoinvmass", "Invariant mass of Reconstructed MC #Lambda(1520)0", kTHnSparseF, {axisMult, axisPt, axisMassLambda1520}); histos.add("Result/MC/h3antilambda1520Recoinvmass", "Invariant mass of Reconstructed MC Anti-#Lambda(1520)0", kTHnSparseF, {axisMult, axisPt, axisMassLambda1520}); - - ccdb->setURL(cfgURL); - ccdbApi.init("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()); } // Print output histograms statistics - LOG(info) << "Size of the histograms in spectraTOF"; + LOG(info) << "Size of the histograms in LstarAnalysis:"; histos.print(); } @@ -394,27 +401,6 @@ struct Lstaranalysis { } } - template - int getDetId(DetNameType const& name) - { - LOGF(info, "getDetId running"); - 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 { - return false; - } - } - template bool trackCut(const TrackType track) { @@ -488,7 +474,7 @@ struct Lstaranalysis { } // TOF PID - if (candidate.hasTOF()) { + if (candidate.hasTOF() && candidate.pt() > vProtonTPCPIDpTintv[lengthOfprotonTPCPIDpTintv - 1]) { if (cPIDcutType == 1) { if (lengthOfprotonTOFPIDpTintv > 0) { if (candidate.pt() > vProtonTOFPIDpTintv[lengthOfprotonTOFPIDpTintv - 1]) { @@ -566,7 +552,7 @@ struct Lstaranalysis { } // TOF PID - if (candidate.hasTOF()) { + if (candidate.hasTOF() && candidate.pt() > vKaonTPCPIDpTintv[lengthOfkaonTPCPIDpTintv - 1]) { if (cPIDcutType == 1) { if (lengthOfkaonTOFPIDpTintv > 0) { if (candidate.pt() > vKaonTOFPIDpTintv[lengthOfkaonTOFPIDpTintv - 1]) { @@ -771,9 +757,12 @@ struct Lstaranalysis { lDecayDaughter1 = LorentzVectorPtEtaPhiMass(trk1.pt(), trk1.eta(), trk1.phi(), massPr); lDecayDaughter2 = LorentzVectorPtEtaPhiMass(trk2.pt(), trk2.eta(), trk2.phi(), massKa); lResonance = lDecayDaughter1 + lDecayDaughter2; - // Rapidity cut - if (std::abs(lResonance.Rapidity()) > static_cast(0.5)) - continue; + + if constexpr (IsData || IsMix) { + // Rapidity cut + if (std::abs(lResonance.Rapidity()) > static_cast(0.5)) + continue; + } if (cfgCutsOnMother) { if (lResonance.Pt() >= cMaxPtMotherCut) // excluding candidates in overflow @@ -837,44 +826,68 @@ struct Lstaranalysis { // MC if constexpr (IsMC) { - // LOG(info) << "trk1 pdgcode: " << trk1.pdgCode() << "trk2 pdgcode: " << trk2.pdgCode() << endl; - const auto mctrack1 = trk1.mcParticle(); - const auto mctrack2 = trk2.mcParticle(); + // ------ 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() > 2) { + motherstrk1.pop_back(); + mothersPDGtrk1.pop_back(); + } - if (std::abs(mctrack1.pdgCode()) != PDG_t::kProton || std::abs(mctrack2.pdgCode()) != PDG_t::kKPlus) - continue; - bool isMotherOk = false; - int pdgCodeMother = -999; + const auto& mctrk2 = trk2.mcParticle(); + if (mctrk2.has_mothers()) { + motherstrk2 = getMothersIndeces(mctrk2); + mothersPDGtrk2 = getMothersPDGCodes(mctrk2); + } + while (motherstrk2.size() > 2) { + motherstrk2.pop_back(); + mothersPDGtrk2.pop_back(); + } - if (!trk1.has_mcParticle() || !trk2.has_mcParticle()) + if (std::abs(mctrk1.pdgCode()) != 2212 || std::abs(mctrk2.pdgCode()) != 321) continue; - for (const auto& mothertrack1 : mctrack1.template mothers_as()) { - for (const auto& mothertrack2 : mctrack2.template mothers_as()) { - if (mothertrack1.pdgCode() != mothertrack2.pdgCode()) - continue; - if (mothertrack1.globalIndex() != mothertrack2.globalIndex()) - continue; - - if (std::abs(mothertrack1.pdgCode()) == kLambda1520PDG) // Pb PDG code - continue; - - pdgCodeMother = mothertrack1.pdgCode(); + if (motherstrk1[0] != motherstrk2[0]) // Same mother + continue; - isMotherOk = true; - } - } + if (std::abs(mothersPDGtrk1[0]) != 102134) + continue; - // if (motherdTracks1.id() != motherdTracks2.id()) // Same mother - // continue; - // if (std::abs(motherdTracks1.pdgCode()) != kLambda1520PDG) - // 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 (std::abs(lResonance.Eta()) > cEtacutMC) // eta cut + if (cUseEtacutMC && std::abs(lResonance.Eta()) > cEtacutMC) // eta cut continue; - if (!isMotherOk) + if (cUseRapcutMC && std::abs(lResonance.Rapidity()) > static_cast(0.5)) // rapidity cut continue; histos.fill(HIST("QA/MC/h2RecoEtaPt_after"), lResonance.Eta(), lResonance.Pt()); @@ -896,7 +909,7 @@ struct Lstaranalysis { } // MC histograms - if (pdgCodeMother > 0) { + if (mothersPDGtrk1[0] > 0) { histos.fill(HIST("Result/MC/h3lambda1520Recoinvmass"), multiplicity, lResonance.Pt(), lResonance.M()); } else { histos.fill(HIST("Result/MC/h3antilambda1520Recoinvmass"), multiplicity, lResonance.Pt(), lResonance.M()); @@ -922,16 +935,11 @@ struct Lstaranalysis { } void processData(EventCandidates::iterator const& collision, - TrackCandidates const& tracks, - BCsWithTimestamps const&) + TrackCandidates const& tracks) { if (!colCuts.isSelected(collision)) // Default event selection return; - centrality = getCentrality(collision); - // if (centrality < cfgEventCentralityMin || centrality > cfgEventCentralityMax) - // return; - colCuts.fillQA(collision); if (cFilladditionalQAeventPlots) @@ -941,69 +949,69 @@ struct Lstaranalysis { PROCESS_SWITCH(Lstaranalysis, processData, "Process Event for data without partition", false); void processMC(MCEventCandidates::iterator const& collision, - MCTrackCandidates const& tracks, - BCsWithTimestamps const&) + aod::McCollisions const&, + MCTrackCandidates const& tracks, aod::McParticles const&) { - if (!colCuts.isSelected(collision) || (std::abs(collision.posZ()) > cZvertCutMC)) // MC event selection, all cuts missing vtx cut + colCuts.fillQA(collision); + + if (std::abs(collision.posZ()) > cZvertCutMC) // Z-vertex cut return; + fillHistograms(collision, tracks, tracks); } PROCESS_SWITCH(Lstaranalysis, processMC, "Process Event for MC Light without partition", false); - void processMCTrue(EventCandidates::iterator const& collision, McParticles const& mcParticles) + Partition selectedMCParticles = (nabs(aod::mcparticle::pdgCode) == 102134); // Lambda(1520) + + void processMCTrue(MCEventCandidates::iterator const& collision, aod::McCollisions const&, aod::McParticles const& mcParticles) { + bool IsInAfterAllCuts = colCuts.isSelected(collision); + bool inVtx10 = (std::abs(collision.mcCollision().posZ()) > 10.) ? false : true; + bool isTriggerTVX = collision.selection_bit(aod::evsel::kIsTriggerTVX); + bool isSel8 = collision.sel8(); + auto multiplicity = collision.centFT0M(); - LorentzVectorPtEtaPhiMass lDecayDaughter1, lDecayDaughter2, vresoParent; + auto mcParts = selectedMCParticles->sliceBy(perMcCollision, collision.mcCollision().globalIndex()); // Not related to the real collisions - for (const auto& part : mcParticles) { // loop over all MC particles + for (const auto& part : mcParts) { // loop over all MC particles + if (std::abs(part.pdgCode()) != kLambda1520PDG) // Lambda1520(0) continue; - auto kDaughters = part.daughters_as(); - if (kDaughters.size() != static_cast(2)) { - continue; + 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(part.daughterPDG1()) == 321 || std::abs(part.daughterPDG2()) == 321; // At least one decay to Kaon - // bool pass2 = std::abs(part.daughterPDG1()) == 2212 || std::abs(part.daughterPDG2()) == 2212; // At least one decay to Proton - - auto daughtp = false; - auto daughtk = false; - for (const auto& kCurrentDaughter : kDaughters) { - if (!kCurrentDaughter.isPhysicalPrimary()) - break; - - if (std::abs(kCurrentDaughter.pdgCode()) == PDG_t::kProton) { // Proton - daughtp = true; - lDecayDaughter1 = LorentzVectorPtEtaPhiMass(kCurrentDaughter.pt(), kCurrentDaughter.eta(), kCurrentDaughter.phi(), massPr); - } else if (std::abs(kCurrentDaughter.pdgCode()) == PDG_t::kKPlus) { - daughtk = true; - lDecayDaughter2 = LorentzVectorPtEtaPhiMass(kCurrentDaughter.pt(), kCurrentDaughter.eta(), kCurrentDaughter.phi(), massKa); - } - } + bool pass1 = std::abs(daughterPDGs[0]) == 321 || std::abs(daughterPDGs[1]) == 321; // At least one decay to Kaon + bool pass2 = std::abs(daughterPDGs[0]) == 2212 || std::abs(daughterPDGs[1]) == 2212; // At least one decay to Proton // Checking if we have both decay products - if (!daughtp || !daughtk) + if (!pass1 || !pass2) continue; - vresoParent = lDecayDaughter1 + lDecayDaughter2; + // LOGF(info, "Part PDG: %d", part.pdgCode(), "DAU_ID1: %d", pass1, "DAU_ID2: %d", pass2); - histos.fill(HIST("QA/MC/h2GenEtaPt_beforeanycut"), vresoParent.Eta(), part.pt()); - histos.fill(HIST("QA/MC/h2GenPhiRapidity_beforeanycut"), vresoParent.Phi(), part.y()); + histos.fill(HIST("QA/MC/h2GenEtaPt_beforeanycut"), part.eta(), part.pt()); + histos.fill(HIST("QA/MC/h2GenPhiRapidity_beforeanycut"), part.phi(), part.y()); - if (std::abs(part.y()) > static_cast(0.5)) // rapidity cut + if (cUseRapcutMC && std::abs(part.y()) > static_cast(0.5)) // rapidity cut continue; - histos.fill(HIST("QA/MC/h2GenEtaPt_beforeEtacut"), vresoParent.Eta(), part.pt()); - histos.fill(HIST("QA/MC/h2GenPhiRapidity_beforeEtacut"), vresoParent.Phi(), part.y()); + histos.fill(HIST("QA/MC/h2GenEtaPt_afterRapcut"), part.eta(), part.pt()); + histos.fill(HIST("QA/MC/h2GenPhiRapidity_afterRapcut"), part.phi(), part.y()); - if (std::abs(vresoParent.Eta()) > cEtacutMC) // eta cut + if (cUseEtacutMC && std::abs(part.eta()) > cEtacutMC) // eta cut continue; - histos.fill(HIST("QA/MC/h2GenEtaPt_afterEtacut"), vresoParent.Eta(), part.pt()); - histos.fill(HIST("QA/MC/h2GenPhiRapidity_afterEtacut"), vresoParent.Phi(), part.y()); + histos.fill(HIST("QA/MC/h2GenEtaPt_afterEtaRapCut"), part.eta(), part.pt()); + histos.fill(HIST("QA/MC/h2GenPhiRapidity_afterEtaRapCut"), part.phi(), part.y()); // without any event selection if (part.pdgCode() > 0) @@ -1011,28 +1019,28 @@ struct Lstaranalysis { else histos.fill(HIST("Result/MC/Genantilambda1520pt"), 0, part.pt(), multiplicity); - if (collision.posZ() > static_cast(10.)) // INEL10 + if (inVtx10) // INEL10 { if (part.pdgCode() > 0) histos.fill(HIST("Result/MC/Genlambda1520pt"), 1, part.pt(), multiplicity); else histos.fill(HIST("Result/MC/Genantilambda1520pt"), 1, part.pt(), multiplicity); } - if (collision.posZ() > static_cast(10.) && collision.sel8()) // INEL>10, vtx10 + if (inVtx10 && isSel8) // INEL>10, vtx10 { if (part.pdgCode() > 0) histos.fill(HIST("Result/MC/Genlambda1520pt"), 2, part.pt(), multiplicity); else histos.fill(HIST("Result/MC/Genantilambda1520pt"), 2, part.pt(), multiplicity); } - if (collision.posZ() > static_cast(10.) && collision.selection_bit(aod::evsel::kIsTriggerTVX)) // vtx10, TriggerTVX + if (inVtx10 && isTriggerTVX) // vtx10, TriggerTVX { if (part.pdgCode() > 0) histos.fill(HIST("Result/MC/Genlambda1520pt"), 3, part.pt(), multiplicity); else histos.fill(HIST("Result/MC/Genantilambda1520pt"), 3, part.pt(), multiplicity); } - if (colCuts.isSelected(collision)) // after all event selection + if (IsInAfterAllCuts) // after all event selection { if (part.pdgCode() > 0) histos.fill(HIST("Result/MC/Genlambda1520pt"), 4, part.pt(), multiplicity); @@ -1048,8 +1056,7 @@ struct Lstaranalysis { BinningTypeVtxZT0M colBinning{{cfgVtxBins, cfgMultBins}, true}; void processME(EventCandidates const& collision, - TrackCandidates const& tracks, - BCsWithTimestamps const&) + TrackCandidates const& tracks) { auto tracksTuple = std::make_tuple(tracks); SameKindPair pairs{colBinning, nEvtMixing, -1, collision, tracksTuple, &cache}; // -1 is the number of the bin to skip From 676a5563e28731ef20830bcf9249faf1e90e07ea Mon Sep 17 00:00:00 2001 From: Marcello Di Costanzo <96481191+Marcellocosti@users.noreply.github.com> Date: Thu, 19 Jun 2025 18:45:41 +0200 Subject: [PATCH 148/871] [PWGHF] Remove BCId from D+ tree creator (#11684) --- PWGHF/TableProducer/treeCreatorDplusToPiKPi.cxx | 6 ------ 1 file changed, 6 deletions(-) diff --git a/PWGHF/TableProducer/treeCreatorDplusToPiKPi.cxx b/PWGHF/TableProducer/treeCreatorDplusToPiKPi.cxx index eb861f1b626..08ae6c65552 100644 --- a/PWGHF/TableProducer/treeCreatorDplusToPiKPi.cxx +++ b/PWGHF/TableProducer/treeCreatorDplusToPiKPi.cxx @@ -140,7 +140,6 @@ DECLARE_SOA_TABLE(HfCandDpLites, "AOD", "HFCANDDPLITE", hf_cand_3prong::FlagMcDecayChanRec) DECLARE_SOA_TABLE(HfCandDpFulls, "AOD", "HFCANDDPFULL", - collision::BCId, collision::NumContrib, collision::PosX, collision::PosY, @@ -222,7 +221,6 @@ DECLARE_SOA_TABLE(HfCandDpFulls, "AOD", "HFCANDDPFULL", hf_cand_3prong::FlagMcDecayChanRec); DECLARE_SOA_TABLE(HfCandDpFullEvs, "AOD", "HFCANDDPFULLEV", - collision::BCId, collision::NumContrib, collision::PosX, collision::PosY, @@ -231,7 +229,6 @@ DECLARE_SOA_TABLE(HfCandDpFullEvs, "AOD", "HFCANDDPFULLEV", full::RunNumber); DECLARE_SOA_TABLE(HfCandDpFullPs, "AOD", "HFCANDDPFULLP", - collision::BCId, full::Pt, full::Eta, full::Phi, @@ -284,7 +281,6 @@ struct HfTreeCreatorDplusToPiKPi { void fillEvent(const T& collision, int isEventReject, int runNumber) { rowCandidateFullEvents( - collision.bcId(), collision.numContrib(), collision.posX(), collision.posY(), @@ -370,7 +366,6 @@ struct HfTreeCreatorDplusToPiKPi { channelMc); } else { rowCandidateFull( - coll.bcId(), coll.numContrib(), candidate.posX(), candidate.posY(), @@ -544,7 +539,6 @@ struct HfTreeCreatorDplusToPiKPi { rowCandidateFullParticles.reserve(particles.size()); for (const auto& particle : particles) { rowCandidateFullParticles( - particle.mcCollision().bcId(), particle.pt(), particle.eta(), particle.phi(), From b0d55a0cd8c3fcf25fb4511a908f63b7a87664eb Mon Sep 17 00:00:00 2001 From: Jaideep Tanwar <141036812+jtanwar2212@users.noreply.github.com> Date: Thu, 19 Jun 2025 23:48:34 +0530 Subject: [PATCH 149/871] [PWGLF] Update nucleitpcpbpb.cxx added tof information (#11687) Co-authored-by: ALICE Action Bot --- PWGLF/Tasks/Nuspex/nucleitpcpbpb.cxx | 220 +++++++++++++++------------ 1 file changed, 122 insertions(+), 98 deletions(-) diff --git a/PWGLF/Tasks/Nuspex/nucleitpcpbpb.cxx b/PWGLF/Tasks/Nuspex/nucleitpcpbpb.cxx index 090f57589bc..b833a4cf0de 100644 --- a/PWGLF/Tasks/Nuspex/nucleitpcpbpb.cxx +++ b/PWGLF/Tasks/Nuspex/nucleitpcpbpb.cxx @@ -10,44 +10,43 @@ // or submit itself to any jurisdiction. /// /// \file nucleitpcpbpb.cxx +/// \brief nuclei analysis +/// \author Jaideep Tanwar /// -/// \brief This task use global tracks and used for primary selection analysis using TPC detector. -/// It currently contemplates 6 particle types: -/// pion, Proton, Deuteron, Triton, Helium3, Alpha -/// -/// \author Jaideep Tanwar -/// \since Jan. 20, 2025 -/// -#include -#include -#include -#include -#include -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.h" +#include "Common/Core/PID/PIDTOF.h" +#include "Common/Core/PID/TPCPIDResponse.h" #include "Common/Core/RecoDecay.h" #include "Common/Core/trackUtilities.h" -#include "Common/Core/PID/TPCPIDResponse.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "Common/DataModel/EventSelection.h" #include "Common/DataModel/Centrality.h" -#include "Common/DataModel/PIDResponse.h" #include "Common/DataModel/CollisionAssociationTables.h" -#include "ReconstructionDataFormats/Track.h" -#include "DataFormatsTPC/BetheBlochAleph.h" -#include "DataFormatsParameters/GRPObject.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/PIDResponseITS.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include "CCDB/BasicCCDBManager.h" #include "DataFormatsParameters/GRPMagField.h" +#include "DataFormatsParameters/GRPObject.h" +#include "DataFormatsTPC/BetheBlochAleph.h" #include "DetectorsBase/GeometryManager.h" #include "DetectorsBase/Propagator.h" -#include "CCDB/BasicCCDBManager.h" -#include "DCAFitter/DCAFitterN.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" +#include "ReconstructionDataFormats/Track.h" + +#include +#include + +#include +#include +#include using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; using CollisionsFull = soa::Join; -using TracksFull = soa::Join; +using TracksFull = soa::Join; //--------------------------------------------------------------------------------------------------------------------------------- namespace { @@ -65,15 +64,15 @@ constexpr double betheBlochDefault[nParticles][nBetheParams]{ {5.393020, 7.859534, 0.004048, 2.323197, 1.609307, 0.09}, // triton {-126.557359, -0.858569, 1.111643, 1.210323, 2.656374, 0.09}, // helion {-126.557359, -0.858569, 1.111643, 1.210323, 2.656374, 0.09}}; // alpha -const int nTrkSettings = 16; -static const std::vector trackPIDsettingsNames{"useBBparams", "minITSnCls", "minTPCnCls", "maxTPCchi2", "maxITSchi2", "minRigidity", "maxRigidity", "maxTPCnSigma", "TOFrequiredabove", "minTOFmass", "maxTOFmass", "maxDcaXY", "maxDcaZ", "minITSclsSize", "maxITSclsSize", "minTPCnClsCrossedRows"}; +const int nTrkSettings = 18; +static const std::vector trackPIDsettingsNames{"useBBparams", "minITSnCls", "minITSnClscos", "minTPCnCls", "maxTPCchi2", "minTPCchi2", "maxITSchi2", "minRigidity", "maxRigidity", "maxTPCnSigma", "TOFrequiredabove", "minTOFmass", "maxTOFmass", "maxDcaXY", "maxDcaZ", "minITSclsSize", "maxITSclsSize", "minTPCnClsCrossedRows"}; constexpr double trackPIDsettings[nParticles][nTrkSettings]{ - {0, 0, 60, 3.0, 100, 0.15, 1.2, 2.5, -1, 0, 100, 2., 2., 0., 1000, 70}, - {1, 0, 70, 2.5, 100, 0.20, 4.0, 3.0, -1, 0, 100, 2., 2., 0., 1000, 70}, - {1, 0, 70, 5.0, 100, 0.50, 5.0, 3.0, -1, 0, 100, 2., 2., 0., 1000, 70}, - {1, 0, 70, 5.0, 100, 0.50, 5.0, 3.0, -1, 0, 100, 2., 2., 0., 1000, 70}, - {1, 0, 75, 1.5, 100, 0.50, 5.0, 3.0, -1, 0, 100, 2., 2., 0., 1000, 70}, - {1, 0, 70, 1.5, 100, 0.50, 5.0, 3.0, -1, 0, 100, 2., 2., 0., 1000, 70}}; + {0, 0, 4, 60, 4.0, 0.5, 100, 0.15, 1.2, 2.5, -1, 0, 100, 2., 2., 0., 1000, 70}, + {1, 0, 4, 70, 4.0, 0.5, 100, 0.20, 4.0, 3.0, -1, 0, 100, 2., 2., 0., 1000, 70}, + {1, 0, 4, 70, 4.0, 0.5, 100, 0.50, 5.0, 3.0, -1, 0, 100, 2., 2., 0., 1000, 70}, + {1, 0, 4, 70, 4.0, 0.5, 100, 0.50, 5.0, 3.0, -1, 0, 100, 2., 2., 0., 1000, 70}, + {1, 0, 4, 75, 4.0, 0.5, 100, 0.50, 5.0, 5.0, -1, 0, 100, 2., 2., 0., 1000, 70}, + {1, 0, 4, 70, 4.0, 0.5, 100, 0.50, 5.0, 5.0, -1, 0, 100, 2., 2., 0., 1000, 70}}; struct PrimParticles { TString name; int pdgCode, charge; @@ -117,9 +116,12 @@ struct NucleitpcPbPb { Configurable cfgTPCNClsfoundRequire{"cfgTPCNClsfoundRequire", true, "Require TPCNClsfound Cut"}; Configurable cfgTPCNClsCrossedRowsRequire{"cfgTPCNClsCrossedRowsRequire", true, "Require TPCNClsCrossedRows Cut"}; Configurable cfgmaxTPCchi2Require{"cfgmaxTPCchi2Require", true, "Require maxTPCchi2 Cut"}; - Configurable cfgminITSnClsRequire{"cfgminITSnClsRequire", true, "Require minITSnCls Cut"}; + Configurable cfgminTPCchi2Require{"cfgminTPCchi2Require", true, "Require minTPCchi2 Cut"}; + Configurable cfgminITSnClsRequire{"cfgminITSnClsRequire", false, "Require minITSnCls Cut"}; + Configurable cfgminITSnClscosRequire{"cfgminITSnClscosRequire", true, "Require minITSnCls / cosh(eta) Cut"}; Configurable cfgmaxITSchi2Require{"cfgmaxITSchi2Require", true, "Require maxITSchi2 Cut"}; Configurable cfgmaxTPCnSigmaRequire{"cfgmaxTPCnSigmaRequire", true, "Require maxTPCnSigma Cut"}; + Configurable cfgmaxITSnSigmaRequire{"cfgmaxITSnSigmaRequire", true, "Require maxITSnSigma Cut for helium"}; Configurable cfgminGetMeanItsClsSizeRequire{"cfgminGetMeanItsClsSizeRequire", true, "Require minGetMeanItsClsSize Cut"}; Configurable cfgmaxGetMeanItsClsSizeRequire{"cfgmaxGetMeanItsClsSizeRequire", true, "Require maxGetMeanItsClsSize Cut"}; Configurable cfgRigidityCutRequire{"cfgRigidityCutRequire", true, "Require Rigidity Cut"}; @@ -129,16 +131,16 @@ struct NucleitpcPbPb { Configurable cfgTwicemass{"cfgTwicemass", true, "multiply mass by its charge"}; Configurable> cfgBetheBlochParams{"cfgBetheBlochParams", {betheBlochDefault[0], nParticles, nBetheParams, particleNames, betheBlochParNames}, "TPC Bethe-Bloch parameterisation for light nuclei"}; Configurable> cfgTrackPIDsettings{"cfgTrackPIDsettings", {trackPIDsettings[0], nParticles, nTrkSettings, particleNames, trackPIDsettingsNames}, "track selection and PID criteria"}; - Configurable cfgFillDeDxWithoutCut{"cfgFillDeDxWithoutCut", false, "Fill without cut beth bloch"}; - Configurable cfgFillDeDxWithCut{"cfgFillDeDxWithCut", false, "Fill with cut beth bloch"}; - Configurable cfgFillnsigma{"cfgFillnsigma", true, "Fill n-sigma histograms"}; + Configurable cfgFillDeDxWithCut{"cfgFillDeDxWithCut", true, "Fill with cut beth bloch"}; + Configurable cfgFillnsigma{"cfgFillnsigma", false, "Fill n-sigma histograms"}; Configurable cfgFillmass{"cfgFillmass", false, "Fill mass histograms"}; Configurable centcut{"centcut", 80.0f, "centrality cut"}; Configurable cfgCutRapidity{"cfgCutRapidity", 0.5f, "Rapidity range"}; Configurable cfgZvertex{"cfgZvertex", 10, "Min Z Vertex"}; + Configurable cfgITSnsigma{"cfgITSnsigma", 5, "Max ITS nsigma value"}; Configurable cfgtpcNClsFound{"cfgtpcNClsFound", 100.0f, "min. no. of tpcNClsFound"}; Configurable cfgitsNCls{"cfgitsNCls", 2.0f, "min. no. of itsNCls"}; - + o2::track::TrackParametrizationWithError mTrackParCov; // CCDB Service ccdb; Configurable bField{"bField", -999, "bz field, -999 is automatic"}; @@ -148,6 +150,7 @@ struct NucleitpcPbPb { Configurable lutPath{"lutPath", "GLO/Param/MatLUT", "Path of the Lut parametrization"}; Configurable geoPath{"geoPath", "GLO/Config/GeometryAligned", "Path of the geometry file"}; Configurable pidPath{"pidPath", "", "Path to the PID response object"}; + std::vector primaryParticles; std::vector primVtx, cents; bool collHasCandidate, collPassedEvSel; @@ -171,13 +174,13 @@ struct NucleitpcPbPb { const AxisSpec axisMagField{10, -10., 10., "magnetic field"}; const AxisSpec axisNev{3, 0., 3., "Number of events"}; const AxisSpec axisRigidity{4000, -10., 10., "#it{p}^{TPC}/#it{z}"}; - const AxisSpec axisdEdx{2000, 0, 2000, "d#it{E}/d#it{x}"}; + const AxisSpec axisdEdx{4000, 0, 4000, "d#it{E}/d#it{x}"}; const AxisSpec axisCent{100, 0, 100, "centrality"}; const AxisSpec axisVtxZ{100, -20, 20, "z"}; const AxisSpec ptAxis{200, 0, 20, "#it{p}_{T} (GeV/#it{c})"}; const AxisSpec axiseta{100, -1, 1, "eta"}; const AxisSpec axisrapidity{100, -2, 2, "rapidity"}; - const AxisSpec axismass{100, 0, 20, "mass^{2}"}; + const AxisSpec axismass{100, -10, 10, "mass^{2}"}; AxisSpec nsigmaAxis = {160, -20, 20, "n#sigma_{#pi^{+}}"}; // create histograms histos.add("histeta", "histeta", kTH1F, {axiseta}); @@ -197,11 +200,8 @@ struct NucleitpcPbPb { hmass.resize(2 * nParticles + 2); for (int i = 0; i < nParticles + 1; i++) { TString histName = i < nParticles ? primaryParticles[i].name : "all"; - if (cfgFillDeDxWithoutCut) { - hDeDx[2 * i] = histos.add(Form("dedx/histdEdx_%s", histName.Data()), ";p_{TPC}/z (GeV/#it{c}); d#it{E}/d#it{x}", HistType::kTH2F, {axisRigidity, axisdEdx}); - } if (cfgFillDeDxWithCut) { - hDeDx[2 * i + 1] = histos.add(Form("dedx/histdEdx_%s_Cuts", histName.Data()), ";p_{TPC}/z (GeV/#it{c}); d#it{E}/d#it{x}", HistType::kTH2F, {axisRigidity, axisdEdx}); + hDeDx[2 * i] = histos.add(Form("dedx/histdEdx_%s_Cuts", histName.Data()), ";p_{TPC}/z (GeV/#it{c}); d#it{E}/d#it{x}", HistType::kTH2F, {axisRigidity, axisdEdx}); } } for (int i = 0; i < nParticles; i++) { @@ -219,10 +219,8 @@ struct NucleitpcPbPb { //---------------------------------------------------------------------------------------------------------------- void findprimaryParticles(aod::TrackAssoc const& tracksByColl, TracksFull const& tracks) { - // track loop, store daughter candidates in std::vector for (const auto& trackId : tracksByColl) { const auto& track = tracks.rawIteratorAt(trackId.trackId()); - filldedx(track, nParticles); if (!track.isPVContributor() && cfgUsePVcontributors) continue; if (!track.hasITS() && cfgITSrequire) @@ -240,13 +238,17 @@ struct NucleitpcPbPb { continue; if (track.tpcNClsFound() < cfgTrackPIDsettings->get(i, "minTPCnCls") && cfgTPCNClsfoundRequire) continue; - double min_value = 0.8; - if (((track.tpcNClsCrossedRows() < cfgTrackPIDsettings->get(i, "minTPCnClsCrossedRows")) || track.tpcNClsCrossedRows() < min_value * track.tpcNClsFindable()) && cfgTPCNClsCrossedRowsRequire) + if (((track.tpcNClsCrossedRows() < cfgTrackPIDsettings->get(i, "minTPCnClsCrossedRows")) || track.tpcNClsCrossedRows() < 0.8 * track.tpcNClsFindable()) && cfgTPCNClsCrossedRowsRequire) // o2-linter: disable=magic-number (To be checked) continue; if (track.tpcChi2NCl() > cfgTrackPIDsettings->get(i, "maxTPCchi2") && cfgmaxTPCchi2Require) continue; + if (track.tpcChi2NCl() < cfgTrackPIDsettings->get(i, "minTPCchi2") && cfgminTPCchi2Require) + continue; if (track.itsNCls() < cfgTrackPIDsettings->get(i, "minITSnCls") && cfgminITSnClsRequire) continue; + double cosheta = std::cosh(track.eta()); + if ((track.itsNCls() / cosheta) < cfgTrackPIDsettings->get(i, "minITSnClscos") && cfgminITSnClscosRequire) + continue; if (track.itsChi2NCl() > cfgTrackPIDsettings->get(i, "maxITSchi2") && cfgmaxITSchi2Require) continue; if (getMeanItsClsSize(track) < cfgTrackPIDsettings->get(i, "minITSclsSize") && cfgminGetMeanItsClsSizeRequire) @@ -255,28 +257,41 @@ struct NucleitpcPbPb { continue; if ((getRigidity(track) < cfgTrackPIDsettings->get(i, "minRigidity") || getRigidity(track) > cfgTrackPIDsettings->get(i, "maxRigidity")) && cfgRigidityCutRequire) continue; - if ((cfgTrackPIDsettings->get(i, "TOFrequiredabove") >= 0 && getRigidity(track) > cfgTrackPIDsettings->get(i, "TOFrequiredabove") && (track.mass() < cfgTrackPIDsettings->get(i, "minTOFmass") || track.mass() > cfgTrackPIDsettings->get(i, "maxTOFmass"))) && cfgmassRequire) - continue; - bool insideDCAxy = (std::abs(track.dcaXY()) <= (cfgTrackPIDsettings->get(i, "maxDcaXY") * (0.0105f + 0.0350f / std::pow(track.pt(), 1.1f)))); - if ((!(insideDCAxy) || std::abs(track.dcaZ()) > cfgTrackPIDsettings->get(i, "maxDcaZ")) && cfgDCAwithptRequire) - continue; - if ((std::abs(track.dcaXY()) > cfgTrackPIDsettings->get(i, "maxDcaXY") || std::abs(track.dcaZ()) > cfgTrackPIDsettings->get(i, "maxDcaZ")) && cfgDCAnopt) + float pt_momn; + setTrackParCov(track, mTrackParCov); + mTrackParCov.setPID(track.pidForTracking()); + pt_momn = (i == 4 || i == 5) ? 2 * mTrackParCov.getPt() : mTrackParCov.getPt(); + bool insideDCAxy = (std::abs(track.dcaXY()) <= (cfgTrackPIDsettings->get(i, "maxDcaXY") * (0.0105f + 0.0350f / std::pow(pt_momn, 1.1f)))); + if ((!(insideDCAxy) || std::abs(track.dcaZ()) > DCAzSigma(pt_momn, cfgTrackPIDsettings->get(i, "maxDcaZ"))) && cfgDCAwithptRequire) continue; if (track.sign() > 0) { - histos.fill(HIST("histDcaZVsPtData_particle"), track.pt(), track.dcaZ()); - histos.fill(HIST("histDcaXYVsPtData_particle"), track.pt(), track.dcaXY()); + histos.fill(HIST("histDcaZVsPtData_particle"), pt_momn, track.dcaZ()); + histos.fill(HIST("histDcaXYVsPtData_particle"), pt_momn, track.dcaXY()); } if (track.sign() < 0) { - histos.fill(HIST("histDcaZVsPtData_antiparticle"), track.pt(), track.dcaZ()); - histos.fill(HIST("histDcaXYVsPtData_antiparticle"), track.pt(), track.dcaXY()); + histos.fill(HIST("histDcaZVsPtData_antiparticle"), pt_momn, track.dcaZ()); + histos.fill(HIST("histDcaXYVsPtData_antiparticle"), pt_momn, track.dcaXY()); } - fillnsigma(track, i); - if (std::abs(getTPCnSigma(track, primaryParticles.at(i))) > cfgTrackPIDsettings->get(i, "maxTPCnSigma") && cfgmaxTPCnSigmaRequire) + float tpcNsigma = getTPCnSigma(track, primaryParticles.at(i)); + if ((std::abs(tpcNsigma) > cfgTrackPIDsettings->get(i, "maxTPCnSigma")) && cfgmaxTPCnSigmaRequire) + continue; + float itsSigma = getITSnSigma(track, primaryParticles.at(i)); + if ((std::abs(itsSigma) > cfgITSnsigma) && cfgmaxITSnSigmaRequire) continue; + fillnsigma(track, i); filldedx(track, i); + // TOF selection + if (!track.hasTOF() && cfgTrackPIDsettings->get(i, "TOFrequiredabove") < 1) + continue; + float beta{o2::pid::tof::Beta::GetBeta(track)}; + float charge{1.f + static_cast(i == 4 || i == 5)}; + float tofMasses = getRigidity(track) * charge * std::sqrt(1.f / (beta * beta) - 1.f); + if ((getRigidity(track) > cfgTrackPIDsettings->get(i, "TOFrequiredabove") && (tofMasses < cfgTrackPIDsettings->get(i, "minTOFmass") || tofMasses > cfgTrackPIDsettings->get(i, "maxTOFmass"))) && cfgmassRequire) + continue; fillhmass(track, i); } histos.fill(HIST("histeta"), track.eta()); + filldedx(track, nParticles); } // track loop } //---------------------------------------------------------------------------------------------------------------- @@ -358,7 +373,6 @@ struct NucleitpcPbPb { if (collPassedEvSel) { histos.fill(HIST("histNev"), 1.5); histos.fill(HIST("histVtxZ"), collision.posZ()); - // histos.fill(HIST("histCentFT0A"), collision.centFT0A()); histos.fill(HIST("histCentFT0C"), collision.centFT0C()); histos.fill(HIST("histCentFT0M"), collision.centFT0M()); } @@ -370,13 +384,10 @@ struct NucleitpcPbPb { void filldedx(T const& track, int species) { const float rigidity = getRigidity(track); - if (cfgFillDeDxWithoutCut) { - hDeDx[2 * species]->Fill(track.sign() * rigidity, track.tpcSignal()); - } if (track.tpcNClsFound() < cfgtpcNClsFound || track.itsNCls() < cfgitsNCls) return; if (cfgFillDeDxWithCut) { - hDeDx[2 * species + 1]->Fill(track.sign() * rigidity, track.tpcSignal()); + hDeDx[2 * species]->Fill(track.sign() * rigidity, track.tpcSignal()); } } //---------------------------------------------------------------------------------------------------------------- @@ -388,19 +399,15 @@ struct NucleitpcPbPb { if (cfgFillnsigma) { int i = species; const float tpcNsigma = getTPCnSigma(track, primaryParticles.at(i)); - double momn; - int speciesHe3 = 4; - int speciesHe4 = 5; - if (species == speciesHe3 || species == speciesHe4) { - momn = 2 * track.pt(); - } else { - momn = track.pt(); - } + float pt_momn; + setTrackParCov(track, mTrackParCov); + mTrackParCov.setPID(track.pidForTracking()); + pt_momn = (i == 4 || i == 5) ? 2 * mTrackParCov.getPt() : mTrackParCov.getPt(); if (track.sign() > 0) { - hNsigmaPt[2 * species]->Fill(momn, tpcNsigma); + hNsigmaPt[2 * species]->Fill(pt_momn, tpcNsigma); } if (track.sign() < 0) { - hNsigmaPt[2 * species + 1]->Fill(momn, tpcNsigma); + hNsigmaPt[2 * species]->Fill(pt_momn, tpcNsigma); } } } @@ -410,32 +417,31 @@ struct NucleitpcPbPb { { if (track.tpcNClsFound() < cfgtpcNClsFound || track.itsNCls() < cfgitsNCls) return; - if (cfgFillmass) { - double mass; - int speciesHe3 = 4; - int speciesHe4 = 5; - if ((species == speciesHe3 || species == speciesHe4) && cfgTwicemass) { - mass = 2 * track.mass(); - } else { - mass = track.mass(); - } - double momn; - if (species == speciesHe3 || species == speciesHe4) { - momn = 2 * track.pt(); - } else { - momn = track.pt(); - } - if (track.sign() > 0) { - hmass[2 * species]->Fill(momn, mass * mass); - } - if (track.sign() < 0) { - hmass[2 * species + 1]->Fill(momn, mass * mass); - } + if (!track.hasTOF() || !cfgFillmass) + return; + float beta{o2::pid::tof::Beta::GetBeta(track)}; + if (beta <= 0.f || beta >= 1.f) + return; + float charge = (species == 4 || species == 5) ? 2.f : 1.f; + float p = getRigidity(track); // assuming this is the momentum from inner TPC + float massTOF = p * charge * std::sqrt(1.f / (beta * beta) - 1.f); + // get PDG mass + float pdgMass = particleMasses[species]; + float massDiff = massTOF - pdgMass; + float pt_momn; + setTrackParCov(track, mTrackParCov); + mTrackParCov.setPID(track.pidForTracking()); + pt_momn = (species == 4 || species == 5) ? 2 * mTrackParCov.getPt() : mTrackParCov.getPt(); + if (track.sign() > 0) { + hmass[2 * species]->Fill(pt_momn, massDiff * massDiff); + } else if (track.sign() < 0) { + hmass[2 * species + 1]->Fill(pt_momn, massDiff * massDiff); } } + //---------------------------------------------------------------------------------------------------------------- template - float getTPCnSigma(T const& track, PrimParticles const& particle) + float getTPCnSigma(T const& track, PrimParticles& particle) { const float rigidity = getRigidity(track); if (!track.hasTPC()) @@ -458,6 +464,19 @@ struct NucleitpcPbPb { float sigmaTPC = static_cast((track.tpcSignal() - expBethe) / expSigma); return sigmaTPC; } + //---------------------------------------------------------------------------------------------------------------- + template + float getITSnSigma(T const& track, PrimParticles& particle) + { + if (!track.hasITS()) + return -999; + o2::aod::ITSResponse itsResponse; + if (particle.name == "helion") + return itsResponse.nSigmaITS(track); + + return -999; // fallback if no match + } + //---------------------------------------------------------------------------------------------------------------- template float getMeanItsClsSize(T const& track) @@ -480,6 +499,11 @@ struct NucleitpcPbPb { bool hePID = track.pidForTracking() == o2::track::PID::Helium3 || track.pidForTracking() == o2::track::PID::Alpha; return hePID ? track.tpcInnerParam() / 2 : track.tpcInnerParam(); } + float DCAzSigma(double pt, float dcasigma) + { + float invPt = 1.f / pt; + return (5.00000e-04 + 8.73690e-03 * invPt + 9.62329e-04 * invPt * invPt) * dcasigma; // o2-linter: disable=magic-number (To be checked) + } //---------------------------------------------------------------------------------------------------------------- template float getRapidity(T const& track, int species) From 85fe093e3b2785f43ff5ee151e98111448db0ef1 Mon Sep 17 00:00:00 2001 From: Nicolas Strangmann <77485327+nstrangm@users.noreply.github.com> Date: Thu, 19 Jun 2025 21:52:12 +0200 Subject: [PATCH 150/871] [PWGEM/PhotonMeson,PWGJE/EMCal] Include BCWise centrality and qa histograms (#11694) Co-authored-by: Nicolas Strangmann Co-authored-by: ALICE Action Bot --- .../TableProducer/bcWiseClusterSkimmer.cxx | 17 ++++++------- PWGEM/PhotonMeson/Tasks/CMakeLists.txt | 4 ++-- ...cWisePi0.cxx => emcalBcWiseGammaGamma.cxx} | 24 +++++++++---------- PWGJE/Tasks/emcEventSelectionQA.cxx | 2 +- 4 files changed, 24 insertions(+), 23 deletions(-) rename PWGEM/PhotonMeson/Tasks/{emcalBcWisePi0.cxx => emcalBcWiseGammaGamma.cxx} (98%) diff --git a/PWGEM/PhotonMeson/TableProducer/bcWiseClusterSkimmer.cxx b/PWGEM/PhotonMeson/TableProducer/bcWiseClusterSkimmer.cxx index 8a09995167d..bc24734ee2d 100644 --- a/PWGEM/PhotonMeson/TableProducer/bcWiseClusterSkimmer.cxx +++ b/PWGEM/PhotonMeson/TableProducer/bcWiseClusterSkimmer.cxx @@ -43,7 +43,7 @@ using namespace o2::framework::expressions; using MyCollisions = soa::Join; using MyMCCollisions = soa::Join; -using MyBCs = soa::Join; +using MyBCs = soa::Join; using SelectedUniqueClusters = soa::Filtered; // Clusters from collisions with only one collision in the BC using SelectedUniqueMCClusters = soa::Filtered>; // Clusters from collisions with only one collision in the BC @@ -100,6 +100,7 @@ struct bcWiseClusterSkimmer { mHistManager.get(HIST("nBCs"))->GetXaxis()->SetBinLabel(iBin + 1, binLabels[iBin]); mHistManager.add("CentralityVsGenMultiplicity", "Centrality vs number of generated MC particles;Centrality;#bf{#it{N}_{gen}}", HistType::kTH2F, {{102, 0., 102}, cfgMultiplicityBinning}); + mHistManager.add("BCCentVsCollCent", "Centrality of the BC vs Centrality of the collision;BC Centrality;Collision Centrality", HistType::kTH2F, {{102, 0., 102}, {102, 0., 102}}); LOG(info) << "BC wise cluster skimmer cuts:"; LOG(info) << "------------------------------------"; @@ -232,11 +233,14 @@ struct bcWiseClusterSkimmer { double mu = cfgStoreMu ? calculateMu(bc) : 0.; float ft0Amp = hasFT0 ? bc.foundFT0().sumAmpA() + bc.foundFT0().sumAmpC() : 0.; - double centrality = 101.5; + double centralityOfCollision = 101.5; if (collisionsInBC.size() > 0) - centrality = collisionsInBC.iteratorAt(0).centFT0M(); + centralityOfCollision = collisionsInBC.iteratorAt(0).centFT0M(); + double centralityOfBC = bc.centFT0M(); - bcTable(hasFT0, hasTVX, haskTVXinEMC, hasEMCCell, hasNoTFROFBorder, convertForStorage(centrality, kFT0MCent), convertForStorage(ft0Amp, kFT0Amp), convertForStorage(mu, kMu)); + mHistManager.fill(HIST("BCCentVsCollCent"), centralityOfBC, centralityOfCollision); + + bcTable(hasFT0, hasTVX, haskTVXinEMC, hasEMCCell, hasNoTFROFBorder, convertForStorage(centralityOfBC, kFT0MCent), convertForStorage(ft0Amp, kFT0Amp), convertForStorage(mu, kMu)); for (const auto& collision : collisionsInBC) collisionTable(bcTable.lastIndex(), convertForStorage(collision.centFT0M(), kFT0MCent), convertForStorage(collision.posZ(), kZVtx)); @@ -313,10 +317,7 @@ struct bcWiseClusterSkimmer { auto mcCollisionsBC = mcCollisions.sliceBy(mcCollperBC, bc.globalIndex()); for (const auto& mcCollision : mcCollisionsBC) { auto mcParticlesInColl = mcParticles.sliceBy(perMcCollision, mcCollision.globalIndex()); - double centrality = 101.5; - if (collisionsInBC.size() > 0) - centrality = collisionsInBC.iteratorAt(0).centFT0M(); - mHistManager.fill(HIST("CentralityVsGenMultiplicity"), centrality, mcParticlesInColl.size()); + mHistManager.fill(HIST("CentralityVsGenMultiplicity"), bc.centFT0M(), mcParticlesInColl.size()); for (const auto& mcParticle : mcParticlesInColl) { if (mcParticle.pdgCode() != 111 || std::abs(mcParticle.y()) > cfgRapidityCut || !isGammaGammaDecay(mcParticle, mcParticles) || mcParticle.pt() < cfgMinPtGenPi0) continue; diff --git a/PWGEM/PhotonMeson/Tasks/CMakeLists.txt b/PWGEM/PhotonMeson/Tasks/CMakeLists.txt index 6483af43f4c..f06ad37b67a 100644 --- a/PWGEM/PhotonMeson/Tasks/CMakeLists.txt +++ b/PWGEM/PhotonMeson/Tasks/CMakeLists.txt @@ -24,8 +24,8 @@ o2physics_add_dpl_workflow(emc-pi0-qc PUBLIC_LINK_LIBRARIES O2::Framework O2::EMCALBase O2::EMCALCalib O2Physics::AnalysisCore COMPONENT_NAME Analysis) -o2physics_add_dpl_workflow(emc-bc-wise-pi0 - SOURCES emcalBcWisePi0.cxx +o2physics_add_dpl_workflow(emc-bc-wise-gammagamma + SOURCES emcalBcWiseGammaGamma.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::EMCALBase O2::EMCALCalib O2Physics::AnalysisCore COMPONENT_NAME Analysis) diff --git a/PWGEM/PhotonMeson/Tasks/emcalBcWisePi0.cxx b/PWGEM/PhotonMeson/Tasks/emcalBcWiseGammaGamma.cxx similarity index 98% rename from PWGEM/PhotonMeson/Tasks/emcalBcWisePi0.cxx rename to PWGEM/PhotonMeson/Tasks/emcalBcWiseGammaGamma.cxx index ec420371e54..03c5cfb1b5c 100644 --- a/PWGEM/PhotonMeson/Tasks/emcalBcWisePi0.cxx +++ b/PWGEM/PhotonMeson/Tasks/emcalBcWiseGammaGamma.cxx @@ -17,20 +17,20 @@ /// \author Nicolas Strangmann (nicolas.strangmann@cern.ch) Goethe University Frankfurt /// -#include "Framework/runDataProcessing.h" +#include "PWGEM/PhotonMeson/DataModel/bcWiseTables.h" + +#include "CommonConstants/MathConstants.h" +#include "EMCALBase/Geometry.h" #include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" +#include "Framework/runDataProcessing.h" -#include "TString.h" -#include "Math/Vector4D.h" -#include "Math/Vector3D.h" +#include "Math/AxisAngle.h" #include "Math/LorentzRotation.h" #include "Math/Rotation3D.h" -#include "Math/AxisAngle.h" - -#include "CommonConstants/MathConstants.h" -#include "EMCALBase/Geometry.h" -#include "PWGEM/PhotonMeson/DataModel/bcWiseTables.h" +#include "Math/Vector3D.h" +#include "Math/Vector4D.h" +#include "TString.h" using namespace o2; using namespace o2::framework; @@ -39,7 +39,7 @@ using namespace o2::framework::expressions; using SelectedClusters = soa::Filtered; using SelectedMCClusters = soa::Filtered>; -struct EmcalBcWisePi0 { +struct EmcalBcWiseGammaGamma { HistogramRegistry mHistManager{"EmcalGammaGammaBcWiseHistograms"}; Configurable cfgRequirekTVXinEMC{"cfgRequirekTVXinEMC", true, "Reconstruct pi0s only in kTVXinEMC triggered BCs"}; @@ -313,7 +313,7 @@ struct EmcalBcWisePi0 { reconstructTrueMesons(clusters, mcPi0s, bc); } - PROCESS_SWITCH(EmcalBcWisePi0, processMCInfo, "Run true and gen", false); + PROCESS_SWITCH(EmcalBcWiseGammaGamma, processMCInfo, "Run true and gen", false); }; -WorkflowSpec defineDataProcessing(o2::framework::ConfigContext const& cfgc) { return WorkflowSpec{adaptAnalysisTask(cfgc)}; } +WorkflowSpec defineDataProcessing(o2::framework::ConfigContext const& cfgc) { return WorkflowSpec{adaptAnalysisTask(cfgc)}; } diff --git a/PWGJE/Tasks/emcEventSelectionQA.cxx b/PWGJE/Tasks/emcEventSelectionQA.cxx index 49fa5d97b7b..8ba3f5168c8 100644 --- a/PWGJE/Tasks/emcEventSelectionQA.cxx +++ b/PWGJE/Tasks/emcEventSelectionQA.cxx @@ -145,7 +145,7 @@ struct EmcEventSelectionQA { if (bc.runNumber() > mRun3MinNumber) { // in case of run3 not all BCs contain EMCAL data, require trigger selection also for min. bias // in addition select also L0/L1 triggers as triggers with EMCAL in reaodut - if (bc.alias_bit(kTVXinEMC) || bc.alias_bit(kEMC7) || bc.alias_bit(kEG1) || bc.alias_bit(kEG2) || bc.alias_bit(kDG1) || bc.alias_bit(kDG2) || bc.alias_bit(kEJ1) || bc.alias_bit(kEJ2) || bc.alias_bit(kDJ1) || bc.alias_bit(kDJ2)) { + if (bc.alias_bit(kTVXinEMC) || bc.alias_bit(kEMC7) || bc.alias_bit(kDMC7) || bc.alias_bit(kEG1) || bc.alias_bit(kEG2) || bc.alias_bit(kDG1) || bc.alias_bit(kDG2) || bc.alias_bit(kEJ1) || bc.alias_bit(kEJ2) || bc.alias_bit(kDJ1) || bc.alias_bit(kDJ2)) { isEMCALreadout = true; } } else { From 94def5ed25a98e0dca7d19e3417150fa118617ea Mon Sep 17 00:00:00 2001 From: Daiki Sekihata Date: Thu, 19 Jun 2025 22:26:09 +0200 Subject: [PATCH 151/871] [PWGEM/Dilepton] upadte PID ML (#11689) Co-authored-by: ALICE Action Bot --- PWGEM/Dilepton/Core/Dilepton.h | 2 +- PWGEM/Dilepton/Core/DileptonMC.h | 2 +- PWGEM/Dilepton/Core/PhotonHBT.h | 2 +- PWGEM/Dilepton/Core/SingleTrackQC.h | 2 +- PWGEM/Dilepton/Core/SingleTrackQCMC.h | 2 +- PWGEM/Dilepton/TableProducer/CMakeLists.txt | 2 +- .../TableProducer/skimmerPrimaryElectron.cxx | 126 +++++-- .../Utils/MlResponseDielectronSingleTrack.h | 18 +- PWGEM/Dilepton/Utils/MlResponseO2Track.h | 333 ++++++++++++++++++ 9 files changed, 451 insertions(+), 38 deletions(-) create mode 100644 PWGEM/Dilepton/Utils/MlResponseO2Track.h diff --git a/PWGEM/Dilepton/Core/Dilepton.h b/PWGEM/Dilepton/Core/Dilepton.h index d5d63c90b8f..bd8d07a952d 100644 --- a/PWGEM/Dilepton/Core/Dilepton.h +++ b/PWGEM/Dilepton/Core/Dilepton.h @@ -707,7 +707,7 @@ struct Dilepton { if (dielectroncuts.cfg_pid_scheme == static_cast(DielectronCut::PIDSchemes::kPIDML)) { // please call this at the end of DefineDileptonCut static constexpr int nClassesMl = 2; - const std::vector cutDirMl = {o2::cuts_ml::CutSmaller, o2::cuts_ml::CutNot}; + const std::vector cutDirMl = {o2::cuts_ml::CutGreater, o2::cuts_ml::CutNot}; const std::vector labelsClasses = {"Signal", "Background"}; const uint32_t nBinsMl = dielectroncuts.binsMl.value.size() - 1; const std::vector labelsBins(nBinsMl, "bin"); diff --git a/PWGEM/Dilepton/Core/DileptonMC.h b/PWGEM/Dilepton/Core/DileptonMC.h index b7e24e7d4d5..e23b18d56db 100644 --- a/PWGEM/Dilepton/Core/DileptonMC.h +++ b/PWGEM/Dilepton/Core/DileptonMC.h @@ -672,7 +672,7 @@ struct DileptonMC { if (dielectroncuts.cfg_pid_scheme == static_cast(DielectronCut::PIDSchemes::kPIDML)) { // please call this at the end of DefineDileptonCut static constexpr int nClassesMl = 2; - const std::vector cutDirMl = {o2::cuts_ml::CutSmaller, o2::cuts_ml::CutNot}; + const std::vector cutDirMl = {o2::cuts_ml::CutGreater, o2::cuts_ml::CutNot}; const std::vector labelsClasses = {"Signal", "Background"}; const uint32_t nBinsMl = dielectroncuts.binsMl.value.size() - 1; const std::vector labelsBins(nBinsMl, "bin"); diff --git a/PWGEM/Dilepton/Core/PhotonHBT.h b/PWGEM/Dilepton/Core/PhotonHBT.h index cc8251fb0cd..99be337aa67 100644 --- a/PWGEM/Dilepton/Core/PhotonHBT.h +++ b/PWGEM/Dilepton/Core/PhotonHBT.h @@ -589,7 +589,7 @@ struct PhotonHBT { if (dielectroncuts.cfg_pid_scheme == static_cast(DielectronCut::PIDSchemes::kPIDML)) { // please call this at the end of DefineDileptonCut static constexpr int nClassesMl = 2; - const std::vector cutDirMl = {o2::cuts_ml::CutSmaller, o2::cuts_ml::CutNot}; + const std::vector cutDirMl = {o2::cuts_ml::CutGreater, o2::cuts_ml::CutNot}; const std::vector labelsClasses = {"Signal", "Background"}; const uint32_t nBinsMl = dielectroncuts.binsMl.value.size() - 1; const std::vector labelsBins(nBinsMl, "bin"); diff --git a/PWGEM/Dilepton/Core/SingleTrackQC.h b/PWGEM/Dilepton/Core/SingleTrackQC.h index 799e276d790..2d3389354d9 100644 --- a/PWGEM/Dilepton/Core/SingleTrackQC.h +++ b/PWGEM/Dilepton/Core/SingleTrackQC.h @@ -415,7 +415,7 @@ struct SingleTrackQC { if (dielectroncuts.cfg_pid_scheme == static_cast(DielectronCut::PIDSchemes::kPIDML)) { // please call this at the end of DefineDileptonCut static constexpr int nClassesMl = 2; - const std::vector cutDirMl = {o2::cuts_ml::CutSmaller, o2::cuts_ml::CutNot}; + const std::vector cutDirMl = {o2::cuts_ml::CutGreater, o2::cuts_ml::CutNot}; const std::vector labelsClasses = {"Signal", "Background"}; const uint32_t nBinsMl = dielectroncuts.binsMl.value.size() - 1; const std::vector labelsBins(nBinsMl, "bin"); diff --git a/PWGEM/Dilepton/Core/SingleTrackQCMC.h b/PWGEM/Dilepton/Core/SingleTrackQCMC.h index e817e1b30fd..3b76e8f8b93 100644 --- a/PWGEM/Dilepton/Core/SingleTrackQCMC.h +++ b/PWGEM/Dilepton/Core/SingleTrackQCMC.h @@ -474,7 +474,7 @@ struct SingleTrackQCMC { if (dielectroncuts.cfg_pid_scheme == static_cast(DielectronCut::PIDSchemes::kPIDML)) { // please call this at the end of DefineDileptonCut static constexpr int nClassesMl = 2; - const std::vector cutDirMl = {o2::cuts_ml::CutSmaller, o2::cuts_ml::CutNot}; + const std::vector cutDirMl = {o2::cuts_ml::CutGreater, o2::cuts_ml::CutNot}; const std::vector labelsClasses = {"Signal", "Background"}; const uint32_t nBinsMl = dielectroncuts.binsMl.value.size() - 1; const std::vector labelsBins(nBinsMl, "bin"); diff --git a/PWGEM/Dilepton/TableProducer/CMakeLists.txt b/PWGEM/Dilepton/TableProducer/CMakeLists.txt index c95928b3eb1..e756d0a9fc7 100644 --- a/PWGEM/Dilepton/TableProducer/CMakeLists.txt +++ b/PWGEM/Dilepton/TableProducer/CMakeLists.txt @@ -22,7 +22,7 @@ o2physics_add_dpl_workflow(tree-creator-electron-ml-dda o2physics_add_dpl_workflow(skimmer-primary-electron SOURCES skimmerPrimaryElectron.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::MLCore COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(skimmer-primary-muon diff --git a/PWGEM/Dilepton/TableProducer/skimmerPrimaryElectron.cxx b/PWGEM/Dilepton/TableProducer/skimmerPrimaryElectron.cxx index a4eac761725..ad5976b9850 100644 --- a/PWGEM/Dilepton/TableProducer/skimmerPrimaryElectron.cxx +++ b/PWGEM/Dilepton/TableProducer/skimmerPrimaryElectron.cxx @@ -12,30 +12,34 @@ /// \brief write relevant information about primary electrons. /// \author daiki.sekihata@cern.ch -#include -#include -#include -#include +#include "PWGEM/Dilepton/DataModel/dileptonTables.h" +#include "PWGEM/Dilepton/Utils/MlResponseO2Track.h" +#include "PWGEM/Dilepton/Utils/PairUtilities.h" -#include "Math/Vector4D.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "DetectorsBase/Propagator.h" -#include "DetectorsBase/GeometryManager.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "DataFormatsCalibration/MeanVertexObject.h" -#include "CCDB/BasicCCDBManager.h" +#include "Common/Core/TableHelper.h" #include "Common/Core/trackUtilities.h" -#include "CommonConstants/PhysicsConstants.h" #include "Common/DataModel/CollisionAssociationTables.h" -#include "Common/Core/TableHelper.h" #include "Common/DataModel/PIDResponse.h" #include "Common/DataModel/PIDResponseITS.h" +#include "Tools/ML/MlResponse.h" -#include "PWGEM/Dilepton/DataModel/dileptonTables.h" -#include "PWGEM/Dilepton/Utils/PairUtilities.h" +#include "CCDB/BasicCCDBManager.h" +#include "CommonConstants/PhysicsConstants.h" +#include "DataFormatsCalibration/MeanVertexObject.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "DataFormatsParameters/GRPObject.h" +#include "DetectorsBase/GeometryManager.h" +#include "DetectorsBase/Propagator.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" + +#include "Math/Vector4D.h" + +#include +#include +#include +#include using namespace o2; using namespace o2::soa; @@ -70,7 +74,7 @@ struct skimmerPrimaryElectron { // Operation and minimisation criteria Configurable fillQAHistogram{"fillQAHistogram", false, "flag to fill QA histograms"}; Configurable d_bz_input{"d_bz_input", -999, "bz field in kG, -999 is automatic"}; - Configurable min_ncluster_tpc{"min_ncluster_tpc", 10, "min ncluster tpc"}; + Configurable min_ncluster_tpc{"min_ncluster_tpc", 0, "min ncluster tpc"}; Configurable mincrossedrows{"mincrossedrows", 70, "min. crossed rows"}; Configurable min_tpc_cr_findable_ratio{"min_tpc_cr_findable_ratio", 0.8, "min. TPC Ncr/Nf ratio"}; Configurable min_ncluster_its{"min_ncluster_its", 4, "min ncluster its"}; @@ -79,8 +83,8 @@ struct skimmerPrimaryElectron { Configurable maxchi2its{"maxchi2its", 6.0, "max. chi2/NclsITS"}; Configurable minpt{"minpt", 0.15, "min pt for track"}; Configurable maxeta{"maxeta", 0.9, "eta acceptance"}; - Configurable dca_xy_max{"dca_xy_max", 0.3f, "max DCAxy in cm"}; - Configurable dca_z_max{"dca_z_max", 0.3f, "max DCAz in cm"}; + Configurable dca_xy_max{"dca_xy_max", 1.0, "max DCAxy in cm"}; + Configurable dca_z_max{"dca_z_max", 1.0, "max DCAz in cm"}; Configurable dca_3d_sigma_max{"dca_3d_sigma_max", 1e+10, "max DCA 3D in sigma"}; Configurable minTPCNsigmaEl{"minTPCNsigmaEl", -2.5, "min. TPC n sigma for electron inclusion"}; Configurable maxTPCNsigmaEl{"maxTPCNsigmaEl", 3.5, "max. TPC n sigma for electron inclusion"}; @@ -96,7 +100,20 @@ struct skimmerPrimaryElectron { Configurable max_pin_for_pion_rejection{"max_pin_for_pion_rejection", 0.5, "pion rejection is applied below this pin"}; Configurable max_frac_shared_clusters_tpc{"max_frac_shared_clusters_tpc", 999.f, "max fraction of shared clusters in TPC"}; + // configuration for PID ML + Configurable usePIDML{"usePIDML", false, "Flag to use PID ML"}; + Configurable> onnxFileNames{"onnxFileNames", std::vector{"filename"}, "ONNX file names for each bin (if not from CCDB full path)"}; + Configurable> onnxPathsCCDB{"onnxPathsCCDB", std::vector{"path"}, "Paths of models on CCDB"}; + Configurable> binsMl{"binsMl", std::vector{-999999., 999999.}, "Bin limits for ML application"}; + 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 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)"}; + HistogramRegistry fRegistry{"output", {}, OutputObjHandlingPolicy::AnalysisObject, false, false}; + o2::analysis::MlResponseO2Track mlResponseSingleTrack; int mRunNumber; float d_bz; @@ -106,6 +123,7 @@ struct skimmerPrimaryElectron { o2::dataformats::VertexBase mVtx; const o2::dataformats::MeanVertexObject* mMeanVtx = nullptr; o2::base::MatLayerCylSet* lut = nullptr; + o2::ccdb::CcdbApi ccdbApi; void init(InitContext&) { @@ -116,6 +134,7 @@ struct skimmerPrimaryElectron { ccdb->setCaching(true); ccdb->setLocalObjectValidityChecking(); ccdb->setFatalWhenNull(false); + ccdbApi.init(ccdburl); if (fillQAHistogram) { fRegistry.add("Track/hPt", "pT;p_{T} (GeV/c)", kTH1F, {{1000, 0.0f, 10}}, false); @@ -154,6 +173,31 @@ struct skimmerPrimaryElectron { fRegistry.add("Track/hITSNsigmaKa", "ITS n sigma ka;p_{pv} (GeV/c);n #sigma_{K}^{ITS}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); fRegistry.add("Track/hITSNsigmaPr", "ITS n sigma pr;p_{pv} (GeV/c);n #sigma_{p}^{ITS}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); } + + if (usePIDML) { + static constexpr int nClassesMl = 2; + const std::vector cutDirMl = {o2::cuts_ml::CutGreater, o2::cuts_ml::CutNot}; + const std::vector labelsClasses = {"Signal", "Background"}; + 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] = cutsMl.value[i]; + cutsMlArr[i][1] = 0.; + } + 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) @@ -299,10 +343,32 @@ struct skimmerPrimaryElectron { return true; } - template - bool isElectron(TTrack const& track) + template + bool isElectron(TCollision const& collision, TTrack const& track) { - return isElectron_TPChadrej(track) || isElectron_TOFreq(track); + if (usePIDML) { + if (track.tpcNSigmaEl() < minTPCNsigmaEl || maxTPCNsigmaEl < track.tpcNSigmaEl()) { + return false; + } + if (track.hasTOF() && (maxTOFNsigmaEl < std::fabs(track.tofNSigmaEl()))) { + return false; + } + + // return false; + o2::dataformats::DCA mDcaInfoCov; + mDcaInfoCov.set(999, 999, 999, 999, 999); + auto trackParCov = getTrackParCov(track); + trackParCov.setPID(o2::track::PID::Electron); + 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, trackParCov, 2.f, matCorr, &mDcaInfoCov); + + std::vector inputFeatures = mlResponseSingleTrack.getInputFeatures(track, trackParCov, collision); + float binningFeature = mlResponseSingleTrack.getBinningFeature(track, trackParCov, collision); + return mlResponseSingleTrack.isSelectedMl(inputFeatures, binningFeature); + } else { + return isElectron_TPChadrej(track) || isElectron_TOFreq(track); + } } template @@ -460,7 +526,7 @@ struct skimmerPrimaryElectron { auto tracks_per_coll = tracksWithITSPid.sliceBy(perCol, collision.globalIndex()); for (const auto& track : tracks_per_coll) { - if (!checkTrack(collision, track) || !isElectron(track)) { + if (!checkTrack(collision, track) || !isElectron(collision, track)) { continue; } fillTrackTable(collision, track); @@ -491,7 +557,7 @@ struct skimmerPrimaryElectron { for (const auto& trackId : trackIdsThisCollision) { // auto track = trackId.template track_as(); auto track = tracksWithITSPid.rawIteratorAt(trackId.trackId()); - if (!checkTrack(collision, track) || !isElectron(track)) { + if (!checkTrack(collision, track) || !isElectron(collision, track)) { continue; } fillTrackTable(collision, track); @@ -522,7 +588,7 @@ struct skimmerPrimaryElectron { auto tracks_per_coll = tracksWithITSPid.sliceBy(perCol, collision.globalIndex()); for (const auto& track : tracks_per_coll) { - if (!checkTrack(collision, track) || !isElectron(track)) { + if (!checkTrack(collision, track) || !isElectron(collision, track)) { continue; } fillTrackTable(collision, track); @@ -556,7 +622,7 @@ struct skimmerPrimaryElectron { for (const auto& trackId : trackIdsThisCollision) { // auto track = trackId.template track_as(); auto track = tracksWithITSPid.rawIteratorAt(trackId.trackId()); - if (!checkTrack(collision, track) || !isElectron(track)) { + if (!checkTrack(collision, track) || !isElectron(collision, track)) { continue; } fillTrackTable(collision, track); @@ -591,7 +657,7 @@ struct skimmerPrimaryElectron { auto tracks_per_coll = tracksWithITSPid.sliceBy(perCol, collision.globalIndex()); for (const auto& track : tracks_per_coll) { - if (!checkTrack(collision, track) || !isElectron(track)) { + if (!checkTrack(collision, track) || !isElectron(collision, track)) { continue; } fillTrackTable(collision, track); @@ -624,7 +690,7 @@ struct skimmerPrimaryElectron { for (const auto& trackId : trackIdsThisCollision) { // auto track = trackId.template track_as(); auto track = tracksWithITSPid.rawIteratorAt(trackId.trackId()); - if (!checkTrack(collision, track) || !isElectron(track)) { + if (!checkTrack(collision, track) || !isElectron(collision, track)) { continue; } fillTrackTable(collision, track); diff --git a/PWGEM/Dilepton/Utils/MlResponseDielectronSingleTrack.h b/PWGEM/Dilepton/Utils/MlResponseDielectronSingleTrack.h index ef1c7b33474..3db865a69e4 100644 --- a/PWGEM/Dilepton/Utils/MlResponseDielectronSingleTrack.h +++ b/PWGEM/Dilepton/Utils/MlResponseDielectronSingleTrack.h @@ -17,12 +17,12 @@ #ifndef PWGEM_DILEPTON_UTILS_MLRESPONSEDIELECTRONSINGLETRACK_H_ #define PWGEM_DILEPTON_UTILS_MLRESPONSEDIELECTRONSINGLETRACK_H_ +#include "Tools/ML/MlResponse.h" + #include #include #include -#include "Tools/ML/MlResponse.h" - // Fill the map of available input features // the key is the feature's name (std::string) // the value is the corresponding value in EnumInputFeatures @@ -76,6 +76,16 @@ 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_DIELECTRON_SINGLE_TRACK_RELDIFF(FEATURE, GETTER1, GETTER2) \ + case static_cast(InputFeaturesDielectronSingleTrack::FEATURE): { \ + inputFeature = (track.GETTER2() - track.GETTER1()) / track.GETTER1(); \ + 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 @@ -104,6 +114,7 @@ enum class InputFeaturesDielectronSingleTrack : uint8_t { tpcNClsShared, tpcChi2NCl, tpcInnerParam, + reldiffp, tpcSignal, tpcNSigmaEl, tpcNSigmaMu, @@ -225,6 +236,7 @@ class MlResponseDielectronSingleTrack : public MlResponse CHECK_AND_FILL_DIELECTRON_SINGLE_TRACK(tpcNClsShared); CHECK_AND_FILL_DIELECTRON_SINGLE_TRACK(tpcChi2NCl); CHECK_AND_FILL_DIELECTRON_SINGLE_TRACK(tpcInnerParam); + CHECK_AND_FILL_DIELECTRON_SINGLE_TRACK_RELDIFF(reldiffp, p, tpcInnerParam); CHECK_AND_FILL_DIELECTRON_SINGLE_TRACK(tpcSignal); CHECK_AND_FILL_DIELECTRON_SINGLE_TRACK(tpcNSigmaEl); CHECK_AND_FILL_DIELECTRON_SINGLE_TRACK(tpcNSigmaMu); @@ -372,6 +384,7 @@ class MlResponseDielectronSingleTrack : public MlResponse FILL_MAP_DIELECTRON_SINGLE_TRACK(tpcNClsShared), FILL_MAP_DIELECTRON_SINGLE_TRACK(tpcChi2NCl), FILL_MAP_DIELECTRON_SINGLE_TRACK(tpcInnerParam), + FILL_MAP_DIELECTRON_SINGLE_TRACK(reldiffp), FILL_MAP_DIELECTRON_SINGLE_TRACK(tpcSignal), FILL_MAP_DIELECTRON_SINGLE_TRACK(tpcNSigmaEl), FILL_MAP_DIELECTRON_SINGLE_TRACK(tpcNSigmaMu), @@ -475,6 +488,7 @@ class MlResponseDielectronSingleTrack : public MlResponse #undef CHECK_AND_FILL_DIELECTRON_SINGLE_TRACK_SQRT #undef CHECK_AND_FILL_DIELECTRON_SINGLE_TRACK_COS #undef CHECK_AND_FILL_DIELECTRON_SINGLE_TRACK_TPCTOF +#undef CHECK_AND_FILL_DIELECTRON_SINGLE_TRACK_RELDIFF #undef CHECK_AND_FILL_DIELECTRON_COLLISION #endif // PWGEM_DILEPTON_UTILS_MLRESPONSEDIELECTRONSINGLETRACK_H_ diff --git a/PWGEM/Dilepton/Utils/MlResponseO2Track.h b/PWGEM/Dilepton/Utils/MlResponseO2Track.h new file mode 100644 index 00000000000..cd9be049af6 --- /dev/null +++ b/PWGEM/Dilepton/Utils/MlResponseO2Track.h @@ -0,0 +1,333 @@ +// 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 MlResponseO2Track.h +/// \brief Class to compute the ML response for dielectron analyses at the single track level +/// \author Daniel Samitz , SMI Vienna +/// Elisa Meninno, , SMI Vienna + +#ifndef PWGEM_DILEPTON_UTILS_MLRESPONSEO2TRACK_H_ +#define PWGEM_DILEPTON_UTILS_MLRESPONSEO2TRACK_H_ + +#include "Tools/ML/MlResponse.h" + +#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_O2_TRACK(FEATURE) \ + { \ + #FEATURE, static_cast(InputFeaturesO2Track::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_O2_TRACK(GETTER) \ + case static_cast(InputFeaturesO2Track::GETTER): { \ + inputFeature = track.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_O2_TRACKPARCOV(FEATURE, GETTER) \ + case static_cast(InputFeaturesO2Track::FEATURE): { \ + inputFeature = trackParCov.GETTER(); \ + break; \ + } + +// mean ITS cluster size +#define CHECK_AND_FILL_O2_TRACK_MEAN_ITSCLUSTER_SIZE(FEATURE, v1, v2) \ + case static_cast(InputFeaturesO2Track::FEATURE): { \ + int nsize = 0; \ + int ncls = 0; \ + for (int il = v1; il < v2; il++) { \ + nsize += track.itsClsSizeInLayer(il); \ + if (nsize > 0) { \ + ncls++; \ + } \ + } \ + inputFeature = static_cast(nsize) / static_cast(ncls); \ + break; \ + } + +// mean ITS cluster size x cos(lambda) +#define CHECK_AND_FILL_O2_TRACK_MEAN_ITSCLUSTER_SIZE_COS(FEATURE, v1, v2) \ + case static_cast(InputFeaturesO2Track::FEATURE): { \ + int nsize = 0; \ + int ncls = 0; \ + for (int il = v1; il < v2; il++) { \ + nsize += track.itsClsSizeInLayer(il); \ + if (nsize > 0) { \ + ncls++; \ + } \ + } \ + inputFeature = static_cast(nsize) / static_cast(ncls) * std::cos(std::atan(trackParCov.getTgl())); \ + break; \ + } + +// TPC+TOF combined nSigma +#define CHECK_AND_FILL_O2_TRACK_TPCTOF(FEATURE, GETTER1, GETTER2, GETTER3) \ + case static_cast(InputFeaturesO2Track::FEATURE): { \ + if (!track.GETTER3()) { \ + inputFeature = track.GETTER1(); \ + } else { \ + if (track.GETTER1() > 0) { \ + inputFeature = sqrt((pow(track.GETTER1(), 2) + pow(track.GETTER2(), 2)) / 2.); \ + } else { \ + inputFeature = (-1) * sqrt((pow(track.GETTER1(), 2) + pow(track.GETTER2(), 2)) / 2.); \ + } \ + } \ + 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 from track and applying a sqrt +#define CHECK_AND_FILL_O2_TRACK_SQRT(FEATURE, GETTER) \ + case static_cast(InputFeaturesO2Track::FEATURE): { \ + inputFeature = sqrt(track.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 GETTER1 from track and multiplying with cos(atan(GETTER2)) +#define CHECK_AND_FILL_O2_TRACK_COS(FEATURE, GETTER1, GETTER2) \ + case static_cast(InputFeaturesO2Track::FEATURE): { \ + inputFeature = track.GETTER1() * std::cos(std::atan(track.GETTER2())); \ + 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_O2_TRACK_RELDIFF(FEATURE, GETTER1, GETTER2) \ + case static_cast(InputFeaturesO2Track::FEATURE): { \ + inputFeature = (track.GETTER2() - trackParCov.GETTER1()) / trackParCov.GETTER1(); \ + 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_DIELECTRON_COLLISION(GETTER) \ + case static_cast(InputFeaturesO2Track::GETTER): { \ + inputFeature = collision.GETTER(); \ + break; \ + } + +namespace o2::analysis +{ +// possible input features for ML +enum class InputFeaturesO2Track : uint8_t { + tpcInnerParam, + reldiffp, + tpcSignal, + tpcNSigmaEl, + tpcNSigmaMu, + tpcNSigmaPi, + tpcNSigmaKa, + tpcNSigmaPr, + beta, + tofNSigmaEl, + tofNSigmaMu, + tofNSigmaPi, + tofNSigmaKa, + tofNSigmaPr, + tpctofNSigmaEl, + tpctofNSigmaMu, + tpctofNSigmaPi, + tpctofNSigmaKa, + tpctofNSigmaPr, + tpcNClsFound, + tpcNClsCrossedRows, + hasITS, + hasTPC, + hasTRD, + hasTOF, + tgl, + p, + itsClusterSizes, + meanClusterSizeITS, + meanClusterSizeITSib, + meanClusterSizeITSob, + meanClusterSizeITSCos, + meanClusterSizeITSibCos, + meanClusterSizeITSobCos, + posZ, + numContrib, + trackOccupancyInTimeRange, + ft0cOccupancyInTimeRange, +}; + +template +class MlResponseO2Track : public MlResponse +{ + public: + /// Default constructor + MlResponseO2Track() = default; + /// Default destructor + virtual ~MlResponseO2Track() = default; + + template + float return_feature(uint8_t idx, T const& track, U const& trackParCov, V const& collision) + { + float inputFeature = 0.; + switch (idx) { + CHECK_AND_FILL_O2_TRACK(tpcInnerParam); + CHECK_AND_FILL_O2_TRACK_RELDIFF(reldiffp, getP, tpcInnerParam); + CHECK_AND_FILL_O2_TRACK(tpcSignal); + CHECK_AND_FILL_O2_TRACK(tpcNSigmaEl); + CHECK_AND_FILL_O2_TRACK(tpcNSigmaMu); + CHECK_AND_FILL_O2_TRACK(tpcNSigmaPi); + CHECK_AND_FILL_O2_TRACK(tpcNSigmaKa); + CHECK_AND_FILL_O2_TRACK(tpcNSigmaPr); + CHECK_AND_FILL_O2_TRACK(beta); + CHECK_AND_FILL_O2_TRACK(tofNSigmaEl); + CHECK_AND_FILL_O2_TRACK(tofNSigmaMu); + CHECK_AND_FILL_O2_TRACK(tofNSigmaPi); + CHECK_AND_FILL_O2_TRACK(tofNSigmaKa); + CHECK_AND_FILL_O2_TRACK(tofNSigmaPr); + CHECK_AND_FILL_O2_TRACK_TPCTOF(tpctofNSigmaEl, tpcNSigmaEl, tofNSigmaEl, hasTOF); + CHECK_AND_FILL_O2_TRACK_TPCTOF(tpctofNSigmaMu, tpcNSigmaMu, tofNSigmaMu, hasTOF); + CHECK_AND_FILL_O2_TRACK_TPCTOF(tpctofNSigmaPi, tpcNSigmaPi, tofNSigmaPi, hasTOF); + CHECK_AND_FILL_O2_TRACK_TPCTOF(tpctofNSigmaKa, tpcNSigmaKa, tofNSigmaKa, hasTOF); + CHECK_AND_FILL_O2_TRACK_TPCTOF(tpctofNSigmaPr, tpcNSigmaPr, tofNSigmaPr, hasTOF); + CHECK_AND_FILL_O2_TRACK(tpcNClsFound); + CHECK_AND_FILL_O2_TRACK(tpcNClsCrossedRows); + CHECK_AND_FILL_O2_TRACK(hasITS); + CHECK_AND_FILL_O2_TRACK(hasTPC); + CHECK_AND_FILL_O2_TRACK(hasTRD); + CHECK_AND_FILL_O2_TRACK(hasTOF); + CHECK_AND_FILL_O2_TRACKPARCOV(tgl, getTgl); + CHECK_AND_FILL_O2_TRACKPARCOV(p, getP); + CHECK_AND_FILL_O2_TRACK(itsClusterSizes); + CHECK_AND_FILL_O2_TRACK_MEAN_ITSCLUSTER_SIZE(meanClusterSizeITS, 0, 7); + CHECK_AND_FILL_O2_TRACK_MEAN_ITSCLUSTER_SIZE(meanClusterSizeITSib, 0, 3); + CHECK_AND_FILL_O2_TRACK_MEAN_ITSCLUSTER_SIZE(meanClusterSizeITSob, 3, 7); + CHECK_AND_FILL_O2_TRACK_MEAN_ITSCLUSTER_SIZE_COS(meanClusterSizeITSCos, 0, 7); + CHECK_AND_FILL_O2_TRACK_MEAN_ITSCLUSTER_SIZE_COS(meanClusterSizeITSibCos, 0, 3); + CHECK_AND_FILL_O2_TRACK_MEAN_ITSCLUSTER_SIZE_COS(meanClusterSizeITSobCos, 3, 7); + CHECK_AND_FILL_DIELECTRON_COLLISION(posZ); + CHECK_AND_FILL_DIELECTRON_COLLISION(numContrib); + CHECK_AND_FILL_DIELECTRON_COLLISION(trackOccupancyInTimeRange); + CHECK_AND_FILL_DIELECTRON_COLLISION(ft0cOccupancyInTimeRange); + } + 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, U const& trackParCov, V const& collision) + { + std::vector inputFeatures; + for (const auto& idx : MlResponse::mCachedIndices) { + float inputFeature = return_feature(idx, track, trackParCov, collision); + 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, U const& trackParCov, V const& collision) + { + return return_feature(mCachedIndexBinning, track, trackParCov, collision); + } + + 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_O2_TRACK(tpcInnerParam), + FILL_MAP_O2_TRACK(reldiffp), + FILL_MAP_O2_TRACK(tpcSignal), + FILL_MAP_O2_TRACK(tpcNSigmaEl), + FILL_MAP_O2_TRACK(tpcNSigmaMu), + FILL_MAP_O2_TRACK(tpcNSigmaPi), + FILL_MAP_O2_TRACK(tpcNSigmaKa), + FILL_MAP_O2_TRACK(tpcNSigmaPr), + FILL_MAP_O2_TRACK(beta), + FILL_MAP_O2_TRACK(tofNSigmaEl), + FILL_MAP_O2_TRACK(tofNSigmaMu), + FILL_MAP_O2_TRACK(tofNSigmaPi), + FILL_MAP_O2_TRACK(tofNSigmaKa), + FILL_MAP_O2_TRACK(tofNSigmaPr), + FILL_MAP_O2_TRACK(tpctofNSigmaEl), + FILL_MAP_O2_TRACK(tpctofNSigmaMu), + FILL_MAP_O2_TRACK(tpctofNSigmaPi), + FILL_MAP_O2_TRACK(tpctofNSigmaKa), + FILL_MAP_O2_TRACK(tpctofNSigmaPr), + FILL_MAP_O2_TRACK(tpcNClsFound), + FILL_MAP_O2_TRACK(tpcNClsCrossedRows), + FILL_MAP_O2_TRACK(hasITS), + FILL_MAP_O2_TRACK(hasTPC), + FILL_MAP_O2_TRACK(hasTRD), + FILL_MAP_O2_TRACK(hasTOF), + FILL_MAP_O2_TRACK(tgl), + FILL_MAP_O2_TRACK(p), + FILL_MAP_O2_TRACK(itsClusterSizes), + FILL_MAP_O2_TRACK(meanClusterSizeITS), + FILL_MAP_O2_TRACK(meanClusterSizeITSib), + FILL_MAP_O2_TRACK(meanClusterSizeITSob), + FILL_MAP_O2_TRACK(meanClusterSizeITSCos), + FILL_MAP_O2_TRACK(meanClusterSizeITSibCos), + FILL_MAP_O2_TRACK(meanClusterSizeITSobCos), + FILL_MAP_O2_TRACK(posZ), + FILL_MAP_O2_TRACK(numContrib), + FILL_MAP_O2_TRACK(trackOccupancyInTimeRange), + FILL_MAP_O2_TRACK(ft0cOccupancyInTimeRange)}; + } + + uint8_t mCachedIndexBinning; // index correspondance between configurable and available input features +}; + +} // namespace o2::analysis + +#undef FILL_MAP_O2_TRACK +#undef CHECK_AND_FILL_O2_TRACK +#undef CHECK_AND_FILL_O2_TRACKPARCOV +#undef CHECK_AND_FILL_O2_TRACK_MEAN_ITSCLUSTER_SIZE +#undef CHECK_AND_FILL_O2_TRACK_MEAN_ITSCLUSTER_SIZE_COS +#undef CHECK_AND_FILL_O2_TRACK_SQRT +#undef CHECK_AND_FILL_O2_TRACK_COS +#undef CHECK_AND_FILL_O2_TRACK_TPCTOF +#undef CHECK_AND_FILL_O2_TRACK_RELDIFF +#undef CHECK_AND_FILL_DIELECTRON_COLLISION + +#endif // PWGEM_DILEPTON_UTILS_MLRESPONSEO2TRACK_H_ From ecd2f9f295f1cd931372e1d7e6e383599dcc295e Mon Sep 17 00:00:00 2001 From: Sweta Singh <122526337+sweta29singh@users.noreply.github.com> Date: Thu, 19 Jun 2025 23:29:36 +0200 Subject: [PATCH 152/871] [PWGCF] Added more histograms for Monte Carlo to calculate mean pt fluctuations for identified particles (#11515) --- PWGCF/EbyEFluctuations/Tasks/CMakeLists.txt | 4 +- .../Tasks/IdentifiedMeanPtFluctuations.cxx | 1173 -------------- .../EbyEFluctuations/Tasks/eventMeanPtId.cxx | 1382 +++++++++++++++++ 3 files changed, 1384 insertions(+), 1175 deletions(-) delete mode 100644 PWGCF/EbyEFluctuations/Tasks/IdentifiedMeanPtFluctuations.cxx create mode 100644 PWGCF/EbyEFluctuations/Tasks/eventMeanPtId.cxx diff --git a/PWGCF/EbyEFluctuations/Tasks/CMakeLists.txt b/PWGCF/EbyEFluctuations/Tasks/CMakeLists.txt index 1dd4e544331..5bdc496b812 100644 --- a/PWGCF/EbyEFluctuations/Tasks/CMakeLists.txt +++ b/PWGCF/EbyEFluctuations/Tasks/CMakeLists.txt @@ -34,8 +34,8 @@ o2physics_add_dpl_workflow(antiproton-cumulants-mc PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGCFCore COMPONENT_NAME Analysis) -o2physics_add_dpl_workflow(identified-meanpt-fluctuations - SOURCES IdentifiedMeanPtFluctuations.cxx +o2physics_add_dpl_workflow(event-mean-pt-id + SOURCES eventMeanPtId.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGCFCore COMPONENT_NAME Analysis) diff --git a/PWGCF/EbyEFluctuations/Tasks/IdentifiedMeanPtFluctuations.cxx b/PWGCF/EbyEFluctuations/Tasks/IdentifiedMeanPtFluctuations.cxx deleted file mode 100644 index 2217a2c1f4f..00000000000 --- a/PWGCF/EbyEFluctuations/Tasks/IdentifiedMeanPtFluctuations.cxx +++ /dev/null @@ -1,1173 +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. - -/// \author Sweta Singh (sweta.singh@cern.ch) - -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/PIDResponse.h" -#include "Common/Core/trackUtilities.h" -#include "Common/CCDB/EventSelectionParams.h" -#include "Common/Core/TrackSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "Common/DataModel/Centrality.h" -#include "CommonConstants/MathConstants.h" -#include "Common/DataModel/FT0Corrected.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/RunningWorkflowInfo.h" -#include "PWGCF/Core/CorrelationContainer.h" -#include "PWGCF/Core/PairCuts.h" -#include "TDatabasePDG.h" -#include -#include "Common/CCDB/TriggerAliases.h" - -using namespace o2; -using namespace o2::framework; -using namespace o2::framework::expressions; -using namespace std; - -namespace o2::aod -{ - -using MyCollisions = soa::Join; -using MyTracks = soa::Join; - -using MyMCRecoCollisions = soa::Join; - -using MyMCRecoTracks = soa::Join; - -using MyCollision = MyCollisions::iterator; -using MyTrack = MyTracks::iterator; -} // namespace o2::aod - -double massPi = TDatabasePDG::Instance()->GetParticle(211)->Mass(); -double massKa = TDatabasePDG::Instance()->GetParticle(321)->Mass(); -double massPr = TDatabasePDG::Instance()->GetParticle(2212)->Mass(); - -struct IdentifiedMeanPtFluctuations { - - HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; - - Configurable piluprejection{"piluprejection", false, "Pileup rejection"}; - - void init(o2::framework::InitContext&) - { - AxisSpec vtxZAxis = {100, -20, 20, "Z (cm)"}; - AxisSpec dcaAxis = {1002, -5.01, 5.01, "DCA_{xy} (cm)"}; - AxisSpec dcazAxis = {1002, -5.01, 5.01, "DCA_{z} (cm)"}; - AxisSpec ptAxis = {400, 0.0, 4.0, "#it{p}_{T} (GeV/#it{c})"}; - AxisSpec pAxis = {400, 0.0, 4.0, "#it{p} (GeV/#it{c})"}; - AxisSpec betaAxis = {200, 0.0, 2.0, "TOF_{#beta} (GeV/#it{c})"}; - AxisSpec dEdxAxis = {2000, 0.0, 200.0, "dE/dx (GeV/#it{c})"}; - AxisSpec etaAxis = {100, -1.5, 1.5, "#eta"}; - AxisSpec nSigmaTPCAxis = {170, -8.5, 8.5, "n#sigma_{TPC}^{proton}"}; - AxisSpec nSigmaTPCAxispid = {170, -8.5, 8.5, "n#sigma_{TPC}"}; - AxisSpec nSigmaTOFAxispid = {170, -8.5, 8.5, "n#sigma_{TOF}"}; - // AxisSpec nChAxis = {2500, -0.5, 2499.5, "nCh"}; - AxisSpec centAxis = {100, 0., 100., "centrality"}; - AxisSpec subAxis = {30, 0., 30., "sample"}; - AxisSpec nchAxis = {4000, 0., 4000., "nch"}; - AxisSpec varAxis1 = {400, 0., 4., "var1"}; - AxisSpec varAxis2 = {400, 0., 4., "var2"}; - AxisSpec Chi2Axis = {100, 0., 100., "Chi2"}; - AxisSpec CrossedrowTPCAxis = {600, 0., 600., "TPC Crossed rows"}; - AxisSpec Counter = {10, 0., 10., "events"}; - - // QA Plots - histos.add("hEventCounter", "event counts", kTH1D, {Counter}); - - auto h = histos.add("tracksel", "tracksel", HistType::kTH1D, {{10, 0.5, 10.5}}); - h->GetXaxis()->SetBinLabel(1, "Tracks read"); - h->GetXaxis()->SetBinLabel(2, "Global track passed"); - h->GetXaxis()->SetBinLabel(3, "DCAxy passed"); - h->GetXaxis()->SetBinLabel(4, "DCAz passed"); - h->GetXaxis()->SetBinLabel(5, "Eta-cut passed"); - h->GetXaxis()->SetBinLabel(6, "pT-cut passed"); - h->GetXaxis()->SetBinLabel(7, "TPC crossed rows passed"); - h->GetXaxis()->SetBinLabel(8, "TPC Chai2cluster passed"); - h->GetXaxis()->SetBinLabel(9, "ITS Chai2cluster passed"); - - histos.add("hEventCounter_recMC", "event counts rec MC", kTH1D, {Counter}); - - auto h_rec = histos.add("tracksel_rec", "tracksel_rec", HistType::kTH1D, {{10, 0.5, 10.5}}); - h_rec->GetXaxis()->SetBinLabel(1, "has_mcCollision() read"); - h_rec->GetXaxis()->SetBinLabel(2, "Vertex Z > 10cm passed"); - h_rec->GetXaxis()->SetBinLabel(3, "sel 8 passed"); - h_rec->GetXaxis()->SetBinLabel(4, "kNoSameBunchPileup passed"); - h_rec->GetXaxis()->SetBinLabel(5, "kNoITSROFrameBorder passed"); - h_rec->GetXaxis()->SetBinLabel(6, "klsGoodZvtxFT0vsPV passed"); - h_rec->GetXaxis()->SetBinLabel(7, "klsVertexITSTPC passed"); - - histos.add("hZvtx_before_sel", "hZvtx_before_sel", kTH1D, {vtxZAxis}); - histos.add("hZvtx_after_sel", "hZvtx_after_sel", kTH1D, {vtxZAxis}); - histos.add("hZvtx_after_sel8", "hZvtx_after_sel8", kTH1D, {vtxZAxis}); - histos.add("hP", "hP", kTH1D, {pAxis}); - histos.add("hEta", ";hEta", kTH1D, {etaAxis}); - histos.add("hPt", ";#it{p}_{T} (GeV/#it{c})", kTH1D, {ptAxis}); - histos.add("hNsigmaTPC", "hNsigmaTPC", kTH2D, - {pAxis, nSigmaTPCAxis}); - histos.add("hDCAxy", "hDCAxy", kTH1D, {dcaAxis}); - histos.add("hDCAz", "hDCAz", kTH1D, {dcazAxis}); - - histos.add("hPtDCAxy", "hPtDCAxy", kTH2D, {ptAxis, dcaAxis}); - histos.add("hPtDCAz", "hPtDCAz", kTH2D, {ptAxis, dcazAxis}); - histos.add("NSigamaTPCpion", "NSigamaTPCpion", kTH2D, {ptAxis, nSigmaTPCAxispid}); - histos.add("NSigamaTPCkaon", "NSigamaTPCkaon", kTH2D, {ptAxis, nSigmaTPCAxispid}); - histos.add("NSigamaTPCproton", "NSigamaTPCproton", kTH2D, {ptAxis, nSigmaTPCAxispid}); - - histos.add("NSigamaTOFpion", "NSigamaTOFpion", kTH2D, {ptAxis, nSigmaTOFAxispid}); - histos.add("NSigamaTOFkaon", "NSigamaTOFkaon", kTH2D, {ptAxis, nSigmaTOFAxispid}); - histos.add("NSigamaTOFproton", "NSigamaTOFproton", kTH2D, {ptAxis, nSigmaTOFAxispid}); - - histos.add("NSigamaTPCpion_rec", "NSigamaTPCpion_rec", kTH2D, {pAxis, nSigmaTPCAxispid}); - histos.add("NSigamaTPCkaon_rec", "NSigamaTPCkaon_rec", kTH2D, {pAxis, nSigmaTPCAxispid}); - histos.add("NSigamaTPCproton_rec", "NSigamaTPCproton_rec", kTH2D, {pAxis, nSigmaTPCAxispid}); - - histos.add("NSigamaTOFpion_rec", "NSigamaTOFpion_rec", kTH2D, {pAxis, nSigmaTOFAxispid}); - histos.add("NSigamaTOFkaon_rec", "NSigamaTOFkaon_rec", kTH2D, {pAxis, nSigmaTOFAxispid}); - histos.add("NSigamaTOFproton_rec", "NSigamaTOFproton_rec", kTH2D, {pAxis, nSigmaTOFAxispid}); - - histos.add("NSigamaTPCTOFpion", "NSigamaTPCTOFpion", kTH2D, {nSigmaTPCAxispid, nSigmaTOFAxispid}); - histos.add("NSigamaTPCTOFkaon", "NSigamaTPCTOFkaon", kTH2D, {nSigmaTPCAxispid, nSigmaTOFAxispid}); - histos.add("NSigamaTPCTOFproton", "NSigamaTPCTOFproton", kTH2D, {nSigmaTPCAxispid, nSigmaTOFAxispid}); - - histos.add("NSigamaTPCTOFpion_rec", "NSigamaTPCTOFpion_rec", kTH2D, {nSigmaTPCAxispid, nSigmaTOFAxispid}); - histos.add("NSigamaTPCTOFkaon_rec", "NSigamaTPCTOFkaon_rec", kTH2D, {nSigmaTPCAxispid, nSigmaTOFAxispid}); - histos.add("NSigamaTPCTOFproton_rec", "NSigamaTPCTOFproton_rec", kTH2D, {nSigmaTPCAxispid, nSigmaTOFAxispid}); - - histos.add("NSigamaTPCpion_rec_bf_sel", "NSigamaTPCpion_rec_bf_sel", kTH2D, {pAxis, nSigmaTPCAxispid}); - histos.add("NSigamaTPCkaon_rec_bf_sel", "NSigamaTPCkaon_rec_bf_sel", kTH2D, {pAxis, nSigmaTPCAxispid}); - histos.add("NSigamaTPCproton_rec_bf_sel", "NSigamaTPCproton_rec_bf_sel", kTH2D, {pAxis, nSigmaTPCAxispid}); - - histos.add("NSigamaTOFpion_rec_bf_sel", "NSigamaTOFpion_rec_bf_sel", kTH2D, {pAxis, nSigmaTOFAxispid}); - histos.add("NSigamaTOFkaon_rec_bf_sel", "NSigamaTOFkaon_rec_bf_sel", kTH2D, {pAxis, nSigmaTOFAxispid}); - histos.add("NSigamaTOFproton_rec_bf_sel", "NSigamaTOFproton_rec_bf_sel", kTH2D, {pAxis, nSigmaTOFAxispid}); - - histos.add("NSigamaTPCTOFpion_rec_bf_sel", "NSigamaTPCTOFpion_rec_bf_sel", kTH2D, {nSigmaTPCAxispid, nSigmaTOFAxispid}); - histos.add("NSigamaTPCTOFkaon_rec_bf_sel", "NSigamaTPCTOFkaon_rec_bf_sel", kTH2D, {nSigmaTPCAxispid, nSigmaTOFAxispid}); - histos.add("NSigamaTPCTOFproton_rec_bf_sel", "NSigamaTPCTOFproton_rec_bf_sel", kTH2D, {nSigmaTPCAxispid, nSigmaTOFAxispid}); - - histos.add("hPtPion", ";#it{p}_{T} (GeV/#it{c})", kTH1D, {ptAxis}); - histos.add("hPtKaon", ";#it{p}_{T} (GeV/#it{c})", kTH1D, {ptAxis}); - histos.add("hPtProton", ";#it{p}_{T} (GeV/#it{c})", kTH1D, {ptAxis}); - - histos.add("hEtaPion", ";hEta", kTH1D, {etaAxis}); - histos.add("hEtaKaon", ";hEta", kTH1D, {etaAxis}); - histos.add("hEtaProton", ";hEta", kTH1D, {etaAxis}); - //=====================rapidity===================================== - histos.add("hyPion", ";hyPion", kTH1D, {etaAxis}); - histos.add("hyKaon", ";hyKaon", kTH1D, {etaAxis}); - histos.add("hyProton", ";hyProton", kTH1D, {etaAxis}); - - histos.add("hPtCh", "hPtCh", kTH2D, {nchAxis, ptAxis}); - histos.add("hPtChPion", "hPtChPion", kTH2D, {nchAxis, ptAxis}); - histos.add("hPtChKaon", "hPtChKaon", kTH2D, {nchAxis, ptAxis}); - histos.add("hPtChProton", "hPtChProton", kTH2D, {nchAxis, ptAxis}); - - histos.add("hPtCent", "hPtCent", kTH2D, {centAxis, ptAxis}); - histos.add("hPtCentPion", "hPtCentPion", kTH2D, {centAxis, ptAxis}); - histos.add("hPtCentKaon", "hPtCentKaon", kTH2D, {centAxis, ptAxis}); - histos.add("hPtCentProton", "hPtCentProton", kTH2D, {centAxis, ptAxis}); - - histos.add("hMeanPtCh", "hMeanPtCh", kTH2D, {nchAxis, ptAxis}); - histos.add("hCent", "hCent", kTH2D, {nchAxis, centAxis}); - - histos.add("hVar1", "hVar1", kTH2D, {subAxis, centAxis}); - histos.add("hVar2", "hVar2", kTH2D, {subAxis, centAxis}); - histos.add("hVar2meanpt", "hVar2meanpt", kTH2D, {centAxis, varAxis2}); - histos.add("hVar", "hVar", kTH2D, {subAxis, centAxis}); - histos.add("hVarc", "hVarc", kTH2D, {subAxis, centAxis}); - - histos.add("hVar1pi", "hVar1pi", kTH2D, {subAxis, centAxis}); - histos.add("hVar2pi", "hVar2pi", kTH2D, {subAxis, centAxis}); - histos.add("hVarpi", "hVarpi", kTH2D, {subAxis, centAxis}); - histos.add("hVar2meanptpi", "hVar2meanptpi", kTH2D, {centAxis, varAxis2}); - - histos.add("hVar1k", "hVar1k", kTH2D, {subAxis, centAxis}); - histos.add("hVar2k", "hVar2k", kTH2D, {subAxis, centAxis}); - histos.add("hVark", "hVark", kTH2D, {subAxis, centAxis}); - histos.add("hVar2meanptk", "hVar2meanptk", kTH2D, {centAxis, varAxis2}); - - histos.add("hVar1p", "hVar1p", kTH2D, {subAxis, centAxis}); - histos.add("hVar2p", "hVar2p", kTH2D, {subAxis, centAxis}); - histos.add("hVarp", "hVarp", kTH2D, {subAxis, centAxis}); - histos.add("hVar2meanptp", "hVar2meanptp", kTH2D, {centAxis, varAxis2}); - - //--------------------------------nch---------------------------------- - histos.add("hVar1x", "hVar1x", kTH2D, {subAxis, nchAxis}); - histos.add("hVar2x", "hVar2x", kTH2D, {subAxis, nchAxis}); - histos.add("hVarx", "hVarx", kTH2D, {subAxis, nchAxis}); - histos.add("hVar2meanptx", "hVar2meanptx", kTH2D, {nchAxis, varAxis2}); - - histos.add("hVar1pix", "hVar1pix", kTH2D, {subAxis, nchAxis}); - histos.add("hVar2pix", "hVar2pix", kTH2D, {subAxis, nchAxis}); - histos.add("hVarpix", "hVarpix", kTH2D, {subAxis, nchAxis}); - histos.add("hVar2meanptpix", "hVar2meanptpix", kTH2D, {nchAxis, varAxis2}); - - histos.add("hVar1kx", "hVar1kx", kTH2D, {subAxis, nchAxis}); - histos.add("hVar2kx", "hVar2kx", kTH2D, {subAxis, nchAxis}); - histos.add("hVarkx", "hVarkx", kTH2D, {subAxis, nchAxis}); - histos.add("hVar2meanptkx", "hVar2meanptkx", kTH2D, {nchAxis, varAxis2}); - - histos.add("hVar1px", "hVar1px", kTH2D, {subAxis, nchAxis}); - histos.add("hVar2px", "hVar2px", kTH2D, {subAxis, nchAxis}); - histos.add("hVarpx", "hVarpx", kTH2D, {subAxis, nchAxis}); - histos.add("hVar2meanptpx", "hVar2meanptpx", kTH2D, {nchAxis, varAxis2}); - - histos.add("ht", "ht", kTH1D, {centAxis}); - - histos.add("hCentrality", "hCentrality", kTH1D, {centAxis}); - - histos.add("hPEta", "hPEta", kTH2D, {pAxis, etaAxis}); - histos.add("hPtEta", "hPtEta", kTH2D, {ptAxis, etaAxis}); - histos.add("hPy", "hPy", kTH2D, {pAxis, etaAxis}); - histos.add("hPty", "hPty", kTH2D, {ptAxis, etaAxis}); - - histos.add("hPtyPion", "hPtyPion", kTH2D, {ptAxis, etaAxis}); - histos.add("hPtyKaon", "hPtyKaon", kTH2D, {ptAxis, etaAxis}); - histos.add("hPtyProton", "hPtyProton", kTH2D, {ptAxis, etaAxis}); - - histos.add("hPtyPion_rec", "hPtyPion_rec", kTH2D, {ptAxis, etaAxis}); - histos.add("hPtyKaon_rec", "hPtyKaon_rec", kTH2D, {ptAxis, etaAxis}); - histos.add("hPtyProton_rec", "hPtyProton_rec", kTH2D, {ptAxis, etaAxis}); - - histos.add("hPyPion_rec", "hPyPion_rec", kTH2D, {pAxis, etaAxis}); - histos.add("hPyKaon_rec", "hPyKaon_rec", kTH2D, {pAxis, etaAxis}); - histos.add("hPyProton_rec", "hPyProton_rec", kTH2D, {pAxis, etaAxis}); - - histos.add("hTOFbeta", "hTOFbeta", kTH2D, {pAxis, betaAxis}); - histos.add("hdEdx", "hdEdx", kTH2D, {pAxis, dEdxAxis}); - - histos.add("hTOFbeta_afterselection", "hTOFbeta_afterselection", kTH2D, {pAxis, betaAxis}); - histos.add("hdEdx_afterselection", "hdEdx_afterselection", kTH2D, {pAxis, dEdxAxis}); - - histos.add("hTOFbeta_afterselection1", "hTOFbeta_afterselection1", kTH2D, {pAxis, betaAxis}); - histos.add("hdEdx_afterselection1", "hdEdx_afterselection1", kTH2D, {pAxis, dEdxAxis}); - - histos.add("hTOFbeta_afterselection_rec_afterpidcut", "hTOFbeta_afterselection_rec_afterpidcut", kTH2D, {pAxis, betaAxis}); - histos.add("hdEdx_afterselection_rec_afterpidcut", "hdEdx_afterselection_rec_afterpidcut", kTH2D, {pAxis, dEdxAxis}); - - histos.add("hTOFbeta_afterselection_rec_beforepidcut", "hTOFbeta_afterselection_rec_beforepidcut", kTH2D, {pAxis, betaAxis}); - histos.add("hdEdx_afterselection_rec_beforepidcut", "hdEdx_afterselection_rec_beforepidcut", kTH2D, {pAxis, dEdxAxis}); - - histos.add("hdEdx_rec_bf_anycut", "hdEdx_rec_bf_anycut", kTH2D, {pAxis, dEdxAxis}); - - histos.add("hTPCchi2perCluster_before", "TPC #Chi^{2}/Cluster", kTH1D, {Chi2Axis}); - histos.add("hITSchi2perCluster_before", "ITS #Chi^{2}/Cluster", kTH1D, {Chi2Axis}); - histos.add("hTPCCrossedrows_before", "Crossed TPC rows", kTH1D, {CrossedrowTPCAxis}); - - histos.add("hTPCchi2perCluster_after", "TPC #Chi^{2}/Cluster", kTH1D, {Chi2Axis}); - histos.add("hITSchi2perCluster_after", "ITS #Chi^{2}/Cluster", kTH1D, {Chi2Axis}); - histos.add("hTPCCrossedrows_after", "Crossed TPC rows", kTH1D, {CrossedrowTPCAxis}); - - //--------------------------------nch---------------------------------- - histos.add("hVar1x_rec", "hVar1x_rec", kTH2D, {subAxis, nchAxis}); - histos.add("hVar2x_rec", "hVar2x_rec", kTH2D, {subAxis, nchAxis}); - histos.add("hVarx_rec", "hVarx_rec", kTH2D, {subAxis, nchAxis}); - histos.add("hVar2meanptx_rec", "hVar2meanptx_rec", kTH2D, {nchAxis, varAxis2}); - - histos.add("hVar1pix_rec", "hVar1pix_rec", kTH2D, {subAxis, nchAxis}); - histos.add("hVar2pix_rec", "hVar2pix_rec", kTH2D, {subAxis, nchAxis}); - histos.add("hVarpix_rec", "hVarpix_rec", kTH2D, {subAxis, nchAxis}); - histos.add("hVar2meanptpix_rec", "hVar2meanptpix_rec", kTH2D, {nchAxis, varAxis2}); - - histos.add("hVar1kx_rec", "hVar1kx_rec", kTH2D, {subAxis, nchAxis}); - histos.add("hVar2kx_rec", "hVar2kx_rec", kTH2D, {subAxis, nchAxis}); - histos.add("hVarkx_rec", "hVarkx_rec", kTH2D, {subAxis, nchAxis}); - histos.add("hVar2meanptkx_rec", "hVar2meanptkx_rec", kTH2D, {nchAxis, varAxis2}); - - histos.add("hVar1px_rec", "hVar1px_rec", kTH2D, {subAxis, nchAxis}); - histos.add("hVar2px_rec", "hVar2px_rec", kTH2D, {subAxis, nchAxis}); - histos.add("hVarpx_rec", "hVarpx_rec", kTH2D, {subAxis, nchAxis}); - histos.add("hVar2meanptpx_rec", "hVar2meanptpx_rec", kTH2D, {nchAxis, varAxis2}); - - //=======================MC histograms Generated ================================================ - histos.add("ptHistogram_allcharge_gen", "ptHistogram_allcharge_gen", kTH1D, {ptAxis}); - histos.add("ptHistogramPion", "ptHistogramPion", kTH1D, {ptAxis}); - histos.add("ptHistogramKaon", "ptHistogramKaon", kTH1D, {ptAxis}); - histos.add("ptHistogramProton", "ptHistogramProton", kTH1D, {ptAxis}); - - histos.add("hMC_Pt", ";#it{p}_{T} (GeV/#it{c})", kTH1D, {ptAxis}); - histos.add("MC_hZvtx_after_sel", ";#it{p}_{T} (GeV/#it{c})", kTH1D, {vtxZAxis}); - - histos.add("hTOFbeta_gen_pion", "hTOFbeta_gen_pion", kTH2D, {pAxis, betaAxis}); - histos.add("hdEdx_gen_pion", "hdEdx_gen_pion", kTH2D, {pAxis, dEdxAxis}); - - histos.add("hVar1x_gen", "hVar1x_gen", kTH2D, {subAxis, nchAxis}); - histos.add("hVar2x_gen", "hVar2x_gen", kTH2D, {subAxis, nchAxis}); - histos.add("hVarx_gen", "hVarx_gen", kTH2D, {subAxis, nchAxis}); - histos.add("hVar2meanptx_gen", "hVar2meanptx_gen", kTH2D, {nchAxis, varAxis2}); - - histos.add("hVar1pix_gen", "hVar1pix_gen", kTH2D, {subAxis, nchAxis}); - histos.add("hVar2pix_gen", "hVar2pix_gen", kTH2D, {subAxis, nchAxis}); - histos.add("hVarpix_gen", "hVarpix_gen", kTH2D, {subAxis, nchAxis}); - histos.add("hVar2meanptpix_gen", "hVar2meanptpix_gen", kTH2D, {nchAxis, varAxis2}); - - histos.add("hVar1kx_gen", "hVar1kx_gen", kTH2D, {subAxis, nchAxis}); - histos.add("hVar2kx_gen", "hVar2kx_gen", kTH2D, {subAxis, nchAxis}); - histos.add("hVarkx_gen", "hVarkx_gen", kTH2D, {subAxis, nchAxis}); - histos.add("hVar2meanptkx_gen", "hVar2meanptkx_gen", kTH2D, {nchAxis, varAxis2}); - - histos.add("hVar1px_gen", "hVar1px_gen", kTH2D, {subAxis, nchAxis}); - histos.add("hVar2px_gen", "hVar2px_gen", kTH2D, {subAxis, nchAxis}); - histos.add("hVarpx_gen", "hVarpx_gen", kTH2D, {subAxis, nchAxis}); - histos.add("hVar2meanptpx_gen", "hVar2meanptpx_gen", kTH2D, {nchAxis, varAxis2}); - - //========================MC Histograms Reconstructed================================================= - - histos.add("hZvtx_after_sel_rec", "hZvtx_after_sel_rec", kTH1D, {vtxZAxis}); - histos.add("hZvtx_after_sel8_rec", "hZvtx_after_sel8_rec", kTH1D, {vtxZAxis}); - - histos.add("ptHistogram_allcharge_rec", "ptHistogram_allcharge_rec", kTH1D, {ptAxis}); - histos.add("ptHistogramPionrec", "ptHistogramPionrec", kTH1D, {ptAxis}); - histos.add("ptHistogramKaonrec", "ptHistogramKaonrec", kTH1D, {ptAxis}); - histos.add("ptHistogramProtonrec", "ptHistogramProtonrec", kTH1D, {ptAxis}); - - histos.add("ptHistogramPionrec_purity", "ptHistogramPionrec_purity", kTH1D, {ptAxis}); - histos.add("ptHistogramKaonrec_purity", "ptHistogramKaonrec_purity", kTH1D, {ptAxis}); - histos.add("ptHistogramProtonrec_purity", "ptHistogramProtonrec_purity", kTH1D, {ptAxis}); - - histos.add("ptHistogramPionrec_pdg", "ptHistogramPionrec_pdg", kTH1D, {ptAxis}); - histos.add("ptHistogramKaonrec_pdg", "ptHistogramKaonrec_pdg", kTH1D, {ptAxis}); - histos.add("ptHistogramProtonrec_pdg", "ptHistogramProtonrec_pdg", kTH1D, {ptAxis}); - - histos.add("Histogram_mass2_p_rec_beforesel", "Histogram_mass2_p_rec_beforesel", kTH1D, {ptAxis}); - histos.add("Histogram_mass2_p_rec_aftersel", "Histogram_mass2_p_rec_aftersel", kTH1D, {ptAxis}); - } - - //++++++++++++++++++++++++Monte Carlo Reconstructed +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - template - void SelTPConlyPions(const T& track1) - { - (track1.hasTPC() && (track1.p() < 0.7) && abs(track1.tpcNSigmaPi()) < 3. && (std::abs(track1.tpcNSigmaKa()) > 3.0 && std::abs(track1.tpcNSigmaPr()) > 3.0)); - } - template - void SelTPConlyKaons(const T& track1) - { - (track1.hasTPC() && (track1.p() < 0.7) && abs(track1.tpcNSigmaKa()) < 3.0 && (std::abs(track1.tpcNSigmaPi()) > 3.0 && std::abs(track1.tpcNSigmaPr()) > 3.0)); - } - template - void SelTPConlyProtons(const T& track1) - { - (track1.hasTPC() && (track1.p() < 1.1) && abs(track1.tpcNSigmaPr()) < 3.0 && (std::abs(track1.tpcNSigmaPi()) > 3.0 && std::abs(track1.tpcNSigmaKa()) > 3.0)); - } - - template - void SelTPCTOFPions(const T& track1) - { - (track1.hasTPC() && track1.hasTOF() && track1.p() >= 0.7 && TMath::Hypot((track1.tofNSigmaPr() + 2) / 3.0, (track1.tpcNSigmaPr() - 6) / 4.0) > 3. && TMath::Hypot((track1.tofNSigmaKa() + 2) / 3.0, (track1.tpcNSigmaKa() - 6) / 4.0) > 3. && TMath::Hypot((track1.tofNSigmaPi() + 2) / 3.0, (track1.tpcNSigmaPi() - 6) / 4.0) < 3.); - } - - template - void SelTPCTOFKaons(const T& track1) - { - (track1.hasTPC() && track1.hasTOF() && track1.p() >= 0.7 && TMath::Hypot((track1.tofNSigmaPr() + 2) / 3.0, (track1.tpcNSigmaPr() - 6) / 4.0) > 3. && TMath::Hypot((track1.tofNSigmaPi() + 2) / 3.0, (track1.tpcNSigmaPi() - 6) / 4.0) > 3. && TMath::Hypot((track1.tofNSigmaKa() + 2) / 3.0, (track1.tpcNSigmaKa() - 6) / 4.0) < 3.); - } - - template - void SelTPCTOFProtons(const T& track1) - { - if (track1.hasTPC() && track1.hasTOF() && track1.p() >= 1.1 && TMath::Hypot((track1.tofNSigmaPi() + 2) / 3.0, (track1.tpcNSigmaPi() - 6) / 4.0) > 3. && TMath::Hypot((track1.tofNSigmaKa() + 2) / 3.0, (track1.tpcNSigmaKa() - 6) / 4.0) > 3. && TMath::Hypot((track1.tofNSigmaPr() + 2) / 3.0, (track1.tpcNSigmaPr() - 6) / 4.0) < 3.) { - }; - } - - void processMCReco(aod::MyMCRecoCollisions::iterator const& mccoll, aod::MyMCRecoTracks const& mcrectrack, aod::McParticles const& /*mcParticles*/) - { - if (!mccoll.has_mcCollision()) { - return; - } - histos.fill(HIST("tracksel_rec"), 1); - - if (fabs(mccoll.posZ()) > 10.f) { - return; - } - histos.fill(HIST("hZvtx_after_sel_rec"), mccoll.posZ()); - - histos.fill(HIST("tracksel_rec"), 2); - - if (!mccoll.sel8()) { - return; - } - - histos.fill(HIST("hZvtx_after_sel8_rec"), mccoll.posZ()); - - histos.fill(HIST("tracksel_rec"), 3); - - if (!mccoll.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { - return; - } - histos.fill(HIST("tracksel_rec"), 4); - - if (!mccoll.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { - return; - } - histos.fill(HIST("tracksel_rec"), 5); - - if (!mccoll.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { - return; - } - histos.fill(HIST("tracksel_rec"), 6); - - if (!mccoll.selection_bit(o2::aod::evsel::kIsVertexITSTPC)) { - return; - } - histos.fill(HIST("tracksel_rec"), 7); - - double nCh_rec = 0.; - double nChpi_rec = 0.; - double nChk_rec = 0.; - double nChp_rec = 0.; - - double Q1_rec = 0, Q2_rec = 0; - double Q1pi_rec = 0, Q2pi_rec = 0; - double Q1k_rec = 0, Q2k_rec = 0; - double Q1p_rec = 0, Q2p_rec = 0; - double var1_rec = 0, var2_rec = 0; - double var1pi_rec = 0, var2pi_rec = 0; - double var1k_rec = 0, var2k_rec = 0; - double var1p_rec = 0, var2p_rec = 0; - - int sample_rec = histos.get(HIST("hZvtx_after_sel8_rec"))->GetEntries(); - sample_rec = sample_rec % 30; - - for (auto track1 : mcrectrack) { - if (!(track1.has_collision())) - continue; - if (!(track1.has_mcParticle())) - continue; - if (!(track1.mcParticle().isPhysicalPrimary())) - continue; - if (!track1.isGlobalTrack()) - continue; - - if (!(track1.pt() > 0.15) || !(track1.pt() < 2.0)) - continue; // pt = 0.15 - if (!(track1.eta() > -0.8) || !(track1.eta() < 0.8)) - continue; // eta cut - - nCh_rec += 1.; - - Q1_rec += track1.pt(); - Q2_rec += (track1.pt() * track1.pt()); - - histos.fill(HIST("ptHistogram_allcharge_rec"), track1.pt()); - - if (track1.hasTPC()) - histos.fill(HIST("hdEdx_rec_bf_anycut"), track1.p(), track1.tpcSignal()); - - //======================================================================== - - if (abs(track1.mcParticle().pdgCode()) == 211) { - - histos.fill(HIST("ptHistogramPionrec_pdg"), track1.pt()); - } - if (abs(track1.mcParticle().pdgCode()) == 321) { - - histos.fill(HIST("ptHistogramKaonrec_pdg"), track1.pt()); - } - if (abs(track1.mcParticle().pdgCode()) == 2212) { - - histos.fill(HIST("ptHistogramProtonrec_pdg"), track1.pt()); - } - - //+++++++++ electron rejection ++++++++++++++++++++++++++++++++// - - if (abs(track1.tpcNSigmaEl()) < 3.0 && abs(track1.tpcNSigmaPi()) > 3. && abs(track1.tpcNSigmaKa()) > 3. && abs(track1.tpcNSigmaPr()) > 3.) - continue; - - //============Reconstructed MC=================PIONS selection==============================================================// - - if (track1.hasTPC()) - histos.fill(HIST("hdEdx_afterselection_rec_beforepidcut"), track1.p(), track1.tpcSignal()); - if (track1.hasTOF()) - histos.fill(HIST("hTOFbeta_afterselection_rec_beforepidcut"), track1.p(), track1.beta()); - - if (track1.hasTPC() && track1.hasTOF()) { - - histos.fill(HIST("NSigamaTPCpion_rec_bf_sel"), track1.p(), track1.tpcNSigmaPi()); - histos.fill(HIST("NSigamaTOFpion_rec_bf_sel"), track1.p(), track1.tofNSigmaPi()); - histos.fill(HIST("NSigamaTPCTOFpion_rec_bf_sel"), track1.tpcNSigmaPi(), track1.tofNSigmaPi()); - } - - SelTPConlyPions(track1); // Pion (TPC only) - SelTPCTOFPions(track1); // Pion passes TPC and TOF both! - - { - - histos.fill(HIST("ptHistogramPionrec"), track1.pt()); - - nChpi_rec += 1.; - Q1pi_rec += track1.pt(); - Q2pi_rec += (track1.pt() * track1.pt()); - - histos.fill(HIST("NSigamaTPCpion_rec"), track1.p(), track1.tpcNSigmaPi()); - histos.fill(HIST("NSigamaTOFpion_rec"), track1.p(), track1.tofNSigmaPi()); - histos.fill(HIST("NSigamaTPCTOFpion_rec"), track1.tpcNSigmaPi(), track1.tofNSigmaPi()); - - if (track1.beta() > 1) - continue; - - histos.fill(HIST("hdEdx_afterselection_rec_afterpidcut"), track1.p(), track1.tpcSignal()); - histos.fill(HIST("hTOFbeta_afterselection_rec_afterpidcut"), track1.p(), track1.beta()); - - if (abs(track1.mcParticle().pdgCode()) == 211) { - histos.fill(HIST("ptHistogramPionrec_purity"), track1.pt()); - } - - if (abs(track1.rapidity(massPi)) < 0.5) { - - histos.fill(HIST("hPyPion_rec"), track1.p(), track1.rapidity(massPi)); - histos.fill(HIST("hPtyPion_rec"), track1.pt(), track1.rapidity(massPi)); - } - } - - //============Reconstructed MC=================KAONS selection==============================================================// - - if (track1.hasTPC()) - histos.fill(HIST("hdEdx_afterselection_rec_beforepidcut"), track1.p(), track1.tpcSignal()); - if (track1.hasTOF()) - histos.fill(HIST("hTOFbeta_afterselection_rec_beforepidcut"), track1.p(), track1.beta()); - - if (track1.hasTPC() && track1.hasTOF()) { - - histos.fill(HIST("NSigamaTPCkaon_rec_bf_sel"), track1.p(), track1.tpcNSigmaKa()); - histos.fill(HIST("NSigamaTOFkaon_rec_bf_sel"), track1.p(), track1.tofNSigmaKa()); - histos.fill(HIST("NSigamaTPCTOFkaon_rec_bf_sel"), track1.tpcNSigmaKa(), track1.tofNSigmaKa()); - } - - SelTPConlyKaons(track1); // Kaons passes from TPC only! - SelTPCTOFKaons(track1); // Kaons passes from TPC and TOF both! - - { - - histos.fill(HIST("ptHistogramKaonrec"), track1.pt()); - - nChk_rec += 1.; - Q1k_rec += track1.pt(); - Q2k_rec += (track1.pt() * track1.pt()); - - histos.fill(HIST("NSigamaTPCkaon_rec"), track1.p(), track1.tpcNSigmaKa()); - histos.fill(HIST("NSigamaTOFkaon_rec"), track1.p(), track1.tofNSigmaKa()); - histos.fill(HIST("NSigamaTPCTOFkaon_rec"), track1.tpcNSigmaKa(), track1.tofNSigmaKa()); - - if (track1.beta() > 1) - continue; - - histos.fill(HIST("hdEdx_afterselection_rec_afterpidcut"), track1.p(), track1.tpcSignal()); - histos.fill(HIST("hTOFbeta_afterselection_rec_afterpidcut"), track1.p(), track1.beta()); - - if (abs(track1.mcParticle().pdgCode()) == 321) { - histos.fill(HIST("ptHistogramKaonrec_purity"), track1.pt()); - } - - if (abs(track1.rapidity(massKa)) < 0.5) { - - histos.fill(HIST("hPyKaon_rec"), track1.p(), track1.rapidity(massKa)); - histos.fill(HIST("hPtyKaon_rec"), track1.pt(), track1.rapidity(massKa)); - } - } - - //============Reconstructed MC=================PROTONS selection==============================================================// - - if (track1.hasTPC()) - histos.fill(HIST("hdEdx_afterselection_rec_beforepidcut"), track1.p(), track1.tpcSignal()); - if (track1.hasTOF()) - histos.fill(HIST("hTOFbeta_afterselection_rec_beforepidcut"), track1.p(), track1.beta()); - - if (track1.hasTPC() && track1.hasTOF()) { - - histos.fill(HIST("NSigamaTPCproton_rec_bf_sel"), track1.p(), track1.tpcNSigmaPr()); - histos.fill(HIST("NSigamaTOFproton_rec_bf_sel"), track1.p(), track1.tofNSigmaPr()); - histos.fill(HIST("NSigamaTPCTOFproton_rec_bf_sel"), track1.tpcNSigmaPr(), track1.tofNSigmaPr()); - } - - SelTPConlyProtons(track1); // Protons passes from TPC only! - SelTPCTOFProtons(track1); // Protons passes from TPC and TOF both! - - { - - histos.fill(HIST("ptHistogramProtonrec"), track1.pt()); - - nChp_rec += 1.; - Q1p_rec += track1.pt(); - Q2p_rec += (track1.pt() * track1.pt()); - - histos.fill(HIST("NSigamaTPCproton_rec"), track1.p(), track1.tpcNSigmaPr()); - histos.fill(HIST("NSigamaTOFproton_rec"), track1.p(), track1.tofNSigmaPr()); - histos.fill(HIST("NSigamaTPCTOFproton_rec"), track1.tpcNSigmaPr(), track1.tofNSigmaPr()); - - if (track1.beta() > 1) - continue; - - histos.fill(HIST("hdEdx_afterselection_rec_afterpidcut"), track1.p(), track1.tpcSignal()); - histos.fill(HIST("hTOFbeta_afterselection_rec_afterpidcut"), track1.p(), track1.beta()); - - if (abs(track1.mcParticle().pdgCode()) == 2212) { - histos.fill(HIST("ptHistogramProtonrec_purity"), track1.pt()); - } - - if (abs(track1.rapidity(massPr)) < 0.5) { - - histos.fill(HIST("hPyProton_rec"), track1.p(), track1.rapidity(massPr)); - histos.fill(HIST("hPtyProton_rec"), track1.pt(), track1.rapidity(massPr)); - } - } - - //============================================================================ - - } // track loop ends - - if (nCh_rec < 2) - return; - - //------------------ all charges------------------------------------- - var1_rec = (Q1_rec * Q1_rec - Q2_rec) / (nCh_rec * (nCh_rec - 1)); - var2_rec = (Q1_rec / nCh_rec); - - //---------------------- pions ---------------------------------------- - - if (nChpi_rec > 2) { - var1pi_rec = (Q1pi_rec * Q1pi_rec - Q2pi_rec) / (nChpi_rec * (nChpi_rec - 1)); - var2pi_rec = (Q1pi_rec / nChpi_rec); - } - - //----------------------- kaons --------------------------------------- - if (nChk_rec > 2) { - var1k_rec = (Q1k_rec * Q1k_rec - Q2k_rec) / (nChk_rec * (nChk_rec - 1)); - var2k_rec = (Q1k_rec / nChk_rec); - } - - //---------------------------- protons ---------------------------------- - if (nChp_rec > 2) { - var1p_rec = (Q1p_rec * Q1p_rec - Q2p_rec) / (nChp_rec * (nChp_rec - 1)); - var2p_rec = (Q1p_rec / nChp_rec); - } - - //-----------------------nch------------------------------------- - histos.fill(HIST("hVar1x_rec"), sample_rec, nCh_rec, var1_rec); - histos.fill(HIST("hVar2x_rec"), sample_rec, nCh_rec, var2_rec); - histos.fill(HIST("hVarx_rec"), sample_rec, nCh_rec); - histos.fill(HIST("hVar2meanptx_rec"), nCh_rec, var2_rec); - - histos.fill(HIST("hVar1pix_rec"), sample_rec, nCh_rec, var1pi_rec); - histos.fill(HIST("hVar2pix_rec"), sample_rec, nCh_rec, var2pi_rec); - histos.fill(HIST("hVarpix_rec"), sample_rec, nChpi_rec); - histos.fill(HIST("hVar2meanptpix_rec"), nCh_rec, var2pi_rec); - - histos.fill(HIST("hVar1kx_rec"), sample_rec, nCh_rec, var1k_rec); - histos.fill(HIST("hVar2kx_rec"), sample_rec, nCh_rec, var2k_rec); - histos.fill(HIST("hVarkx_rec"), sample_rec, nChk_rec); - histos.fill(HIST("hVar2meanptkx_rec"), nCh_rec, var2k_rec); - - histos.fill(HIST("hVar1px_rec"), sample_rec, nCh_rec, var1p_rec); - histos.fill(HIST("hVar2px_rec"), sample_rec, nCh_rec, var2p_rec); - histos.fill(HIST("hVarpx_rec"), sample_rec, nChp_rec); - histos.fill(HIST("hVar2meanptpx_rec"), nCh_rec, var2p_rec); - - } // ends - - PROCESS_SWITCH(IdentifiedMeanPtFluctuations, processMCReco, "process reconstructed information", true); - - //++++++++++++++++++++++++++++Monte Carlo Generated ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - void processMCGen(aod::McCollision const& mcCollision, aod::McParticles& mcParticles) - - { - - if (fabs(mcCollision.posZ()) > 10.f) { - return; - } - histos.fill(HIST("MC_hZvtx_after_sel"), mcCollision.posZ()); - - double nCh_gen = 0.; - double nChpi_gen = 0.; - double nChk_gen = 0.; - double nChp_gen = 0.; - - double Q1_gen = 0, Q2_gen = 0; - double Q1pi_gen = 0, Q2pi_gen = 0; - double Q1k_gen = 0, Q2k_gen = 0; - double Q1p_gen = 0, Q2p_gen = 0; - - double var1_gen = 0, var2_gen = 0; - double var1pi_gen = 0, var2pi_gen = 0; - double var1k_gen = 0, var2k_gen = 0; - double var1p_gen = 0, var2p_gen = 0; - - int sample_gen = histos.get(HIST("hZvtx_after_sel"))->GetEntries(); - sample_gen = sample_gen % 30; - - for (auto& mcgentrack : mcParticles) - - { - auto pdgcode = std::abs(mcgentrack.pdgCode()); - if (!(mcgentrack.has_mcCollision())) - continue; - if (!(mcgentrack.isPhysicalPrimary())) - continue; - if (!(mcgentrack.pt() > 0.15) || !(mcgentrack.pt() < 2.)) - continue; - if (!(mcgentrack.eta() > -0.8) || !(mcgentrack.eta() < 0.8)) - continue; - - nCh_gen += 1.; - - Q1_gen += mcgentrack.pt(); - Q2_gen += (mcgentrack.pt() * mcgentrack.pt()); - - histos.fill(HIST("ptHistogram_allcharge_gen"), mcgentrack.pt()); - - if (pdgcode == 211) { - - histos.fill(HIST("ptHistogramPion"), mcgentrack.pt()); - - nChpi_gen += 1.; - Q1pi_gen += mcgentrack.pt(); - Q2pi_gen += (mcgentrack.pt() * mcgentrack.pt()); - } - - if (pdgcode == 321) { - - histos.fill(HIST("ptHistogramKaon"), mcgentrack.pt()); - - nChk_gen += 1.; - Q1k_gen += mcgentrack.pt(); - Q2k_gen += (mcgentrack.pt() * mcgentrack.pt()); - } - - if (pdgcode == 2212) { - - histos.fill(HIST("ptHistogramProton"), mcgentrack.pt()); - - nChp_gen += 1.; - Q1p_gen += mcgentrack.pt(); - Q2p_gen += (mcgentrack.pt() * mcgentrack.pt()); - } - - //================================= Pion Generated Calculation ==================================== - - } // track loop ends! - - if (nCh_gen < 2) - return; - - //------------------ all charges------------------------------------- - var1_gen = (Q1_gen * Q1_gen - Q2_gen) / (nCh_gen * (nCh_gen - 1)); - var2_gen = (Q1_gen / nCh_gen); - - //---------------------- pions ---------------------------------------- - - if (nChpi_gen > 2) { - var1pi_gen = (Q1pi_gen * Q1pi_gen - Q2pi_gen) / (nChpi_gen * (nChpi_gen - 1)); - var2pi_gen = (Q1pi_gen / nChpi_gen); - } - - //----------------------- kaons --------------------------------------- - if (nChk_gen > 2) { - var1k_gen = (Q1k_gen * Q1k_gen - Q2k_gen) / (nChk_gen * (nChk_gen - 1)); - var2k_gen = (Q1k_gen / nChk_gen); - } - - //---------------------------- protons ---------------------------------- - if (nChp_gen > 2) { - var1p_gen = (Q1p_gen * Q1p_gen - Q2p_gen) / (nChp_gen * (nChp_gen - 1)); - var2p_gen = (Q1p_gen / nChp_gen); - } - - //-----------------------nch------------------------------------- - histos.fill(HIST("hVar1x_gen"), sample_gen, nCh_gen, var1_gen); - histos.fill(HIST("hVar2x_gen"), sample_gen, nCh_gen, var2_gen); - histos.fill(HIST("hVarx_gen"), sample_gen, nCh_gen); - histos.fill(HIST("hVar2meanptx_gen"), nCh_gen, var2_gen); - - histos.fill(HIST("hVar1pix_gen"), sample_gen, nCh_gen, var1pi_gen); - histos.fill(HIST("hVar2pix_gen"), sample_gen, nCh_gen, var2pi_gen); - histos.fill(HIST("hVarpix_gen"), sample_gen, nChpi_gen); - histos.fill(HIST("hVar2meanptpix_gen"), nCh_gen, var2pi_gen); - - histos.fill(HIST("hVar1kx_gen"), sample_gen, nCh_gen, var1k_gen); - histos.fill(HIST("hVar2kx_gen"), sample_gen, nCh_gen, var2k_gen); - histos.fill(HIST("hVarkx_gen"), sample_gen, nChk_gen); - histos.fill(HIST("hVar2meanptkx_gen"), nCh_gen, var2k_gen); - - histos.fill(HIST("hVar1px_gen"), sample_gen, nCh_gen, var1p_gen); - histos.fill(HIST("hVar2px_gen"), sample_gen, nCh_gen, var2p_gen); - histos.fill(HIST("hVarpx_gen"), sample_gen, nChp_gen); - histos.fill(HIST("hVar2meanptpx_gen"), nCh_gen, var2p_gen); - } - PROCESS_SWITCH(IdentifiedMeanPtFluctuations, processMCGen, "process generated information", true); - - //+++++++++++++++++++++++++++++DATA CALCULATION +++++++++++++++++++++++++++++++++++++++++++++++++++++ - void process(aod::MyCollision const& coll, aod::MyTracks const& inputTracks) - - { - histos.fill(HIST("hEventCounter"), 1.); - - histos.fill(HIST("hZvtx_before_sel"), coll.posZ()); - if (fabs(coll.posZ()) > 10.f) { - return; - } - - histos.fill(HIST("hEventCounter"), 2.); - - histos.fill(HIST("hZvtx_after_sel"), coll.posZ()); - - if (!coll.sel8()) { - return; - } - histos.fill(HIST("hZvtx_after_sel8"), coll.posZ()); - - histos.fill(HIST("hEventCounter"), 3.); - - const auto cent = coll.centFT0C(); - histos.fill(HIST("hCentrality"), cent); - - double nCh = 0.; - double nChpi = 0.; - double nChk = 0.; - double nChp = 0.; - - double Q1 = 0., Q2 = 0.; - double Q1pi = 0., Q2pi = 0.; - double Q1k = 0., Q2k = 0.; - double Q1p = 0., Q2p = 0.; - double var1 = 0., var2 = 0., twopar_allcharge = 0.; - double var1pi = 0., var2pi = 0.; - double var1k = 0., var2k = 0.; - double var1p = 0., var2p = 0.; - // cent = 0; - - // sampling - int sample = histos.get(HIST("hZvtx_after_sel8"))->GetEntries(); - sample = sample % 30; - - // Perfroming the track selection========================================== - for (auto track : inputTracks) { - // Loop over tracks - - // inital tracks - histos.fill(HIST("tracksel"), 1); - - histos.fill(HIST("hTPCchi2perCluster_before"), track.tpcChi2NCl()); - histos.fill(HIST("hITSchi2perCluster_before"), track.itsChi2NCl()); - histos.fill(HIST("hTPCCrossedrows_before"), track.tpcNClsCrossedRows()); - - // tracks passed after GlobalTrackcut - if (!track.isGlobalTrack()) - continue; - histos.fill(HIST("tracksel"), 2); - - // tracks passed after DCAxy - // if (!(fabs(track.dcaXY()) < 0.12)) continue;//global cut already includes - histos.fill(HIST("tracksel"), 3); - - // tracks passed after DCAz - // - histos.fill(HIST("hDCAxy"), track.dcaXY()); - histos.fill(HIST("hDCAz"), track.dcaZ()); - - // if (!(fabs(track.dcaZ()) < 1.)) continue;//global cut already includes (DCAz< 2.0) cm - histos.fill(HIST("tracksel"), 4); - - // tracks passed after Eta-cut - if (!(fabs(track.eta()) < 0.8)) - continue; - histos.fill(HIST("tracksel"), 5); - - // tracks passed after pT-cut - if (!(track.pt() > 0.15 && track.pt() < 2.)) - continue; // pt = 0.15 - histos.fill(HIST("tracksel"), 6); - - // if (track.tpcNClsCrossedRows() < 70.0) continue; - histos.fill(HIST("hTPCCrossedrows_after"), track.tpcNClsCrossedRows()); - histos.fill(HIST("tracksel"), 7); - - // if (track.tpcChi2NCl() > 4.0) continue; - histos.fill(HIST("hTPCchi2perCluster_after"), track.tpcChi2NCl()); - histos.fill(HIST("tracksel"), 8); - - // if (track.itsChi2NCl() > 36.0) continue; - histos.fill(HIST("hITSchi2perCluster_after"), track.itsChi2NCl()); - histos.fill(HIST("tracksel"), 9); - - nCh += 1.; - - Q1 += track.pt(); - Q2 += (track.pt() * track.pt()); - - histos.fill(HIST("hP"), track.p()); - histos.fill(HIST("hPt"), track.pt()); - histos.fill(HIST("hEta"), track.eta()); - histos.fill(HIST("hPtDCAxy"), track.pt(), track.dcaXY()); - histos.fill(HIST("hPtDCAz"), track.pt(), track.dcaZ()); - - histos.fill(HIST("hPtEta"), track.pt(), track.eta()); - histos.fill(HIST("hPEta"), track.p(), track.eta()); - - histos.fill(HIST("hNsigmaTPC"), track.p(), track.tpcNSigmaPr()); - - // only TPC tracks: Pion, Kaon, Proton - if (track.hasTPC() && abs(track.tpcNSigmaPi()) < 2.) - histos.fill(HIST("NSigamaTPCpion"), track.pt(), track.tpcNSigmaPi()); - if (track.hasTPC() && abs(track.tpcNSigmaKa()) < 2.) - histos.fill(HIST("NSigamaTPCkaon"), track.pt(), track.tpcNSigmaKa()); - if (track.hasTPC() && abs(track.tpcNSigmaPr()) < 2.) - histos.fill(HIST("NSigamaTPCproton"), track.pt(), track.tpcNSigmaPr()); - - // only TOF tracks: Pion, Kaon, Proton - if (track.hasTOF() && abs(track.tofNSigmaPi()) < 2.) - histos.fill(HIST("NSigamaTOFpion"), track.pt(), track.tofNSigmaPi()); - if (track.hasTOF() && abs(track.tofNSigmaKa()) < 2.) - histos.fill(HIST("NSigamaTOFkaon"), track.pt(), track.tofNSigmaKa()); - if (track.hasTOF() && abs(track.tofNSigmaPr()) < 2.) - histos.fill(HIST("NSigamaTOFproton"), track.pt(), track.tofNSigmaPr()); - - if (track.hasTPC()) - histos.fill(HIST("hdEdx"), track.p(), track.tpcSignal()); - if (track.hasTOF()) - histos.fill(HIST("hTOFbeta"), track.p(), track.beta()); - - //=============================pion============================================================== - // only TPC+TOF tracks: Pion, Kaon, Proton - if ((track.hasTPC() && abs(track.tpcNSigmaPi()) < 2.) && (track.hasTOF() && abs(track.tofNSigmaPi()) < 2.)) { - histos.fill(HIST("NSigamaTPCTOFpion"), track.tpcNSigmaPi(), track.tofNSigmaPi()); - - histos.fill(HIST("hdEdx_afterselection"), track.p(), track.tpcSignal()); - histos.fill(HIST("hTOFbeta_afterselection"), track.p(), track.beta()); - } - - // pion-TPC----------------------------------------------------------------------------------- - - if ((track.hasTPC() && abs(track.tpcNSigmaPi()) < 2. && (track.pt() >= 0.15 && track.pt() < 0.65) && (abs(track.rapidity(massPi)) < 0.5) && (std::abs(track.tpcNSigmaEl()) > 1.0 && std::abs(track.tpcNSigmaKa()) > 2.0 && std::abs(track.tpcNSigmaPr()) > 2.0))) { - - histos.fill(HIST("hPtPion"), track.pt()); - histos.fill(HIST("hEtaPion"), track.eta()); - histos.fill(HIST("hyPion"), track.rapidity(massPi)); - histos.fill(HIST("hPtyPion"), track.pt(), track.rapidity(massPi)); - - nChpi += 1.; - Q1pi += track.pt(); - Q2pi += (track.pt() * track.pt()); - - if (track.beta() > 1) - continue; - - histos.fill(HIST("hdEdx_afterselection1"), track.p(), track.tpcSignal()); - histos.fill(HIST("hTOFbeta_afterselection1"), track.p(), track.beta()); - } - - // pion->(TPC+TOF)------------------------------------------------------------------------------------ - if ((track.pt() >= 0.65 && track.pt() < 2.0) && (abs(track.rapidity(massPi)) < 0.5) && track.hasTPC() && track.hasTOF() && (std::abs(track.tofNSigmaKa()) > 2.0 && std::abs(track.tofNSigmaPr()) > 2.0) && abs(sqrt(track.tpcNSigmaPi()) * (track.tpcNSigmaPi()) + (track.tofNSigmaPi()) * (track.tofNSigmaPi())) < 2.) { - - histos.fill(HIST("hPtPion"), track.pt()); - histos.fill(HIST("hEtaPion"), track.eta()); - histos.fill(HIST("hyPion"), track.rapidity(massPi)); - histos.fill(HIST("hPtyPion"), track.pt(), track.rapidity(massPi)); - - nChpi += 1.; - Q1pi += track.pt(); - Q2pi += (track.pt() * track.pt()); - - if (track.beta() > 1) - continue; - - histos.fill(HIST("hdEdx_afterselection1"), track.p(), track.tpcSignal()); - histos.fill(HIST("hTOFbeta_afterselection1"), track.p(), track.beta()); - } - - //===========================kaon=============================================================== - - if ((track.hasTPC() && abs(track.tpcNSigmaKa()) < 2.) && (track.hasTOF() && abs(track.tofNSigmaKa()) < 2.)) { - histos.fill(HIST("NSigamaTPCTOFkaon"), track.tpcNSigmaKa(), track.tofNSigmaKa()); - histos.fill(HIST("hdEdx_afterselection"), track.p(), track.tpcSignal()); - histos.fill(HIST("hTOFbeta_afterselection"), track.p(), track.beta()); - } - - if (track.hasTPC() && abs(track.tpcNSigmaKa()) < 2. && (track.pt() >= 0.15 && track.pt() < 0.65) && (abs(track.rapidity(massKa)) < 0.5) && (std::abs(track.tpcNSigmaEl()) > 1.0 && std::abs(track.tpcNSigmaPi()) > 2.0 && std::abs(track.tpcNSigmaPr()) > 2.0)) { - - histos.fill(HIST("hPtKaon"), track.pt()); - histos.fill(HIST("hEtaKaon"), track.eta()); - histos.fill(HIST("hyKaon"), track.rapidity(massKa)); - histos.fill(HIST("hPtyKaon"), track.pt(), track.rapidity(massKa)); - - nChk += 1.; - Q1k += track.pt(); - Q2k += (track.pt() * track.pt()); - - if (track.beta() > 1) - continue; - - histos.fill(HIST("hdEdx_afterselection1"), track.p(), track.tpcSignal()); - histos.fill(HIST("hTOFbeta_afterselection1"), track.p(), track.beta()); - } - - if ((track.pt() >= 0.65 && track.pt() < 2.0) && (abs(track.rapidity(massKa)) < 0.5) && track.hasTPC() && track.hasTOF() && (std::abs(track.tofNSigmaPi()) > 2.0 && std::abs(track.tofNSigmaPr()) > 2.0) && (abs(sqrt(track.tpcNSigmaKa()) * (track.tpcNSigmaKa()) + (track.tofNSigmaKa()) * (track.tofNSigmaKa())) < 2.)) { - - histos.fill(HIST("hPtKaon"), track.pt()); - histos.fill(HIST("hEtaKaon"), track.eta()); - histos.fill(HIST("hyKaon"), track.rapidity(massKa)); - histos.fill(HIST("hPtyKaon"), track.pt(), track.rapidity(massKa)); - - nChk += 1.; - Q1k += track.pt(); - Q2k += (track.pt() * track.pt()); - - if (track.beta() > 1) - continue; - - histos.fill(HIST("hdEdx_afterselection1"), track.p(), track.tpcSignal()); - histos.fill(HIST("hTOFbeta_afterselection1"), track.p(), track.beta()); - } - - //============================proton=========================================================== - - if ((track.hasTPC() && abs(track.tpcNSigmaPr()) < 2.) && (track.hasTOF() && abs(track.tofNSigmaPr()) < 2.)) { - histos.fill(HIST("NSigamaTPCTOFproton"), track.tpcNSigmaPr(), track.tofNSigmaPr()); - - histos.fill(HIST("hdEdx_afterselection"), track.p(), track.tpcSignal()); - histos.fill(HIST("hTOFbeta_afterselection"), track.p(), track.beta()); - } - - if (track.hasTPC() && abs(track.tpcNSigmaPr()) < 2. && (track.pt() >= 0.4 && track.pt() < 0.85) && (abs(track.rapidity(massPr)) < 0.5) && (std::abs(track.tpcNSigmaEl()) > 1.0 && std::abs(track.tpcNSigmaKa()) > 2.0 && std::abs(track.tpcNSigmaPi()) > 2.0)) { - - histos.fill(HIST("hPtProton"), track.pt()); - histos.fill(HIST("hEtaProton"), track.eta()); - histos.fill(HIST("hyProton"), track.rapidity(massPr)); - histos.fill(HIST("hPtyProton"), track.pt(), track.rapidity(massPr)); - - nChp += 1.; - Q1p += track.pt(); - Q2p += (track.pt() * track.pt()); - - if (track.beta() > 1) - continue; - - histos.fill(HIST("hdEdx_afterselection1"), track.p(), track.tpcSignal()); - histos.fill(HIST("hTOFbeta_afterselection1"), track.p(), track.beta()); - } - - if ((track.pt() >= 0.85 && track.pt() < 2.0) && (abs(track.rapidity(massPr)) < 0.5) && track.hasTPC() && track.hasTOF() && (std::abs(track.tofNSigmaKa()) > 2.0 && std::abs(track.tofNSigmaPi()) > 2.0) && (abs(sqrt(track.tpcNSigmaPr()) * (track.tpcNSigmaPr()) + (track.tofNSigmaPr()) * (track.tofNSigmaPr())) < 2.)) { - - histos.fill(HIST("hPtProton"), track.pt()); - histos.fill(HIST("hEtaProton"), track.eta()); - histos.fill(HIST("hyProton"), track.rapidity(massPr)); - histos.fill(HIST("hPtyProton"), track.pt(), track.rapidity(massPr)); - - nChp += 1.; - Q1p += track.pt(); - Q2p += (track.pt() * track.pt()); - - if (track.beta() > 1) - continue; - - histos.fill(HIST("hdEdx_afterselection1"), track.p(), track.tpcSignal()); - histos.fill(HIST("hTOFbeta_afterselection1"), track.p(), track.beta()); - } - - //==================================================================================================== - } - // Track loop ends! - - if (nCh < 2) - return; - - //------------------ all charges------------------------------------- - var1 = (Q1 * Q1 - Q2) / (nCh * (nCh - 1)); - histos.fill(HIST("hVar1"), sample, cent, var1); - var2 = (Q1 / nCh); - histos.fill(HIST("hVar2"), sample, cent, var2); - histos.fill(HIST("hVarc"), sample, cent); - histos.fill(HIST("hVar2meanpt"), cent, var2); - - twopar_allcharge = (var1 - var2); - histos.fill(HIST("hVar"), nCh, twopar_allcharge); - - //---------------------- pions ---------------------------------------- - - if (nChpi > 2) { - var1pi = (Q1pi * Q1pi - Q2pi) / (nChpi * (nChpi - 1)); - var2pi = (Q1pi / nChpi); - } - - //----------------------- kaons --------------------------------------- - if (nChk > 2) { - var1k = (Q1k * Q1k - Q2k) / (nChk * (nChk - 1)); - var2k = (Q1k / nChk); - } - - //---------------------------- protons ---------------------------------- - if (nChp > 2) { - var1p = (Q1p * Q1p - Q2p) / (nChp * (nChp - 1)); - var2p = (Q1p / nChp); - } - - //========================centrality========================================== - - histos.fill(HIST("hVar1pi"), sample, cent, var1pi); - histos.fill(HIST("hVar2pi"), sample, cent, var2pi); - histos.fill(HIST("hVar2meanptpi"), cent, var2pi); - - histos.fill(HIST("hVar1k"), sample, cent, var1k); - histos.fill(HIST("hVar2k"), sample, cent, var2k); - histos.fill(HIST("hVar2meanptk"), cent, var2k); - - histos.fill(HIST("hVar1p"), sample, cent, var1p); - histos.fill(HIST("hVar2p"), sample, cent, var2p); - histos.fill(HIST("hVar2meanptp"), cent, var2p); - - //-----------------------nch------------------------------------- - histos.fill(HIST("hVar1x"), sample, nCh, var1); - histos.fill(HIST("hVar2x"), sample, nCh, var2); - histos.fill(HIST("hVarx"), sample, nCh); - histos.fill(HIST("hVar2meanptx"), nCh, var2); - - histos.fill(HIST("hVar1pix"), sample, nCh, var1pi); - histos.fill(HIST("hVar2pix"), sample, nCh, var2pi); - histos.fill(HIST("hVarpix"), sample, nChpi); - histos.fill(HIST("hVar2meanptpix"), nCh, var2pi); - - histos.fill(HIST("hVar1kx"), sample, nCh, var1k); - histos.fill(HIST("hVar2kx"), sample, nCh, var2k); - histos.fill(HIST("hVarkx"), sample, nChk); - histos.fill(HIST("hVar2meanptkx"), nCh, var2k); - - histos.fill(HIST("hVar1px"), sample, nCh, var1p); - histos.fill(HIST("hVar2px"), sample, nCh, var2p); - histos.fill(HIST("hVarpx"), sample, nChp); - histos.fill(HIST("hVar2meanptpx"), nCh, var2p); - - } // event loop ends! - - PROCESS_SWITCH(IdentifiedMeanPtFluctuations, process, "process real data information", true); -}; - -WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) -{ - WorkflowSpec workflow{adaptAnalysisTask(cfgc)}; - return workflow; -} diff --git a/PWGCF/EbyEFluctuations/Tasks/eventMeanPtId.cxx b/PWGCF/EbyEFluctuations/Tasks/eventMeanPtId.cxx new file mode 100644 index 00000000000..182876d39d1 --- /dev/null +++ b/PWGCF/EbyEFluctuations/Tasks/eventMeanPtId.cxx @@ -0,0 +1,1382 @@ +// 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 eventMeanPtId.cxx +/// \brief Analysis task to study Mean pT Fluctuations using two particle correlator using Cumulant Method +/// \author Sweta Singh (sweta.singh@cern.ch) + +#include "PWGCF/Core/CorrelationContainer.h" +#include "PWGCF/Core/PairCuts.h" + +#include "Common/CCDB/EventSelectionParams.h" +#include "Common/CCDB/TriggerAliases.h" +#include "Common/Core/TrackSelection.h" +#include "Common/Core/trackUtilities.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/FT0Corrected.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include "CCDB/BasicCCDBManager.h" +#include "CommonConstants/MathConstants.h" +#include "CommonConstants/PhysicsConstants.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/O2DatabasePDGPlugin.h" +#include "Framework/RunningWorkflowInfo.h" +#include "Framework/runDataProcessing.h" + +#include + +#include +#include +#include +#include + +double massPi = o2::constants::physics::MassPionCharged; +double massKa = o2::constants::physics::MassKaonCharged; +double massPr = o2::constants::physics::MassProton; + +using namespace o2::constants::physics; +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace std; +using o2::constants::physics::Pdg; + +namespace o2::aod +{ +using MyCollisions = soa::Join; +using MyTracks = soa::Join; + +using MyMCRecoCollisions = soa::Join; +using MyMCRecoCollision = MyMCRecoCollisions::iterator; + +using MyMCRecoTracks = soa::Join; +using MyMCRecoTrack = MyMCRecoTracks::iterator; + +using EventCandidatesMC = soa::Join; +using MyCollision = MyCollisions::iterator; +using MyTrack = MyTracks::iterator; +} // namespace o2::aod + +struct EventMeanPtId { + Service ccdb; + Service pdg; + + 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 cfgUrlCCDB{"cfgUrlCCDB", "http://alice-ccdb.cern.ch", "url of ccdb"}; + Configurable cfgPathCCDB{"cfgPathCCDB", "Users/s/swsingh/My/Object/eff_Pb", "Path for ccdb-object"}; + Configurable cfgLoadEff{"cfgLoadEff", true, "Load efficiency"}; + + HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + TH1D* ptHistogramAllchargeRec = nullptr; + TH1D* ptHistogramPionrec = nullptr; + TH1D* ptHistogramKaonrec = nullptr; + TH1D* ptHistogramProtonrec = nullptr; + TH1D* hRecoPi = nullptr; + TH1D* hRecoKa = nullptr; + TH1D* hRecoPr = nullptr; + TH2D* hPtyPion = nullptr; + TH2D* hPtyKaon = nullptr; + TH2D* hPtyProton = nullptr; + + Configurable ptMax{"ptMax", 2.0, "maximum pT"}; + Configurable ptMin{"ptMin", 0.15, "minimum pT"}; + Configurable> ptBins{"ptBins", {0.15, 0.20, 0.25, 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.05, 1.10, 1.15, 1.20, 1.25, 1.30, 1.35, 1.40, 1.45, 1.50, 1.55, 1.60, 1.65, 1.70, 1.75, 1.80, 1.85, 1.90, 1.95, 2.00}, "p_{T} bins"}; + Configurable piluprejection{"piluprejection", false, "Pileup rejection"}; + + void init(o2::framework::InitContext&) + { + if (cfgLoadEff) { + // Set CCDB url + ccdb->setURL(cfgUrlCCDB.value); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + // ccdb->setCreatedNotAfter(ccdbNoLaterThan.value); + // LOGF(info, "Getting object %s", ccdbPath.value.data()); + + TList* lst = ccdb->getForTimeStamp(cfgPathCCDB.value, -1); + ptHistogramAllchargeRec = reinterpret_cast(lst->FindObject("ptHistogramAllchargeRec")); + ptHistogramPionrec = reinterpret_cast(lst->FindObject("ptHistogramPionrec")); + ptHistogramKaonrec = reinterpret_cast(lst->FindObject("ptHistogramKaonrec")); + ptHistogramProtonrec = reinterpret_cast(lst->FindObject("ptHistogramProtonrec")); + hRecoPi = reinterpret_cast(lst->FindObject("hRecoPi")); + hRecoKa = reinterpret_cast(lst->FindObject("hRecoKa")); + hRecoPr = reinterpret_cast(lst->FindObject("hRecoPr")); + hPtyPion = reinterpret_cast(lst->FindObject("hPtyPion")); + hPtyKaon = reinterpret_cast(lst->FindObject("hPtyKaon")); + hPtyProton = reinterpret_cast(lst->FindObject("hPtyProton")); + + if (!ptHistogramAllchargeRec || !ptHistogramPionrec || !ptHistogramKaonrec || !ptHistogramProtonrec || !hRecoPi || !hRecoKa || !hRecoPr || !hPtyPion || !hPtyKaon || !hPtyProton) { + LOGF(info, "FATAL!! Could not find required histograms in CCDB"); + } + } + + 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}; + // AxisSpec ptAxis = {ptBinning, "#it{p}_{T} (GeV/#it{c})"}; + AxisSpec vtxZAxis = {100, -20.0, 20.0, "Z (cm)"}; + AxisSpec dcaAxis = {1002, -5.01, 5.01, "DCA_{xy} (cm)"}; + AxisSpec dcazAxis = {1002, -5.01, 5.01, "DCA_{z} (cm)"}; + AxisSpec ptAxis = {600, 0.0, 6.0, "#it{p}_{T} (GeV/#it{c})"}; + AxisSpec pAxis = {400, 0.0, 4.0, "#it{p} (GeV/#it{c})"}; + AxisSpec betaAxis = {200, 0.0, 2.0, "TOF_{#beta} (GeV/#it{c})"}; + AxisSpec dEdxAxis = {2000, 0.0, 200.0, "dE/dx (GeV/#it{c})"}; + AxisSpec etaAxis = {300, -1.5, 1.5, "#eta"}; // 300, -1.5, 1.5 + AxisSpec nSigmaTPCAxis = {170, -8.5, 8.5, "n#sigma_{TPC}^{proton}"}; + AxisSpec nSigmaTPCAxispid = {170, -8.5, 8.5, "n#sigma_{TPC}"}; + AxisSpec nSigmaTOFAxispid = {170, -8.5, 8.5, "n#sigma_{TOF}"}; + AxisSpec centAxis = {100, 0., 100., "centrality"}; + AxisSpec subAxis = {30, 0., 30., "sample"}; + AxisSpec nchAxis = {4000, 0., 4000., "nch"}; + AxisSpec varAxis1 = {400, 0., 4., "var1"}; + AxisSpec varAxis2 = {400, 0., 4., "var2"}; + AxisSpec chi2Axis = {100, 0., 100., "Chi2"}; + AxisSpec crossedRowTpcAxis = {600, 0., 600., "TPC Crossed rows"}; + AxisSpec counter = {10, 0., 10., "events"}; + + // QA Plots + histos.add("hEventcounter", "event counts", kTH1D, {counter}); + auto h = histos.add("tracksel", "tracksel", HistType::kTH1D, {{10, 0.5, 10.5}}); + h->GetXaxis()->SetBinLabel(1, "Tracks read"); + h->GetXaxis()->SetBinLabel(2, "Global track passed"); + h->GetXaxis()->SetBinLabel(3, "DCAxy passed"); + h->GetXaxis()->SetBinLabel(4, "DCAz passed"); + h->GetXaxis()->SetBinLabel(5, "Eta-cut passed"); + h->GetXaxis()->SetBinLabel(6, "pT-cut passed"); + h->GetXaxis()->SetBinLabel(7, "TPC crossed rows passed"); + h->GetXaxis()->SetBinLabel(8, "TPC Chai2cluster passed"); + h->GetXaxis()->SetBinLabel(9, "ITS Chai2cluster passed"); + + histos.add("hEventcounter_recMC", "event counts rec MC", kTH1D, {counter}); + auto hRec = histos.add("trackSelRec", "trackSelRec", HistType::kTH1D, {{10, 0.5, 10.5}}); + hRec->GetXaxis()->SetBinLabel(1, "has_mcCollision() read"); + hRec->GetXaxis()->SetBinLabel(2, "Vertex Z > 10cm passed"); + hRec->GetXaxis()->SetBinLabel(3, "sel 8 passed"); + hRec->GetXaxis()->SetBinLabel(4, "kNoSameBunchPileup passed"); + hRec->GetXaxis()->SetBinLabel(5, "kNoITSROFrameBorder passed"); + hRec->GetXaxis()->SetBinLabel(6, "klsGoodZvtxFT0vsPV passed"); + hRec->GetXaxis()->SetBinLabel(7, "klsVertexITSTPC passed"); + + histos.add("Data/hZvtx_before_sel", "hZvtx_before_sel", kTH1D, {vtxZAxis}); + histos.add("Data/hZvtx_after_sel", "hZvtx_after_sel", kTH1D, {vtxZAxis}); + histos.add("Data/hZvtx_after_sel8", "hZvtx_after_sel8", kTH1D, {vtxZAxis}); + histos.add("Data/hP", "hP", kTH1D, {pAxis}); + histos.add("Data/hEta", ";hEta", kTH1D, {etaAxis}); + histos.add("Data/hPt", ";#it{p}_{T} (GeV/#it{c})", kTH1D, {ptAxis}); + histos.add("Data/hNsigmaTPC", "hNsigmaTPC", kTH2D, {pAxis, nSigmaTPCAxis}); + histos.add("Data/hDCAxy", "hDCAxy", kTH1D, {dcaAxis}); + histos.add("Data/hDCAz", "hDCAz", kTH1D, {dcazAxis}); + histos.add("Data/hPtDCAxy", "hPtDCAxy", kTH2D, {ptAxis, dcaAxis}); + histos.add("Data/hPtDCAz", "hPtDCAz", kTH2D, {ptAxis, dcazAxis}); + histos.add("Data/NSigamaTPCpion", "NSigamaTPCpion", kTH2D, {ptAxis, nSigmaTPCAxispid}); + histos.add("Data/NSigamaTPCkaon", "NSigamaTPCkaon", kTH2D, {ptAxis, nSigmaTPCAxispid}); + histos.add("Data/NSigamaTPCproton", "NSigamaTPCproton", kTH2D, {ptAxis, nSigmaTPCAxispid}); + histos.add("Data/NSigamaTOFpion", "NSigamaTOFpion", kTH2D, {ptAxis, nSigmaTOFAxispid}); + histos.add("Data/NSigamaTOFkaon", "NSigamaTOFkaon", kTH2D, {ptAxis, nSigmaTOFAxispid}); + histos.add("Data/NSigamaTOFproton", "NSigamaTOFproton", kTH2D, {ptAxis, nSigmaTOFAxispid}); + histos.add("Data/NSigamaTPCTOFpion", "NSigamaTPCTOFpion", kTH2D, {nSigmaTPCAxispid, nSigmaTOFAxispid}); + histos.add("Data/NSigamaTPCTOFkaon", "NSigamaTPCTOFkaon", kTH2D, {nSigmaTPCAxispid, nSigmaTOFAxispid}); + histos.add("Data/NSigamaTPCTOFproton", "NSigamaTPCTOFproton", kTH2D, {nSigmaTPCAxispid, nSigmaTOFAxispid}); + histos.add("Data/hPtPion", ";#it{p}_{T} (GeV/#it{c})", kTH1D, {ptAxis}); + histos.add("Data/hPtKaon", ";#it{p}_{T} (GeV/#it{c})", kTH1D, {ptAxis}); + histos.add("Data/hPtProton", ";#it{p}_{T} (GeV/#it{c})", kTH1D, {ptAxis}); + histos.add("Data/hEtaPion", ";hEta", kTH1D, {etaAxis}); + histos.add("Data/hEtaKaon", ";hEta", kTH1D, {etaAxis}); + histos.add("Data/hEtaProton", ";hEta", kTH1D, {etaAxis}); + histos.add("Data/hyPion", ";hyPion", kTH1D, {etaAxis}); + histos.add("Data/hyKaon", ";hyKaon", kTH1D, {etaAxis}); + histos.add("Data/hyProton", ";hyProton", kTH1D, {etaAxis}); + histos.add("Data/hPtCh", "hPtCh", kTH2D, {nchAxis, ptAxis}); + histos.add("Data/hPtChPion", "hPtChPion", kTH2D, {nchAxis, ptAxis}); + histos.add("Data/hPtChKaon", "hPtChKaon", kTH2D, {nchAxis, ptAxis}); + histos.add("Data/hPtChProton", "hPtChProton", kTH2D, {nchAxis, ptAxis}); + histos.add("Data/hPtCent", "hPtCent", kTH2D, {centAxis, ptAxis}); + histos.add("Data/hPtCentPion", "hPtCentPion", kTH2D, {centAxis, ptAxis}); + histos.add("Data/hPtCentKaon", "hPtCentKaon", kTH2D, {centAxis, ptAxis}); + histos.add("Data/hPtCentProton", "hPtCentProton", kTH2D, {centAxis, ptAxis}); + histos.add("Data/hMeanPtCh", "hMeanPtCh", kTH2D, {nchAxis, ptAxis}); + histos.add("Data/hCent", "hCent", kTH2D, {nchAxis, centAxis}); + + histos.add("Data/hVar1", "hVar1", kTH2D, {subAxis, centAxis}); + histos.add("Data/hVar2", "hVar2", kTH2D, {subAxis, centAxis}); + histos.add("Data/hVar2meanpt", "hVar2meanpt", kTH2D, {centAxis, varAxis2}); + histos.add("Data/hVar", "hVar", kTH2D, {subAxis, centAxis}); + histos.add("Data/hVarc", "hVarc", kTH2D, {subAxis, centAxis}); + histos.add("Data/hVar1pi", "hVar1pi", kTH2D, {subAxis, centAxis}); + histos.add("Data/hVar2pi", "hVar2pi", kTH2D, {subAxis, centAxis}); + histos.add("Data/hVarpi", "hVarpi", kTH2D, {subAxis, centAxis}); + histos.add("Data/hVar2meanptpi", "hVar2meanptpi", kTH2D, {centAxis, varAxis2}); + histos.add("Data/hVar1k", "hVar1k", kTH2D, {subAxis, centAxis}); + histos.add("Data/hVar2k", "hVar2k", kTH2D, {subAxis, centAxis}); + histos.add("Data/hVark", "hVark", kTH2D, {subAxis, centAxis}); + histos.add("Data/hVar2meanptk", "hVar2meanptk", kTH2D, {centAxis, varAxis2}); + histos.add("Data/hVar1p", "hVar1p", kTH2D, {subAxis, centAxis}); + histos.add("Data/hVar2p", "hVar2p", kTH2D, {subAxis, centAxis}); + histos.add("Data/hVarp", "hVarp", kTH2D, {subAxis, centAxis}); + histos.add("Data/hVar2meanptp", "hVar2meanptp", kTH2D, {centAxis, varAxis2}); + + histos.add("Data/hnchAll", ";hnchAll", kTH1D, {nchAxis}); + histos.add("Data/hnchAll_bf_cut", ";hnchAll_bf_cut", kTH1D, {nchAxis}); + histos.add("Data/hnch", ";hnch", kTH1D, {nchAxis}); + histos.add("Data/hnchTrue", ";hnchTrue", kTH1D, {nchAxis}); + histos.add("Data/hnchTrue_pt", ";hnchTrue_pt", kTH1D, {nchAxis}); + + histos.add("Data/hVar1x", "hVar1x", kTH2D, {subAxis, nchAxis}); + histos.add("Data/hVar2x", "hVar2x", kTH2D, {subAxis, nchAxis}); + histos.add("Data/hVarx", "hVarx", kTH2D, {subAxis, nchAxis}); + histos.add("Data/hVar2meanptx", "hVar2meanptx", kTH2D, {nchAxis, varAxis2}); + histos.add("Data/hVar1pix", "hVar1pix", kTH2D, {subAxis, nchAxis}); + histos.add("Data/hVar2pix", "hVar2pix", kTH2D, {subAxis, nchAxis}); + histos.add("Data/hVarpix", "hVarpix", kTH2D, {subAxis, nchAxis}); + histos.add("Data/hVar2meanptpix", "hVar2meanptpix", kTH2D, {nchAxis, varAxis2}); + histos.add("Data/hVar1kx", "hVar1kx", kTH2D, {subAxis, nchAxis}); + histos.add("Data/hVar2kx", "hVar2kx", kTH2D, {subAxis, nchAxis}); + histos.add("Data/hVarkx", "hVarkx", kTH2D, {subAxis, nchAxis}); + histos.add("Data/hVar2meanptkx", "hVar2meanptkx", kTH2D, {nchAxis, varAxis2}); + histos.add("Data/hVar1px", "hVar1px", kTH2D, {subAxis, nchAxis}); + histos.add("Data/hVar2px", "hVar2px", kTH2D, {subAxis, nchAxis}); + histos.add("Data/hVarpx", "hVarpx", kTH2D, {subAxis, nchAxis}); + histos.add("Data/hVar2meanptpx", "hVar2meanptpx", kTH2D, {nchAxis, varAxis2}); + histos.add("Data/ht", "ht", kTH1D, {centAxis}); + histos.add("Data/hCentrality", "hCentrality", kTH1D, {centAxis}); + histos.add("Data/hPEta", "hPEta", kTH2D, {pAxis, etaAxis}); + histos.add("Data/hPtEta", "hPtEta", kTH2D, {ptAxis, etaAxis}); + histos.add("Data/hPy", "hPy", kTH2D, {pAxis, etaAxis}); + histos.add("Data/hPty", "hPty", kTH2D, {ptAxis, etaAxis}); + histos.add("Data/hPtyPion", "hPtyPion", kTH2D, {ptAxis, etaAxis}); + histos.add("Data/hPtyKaon", "hPtyKaon", kTH2D, {ptAxis, etaAxis}); + histos.add("Data/hPtyProton", "hPtyProton", kTH2D, {ptAxis, etaAxis}); + histos.add("Data/hTOFbeta", "hTOFbeta", kTH2D, {pAxis, betaAxis}); + histos.add("Data/hdEdx", "hdEdx", kTH2D, {pAxis, dEdxAxis}); + histos.add("Data/hTOFbeta_afterselection", "hTOFbeta_afterselection", kTH2D, {pAxis, betaAxis}); + histos.add("Data/hdEdx_afterselection", "hdEdx_afterselection", kTH2D, {pAxis, dEdxAxis}); + histos.add("Data/hTOFbeta_afterselection1", "hTOFbeta_afterselection1", kTH2D, {pAxis, betaAxis}); + histos.add("Data/hdEdx_afterselection1", "hdEdx_afterselection1", kTH2D, {pAxis, dEdxAxis}); + histos.add("Data/hTPCchi2perCluster_before", "TPC #Chi^{2}/Cluster", kTH1D, {chi2Axis}); + histos.add("Data/hITSchi2perCluster_before", "ITS #Chi^{2}/Cluster", kTH1D, {chi2Axis}); + histos.add("Data/hTPCCrossedrows_before", "Crossed TPC rows", kTH1D, {crossedRowTpcAxis}); + histos.add("Data/hTPCchi2perCluster_after", "TPC #Chi^{2}/Cluster", kTH1D, {chi2Axis}); + histos.add("Data/hITSchi2perCluster_after", "ITS #Chi^{2}/Cluster", kTH1D, {chi2Axis}); + histos.add("Data/hTPCCrossedrows_after", "Crossed TPC rows", kTH1D, {crossedRowTpcAxis}); + histos.add("Data/hdEdx_rec_bf_anycut", "hdEdx_rec_bf_anycut", kTH2D, {pAxis, dEdxAxis}); + histos.add("Data/hcent_nacc", "hcent_nacc", kTH2D, {centAxis, nchAxis}); + + histos.addClone("Data/", "Rec/"); + // rec histograms + histos.add("NSigamaTPCpion_rec", "NSigamaTPCpion_rec", kTH2D, {pAxis, nSigmaTPCAxispid}); + histos.add("NSigamaTPCkaon_rec", "NSigamaTPCkaon_rec", kTH2D, {pAxis, nSigmaTPCAxispid}); + histos.add("NSigamaTPCproton_rec", "NSigamaTPCproton_rec", kTH2D, {pAxis, nSigmaTPCAxispid}); + histos.add("NSigamaTOFpion_rec", "NSigamaTOFpion_rec", kTH2D, {pAxis, nSigmaTOFAxispid}); + histos.add("NSigamaTOFkaon_rec", "NSigamaTOFkaon_rec", kTH2D, {pAxis, nSigmaTOFAxispid}); + histos.add("NSigamaTOFproton_rec", "NSigamaTOFproton_rec", kTH2D, {pAxis, nSigmaTOFAxispid}); + histos.add("NSigamaTPCTOFpion_rec", "NSigamaTPCTOFpion_rec", kTH2D, {nSigmaTPCAxispid, nSigmaTOFAxispid}); + histos.add("NSigamaTPCTOFkaon_rec", "NSigamaTPCTOFkaon_rec", kTH2D, {nSigmaTPCAxispid, nSigmaTOFAxispid}); + histos.add("NSigamaTPCTOFproton_rec", "NSigamaTPCTOFproton_rec", kTH2D, {nSigmaTPCAxispid, nSigmaTOFAxispid}); + histos.add("NSigamaTPCpion_rec_bf_sel", "NSigamaTPCpion_rec_bf_sel", kTH2D, {pAxis, nSigmaTPCAxispid}); + histos.add("NSigamaTPCkaon_rec_bf_sel", "NSigamaTPCkaon_rec_bf_sel", kTH2D, {pAxis, nSigmaTPCAxispid}); + histos.add("NSigamaTPCproton_rec_bf_sel", "NSigamaTPCproton_rec_bf_sel", kTH2D, {pAxis, nSigmaTPCAxispid}); + histos.add("NSigamaTOFpion_rec_bf_sel", "NSigamaTOFpion_rec_bf_sel", kTH2D, {pAxis, nSigmaTOFAxispid}); + histos.add("NSigamaTOFkaon_rec_bf_sel", "NSigamaTOFkaon_rec_bf_sel", kTH2D, {pAxis, nSigmaTOFAxispid}); + histos.add("NSigamaTOFproton_rec_bf_sel", "NSigamaTOFproton_rec_bf_sel", kTH2D, {pAxis, nSigmaTOFAxispid}); + histos.add("NSigamaTPCTOFpion_rec_bf_sel", "NSigamaTPCTOFpion_rec_bf_sel", kTH2D, {nSigmaTPCAxispid, nSigmaTOFAxispid}); + histos.add("NSigamaTPCTOFkaon_rec_bf_sel", "NSigamaTPCTOFkaon_rec_bf_sel", kTH2D, {nSigmaTPCAxispid, nSigmaTOFAxispid}); + histos.add("NSigamaTPCTOFproton_rec_bf_sel", "NSigamaTPCTOFproton_rec_bf_sel", kTH2D, {nSigmaTPCAxispid, nSigmaTOFAxispid}); + histos.add("hPtyPion_rec", "hPtyPion_rec", kTH2D, {ptAxis, etaAxis}); + histos.add("hPtyKaon_rec", "hPtyKaon_rec", kTH2D, {ptAxis, etaAxis}); + histos.add("hPtyProton_rec", "hPtyProton_rec", kTH2D, {ptAxis, etaAxis}); + histos.add("hPyPion_rec", "hPyPion_rec", kTH2D, {pAxis, etaAxis}); + histos.add("hPyKaon_rec", "hPyKaon_rec", kTH2D, {pAxis, etaAxis}); + histos.add("hPyProton_rec", "hPyProton_rec", kTH2D, {pAxis, etaAxis}); + histos.add("hTOFbeta_afterselection_rec_afterpidcut", "hTOFbeta_afterselection_rec_afterpidcut", kTH2D, {pAxis, betaAxis}); + histos.add("hdEdx_afterselection_rec_afterpidcut", "hdEdx_afterselection_rec_afterpidcut", kTH2D, {pAxis, dEdxAxis}); + histos.add("hTOFbeta_afterselection_rec_beforepidcut", "hTOFbeta_afterselection_rec_beforepidcut", kTH2D, {pAxis, betaAxis}); + histos.add("hdEdx_afterselection_rec_beforepidcut", "hdEdx_afterselection_rec_beforepidcut", kTH2D, {pAxis, dEdxAxis}); + + histos.add("heffVar1x", "heffVar1x", kTH2D, {subAxis, nchAxis}); + histos.add("heffVar2x", "heffVar2x", kTH2D, {subAxis, nchAxis}); + histos.add("heffVarx", "heffVarx", kTH2D, {subAxis, nchAxis}); + histos.add("heffVar2meanptx", "heffVar2meanptx", kTH2D, {nchAxis, varAxis2}); + histos.add("hnchRec_all", ";hnchRec_all", kTH1D, {nchAxis}); + histos.add("hnchRec", ";hnchRec", kTH1D, {nchAxis}); + histos.add("hnchRec_true", ";hnchRec_true", kTH1D, {nchAxis}); + histos.add("hVar1x_rec_old", "hVar1x_rec_old", kTH2D, {subAxis, nchAxis}); + histos.add("hVar2x_rec_old", "hVar2x_rec_old", kTH2D, {subAxis, nchAxis}); + histos.add("hVarx_rec_old", "hVarx_rec_old", kTH2D, {subAxis, nchAxis}); + histos.add("hVar1x_rec", "hVar1x_rec", kTH2D, {subAxis, nchAxis}); + histos.add("hVar2x_rec", "hVar2x_rec", kTH2D, {subAxis, nchAxis}); + histos.add("hVarx_rec", "hVarx_rec", kTH2D, {subAxis, nchAxis}); + histos.add("hVar2meanptx_rec", "hVar2meanptx_rec", kTH2D, {nchAxis, varAxis2}); + histos.add("hVar1pix_rec", "hVar1pix_rec", kTH2D, {subAxis, nchAxis}); + histos.add("hVar2pix_rec", "hVar2pix_rec", kTH2D, {subAxis, nchAxis}); + histos.add("hVarpix_rec", "hVarpix_rec", kTH2D, {subAxis, nchAxis}); + histos.add("hVar2meanptpix_rec", "hVar2meanptpix_rec", kTH2D, {nchAxis, varAxis2}); + histos.add("hVar1kx_rec", "hVar1kx_rec", kTH2D, {subAxis, nchAxis}); + histos.add("hVar2kx_rec", "hVar2kx_rec", kTH2D, {subAxis, nchAxis}); + histos.add("hVarkx_rec", "hVarkx_rec", kTH2D, {subAxis, nchAxis}); + histos.add("hVar2meanptkx_rec", "hVar2meanptkx_rec", kTH2D, {nchAxis, varAxis2}); + histos.add("hVar1px_rec", "hVar1px_rec", kTH2D, {subAxis, nchAxis}); + histos.add("hVar2px_rec", "hVar2px_rec", kTH2D, {subAxis, nchAxis}); + histos.add("hVarpx_rec", "hVarpx_rec", kTH2D, {subAxis, nchAxis}); + histos.add("hVar2meanptpx_rec", "hVar2meanptpx_rec", kTH2D, {nchAxis, varAxis2}); + histos.add("hZvtx_after_sel_rec", "hZvtx_after_sel_rec", kTH1D, {vtxZAxis}); + histos.add("hZvtx_after_sel8_rec", "hZvtx_after_sel8_rec", kTH1D, {vtxZAxis}); + histos.add("etaHistogram_allcharge_rec", "etaHistogram_allcharge_rec", kTH1D, {etaAxis}); + histos.add("ptHistogram_allcharge_bfptcut_rec", "ptHistogram_allcharge_bfptcut_rec", kTH1D, {ptAxis}); + histos.add("ptHistogramAllchargeRec", "ptHistogramAllchargeRec", kTH1D, {ptAxis}); + histos.add("ptHistogramPionrec", "ptHistogramPionrec", kTH1D, {ptAxis}); + histos.add("ptHistogramKaonrec", "ptHistogramKaonrec", kTH1D, {ptAxis}); + histos.add("ptHistogramProtonrec", "ptHistogramProtonrec", kTH1D, {ptAxis}); + histos.add("ptHistogramPionrec_purity", "ptHistogramPionrec_purity", kTH1D, {ptAxis}); + histos.add("ptHistogramKaonrec_purity", "ptHistogramKaonrec_purity", kTH1D, {ptAxis}); + histos.add("ptHistogramProtonrec_purity", "ptHistogramProtonrec_purity", kTH1D, {ptAxis}); + histos.add("ptHistogramPionrec_pdg", "ptHistogramPionrec_pdg", kTH1D, {ptAxis}); + histos.add("ptHistogramKaonrec_pdg", "ptHistogramKaonrec_pdg", kTH1D, {ptAxis}); + histos.add("ptHistogramProtonrec_pdg", "ptHistogramProtonrec_pdg", kTH1D, {ptAxis}); + histos.add("Histogram_mass2_p_rec_beforesel", "Histogram_mass2_p_rec_beforesel", kTH1D, {ptAxis}); + histos.add("Histogram_mass2_p_rec_aftersel", "Histogram_mass2_p_rec_aftersel", kTH1D, {ptAxis}); + histos.add("hEffVar1x", "hEffVar1x", kTH2D, {subAxis, nchAxis}); + histos.add("hEffVar2x", "hEffVar2x", kTH2D, {subAxis, nchAxis}); + histos.add("hEffVarx", "hEffVarx", kTH2D, {subAxis, nchAxis}); + histos.add("hEffVar1pix", "hEffVar1pix", kTH2D, {subAxis, nchAxis}); + histos.add("hEffVar2pix", "hEffVar2pix", kTH2D, {subAxis, nchAxis}); + histos.add("hEffVarpix", "hEffVarpix", kTH2D, {subAxis, nchAxis}); + histos.add("hEffVar1kx", "hEffVar1kx", kTH2D, {subAxis, nchAxis}); + histos.add("hEffVar2kx", "hEffVar2kx", kTH2D, {subAxis, nchAxis}); + histos.add("hEffVarkx", "hEffVarkx", kTH2D, {subAxis, nchAxis}); + histos.add("hEffVar1px", "hEffVar1px", kTH2D, {subAxis, nchAxis}); + histos.add("hEffVar2px", "hEffVar2px", kTH2D, {subAxis, nchAxis}); + histos.add("hEffVarpx", "hEffVarpx", kTH2D, {subAxis, nchAxis}); + histos.add("hEffVar2Meanptx", "hEffVar2Meanptx", kTH2D, {nchAxis, varAxis2}); + histos.add("hEffVar2Meanptpix", "hEffVar2Meanptpix", kTH2D, {nchAxis, varAxis2}); + histos.add("hEffVar2Meanptkx", "hEffVar2Meanptkx", kTH2D, {nchAxis, varAxis2}); + histos.add("hEffVar2Meanptpx", "hEffVar2Meanptpx", kTH2D, {nchAxis, varAxis2}); + //=======================MC histograms Generated ================================================ + histos.add("ptHistogram_allcharge_gen", "ptHistogram_allcharge_gen", kTH1D, {ptAxis}); + histos.add("ptHistogramPion", "ptHistogramPion", kTH1D, {ptAxis}); + histos.add("ptHistogramKaon", "ptHistogramKaon", kTH1D, {ptAxis}); + histos.add("ptHistogramProton", "ptHistogramProton", kTH1D, {ptAxis}); + histos.add("hMC_Pt", ";#it{p}_{T} (GeV/#it{c})", kTH1D, {ptAxis}); + histos.add("MC_hZvtx_after_sel", ";#it{p}_{T} (GeV/#it{c})", kTH1D, {vtxZAxis}); + histos.add("hTOFbeta_gen_pion", "hTOFbeta_gen_pion", kTH2D, {pAxis, betaAxis}); + histos.add("hdEdx_gen_pion", "hdEdx_gen_pion", kTH2D, {pAxis, dEdxAxis}); + histos.add("hnch_gen_all", ";hnch_gen_all", kTH1D, {nchAxis}); + histos.add("hnch_gen", ";hnch_gen", kTH1D, {nchAxis}); + histos.add("hnch_gen_true", ";hnch_gen_true", kTH1D, {nchAxis}); + histos.add("hnch_gen_eta", ";hnch_gen_eta", kTH1D, {etaAxis}); + histos.add("hnch1", ";hnch1", kTH1D, {nchAxis}); + histos.add("hnch2", ";hnch2", kTH1D, {nchAxis}); + histos.add("hnch3", ";hnch3", kTH1D, {nchAxis}); + histos.add("hnch_pi", ";hnch_pi", kTH1D, {nchAxis}); + histos.add("hnch_ka", ";hnch_ka", kTH1D, {nchAxis}); + histos.add("hnch_pr", ";hnch_pr", kTH1D, {nchAxis}); + + histos.add("hVar1x_gen_old", "hVar1x_gen_old", kTH2D, {subAxis, nchAxis}); + histos.add("hVar2x_gen_old", "hVar2x_gen_old", kTH2D, {subAxis, nchAxis}); + histos.add("hVarx_gen_old", "hVarx_gen_old", kTH2D, {subAxis, nchAxis}); + histos.add("hVar1x_gen", "hVar1x_gen", kTH2D, {subAxis, nchAxis}); + histos.add("hVar2x_gen", "hVar2x_gen", kTH2D, {subAxis, nchAxis}); + histos.add("hVarx_gen", "hVarx_gen", kTH2D, {subAxis, nchAxis}); + histos.add("hVar2meanptx_gen", "hVar2meanptx_gen", kTH2D, {nchAxis, varAxis2}); + histos.add("hVar1pix_gen", "hVar1pix_gen", kTH2D, {subAxis, nchAxis}); + histos.add("hVar2pix_gen", "hVar2pix_gen", kTH2D, {subAxis, nchAxis}); + histos.add("hVarpix_gen", "hVarpix_gen", kTH2D, {subAxis, nchAxis}); + histos.add("hVar2meanptpix_gen", "hVar2meanptpix_gen", kTH2D, {nchAxis, varAxis2}); + histos.add("hVar1kx_gen", "hVar1kx_gen", kTH2D, {subAxis, nchAxis}); + histos.add("hVar2kx_gen", "hVar2kx_gen", kTH2D, {subAxis, nchAxis}); + histos.add("hVarkx_gen", "hVarkx_gen", kTH2D, {subAxis, nchAxis}); + histos.add("hVar2meanptkx_gen", "hVar2meanptkx_gen", kTH2D, {nchAxis, varAxis2}); + histos.add("hVar1px_gen", "hVar1px_gen", kTH2D, {subAxis, nchAxis}); + histos.add("hVar2px_gen", "hVar2px_gen", kTH2D, {subAxis, nchAxis}); + histos.add("hVarpx_gen", "hVarpx_gen", kTH2D, {subAxis, nchAxis}); + histos.add("hVar2meanptpx_gen", "hVar2meanptpx_gen", kTH2D, {nchAxis, varAxis2}); + histos.add("hcent_nacc_rec", "hcent_nacc_rec", kTH2D, {centAxis, nchAxis}); + histos.add("hcent_nacc_gen", "hcent_nacc_gen", kTH2D, {centAxis, nchAxis}); + histos.add("hGenCentrality", "hGenCentrality", kTH1D, {centAxis}); + histos.add("hVtxZ_before_gen", "", kTH1F, {vtxZAxis}); + histos.add("hVtxZ_after_gen", "", kTH1F, {vtxZAxis}); + histos.add("hEta_gen", "", kTH1F, {etaAxis}); + histos.add("hEta_rec", "", kTH1F, {etaAxis}); + histos.add("hPt_gen", "", kTH1F, {ptAxis}); + histos.add("hPt_rec", "", kTH1F, {ptAxis}); + } + // Configurables + Configurable cVtxZcut{"cVtxZcut", 10.f, "Vertex Z"}; + Configurable cEtacut{"cEtacut", 0.8, "Eta cut"}; + Configurable cPtmincut{"cPtmincut", 0.2, "Pt min cut"}; + Configurable cPtmaxcut{"cPtmaxcut", 2.0, "Pt max cut"}; + Configurable cDcaXYcut{"cDcaXYcut", 0.12, "DCA XY cut"}; + Configurable cDcaZcut{"cDcaZcut", 0.3, "DCA Z cut"}; + Configurable cCentmincut{"cCentmincut", 0.0, "Min cent cut"}; + Configurable cCentmaxcut{"cCentmaxcut", 90.0, "Max cent cut"}; + Configurable cTPCcrosscut{"cTPCcrosscut", 70, "TPC crossrows cut"}; + Configurable cItsChiCut{"cItsChiCut", 70, "ITS chi2 cluster cut"}; + Configurable cTpcChiCut{"cTpcChiCut", 70, "TPC chi2 cluster cut"}; + + // Event selections + Configurable cSel8Trig{"cSel8Trig", true, "Sel8 (T0A + T0C) Selection Run3"}; + Configurable cTFBorder{"cTFBorder", true, "Timeframe Border Selection"}; + Configurable cNoItsROBorder{"cNoItsROBorder", true, "No ITSRO Border Cut"}; + Configurable cItsTpcVtx{"cItsTpcVtx", true, "ITS+TPC Vertex Selection"}; + Configurable cPileupReject{"cPileupReject", true, "Pileup rejection"}; + Configurable cZVtxTimeDiff{"cZVtxTimeDiff", true, "z-vtx time diff selection"}; + Configurable cIsGoodITSLayers{"cIsGoodITSLayers", true, "Good ITS Layers All"}; + Configurable cItslayerall{"cItslayerall", true, "dead staves of ITS removed"}; + Configurable cvtxtofmatched{"cvtxtofmatched", true, "TOF vertex matched"}; + Configurable cfgRejEl{"cfgRejEl", true, "Rejected electrons"}; + + // PID selection configurables + Configurable cPionPmincut{"cPionPmincut", 0.2, "pion min cut of pion"}; + Configurable cKaonPmincut{"cKaonPmincut", 0.2, "kaon min cut of kaon"}; + Configurable cProtonPmincut{"cProtonPmincut", 0.2, "proton min cut of proton"}; + Configurable cPionPmaxcut{"cPionPmaxcut", 2.0, "pion min cut of pion"}; + Configurable cKaonPmaxcut{"cKaonPmaxcut", 2.0, "kaon min cut of kaon"}; + Configurable cProtonPmaxcut{"cProtonPmaxcut", 2.0, "proton min cut of proton"}; + Configurable cPionPthcut{"cPionPthcut", 0.65, "pion threshold cut of pion"}; + Configurable cKaonPthcut{"cKaonPthcut", 0.65, "kaon threshold cut of kaon"}; + Configurable cProtonPthcut{"cProtonPthcut", 1.0, "proton threshold cut of proton"}; + Configurable cNSigCut2{"cNSigCut2", 2.0, "nSigma cut (2)"}; + Configurable cNSigCut3{"cNSigCut3", 3.0, "nSigma cut (3)"}; + Configurable cElMinCut{"cElMinCut", -3.0, "electron min cut"}; + Configurable cElMaxCut{"cElMaxCut", 5.0, "electron max cut"}; + Configurable cTwoPtlCut2{"cTwoPtlCut2", 2.0, "n2ptl cut"}; + Configurable cRapidityCut05{"cRapidityCut05", 0.5, "rapidity cut"}; + + template + bool selCollision(C const& coll) + { + + if (std::abs(coll.posZ()) > cVtxZcut) { + return false; + } // Reject the collisions with large vertex-z + histos.fill(HIST("hEventcounter"), 2.); + + // cent = coll.centFT0M(); //centrality for run3 + if (cSel8Trig && !coll.sel8()) { + return false; + } // require min bias trigger + histos.fill(HIST("hEventcounter"), 3.); + + if (cTFBorder && !coll.selection_bit(aod::evsel::kNoTimeFrameBorder)) { + return false; + } + if (cNoItsROBorder && !coll.selection_bit(aod::evsel::kNoITSROFrameBorder)) { + return false; + } + histos.fill(HIST("trackSelRec"), 4); + + if (cPileupReject && !coll.selection_bit(aod::evsel::kNoSameBunchPileup)) { + return false; + } + histos.fill(HIST("trackSelRec"), 5); + + if (cZVtxTimeDiff && !coll.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV)) { + return false; + } + histos.fill(HIST("trackSelRec"), 6); + + if (cItsTpcVtx && !coll.selection_bit(aod::evsel::kIsVertexITSTPC)) { + return false; + } + histos.fill(HIST("trackSelRec"), 7); + + // if (cItslayerall && !coll.selection_bit(aod::evsel::kIsGoodITSLayersAll)) {return false;} + histos.fill(HIST("trackSelRec"), 8); + + if (cvtxtofmatched && !coll.selection_bit(aod::evsel::kIsVertexTOFmatched)) { + return false; + } + histos.fill(HIST("trackSelRec"), 9); + + return true; // if all checks pass, accept the collision + } + + template + bool selTrack(T const& track) + { + if (!track.isGlobalTrack()) { + return false; + } // accept only global tracks + histos.fill(HIST("tracksel"), 2); + + // if (std::fabs(track.dcaXY()) > cDcaXYcut) {return false;} + histos.fill(HIST("tracksel"), 3); + + // if (std::fabs(track.dcaZ()) > cDcaZcut) {return false;} + histos.fill(HIST("tracksel"), 4); + + if (std::fabs(track.eta()) >= cEtacut) { + return false; + } + histos.fill(HIST("tracksel"), 5); + + if (track.pt() < cPtmincut) { + return false; + } + if (track.pt() > cPtmaxcut) { + return false; + } + histos.fill(HIST("tracksel"), 6); + + // if (track.tpcNClsCrossedRows() < cTPCcrosscut) {return false;} + histos.fill(HIST("tracksel"), 7); + + // if (track.itsChi2NCl() > cItsChiCut) {return false;} + histos.fill(HIST("tracksel"), 8); + + // if (track.tpcChi2NCl() > cTpcChiCut) {return false;} + histos.fill(HIST("tracksel"), 9); + + if (track.sign() == 0) + return false; + + return true; // if all checks pass, accept the collision + } + + template + bool rejEl(T const& track) + { + if (track.tpcNSigmaEl() > cElMinCut && track.tpcNSigmaEl() < cElMaxCut && std::fabs(track.tpcNSigmaPi()) > cNSigCut3 && std::fabs(track.tpcNSigmaKa()) > cNSigCut3 && std::fabs(track.tpcNSigmaPr()) > cNSigCut3) { + return true; + } + return false; + } + + template + bool selProton(T const& track) + { + //! if pt < threshold (For tracks without TOF information) + if (track.p() > cProtonPmincut && track.p() <= cProtonPthcut) { + if (track.hasTPC() && std::fabs(track.tpcNSigmaPr()) < cNSigCut2 && std::fabs(track.tpcNSigmaPi()) > cNSigCut2 && std::fabs(track.tpcNSigmaKa()) > cNSigCut2) { + return true; + } + } + + //! if pt < threshold (For tracks with TOF information) + if (track.p() > cProtonPmincut && track.p() <= cProtonPthcut) { + if (track.hasTOF() && std::fabs(track.tpcNSigmaPr()) < cNSigCut2 && std::fabs(track.tofNSigmaPr()) < cNSigCut2 && std::fabs(track.tpcNSigmaPi()) > cNSigCut2 && std::fabs(track.tpcNSigmaKa()) > cNSigCut2) { + return true; + } + } + + //! if pt > threshold (For tracks with TOF information) + if (track.p() > cProtonPthcut && track.p() <= cProtonPmaxcut) { + if (track.hasTPC() && track.hasTOF() && std::fabs(track.tpcNSigmaPr()) < cNSigCut2 && std::fabs(track.tofNSigmaPr()) < cNSigCut2 && std::hypot(track.tofNSigmaPi(), track.tpcNSigmaPi()) > cNSigCut2 && std::hypot(track.tofNSigmaKa(), track.tpcNSigmaKa()) > cNSigCut2) { + return true; + } + } + + return false; + } + + template + bool selKaon(T const& track) + { + //! if pt < threshold (For tracks without TOF information) + if (track.p() > cKaonPmincut && track.p() <= cKaonPthcut) { + if (track.hasTPC() && std::fabs(track.tpcNSigmaKa()) < cNSigCut2 && std::fabs(track.tpcNSigmaPi()) > cNSigCut2 && std::fabs(track.tpcNSigmaPr()) > cNSigCut2) { + return true; + } + } + + //! if pt < threshold (For tracks with TOF information) + if (track.p() > cKaonPmincut && track.p() <= cKaonPthcut) { + if (track.hasTOF() && std::fabs(track.tpcNSigmaKa()) < cNSigCut2 && std::fabs(track.tofNSigmaKa()) < cNSigCut2 && std::fabs(track.tpcNSigmaPi()) > cNSigCut2 && std::fabs(track.tpcNSigmaPr()) > cNSigCut2) { + return true; + } + } + + //! if pt > threshold (For tracks with TOF information) + if (track.p() > cKaonPthcut && track.p() <= cKaonPmaxcut) { + if (track.hasTPC() && track.hasTOF() && std::fabs(track.tpcNSigmaKa()) < cNSigCut2 && std::fabs(track.tofNSigmaKa()) < cNSigCut2 && std::hypot(track.tofNSigmaPi(), track.tpcNSigmaPi()) > cNSigCut2 && std::hypot(track.tofNSigmaPr(), track.tpcNSigmaPr()) > cNSigCut2) { + return true; + } + } + + return false; + } + + template + bool selPion(T const& track) + { + //! if pt < threshold (For tracks without TOF information) + if (track.p() > cPionPmincut && track.p() <= cPionPthcut) { + if (track.hasTPC() && std::fabs(track.tpcNSigmaPi()) < cNSigCut2 && std::fabs(track.tpcNSigmaKa()) > cNSigCut2 && std::fabs(track.tpcNSigmaPr()) > cNSigCut2) { + return true; + } + } + + //! if pt < threshold (For tracks with TOF information) + if (track.p() > cPionPmincut && track.p() <= cPionPthcut) { + if (track.hasTOF() && std::fabs(track.tpcNSigmaPi()) < cNSigCut2 && std::fabs(track.tofNSigmaPi()) < cNSigCut2 && std::fabs(track.tpcNSigmaKa()) > cNSigCut2 && std::fabs(track.tpcNSigmaPr()) > cNSigCut2) { + return true; + } + } + + //! if pt > threshold (For tracks with TOF information) + if (track.p() > cPionPthcut && track.p() <= cPionPmaxcut) { + if (track.hasTPC() && track.hasTOF() && std::fabs(track.tpcNSigmaPi()) < cNSigCut2 && std::fabs(track.tofNSigmaPi()) < cNSigCut2 && std::hypot(track.tofNSigmaKa(), track.tpcNSigmaKa()) > cNSigCut2 && std::hypot(track.tofNSigmaPr(), track.tpcNSigmaPr()) > cNSigCut2) { + return true; + } + } + + return false; + } + + double getEfficiency(double pt, TH1D* ptHistogramAllchargeRec) + { + int bin = ptHistogramAllchargeRec->FindBin(pt); + double eff = ptHistogramAllchargeRec->GetBinContent(bin); + return (eff > 0) ? eff : 1e-6; // Avoid division by zero + } + + //++++++++++++++++++++++++++++++++++++DATA CALCULATION +++++++++++++++++++++++++++++++++++++++++++++++++++++// + + void process(aod::MyCollision const& coll, aod::MyTracks const& inputTracks) + { + histos.fill(HIST("hEventcounter"), 1.); + histos.fill(HIST("Data/hZvtx_before_sel"), coll.posZ()); + + if (!selCollision(coll)) + return; + { + histos.fill(HIST("Data/hZvtx_after_sel8"), coll.posZ()); + } + + const auto cent = coll.centFT0C(); + histos.fill(HIST("Data/hCentrality"), cent); + + double nch = 0., nchPi = 0., nchKa = 0., nchPr = 0., nchAll = 0., nchAllBfCut = 0., nchEta = 0., nchPt = 0.; + double q1 = 0., q2 = 0.; + double q1Pi = 0., q2Pi = 0., q1Ka = 0., q2Ka = 0., q1Pr = 0., q2Pr = 0.; + double var1 = 0., var2 = 0., twoParAllCharge = 0.; + double var1Pi = 0., var2Pi = 0.; + double var1Ka = 0., var2Ka = 0.; + double var1Pr = 0., var2Pr = 0.; + + int sample = histos.get(HIST("Data/hZvtx_after_sel8"))->GetEntries(); + sample = sample % 30; // subsample error estimation + for (const auto& track : inputTracks) { + nchAllBfCut += 1.; + histos.fill(HIST("Data/hnchAll_bf_cut"), nchAllBfCut); + + histos.fill(HIST("tracksel"), 1); + histos.fill(HIST("Data/hTPCchi2perCluster_before"), track.tpcChi2NCl()); + histos.fill(HIST("Data/hITSchi2perCluster_before"), track.itsChi2NCl()); + histos.fill(HIST("Data/hTPCCrossedrows_before"), track.tpcNClsCrossedRows()); + + if (std::fabs(track.eta()) <= cEtacut) { + nchEta++; + histos.fill(HIST("Data/hnchTrue"), nchEta); + } + if (track.pt() >= cPtmincut && track.pt() <= cPtmaxcut) { + nchPt += 1.; + histos.fill(HIST("Data/hnchTrue_pt"), nchPt); + } + + if (track.sign() == 0) + continue; + if (!selTrack(track)) + continue; + + nchAll += 1.; + histos.fill(HIST("Data/hnchAll"), nchAll); + histos.fill(HIST("Data/hDCAxy"), track.dcaXY()); + histos.fill(HIST("Data/hDCAz"), track.dcaZ()); + histos.fill(HIST("Data/hTPCCrossedrows_after"), track.tpcNClsCrossedRows()); + histos.fill(HIST("Data/hTPCchi2perCluster_after"), track.tpcChi2NCl()); + histos.fill(HIST("Data/hITSchi2perCluster_after"), track.itsChi2NCl()); + histos.fill(HIST("Data/hP"), track.p()); + histos.fill(HIST("Data/hPt"), track.pt()); + histos.fill(HIST("Data/hEta"), track.eta()); + histos.fill(HIST("Data/hPtDCAxy"), track.pt(), track.dcaXY()); + histos.fill(HIST("Data/hPtDCAz"), track.pt(), track.dcaZ()); + histos.fill(HIST("Data/hPtEta"), track.pt(), track.eta()); + histos.fill(HIST("Data/hPEta"), track.p(), track.eta()); + histos.fill(HIST("Data/hNsigmaTPC"), track.p(), track.tpcNSigmaPr()); + + if (track.pt() >= cPtmincut || track.pt() <= cPtmaxcut) // do not change this (it is for different pt work) + { + nch += 1.; + histos.fill(HIST("Data/hnch"), nch); + } + + q1 += track.pt(); + q2 += (track.pt() * track.pt()); + + // only TPC tracks: Pion, Kaon, Proton + if (track.hasTPC() && std::abs(track.tpcNSigmaPi()) < cNSigCut3) + histos.fill(HIST("Data/NSigamaTPCpion"), track.pt(), track.tpcNSigmaPi()); + if (track.hasTPC() && std::abs(track.tpcNSigmaKa()) < cNSigCut3) + histos.fill(HIST("Data/NSigamaTPCkaon"), track.pt(), track.tpcNSigmaKa()); + if (track.hasTPC() && std::abs(track.tpcNSigmaPr()) < cNSigCut3) + histos.fill(HIST("Data/NSigamaTPCproton"), track.pt(), track.tpcNSigmaPr()); + + // only TOF tracks: Pion, Kaon, Proton + if (track.hasTOF() && std::abs(track.tofNSigmaPi()) < cNSigCut3) + histos.fill(HIST("Data/NSigamaTOFpion"), track.pt(), track.tofNSigmaPi()); + if (track.hasTOF() && std::abs(track.tofNSigmaKa()) < cNSigCut3) + histos.fill(HIST("Data/NSigamaTOFkaon"), track.pt(), track.tofNSigmaKa()); + if (track.hasTOF() && std::abs(track.tofNSigmaPr()) < cNSigCut3) + histos.fill(HIST("Data/NSigamaTOFproton"), track.pt(), track.tofNSigmaPr()); + + if (track.hasTPC()) + histos.fill(HIST("Data/hdEdx"), track.p(), track.tpcSignal()); + if (track.hasTOF()) + histos.fill(HIST("Data/hTOFbeta"), track.p(), track.beta()); + + //===================================pion============================================================== + // only TPC+TOF tracks: Pion, Kaon, Proton + if ((track.hasTPC() && std::abs(track.tpcNSigmaPi()) < cNSigCut3) && (track.hasTOF() && std::abs(track.tofNSigmaPi()) < cNSigCut3)) { + histos.fill(HIST("Data/NSigamaTPCTOFpion"), track.tpcNSigmaPi(), track.tofNSigmaPi()); + + histos.fill(HIST("Data/hdEdx_afterselection"), track.p(), track.tpcSignal()); + histos.fill(HIST("Data/hTOFbeta_afterselection"), track.p(), track.beta()); + } + + if (selPion(track)) { + histos.fill(HIST("Data/hPtPion"), track.pt()); + histos.fill(HIST("Data/hEtaPion"), track.eta()); + histos.fill(HIST("Data/hyPion"), track.rapidity(massPi)); + histos.fill(HIST("Data/hPtyPion"), track.pt(), track.rapidity(massPi)); + nchPi += 1.; + q1Pi += track.pt(); + q2Pi += (track.pt() * track.pt()); + + if (track.beta() > 1) + continue; + histos.fill(HIST("Data/hdEdx_afterselection1"), track.p(), track.tpcSignal()); + histos.fill(HIST("Data/hTOFbeta_afterselection1"), track.p(), track.beta()); + } + + //===========================kaon=============================================================== + if ((track.hasTPC() && std::abs(track.tpcNSigmaKa()) < cNSigCut3) && (track.hasTOF() && std::abs(track.tofNSigmaKa()) < cNSigCut3)) { + histos.fill(HIST("Data/NSigamaTPCTOFkaon"), track.tpcNSigmaKa(), track.tofNSigmaKa()); + histos.fill(HIST("Data/hdEdx_afterselection"), track.p(), track.tpcSignal()); + histos.fill(HIST("Data/hTOFbeta_afterselection"), track.p(), track.beta()); + } + + if (selKaon(track)) { + histos.fill(HIST("Data/hPtKaon"), track.pt()); + histos.fill(HIST("Data/hEtaKaon"), track.eta()); + histos.fill(HIST("Data/hyKaon"), track.rapidity(massKa)); + histos.fill(HIST("Data/hPtyKaon"), track.pt(), track.rapidity(massKa)); + nchKa += 1.; + q1Ka += track.pt(); + q2Ka += (track.pt() * track.pt()); + + if (track.beta() > 1) + continue; + histos.fill(HIST("Data/hdEdx_afterselection1"), track.p(), track.tpcSignal()); + histos.fill(HIST("Data/hTOFbeta_afterselection1"), track.p(), track.beta()); + } + + //============================proton=========================================================== + if ((track.hasTPC() && std::abs(track.tpcNSigmaPr()) < cNSigCut3) && (track.hasTOF() && std::abs(track.tofNSigmaPr()) < cNSigCut3)) { + histos.fill(HIST("Data/NSigamaTPCTOFproton"), track.tpcNSigmaPr(), track.tofNSigmaPr()); + histos.fill(HIST("Data/hdEdx_afterselection"), track.p(), track.tpcSignal()); + histos.fill(HIST("Data/hTOFbeta_afterselection"), track.p(), track.beta()); + } + + if (selProton(track)) { + histos.fill(HIST("Data/hPtProton"), track.pt()); + histos.fill(HIST("Data/hEtaProton"), track.eta()); + histos.fill(HIST("Data/hyProton"), track.rapidity(massPr)); + histos.fill(HIST("Data/hPtyProton"), track.pt(), track.rapidity(massPr)); + nchPr += 1.; + q1Pr += track.pt(); + q2Pr += (track.pt() * track.pt()); + + if (track.beta() > 1) + continue; + histos.fill(HIST("Data/hdEdx_afterselection1"), track.p(), track.tpcSignal()); + histos.fill(HIST("Data/hTOFbeta_afterselection1"), track.p(), track.beta()); + } + } // Track loop ends! + histos.fill(HIST("Data/hcent_nacc"), cent, nchAll); + + if (nchAll < cTwoPtlCut2) + return; + var1 = (q1 * q1 - q2) / (nchAll * (nchAll - 1)); + var2 = (q1 / nchAll); + + //------------------ all charges------------------------------------- + histos.fill(HIST("Data/hVar1"), sample, cent, var1); + histos.fill(HIST("Data/hVar2"), sample, cent, var2); + histos.fill(HIST("Data/hVarc"), sample, cent); + histos.fill(HIST("Data/hVar2meanpt"), cent, var2); + twoParAllCharge = (var1 - var2); + histos.fill(HIST("Data/hVar"), nchAll, twoParAllCharge); + + //---------------------- pions ---------------------------------------- + if (nchPi >= cTwoPtlCut2) { + var1Pi = (q1Pi * q1Pi - q2Pi) / (nchPi * (nchPi - 1)); + var2Pi = (q1Pi / nchPi); + } + + //----------------------- kaons --------------------------------------- + if (nchKa >= cTwoPtlCut2) { + var1Ka = (q1Ka * q1Ka - q2Ka) / (nchKa * (nchKa - 1)); + var2Ka = (q1Ka / nchKa); + } + + //---------------------------- protons ---------------------------------- + if (nchPr >= cTwoPtlCut2) { + var1Pr = (q1Pr * q1Pr - q2Pr) / (nchPr * (nchPr - 1)); + var2Pr = (q1Pr / nchPr); + } + + //========================centrality========================================== + histos.fill(HIST("Data/hVar1pi"), sample, cent, var1Pi); + histos.fill(HIST("Data/hVar2pi"), sample, cent, var2Pi); + histos.fill(HIST("Data/hVar2meanptpi"), cent, var2Pi); + + histos.fill(HIST("Data/hVar1k"), sample, cent, var1Ka); + histos.fill(HIST("Data/hVar2k"), sample, cent, var2Ka); + histos.fill(HIST("Data/hVar2meanptk"), cent, var2Ka); + + histos.fill(HIST("Data/hVar1p"), sample, cent, var1Pr); + histos.fill(HIST("Data/hVar2p"), sample, cent, var2Pr); + histos.fill(HIST("Data/hVar2meanptp"), cent, var2Pr); + + //-----------------------nch------------------------------------- + histos.fill(HIST("Data/hVar1x"), sample, nchAll, var1); + histos.fill(HIST("Data/hVar2x"), sample, nchAll, var2); + histos.fill(HIST("Data/hVarx"), sample, nchAll); + histos.fill(HIST("Data/hVar2meanptx"), nchAll, var2); + + histos.fill(HIST("Data/hVar1pix"), sample, nchAll, var1Pi); + histos.fill(HIST("Data/hVar2pix"), sample, nchAll, var2Pi); + histos.fill(HIST("Data/hVarpix"), sample, nchPi); + histos.fill(HIST("Data/hVar2meanptpix"), nchAll, var2Pi); + + histos.fill(HIST("Data/hVar1kx"), sample, nchAll, var1Ka); + histos.fill(HIST("Data/hVar2kx"), sample, nchAll, var2Ka); + histos.fill(HIST("Data/hVarkx"), sample, nchKa); + histos.fill(HIST("Data/hVar2meanptkx"), nchAll, var2Ka); + + histos.fill(HIST("Data/hVar1px"), sample, nchAll, var1Pr); + histos.fill(HIST("Data/hVar2px"), sample, nchAll, var2Pr); + histos.fill(HIST("Data/hVarpx"), sample, nchPr); + histos.fill(HIST("Data/hVar2meanptpx"), nchAll, var2Pr); + + } // event loop ends! + + PROCESS_SWITCH(EventMeanPtId, process, "process real data information", false); + + //++++++++++++++++++++++++++++++++++++MC Reconstructed +++++++++++++++++++++++++++++++++++++++++++++++++++++// + + SliceCache cache; + Preslice mcTrack = o2::aod::mcparticle::mcCollisionId; + void processMcReco(aod::MyMCRecoCollision const& coll, aod::MyMCRecoTracks const& inputTracks, aod::McCollisions const& mcCollisions, aod::McParticles const& mcParticles) + { + (void)mcCollisions; + if (!coll.has_mcCollision()) { + return; + } + histos.fill(HIST("Rec/hZvtx_before_sel"), coll.posZ()); + histos.fill(HIST("hVtxZ_before_gen"), coll.mcCollision().posZ()); + + if (cTFBorder && !coll.selection_bit(aod::evsel::kNoTimeFrameBorder)) { + return; + } + if (cNoItsROBorder && !coll.selection_bit(aod::evsel::kNoITSROFrameBorder)) { + return; + } + if (cPileupReject && !coll.selection_bit(aod::evsel::kNoSameBunchPileup)) { + return; + } + if (cZVtxTimeDiff && !coll.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV)) { + return; + } + if (cItsTpcVtx && !coll.selection_bit(aod::evsel::kIsVertexITSTPC)) { + return; + } + if (cvtxtofmatched && !coll.selection_bit(aod::evsel::kIsVertexTOFmatched)) { + return; + } + if (std::abs(coll.posZ()) > cVtxZcut) { + return; + } + + if (!coll.sel8()) { + return; + } + float cent = coll.centFT0C(); + histos.fill(HIST("Rec/hZvtx_after_sel8"), coll.posZ()); + + double nch = 0., nchPi = 0., nchKa = 0., nchPr = 0., nchAll = 0., nchAllBfCut = 0., nchEta = 0., nchPt = 0.; + double q1 = 0., q2 = 0.; + double q1Pi = 0., q2Pi = 0., q1Ka = 0., q2Ka = 0., q1Pr = 0., q2Pr = 0.; + double var1 = 0., var2 = 0., twoParAllCharge = 0.; + double var1Pi = 0., var2Pi = 0., var1Ka = 0., var2Ka = 0., var1Pr = 0., var2Pr = 0.; + double sumPtWeight = 0., sumWeight = 0., sumPtPtWeight = 0., var1Eff = 0., var2Eff = 0.; + double sumPtWeightPi = 0., sumWeightPi = 0., sumPtPtWeightPi = 0., var1EffPi = 0., var2EffPi = 0.; + double sumPtWeightKa = 0., sumWeightKa = 0., sumPtPtWeightKa = 0., var1EffKa = 0., var2EffKa = 0.; + double sumPtWeightPr = 0., sumWeightPr = 0., sumPtPtWeightPr = 0., var1EffPr = 0., var2EffPr = 0.; + + int sample = histos.get(HIST("Rec/hZvtx_after_sel8"))->GetEntries(); + sample = sample % 30; + + for (const auto& track : inputTracks) { + nchAllBfCut += 1.; + histos.fill(HIST("Rec/hnchAll_bf_cut"), nchAllBfCut); + histos.fill(HIST("Rec/hTPCchi2perCluster_before"), track.tpcChi2NCl()); + histos.fill(HIST("Rec/hITSchi2perCluster_before"), track.itsChi2NCl()); + histos.fill(HIST("Rec/hTPCCrossedrows_before"), track.tpcNClsCrossedRows()); + + if (std::fabs(track.eta()) <= cEtacut) { + nchEta++; + histos.fill(HIST("Rec/hnchTrue"), nchEta); + } + if (track.pt() >= cPtmincut && track.pt() <= cPtmaxcut) { + nchPt += 1.; + histos.fill(HIST("Rec/hnchTrue_pt"), nchPt); + } + if (!track.isGlobalTrack()) + continue; + if (std::fabs(track.eta()) > cEtacut) + continue; + if ((track.pt() <= cPtmincut) || (track.pt() >= cPtmaxcut)) + continue; + if (track.sign() == 0) + continue; + // if (std::fabs(track.y()) > 0.5) continue; + histos.fill(HIST("hPt_rec"), track.pt()); + histos.fill(HIST("hEta_rec"), track.eta()); + + auto mcParticle = track.mcParticle(); + nchAll += 1.; + histos.fill(HIST("Rec/hnchAll"), nchAll); + histos.fill(HIST("ptHistogramAllchargeRec"), track.pt()); + histos.fill(HIST("Rec/hDCAxy"), track.dcaXY()); + histos.fill(HIST("Rec/hDCAz"), track.dcaZ()); + histos.fill(HIST("Rec/hTPCCrossedrows_after"), track.tpcNClsCrossedRows()); + histos.fill(HIST("Rec/hTPCchi2perCluster_after"), track.tpcChi2NCl()); + histos.fill(HIST("Rec/hITSchi2perCluster_after"), track.itsChi2NCl()); + histos.fill(HIST("Rec/hP"), track.p()); + histos.fill(HIST("Rec/hPt"), track.pt()); + histos.fill(HIST("Rec/hEta"), track.eta()); + histos.fill(HIST("Rec/hPtDCAxy"), track.pt(), track.dcaXY()); + histos.fill(HIST("Rec/hPtDCAz"), track.pt(), track.dcaZ()); + histos.fill(HIST("Rec/hPtEta"), track.pt(), track.eta()); + histos.fill(HIST("Rec/hPEta"), track.p(), track.eta()); + histos.fill(HIST("Rec/hNsigmaTPC"), track.p(), track.tpcNSigmaPr()); + + if (track.pt() >= cPtmincut || track.pt() <= cPtmaxcut) // do not change this (it is for different pt work) + { + nch += 1.; + histos.fill(HIST("Rec/hnch"), nch); + } + q1 += track.pt(); + q2 += (track.pt() * track.pt()); + + double eff = getEfficiency(track.pt(), ptHistogramAllchargeRec); + // LOGF(info, " with value %.2f", eff); + sumPtWeight += track.pt() / eff; + sumPtPtWeight += (track.pt() * track.pt()) / (eff * eff); + sumWeight += 1. / eff; + + if (std::abs(mcParticle.pdgCode()) == PDG_t::kPiPlus) + histos.fill(HIST("ptHistogramPionrec_pdg"), track.pt()); + if (std::abs(mcParticle.pdgCode()) == PDG_t::kKPlus) + histos.fill(HIST("ptHistogramKaonrec_pdg"), track.pt()); + if (std::abs(mcParticle.pdgCode()) == PDG_t::kProton) + histos.fill(HIST("ptHistogramProtonrec_pdg"), track.pt()); + + if (cfgRejEl == false && rejEl(track)) { + return; + } + + // only TPC tracks: Pion, Kaon, Proton + if (track.hasTPC() && std::abs(track.tpcNSigmaPi()) < cNSigCut3) + histos.fill(HIST("Rec/NSigamaTPCpion"), track.pt(), track.tpcNSigmaPi()); + if (track.hasTPC() && std::abs(track.tpcNSigmaKa()) < cNSigCut3) + histos.fill(HIST("Rec/NSigamaTPCkaon"), track.pt(), track.tpcNSigmaKa()); + if (track.hasTPC() && std::abs(track.tpcNSigmaPr()) < cNSigCut3) + histos.fill(HIST("Rec/NSigamaTPCproton"), track.pt(), track.tpcNSigmaPr()); + + // only TOF tracks: Pion, Kaon, Proton + if (track.hasTOF() && std::abs(track.tofNSigmaPi()) < cNSigCut3) + histos.fill(HIST("Rec/NSigamaTOFpion"), track.pt(), track.tofNSigmaPi()); + if (track.hasTOF() && std::abs(track.tofNSigmaKa()) < cNSigCut3) + histos.fill(HIST("Rec/NSigamaTOFkaon"), track.pt(), track.tofNSigmaKa()); + if (track.hasTOF() && std::abs(track.tofNSigmaPr()) < cNSigCut3) + histos.fill(HIST("Rec/NSigamaTOFproton"), track.pt(), track.tofNSigmaPr()); + + if (track.hasTPC()) + histos.fill(HIST("Rec/hdEdx"), track.p(), track.tpcSignal()); + if (track.hasTOF()) + histos.fill(HIST("Rec/hTOFbeta"), track.p(), track.beta()); + if (track.hasTPC()) + histos.fill(HIST("hdEdx_afterselection_rec_beforepidcut"), track.p(), track.tpcSignal()); + if (track.hasTOF()) + histos.fill(HIST("hTOFbeta_afterselection_rec_beforepidcut"), track.p(), track.beta()); + + //===================================pion============================================================== + if ((track.hasTPC() && std::abs(track.tpcNSigmaPi()) < cNSigCut3) && (track.hasTOF() && std::abs(track.tofNSigmaPi()) < cNSigCut3)) { + histos.fill(HIST("Rec/NSigamaTPCTOFpion"), track.tpcNSigmaPi(), track.tofNSigmaPi()); + + histos.fill(HIST("Rec/hdEdx_afterselection"), track.p(), track.tpcSignal()); + histos.fill(HIST("Rec/hTOFbeta_afterselection"), track.p(), track.beta()); + } + + if (selPion(track)) { + if (std::fabs(track.y()) > cRapidityCut05) + continue; + if (track.beta() > 1) + continue; + histos.fill(HIST("ptHistogramPionrec"), track.pt()); + histos.fill(HIST("Rec/hPtPion"), track.pt()); + histos.fill(HIST("Rec/hEtaPion"), track.eta()); + histos.fill(HIST("Rec/hyPion"), track.rapidity(massPi)); + histos.fill(HIST("Rec/hPtyPion"), track.pt(), track.rapidity(massPi)); + histos.fill(HIST("NSigamaTPCpion_rec"), track.p(), track.tpcNSigmaPi()); + histos.fill(HIST("NSigamaTOFpion_rec"), track.p(), track.tofNSigmaPi()); + histos.fill(HIST("NSigamaTPCTOFpion_rec"), track.tpcNSigmaPi(), track.tofNSigmaPi()); + histos.fill(HIST("Rec/hdEdx_afterselection1"), track.p(), track.tpcSignal()); + histos.fill(HIST("Rec/hTOFbeta_afterselection1"), track.p(), track.beta()); + if (std::abs(track.mcParticle().pdgCode()) == PDG_t::kPiPlus) { + histos.fill(HIST("ptHistogramPionrec_purity"), track.pt()); + } + nchPi += 1.; + q1Pi += track.pt(); + q2Pi += (track.pt() * track.pt()); + + double effPi = getEfficiency(track.pt(), ptHistogramPionrec); + // LOGF(info, " with value %.2f", eff); + sumPtWeightPi += track.pt() / effPi; + sumPtPtWeightPi += (track.pt() * track.pt()) / (effPi * effPi); + sumWeightPi += 1. / effPi; + + histos.fill(HIST("hPyPion_rec"), track.p(), track.rapidity(massPi)); + histos.fill(HIST("hPtyPion_rec"), track.pt(), track.rapidity(massPi)); + } + + //===========================kaon=============================================================== + + if ((track.hasTPC() && std::abs(track.tpcNSigmaKa()) < cNSigCut3) && (track.hasTOF() && std::abs(track.tofNSigmaKa()) < cNSigCut3)) { + histos.fill(HIST("Rec/NSigamaTPCTOFkaon"), track.tpcNSigmaKa(), track.tofNSigmaKa()); + histos.fill(HIST("Rec/hdEdx_afterselection"), track.p(), track.tpcSignal()); + histos.fill(HIST("Rec/hTOFbeta_afterselection"), track.p(), track.beta()); + } + + if (selKaon(track)) { + if (std::fabs(track.y()) > cRapidityCut05) + continue; + if (track.beta() > 1) + continue; + histos.fill(HIST("ptHistogramKaonrec"), track.pt()); + histos.fill(HIST("Rec/hPtKaon"), track.pt()); + histos.fill(HIST("Rec/hEtaKaon"), track.eta()); + histos.fill(HIST("Rec/hyKaon"), track.rapidity(massKa)); + histos.fill(HIST("Rec/hPtyKaon"), track.pt(), track.rapidity(massKa)); + histos.fill(HIST("NSigamaTPCkaon_rec"), track.p(), track.tpcNSigmaKa()); + histos.fill(HIST("NSigamaTOFkaon_rec"), track.p(), track.tofNSigmaKa()); + histos.fill(HIST("NSigamaTPCTOFkaon_rec"), track.tpcNSigmaKa(), track.tofNSigmaKa()); + histos.fill(HIST("Rec/hdEdx_afterselection1"), track.p(), track.tpcSignal()); + histos.fill(HIST("Rec/hTOFbeta_afterselection1"), track.p(), track.beta()); + if (std::abs(track.mcParticle().pdgCode()) == PDG_t::kKPlus) { + histos.fill(HIST("ptHistogramKaonrec_purity"), track.pt()); + } + nchKa += 1.; + q1Ka += track.pt(); + q2Ka += (track.pt() * track.pt()); + + double effKa = getEfficiency(track.pt(), ptHistogramKaonrec); + // LOGF(info, " with value %.2f", eff); + sumPtWeightKa += track.pt() / effKa; + sumPtPtWeightKa += (track.pt() * track.pt()) / (effKa * effKa); + sumWeightKa += 1. / effKa; + + histos.fill(HIST("hPyKaon_rec"), track.p(), track.rapidity(massKa)); + histos.fill(HIST("hPtyKaon_rec"), track.pt(), track.rapidity(massKa)); + } + + //============================proton=========================================================== + + if ((track.hasTPC() && std::abs(track.tpcNSigmaPr()) < cNSigCut3) && (track.hasTOF() && std::abs(track.tofNSigmaPr()) < cNSigCut3)) { + histos.fill(HIST("Rec/NSigamaTPCTOFproton"), track.tpcNSigmaPr(), track.tofNSigmaPr()); + histos.fill(HIST("Rec/hdEdx_afterselection"), track.p(), track.tpcSignal()); + histos.fill(HIST("Rec/hTOFbeta_afterselection"), track.p(), track.beta()); + } + + if (selProton(track)) { + if (std::fabs(track.y()) > cRapidityCut05) + continue; + if (track.beta() > 1) + continue; + histos.fill(HIST("ptHistogramProtonrec"), track.pt()); + histos.fill(HIST("Rec/hPtProton"), track.pt()); + histos.fill(HIST("Rec/hEtaProton"), track.eta()); + histos.fill(HIST("Rec/hyProton"), track.rapidity(massPr)); + histos.fill(HIST("Rec/hPtyProton"), track.pt(), track.rapidity(massPr)); + histos.fill(HIST("NSigamaTPCproton_rec"), track.p(), track.tpcNSigmaPr()); + histos.fill(HIST("NSigamaTOFproton_rec"), track.p(), track.tofNSigmaPr()); + histos.fill(HIST("NSigamaTPCTOFproton_rec"), track.tpcNSigmaPr(), track.tofNSigmaPr()); + histos.fill(HIST("Rec/hdEdx_afterselection1"), track.p(), track.tpcSignal()); + histos.fill(HIST("Rec/hTOFbeta_afterselection1"), track.p(), track.beta()); + if (std::abs(track.mcParticle().pdgCode()) == PDG_t::kProton) { + histos.fill(HIST("ptHistogramProtonrec_purity"), track.pt()); + } + nchPr += 1.; + q1Pr += track.pt(); + q2Pr += (track.pt() * track.pt()); + + double effPr = getEfficiency(track.pt(), ptHistogramProtonrec); + // LOGF(info, " with value %.2f", eff); + sumPtWeightPr += track.pt() / effPr; + sumPtPtWeightPr += (track.pt() * track.pt()) / (effPr * effPr); + sumWeightPr += 1. / effPr; + + histos.fill(HIST("hPyProton_rec"), track.p(), track.rapidity(massPr)); + histos.fill(HIST("hPtyProton_rec"), track.pt(), track.rapidity(massPr)); + } + + } // loop over tracks + histos.fill(HIST("Rec/hcent_nacc"), cent, nchAll); + + if (nchAll < cTwoPtlCut2) + return; + var1 = (q1 * q1 - q2) / (nchAll * (nchAll - 1)); + var2 = (q1 / nchAll); + + //------------------ Efficiency corrected histograms --------------- + + var1Eff = (sumPtWeight * sumPtWeight - sumPtPtWeight) / (sumWeight * (sumWeight - 1)); + var2Eff = (sumPtWeight / sumWeight); + + histos.fill(HIST("Rec/hVar1"), sample, cent, var1); + histos.fill(HIST("Rec/hVar2"), sample, cent, var2); + histos.fill(HIST("Rec/hVarc"), sample, cent); + histos.fill(HIST("Rec/hVar2meanpt"), cent, var2); + twoParAllCharge = (var1 - var2); + histos.fill(HIST("Rec/hVar"), nchAll, twoParAllCharge); + + //---------------------- pions ---------------------------------------- + if (nchPi >= cTwoPtlCut2) { + var1Pi = (q1Pi * q1Pi - q2Pi) / (nchPi * (nchPi - 1)); + var2Pi = (q1Pi / nchPi); + + var1EffPi = (sumPtWeightPi * sumPtWeightPi - sumPtPtWeightPi) / (sumWeightPi * (sumWeightPi - 1)); + var2EffPi = (sumPtWeightPi / sumWeightPi); + } + //----------------------- kaons --------------------------------------- + if (nchKa >= cTwoPtlCut2) { + var1Ka = (q1Ka * q1Ka - q2Ka) / (nchKa * (nchKa - 1)); + var2Ka = (q1Ka / nchKa); + + var1EffKa = (sumPtWeightKa * sumPtWeightKa - sumPtPtWeightKa) / (sumWeightKa * (sumWeightKa - 1)); + var2EffKa = (sumPtWeightKa / sumWeightKa); + } + //---------------------------- protons ---------------------------------- + if (nchPr >= cTwoPtlCut2) { + var1Pr = (q1Pr * q1Pr - q2Pr) / (nchPr * (nchPr - 1)); + var2Pr = (q1Pr / nchPr); + + var1EffPr = (sumPtWeightPr * sumPtWeightPr - sumPtPtWeightPr) / (sumWeightPr * (sumWeightPr - 1)); + var2EffPr = (sumPtWeightPr / sumWeightPr); + } + //========================centrality========================================== + + histos.fill(HIST("Rec/hVar1pi"), sample, cent, var1Pi); + histos.fill(HIST("Rec/hVar2pi"), sample, cent, var2Pi); + histos.fill(HIST("Rec/hVar2meanptpi"), cent, var2Pi); + histos.fill(HIST("Rec/hVar1k"), sample, cent, var1Ka); + histos.fill(HIST("Rec/hVar2k"), sample, cent, var2Ka); + histos.fill(HIST("Rec/hVar2meanptk"), cent, var2Ka); + histos.fill(HIST("Rec/hVar1p"), sample, cent, var1Pr); + histos.fill(HIST("Rec/hVar2p"), sample, cent, var2Pr); + histos.fill(HIST("Rec/hVar2meanptp"), cent, var2Pr); + + //-----------------------nch------------------------------------- + histos.fill(HIST("Rec/hVar1x"), sample, nchAll, var1); + histos.fill(HIST("Rec/hVar2x"), sample, nchAll, var2); + histos.fill(HIST("Rec/hVarx"), sample, nchAll); + histos.fill(HIST("Rec/hVar2meanptx"), nchAll, var2); + histos.fill(HIST("Rec/hVar1pix"), sample, nchAll, var1Pi); + histos.fill(HIST("Rec/hVar2pix"), sample, nchAll, var2Pi); + histos.fill(HIST("Rec/hVarpix"), sample, nchPi); + histos.fill(HIST("Rec/hVar2meanptpix"), nchAll, var2Pi); + histos.fill(HIST("Rec/hVar1kx"), sample, nchAll, var1Ka); + histos.fill(HIST("Rec/hVar2kx"), sample, nchAll, var2Ka); + histos.fill(HIST("Rec/hVarkx"), sample, nchKa); + histos.fill(HIST("Rec/hVar2meanptkx"), nchAll, var2Ka); + histos.fill(HIST("Rec/hVar1px"), sample, nchAll, var1Pr); + histos.fill(HIST("Rec/hVar2px"), sample, nchAll, var2Pr); + histos.fill(HIST("Rec/hVarpx"), sample, nchPr); + histos.fill(HIST("Rec/hVar2meanptpx"), nchAll, var2Pr); + + histos.fill(HIST("hEffVar1x"), sample, nchAll, var1Eff); + histos.fill(HIST("hEffVar2x"), sample, nchAll, var2Eff); + histos.fill(HIST("hEffVarx"), sample, nchAll); + histos.fill(HIST("hEffVar2Meanptx"), nchAll, var2Eff); + + histos.fill(HIST("hEffVar1pix"), sample, nchAll, var1EffPi); + histos.fill(HIST("hEffVar2pix"), sample, nchAll, var2EffPi); + histos.fill(HIST("hEffVarpix"), sample, nchAll); + histos.fill(HIST("hEffVar2Meanptpix"), nchAll, var2EffPi); + + histos.fill(HIST("hEffVar1kx"), sample, nchAll, var1EffKa); + histos.fill(HIST("hEffVar2kx"), sample, nchAll, var2EffKa); + histos.fill(HIST("hEffVarkx"), sample, nchAll); + histos.fill(HIST("hEffVar2Meanptkx"), nchAll, var2EffKa); + + histos.fill(HIST("hEffVar1px"), sample, nchAll, var1EffPr); + histos.fill(HIST("hEffVar2px"), sample, nchAll, var2EffPr); + histos.fill(HIST("hEffVarpx"), sample, nchAll); + histos.fill(HIST("hEffVar2Meanptpx"), nchAll, var2EffPr); + + //================= generated level============================== + + const auto& mccolgen = coll.mcCollision_as(); + if (std::abs(mccolgen.posZ()) > cVtxZcut) { + return; + } + const auto& mcpartgen = mcParticles.sliceByCached(aod::mcparticle::mcCollisionId, mccolgen.globalIndex(), cache); + histos.fill(HIST("hVtxZ_after_gen"), mccolgen.posZ()); + + double nchGen = 0., nchGenAll = 0., nchGenTrue = 0.; + double nchPiGen = 0., nchKaGen = 0., nchPrGen = 0.; + double nch1 = 0., nch2 = 0., nch3 = 0.; + double q1AllGen = 0, q2AllGen = 0.; + double q1PiGen = 0, q2PiGen = 0, q1KaGen = 0, q2KaGen = 0, q1PrGen = 0, q2PrGen = 0; + double var1AllGen = 0, var2AllGen = 0.; + double var1PiGen = 0, var2PiGen = 0, var1KaGen = 0, var2KaGen = 0, var1PrGen = 0, var2PrGen = 0; + + int sampleGen = histos.get(HIST("hVtxZ_after_gen"))->GetEntries(); + sampleGen = sampleGen % 30; + + for (const auto& mcpart : mcpartgen) { + // auto pdgcode = std::abs(mcpart.pdgCode()); + if (!mcpart.isPhysicalPrimary()) { + continue; + } + nch1++; + histos.fill(HIST("hnch1"), nch1); + nch2++; + histos.fill(HIST("hnch2"), nch2); + nch3++; + histos.fill(HIST("hnch3"), nch3); + + int pid = mcpart.pdgCode(); + auto sign = 0; + auto* pd = pdg->GetParticle(pid); + if (pd != nullptr) { + sign = pd->Charge() / 3.; + } + if (sign == 0) { + continue; + } + // histos.fill(HIST("gen_hSign"), sign); + if (std::fabs(mcpart.eta()) > cEtacut) + continue; + nchGenTrue++; + histos.fill(HIST("hnch_gen_true"), nchGenTrue); + if ((mcpart.pt() <= cPtmincut) || (mcpart.pt() >= cPtmaxcut)) + continue; + histos.fill(HIST("hPt_gen"), mcpart.pt()); + histos.fill(HIST("hEta_gen"), mcpart.eta()); + histos.fill(HIST("ptHistogram_allcharge_gen"), mcpart.pt()); + nchGenAll += 1.; + q1AllGen += mcpart.pt(); + q2AllGen += (mcpart.pt() * mcpart.pt()); + histos.fill(HIST("hnch_gen_all"), nchGenAll); + if (std::fabs(mcpart.y()) < cRapidityCut05) { + + if (mcpart.pdgCode() == PDG_t::kPiPlus || mcpart.pdgCode() == PDG_t::kPiMinus) { + histos.fill(HIST("ptHistogramPion"), mcpart.pt()); + nchPiGen += 1.; + q1PiGen += mcpart.pt(); + q2PiGen += (mcpart.pt() * mcpart.pt()); + histos.fill(HIST("hnch_pi"), nchPiGen); + } + + if (mcpart.pdgCode() == PDG_t::kKPlus || mcpart.pdgCode() == PDG_t::kKMinus) { + histos.fill(HIST("ptHistogramKaon"), mcpart.pt()); + nchKaGen += 1.; + q1KaGen += mcpart.pt(); + q2KaGen += (mcpart.pt() * mcpart.pt()); + histos.fill(HIST("hnch_ka"), nchKaGen); + } + + if (mcpart.pdgCode() == PDG_t::kProton || mcpart.pdgCode() == PDG_t::kProtonBar) { + histos.fill(HIST("ptHistogramProton"), mcpart.pt()); + nchPrGen += 1.; + q1PrGen += mcpart.pt(); + q2PrGen += (mcpart.pt() * mcpart.pt()); + histos.fill(HIST("hnch_pr"), nchPrGen); + } + + } //|y| < 0.5 cut ends! + + } // particle + histos.fill(HIST("hcent_nacc_gen"), cent, nchGen); + + if (nchGenAll < cTwoPtlCut2) + return; + var1AllGen = (q1AllGen * q1AllGen - q2AllGen) / (nchGenAll * (nchGenAll - 1)); + var2AllGen = (q1AllGen / nchGenAll); + + if (nchPiGen >= cTwoPtlCut2) { + var1PiGen = (q1PiGen * q1PiGen - q2PiGen) / (nchPiGen * (nchPiGen - 1)); + var2PiGen = (q1PiGen / nchPiGen); + } + + //----------------------- kaons --------------------------------------- + if (nchKaGen >= cTwoPtlCut2) { + var1KaGen = (q1KaGen * q1KaGen - q2KaGen) / (nchKaGen * (nchKaGen - 1)); + var2KaGen = (q1KaGen / nchKaGen); + } + //---------------------------- protons ---------------------------------- + if (nchPrGen >= cTwoPtlCut2) { + var1PrGen = (q1PrGen * q1PrGen - q2PrGen) / (nchPrGen * (nchPrGen - 1)); + var2PrGen = (q1PrGen / nchPrGen); + } + //-----------------------nch------------------------------------- + histos.fill(HIST("hVar1x_gen"), sampleGen, nchGenAll, var1AllGen); + histos.fill(HIST("hVar2x_gen"), sampleGen, nchGenAll, var2AllGen); + histos.fill(HIST("hVarx_gen"), sampleGen, nchGenAll); + histos.fill(HIST("hVar2meanptx_gen"), nchGenAll, var2AllGen); + histos.fill(HIST("hVar1pix_gen"), sampleGen, nchGenAll, var1PiGen); + histos.fill(HIST("hVar2pix_gen"), sampleGen, nchGenAll, var2PiGen); + histos.fill(HIST("hVarpix_gen"), sampleGen, nchPiGen); + histos.fill(HIST("hVar2meanptpix_gen"), nchGenAll, var2PiGen); + histos.fill(HIST("hVar1kx_gen"), sampleGen, nchGenAll, var1KaGen); + histos.fill(HIST("hVar2kx_gen"), sampleGen, nchGenAll, var2KaGen); + histos.fill(HIST("hVarkx_gen"), sampleGen, nchKaGen); + histos.fill(HIST("hVar2meanptkx_gen"), nchGenAll, var2KaGen); + histos.fill(HIST("hVar1px_gen"), sampleGen, nchGenAll, var1PrGen); + histos.fill(HIST("hVar2px_gen"), sampleGen, nchGenAll, var2PrGen); + histos.fill(HIST("hVarpx_gen"), sampleGen, nchPrGen); + histos.fill(HIST("hVar2meanptpx_gen"), nchGenAll, var2PrGen); + + } // void process + PROCESS_SWITCH(EventMeanPtId, processMcReco, "Process reconstructed", true); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + WorkflowSpec workflow{adaptAnalysisTask(cfgc)}; + return workflow; +} From 490435ddd67f2910894ab7f60a712b09394736b1 Mon Sep 17 00:00:00 2001 From: Zhiyong <71517277+Luzhiyongg@users.noreply.github.com> Date: Fri, 20 Jun 2025 07:29:24 +0800 Subject: [PATCH 153/871] [PWGCF] add bool for pT ordering cut (#11690) --- .../TwoParticleCorrelations/Tasks/diHadronCor.cxx | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/PWGCF/TwoParticleCorrelations/Tasks/diHadronCor.cxx b/PWGCF/TwoParticleCorrelations/Tasks/diHadronCor.cxx index 13c8b352d9f..ef2c29e4f21 100644 --- a/PWGCF/TwoParticleCorrelations/Tasks/diHadronCor.cxx +++ b/PWGCF/TwoParticleCorrelations/Tasks/diHadronCor.cxx @@ -94,7 +94,8 @@ struct DiHadronCor { O2_DEFINE_CONFIGURABLE(cfgLocalEfficiency, bool, false, "Use local efficiency object") O2_DEFINE_CONFIGURABLE(cfgVerbosity, bool, false, "Verbose output") O2_DEFINE_CONFIGURABLE(cfgUseEventWeights, bool, false, "Use event weights for mixed event") - O2_DEFINE_CONFIGURABLE(cfgUsePtDiff, bool, false, "To enable pt differential vn, one needs to set this to true and set the pt bins accordingly") + 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") SliceCache cache; @@ -473,10 +474,12 @@ struct DiHadronCor { associatedWeight = efficiencyAssociatedCache[track2.filteredIndex()]; } - if (cfgUsePtDiff && track1.globalIndex() == track2.globalIndex()) + if (!cfgUsePtOrder && track1.globalIndex() == track2.globalIndex()) continue; // For pt-differential correlations, skip if the trigger and associate are the same track - if (!cfgUsePtDiff && track1.pt() <= track2.pt()) + if (cfgUsePtOrder && system == SameEvent && track1.pt() <= track2.pt()) continue; // Without pt-differential correlations, skip if the trigger pt is less than the associate pt + if (cfgUsePtOrder && system == MixedEvent && cfgUsePtOrderInMixEvent && track1.pt() <= track2.pt()) + continue; // For pt-differential correlations in mixed events, skip if the trigger pt is less than the associate pt float deltaPhi = RecoDecay::constrainAngle(track1.phi() - track2.phi(), -PIHalf); float deltaEta = track1.eta() - track2.eta(); @@ -540,10 +543,12 @@ struct DiHadronCor { if (doprocessOntheflyMixed && !genTrackSelected(track2)) continue; - if (cfgUsePtDiff && track1.globalIndex() == track2.globalIndex()) + if (!cfgUsePtOrder && track1.globalIndex() == track2.globalIndex()) continue; // For pt-differential correlations, skip if the trigger and associate are the same track - if (!cfgUsePtDiff && track1.pt() <= track2.pt()) + if (cfgUsePtOrder && system == SameEvent && track1.pt() <= track2.pt()) continue; // Without pt-differential correlations, skip if the trigger pt is less than the associate pt + if (cfgUsePtOrder && system == MixedEvent && cfgUsePtOrderInMixEvent && track1.pt() <= track2.pt()) + continue; // For pt-differential correlations in mixed events, skip if the trigger pt is less than the associate pt float deltaPhi = RecoDecay::constrainAngle(track1.phi() - track2.phi(), -PIHalf); float deltaEta = track1.eta() - track2.eta(); From fa9d24e57a56cb34b1c8f08a212aac40029ac689 Mon Sep 17 00:00:00 2001 From: Antonio Ortiz <42810873+aortizve@users.noreply.github.com> Date: Thu, 19 Jun 2025 18:55:08 -0600 Subject: [PATCH 154/871] [PWGLF,Trigger] new event selection criteria (#11696) --- EventFiltering/PWGMM/multFilter.cxx | 39 ++++++++++++++++++++--------- 1 file changed, 27 insertions(+), 12 deletions(-) diff --git a/EventFiltering/PWGMM/multFilter.cxx b/EventFiltering/PWGMM/multFilter.cxx index cf9057a28a3..fe641438a43 100644 --- a/EventFiltering/PWGMM/multFilter.cxx +++ b/EventFiltering/PWGMM/multFilter.cxx @@ -8,24 +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. -#include -#include - -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/StaticFor.h" - +#include "Common/Core/TrackSelection.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/TrackSelectionTables.h" #include "EventFiltering/filterTables.h" #include "CCDB/BasicCCDBManager.h" #include "CCDB/CcdbApi.h" #include "DataFormatsFT0/Digit.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/StaticFor.h" +#include "Framework/runDataProcessing.h" #include "ReconstructionDataFormats/Track.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "Common/Core/TrackSelection.h" + +#include +#include using namespace o2; using namespace o2::framework; @@ -58,6 +57,9 @@ struct multFilter { Configurable sel8{"sel8", 1, "apply sel8 event selection"}; Configurable selt0time{"selt0time", 0, "apply 1ns cut T0A and T0C"}; Configurable selt0vtx{"selt0vtx", 0, "apply T0 vertext trigger"}; + Configurable isTimeFrameBorderCut{"isTimeFrameBorderCut", 1, "apply timeframe border cut"}; + Configurable isSameBunchPileup{"isSameBunchPileup", 1, "apply same bunch pileup cut"}; + Configurable isGoodZvtxFT0vsPV{"isGoodZvtxFT0vsPV", 1, "apply good vtx FT0vsPV cut"}; Configurable avPyT0A{"avPyT0A", 8.16, "nch from pythia T0A"}; Configurable avPyT0C{"avPyT0C", 8.83, "nch from pythia T0C"}; @@ -358,6 +360,19 @@ struct multFilter { return; } + if (isTimeFrameBorderCut && !collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)) { + tags(false, false, false, false, false, false, false); + return; + } + if (isSameBunchPileup && !collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { + tags(false, false, false, false, false, false, false); + return; + } + if (isGoodZvtxFT0vsPV && !collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { + tags(false, false, false, false, false, false, false); + return; + } + multiplicity.fill(HIST("hMultFV0sel"), sumAmpFV0); multiplicity.fill(HIST("hMultFV01to4Ringsel"), sumAmpFV01to4Ring); multiplicity.fill(HIST("hMultFV05Ringsel"), sumAmpFV05Ring); From 1a2c7cfbcabb21a8f7945e59054d4bd24736043f Mon Sep 17 00:00:00 2001 From: skundu692 <86804743+skundu692@users.noreply.github.com> Date: Fri, 20 Jun 2025 03:57:20 +0200 Subject: [PATCH 155/871] [PWGLF] Fix bug in index of dirived data (#11693) --- PWGLF/DataModel/LFSpincorrelationTables.h | 58 +++++++++---------- .../Strangeness/lambdaspincorrelation.cxx | 35 ++++++----- 2 files changed, 48 insertions(+), 45 deletions(-) diff --git a/PWGLF/DataModel/LFSpincorrelationTables.h b/PWGLF/DataModel/LFSpincorrelationTables.h index 40a823da48c..f7ff44377d4 100644 --- a/PWGLF/DataModel/LFSpincorrelationTables.h +++ b/PWGLF/DataModel/LFSpincorrelationTables.h @@ -28,21 +28,21 @@ namespace o2::aod { -namespace lambdaspincorrevent +namespace lambdaevent { DECLARE_SOA_COLUMN(Cent, cent, float); DECLARE_SOA_COLUMN(Posz, posz, float); -} // namespace lambdaspincorrevent -DECLARE_SOA_TABLE(LambdaSpinCorrEvents, "AOD", "LAMBDASPINCOREVENT", +} // namespace lambdaevent +DECLARE_SOA_TABLE(LambdaEvents, "AOD", "LAMBDAEVENT", o2::soa::Index<>, - lambdaspincorrevent::Cent, - lambdaspincorrevent::Posz) -using LambdaSpinCorrEvent = LambdaSpinCorrEvents::iterator; + lambdaevent::Cent, + lambdaevent::Posz) +using LambdaEvent = LambdaEvents::iterator; -namespace lambdaspincorrpair +namespace lambdapair { -DECLARE_SOA_INDEX_COLUMN(LambdaSpinCorrEvent, lambdaspincorrevent); -DECLARE_SOA_COLUMN(V0Status, v0Status, float); //! Lambda or Anti-Lambda status +DECLARE_SOA_INDEX_COLUMN(LambdaEvent, lambdaevent); +DECLARE_SOA_COLUMN(V0Status, v0Status, int); //! Lambda or Anti-Lambda status DECLARE_SOA_COLUMN(DoubleStatus, doubleStatus, bool); //! Double status DECLARE_SOA_COLUMN(V0Cospa, v0Cospa, float); //! V0 Cospa DECLARE_SOA_COLUMN(V0Radius, v0Radius, float); //! V0 Radius @@ -58,27 +58,27 @@ DECLARE_SOA_COLUMN(ProtonEta, protonEta, float); //! Proton Et DECLARE_SOA_COLUMN(ProtonPhi, protonPhi, float); //! Proton Phi DECLARE_SOA_COLUMN(ProtonIndex, protonIndex, int); //! Proton index DECLARE_SOA_COLUMN(PionIndex, pionIndex, int); //! Pion index -} // namespace lambdaspincorrpair -DECLARE_SOA_TABLE(LambdaSpinCorrPairs, "AOD", "LAMBDAPAIR", +} // namespace lambdapair +DECLARE_SOA_TABLE(LambdaPairs, "AOD", "LAMBDAPAIR", o2::soa::Index<>, - lambdaspincorrpair::LambdaSpinCorrEventId, - lambdaspincorrpair::V0Status, - lambdaspincorrpair::DoubleStatus, - lambdaspincorrpair::V0Cospa, - lambdaspincorrpair::V0Radius, - lambdaspincorrpair::DcaPositive, - lambdaspincorrpair::DcaNegative, - lambdaspincorrpair::DcaBetweenDaughter, - lambdaspincorrpair::LambdaPt, - lambdaspincorrpair::LambdaEta, - lambdaspincorrpair::LambdaPhi, - lambdaspincorrpair::LambdaMass, - lambdaspincorrpair::ProtonPt, - lambdaspincorrpair::ProtonEta, - lambdaspincorrpair::ProtonPhi, - lambdaspincorrpair::ProtonIndex, - lambdaspincorrpair::PionIndex); + lambdapair::LambdaEventId, + lambdapair::V0Status, + lambdapair::DoubleStatus, + lambdapair::V0Cospa, + lambdapair::V0Radius, + lambdapair::DcaPositive, + lambdapair::DcaNegative, + lambdapair::DcaBetweenDaughter, + lambdapair::LambdaPt, + lambdapair::LambdaEta, + lambdapair::LambdaPhi, + lambdapair::LambdaMass, + lambdapair::ProtonPt, + lambdapair::ProtonEta, + lambdapair::ProtonPhi, + lambdapair::ProtonIndex, + lambdapair::PionIndex); -using LambdaSpinCorrPair = LambdaSpinCorrPairs::iterator; +using LambdaPair = LambdaPairs::iterator; } // namespace o2::aod #endif // PWGLF_DATAMODEL_LFSPINCORRELATIONTABLES_H_ diff --git a/PWGLF/TableProducer/Strangeness/lambdaspincorrelation.cxx b/PWGLF/TableProducer/Strangeness/lambdaspincorrelation.cxx index 7f60348230e..2cce0f69568 100644 --- a/PWGLF/TableProducer/Strangeness/lambdaspincorrelation.cxx +++ b/PWGLF/TableProducer/Strangeness/lambdaspincorrelation.cxx @@ -58,8 +58,8 @@ using namespace o2::aod::rctsel; struct lambdaspincorrelation { - Produces spinCorrEvent; - Produces spinCorrPair; + Produces lambdaEvent; + Produces lambdaPair; Service ccdb; @@ -246,22 +246,24 @@ struct lambdaspincorrelation { void processData(EventCandidates::iterator const& collision, AllTrackCandidates const&, ResoV0s const& V0s) { + 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; // LOGF(info, "event collisions: (%d)", collision.index()); auto centrality = collision.centFT0C(); + auto vz = collision.posZ(); int occupancy = collision.trackOccupancyInTimeRange(); histos.fill(HIST("hEvtSelInfo"), 0.5); if ((rctCut.requireRCTFlagChecker && rctChecker(collision)) && collision.selection_bit(aod::evsel::kNoSameBunchPileup) && collision.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV) && collision.selection_bit(aod::evsel::kNoTimeFrameBorder) && collision.selection_bit(aod::evsel::kNoITSROFrameBorder) && collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard) && collision.sel8() && collision.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll) && occupancy < cfgCutOccupancy) { histos.fill(HIST("hEvtSelInfo"), 1.5); - 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 = {}; for (const auto& v0 : V0s) { // LOGF(info, "v0 index 0 : (%d)", v0.index()); auto [lambdaTag, aLambdaTag, isValid] = getLambdaTags(v0, collision); @@ -320,19 +322,20 @@ struct lambdaspincorrelation { pionDaughter.push_back(pion); histos.fill(HIST("hLambdaMass"), lambda.M()); } + numbV0 = numbV0 + 1; } } - if (v0Status.size() > 1) { + if (numbV0 > 1 && v0Cospa.size() > 1) { histos.fill(HIST("hEvtSelInfo"), 2.5); - spinCorrEvent(centrality, collision.posZ()); - auto indexEvent = spinCorrEvent.lastIndex(); + lambdaEvent(centrality, vz); + auto indexEvent = lambdaEvent.lastIndex(); //// Fill track table for V0////////////////// 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); - spinCorrPair(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)); + lambdaPair(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)); } } } From bbf53d018b15844dffe53c7b52b30f0996f4bc82 Mon Sep 17 00:00:00 2001 From: Daiki Sekihata Date: Fri, 20 Jun 2025 07:36:51 +0200 Subject: [PATCH 156/871] [PWGEM/Dilepton] upadte ITSsa (#11695) --- .../TableProducer/skimmerPrimaryElectron.cxx | 221 ++++++++++++------ .../skimmerPrimaryElectronFromDalitzEE.cxx | 138 ++++++++--- 2 files changed, 253 insertions(+), 106 deletions(-) diff --git a/PWGEM/Dilepton/TableProducer/skimmerPrimaryElectron.cxx b/PWGEM/Dilepton/TableProducer/skimmerPrimaryElectron.cxx index ad5976b9850..cbf66569224 100644 --- a/PWGEM/Dilepton/TableProducer/skimmerPrimaryElectron.cxx +++ b/PWGEM/Dilepton/TableProducer/skimmerPrimaryElectron.cxx @@ -50,7 +50,7 @@ using namespace o2::constants::physics; using MyCollisions = soa::Join; using MyCollisionsWithSWT = soa::Join; -using MyTracks = soa::Join; using MyTrack = MyTracks::iterator; @@ -81,7 +81,8 @@ struct skimmerPrimaryElectron { Configurable min_ncluster_itsib{"min_ncluster_itsib", 1, "min ncluster itsib"}; Configurable maxchi2tpc{"maxchi2tpc", 5.0, "max. chi2/NclsTPC"}; Configurable maxchi2its{"maxchi2its", 6.0, "max. chi2/NclsITS"}; - Configurable minpt{"minpt", 0.15, "min pt for track"}; + Configurable minpt_itstpc{"minpt_itstpc", 0.1, "min pt for ITS-TPC track"}; + Configurable minpt_itssa{"minpt_itssa", 0.05, "min pt for ITSsa track"}; Configurable maxeta{"maxeta", 0.9, "eta acceptance"}; Configurable dca_xy_max{"dca_xy_max", 1.0, "max DCAxy in cm"}; Configurable dca_z_max{"dca_z_max", 1.0, "max DCAz in cm"}; @@ -99,6 +100,9 @@ struct skimmerPrimaryElectron { 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 Configurable max_pin_for_pion_rejection{"max_pin_for_pion_rejection", 0.5, "pion rejection is applied below this pin"}; Configurable max_frac_shared_clusters_tpc{"max_frac_shared_clusters_tpc", 999.f, "max fraction of shared clusters in TPC"}; + Configurable includeITSsa{"includeITSsa", false, "Flag to include ITSsa tracks"}; + Configurable maxpt_itssa{"maxpt_itssa", 0.15, "max pt for ITSsa track"}; + Configurable maxMeanITSClusterSize{"maxMeanITSClusterSize", 16, "max x cos(lambda)"}; // configuration for PID ML Configurable usePIDML{"usePIDML", false, "Flag to use PID ML"}; @@ -166,7 +170,9 @@ struct skimmerPrimaryElectron { fRegistry.add("Track/hTOFNsigmaPi", "TOF n sigma pi;p_{in} (GeV/c);n #sigma_{#pi}^{TOF}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); fRegistry.add("Track/hTOFNsigmaKa", "TOF n sigma ka;p_{in} (GeV/c);n #sigma_{K}^{TOF}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); fRegistry.add("Track/hTOFNsigmaPr", "TOF n sigma pr;p_{in} (GeV/c);n #sigma_{p}^{TOF}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); - fRegistry.add("Track/hMeanClusterSizeITS", "mean cluster size ITS;p_{pv} (GeV/c); on ITS #times cos(#lambda)", kTH2F, {{1000, 0, 10}, {150, 0, 15}}, false); + fRegistry.add("Track/hMeanClusterSizeITS", "mean cluster size ITS;p_{pv} (GeV/c); #times cos(#lambda)", kTH2F, {{1000, 0, 10}, {150, 0, 15}}, false); + fRegistry.add("Track/hMeanClusterSizeITSib", "mean cluster size ITSib;p_{pv} (GeV/c); #times cos(#lambda)", kTH2F, {{1000, 0, 10}, {150, 0, 15}}, false); + fRegistry.add("Track/hMeanClusterSizeITSob", "mean cluster size ITSob;p_{pv} (GeV/c); #times cos(#lambda)", kTH2F, {{1000, 0, 10}, {150, 0, 15}}, false); fRegistry.add("Track/hITSNsigmaEl", "ITS n sigma el;p_{pv} (GeV/c);n #sigma_{e}^{ITS}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); fRegistry.add("Track/hITSNsigmaMu", "ITS n sigma mu;p_{pv} (GeV/c);n #sigma_{#mu}^{ITS}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); fRegistry.add("Track/hITSNsigmaPi", "ITS n sigma pi;p_{pv} (GeV/c);n #sigma_{#pi}^{ITS}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); @@ -270,17 +276,13 @@ struct skimmerPrimaryElectron { return false; } - if (track.tpcChi2NCl() > maxchi2tpc) { + if (!track.hasITS()) { return false; } if (track.itsChi2NCl() > maxchi2its) { return false; } - - if (!track.hasITS() || !track.hasTPC()) { - return false; - } if (track.itsNCls() < min_ncluster_its) { return false; } @@ -288,24 +290,30 @@ struct skimmerPrimaryElectron { return false; } - if (track.tpcNClsFound() < min_ncluster_tpc) { + if (!includeITSsa && (!track.hasITS() || !track.hasTPC())) { return false; } - if (track.tpcNClsCrossedRows() < mincrossedrows) { - return false; - } + if (track.hasTPC()) { + if (track.tpcChi2NCl() > maxchi2tpc) { + return false; + } - if (track.tpcCrossedRowsOverFindableCls() < min_tpc_cr_findable_ratio) { - return false; - } + if (track.tpcNClsFound() < min_ncluster_tpc) { + return false; + } - if (track.tpcFractionSharedCls() > max_frac_shared_clusters_tpc) { - return false; - } + if (track.tpcNClsCrossedRows() < mincrossedrows) { + return false; + } - if (track.hasTOF() && (maxTOFNsigmaEl < std::fabs(track.tofNSigmaEl()))) { - return false; + if (track.tpcCrossedRowsOverFindableCls() < min_tpc_cr_findable_ratio) { + return false; + } + + if (track.tpcFractionSharedCls() > max_frac_shared_clusters_tpc) { + return false; + } } o2::dataformats::DCA mDcaInfoCov; @@ -324,10 +332,6 @@ struct skimmerPrimaryElectron { return false; } - if (track_par_cov_recalc.getPt() < minpt || std::fabs(track_par_cov_recalc.getEta()) > maxeta) { - return false; - } - float dca_3d = 999.f; float det = track_par_cov_recalc.getSigmaY2() * track_par_cov_recalc.getSigmaZ2() - track_par_cov_recalc.getSigmaZY() * track_par_cov_recalc.getSigmaZY(); if (det < 0) { @@ -340,12 +344,43 @@ struct skimmerPrimaryElectron { return false; } + if (std::fabs(track_par_cov_recalc.getEta()) > maxeta) { + return false; + } + + if ((track.hasITS() && track.hasTPC()) && track_par_cov_recalc.getPt() < minpt_itstpc) { + return false; + } + + if ((track.hasITS() && !track.hasTPC() && !track.hasTOF() && !track.hasTRD()) && (track_par_cov_recalc.getPt() < minpt_itssa || maxpt_itssa < track_par_cov_recalc.getPt())) { + return false; + } + + if (track.hasITS() && !track.hasTPC() && !track.hasTRD() && !track.hasTOF()) { + 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 (maxMeanITSClusterSize < static_cast(total_cluster_size) / static_cast(nl) * std::cos(std::atan(track_par_cov_recalc.getTgl()))) { + return false; + } + } + return true; } template bool isElectron(TCollision const& collision, TTrack const& track) { + if (includeITSsa && (track.hasITS() && !track.hasTPC() && !track.hasTRD() && !track.hasTOF())) { + return true; + } + if (usePIDML) { if (track.tpcNSigmaEl() < minTPCNsigmaEl || maxTPCNsigmaEl < track.tpcNSigmaEl()) { return false; @@ -418,6 +453,7 @@ struct skimmerPrimaryElectron { float pt_recalc = track_par_cov_recalc.getPt(); float eta_recalc = track_par_cov_recalc.getEta(); float phi_recalc = track_par_cov_recalc.getPhi(); + o2::math_utils::bringTo02Pi(phi_recalc); bool isAssociatedToMPC = collision.globalIndex() == track.collisionId(); @@ -451,16 +487,34 @@ struct skimmerPrimaryElectron { stored_trackIds.emplace_back(std::pair{collision.globalIndex(), track.globalIndex()}); if (fillQAHistogram) { - uint32_t itsClusterSizes = track.itsClusterSizes(); + // uint32_t itsClusterSizes = track.itsClusterSizes(); int total_cluster_size = 0, nl = 0; for (unsigned int layer = 0; layer < 7; layer++) { - int cluster_size_per_layer = (itsClusterSizes >> (layer * 4)) & 0xf; + 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; + } + fRegistry.fill(HIST("Track/hPt"), pt_recalc); fRegistry.fill(HIST("Track/hQoverPt"), track.sign() / pt_recalc); fRegistry.fill(HIST("Track/hEtaPhi"), phi_recalc, eta_recalc); @@ -484,26 +538,27 @@ struct skimmerPrimaryElectron { fRegistry.fill(HIST("Track/hTPCNsigmaPi"), track.tpcInnerParam(), track.tpcNSigmaPi()); fRegistry.fill(HIST("Track/hTPCNsigmaKa"), track.tpcInnerParam(), track.tpcNSigmaKa()); fRegistry.fill(HIST("Track/hTPCNsigmaPr"), track.tpcInnerParam(), track.tpcNSigmaPr()); - fRegistry.fill(HIST("Track/hTOFbeta"), track.p(), track.beta()); + fRegistry.fill(HIST("Track/hTOFbeta"), track_par_cov_recalc.getP(), track.beta()); fRegistry.fill(HIST("Track/hTOFNsigmaEl"), track.tpcInnerParam(), track.tofNSigmaEl()); fRegistry.fill(HIST("Track/hTOFNsigmaMu"), track.tpcInnerParam(), track.tofNSigmaMu()); fRegistry.fill(HIST("Track/hTOFNsigmaPi"), track.tpcInnerParam(), track.tofNSigmaPi()); fRegistry.fill(HIST("Track/hTOFNsigmaKa"), track.tpcInnerParam(), track.tofNSigmaKa()); fRegistry.fill(HIST("Track/hTOFNsigmaPr"), track.tpcInnerParam(), track.tofNSigmaPr()); - fRegistry.fill(HIST("Track/hMeanClusterSizeITS"), track.p(), static_cast(total_cluster_size) / static_cast(nl) * std::cos(std::atan(track.tgl()))); - fRegistry.fill(HIST("Track/hITSNsigmaEl"), track.p(), track.itsNSigmaEl()); - fRegistry.fill(HIST("Track/hITSNsigmaMu"), track.p(), track.itsNSigmaMu()); - fRegistry.fill(HIST("Track/hITSNsigmaPi"), track.p(), track.itsNSigmaPi()); - fRegistry.fill(HIST("Track/hITSNsigmaKa"), track.p(), track.itsNSigmaKa()); - fRegistry.fill(HIST("Track/hITSNsigmaPr"), track.p(), track.itsNSigmaPr()); + fRegistry.fill(HIST("Track/hMeanClusterSizeITS"), track_par_cov_recalc.getP(), static_cast(total_cluster_size) / static_cast(nl) * std::cos(std::atan(track_par_cov_recalc.getTgl()))); + fRegistry.fill(HIST("Track/hMeanClusterSizeITSib"), track_par_cov_recalc.getP(), static_cast(total_cluster_size_ib) / static_cast(nl_ib) * std::cos(std::atan(track_par_cov_recalc.getTgl()))); + fRegistry.fill(HIST("Track/hMeanClusterSizeITSob"), track_par_cov_recalc.getP(), static_cast(total_cluster_size_ob) / static_cast(nl_ob) * std::cos(std::atan(track_par_cov_recalc.getTgl()))); + fRegistry.fill(HIST("Track/hITSNsigmaEl"), track_par_cov_recalc.getP(), track.itsNSigmaEl()); + fRegistry.fill(HIST("Track/hITSNsigmaMu"), track_par_cov_recalc.getP(), track.itsNSigmaMu()); + fRegistry.fill(HIST("Track/hITSNsigmaPi"), track_par_cov_recalc.getP(), track.itsNSigmaPi()); + fRegistry.fill(HIST("Track/hITSNsigmaKa"), track_par_cov_recalc.getP(), track.itsNSigmaKa()); + fRegistry.fill(HIST("Track/hITSNsigmaPr"), track_par_cov_recalc.getP(), track.itsNSigmaPr()); } } } Preslice trackIndicesPerCollision = aod::track_association::collisionId; std::vector> stored_trackIds; - Filter trackFilter = o2::aod::track::pt > minpt&& nabs(o2::aod::track::eta) < maxeta&& o2::aod::track::tpcChi2NCl < maxchi2tpc&& o2::aod::track::itsChi2NCl < maxchi2its&& ncheckbit(aod::track::v001::detectorMap, (uint8_t)o2::aod::track::ITS) == true && ncheckbit(aod::track::v001::detectorMap, (uint8_t)o2::aod::track::TPC) == true; - Filter pidFilter = minTPCNsigmaEl < o2::aod::pidtpc::tpcNSigmaEl && o2::aod::pidtpc::tpcNSigmaEl < maxTPCNsigmaEl; + Filter trackFilter = o2::aod::track::pt > minpt_itssa&& nabs(o2::aod::track::eta) < maxeta&& o2::aod::track::itsChi2NCl < maxchi2its&& ncheckbit(aod::track::v001::detectorMap, (uint8_t)o2::aod::track::ITS) == true; using MyFilteredTracks = soa::Filtered; Partition posTracks = o2::aod::track::signed1Pt > 0.f; @@ -724,7 +779,8 @@ struct prefilterPrimaryElectron { Configurable fillQAHistogram{"fillQAHistogram", false, "flag to fill QA histograms"}; Configurable max_dcaxy{"max_dcaxy", 0.3, "DCAxy To PV for loose track sample"}; Configurable max_dcaz{"max_dcaz", 0.3, "DCAz To PV for loose track sample"}; - Configurable minpt{"minpt", 0.1, "min pt for track for loose track sample"}; + Configurable minpt_itstpc{"minpt_itstpc", 0.1, "min pt for ITS-TPC track"}; + Configurable minpt_itssa{"minpt_itssa", 0.05, "min pt for ITSsa track"}; Configurable maxeta{"maxeta", 1.2, "eta acceptance for loose track sample"}; Configurable min_ncluster_tpc{"min_ncluster_tpc", 0, "min ncluster tpc"}; Configurable mincrossedrows{"mincrossedrows", 70, "min crossed rows"}; @@ -738,6 +794,9 @@ struct prefilterPrimaryElectron { Configurable maxTPCNsigmaEl{"maxTPCNsigmaEl", 3.0, "max. TPC n sigma for electron inclusion"}; Configurable slope{"slope", 0.0185, "slope for m vs. phiv"}; Configurable intercept{"intercept", -0.0280, "intercept for m vs. phiv"}; + Configurable includeITSsa{"includeITSsa", false, "Flag to include ITSsa tracks"}; + Configurable maxpt_itssa{"maxpt_itssa", 0.15, "mix pt for ITSsa track"}; + Configurable maxMeanITSClusterSize{"maxMeanITSClusterSize", 16, "max x cos(lambda)"}; Configurable> max_mee_vec{"max_mee_vec", std::vector{0.06, 0.08, 0.10}, "vector fo max mee for prefilter in ULS. Please sort this by increasing order."}; // currently, 3 thoresholds are allowed. @@ -852,26 +911,29 @@ struct prefilterPrimaryElectron { return false; } - if (!track.hasTPC()) { - return false; - } - if (track.tpcNSigmaEl() < minTPCNsigmaEl || maxTPCNsigmaEl < track.tpcNSigmaEl()) { - return false; - } - if (track.tpcNClsFound() < min_ncluster_tpc) { - return false; - } - if (track.tpcNClsCrossedRows() < mincrossedrows) { - return false; - } - if (track.tpcCrossedRowsOverFindableCls() < min_tpc_cr_findable_ratio) { - return false; - } - if (track.tpcFractionSharedCls() > max_frac_shared_clusters_tpc) { + if (!includeITSsa && (!track.hasITS() || !track.hasTPC())) { return false; } - if (track.tpcChi2NCl() > maxchi2its) { - return false; + + if (track.hasTPC()) { + if (track.tpcNSigmaEl() < minTPCNsigmaEl || maxTPCNsigmaEl < track.tpcNSigmaEl()) { + return false; + } + if (track.tpcNClsFound() < min_ncluster_tpc) { + return false; + } + if (track.tpcNClsCrossedRows() < mincrossedrows) { + return false; + } + if (track.tpcCrossedRowsOverFindableCls() < min_tpc_cr_findable_ratio) { + return false; + } + if (track.tpcFractionSharedCls() > max_frac_shared_clusters_tpc) { + return false; + } + if (track.tpcChi2NCl() > maxchi2tpc) { + return false; + } } o2::dataformats::DCA mDcaInfoCov; @@ -888,10 +950,33 @@ struct prefilterPrimaryElectron { return false; } - if (track_par_cov_recalc.getPt() < minpt || std::fabs(track_par_cov_recalc.getEta()) > maxeta) { + if (std::fabs(track_par_cov_recalc.getEta()) > maxeta) { return false; } + if ((track.hasITS() && track.hasTPC()) && track_par_cov_recalc.getPt() < minpt_itstpc) { + return false; + } + + if ((track.hasITS() && !track.hasTPC() && !track.hasTOF() && !track.hasTRD()) && (track_par_cov_recalc.getPt() < minpt_itssa || maxpt_itssa < track_par_cov_recalc.getPt())) { + return false; + } + + if (track.hasITS() && !track.hasTPC() && !track.hasTOF() && !track.hasTRD()) { + 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 (maxMeanITSClusterSize < static_cast(total_cluster_size) / static_cast(nl) * std::cos(std::atan(track_par_cov_recalc.getTgl()))) { + return false; + } + } + return true; } @@ -936,7 +1021,7 @@ struct prefilterPrimaryElectron { Preslice trackIndicesPerCollision = aod::track_association::collisionId; - Filter trackFilter = o2::aod::track::pt > minpt&& nabs(o2::aod::track::eta) < maxeta&& ncheckbit(aod::track::v001::detectorMap, (uint8_t)o2::aod::track::ITS) == true && ncheckbit(aod::track::v001::detectorMap, (uint8_t)o2::aod::track::TPC) == true; + Filter trackFilter = o2::aod::track::pt > minpt_itssa&& nabs(o2::aod::track::eta) < maxeta&& o2::aod::track::itsChi2NCl < maxchi2its&& ncheckbit(aod::track::v001::detectorMap, (uint8_t)o2::aod::track::ITS) == true; using MyFilteredTracks = soa::Filtered; Partition posTracks = o2::aod::track::signed1Pt > 0.f; Partition negTracks = o2::aod::track::signed1Pt < 0.f; @@ -981,9 +1066,9 @@ struct prefilterPrimaryElectron { } for (const auto& ele : negTracks_per_coll) { - if (!checkTrack(collision, ele)) { - continue; - } + // if (!checkTrack(collision, ele)) { + // continue; + // } o2::dataformats::DCA mDcaInfoCov; mDcaInfoCov.set(999, 999, 999, 999, 999); std::array pVec_recalc = {0, 0, 0}; // px, py, pz @@ -1026,9 +1111,9 @@ struct prefilterPrimaryElectron { } // end of loose electron loop for (const auto& pos : posTracks_per_coll) { - if (!checkTrack(collision, pos)) { // track cut is applied to loose sample - continue; - } + // if (!checkTrack(collision, pos)) { // track cut is applied to loose sample + // continue; + // } o2::dataformats::DCA mDcaInfoCov; mDcaInfoCov.set(999, 999, 999, 999, 999); std::array pVec_recalc = {0, 0, 0}; // px, py, pz @@ -1069,9 +1154,9 @@ struct prefilterPrimaryElectron { } // end of loose positon loop for (const auto& pos : posTracks_per_coll) { - if (!checkTrack(collision, pos)) { // track cut is applied to loose sample - continue; - } + // if (!checkTrack(collision, pos)) { // track cut is applied to loose sample + // continue; + // } o2::dataformats::DCA mDcaInfoCov; mDcaInfoCov.set(999, 999, 999, 999, 999); std::array pVec_recalc = {0, 0, 0}; // px, py, pz @@ -1098,9 +1183,9 @@ struct prefilterPrimaryElectron { } // end of loose positon loop for (const auto& ele : negTracks_per_coll) { - if (!checkTrack(collision, ele)) { - continue; - } + // if (!checkTrack(collision, ele)) { + // continue; + // } o2::dataformats::DCA mDcaInfoCov; mDcaInfoCov.set(999, 999, 999, 999, 999); std::array pVec_recalc = {0, 0, 0}; // px, py, pz diff --git a/PWGEM/PhotonMeson/TableProducer/skimmerPrimaryElectronFromDalitzEE.cxx b/PWGEM/PhotonMeson/TableProducer/skimmerPrimaryElectronFromDalitzEE.cxx index 7f840cb179c..91b22a88100 100644 --- a/PWGEM/PhotonMeson/TableProducer/skimmerPrimaryElectronFromDalitzEE.cxx +++ b/PWGEM/PhotonMeson/TableProducer/skimmerPrimaryElectronFromDalitzEE.cxx @@ -12,25 +12,28 @@ /// \brief write relevant information about primary electrons. /// \author daiki.sekihata@cern.ch -#include -#include -#include -#include +#include "PWGEM/Dilepton/Utils/PairUtilities.h" +#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" +#include "PWGEM/PhotonMeson/Utils/TrackSelection.h" -#include "Math/Vector4D.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "DetectorsBase/Propagator.h" -#include "DetectorsBase/GeometryManager.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "CCDB/BasicCCDBManager.h" #include "Common/Core/trackUtilities.h" + +#include "CCDB/BasicCCDBManager.h" #include "CommonConstants/PhysicsConstants.h" -#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" -#include "PWGEM/PhotonMeson/Utils/TrackSelection.h" -#include "PWGEM/Dilepton/Utils/PairUtilities.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "DataFormatsParameters/GRPObject.h" +#include "DetectorsBase/GeometryManager.h" +#include "DetectorsBase/Propagator.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" + +#include "Math/Vector4D.h" + +#include +#include +#include +#include using namespace o2; using namespace o2::soa; @@ -67,7 +70,8 @@ struct skimmerPrimaryElectronFromDalitzEE { Configurable min_ncluster_itsib{"min_ncluster_itsib", 1, "min ncluster itsib"}; Configurable maxchi2tpc{"maxchi2tpc", 5.0, "max. chi2/NclsTPC"}; Configurable maxchi2its{"maxchi2its", 6.0, "max. chi2/NclsITS"}; - Configurable minpt{"minpt", 0.05, "min pt for track"}; + Configurable minpt_itstpc{"minpt_itstpc", 0.05, "min pt for ITS-TPC track"}; + Configurable minpt_itssa{"minpt_itssa", 0.05, "min pt for ITSsa track"}; Configurable maxeta{"maxeta", 2.0, "max eta acceptance"}; Configurable dca_xy_max{"dca_xy_max", 1, "max DCAxy in cm"}; Configurable dca_z_max{"dca_z_max", 1, "max DCAz in cm"}; @@ -80,6 +84,9 @@ struct skimmerPrimaryElectronFromDalitzEE { Configurable maxTOFNsigmaEl{"maxTOFNsigmaEl", +3.5, "max. TOF n sigma for electron inclusion"}; Configurable maxMee{"maxMee", 0.04, "max. mee to store dalitz ee pairs"}; Configurable fillLS{"fillLS", true, "flag to fill LS histograms for QA"}; + Configurable includeITSsa{"includeITSsa", false, "Flag to include ITSsa tracks"}; + Configurable maxpt_itssa{"maxpt_itssa", 0.15, "max pt for ITSsa track"}; + Configurable maxMeanITSClusterSize{"maxMeanITSClusterSize", 16, "max x cos(lambda)"}; HistogramRegistry fRegistry{"output", {}, OutputObjHandlingPolicy::AnalysisObject, false, false}; static constexpr std::string_view dileptonSigns[3] = {"uls/", "lspp/", "lsmm/"}; @@ -125,7 +132,9 @@ struct skimmerPrimaryElectronFromDalitzEE { fRegistry.add("Track/hNclsITS", "number of ITS clusters", kTH1F, {{8, -0.5, 7.5}}, false); fRegistry.add("Track/hChi2ITS", "chi2/number of ITS clusters", kTH1F, {{100, 0, 10}}, false); fRegistry.add("Track/hITSClusterMap", "ITS cluster map", kTH1F, {{128, -0.5, 127.5}}, false); - fRegistry.add("Track/hMeanClusterSizeITS", "mean cluster size ITS;p_{pv} (GeV/c); on ITS #times cos(#lambda)", kTH2F, {{1000, 0, 10}, {150, 0, 15}}, false); + fRegistry.add("Track/hMeanClusterSizeITS", "mean cluster size ITS;p_{pv} (GeV/c); #times cos(#lambda)", kTH2F, {{1000, 0, 10}, {150, 0, 15}}, false); + fRegistry.add("Track/hMeanClusterSizeITSib", "mean cluster size ITSib;p_{pv} (GeV/c); #times cos(#lambda)", kTH2F, {{1000, 0, 10}, {150, 0, 15}}, false); + fRegistry.add("Track/hMeanClusterSizeITSob", "mean cluster size ITSob;p_{pv} (GeV/c); #times cos(#lambda)", kTH2F, {{1000, 0, 10}, {150, 0, 15}}, false); // TOF fRegistry.add("Track/hChi2TOF", "chi2 of TOF", kTH1F, {{100, 0, 10}}, false); @@ -190,7 +199,7 @@ struct skimmerPrimaryElectronFromDalitzEE { } } - if (track.tpcChi2NCl() > maxchi2tpc) { + if (!track.hasITS()) { return false; } @@ -198,9 +207,6 @@ struct skimmerPrimaryElectronFromDalitzEE { return false; } - if (!track.hasITS() || !track.hasTPC()) { - return false; - } if (track.itsNCls() < min_ncluster_its) { return false; } @@ -208,20 +214,30 @@ struct skimmerPrimaryElectronFromDalitzEE { return false; } - if (track.tpcNClsFound() < min_ncluster_tpc) { + if (!includeITSsa && (!track.hasITS() || !track.hasTPC())) { return false; } - if (track.tpcNClsCrossedRows() < mincrossedrows) { - return false; - } + if (track.hasTPC()) { + if (track.tpcChi2NCl() > maxchi2tpc) { + return false; + } - if (track.tpcCrossedRowsOverFindableCls() < min_tpc_cr_findable_ratio) { - return false; - } + if (track.tpcNClsFound() < min_ncluster_tpc) { + return false; + } - if (track.tpcFractionSharedCls() > max_frac_shared_clusters_tpc) { - return false; + if (track.tpcNClsCrossedRows() < mincrossedrows) { + return false; + } + + if (track.tpcCrossedRowsOverFindableCls() < min_tpc_cr_findable_ratio) { + return false; + } + + if (track.tpcFractionSharedCls() > max_frac_shared_clusters_tpc) { + return false; + } } if (std::fabs(track.dcaXY()) > dca_xy_max || std::fabs(track.dcaZ()) > dca_z_max) { @@ -240,7 +256,13 @@ struct skimmerPrimaryElectronFromDalitzEE { return false; } - if (track.pt() < minpt || std::fabs(track.eta()) > maxeta) { + if (std::fabs(track.eta()) > maxeta) { + return false; + } + if ((track.hasITS() && track.hasTPC()) && track.pt() < minpt_itstpc) { + return false; + } + if ((track.hasITS() && !track.hasTPC() && !track.hasTRD() && !track.hasTOF()) && (track.pt() < minpt_itssa || maxpt_itssa < track.pt())) { return false; } @@ -250,6 +272,23 @@ struct skimmerPrimaryElectronFromDalitzEE { template bool isElectron(TTrack const& track) { + if (includeITSsa && (track.hasITS() && !track.hasTPC() && !track.hasTRD() && !track.hasTOF())) { + 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 (maxMeanITSClusterSize > static_cast(total_cluster_size) / static_cast(nl) * std::cos(std::atan(track.tgl()))) { + return true; + } else { + return false; + } + } + if (track.tpcNSigmaEl() < minTPCNsigmaEl || maxTPCNsigmaEl < track.tpcNSigmaEl()) { return false; } @@ -304,11 +343,35 @@ struct skimmerPrimaryElectronFromDalitzEE { fRegistry.fill(HIST("Track/hChi2ITS"), track.itsChi2NCl()); fRegistry.fill(HIST("Track/hITSClusterMap"), track.itsClusterMap()); - int nsize = 0; - for (int il = 0; il < 7; il++) { - nsize += track.itsClsSizeInLayer(il); + 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; } - fRegistry.fill(HIST("Track/hMeanClusterSizeITS"), track.p(), static_cast(nsize) / static_cast(track.itsNCls()) * std::cos(std::atan(track.tgl()))); + fRegistry.fill(HIST("Track/hMeanClusterSizeITS"), track.p(), static_cast(total_cluster_size) / static_cast(nl) * std::cos(std::atan(track.tgl()))); + fRegistry.fill(HIST("Track/hMeanClusterSizeITSib"), track.p(), static_cast(total_cluster_size_ib) / static_cast(nl_ib) * std::cos(std::atan(track.tgl()))); + fRegistry.fill(HIST("Track/hMeanClusterSizeITSob"), track.p(), static_cast(total_cluster_size_ob) / static_cast(nl_ob) * std::cos(std::atan(track.tgl()))); stored_trackIds.emplace_back(std::make_pair(collision.globalIndex(), track.globalIndex())); } @@ -359,8 +422,7 @@ struct skimmerPrimaryElectronFromDalitzEE { } std::vector> stored_trackIds; - Filter trackFilter = o2::aod::track::pt > minpt&& nabs(o2::aod::track::eta) < maxeta&& o2::aod::track::tpcChi2NCl < maxchi2tpc&& o2::aod::track::itsChi2NCl < maxchi2its&& ncheckbit(aod::track::v001::detectorMap, (uint8_t)o2::aod::track::ITS) == true && ncheckbit(aod::track::v001::detectorMap, (uint8_t)o2::aod::track::TPC) == true && nabs(o2::aod::track::dcaXY) < dca_xy_max&& nabs(o2::aod::track::dcaZ) < dca_z_max; - Filter pidFilter = minTPCNsigmaEl < o2::aod::pidtpc::tpcNSigmaEl && o2::aod::pidtpc::tpcNSigmaEl < maxTPCNsigmaEl; + Filter trackFilter = o2::aod::track::pt > minpt_itssa&& nabs(o2::aod::track::eta) < maxeta&& o2::aod::track::itsChi2NCl < maxchi2its&& ncheckbit(aod::track::v001::detectorMap, (uint8_t)o2::aod::track::ITS) == true && nabs(o2::aod::track::dcaXY) < dca_xy_max&& nabs(o2::aod::track::dcaZ) < dca_z_max; using MyFilteredTracks = soa::Filtered; Partition posTracks = o2::aod::track::signed1Pt > 0.f; Partition negTracks = o2::aod::track::signed1Pt < 0.f; From 85d0325a90437ba463a0f2d6abf6e0be261d5c67 Mon Sep 17 00:00:00 2001 From: SuJeong Ji <120470463+SuJeong-Ji@users.noreply.github.com> Date: Fri, 20 Jun 2025 15:45:42 +0900 Subject: [PATCH 157/871] [PWGLF,Tutorial] Upload k1analysismicro.cxx and fix typo (#11528) Co-authored-by: ALICE Action Bot --- PWGLF/DataModel/LFResonanceTables.h | 16 +- .../Resonances/resonanceInitializer.cxx | 8 +- .../Resonances/resonanceModuleInitializer.cxx | 8 +- PWGLF/Tasks/Resonances/CMakeLists.txt | 5 + .../Tasks/Resonances/doubleResonanceScan.cxx | 22 +- PWGLF/Tasks/Resonances/k1AnalysisMicro.cxx | 741 ++++++++++++++++++ PWGLF/Tasks/Resonances/xi1530Analysisqa.cxx | 18 +- .../PWGLF/Resonance/resonancesMicrotrack.cxx | 16 +- 8 files changed, 790 insertions(+), 44 deletions(-) create mode 100644 PWGLF/Tasks/Resonances/k1AnalysisMicro.cxx diff --git a/PWGLF/DataModel/LFResonanceTables.h b/PWGLF/DataModel/LFResonanceTables.h index 6d0b909a695..67e1fb013c5 100644 --- a/PWGLF/DataModel/LFResonanceTables.h +++ b/PWGLF/DataModel/LFResonanceTables.h @@ -332,7 +332,7 @@ DECLARE_SOA_DYNAMIC_COLUMN(Sign, sign, } // namespace resodaughter -namespace resodmciroaughter +namespace resomicrodaughter { // micro track for primary pion @@ -471,7 +471,7 @@ struct ResoMicroTrackSelFlag { }; DECLARE_SOA_DYNAMIC_COLUMN(Pt, pt, [](float px, float py) -> float { return RecoDecay::sqrtSumOfSquares(px, py); }); -} // namespace resodmciroaughter +} // namespace resomicrodaughter DECLARE_SOA_TABLE(ResoTracks, "AOD", "RESOTRACK", o2::soa::Index<>, @@ -525,13 +525,13 @@ DECLARE_SOA_TABLE(ResoMicroTracks, "AOD", "RESOMICROTRACK", resodaughter::Px, resodaughter::Py, resodaughter::Pz, - resodmciroaughter::PidNSigmaPiFlag, - resodmciroaughter::PidNSigmaKaFlag, - resodmciroaughter::PidNSigmaPrFlag, - resodmciroaughter::TrackSelectionFlags, + resomicrodaughter::PidNSigmaPiFlag, + resomicrodaughter::PidNSigmaKaFlag, + resomicrodaughter::PidNSigmaPrFlag, + resomicrodaughter::TrackSelectionFlags, resodaughter::TrackFlags, // Dynamic columns - resodmciroaughter::Pt, + resomicrodaughter::Pt, resodaughter::Eta, resodaughter::Phi, resodaughter::PassedITSRefit, @@ -540,7 +540,7 @@ DECLARE_SOA_TABLE(ResoMicroTracks, "AOD", "RESOMICROTRACK", resodaughter::IsGlobalTrack, resodaughter::IsPrimaryTrack, resodaughter::IsPVContributor, - resodmciroaughter::HasTOF, + resomicrodaughter::HasTOF, resodaughter::Sign); using ResoMicroTrack = ResoMicroTracks::iterator; diff --git a/PWGLF/TableProducer/Resonances/resonanceInitializer.cxx b/PWGLF/TableProducer/Resonances/resonanceInitializer.cxx index da010f6ea59..c318d1d57d9 100644 --- a/PWGLF/TableProducer/Resonances/resonanceInitializer.cxx +++ b/PWGLF/TableProducer/Resonances/resonanceInitializer.cxx @@ -654,7 +654,7 @@ struct ResonanceInitializer { continue; if (!filterMicroTrack(track)) continue; - o2::aod::resodmciroaughter::ResoMicroTrackSelFlag trackSelFlag(track.dcaXY(), track.dcaZ()); + o2::aod::resomicrodaughter::ResoMicroTrackSelFlag trackSelFlag(track.dcaXY(), track.dcaZ()); if (std::abs(track.dcaXY()) < (0.004 + (0.013 / track.pt()))) { trackSelFlag.setDCAxy0(); } @@ -673,9 +673,9 @@ struct ResonanceInitializer { track.px(), track.py(), track.pz(), - static_cast(o2::aod::resodmciroaughter::PidNSigma(std::abs(track.tpcNSigmaPi()), std::abs(track.tofNSigmaPi()), track.hasTOF())), - static_cast(o2::aod::resodmciroaughter::PidNSigma(std::abs(track.tpcNSigmaKa()), std::abs(track.tofNSigmaKa()), track.hasTOF())), - static_cast(o2::aod::resodmciroaughter::PidNSigma(std::abs(track.tpcNSigmaPr()), std::abs(track.tofNSigmaPr()), track.hasTOF())), + static_cast(o2::aod::resomicrodaughter::PidNSigma(std::abs(track.tpcNSigmaPi()), std::abs(track.tofNSigmaPi()), track.hasTOF())), + static_cast(o2::aod::resomicrodaughter::PidNSigma(std::abs(track.tpcNSigmaKa()), std::abs(track.tofNSigmaKa()), track.hasTOF())), + static_cast(o2::aod::resomicrodaughter::PidNSigma(std::abs(track.tpcNSigmaPr()), std::abs(track.tofNSigmaPr()), track.hasTOF())), static_cast(trackSelFlag), trackFlags); if (!cfgBypassTrackIndexFill) { diff --git a/PWGLF/TableProducer/Resonances/resonanceModuleInitializer.cxx b/PWGLF/TableProducer/Resonances/resonanceModuleInitializer.cxx index 5dc53b28509..54d2533b05a 100644 --- a/PWGLF/TableProducer/Resonances/resonanceModuleInitializer.cxx +++ b/PWGLF/TableProducer/Resonances/resonanceModuleInitializer.cxx @@ -817,7 +817,7 @@ struct ResonanceDaughterInitializer { for (auto const& track : tracks) { if (!filterMicroTrack(track)) continue; - o2::aod::resodmciroaughter::ResoMicroTrackSelFlag trackSelFlag(track.dcaXY(), track.dcaZ()); + o2::aod::resomicrodaughter::ResoMicroTrackSelFlag trackSelFlag(track.dcaXY(), track.dcaZ()); if (std::abs(track.dcaXY()) < (0.004 + (0.013 / track.pt()))) { trackSelFlag.setDCAxy0(); } @@ -836,9 +836,9 @@ struct ResonanceDaughterInitializer { track.px(), track.py(), track.pz(), - static_cast(o2::aod::resodmciroaughter::PidNSigma(std::abs(track.tpcNSigmaPi()), std::abs(track.tofNSigmaPi()), track.hasTOF())), - static_cast(o2::aod::resodmciroaughter::PidNSigma(std::abs(track.tpcNSigmaKa()), std::abs(track.tofNSigmaKa()), track.hasTOF())), - static_cast(o2::aod::resodmciroaughter::PidNSigma(std::abs(track.tpcNSigmaPr()), std::abs(track.tofNSigmaPr()), track.hasTOF())), + static_cast(o2::aod::resomicrodaughter::PidNSigma(std::abs(track.tpcNSigmaPi()), std::abs(track.tofNSigmaPi()), track.hasTOF())), + static_cast(o2::aod::resomicrodaughter::PidNSigma(std::abs(track.tpcNSigmaKa()), std::abs(track.tofNSigmaKa()), track.hasTOF())), + static_cast(o2::aod::resomicrodaughter::PidNSigma(std::abs(track.tpcNSigmaPr()), std::abs(track.tofNSigmaPr()), track.hasTOF())), static_cast(trackSelFlag), trackFlags); if (!cfgBypassTrackIndexFill) { diff --git a/PWGLF/Tasks/Resonances/CMakeLists.txt b/PWGLF/Tasks/Resonances/CMakeLists.txt index 4ba33fce401..23eb01caf39 100644 --- a/PWGLF/Tasks/Resonances/CMakeLists.txt +++ b/PWGLF/Tasks/Resonances/CMakeLists.txt @@ -54,6 +54,11 @@ o2physics_add_dpl_workflow(k1analysis PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(k1analysismicro + SOURCES k1AnalysisMicro.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(phianalysisrun3 SOURCES phianalysisrun3.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore diff --git a/PWGLF/Tasks/Resonances/doubleResonanceScan.cxx b/PWGLF/Tasks/Resonances/doubleResonanceScan.cxx index 5d8772ef7e9..4b67171c448 100644 --- a/PWGLF/Tasks/Resonances/doubleResonanceScan.cxx +++ b/PWGLF/Tasks/Resonances/doubleResonanceScan.cxx @@ -232,13 +232,13 @@ struct DoubleResonanceScan { if (std::abs(track.pt()) < cMinPtcut) return false; if (cUsePtDependentDCArCut) { - if (o2::aod::resodmciroaughter::ResoMicroTrackSelFlag::decodeDCAxy(track.trackSelectionFlags()) > -Epsilon) + if (o2::aod::resomicrodaughter::ResoMicroTrackSelFlag::decodeDCAxy(track.trackSelectionFlags()) > -Epsilon) return false; } else { - if (o2::aod::resodmciroaughter::ResoMicroTrackSelFlag::decodeDCAxy(track.trackSelectionFlags()) > cMaxDCArToPVcut - Epsilon) + if (o2::aod::resomicrodaughter::ResoMicroTrackSelFlag::decodeDCAxy(track.trackSelectionFlags()) > cMaxDCArToPVcut - Epsilon) return false; } - if (o2::aod::resodmciroaughter::ResoMicroTrackSelFlag::decodeDCAz(track.trackSelectionFlags()) > cMaxDCAzToPVcut - Epsilon) + if (o2::aod::resomicrodaughter::ResoMicroTrackSelFlag::decodeDCAz(track.trackSelectionFlags()) > cMaxDCAzToPVcut - Epsilon) return false; if (cfgPrimaryTrack && !track.isPrimaryTrack()) return false; @@ -268,11 +268,11 @@ struct DoubleResonanceScan { } else { switch (particleType) { case 0: // pion - return o2::aod::resodmciroaughter::PidNSigma::getTPCnSigma(candidate.pidNSigmaPiFlag()); + return o2::aod::resomicrodaughter::PidNSigma::getTPCnSigma(candidate.pidNSigmaPiFlag()); case 1: // kaon - return o2::aod::resodmciroaughter::PidNSigma::getTPCnSigma(candidate.pidNSigmaKaFlag()); + return o2::aod::resomicrodaughter::PidNSigma::getTPCnSigma(candidate.pidNSigmaKaFlag()); case 2: // proton - return o2::aod::resodmciroaughter::PidNSigma::getTPCnSigma(candidate.pidNSigmaPrFlag()); + return o2::aod::resomicrodaughter::PidNSigma::getTPCnSigma(candidate.pidNSigmaPrFlag()); default: return -999; } @@ -297,11 +297,11 @@ struct DoubleResonanceScan { } else { switch (particleType) { case 0: // pion - return candidate.hasTOF() ? o2::aod::resodmciroaughter::PidNSigma::getTOFnSigma(candidate.pidNSigmaPiFlag()) : -999; + return candidate.hasTOF() ? o2::aod::resomicrodaughter::PidNSigma::getTOFnSigma(candidate.pidNSigmaPiFlag()) : -999; case 1: // kaon - return candidate.hasTOF() ? o2::aod::resodmciroaughter::PidNSigma::getTOFnSigma(candidate.pidNSigmaKaFlag()) : -999; + return candidate.hasTOF() ? o2::aod::resomicrodaughter::PidNSigma::getTOFnSigma(candidate.pidNSigmaKaFlag()) : -999; case 2: // proton - return candidate.hasTOF() ? o2::aod::resodmciroaughter::PidNSigma::getTOFnSigma(candidate.pidNSigmaPrFlag()) : -999; + return candidate.hasTOF() ? o2::aod::resomicrodaughter::PidNSigma::getTOFnSigma(candidate.pidNSigmaPrFlag()) : -999; default: return -999; } @@ -338,8 +338,8 @@ struct DoubleResonanceScan { dcaXY = track.dcaXY(); dcaZ = track.dcaZ(); } else { - dcaXY = o2::aod::resodmciroaughter::ResoMicroTrackSelFlag::decodeDCAxy(track.trackSelectionFlags()); - dcaZ = o2::aod::resodmciroaughter::ResoMicroTrackSelFlag::decodeDCAz(track.trackSelectionFlags()); + dcaXY = o2::aod::resomicrodaughter::ResoMicroTrackSelFlag::decodeDCAxy(track.trackSelectionFlags()); + dcaZ = o2::aod::resomicrodaughter::ResoMicroTrackSelFlag::decodeDCAz(track.trackSelectionFlags()); } // FIXME: Apply better method switch (daughterIndex) { diff --git a/PWGLF/Tasks/Resonances/k1AnalysisMicro.cxx b/PWGLF/Tasks/Resonances/k1AnalysisMicro.cxx new file mode 100644 index 00000000000..35d6224da36 --- /dev/null +++ b/PWGLF/Tasks/Resonances/k1AnalysisMicro.cxx @@ -0,0 +1,741 @@ +// 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 k1AnalysisMicro.cxx +/// \brief Reconstruction of track-track decay resonance candidates +/// \author Su-Jeong Ji , Bong-Hwi Lim +/// + +#include +#include +#include // FIXME +#include // FIXME + +#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" +#include "Framework/AnalysisTask.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/runDataProcessing.h" +#include "PWGLF/DataModel/LFResonanceTables.h" +#include "DataFormatsParameters/GRPObject.h" +#include "CommonConstants/PhysicsConstants.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::soa; +using namespace o2::constants::physics; +using namespace o2::constants::math; +; + +struct K1AnalysisMicro { + enum BinAnti : unsigned int { + kNormal = 0, + kAnti, + kNAEnd + }; + enum BinType : unsigned int { + kK1P = 0, + kK1N, + kK1P_Mix, + kK1N_Mix, + kK1P_GenINEL10, + kK1N_GenINEL10, + kK1P_GenINELgt10, + kK1N_GenINELgt10, + kK1P_GenTrig10, + kK1N_GenTrig10, + kK1P_GenEvtSel, + kK1N_GenEvtSel, + kK1P_Rec, + kK1N_Rec, + kTYEnd + }; + SliceCache cache; + Preslice perRCol = aod::resodaughter::resoCollisionId; + Preslice perCollision = aod::track::collisionId; + HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + using ResoMCCols = soa::Join; + + //// Configurables + Configurable cNbinsDiv{"cNbinsDiv", 1, "Integer to divide the number of bins"}; + /// Event Mixing + Configurable nEvtMixing{"nEvtMixing", 5, "Number of events to mix"}; + 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"}; + ConfigurableAxis cfgMultBins{"cfgMultBins", {VARIABLE_WIDTH, 0.0f, 20.0f, 40.0f, 60.0f, 80.0f, 100.0f, 200.0f, 99999.f}, "Mixing bins - multiplicity"}; + /// Pre-selection cuts + Configurable cMinPtcut{"cMinPtcut", 0.15, "Track minium pt cut"}; + + /// DCA Selections + // DCAr to PV + Configurable cMaxDCArToPVcut{"cMaxDCArToPVcut", 0.1, "Track DCAr cut to PV Maximum"}; + // DCAz to PV + Configurable cMaxDCAzToPVcut{"cMaxDCAzToPVcut", 0.1, "Track DCAz cut to PV Maximum"}; + Configurable cMinDCAzToPVcut{"cMinDCAzToPVcut", 0.0, "Track DCAz cut to PV Minimum"}; + + /// PID Selections + Configurable cMaxTPCnSigmaPion{"cMaxTPCnSigmaPion", 3.0, "TPC nSigma cut for Pion"}; // TPC + Configurable cMaxTOFnSigmaPion{"cMaxTOFnSigmaPion", 3.0, "TOF nSigma cut for Pion"}; // TOF + Configurable nsigmaCutCombinedPion{"nsigmaCutCombinedPion", -999, "Combined nSigma cut for Pion"}; // Combined + Configurable cTOFVeto{"cTOFVeto", true, "TOF Veto, if false, TOF is nessessary for PID selection"}; // TOF Veto + Configurable cUseOnlyTOFTrackPi{"cUseOnlyTOFTrackPi", false, "Use only TOF track for PID selection"}; // Use only TOF track for Pion PID selection + // Kaon + Configurable cMaxTPCnSigmaKaon{"cMaxTPCnSigmaKaon", 3.0, "TPC nSigma cut for Kaon"}; // TPC + Configurable cMaxTOFnSigmaKaon{"cMaxTOFnSigmaKaon", 3.0, "TOF nSigma cut for Kaon"}; // TOF + Configurable nsigmaCutCombinedKaon{"nsigmaCutCombinedKaon", -999, "Combined nSigma cut for Kaon"}; // Combined + Configurable cUseOnlyTOFTrackKa{"cUseOnlyTOFTrackKa", false, "Use only TOF track for PID selection"}; // Use only TOF track for Kaon PID selection + // 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 additionalQAplots{"additionalQAplots", true, "Additional QA plots"}; + Configurable additionalEvsel{"additionalEvsel", true, "Additional event selcection"}; + Configurable cfgTPCcluster{"cfgTPCcluster", 0, "Number of TPC cluster"}; + Configurable cfgUseTPCRefit{"cfgUseTPCRefit", false, "Require TPC Refit"}; + Configurable cfgUseITSRefit{"cfgUseITSRefit", false, "Require ITS Refit"}; + Configurable cfgHasTOF{"cfgHasTOF", false, "Require TOF"}; + + // Secondary selection + Configurable cMinSecondaryPtCut{"cMinSecondaryPtCut", 0.5, "Min pT cut for secondary selection"}; + /* + Configurable cfgModeK892orRho{"cfgModeK892orRho", false, "Secondary scenario for K892 (true) or Rho (false)"}; + Configurable cSecondaryMasswindow{"cSecondaryMasswindow", 0.1, "Secondary inv mass selection window"}; + Configurable cMinAnotherSecondaryMassCut{"cMinAnotherSecondaryMassCut", 0, "Min inv. mass selection of another secondary scenario"}; + Configurable cMaxAnotherSecondaryMassCut{"cMaxAnotherSecondaryMassCut", 999, "MAx inv. mass selection of another secondary scenario"}; + Configurable cMinPiKaMassCut{"cMinPiKaMassCut", 0, "bPion-Kaon pair inv mass selection minimum"}; + Configurable cMaxPiKaMassCut{"cMaxPiKaMassCut", 999, "bPion-Kaon pair inv mass selection maximum"}; + Configurable cMinAngle{"cMinAngle", 0, "Minimum angle between K(892)0 and bachelor pion"}; + Configurable cMaxAngle{"cMaxAngle", 4, "Maximum angle between K(892)0 and bachelor pion"}; + Configurable cMinPairAsym{"cMinPairAsym", -1, "Minimum pair asymmetry"}; + Configurable cMaxPairAsym{"cMaxPairAsym", 1, "Maximum pair asymmetry"}; +*/ + + // K1 selection + Configurable cK1MaxRap{"cK1MaxRap", 0.5, "K1 maximum rapidity"}; + Configurable cK1MinRap{"cK1MinRap", -0.5, "K1 minimum rapidity"}; + + void init(o2::framework::InitContext&) + { + std::vector centBinning = {0., 1., 5., 10., 15., 20., 25., 30., 35., 40., 45., 50., 55., 60., 65., 70., 80., 90., 100., 200.}; + AxisSpec centAxis = {centBinning, "T0M (%)"}; + AxisSpec ptAxis = {150, 0, 15, "#it{p}_{T} (GeV/#it{c})"}; + AxisSpec dcaxyAxis = {300, 0, 3, "DCA_{#it{xy}} (cm)"}; + AxisSpec dcazAxis = {500, 0, 5, "DCA_{#it{z}} (cm)"}; + AxisSpec invMassAxisK892 = {1400 / cNbinsDiv, 0.6, 2.0, "Invariant Mass (GeV/#it{c}^2)"}; // K(892)0 + AxisSpec invMassAxisRho = {2000 / cNbinsDiv, 0.0, 2.0, "Invariant Mass (GeV/#it{c}^2)"}; // rho + AxisSpec invMassAxisReso = {1600 / cNbinsDiv, 0.9f, 2.5f, "Invariant Mass (GeV/#it{c}^2)"}; // K1 + AxisSpec invMassAxisScan = {250, 0, 2.5, "Invariant Mass (GeV/#it{c}^2)"}; // For selection + AxisSpec pidQAAxis = {130, -6.5, 6.5}; + AxisSpec dataTypeAxis = {9, 0, 9, "Histogram types"}; + AxisSpec mcTypeAxis = {4, 0, 4, "Histogram types"}; + + // THnSparse + AxisSpec axisAnti = {BinAnti::kNAEnd, 0, BinAnti::kNAEnd, "Type of bin: Normal or Anti"}; + AxisSpec axisType = {BinType::kTYEnd, 0, BinType::kTYEnd, "Type of bin with charge and mix"}; + AxisSpec mcLabelAxis = {5, -0.5, 4.5, "MC Label"}; + + // DCA QA + // Primary pion + histos.add("QA/trkppionDCAxy", "DCAxy disstribution of primary pion candidates", HistType::kTH1F, {dcaxyAxis}); + histos.add("QA/trkppionDCAz", "DCAz disstribution of primary pion candidates", HistType::kTH1F, {dcazAxis}); + histos.add("QA/trkppionpT", "pT distribution of primary pion candidates", HistType::kTH1F, {ptAxis}); + histos.add("QA/trkppionTPCPID", "TPC PID of primary pion candidates", HistType::kTH2F, {ptAxis, pidQAAxis}); + histos.add("QA/trkppionTOFPID", "TOF PID of primary pion candidates", HistType::kTH2F, {ptAxis, pidQAAxis}); + histos.add("QA/trkppionTPCTOFPID", "TPC-TOF PID map of primary pion candidates", HistType::kTH2F, {pidQAAxis, pidQAAxis}); + + histos.add("QAcut/trkppionDCAxy", "DCAxy distribution of primary pion candidates", HistType::kTH1F, {dcaxyAxis}); + histos.add("QAcut/trkppionDCAz", "DCAz distribution of primary pion candidates", HistType::kTH1F, {dcazAxis}); + histos.add("QAcut/trkppionpT", "pT distribution of primary pion candidates", HistType::kTH1F, {ptAxis}); + histos.add("QAcut/trkppionTPCPID", "TPC PID of primary pion candidates", HistType::kTH2F, {ptAxis, pidQAAxis}); + histos.add("QAcut/trkppionTOFPID", "TOF PID of primary pion candidates", HistType::kTH2F, {ptAxis, pidQAAxis}); + histos.add("QAcut/trkppionTPCTOFPID", "TPC-TOF PID map of primary pion candidates", HistType::kTH2F, {pidQAAxis, pidQAAxis}); + + // Secondary pion + histos.add("QA/trkspionDCAxy", "DCAxy distribution of secondary pion candidates", HistType::kTH1F, {dcaxyAxis}); + histos.add("QA/trkspionDCAz", "DCAz distribution of secondary pion candidates", HistType::kTH1F, {dcazAxis}); + histos.add("QA/trkspionpT", "pT distribution of secondary pion candidates", HistType::kTH1F, {ptAxis}); + histos.add("QA/trkspionTPCPID", "TPC PID of secondary pion candidates", HistType::kTH2F, {ptAxis, pidQAAxis}); + histos.add("QA/trkspionTOFPID", "TOF PID of secondary pion candidates", HistType::kTH2F, {ptAxis, pidQAAxis}); + histos.add("QA/trkspionTPCTOFPID", "TPC-TOF PID map of secondary pion candidates", HistType::kTH2F, {pidQAAxis, pidQAAxis}); + + histos.add("QAcut/trkspionDCAxy", "DCAxy distribution of secondary pion candidates", HistType::kTH1F, {dcaxyAxis}); + histos.add("QAcut/trkspionDCAz", "DCAz distribution of secondary pion candidates", HistType::kTH1F, {dcazAxis}); + histos.add("QAcut/trkspionpT", "pT distribution of secondary pion candidates", HistType::kTH1F, {ptAxis}); + histos.add("QAcut/trkspionTPCPID", "TPC PID of secondary pion candidates", HistType::kTH2F, {ptAxis, pidQAAxis}); + histos.add("QAcut/trkspionTOFPID", "TOF PID of secondary pion candidates", HistType::kTH2F, {ptAxis, pidQAAxis}); + histos.add("QAcut/trkspionTPCTOFPID", "TPC-TOF PID map of secondary pion candidates", HistType::kTH2F, {pidQAAxis, pidQAAxis}); + + // Kaon + histos.add("QA/trkkaonDCAxy", "DCAxy distribution of kaon candidates", HistType::kTH1F, {dcaxyAxis}); + histos.add("QA/trkkaonDCAz", "DCAz distribution of kaon candidates", HistType::kTH1F, {dcazAxis}); + histos.add("QA/trkkaonpT", "pT distribution of kaon candidates", HistType::kTH1F, {ptAxis}); + histos.add("QA/trkkaonTPCPID", "TPC PID of kaon candidates", HistType::kTH2F, {ptAxis, pidQAAxis}); + histos.add("QA/trkkaonTOFPID", "TOF PID of kaon candidates", HistType::kTH2F, {ptAxis, pidQAAxis}); + histos.add("QA/trkkaonTPCTOFPID", "TPC-TOF PID map of kaon candidates", HistType::kTH2F, {pidQAAxis, pidQAAxis}); + + histos.add("QAcut/trkkaonDCAxy", "DCAxy distribution of kaon candidates", HistType::kTH1F, {dcaxyAxis}); + histos.add("QAcut/trkkaonDCAz", "DCAz distribution of kaon candidates", HistType::kTH1F, {dcazAxis}); + histos.add("QAcut/trkkaonpT", "pT distribution of kaon candidates", HistType::kTH1F, {ptAxis}); + histos.add("QAcut/trkkaonTPCPID", "TPC PID of kaon candidates", HistType::kTH2F, {ptAxis, pidQAAxis}); + histos.add("QAcut/trkkaonTOFPID", "TOF PID of kaon candidates", HistType::kTH2F, {ptAxis, pidQAAxis}); + histos.add("QAcut/trkkaonTPCTOFPID", "TPC-TOF PID map of kaon candidates", HistType::kTH2F, {pidQAAxis, pidQAAxis}); + + // K1 + histos.add("QA/K1OA", "Opening angle of K1(1270)", HistType::kTH1F, {AxisSpec{100, 0, 3.14, "Opening angle"}}); + histos.add("QA/K1PairAsym", "Pair asymmetry of K1(1270)", HistType::kTH1F, {AxisSpec{100, -1, 1, "Pair asymmetry"}}); + histos.add("QA/hInvmassK892_Rho", "Invariant mass of K(892)0 vs Rho(770)", HistType::kTH2F, {invMassAxisK892, invMassAxisRho}); + histos.add("QA/hInvmassSecon_PiKa", "Invariant mass of secondary resonance vs pion-kaon", HistType::kTH2F, {invMassAxisRho, invMassAxisK892}); + histos.add("QA/hInvmassSecon", "Invariant mass of secondary resonance", HistType::kTH1F, {invMassAxisRho}); + histos.add("QA/hpT_Secondary", "pT distribution of secondary resonance", HistType::kTH1F, {ptAxis}); + + histos.add("QAcut/K1OA", "Opening angle of K1(1270)", HistType::kTH1F, {AxisSpec{100, 0, 3.14, "Opening angle"}}); + histos.add("QAcut/K1PairAsym", "Pair asymmetry of K1(1270)", HistType::kTH1F, {AxisSpec{100, -1, 1, "Pair asymmetry"}}); + histos.add("QAcut/hInvmassK892_Rho", "Invariant mass of K(892)0 vs Rho(770)", HistType::kTH2F, {invMassAxisK892, invMassAxisRho}); + histos.add("QAcut/hInvmassSecon_PiKa", "Invariant mass of secondary resonance vs pion-kaon", HistType::kTH2F, {invMassAxisRho, invMassAxisK892}); + histos.add("QAcut/hInvmassSecon", "Invariant mass of secondary resonance", HistType::kTH1F, {invMassAxisRho}); + histos.add("QAcut/hpT_Secondary", "pT distribution of secondary resonance", HistType::kTH1F, {ptAxis}); + + // Invariant mass + histos.add("hInvmass_K1", "Invariant mass of K1(1270) (US)", HistType::kTHnSparseD, {axisAnti, axisType, centAxis, ptAxis, invMassAxisReso}); + histos.add("hInvmass_K1_LS", "Invariant mass of K1(1270) (LS)", HistType::kTHnSparseD, {axisAnti, axisType, centAxis, ptAxis, invMassAxisReso}); + histos.add("hInvmass_K1_Mix", "Invariant mass of K1(1270) (ME)", HistType::kTHnSparseD, {axisAnti, axisType, centAxis, ptAxis, invMassAxisReso}); + // Mass QA (quick check) + histos.add("k1invmass", "Invariant mass of K1(1270) (US)", HistType::kTH1F, {invMassAxisReso}); + histos.add("k1invmass_LS", "Invariant mass of K1(1270) (LS)", HistType::kTH1F, {invMassAxisReso}); + histos.add("k1invmass_Mix", "Invariant mass of K1(1270) (ME)", HistType::kTH1F, {invMassAxisReso}); + + // MC + if (doprocessMC) { + histos.add("k1invmass_MC", "Invariant mass of K1(1270)", HistType::kTH1F, {invMassAxisReso}); + histos.add("k1invmass_MC_noK1", "Invariant mass of K1(1270)", HistType::kTH1F, {invMassAxisReso}); + + histos.add("QAMC/trkppionDCAxy", "DCAxy distribution of primary pion candidates", HistType::kTH1F, {dcaxyAxis}); + histos.add("QAMC/trkppionDCAz", "DCAz distribution of primary pion candidates", HistType::kTH1F, {dcazAxis}); + histos.add("QAMC/trkppionpT", "pT distribution of primary pion candidates", HistType::kTH1F, {ptAxis}); + histos.add("QAMC/trkppionTPCPID", "TPC PID of primary pion candidates", HistType::kTH2F, {ptAxis, pidQAAxis}); + histos.add("QAMC/trkppionTOFPID", "TOF PID of primary pion candidates", HistType::kTH2F, {ptAxis, pidQAAxis}); + histos.add("QAMC/trkppionTPCTOFPID", "TPC-TOF PID map of primary pion candidates", HistType::kTH2F, {pidQAAxis, pidQAAxis}); + + histos.add("QAMC/trkspionDCAxy", "DCAxy distribution of secondary pion candidates", HistType::kTH1F, {dcaxyAxis}); + histos.add("QAMC/trkspionDCAz", "DCAz distribution of secondary pion candidates", HistType::kTH1F, {dcazAxis}); + histos.add("QAMC/trkspionpT", "pT distribution of secondary pion candidates", HistType::kTH1F, {ptAxis}); + histos.add("QAMC/trkspionTPCPID", "TPC PID of secondary pion candidates", HistType::kTH2F, {ptAxis, pidQAAxis}); + histos.add("QAMC/trkspionTOFPID", "TOF PID of secondary pion candidates", HistType::kTH2F, {ptAxis, pidQAAxis}); + histos.add("QAMC/trkspionTPCTOFPID", "TPC-TOF PID map of secondary pion candidates", HistType::kTH2F, {pidQAAxis, pidQAAxis}); + + histos.add("QAMC/trkkaonDCAxy", "DCAxy distribution of kaon candidates", HistType::kTH1F, {dcaxyAxis}); + histos.add("QAMC/trkkaonDCAz", "DCAz distribution of kaon candidates", HistType::kTH1F, {dcazAxis}); + histos.add("QAMC/trkkaonpT", "pT distribution of kaon candidates", HistType::kTH1F, {ptAxis}); + histos.add("QAMC/trkkaonTPCPID", "TPC PID of kaon candidates", HistType::kTH2F, {ptAxis, pidQAAxis}); + histos.add("QAMC/trkkaonTOFPID", "TOF PID of kaon candidates", HistType::kTH2F, {ptAxis, pidQAAxis}); + histos.add("QAMC/trkkaonTPCTOFPID", "TPC-TOF PID map of kaon candidates", HistType::kTH2F, {pidQAAxis, pidQAAxis}); + + histos.add("QAMC/K1OA", "Opening angle of K1(1270)", HistType::kTH1F, {AxisSpec{100, 0, 3.14, "Opening angle"}}); + histos.add("QAMC/K1PairAsym", "Pair asymmetry of K1(1270)", HistType::kTH1F, {AxisSpec{100, -1, 1, "Pair asymmetry"}}); + histos.add("QAMC/hInvmassK892_Rho", "Invariant mass of K(892)0 vs Rho(770)", HistType::kTH2F, {invMassAxisK892, invMassAxisRho}); + histos.add("QAMC/hInvmassSecon_PiKa", "Invariant mass of secondary resonance vs pion-kaon", HistType::kTH2F, {invMassAxisRho, invMassAxisK892}); + histos.add("QAMC/hInvmassSecon", "Invariant mass of secondary resonance", HistType::kTH1F, {invMassAxisRho}); + histos.add("QAMC/hpT_Secondary", "pT distribution of secondary resonance", HistType::kTH1F, {ptAxis}); + } // doprocessMC + // Print output histograms statistics + LOG(info) << "Size of the histograms in K1 Analysis Task"; + histos.print(); + } // init + + // PDG code + int kPDGRho770 = 113; + int kK1Plus = 10323; + + template + bool trackCut(const TrackType track) + { + if constexpr (!IsResoMicrotrack) { + // basic track cuts + if (std::abs(track.pt()) < cMinPtcut) + return false; + if (std::abs(track.dcaXY()) > cMaxDCArToPVcut) + return false; + if (std::abs(track.dcaZ()) > cMaxDCAzToPVcut) + return false; + if (track.tpcNClsFound() < cfgTPCcluster) + return false; + if (cfgHasTOF && !track.hasTOF()) + return false; + if (cfgUseITSRefit && !track.passedITSRefit()) + return false; + if (cfgUseTPCRefit && !track.passedTPCRefit()) + return false; + if (cfgPVContributor && !track.isPVContributor()) + return false; + if (cfgPrimaryTrack && !track.isPrimaryTrack()) + return false; + if (cfgGlobalWoDCATrack && !track.isGlobalTrackWoDCA()) + return false; + if (cfgGlobalTrack && !track.isGlobalTrack()) + return false; + } else { + if (std::abs(track.pt()) < cMinPtcut) + return false; + if (o2::aod::resomicrodaughter::ResoMicroTrackSelFlag::decodeDCAxy(track.trackSelectionFlags()) > cMaxDCArToPVcut - Epsilon) + return false; + if (o2::aod::resomicrodaughter::ResoMicroTrackSelFlag::decodeDCAz(track.trackSelectionFlags()) > cMaxDCAzToPVcut - Epsilon) + return false; + if (cfgPrimaryTrack && !track.isPrimaryTrack()) + return false; + if (cfgGlobalWoDCATrack && !track.isGlobalTrackWoDCA()) + return false; + if (cfgPVContributor && !track.isPVContributor()) + return false; + } + return true; + } + + // Pion PID selection tools + template + bool selectionPIDpion(const T& candidate) + { + if constexpr (!IsResoMicrotrack) { + bool tpcPIDPassed{false}, tofPIDPassed{false}; + if (std::abs(candidate.tpcNSigmaPi()) < cMaxTPCnSigmaPion) { + tpcPIDPassed = true; + } else { + return false; + } + if (candidate.hasTOF()) { + if (std::abs(candidate.tofNSigmaPi()) < cMaxTOFnSigmaPion) { + tofPIDPassed = true; + } + if ((nsigmaCutCombinedPion > 0) && (candidate.tpcNSigmaPi() * candidate.tpcNSigmaPi() + candidate.tofNSigmaPi() * candidate.tofNSigmaPi() < nsigmaCutCombinedPion * nsigmaCutCombinedPion)) { + tofPIDPassed = true; + } + } else { + if (!cTOFVeto) { + return false; + } + tofPIDPassed = true; + } + if (tpcPIDPassed && tofPIDPassed) { + return true; + } + } else { + bool tpcPIDPassed{false}, tofPIDPassed{false}; + tpcPIDPassed = std::abs(o2::aod::resomicrodaughter::PidNSigma::getTPCnSigma(candidate.pidNSigmaPiFlag())) < cMaxTPCnSigmaPion + Epsilon; + tofPIDPassed = candidate.hasTOF() ? std::abs(o2::aod::resomicrodaughter::PidNSigma::getTOFnSigma(candidate.pidNSigmaPiFlag())) < cMaxTOFnSigmaPion + Epsilon : true; + if (tpcPIDPassed && tofPIDPassed) { + return true; + } + } + return false; + } + + // Kaon PID selection tools + template + bool selectionPIDkaon(const T& candidate) + { + if constexpr (!IsResoMicrotrack) { + bool tpcPIDPassed{false}, tofPIDPassed{false}; + if (std::abs(candidate.tpcNSigmaKa()) < cMaxTPCnSigmaKaon) { + tpcPIDPassed = true; + } else { + return false; + } + if (candidate.hasTOF()) { + if (std::abs(candidate.tofNSigmaKa()) < cMaxTOFnSigmaKaon) { + tofPIDPassed = true; + } + if ((nsigmaCutCombinedKaon > 0) && (candidate.tpcNSigmaKa() * candidate.tpcNSigmaKa() + candidate.tofNSigmaKa() * candidate.tofNSigmaKa() < nsigmaCutCombinedKaon * nsigmaCutCombinedKaon)) { + tofPIDPassed = true; + } + } else { + if (!cTOFVeto) { + return false; + } + tofPIDPassed = true; + } + if (tpcPIDPassed && tofPIDPassed) { + return true; + } + } else { + bool tpcPIDPassed{false}, tofPIDPassed{false}; + tpcPIDPassed = std::abs(o2::aod::resomicrodaughter::PidNSigma::getTPCnSigma(candidate.pidNSigmaKaFlag())) < cMaxTPCnSigmaKaon + Epsilon; + tofPIDPassed = candidate.hasTOF() ? std::abs(o2::aod::resomicrodaughter::PidNSigma::getTOFnSigma(candidate.pidNSigmaKaFlag())) < cMaxTOFnSigmaKaon + Epsilon : true; + if (tpcPIDPassed && tofPIDPassed) { + return true; + } + } + return false; + } + + template + bool isTrueK1(const T& trk1, const T& trk2, const T2& bTrack) + { + if (std::abs(trk1.pdgCode()) != kPiPlus || std::abs(trk2.pdgCode()) != kPiPlus) + return false; + if (std::abs(bTrack.pdgCode()) != kKPlus) + return false; + auto mother1 = trk1.motherId(); + auto mother2 = trk2.motherId(); + if (mother1 != mother2) + return false; + if (((std::abs(trk1.motherPDG()) && std::abs(trk2.motherPDG()) != kPDGRho770) && (std::abs(bTrack.motherPDG()) != kK1Plus)) || (std::abs(trk1.motherPDG()) && std::abs(bTrack.motherPDG()) != kK0Star892 && (std::abs(trk2.motherPDG()) != kK1Plus)) || (std::abs(trk2.motherPDG()) && std::abs(bTrack.motherPDG()) != kK0Star892 && (std::abs(trk1.motherPDG()) != kK1Plus))) + return false; + auto siblings = bTrack.siblingIds(); + if (siblings[0] != mother1 && siblings[1] != mother2) + return false; + return true; + } // isTrueK1 + + template + bool isTrueK892(const T& trk1, const T& trk2) + { + if (std::abs(trk1.pdgCode()) != kPiPlus || std::abs(trk2.pdgCode()) != kKPlus) + return false; + auto mother1 = trk1.motherId(); + auto mother2 = trk2.motherId(); + if (mother1 != mother2) + return false; + if (std::abs(trk1.motherPDG()) != kK0Star892) + return false; + return true; + } + + template + bool isTrueRho(const T& trk1, const T& trk2) + { + if (std::abs(trk1.pdgCode()) != kPiPlus || std::abs(trk2.pdgCode()) != kPiPlus) + return false; + auto mother1 = trk1.motherId(); + auto mother2 = trk2.motherId(); + if (mother1 != mother2) + return false; + if (std::abs(trk1.motherPDG()) != kPDGRho770) + return false; + return true; + } + template + void fillHistograms(const CollisionType& collision, const TracksType& dTracks1, const TracksType& dTracks2) + { + auto multiplicity = collision.cent(); + TLorentzVector lDecayDaughter1, lDecayDaughter2, lResonanceSecondary, lDecayDaughter_bach, lResonanceK1; + for (const auto& [trk1, trk2] : combinations(CombinationsFullIndexPolicy(dTracks2, 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 too. But the same id pairs are not needed. + // trk1: pion, trk2: pion, bTrack: kaon + if (!trackCut(trk1) || !trackCut(trk2)) + continue; + + auto trk1pt = trk1.pt(); + auto trk2pt = trk2.pt(); + auto isTrk1hasTOF = trk1.hasTOF(); + auto isTrk2hasTOF = trk2.hasTOF(); + + if constexpr (!IsResoMicrotrack) { + auto trk1NSigmaPiTPC = trk1.tpcNSigmaPi(); + auto trk1NSigmaPiTOF = (isTrk1hasTOF) ? trk1.tofNSigmaPi() : -999.; + auto trk2NSigmaPiTPC = trk2.tpcNSigmaPi(); + auto trk2NSigmaPiTOF = (isTrk2hasTOF) ? trk2.tofNSigmaPi() : -999.; + + if (cUseOnlyTOFTrackPi && !isTrk1hasTOF) + continue; + if (!selectionPIDpion(trk1) || !selectionPIDpion(trk2)) + continue; + + if constexpr (!IsMix) { + + histos.fill(HIST("QA/trkppionTPCPID"), trk1pt, trk1NSigmaPiTPC); + if (isTrk1hasTOF) { + histos.fill(HIST("QA/trkppionTOFPID"), trk1pt, trk1NSigmaPiTOF); + histos.fill(HIST("QA/trkppionTPCTOFPID"), trk1NSigmaPiTPC, trk1NSigmaPiTOF); + } + histos.fill(HIST("QA/trkppionpT"), trk1pt); + histos.fill(HIST("QA/trkppionDCAxy"), trk1.dcaXY()); + histos.fill(HIST("QA/trkppionDCAz"), trk1.dcaZ()); + + histos.fill(HIST("QA/trkspionTPCPID"), trk2pt, trk2NSigmaPiTPC); + if (isTrk2hasTOF) { + histos.fill(HIST("QA/trkspionTOFPID"), trk2pt, trk2NSigmaPiTOF); + histos.fill(HIST("QA/trkspionTPCTOFPID"), trk2NSigmaPiTPC, trk2NSigmaPiTOF); + } + histos.fill(HIST("QA/trkspionpT"), trk2pt); + histos.fill(HIST("QA/trkspionDCAxy"), trk2.dcaXY()); + histos.fill(HIST("QA/trkspionDCAz"), trk2.dcaZ()); + } + } else { + histos.fill(HIST("QA/trkppionTPCPID"), trk1pt, o2::aod::resomicrodaughter::PidNSigma::getTPCnSigma(trk1.pidNSigmaPiFlag())); + if (isTrk1hasTOF) { + histos.fill(HIST("QA/trkppionTOFPID"), trk1pt, o2::aod::resomicrodaughter::PidNSigma::getTOFnSigma(trk1.pidNSigmaPiFlag())); + histos.fill(HIST("QA/trkppionTPCTOFPID"), o2::aod::resomicrodaughter::PidNSigma::getTPCnSigma(trk1.pidNSigmaPiFlag()), o2::aod::resomicrodaughter::PidNSigma::getTOFnSigma(trk1.pidNSigmaPiFlag())); + } + histos.fill(HIST("QA/trkppionpT"), trk1pt); + histos.fill(HIST("QA/trkppionDCAxy"), o2::aod::resomicrodaughter::ResoMicroTrackSelFlag::decodeDCAxy(trk1.trackSelectionFlags())); + histos.fill(HIST("QA/trkppionDCAz"), o2::aod::resomicrodaughter::ResoMicroTrackSelFlag::decodeDCAz(trk1.trackSelectionFlags())); + + histos.fill(HIST("QA/trkspionTPCPID"), trk2pt, o2::aod::resomicrodaughter::PidNSigma::getTPCnSigma(trk2.pidNSigmaPiFlag())); + if (isTrk2hasTOF) { + histos.fill(HIST("QA/trkspionTOFPID"), trk2pt, o2::aod::resomicrodaughter::PidNSigma::getTOFnSigma(trk2.pidNSigmaPiFlag())); + histos.fill(HIST("QA/trkspionTPCTOFPID"), o2::aod::resomicrodaughter::PidNSigma::getTPCnSigma(trk2.pidNSigmaPiFlag()), o2::aod::resomicrodaughter::PidNSigma::getTOFnSigma(trk2.pidNSigmaPiFlag())); + } + histos.fill(HIST("QA/trkspionpT"), trk2pt); + histos.fill(HIST("QA/trkspionDCAxy"), o2::aod::resomicrodaughter::ResoMicroTrackSelFlag::decodeDCAxy(trk2.trackSelectionFlags())); + histos.fill(HIST("QA/trkspionDCAz"), o2::aod::resomicrodaughter::ResoMicroTrackSelFlag::decodeDCAz(trk2.trackSelectionFlags())); + } + + // Resonance reconstruction + lDecayDaughter1.SetXYZM(trk1.px(), trk1.py(), trk1.pz(), MassPionCharged); + lDecayDaughter2.SetXYZM(trk2.px(), trk2.py(), trk2.pz(), MassPionCharged); + lResonanceSecondary = lDecayDaughter1 + lDecayDaughter2; + + if (lResonanceSecondary.Pt() < cMinSecondaryPtCut) + continue; + + if constexpr (!IsMix) { + histos.fill(HIST("QA/hInvmassSecon"), lResonanceSecondary.M()); + } + if constexpr (IsMC) { + /* + if (isTrueK892(trk1, trk2)) + histos.fill(HIST("QAMC/hpT_Secondary"), lResonanceSecondary.Pt()); + } else { + if (isTrueRho(trk1, trk2)) + histos.fill(HIST("QAMC/hpT_Secondary"), lResonanceSecondary.Pt()); + } + */ + histos.fill(HIST("QAMC/hpT_Secondary"), lResonanceSecondary.Pt()); + } + // Mass Window cut is removed + + for (const auto& bTrack : dTracks1) { + if (bTrack.index() == trk1.index() || bTrack.index() == trk2.index()) + continue; + if (!trackCut(bTrack)) + continue; + if (!selectionPIDkaon(bTrack)) + continue; + + // K1 reconstruction + lDecayDaughter_bach.SetXYZM(bTrack.px(), bTrack.py(), bTrack.pz(), MassKaonCharged); + lResonanceK1 = lResonanceSecondary + lDecayDaughter_bach; + + // Cuts + if (lResonanceK1.Rapidity() > cK1MaxRap || lResonanceK1.Rapidity() < cK1MinRap) + continue; + + auto lK1Angle = lResonanceSecondary.Angle(lDecayDaughter_bach.Vect()); + auto lPairAsym = (lResonanceSecondary.E() - lDecayDaughter_bach.E()) / (lResonanceSecondary.E() + lDecayDaughter_bach.E()); + + TLorentzVector temp13 = lDecayDaughter1 + lDecayDaughter_bach; + TLorentzVector temp23 = lDecayDaughter2 + lDecayDaughter_bach; + + // QA histogram + if constexpr (!IsMix) { + histos.fill(HIST("QA/K1OA"), lK1Angle); + histos.fill(HIST("QA/K1PairAsym"), lPairAsym); + histos.fill(HIST("QA/hInvmassK892_Rho"), temp13.M(), lResonanceSecondary.M()); + histos.fill(HIST("QA/hInvmassSecon_PiKa"), lResonanceSecondary.M(), temp23.M()); + histos.fill(HIST("QA/hpT_Secondary"), lResonanceSecondary.Pt()); + } + // Selection cuts are removed + // QA histograms after the cuts are removed as no cuts are applied + + if constexpr (!IsMix) { + unsigned int typeK1 = bTrack.sign() > 0 ? BinType::kK1P : BinType::kK1N; + unsigned int typeNormal = BinAnti::kNormal; + if (trk1.sign() * trk2.sign() < 0) { + histos.fill(HIST("k1invmass"), lResonanceK1.M()); + histos.fill(HIST("hInvmass_K1"), typeNormal, typeK1, multiplicity, lResonanceK1.Pt(), lResonanceK1.M()); + } else { + histos.fill(HIST("k1invmass_LS"), lResonanceK1.M()); + histos.fill(HIST("hInvmass_K1_LS"), typeNormal, typeK1, multiplicity, lResonanceK1.Pt(), lResonanceK1.M()); + } + + if constexpr (IsMC) { + if (isTrueK1(trk1, trk2, bTrack)) { + typeK1 = bTrack.sign() > 0 ? BinType::kK1P_Rec : BinType::kK1N_Rec; + histos.fill(HIST("hInvmass_K1"), typeNormal, typeK1, multiplicity, lResonanceK1.Pt(), lResonanceK1.M()); + histos.fill(HIST("k1invmass_MC"), lResonanceK1.M()); + histos.fill(HIST("QAMC/K1OA"), lK1Angle); + histos.fill(HIST("QAMC/K1PairAsym"), lPairAsym); + histos.fill(HIST("QAMC/hInvmassK892_Rho"), temp13.M(), lResonanceSecondary.M()); + histos.fill(HIST("QAMC/hInvmassSecon_PiKa"), lResonanceSecondary.M(), temp23.M()); + histos.fill(HIST("QAMC/hInvmassSecon"), lResonanceSecondary.M()); + histos.fill(HIST("QAMC/hpT_Seocondary"), lResonanceSecondary.Pt()); + + if constexpr (!IsResoMicrotrack) { + + auto trk1NSigmaPiTPC = trk1.tpcNSigmaPi(); + auto trk1NSigmaPiTOF = (isTrk1hasTOF) ? trk1.tofNSigmaPi() : -999.; + auto trk2NSigmaPiTPC = trk2.tpcNSigmaPi(); + auto trk2NSigmaPiTOF = (isTrk2hasTOF) ? trk2.tofNSigmaPi() : -999.; + + // PID QA primary pion + histos.fill(HIST("QAMC/trkppionTPCPID"), trk1pt, trk1NSigmaPiTPC); + if (isTrk1hasTOF) { + histos.fill(HIST("QAMC/trkppionTOFPID"), trk1pt, trk1NSigmaPiTOF); + histos.fill(HIST("QAMC/trkppionTPCTOFPID"), trk1NSigmaPiTPC, trk1NSigmaPiTOF); + } + histos.fill(HIST("QAMC/trkppionpT"), trk1pt); + histos.fill(HIST("QAMC/trkppionDCAxy"), trk1.dcaXY()); + histos.fill(HIST("QAMC/trkppionDCAz"), trk1.dcaZ()); + + // PID QA secondary pion + histos.fill(HIST("QAMC/trkspionTPCPID"), trk2pt, trk2NSigmaPiTPC); + if (isTrk2hasTOF) { + histos.fill(HIST("QAMC/trkspionTOFPID"), trk2pt, trk2NSigmaPiTOF); + histos.fill(HIST("QAMC/trkspionTPCTOFPID"), trk2NSigmaPiTPC, trk2NSigmaPiTOF); + } + histos.fill(HIST("QAMC/trkspionpT"), trk2pt); + histos.fill(HIST("QAMC/trkspionDCAxy"), trk2.dcaXY()); + histos.fill(HIST("QAMC/trkspionDCAz"), trk2.dcaZ()); + + } else { + + histos.fill(HIST("QAMC/trkppionTPCPID"), trk1pt, o2::aod::resomicrodaughter::PidNSigma::getTPCnSigma(trk1.pidNSigmaSelectionFlags())); + if (isTrk1hasTOF) { + histos.fill(HIST("QAMC/trkppionTOFPID"), trk1pt, o2::aod::resomicrodaughter::PidNSigma::getTOFnSigma(trk1.pidNSigmaSelectionFlags())); + histos.fill(HIST("QAMC/trkppionTPCTOFPID"), o2::aod::resomicrodaughter::PidNSigma::getTPCnSigma(trk1.pidNSigmaSelectionFlags()), o2::aod::resomicrodaughter::PidNSigma::getTOFnSigma(trk1.pidNSigmaSelectionFlags())); + } + histos.fill(HIST("QAMC/trkppionpT"), trk1pt); + histos.fill(HIST("QAMC/trkppionDCAxy"), o2::aod::resomicrodaughter::ResoMicroTrackSelFlag::decodeDCAxy(trk1.trackSelectionFlags())); + histos.fill(HIST("QAMC/trkppionDCAz"), o2::aod::resomicrodaughter::ResoMicroTrackSelFlag::decodeDCAz(trk1.trackSelectionFlags())); + + // PID QA secondary pion + histos.fill(HIST("QAMC/trkspionTPCPID"), trk2pt, o2::aod::resomicrodaughter::PidNSigma::getTPCnSigma(trk2.pidNSigmaSelectionFlags())); + if (isTrk2hasTOF) { + histos.fill(HIST("QAMC/trkspionTOFPID"), trk2pt, o2::aod::resomicrodaughter::PidNSigma::getTOFnSigma(trk2.pidNSigmaSelectionFlags())); + histos.fill(HIST("QAMC/trkspionTPCTOFPID"), o2::aod::resomicrodaughter::PidNSigma::getTPCnSigma(trk2.pidNSigmaSelectionFlags()), o2::aod::resomicrodaughter::PidNSigma::getTOFnSigma(trk2.pidNSigmaSelectionFlags())); + } + histos.fill(HIST("QAMC/trkspionpT"), trk2pt); + histos.fill(HIST("QAMC/trkspionDCAxy"), o2::aod::resomicrodaughter::ResoMicroTrackSelFlag::decodeDCAxy(trk2.trackSelectionFlags())); + histos.fill(HIST("QAMC/trkspionDCAz"), o2::aod::resomicrodaughter::ResoMicroTrackSelFlag::decodeDCAz(trk2.trackSelectionFlags())); + } + } else { + histos.fill(HIST("k1invmass_MC_noK1"), lResonanceK1.M()); + } + } // IsMC + } else { + unsigned int typeK1 = bTrack.sign() > 0 ? BinType::kK1P_Mix : BinType::kK1N_Mix; + unsigned int typeNormal = BinAnti::kNormal; + histos.fill(HIST("hInvmass_K1_Mix"), typeNormal, typeK1, multiplicity, lResonanceK1.Pt(), lResonanceK1.M()); + histos.fill(HIST("k1invmass_Mix"), lResonanceK1.M()); + } + } // bTrack + } + } // fillHistograms + + void processResoTracks(aod::ResoCollision const& collision, + aod::ResoTracks const& resotracks) + { + fillHistograms(collision, resotracks, resotracks); + } + PROCESS_SWITCH(K1AnalysisMicro, processResoTracks, "Process ResoTracks", false); + + void processResoMicroTracks(aod::ResoCollision const& collision, + aod::ResoMicroTracks const& resomicrotracks) + { + fillHistograms(collision, resomicrotracks, resomicrotracks); + } + PROCESS_SWITCH(K1AnalysisMicro, processResoMicroTracks, "Process ResoMicroTracks", true); + + void processMC(aod::ResoCollision const& collision, + soa::Join const& resotracks) + { + fillHistograms(collision, resotracks, resotracks); + } + PROCESS_SWITCH(K1AnalysisMicro, processMC, "Process Event for MC", false); + + void processMCTrue(ResoMCCols::iterator const& collision, aod::ResoMCParents const& resoParents) + { + auto multiplicity = collision.cent(); + for (const auto& part : resoParents) { + if (std::abs(part.pdgCode()) != kK1Plus) + continue; + if (std::abs(part.y()) > 0.5) { + continue; + } + bool pass1 = false; + bool pass2 = false; + bool pass3 = false; + bool pass4 = false; + if (std::abs(part.daughterPDG1()) == 313 || std::abs(part.daughterPDG2()) == 313) { // At least one decay into K892 + pass2 = true; + } + if (std::abs(part.daughterPDG1()) == kPiPlus || std::abs(part.daughterPDG2()) == kPiPlus) { // At lest one decay into pion + pass1 = true; + } + if (std::abs(part.daughterPDG1()) == kPDGRho770 || std::abs(part.daughterPDG2()) == kPDGRho770) { + pass4 = true; + } + if (std::abs(part.daughterPDG1()) == kKPlus || std::abs(part.daughterPDG2()) == kKPlus) { + pass3 = true; + } + if (!pass1 || !pass2 || !pass3 || !pass4) // If we have both decay products + continue; + auto typeNormal = part.pdgCode() > 0 ? BinAnti::kNormal : BinAnti::kAnti; + if (collision.isVtxIn10()) // INEL>10 + { + auto typeK1 = part.pdgCode() > 0 ? BinType::kK1P_GenINEL10 : BinType::kK1N_GenINEL10; + histos.fill(HIST("hInvmass_K1"), typeNormal, typeK1, multiplicity, part.pt(), 1); + } + if (collision.isVtxIn10() && collision.isInSel8()) // INEL>10, vtx10 + { + auto typeK1 = part.pdgCode() > 0 ? BinType::kK1P_GenINELgt10 : BinType::kK1N_GenINELgt10; + histos.fill(HIST("hInvmass_K1"), typeNormal, typeK1, multiplicity, part.pt(), 1); + } + if (collision.isVtxIn10() && collision.isTriggerTVX()) // vtx10, TriggerTVX + { + auto typeK1 = part.pdgCode() > 0 ? BinType::kK1P_GenTrig10 : BinType::kK1N_GenTrig10; + histos.fill(HIST("hInvmass_K1"), typeNormal, typeK1, multiplicity, part.pt(), 1); + } + if (collision.isInAfterAllCuts()) // after all event selection + { + auto typeK1 = part.pdgCode() > 0 ? BinType::kK1P_GenEvtSel : BinType::kK1N_GenEvtSel; + histos.fill(HIST("hInvmass_K1"), typeNormal, typeK1, multiplicity, part.pt(), 1); + } + } + } + PROCESS_SWITCH(K1AnalysisMicro, processMCTrue, "Process Event for MC", false); + + // Processing Event Mixing + using BinningTypeVtxZT0M = ColumnBinningPolicy; + void processME(o2::aod::ResoCollisions const& collisions, aod::ResoTracks const& resotracks) + { + auto tracksTuple = std::make_tuple(resotracks); + BinningTypeVtxZT0M colBinning{{cfgVtxBins, cfgMultBins}, true}; + SameKindPair pairs{colBinning, nEvtMixing, -1, collisions, tracksTuple, &cache}; // -1 is the number of the bin to skip + + for (const auto& [collision1, tracks1, collision2, tracks2] : pairs) { + fillHistograms(collision1, tracks1, tracks2); + } + }; + PROCESS_SWITCH(K1AnalysisMicro, processME, "Process EventMixing light without partition", false); + + // Processing Event Mixing -- Micro + // using BinningTypeVtxZT0M = ColumnBinningPolicy; + void processMEMicro(o2::aod::ResoCollisions const& collisions, aod::ResoMicroTracks const& resomicrotracks) + { + auto tracksTuple = std::make_tuple(resomicrotracks); + BinningTypeVtxZT0M colBinning{{cfgVtxBins, cfgMultBins}, true}; + SameKindPair pairs{colBinning, nEvtMixing, -1, collisions, tracksTuple, &cache}; // -1 is the number of the bin to skip + + for (const auto& [collision1, tracks1, collision2, tracks2] : pairs) { + fillHistograms(collision1, tracks1, tracks2); + } + }; + PROCESS_SWITCH(K1AnalysisMicro, processMEMicro, "Process EventMixing light without partition", true); +}; // struct + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} diff --git a/PWGLF/Tasks/Resonances/xi1530Analysisqa.cxx b/PWGLF/Tasks/Resonances/xi1530Analysisqa.cxx index 53e7f283150..42773fa2947 100644 --- a/PWGLF/Tasks/Resonances/xi1530Analysisqa.cxx +++ b/PWGLF/Tasks/Resonances/xi1530Analysisqa.cxx @@ -430,13 +430,13 @@ struct Xi1530Analysisqa { if (std::abs(track.pt()) < cMinPtcut) return false; if constexpr (IsResoMicrotrack) { - if (std::abs(o2::aod::resodmciroaughter::ResoMicroTrackSelFlag::decodeDCAxy(track.trackSelectionFlags())) > (cDCAxytoPVByPtPiFirstP0 + cDCAxyToPVByPtPiFirstExp * std::pow(track.pt(), -1.1))) + if (std::abs(o2::aod::resomicrodaughter::ResoMicroTrackSelFlag::decodeDCAxy(track.trackSelectionFlags())) > (cDCAxytoPVByPtPiFirstP0 + cDCAxyToPVByPtPiFirstExp * std::pow(track.pt(), -1.1))) return false; if (cDCAzToPVAsPt) { - if (std::abs(o2::aod::resodmciroaughter::ResoMicroTrackSelFlag::decodeDCAz(track.trackSelectionFlags())) > (cDCAxytoPVByPtPiFirstP0 + cDCAxyToPVByPtPiFirstExp * std::pow(track.pt(), -1.1))) + if (std::abs(o2::aod::resomicrodaughter::ResoMicroTrackSelFlag::decodeDCAz(track.trackSelectionFlags())) > (cDCAxytoPVByPtPiFirstP0 + cDCAxyToPVByPtPiFirstExp * std::pow(track.pt(), -1.1))) return false; } else { - if (std::abs(o2::aod::resodmciroaughter::ResoMicroTrackSelFlag::decodeDCAz(track.trackSelectionFlags())) > cMaxDCAzToPVCut) + if (std::abs(o2::aod::resomicrodaughter::ResoMicroTrackSelFlag::decodeDCAz(track.trackSelectionFlags())) > cMaxDCAzToPVCut) return false; } } else { @@ -607,8 +607,8 @@ struct Xi1530Analysisqa { float trackPt = candidate.pt(); if constexpr (IsResoMicrotrack) { - tpcNsigmaPionFirst = o2::aod::resodmciroaughter::PidNSigma::getTPCnSigma(candidate.pidNSigmaPiFlag()); - tofNsigmaPionFirst = o2::aod::resodmciroaughter::PidNSigma::getTOFnSigma(candidate.pidNSigmaPiFlag()); + tpcNsigmaPionFirst = o2::aod::resomicrodaughter::PidNSigma::getTPCnSigma(candidate.pidNSigmaPiFlag()); + tofNsigmaPionFirst = o2::aod::resomicrodaughter::PidNSigma::getTOFnSigma(candidate.pidNSigmaPiFlag()); } else { tpcNsigmaPionFirst = candidate.tpcNSigmaPi(); tofNsigmaPionFirst = candidate.tofNSigmaPi(); @@ -700,10 +700,10 @@ struct Xi1530Analysisqa { static float trk1NSigmaPiTPC; static float trk1NSigmaPiTOF; if constexpr (IsResoMicrotrack) { - trk1DCAXY = o2::aod::resodmciroaughter::ResoMicroTrackSelFlag::decodeDCAxy(trk1.trackSelectionFlags()); - trk1DCAZ = o2::aod::resodmciroaughter::ResoMicroTrackSelFlag::decodeDCAz(trk1.trackSelectionFlags()); - trk1NSigmaPiTPC = o2::aod::resodmciroaughter::PidNSigma::getTPCnSigma(trk1.pidNSigmaPiFlag()); - trk1NSigmaPiTOF = o2::aod::resodmciroaughter::PidNSigma::getTOFnSigma(trk1.pidNSigmaPiFlag()); + trk1DCAXY = o2::aod::resomicrodaughter::ResoMicroTrackSelFlag::decodeDCAxy(trk1.trackSelectionFlags()); + trk1DCAZ = o2::aod::resomicrodaughter::ResoMicroTrackSelFlag::decodeDCAz(trk1.trackSelectionFlags()); + trk1NSigmaPiTPC = o2::aod::resomicrodaughter::PidNSigma::getTPCnSigma(trk1.pidNSigmaPiFlag()); + trk1NSigmaPiTOF = o2::aod::resomicrodaughter::PidNSigma::getTOFnSigma(trk1.pidNSigmaPiFlag()); } else { trk1DCAXY = trk1.dcaXY(); trk1DCAZ = trk1.dcaZ(); diff --git a/Tutorials/PWGLF/Resonance/resonancesMicrotrack.cxx b/Tutorials/PWGLF/Resonance/resonancesMicrotrack.cxx index 07736a3e841..5022d4b602d 100644 --- a/Tutorials/PWGLF/Resonance/resonancesMicrotrack.cxx +++ b/Tutorials/PWGLF/Resonance/resonancesMicrotrack.cxx @@ -107,9 +107,9 @@ struct ResonancesMicrotrack { } else { if (std::abs(track.pt()) < cMinPtcut) return false; - if (o2::aod::resodmciroaughter::ResoMicroTrackSelFlag::decodeDCAxy(track.trackSelectionFlags()) > cMaxDCArToPVcut - Epsilon) + if (o2::aod::resomicrodaughter::ResoMicroTrackSelFlag::decodeDCAxy(track.trackSelectionFlags()) > cMaxDCArToPVcut - Epsilon) return false; - if (o2::aod::resodmciroaughter::ResoMicroTrackSelFlag::decodeDCAz(track.trackSelectionFlags()) > cMaxDCAzToPVcut - Epsilon) + if (o2::aod::resomicrodaughter::ResoMicroTrackSelFlag::decodeDCAz(track.trackSelectionFlags()) > cMaxDCAzToPVcut - Epsilon) return false; if (cfgPrimaryTrack && !track.isPrimaryTrack()) return false; @@ -132,8 +132,8 @@ struct ResonancesMicrotrack { } // return true; } else { - bool tpcPass = std::abs(o2::aod::resodmciroaughter::PidNSigma::getTPCnSigma(candidate.pidNSigmaPrFlag())) < nSigmaCutTPC + Epsilon; - bool tofPass = candidate.hasTOF() ? std::abs(o2::aod::resodmciroaughter::PidNSigma::getTOFnSigma(candidate.pidNSigmaPrFlag())) < nSigmaCutTOF + Epsilon : true; + bool tpcPass = std::abs(o2::aod::resomicrodaughter::PidNSigma::getTPCnSigma(candidate.pidNSigmaPrFlag())) < nSigmaCutTPC + Epsilon; + bool tofPass = candidate.hasTOF() ? std::abs(o2::aod::resomicrodaughter::PidNSigma::getTOFnSigma(candidate.pidNSigmaPrFlag())) < nSigmaCutTOF + Epsilon : true; if (tpcPass && tofPass) { return true; } @@ -173,11 +173,11 @@ struct ResonancesMicrotrack { histos.fill(HIST("hPx_ResoMicroTracks"), track.px()); histos.fill(HIST("hPy_ResoMicroTracks"), track.py()); histos.fill(HIST("hPz_ResoMicroTracks"), track.pz()); - histos.fill(HIST("hDcaxy_ResoMicroTracks"), o2::aod::resodmciroaughter::ResoMicroTrackSelFlag::decodeDCAxy(track.trackSelectionFlags())); - histos.fill(HIST("hDcaz_ResoMicroTracks"), o2::aod::resodmciroaughter::ResoMicroTrackSelFlag::decodeDCAz(track.trackSelectionFlags())); - histos.fill(HIST("hNsigmaKaonTPC_ResoMicroTracks"), o2::aod::resodmciroaughter::PidNSigma::getTPCnSigma(track.pidNSigmaPrFlag())); + histos.fill(HIST("hDcaxy_ResoMicroTracks"), o2::aod::resomicrodaughter::ResoMicroTrackSelFlag::decodeDCAxy(track.trackSelectionFlags())); + histos.fill(HIST("hDcaz_ResoMicroTracks"), o2::aod::resomicrodaughter::ResoMicroTrackSelFlag::decodeDCAz(track.trackSelectionFlags())); + histos.fill(HIST("hNsigmaKaonTPC_ResoMicroTracks"), o2::aod::resomicrodaughter::PidNSigma::getTPCnSigma(track.pidNSigmaPrFlag())); if (track.hasTOF()) { - histos.fill(HIST("hNsigmaKaonTOF_ResoMicroTracks"), o2::aod::resodmciroaughter::PidNSigma::getTOFnSigma(track.pidNSigmaPrFlag())); + histos.fill(HIST("hNsigmaKaonTOF_ResoMicroTracks"), o2::aod::resomicrodaughter::PidNSigma::getTOFnSigma(track.pidNSigmaPrFlag())); } } } From 6010ed97366f55feafce52f82219854ec5e65a25 Mon Sep 17 00:00:00 2001 From: Chiara Pinto <48326672+chiarapinto@users.noreply.github.com> Date: Fri, 20 Jun 2025 11:18:41 +0200 Subject: [PATCH 158/871] [PWGLF] removed unnecessary cut (#11692) --- PWGLF/Tasks/Nuspex/antinucleiInJets.cxx | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/PWGLF/Tasks/Nuspex/antinucleiInJets.cxx b/PWGLF/Tasks/Nuspex/antinucleiInJets.cxx index 44dc27260a7..59aca0f7ceb 100644 --- a/PWGLF/Tasks/Nuspex/antinucleiInJets.cxx +++ b/PWGLF/Tasks/Nuspex/antinucleiInJets.cxx @@ -102,7 +102,6 @@ struct AntinucleiInJets { Configurable rejectionPercentage{"rejectionPercentage", 3, "percentage of events to reject"}; Configurable minItsNclusters{"minItsNclusters", 5, "minimum number of ITS clusters"}; Configurable minTpcNcrossedRows{"minTpcNcrossedRows", 80, "minimum number of TPC crossed pad rows"}; - Configurable minTpcNcrossedRowsOverFindable{"minTpcNcrossedRowsOverFindable", 0.8, "crossed rows/findable"}; Configurable maxChiSquareTpc{"maxChiSquareTpc", 4.0, "maximum TPC chi^2/Ncls"}; Configurable maxChiSquareIts{"maxChiSquareIts", 36.0, "maximum ITS chi^2/Ncls"}; Configurable minPt{"minPt", 0.3, "minimum pt of the tracks"}; @@ -388,7 +387,6 @@ struct AntinucleiInJets { { const int minTpcCr = 70; - const double minCrFindable = 0.8; const double maxChi2Tpc = 4.0; const double maxChi2Its = 36.0; const double maxPseudorapidity = 0.8; @@ -406,8 +404,6 @@ struct AntinucleiInJets { return false; if (track.tpcNClsCrossedRows() < minTpcCr) return false; - if ((static_cast(track.tpcNClsCrossedRows()) / static_cast(track.tpcNClsFindable())) < minCrFindable) - return false; if (track.tpcChi2NCl() > maxChi2Tpc) return false; if (track.itsChi2NCl() > maxChi2Its) @@ -437,8 +433,6 @@ struct AntinucleiInJets { return false; if (track.tpcNClsCrossedRows() < minTpcNcrossedRows) return false; - if ((static_cast(track.tpcNClsCrossedRows()) / static_cast(track.tpcNClsFindable())) < minTpcNcrossedRowsOverFindable) - return false; if (track.tpcChi2NCl() > maxChiSquareTpc) return false; if (track.itsChi2NCl() > maxChiSquareIts) @@ -1458,8 +1452,6 @@ struct AntinucleiInJets { continue; if (track.tpcNClsCrossedRows() < tpcNcrossedRowsSyst[i]) continue; - if ((static_cast(track.tpcNClsCrossedRows()) / static_cast(track.tpcNClsFindable())) < minTpcNcrossedRowsOverFindable) - continue; if (track.tpcChi2NCl() > maxChiSquareTpc) continue; if (track.itsChi2NCl() > maxChiSquareIts) @@ -1572,8 +1564,6 @@ struct AntinucleiInJets { continue; if (track.tpcNClsCrossedRows() < tpcNcrossedRowsSyst[i]) continue; - if ((static_cast(track.tpcNClsCrossedRows()) / static_cast(track.tpcNClsFindable())) < minTpcNcrossedRowsOverFindable) - continue; if (track.tpcChi2NCl() > maxChiSquareTpc) continue; if (track.itsChi2NCl() > maxChiSquareIts) From 95b5927c53293c9248b0c0b8f690bd8605812222 Mon Sep 17 00:00:00 2001 From: Nida Malik Date: Fri, 20 Jun 2025 17:06:52 +0530 Subject: [PATCH 159/871] [PWGCF] Added Histograms for Monte Carlo (#11698) --- .../Tasks/netchargeFluctuations.cxx | 379 ++++++++++-------- 1 file changed, 205 insertions(+), 174 deletions(-) diff --git a/PWGCF/EbyEFluctuations/Tasks/netchargeFluctuations.cxx b/PWGCF/EbyEFluctuations/Tasks/netchargeFluctuations.cxx index f94b6161330..d248c5d6620 100644 --- a/PWGCF/EbyEFluctuations/Tasks/netchargeFluctuations.cxx +++ b/PWGCF/EbyEFluctuations/Tasks/netchargeFluctuations.cxx @@ -15,33 +15,36 @@ /// For RUN-3 /// /// \author Nida Malik -#include // Include for std::vector +#include "PWGCF/Core/CorrelationContainer.h" +#include "PWGCF/Core/PairCuts.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" +#include "Common/CCDB/EventSelectionParams.h" +#include "Common/CCDB/TriggerAliases.h" +#include "Common/Core/TrackSelection.h" +#include "Common/Core/trackUtilities.h" +#include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/FT0Corrected.h" #include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/PIDResponse.h" -#include "Common/Core/trackUtilities.h" -#include "Common/CCDB/EventSelectionParams.h" -#include "Common/Core/TrackSelection.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "Common/DataModel/Centrality.h" + #include "CommonConstants/MathConstants.h" -#include "Common/DataModel/FT0Corrected.h" -#include "Framework/AnalysisDataModel.h" +#include "CommonConstants/PhysicsConstants.h" #include "Framework/ASoAHelpers.h" -#include "Framework/RunningWorkflowInfo.h" -#include "PWGCF/Core/CorrelationContainer.h" -#include "PWGCF/Core/PairCuts.h" -#include "Common/CCDB/TriggerAliases.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" #include "Framework/O2DatabasePDGPlugin.h" -#include "CommonConstants/PhysicsConstants.h" +#include "Framework/RunningWorkflowInfo.h" +#include "Framework/runDataProcessing.h" + #include "TProfile.h" #include "TProfile2D.h" #include "TRandom3.h" +#include + using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; @@ -149,22 +152,23 @@ struct NetchargeFluctuations { Configurable cIsGoodITSLayers{"cIsGoodITSLayers", false, "Good ITS Layers All"}; // pileup // Initialization - float cent = 0.; - float mult = 0.; void init(o2::framework::InitContext&) { - const AxisSpec vtxzAxis = {80, -20, 20, "V_{Z} (cm)"}; + const AxisSpec vtxzAxis = {800, -20, 20, "V_{Z} (cm)"}; const AxisSpec dcaAxis = {250, -0.5, 0.5, "DCA_{xy} (cm)"}; const AxisSpec dcazAxis = {250, -0.5, 0.5, "DCA_{z} (cm)"}; const AxisSpec ptAxis = {70, 0.0, 7.0, "#it{p}_{T} (GeV/#it{c})"}; - const AxisSpec etaAxis = {20, -1., 1., "#eta"}; + const AxisSpec etaAxis = {200, -1., 1., "#eta"}; + const AxisSpec cent1Axis = {10, 0., 100., "centrality"}; const AxisSpec centAxis = {100, 0., 100., "centrality"}; const AxisSpec multAxis = {200, 0., 10000., "FT0M Amplitude"}; - const AxisSpec tpcChiAxis = {140, 0., 7., "Chi2"}; - const AxisSpec itsChiAxis = {80, 0., 40., "Chi2"}; - const AxisSpec crossedRowAxis = {160, 0., 160., "TPC Crossed rows"}; + const AxisSpec tpcChiAxis = {1400, 0., 7., "Chi2"}; + const AxisSpec itsChiAxis = {800, 0., 40., "Chi2"}; + const AxisSpec crossedRowAxis = {1600, 0., 160., "TPC Crossed rows"}; const AxisSpec eventsAxis = {10, 0, 10, ""}; const AxisSpec signAxis = {20, -10, 10, ""}; + const AxisSpec nchAxis = {3000, 0, 3000, "Nch"}; + const AxisSpec nchpAxis = {50000, 0, 50000, "Nch"}; histogramRegistry.add("hVtxZ_before", "", kTH1F, {vtxzAxis}); histogramRegistry.add("hDcaXY_before", "", kTH1F, {dcaAxis}); @@ -186,39 +190,40 @@ struct NetchargeFluctuations { histogramRegistry.add("hPt", "", kTH1F, {ptAxis}); histogramRegistry.add("hCentrality", "", kTH1F, {centAxis}); histogramRegistry.add("hMultiplicity", "", kTH1F, {multAxis}); - histogramRegistry.add("rec_hVtxZ_before", "", kTH1F, {vtxzAxis}); histogramRegistry.add("gen_hVtxZ_before", "", kTH1F, {vtxzAxis}); - histogramRegistry.add("rec_hDcaXY_before", "", kTH1D, {dcaAxis}); - histogramRegistry.add("rec_hDcaZ_before", "", kTH1D, {dcazAxis}); - histogramRegistry.add("rec_hTPCchi2perCluster_before", "TPC #Chi^{2}/Cluster", kTH1D, {tpcChiAxis}); - histogramRegistry.add("rec_hITSchi2perCluster_before", "ITS #Chi^{2}/Cluster", kTH1D, {itsChiAxis}); - histogramRegistry.add("rec_hTPCCrossedrows_before", "Crossed TPC rows", kTH1D, {crossedRowAxis}); - histogramRegistry.add("rec_hVtxZ_after", "", kTH1F, {vtxzAxis}); histogramRegistry.add("gen_hVtxZ_after", "", kTH1F, {vtxzAxis}); - histogramRegistry.add("rec_hDcaXY_after", "", kTH1D, {dcaAxis}); - histogramRegistry.add("rec_hDcaZ_after", "", kTH1D, {dcazAxis}); - histogramRegistry.add("rec_hTPCchi2perCluster_after", "TPC #Chi^{2}/Cluster", kTH1D, {tpcChiAxis}); - histogramRegistry.add("rec_hITSchi2perCluster_after", "ITS #Chi^{2}/Cluster", kTH1D, {itsChiAxis}); - histogramRegistry.add("rec_hTPCCrossedrows_after", "Crossed TPC rows", kTH1D, {crossedRowAxis}); histogramRegistry.add("gen_hEta", "", kTH1F, {etaAxis}); - histogramRegistry.add("rec_hEta", "", kTH1F, {etaAxis}); histogramRegistry.add("gen_hSign", "", kTH1F, {signAxis}); histogramRegistry.add("gen_hPt", "", kTH1F, {ptAxis}); - histogramRegistry.add("rec_hPt", "", kTH1F, {ptAxis}); - histogramRegistry.add("rec_hPtDcaXY_after", "hPtDCAxy", kTH2D, {ptAxis, dcaAxis}); - histogramRegistry.add("rec_hPtDcaZ_after", "hPtDCAz", kTH2D, {ptAxis, dcazAxis}); - histogramRegistry.add("rec_hCentrality", "", kTH1D, {centAxis}); - histogramRegistry.add("gen_hCentrality", "", kTH1D, {centAxis}); - histogramRegistry.add("rec_hMultiplicity", "", kTH1D, {multAxis}); - histogramRegistry.add("gen_hMultiplicity", "", kTH1D, {multAxis}); - } + histogramRegistry.add("nch", "", kTH1D, {nchAxis}); + histogramRegistry.add("nch0", "", kTH1D, {nchAxis}); + histogramRegistry.add("nch1", "", kTH1D, {nchAxis}); + histogramRegistry.add("nch2", "", kTH1D, {nchAxis}); + histogramRegistry.add("nch3", "", kTH1D, {nchAxis}); + histogramRegistry.add("nch4", "", kTH1D, {nchAxis}); + histogramRegistry.add("nch5", "", kTH1D, {nchAxis}); + histogramRegistry.add("nch6", "", kTH1D, {nchAxis}); + histogramRegistry.add("nch7", "", kTH1D, {nchAxis}); + histogramRegistry.add("nch8", "", kTH1D, {nchAxis}); + histogramRegistry.add("nch9", "", kTH1D, {nchAxis}); + histogramRegistry.add("nch_pos", "", kTH1D, {nchAxis}); + histogramRegistry.add("nch_neg", "", kTH1D, {nchAxis}); + histogramRegistry.add("nch_negpos", "", kTH1D, {nchpAxis}); + + histogramRegistry.add("nch_cent", "", kTH2D, {centAxis, nchAxis}); + histogramRegistry.add("nch_pos_cent", "", kTH2D, {centAxis, nchAxis}); + histogramRegistry.add("nch_neg_cent", "", kTH2D, {centAxis, nchAxis}); + histogramRegistry.add("nch_negpos_cent", "", kTH2D, {centAxis, nchpAxis}); + } template - bool selCollision(C const& coll) + bool selCollision(C const& coll, float& cent, float& mult) { + histogramRegistry.fill(HIST("hVtxZ_before"), coll.posZ()); + if (std::abs(coll.posZ()) > vertexZcut) { return false; - } // Reject the collisions with large vertex-z + } if constexpr (run == kRun3) { @@ -257,8 +262,75 @@ struct NetchargeFluctuations { if (cItsTpcVtx && !coll.selection_bit(aod::evsel::kIsVertexITSTPC)) { return false; } + histogramRegistry.fill(HIST("hVtxZ_after"), coll.posZ()); + histogramRegistry.fill(HIST("hCentrality"), cent); + histogramRegistry.fill(HIST("hMultiplicity"), mult); - return true; // if all checks pass, accept the collision + return true; + } + template + void fillBeforeQA(T const& track) + { + histogramRegistry.fill(HIST("hTPCchi2perCluster_before"), track.tpcChi2NCl()); + histogramRegistry.fill(HIST("hITSchi2perCluster_before"), track.itsChi2NCl()); + histogramRegistry.fill(HIST("hTPCCrossedrows_before"), track.tpcNClsCrossedRows()); + histogramRegistry.fill(HIST("hDcaXY_before"), track.dcaXY()); + histogramRegistry.fill(HIST("hDcaZ_before"), track.dcaZ()); + histogramRegistry.fill(HIST("hPtDcaXY_before"), track.pt(), track.dcaXY()); + histogramRegistry.fill(HIST("hPtDcaZ_before"), track.pt(), track.dcaZ()); + } + + template + void fillAfterQA(T const& track) + { + histogramRegistry.fill(HIST("hDcaXY_after"), track.dcaXY()); + histogramRegistry.fill(HIST("hDcaZ_after"), track.dcaZ()); + histogramRegistry.fill(HIST("hPt"), track.pt()); + histogramRegistry.fill(HIST("hEta"), track.eta()); + histogramRegistry.fill(HIST("hPtDcaXY_after"), track.pt(), track.dcaXY()); + histogramRegistry.fill(HIST("hPtDcaZ_after"), track.pt(), track.dcaZ()); + histogramRegistry.fill(HIST("hTPCCrossedrows_after"), track.tpcNClsCrossedRows()); + histogramRegistry.fill(HIST("hTPCchi2perCluster_after"), track.tpcChi2NCl()); + histogramRegistry.fill(HIST("hITSchi2perCluster_after"), track.itsChi2NCl()); + } + + template + void nchDistribution(N const& nch, C const& cent) + { + constexpr int kCent0Min = 0, kCent0Max = 5; + constexpr int kCent1Min = 5, kCent1Max = 10; + constexpr int kCent2Min = 10, kCent2Max = 20; + constexpr int kCent3Min = 20, kCent3Max = 30; + constexpr int kCent4Min = 30, kCent4Max = 40; + constexpr int kCent5Min = 40, kCent5Max = 50; + constexpr int kCent6Min = 50, kCent6Max = 60; + constexpr int kCent7Min = 60, kCent7Max = 70; + constexpr int kCent8Min = 70, kCent8Max = 80; + constexpr int kCent9Min = 80, kCent9Max = 90; + + histogramRegistry.fill(HIST("nch"), nch); + histogramRegistry.fill(HIST("nch_cent"), cent, nch); + + if (cent >= kCent0Min && cent < kCent0Max) + histogramRegistry.fill(HIST("nch0"), nch); + else if (cent >= kCent1Min && cent < kCent1Max) + histogramRegistry.fill(HIST("nch1"), nch); + else if (cent >= kCent2Min && cent < kCent2Max) + histogramRegistry.fill(HIST("nch2"), nch); + else if (cent >= kCent3Min && cent < kCent3Max) + histogramRegistry.fill(HIST("nch3"), nch); + else if (cent >= kCent4Min && cent < kCent4Max) + histogramRegistry.fill(HIST("nch4"), nch); + else if (cent >= kCent5Min && cent < kCent5Max) + histogramRegistry.fill(HIST("nch5"), nch); + else if (cent >= kCent6Min && cent < kCent6Max) + histogramRegistry.fill(HIST("nch6"), nch); + else if (cent >= kCent7Min && cent < kCent7Max) + histogramRegistry.fill(HIST("nch7"), nch); + else if (cent >= kCent8Min && cent < kCent8Max) + histogramRegistry.fill(HIST("nch8"), nch); + else if (cent >= kCent9Min && cent < kCent9Max) + histogramRegistry.fill(HIST("nch9"), nch); } template @@ -268,22 +340,26 @@ struct NetchargeFluctuations { return false; } // accept only global tracks - if (std::fabs(track.dcaXY()) > dcaXYCut) { + if (std::fabs(track.eta()) >= etaCut) { return false; } - if (std::fabs(track.dcaZ()) > dcaZCut) { + if (track.pt() <= ptMinCut || track.pt() >= ptMaxCut) { return false; } - if (std::fabs(track.eta()) >= etaCut) { + if (track.sign() == 0) { return false; } + /* if (std::fabs(track.dcaXY()) > dcaXYCut) { + return false; + } - if (track.pt() <= ptMinCut || track.pt() >= ptMaxCut) { - return false; - } + if (std::fabs(track.dcaZ()) > dcaZCut) { + return false ; + }*/ + /* if (track.tpcNClsCrossedRows() < tpcCrossCut) { return false; } @@ -296,162 +372,115 @@ struct NetchargeFluctuations { return false; } - return true; // if all checks pass, accept the collision +*/ + + return true; } template - void calculation(C const& coll, T const& tracks) + void calculationData(C const& coll, T const& tracks) { - histogramRegistry.fill(HIST("hVtxZ_before"), coll.posZ()); - - if (!selCollision(coll)) { + float cent = -1, mult = -1; + if (!selCollision(coll, cent, mult)) { return; } - - histogramRegistry.fill(HIST("hVtxZ_after"), coll.posZ()); - histogramRegistry.fill(HIST("hCentrality"), cent); - histogramRegistry.fill(HIST("hMultiplicity"), mult); - int fpos = 0, fneg = 0, posneg = 0, termn = 0, termp = 0; - + int nch = 0; for (const auto& track : tracks) { - histogramRegistry.fill(HIST("hTPCchi2perCluster_before"), track.tpcChi2NCl()); - histogramRegistry.fill(HIST("hITSchi2perCluster_before"), track.itsChi2NCl()); - histogramRegistry.fill(HIST("hTPCCrossedrows_before"), track.tpcNClsCrossedRows()); - histogramRegistry.fill(HIST("hDcaXY_before"), track.dcaXY()); - histogramRegistry.fill(HIST("hDcaZ_before"), track.dcaZ()); - histogramRegistry.fill(HIST("hPtDcaXY_before"), track.pt(), track.dcaXY()); - histogramRegistry.fill(HIST("hPtDcaZ_before"), track.pt(), track.dcaZ()); + fillBeforeQA(track); if (!selTrack(track)) { continue; } - if (track.sign() == 0) - continue; - histogramRegistry.fill(HIST("hDcaXY_after"), track.dcaXY()); - histogramRegistry.fill(HIST("hDcaZ_after"), track.dcaZ()); - histogramRegistry.fill(HIST("hPt"), track.pt()); - histogramRegistry.fill(HIST("hEta"), track.eta()); - histogramRegistry.fill(HIST("hPtDcaXY_after"), track.pt(), track.dcaXY()); - histogramRegistry.fill(HIST("hPtDcaZ_after"), track.pt(), track.dcaZ()); - histogramRegistry.fill(HIST("hTPCCrossedrows_after"), track.tpcNClsCrossedRows()); - histogramRegistry.fill(HIST("hTPCchi2perCluster_after"), track.tpcChi2NCl()); - histogramRegistry.fill(HIST("hITSchi2perCluster_after"), track.itsChi2NCl()); + nch += 1; + fillAfterQA(track); if (track.sign() == 1) { fpos += 1; - termp = fpos * (fpos - 1); - } - - if (track.sign() == -1) { + } else if (track.sign() == -1) { fneg += 1; - termn = fneg * (fneg - 1); } + } // track + termp = fpos * (fpos - 1); + termn = fneg * (fneg - 1); + posneg = fpos * fneg; + + nchDistribution(nch, cent); - posneg = fpos * fneg; - netCharge(fpos, fneg, fpos * fpos, fneg * fneg, termp, termn, posneg, cent); - } // tracks + histogramRegistry.fill(HIST("nch_pos"), fpos); + histogramRegistry.fill(HIST("nch_pos_cent"), cent, fpos); + histogramRegistry.fill(HIST("nch_neg"), fneg); + histogramRegistry.fill(HIST("nch_neg_cent"), cent, fneg); + histogramRegistry.fill(HIST("nch_negpos"), posneg); + histogramRegistry.fill(HIST("nch_negpos_cent"), cent, posneg); - return; + netCharge(fpos, fneg, fpos * fpos, fneg * fneg, termp, termn, posneg, cent); } template - void histosMcRecoGen(C const& coll, T const& inputTracks, M const& mcCollisions, P const& mcParticles) + void calculationMc(C const& coll, T const& inputTracks, M const& mcCollisions, P const& mcParticles) { (void)mcCollisions; + if (!coll.has_mcCollision()) { return; } - histogramRegistry.fill(HIST("gen_hVtxZ_before"), coll.mcCollision().posZ()); - histogramRegistry.fill(HIST("rec_hVtxZ_before"), coll.posZ()); - if (cNoItsROBorder && !coll.selection_bit(aod::evsel::kNoITSROFrameBorder)) { - return; - } - if (cTFBorder && !coll.selection_bit(aod::evsel::kNoTimeFrameBorder)) { - return; - } - if (cPileupReject && !coll.selection_bit(aod::evsel::kNoSameBunchPileup)) { - return; - } - if (cZVtxTimeDiff && !coll.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV)) { - return; - } - if (cItsTpcVtx && !coll.selection_bit(aod::evsel::kIsVertexITSTPC)) { - return; - } + float cent = -1, mult = -1; - if (std::abs(coll.posZ()) > vertexZcut) { + if (!selCollision(coll, cent, mult)) { return; } - if constexpr (run == kRun3) { - if (cSel8Trig && !coll.sel8()) { - return; - } - - cent = coll.centFT0M(); // centrality for run3 - mult = coll.multFT0M(); - } else { - if (cSel7Trig && !coll.sel7()) { - return; - } - - cent = coll.centRun2V0M(); // centrality for run2 - mult = coll.multFV0M(); // multiplicity for run2 - } - - histogramRegistry.fill(HIST("rec_hVtxZ_after"), coll.posZ()); - histogramRegistry.fill(HIST("rec_hCentrality"), cent); - histogramRegistry.fill(HIST("rec_hMultiplicity"), mult); - - int posRec = 0, negRec = 0, posNegRec = 0, termNRec = 0, termPRec = 0; - int posGen = 0, negGen = 0, posNegGen = 0, termNGen = 0, termPGen = 0; + int fpos = 0, fneg = 0, posneg = 0, termn = 0, termp = 0; + int nch = 0; - const auto& mccolgen = coll.template mcCollision_as(); - if (std::abs(mccolgen.posZ()) > vertexZcut) { - return; - } + for (const auto& track : inputTracks) { - const auto& mcpartgen = mcParticles.sliceByCached(aod::mcparticle::mcCollisionId, mccolgen.globalIndex(), cache); - histogramRegistry.fill(HIST("gen_hVtxZ_after"), mccolgen.posZ()); + fillBeforeQA(track); - for (const auto& track : inputTracks) { - if (!track.isGlobalTrack()) - continue; - if (std::fabs(track.dcaXY()) > dcaXYCut) - continue; - if (std::fabs(track.dcaZ()) > dcaZCut) - continue; - if (std::fabs(track.eta()) > etaCut) - continue; - if ((track.pt() <= ptMinCut) || (track.pt() >= ptMaxCut)) - continue; - if (track.sign() == 0) { + if (!selTrack(track)) { continue; } + nch += 1; - histogramRegistry.fill(HIST("rec_hPt"), track.pt()); - histogramRegistry.fill(HIST("rec_hEta"), track.eta()); + fillAfterQA(track); if (track.sign() == 1) { - posRec += 1; - termPRec = posRec * (posRec - 1); + fpos += 1; + } else if (track.sign() == -1) { + fneg += 1; } + } // track + termp = fpos * (fpos - 1); + termn = fneg * (fneg - 1); + posneg = fpos * fneg; - if (track.sign() == -1) { - negRec += 1; - termNRec = negRec * (negRec - 1); - } + nchDistribution(nch, cent); - posNegRec = posRec * negRec; + histogramRegistry.fill(HIST("nch_pos"), fpos); + histogramRegistry.fill(HIST("nch_pos_cent"), cent, fpos); + histogramRegistry.fill(HIST("nch_neg"), fneg); + histogramRegistry.fill(HIST("nch_neg_cent"), cent, fneg); + histogramRegistry.fill(HIST("nch_negpos"), posneg); + histogramRegistry.fill(HIST("nch_negpos_cent"), cent, posneg); - netCharge(posRec, negRec, posRec * posRec, negRec * negRec, - termPRec, termNRec, posNegRec, cent); - } // loop over inputTracks (reco) + netCharge(fpos, fneg, fpos * fpos, fneg * fneg, termp, termn, posneg, cent); + + int posGen = 0, negGen = 0, posNegGen = 0, termNGen = 0, termPGen = 0; + + const auto& mccolgen = coll.template mcCollision_as(); + + /* if (std::abs(mccolgen.posZ()) > vertexZcut) { + return; + }*/ + + const auto& mcpartgen = mcParticles.sliceByCached(aod::mcparticle::mcCollisionId, mccolgen.globalIndex(), cache); + histogramRegistry.fill(HIST("gen_hVtxZ_after"), mccolgen.posZ()); for (const auto& mcpart : mcpartgen) { + if (!mcpart.isPhysicalPrimary()) { continue; } @@ -461,38 +490,40 @@ struct NetchargeFluctuations { if (pd != nullptr) { sign = pd->Charge() / 3.; } + if (sign == 0) { continue; } - // auto pdgServicecode = mcpart.pdgCode(); + if (std::abs(pid) != kElectron && std::abs(pid) != kMuonMinus && std::abs(pid) != kPiPlus && std::abs(pid) != kKPlus && std::abs(pid) != kProton) { continue; } if (std::fabs(mcpart.eta()) > etaCut) continue; + if ((mcpart.pt() <= ptMinCut) || (mcpart.pt() >= ptMaxCut)) continue; + histogramRegistry.fill(HIST("gen_hPt"), mcpart.pt()); histogramRegistry.fill(HIST("gen_hEta"), mcpart.eta()); histogramRegistry.fill(HIST("gen_hSign"), sign); if (sign == 1) { posGen += 1; - termPGen = posGen * (posGen - 1); } if (sign == -1) { negGen += 1; - termNGen = negGen * (negGen - 1); } + } // particle + termPGen = posGen * (posGen - 1); + termNGen = negGen * (negGen - 1); + posNegGen = posGen * negGen; - posNegGen = posGen * negGen; - - netChargeGen(posGen, negGen, posGen * posGen, negGen * negGen, - termPGen, termNGen, posNegGen, cent); + netChargeGen(posGen, negGen, posGen * posGen, negGen * negGen, + termPGen, termNGen, posNegGen, cent); - } // particle } // void SliceCache cache; @@ -500,14 +531,14 @@ struct NetchargeFluctuations { void processDataRun3(aod::MyCollisionRun3 const& coll, aod::MyTracks const& tracks) { - calculation(coll, tracks); + calculationData(coll, tracks); } - PROCESS_SWITCH(NetchargeFluctuations, processDataRun3, "Process for Run3 DATA", false); + PROCESS_SWITCH(NetchargeFluctuations, processDataRun3, "Process for Run3 DATA", true); void processDataRun2(aod::MyCollisionRun2 const& coll, aod::MyTracks const& tracks) { - calculation(coll, tracks); + calculationData(coll, tracks); } PROCESS_SWITCH(NetchargeFluctuations, processDataRun2, "Process for Run2 DATA", false); @@ -515,15 +546,15 @@ struct NetchargeFluctuations { void processMcRun3(aod::MyMCCollisionRun3 const& coll, aod::MyMCTracks const& inputTracks, aod::McCollisions const& mcCollisions, aod::McParticles const& mcParticles) { - histosMcRecoGen(coll, inputTracks, mcCollisions, mcParticles); + calculationMc(coll, inputTracks, mcCollisions, mcParticles); } - PROCESS_SWITCH(NetchargeFluctuations, processMcRun3, "Process reconstructed", true); + PROCESS_SWITCH(NetchargeFluctuations, processMcRun3, "Process reconstructed", false); void processMcRun2(aod::MyMCCollisionRun2 const& coll, aod::MyMCTracks const& inputTracks, aod::McCollisions const& mcCollisions, aod::McParticles const& mcParticles) { - histosMcRecoGen(coll, inputTracks, mcCollisions, mcParticles); + calculationMc(coll, inputTracks, mcCollisions, mcParticles); } PROCESS_SWITCH(NetchargeFluctuations, processMcRun2, "Process reconstructed", false); From b7c8c7246f7135c2aefa52bba5db37515840361a Mon Sep 17 00:00:00 2001 From: Anton Alkin Date: Fri, 20 Jun 2025 14:36:53 +0200 Subject: [PATCH 160/871] [PWGDQ] Fix for invalid cursor call with 8 arguments instead of 9 (#11700) --- PWGDQ/Tasks/dqEfficiency_withAssoc.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PWGDQ/Tasks/dqEfficiency_withAssoc.cxx b/PWGDQ/Tasks/dqEfficiency_withAssoc.cxx index 397502ed020..d5531f18dc1 100644 --- a/PWGDQ/Tasks/dqEfficiency_withAssoc.cxx +++ b/PWGDQ/Tasks/dqEfficiency_withAssoc.cxx @@ -2077,7 +2077,7 @@ struct AnalysisSameEventPairing { fHistMan->FillHistClass(Form("MCTruthGenPair_%s", sig->GetName()), VarManager::fgValues); if (useMiniTree.fConfigMiniTree) { // WARNING! To be checked - dileptonMiniTreeGen(mcDecision, -999, t1.pt(), t1.eta(), t1.phi(), t2.pt(), t2.eta(), t2.phi()); + dileptonMiniTreeGen(mcDecision, -999, VarManager::fgValues[VarManager::kCentFT0C], t1.pt(), t1.eta(), t1.phi(), t2.pt(), t2.eta(), t2.phi()); } } isig++; From 30b4655b333113fe800406a92101ac82d37dc382 Mon Sep 17 00:00:00 2001 From: Jesper Gumprecht <113693781+jesgum@users.noreply.github.com> Date: Fri, 20 Jun 2025 15:17:06 +0200 Subject: [PATCH 161/871] [ALICE3] Changes to multi-charm datamodel (#11704) --- ALICE3/DataModel/OTFMulticharm.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/ALICE3/DataModel/OTFMulticharm.h b/ALICE3/DataModel/OTFMulticharm.h index c04ad88b4bf..955654c5b47 100644 --- a/ALICE3/DataModel/OTFMulticharm.h +++ b/ALICE3/DataModel/OTFMulticharm.h @@ -116,24 +116,24 @@ DECLARE_SOA_TABLE(MCharmCores, "AOD", "MCharmCores", otfmulticharm::Eta, otfmulticharm::XiDCAxy, - otfmulticharm::XicDCAxy, - otfmulticharm::XiccDCAxy, otfmulticharm::XiDCAz, + otfmulticharm::XicDCAxy, otfmulticharm::XicDCAz, + otfmulticharm::XiccDCAxy, otfmulticharm::XiccDCAz, otfmulticharm::PiFromXiDCAxy, - otfmulticharm::PiFromLaDCAxy, - otfmulticharm::PrFromLaDCAxy, otfmulticharm::PiFromXiDCAz, + otfmulticharm::PiFromLaDCAxy, otfmulticharm::PiFromLaDCAz, + otfmulticharm::PrFromLaDCAxy, otfmulticharm::PrFromLaDCAz, otfmulticharm::Pi1cDCAxy, - otfmulticharm::Pi2cDCAxy, - otfmulticharm::PiccDCAxy, otfmulticharm::Pi1cDCAz, + otfmulticharm::Pi2cDCAxy, otfmulticharm::Pi2cDCAz, + otfmulticharm::PiccDCAxy, otfmulticharm::PiccDCAz, otfmulticharm::XicDecayRadius2D, From 7fd49081fea72997165b71f056e5f2ee0ff23941 Mon Sep 17 00:00:00 2001 From: ynishida-style Date: Fri, 20 Jun 2025 22:25:00 +0900 Subject: [PATCH 162/871] [PWGJE] Improve jet shape calculation logic in jetShape.cxx (#11701) --- PWGJE/Tasks/jetShape.cxx | 58 +++++++++++++++++++--------------------- 1 file changed, 27 insertions(+), 31 deletions(-) diff --git a/PWGJE/Tasks/jetShape.cxx b/PWGJE/Tasks/jetShape.cxx index b52bee180ab..00d2a7f3eea 100644 --- a/PWGJE/Tasks/jetShape.cxx +++ b/PWGJE/Tasks/jetShape.cxx @@ -13,28 +13,24 @@ /// \author Yuto Nishida /// \brief Task for measuring the dependence of the jet shape function rho(r) on the distance r from the jet axis. +#include "PWGJE/Core/FastJetUtilities.h" #include "PWGJE/Core/JetDerivedDataUtilities.h" +#include "PWGJE/Core/JetUtilities.h" #include "PWGJE/DataModel/Jet.h" -#include "PWGJE/DataModel/JetReducedData.h" -#include "PWGJE/DataModel/JetSubtraction.h" #include "Common/Core/RecoDecay.h" -#include "Common/DataModel/PIDResponseTOF.h" -#include "Common/DataModel/PIDResponseTPC.h" +#include "Common/Core/TrackSelection.h" +#include "Common/Core/TrackSelectionDefaults.h" +#include "Common/DataModel/EventSelection.h" #include "Common/DataModel/TrackSelectionTables.h" #include "Framework/ASoA.h" #include "Framework/AnalysisDataModel.h" #include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" -#include -#include -#include -#include -#include +#include "Framework/runDataProcessing.h" #include -#include #include #include @@ -44,10 +40,10 @@ using namespace o2::framework::expressions; struct JetShapeTask { HistogramRegistry registry{"registry", - {{"tpcTofPi", "tpcTofPi", {HistType::kTHnSparseD, {{101, -10.1f, 10.1f}, {20, -10, 10}, {25, 0, 5}, {14, 0, 7}}}}, + {{"tpcTofPi", "tpcTofPi", {HistType::kTHnSparseD, {{101, -10.1f, 10.1f}, {20, -10, 10}, {25, 0, 5}, {14, 0, 0.7}}}}, {"tpcPi", "tpcPi", {HistType::kTH2F, {{100, 0, 5}, {401, -10.025f, 10.025f}}}}, {"tofPi", "tofPi", {HistType::kTH2F, {{100, 0, 5}, {401, -10.025f, 10.025f}}}}, - {"tpcTofPr", "tpcTofPr", {HistType::kTHnSparseD, {{101, -10.1f, 10.1f}, {20, -10, 10}, {25, 0, 5}, {14, 0, 7}}}}, + {"tpcTofPr", "tpcTofPr", {HistType::kTHnSparseD, {{101, -10.1f, 10.1f}, {20, -10, 10}, {25, 0, 5}, {14, 0, 0.7}}}}, {"tpcPr", "tpcPr", {HistType::kTH2F, {{100, 0, 5}, {401, -10.025f, 10.025f}}}}, {"tofPr", "tofPr", {HistType::kTH2F, {{100, 0, 5}, {401, -10.025f, 10.025f}}}}, {"tpcDedx", "tpcDedx", {HistType::kTH2F, {{500, 0, 5}, {1000, 0, 1000}}}}, @@ -154,18 +150,21 @@ struct JetShapeTask { void processJetShape(soa::Filtered>::iterator const& collision, aod::JetTracks const& tracks, soa::Join const& jets) { - std::vector ptDensity(distanceCategory->size() - 1, 0.f); - std::vector ptDensityBg1(distanceCategory->size() - 1, 0.f); - std::vector ptDensityBg2(distanceCategory->size() - 1, 0.f); - for (auto const& jet : jets) { if (!isAcceptedJet(jet)) { continue; } + std::vector trackPtSum(distanceCategory->size() - 1, 0.f); + std::vector trackPtSumBg1(distanceCategory->size() - 1, 0.f); + std::vector trackPtSumBg2(distanceCategory->size() - 1, 0.f); + // Get underlying event subtracted jet.pt() as ptCorr float ptCorr = jet.pt() - collision.rho() * jet.area(); + float phiBg1 = jet.phi() + (o2::constants::math::PIHalf); + float phiBg2 = jet.phi() - (o2::constants::math::PIHalf); + for (const auto& track : tracks) { float preDeltaPhi1 = track.phi() - jet.phi(); float deltaPhi1 = RecoDecay::constrainAngle(preDeltaPhi1); @@ -178,20 +177,13 @@ struct JetShapeTask { registry.fill(HIST("ptVsCentrality"), collision.centrality(), track.pt()); // calculate compornents of jetshapefunction rho(r) - std::vector trackPtSum(distanceCategory->size() - 1, 0.f); - std::vector trackPtSumBg1(distanceCategory->size() - 1, 0.f); - std::vector trackPtSumBg2(distanceCategory->size() - 1, 0.f); - - float phiBg1 = jet.phi() + (o2::constants::math::PIHalf); - float phiBg2 = jet.phi() - (o2::constants::math::PIHalf); float preDeltaPhiBg1 = track.phi() - phiBg1; - float preDeltaPhiBg2 = track.phi() - phiBg2; - float deltaPhiBg1 = RecoDecay::constrainAngle(preDeltaPhiBg1); - float deltaPhiBg2 = RecoDecay::constrainAngle(preDeltaPhiBg2); - float distanceBg1 = std::sqrt(deltaEta * deltaEta + deltaPhiBg1 * deltaPhiBg1); + + float preDeltaPhiBg2 = track.phi() - phiBg2; + float deltaPhiBg2 = RecoDecay::constrainAngle(preDeltaPhiBg2); float distanceBg2 = std::sqrt(deltaEta * deltaEta + deltaPhiBg2 * deltaPhiBg2); for (size_t i = 0; i < distanceCategory->size() - 1; i++) { @@ -202,12 +194,16 @@ struct JetShapeTask { if (distanceCategory->at(i) <= distanceBg2 && distanceBg2 < distanceCategory->at(i + 1)) trackPtSumBg2[i] += track.pt(); } + } - for (size_t i = 0; i < distanceCategory->size() - 1; i++) { - ptDensity[i] += trackPtSum[i] / ((distanceCategory->at(i + 1) - distanceCategory->at(i)) * ptCorr); - ptDensityBg1[i] += trackPtSumBg1[i] / ((distanceCategory->at(i + 1) - distanceCategory->at(i)) * ptCorr); - ptDensityBg2[i] += trackPtSumBg2[i] / ((distanceCategory->at(i + 1) - distanceCategory->at(i)) * ptCorr); - } + std::vector ptDensity(distanceCategory->size() - 1, 0.f); + std::vector ptDensityBg1(distanceCategory->size() - 1, 0.f); + std::vector ptDensityBg2(distanceCategory->size() - 1, 0.f); + + for (size_t i = 0; i < distanceCategory->size() - 1; i++) { + ptDensity[i] += trackPtSum[i] / ((distanceCategory->at(i + 1) - distanceCategory->at(i)) * ptCorr); + ptDensityBg1[i] += trackPtSumBg1[i] / ((distanceCategory->at(i + 1) - distanceCategory->at(i)) * ptCorr); + ptDensityBg2[i] += trackPtSumBg2[i] / ((distanceCategory->at(i + 1) - distanceCategory->at(i)) * ptCorr); } registry.fill(HIST("jetPt"), jet.pt()); From 13b446a6b0e31c8bfac0c952159131ccfba0cdd3 Mon Sep 17 00:00:00 2001 From: dajones2 <140733426+dajones2@users.noreply.github.com> Date: Fri, 20 Jun 2025 14:58:22 +0100 Subject: [PATCH 163/871] [PWGJE] Adding dphi cut for recoil jet response (#11703) --- PWGJE/Tasks/jetHadronRecoil.cxx | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/PWGJE/Tasks/jetHadronRecoil.cxx b/PWGJE/Tasks/jetHadronRecoil.cxx index 03e06f5d07a..bf07f01740f 100644 --- a/PWGJE/Tasks/jetHadronRecoil.cxx +++ b/PWGJE/Tasks/jetHadronRecoil.cxx @@ -530,16 +530,17 @@ struct JetHadronRecoil { float dphip = RecoDecay::constrainAngle(jetTag.phi() - phiTTPart); dRp = getWTAaxisDifference(jetTag, mcpjetsWTA, particles, true); - - registry.fill(HIST("hPtMatched"), jetBase.pt() - (rho * jetBase.area()), jetTag.pt(), weight); - registry.fill(HIST("hPhiMatched"), dphi, dphip, weight); - registry.fill(HIST("hPtResolution"), jetTag.pt(), (jetTag.pt() - (jetBase.pt() - (rho * jetBase.area()))) / jetTag.pt(), weight); - registry.fill(HIST("hPhiResolution"), dphip, dphip - dphi, weight); - registry.fill(HIST("hDeltaRMatched"), dR, dRp, weight); - registry.fill(HIST("hDeltaRResolution"), jetTag.pt(), dRp - dR, weight); - registry.fill(HIST("hFullMatching"), jetBase.pt() - (rho * jetBase.area()), jetTag.pt(), dphi, dphip, dR, dRp, weight); - registry.fill(HIST("hPtMatched1d"), jetTag.pt(), weight); - registry.fill(HIST("hDeltaRMatched1d"), dRp, weight); + if ((std::abs(dphi - o2::constants::math::PI) < 0.6) || (std::abs(dphip - o2::constants::math::PI) < 0.6)) { + registry.fill(HIST("hPtMatched"), jetBase.pt() - (rho * jetBase.area()), jetTag.pt(), weight); + registry.fill(HIST("hPhiMatched"), dphi, dphip, weight); + registry.fill(HIST("hPtResolution"), jetTag.pt(), (jetTag.pt() - (jetBase.pt() - (rho * jetBase.area()))) / jetTag.pt(), weight); + registry.fill(HIST("hPhiResolution"), dphip, dphip - dphi, weight); + registry.fill(HIST("hDeltaRMatched"), dR, dRp, weight); + registry.fill(HIST("hDeltaRResolution"), jetTag.pt(), dRp - dR, weight); + registry.fill(HIST("hFullMatching"), jetBase.pt() - (rho * jetBase.area()), jetTag.pt(), dphi, dphip, dR, dRp, weight); + registry.fill(HIST("hPtMatched1d"), jetTag.pt(), weight); + registry.fill(HIST("hDeltaRMatched1d"), dRp, weight); + } } } } From 7fb2719e9faafa6a64837cbf1114d2f50befc93a Mon Sep 17 00:00:00 2001 From: Daiki Sekihata Date: Fri, 20 Jun 2025 19:05:18 +0200 Subject: [PATCH 164/871] [PWGEM/Dilepton] fix for thresholds in PID ML (#11705) --- PWGEM/Dilepton/Core/Dilepton.h | 8 +-- PWGEM/Dilepton/Core/DileptonMC.h | 8 +-- PWGEM/Dilepton/Core/PhotonHBT.h | 63 ++++++++++--------- PWGEM/Dilepton/Core/SingleTrackQC.h | 8 +-- PWGEM/Dilepton/Core/SingleTrackQCMC.h | 8 +-- .../TableProducer/skimmerPrimaryElectron.cxx | 8 +-- 6 files changed, 52 insertions(+), 51 deletions(-) diff --git a/PWGEM/Dilepton/Core/Dilepton.h b/PWGEM/Dilepton/Core/Dilepton.h index bd8d07a952d..69e5d074fc0 100644 --- a/PWGEM/Dilepton/Core/Dilepton.h +++ b/PWGEM/Dilepton/Core/Dilepton.h @@ -707,14 +707,14 @@ struct Dilepton { if (dielectroncuts.cfg_pid_scheme == static_cast(DielectronCut::PIDSchemes::kPIDML)) { // please call this at the end of DefineDileptonCut static constexpr int nClassesMl = 2; - const std::vector cutDirMl = {o2::cuts_ml::CutGreater, o2::cuts_ml::CutNot}; - const std::vector labelsClasses = {"Signal", "Background"}; + const std::vector cutDirMl = {o2::cuts_ml::CutNot, o2::cuts_ml::CutSmaller}; + const std::vector labelsClasses = {"Background", "Signal"}; const uint32_t nBinsMl = dielectroncuts.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] = dielectroncuts.cutsMl.value[i]; - cutsMlArr[i][1] = 0.; + cutsMlArr[i][0] = 0.; + cutsMlArr[i][1] = dielectroncuts.cutsMl.value[i]; } o2::framework::LabeledArray cutsMl = {cutsMlArr[0], nBinsMl, nClassesMl, labelsBins, labelsClasses}; diff --git a/PWGEM/Dilepton/Core/DileptonMC.h b/PWGEM/Dilepton/Core/DileptonMC.h index e23b18d56db..964ac885cb8 100644 --- a/PWGEM/Dilepton/Core/DileptonMC.h +++ b/PWGEM/Dilepton/Core/DileptonMC.h @@ -672,14 +672,14 @@ struct DileptonMC { if (dielectroncuts.cfg_pid_scheme == static_cast(DielectronCut::PIDSchemes::kPIDML)) { // please call this at the end of DefineDileptonCut static constexpr int nClassesMl = 2; - const std::vector cutDirMl = {o2::cuts_ml::CutGreater, o2::cuts_ml::CutNot}; - const std::vector labelsClasses = {"Signal", "Background"}; + const std::vector cutDirMl = {o2::cuts_ml::CutNot, o2::cuts_ml::CutSmaller}; + const std::vector labelsClasses = {"Background", "Signal"}; const uint32_t nBinsMl = dielectroncuts.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] = dielectroncuts.cutsMl.value[i]; - cutsMlArr[i][1] = 0.; + cutsMlArr[i][0] = 0.; + cutsMlArr[i][1] = dielectroncuts.cutsMl.value[i]; } o2::framework::LabeledArray cutsMl = {cutsMlArr[0], nBinsMl, nClassesMl, labelsBins, labelsClasses}; diff --git a/PWGEM/Dilepton/Core/PhotonHBT.h b/PWGEM/Dilepton/Core/PhotonHBT.h index 99be337aa67..88a7dd2d60b 100644 --- a/PWGEM/Dilepton/Core/PhotonHBT.h +++ b/PWGEM/Dilepton/Core/PhotonHBT.h @@ -17,40 +17,41 @@ #ifndef PWGEM_DILEPTON_CORE_PHOTONHBT_H_ #define PWGEM_DILEPTON_CORE_PHOTONHBT_H_ +#include "PWGEM/Dilepton/Core/DielectronCut.h" +#include "PWGEM/Dilepton/Core/EMEventCut.h" +#include "PWGEM/Dilepton/Utils/EMTrack.h" +#include "PWGEM/Dilepton/Utils/EMTrackUtilities.h" +#include "PWGEM/Dilepton/Utils/EventHistograms.h" +#include "PWGEM/Dilepton/Utils/EventMixingHandler.h" +#include "PWGEM/Dilepton/Utils/MlResponseDielectronSingleTrack.h" +#include "PWGEM/PhotonMeson/Core/V0PhotonCut.h" +#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" + +#include "Tools/ML/MlResponse.h" + +#include "CCDB/BasicCCDBManager.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "DataFormatsParameters/GRPObject.h" +#include "DetectorsBase/GeometryManager.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" + +#include "Math/GenVector/Boost.h" +#include "Math/Vector3D.h" +#include "Math/Vector4D.h" +#include "TString.h" + #include #include #include #include +#include #include -#include #include +#include #include -#include - -#include "TString.h" -#include "Math/Vector4D.h" -#include "Math/Vector3D.h" -#include "Math/GenVector/Boost.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.h" - -#include "DetectorsBase/GeometryManager.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "CCDB/BasicCCDBManager.h" -#include "Tools/ML/MlResponse.h" - -#include "PWGEM/Dilepton/Utils/EMTrackUtilities.h" -#include "PWGEM/Dilepton/Core/EMEventCut.h" -#include "PWGEM/Dilepton/Core/DielectronCut.h" -#include "PWGEM/Dilepton/Utils/EMTrack.h" -#include "PWGEM/Dilepton/Utils/EventMixingHandler.h" -#include "PWGEM/Dilepton/Utils/EventHistograms.h" -#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" -#include "PWGEM/PhotonMeson/Core/V0PhotonCut.h" -#include "PWGEM/Dilepton/Utils/MlResponseDielectronSingleTrack.h" namespace o2::aod::pwgem::dilepton::core::photonhbt { @@ -589,14 +590,14 @@ struct PhotonHBT { if (dielectroncuts.cfg_pid_scheme == static_cast(DielectronCut::PIDSchemes::kPIDML)) { // please call this at the end of DefineDileptonCut static constexpr int nClassesMl = 2; - const std::vector cutDirMl = {o2::cuts_ml::CutGreater, o2::cuts_ml::CutNot}; - const std::vector labelsClasses = {"Signal", "Background"}; + const std::vector cutDirMl = {o2::cuts_ml::CutNot, o2::cuts_ml::CutSmaller}; + const std::vector labelsClasses = {"Background", "Signal"}; const uint32_t nBinsMl = dielectroncuts.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] = dielectroncuts.cutsMl.value[i]; - cutsMlArr[i][1] = 0.; + cutsMlArr[i][0] = 0.; + cutsMlArr[i][1] = dielectroncuts.cutsMl.value[i]; } o2::framework::LabeledArray cutsMl = {cutsMlArr[0], nBinsMl, nClassesMl, labelsBins, labelsClasses}; diff --git a/PWGEM/Dilepton/Core/SingleTrackQC.h b/PWGEM/Dilepton/Core/SingleTrackQC.h index 2d3389354d9..c0782033a39 100644 --- a/PWGEM/Dilepton/Core/SingleTrackQC.h +++ b/PWGEM/Dilepton/Core/SingleTrackQC.h @@ -415,14 +415,14 @@ struct SingleTrackQC { if (dielectroncuts.cfg_pid_scheme == static_cast(DielectronCut::PIDSchemes::kPIDML)) { // please call this at the end of DefineDileptonCut static constexpr int nClassesMl = 2; - const std::vector cutDirMl = {o2::cuts_ml::CutGreater, o2::cuts_ml::CutNot}; - const std::vector labelsClasses = {"Signal", "Background"}; + const std::vector cutDirMl = {o2::cuts_ml::CutNot, o2::cuts_ml::CutSmaller}; + const std::vector labelsClasses = {"Background", "Signal"}; const uint32_t nBinsMl = dielectroncuts.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] = dielectroncuts.cutsMl.value[i]; - cutsMlArr[i][1] = 0.; + cutsMlArr[i][0] = 0.; + cutsMlArr[i][1] = dielectroncuts.cutsMl.value[i]; } o2::framework::LabeledArray cutsMl = {cutsMlArr[0], nBinsMl, nClassesMl, labelsBins, labelsClasses}; diff --git a/PWGEM/Dilepton/Core/SingleTrackQCMC.h b/PWGEM/Dilepton/Core/SingleTrackQCMC.h index 3b76e8f8b93..4e33091a70f 100644 --- a/PWGEM/Dilepton/Core/SingleTrackQCMC.h +++ b/PWGEM/Dilepton/Core/SingleTrackQCMC.h @@ -474,14 +474,14 @@ struct SingleTrackQCMC { if (dielectroncuts.cfg_pid_scheme == static_cast(DielectronCut::PIDSchemes::kPIDML)) { // please call this at the end of DefineDileptonCut static constexpr int nClassesMl = 2; - const std::vector cutDirMl = {o2::cuts_ml::CutGreater, o2::cuts_ml::CutNot}; - const std::vector labelsClasses = {"Signal", "Background"}; + const std::vector cutDirMl = {o2::cuts_ml::CutNot, o2::cuts_ml::CutSmaller}; + const std::vector labelsClasses = {"Background", "Signal"}; const uint32_t nBinsMl = dielectroncuts.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] = dielectroncuts.cutsMl.value[i]; - cutsMlArr[i][1] = 0.; + cutsMlArr[i][0] = 0.; + cutsMlArr[i][1] = dielectroncuts.cutsMl.value[i]; } o2::framework::LabeledArray cutsMl = {cutsMlArr[0], nBinsMl, nClassesMl, labelsBins, labelsClasses}; diff --git a/PWGEM/Dilepton/TableProducer/skimmerPrimaryElectron.cxx b/PWGEM/Dilepton/TableProducer/skimmerPrimaryElectron.cxx index cbf66569224..3a88c448c15 100644 --- a/PWGEM/Dilepton/TableProducer/skimmerPrimaryElectron.cxx +++ b/PWGEM/Dilepton/TableProducer/skimmerPrimaryElectron.cxx @@ -182,14 +182,14 @@ struct skimmerPrimaryElectron { if (usePIDML) { static constexpr int nClassesMl = 2; - const std::vector cutDirMl = {o2::cuts_ml::CutGreater, o2::cuts_ml::CutNot}; - const std::vector labelsClasses = {"Signal", "Background"}; + 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] = cutsMl.value[i]; - cutsMlArr[i][1] = 0.; + cutsMlArr[i][0] = 0.0; + cutsMlArr[i][1] = cutsMl.value[i]; } o2::framework::LabeledArray cutsMl = {cutsMlArr[0], nBinsMl, nClassesMl, labelsBins, labelsClasses}; From c66dbb2290564d8949104e6502f2404ba1acd417 Mon Sep 17 00:00:00 2001 From: Fabrizio Date: Fri, 20 Jun 2025 20:37:00 +0200 Subject: [PATCH 165/871] Fix bug in D+ selector, due to wrong logic for correlated bkgs (#11709) --- PWGHF/TableProducer/candidateSelectorDplusToPiKPi.cxx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/PWGHF/TableProducer/candidateSelectorDplusToPiKPi.cxx b/PWGHF/TableProducer/candidateSelectorDplusToPiKPi.cxx index 5aa753b28d1..8295ddf1e62 100644 --- a/PWGHF/TableProducer/candidateSelectorDplusToPiKPi.cxx +++ b/PWGHF/TableProducer/candidateSelectorDplusToPiKPi.cxx @@ -64,8 +64,6 @@ struct HfCandidateSelectorDplusToPiKPi { Configurable> binsPtTrack{"binsPtTrack", std::vector{hf_cuts_single_track::vecBinsPtTrack}, "track pT bin limits for DCA pT-dependent cut"}; // QA switch Configurable activateQA{"activateQA", false, "Flag to enable QA histogram"}; - // Correlated background from Ds and D+ - Configurable storeDsDplusBkg{"storeDsDplusBkg", false, "Flag to store correlated background from misidentified product of Ds and D+ decay"}; // ML inference Configurable applyMl{"applyMl", false, "Flag to apply ML selections"}; Configurable> binsPtMl{"binsPtMl", std::vector{hf_cuts_ml::vecBinsPt}, "pT bin limits for ML application"}; @@ -229,7 +227,7 @@ struct HfCandidateSelectorDplusToPiKPi { auto ptCand = candidate.pt(); - if (!TESTBIT(candidate.hfflag(), aod::hf_cand_3prong::DecayType::DplusToPiKPi) && !(storeDsDplusBkg && TESTBIT(candidate.hfflag(), aod::hf_cand_3prong::DecayType::DsToKKPi))) { // DecayType::DsToKKPi is used to flag both Ds± → K± K∓ π± and D± → K± K∓ π± + if (!TESTBIT(candidate.hfflag(), aod::hf_cand_3prong::DecayType::DplusToPiKPi)) { hfSelDplusToPiKPiCandidate(statusDplusToPiKPi); if (applyMl) { hfMlDplusToPiKPiCandidate(outputMlNotPreselected); From 05b9a6aa5717ae8752395067e7c4bf16a50c8670 Mon Sep 17 00:00:00 2001 From: Fabrizio Chinu <91954233+fchinu@users.noreply.github.com> Date: Fri, 20 Jun 2025 22:08:32 +0200 Subject: [PATCH 166/871] [PWGHF] Remove need for extended pt column in B -> J/Psi workflow (#11708) --- PWGHF/D2H/DataModel/ReducedDataModel.h | 12 ++++++++++-- .../TableProducer/candidateCreatorBToJpsiReduced.cxx | 2 -- PWGHF/D2H/Tasks/taskBplusToJpsiKReduced.cxx | 2 +- PWGHF/D2H/Tasks/taskBsToJpsiPhiReduced.cxx | 2 +- 4 files changed, 12 insertions(+), 6 deletions(-) diff --git a/PWGHF/D2H/DataModel/ReducedDataModel.h b/PWGHF/D2H/DataModel/ReducedDataModel.h index c385d42f03c..02cab44cb2b 100644 --- a/PWGHF/D2H/DataModel/ReducedDataModel.h +++ b/PWGHF/D2H/DataModel/ReducedDataModel.h @@ -215,6 +215,12 @@ DECLARE_SOA_DYNAMIC_COLUMN(EtaProng2, etaProng2, //! [](float pxProng2, float pyProng2, float pzProng2) -> float { return RecoDecay::eta(std::array{pxProng2, pyProng2, pzProng2}); }); } // namespace hf_track_vars_reduced +namespace hf_b_to_jpsi_track_vars_reduced +{ +DECLARE_SOA_DYNAMIC_COLUMN(Pt, pt, //! transverse momentum + [](float signed1Pt) -> float { return std::abs(signed1Pt) <= o2::constants::math::Almost0 ? o2::constants::math::VeryBig : 1.f / std::abs(signed1Pt); }); +} // namespace hf_b_to_jpsi_track_vars_reduced + namespace hf_track_pid_reduced { DECLARE_SOA_COLUMN(TPCNSigmaPiProng0, tpcNSigmaPiProng0, float); //! NsigmaTPCPi for prong0, o2-linter: disable=name/o2-column (written to disk) @@ -288,6 +294,7 @@ DECLARE_SOA_TABLE(HfRedBach0Bases, "AOD", "HFREDBACH0BASE", //! Table with track hf_track_index_reduced::TrackId, hf_track_index_reduced::HfRedCollisionId, HFTRACKPAR_COLUMNS, + hf_b_to_jpsi_track_vars_reduced::Pt, hf_track_vars_reduced::ItsNCls, hf_track_vars_reduced::TpcNClsCrossedRows, hf_track_vars_reduced::TpcChi2NCl, @@ -318,6 +325,7 @@ DECLARE_SOA_TABLE(HfRedBach1Bases, "AOD", "HFREDBACH1BASE", //! Table with track hf_track_index_reduced::TrackId, hf_track_index_reduced::HfRedCollisionId, HFTRACKPAR_COLUMNS, + hf_b_to_jpsi_track_vars_reduced::Pt, hf_track_vars_reduced::ItsNCls, hf_track_vars_reduced::TpcNClsCrossedRows, hf_track_vars_reduced::TpcChi2NCl, @@ -358,8 +366,8 @@ DECLARE_SOA_EXTENDED_TABLE_USER(HfRedBach1Ext, HfRedBach1Bases, "HFREDBACH1EXT", aod::track::Pt); using HfRedTracks = HfRedTracksExt; -using HfRedBach0Tracks = HfRedBach0Ext; -using HfRedBach1Tracks = HfRedBach1Ext; +using HfRedBach0Tracks = HfRedBach0Bases; +using HfRedBach1Tracks = HfRedBach1Bases; namespace hf_charm_cand_reduced { diff --git a/PWGHF/D2H/TableProducer/candidateCreatorBToJpsiReduced.cxx b/PWGHF/D2H/TableProducer/candidateCreatorBToJpsiReduced.cxx index 960b05ce667..3fe788035af 100644 --- a/PWGHF/D2H/TableProducer/candidateCreatorBToJpsiReduced.cxx +++ b/PWGHF/D2H/TableProducer/candidateCreatorBToJpsiReduced.cxx @@ -421,8 +421,6 @@ struct HfCandidateCreatorBToJpsiReduced { struct HfCandidateCreatorBToJpsiReducedExpressions { Spawns rowCandidateBPlus; Spawns rowCandidateBs; - Spawns rowTracksExt0; - Spawns rowTracksExt1; Produces rowBplusMcRec; Produces rowBsMcRec; diff --git a/PWGHF/D2H/Tasks/taskBplusToJpsiKReduced.cxx b/PWGHF/D2H/Tasks/taskBplusToJpsiKReduced.cxx index 680d7933c48..a3d4cf2dc71 100644 --- a/PWGHF/D2H/Tasks/taskBplusToJpsiKReduced.cxx +++ b/PWGHF/D2H/Tasks/taskBplusToJpsiKReduced.cxx @@ -275,7 +275,7 @@ struct HfTaskBplusToJpsiKReduced { if (doprocessMc || doprocessMcWithBplusMl) { registry.add("hPtJpsiGen", mcParticleMatched + "J/#Psi #it{p}_{T}^{gen} (GeV/#it{c}); B^{+} " + stringPt, {HistType::kTH2F, {axisPtProng, axisPtB}}); registry.add("hPtKGen", mcParticleMatched + "Kaon #it{p}_{T}^{gen} (GeV/#it{c}); B^{+} " + stringPt, {HistType::kTH2F, {axisPtProng, axisPtB}}); - registry.add("hYGenWithProngsInAcceptance", mcParticleMatched + "Kaon #it{p}_{T}^{gen} (GeV/#it{c}); B^{+} " + stringPt, {HistType::kTH2F, {axisPtProng, axisRapidity}}); + registry.add("hYGenWithProngsInAcceptance", mcParticleMatched + "B^{+} #it{p}_{T}^{gen} (GeV/#it{c}); B^{+} #it{y}", {HistType::kTH2F, {axisPtProng, axisRapidity}}); registry.add("hMassRecSig", bPlusCandMatch + "inv. mass J/#Psi K^{+} (GeV/#it{c}^{2}); B^{+} " + stringPt, {HistType::kTH2F, {axisMassBplus, axisPtB}}); registry.add("hMassJpsiRecSig", bPlusCandMatch + "inv. mass #mu^{+}#mu^{#minus} (GeV/#it{c}^{2}); J/#Psi " + stringPt, {HistType::kTH2F, {axisMassJpsi, axisPtJpsi}}); registry.add("hd0KRecSig", bPlusCandMatch + "Kaon DCAxy to prim. vertex (cm); K^{+} " + stringPt, {HistType::kTH2F, {axisImpactPar, axisPtKa}}); diff --git a/PWGHF/D2H/Tasks/taskBsToJpsiPhiReduced.cxx b/PWGHF/D2H/Tasks/taskBsToJpsiPhiReduced.cxx index 90ce04a9cb7..ce140114298 100644 --- a/PWGHF/D2H/Tasks/taskBsToJpsiPhiReduced.cxx +++ b/PWGHF/D2H/Tasks/taskBsToJpsiPhiReduced.cxx @@ -298,7 +298,7 @@ struct HfTaskBsToJpsiPhiReduced { registry.add("hPtJpsiGen", mcParticleMatched + "J/#Psi #it{p}_{T}^{gen} (GeV/#it{c}); B_{s}^{0} " + stringPt, {HistType::kTH2F, {axisPtProng, axisPtB}}); registry.add("hPtPhiGen", mcParticleMatched + "#phi #it{p}_{T}^{gen} (GeV/#it{c}); B_{s}^{0} " + stringPt, {HistType::kTH2F, {axisPtProng, axisPtB}}); registry.add("hPtKGen", mcParticleMatched + "Kaon #it{p}_{T}^{gen} (GeV/#it{c}); B_{s}^{0} " + stringPt, {HistType::kTH2F, {axisPtProng, axisPtB}}); - registry.add("hYGenWithProngsInAcceptance", mcParticleMatched + "Kaon #it{p}_{T}^{gen} (GeV/#it{c}); B_{s}^{0} " + stringPt, {HistType::kTH2F, {axisPtProng, axisRapidity}}); + registry.add("hYGenWithProngsInAcceptance", mcParticleMatched + "B_{s}^{0} #it{p}_{T}^{gen} (GeV/#it{c}); B_{s}^{0} #it{y}", {HistType::kTH2F, {axisPtProng, axisRapidity}}); 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}}); From 633ce6ba87370b6a3b0e1c0562a8d5c5ee0fdc2f Mon Sep 17 00:00:00 2001 From: Mario Ciacco Date: Fri, 20 Jun 2025 23:40:20 +0200 Subject: [PATCH 167/871] [PWGLF] add histograms for kine-transformed mass bias (#11707) Co-authored-by: ALICE Action Bot --- .../TableProducer/Strangeness/CMakeLists.txt | 2 +- ...TreeCreator.cxx => strangeTreeCreator.cxx} | 268 +++++++++++------- 2 files changed, 159 insertions(+), 111 deletions(-) rename PWGLF/TableProducer/Strangeness/{LFStrangeTreeCreator.cxx => strangeTreeCreator.cxx} (77%) diff --git a/PWGLF/TableProducer/Strangeness/CMakeLists.txt b/PWGLF/TableProducer/Strangeness/CMakeLists.txt index 2591c9f06a7..55bf4550601 100644 --- a/PWGLF/TableProducer/Strangeness/CMakeLists.txt +++ b/PWGLF/TableProducer/Strangeness/CMakeLists.txt @@ -92,7 +92,7 @@ o2physics_add_dpl_workflow(lambdakzerospawner COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(strange-tree-creator - SOURCES LFStrangeTreeCreator.cxx + SOURCES strangeTreeCreator.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore COMPONENT_NAME Analysis) diff --git a/PWGLF/TableProducer/Strangeness/LFStrangeTreeCreator.cxx b/PWGLF/TableProducer/Strangeness/strangeTreeCreator.cxx similarity index 77% rename from PWGLF/TableProducer/Strangeness/LFStrangeTreeCreator.cxx rename to PWGLF/TableProducer/Strangeness/strangeTreeCreator.cxx index 4ab2f0cc745..a18397f214e 100644 --- a/PWGLF/TableProducer/Strangeness/LFStrangeTreeCreator.cxx +++ b/PWGLF/TableProducer/Strangeness/strangeTreeCreator.cxx @@ -9,35 +9,37 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#include -#include -#include +/// \file strangeTreeCreator.cxx +/// \brief table producer for strangeness studies +/// \author Mario Ciacco -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.h" -#include "ReconstructionDataFormats/Track.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "Common/DataModel/Centrality.h" -#include "Common/DataModel/Multiplicity.h" -#include "Common/Core/RecoDecay.h" -#include "Common/Core/trackUtilities.h" -#include "Common/DataModel/EventSelection.h" +#include "PWGLF/DataModel/LFSlimStrangeTables.h" #include "PWGLF/DataModel/LFStrangenessTables.h" -#include "DetectorsBase/Propagator.h" -#include "DetectorsBase/GeometryManager.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "CCDB/BasicCCDBManager.h" #include "Common/Core/PID/TPCPIDResponse.h" +#include "Common/Core/RecoDecay.h" +#include "Common/Core/trackUtilities.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/PIDResponse.h" -#include "DCAFitter/DCAFitterN.h" +#include "Common/DataModel/TrackSelectionTables.h" -#include "PWGLF/DataModel/LFSlimStrangeTables.h" +#include "CCDB/BasicCCDBManager.h" +#include "DCAFitter/DCAFitterN.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "DataFormatsParameters/GRPObject.h" +#include "DetectorsBase/GeometryManager.h" +#include "DetectorsBase/Propagator.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" +#include "ReconstructionDataFormats/Track.h" -#include "TDatabasePDG.h" +#include +#include +#include using namespace o2; using namespace o2::framework; @@ -49,7 +51,7 @@ namespace { void momTotXYZ(std::array& momA, std::array const& momB, std::array const& momC) { - for (int i = 0; i < 3; ++i) { + for (unsigned int i{0}; i < momA.size(); ++i) { momA[i] = momB[i] + momC[i]; } } @@ -99,10 +101,27 @@ float etaFromMom(std::array const& momA, std::array const& m (1.f * momA[2] + 1.f * momB[2]) * (1.f * momA[2] + 1.f * momB[2])) - (1.f * momA[2] + 1.f * momB[2]))); } -float CalculateDCAStraightToPV(float X, float Y, float Z, float Px, float Py, float Pz, float pvX, float pvY, float pvZ) +float calculateDCAStraightToPV(float X, float Y, float Z, float Px, float Py, float Pz, float pvX, float pvY, float pvZ) { return std::sqrt((std::pow((pvY - Y) * Pz - (pvZ - Z) * Py, 2) + std::pow((pvX - X) * Pz - (pvZ - Z) * Px, 2) + std::pow((pvX - X) * Py - (pvY - Y) * Px, 2)) / (Px * Px + Py * Py + Pz * Pz)); } +float kineFactor(std::array const& momA, std::array const& momB, std::array const& momC, float const& massB, float const& massC, bool const& reso) +{ + float invMass = invMass2Body(momA, momC, momB, massC, massB); + float ptC = std::hypot(momC[0], momC[1]); + float ptB = std::hypot(momB[0], momB[1]); + float p2C = momC[0] * momC[0] + momC[1] * momC[1] + momC[2] * momC[2]; + float p2B = momB[0] * momB[0] + momB[1] * momB[1] + momB[2] * momB[2]; + float eC = RecoDecay::sqrtSumOfSquares(momC[0], momC[1], momC[2], massC); + float eB = RecoDecay::sqrtSumOfSquares(momB[0], momB[1], momB[2], massB); + float pCpB = momC[0] * momB[0] + momC[1] * momB[1] + momC[2] * momB[2]; + float kineC = (eB * p2C / eC / ptC) - pCpB / ptC; + float kineB = (eC * p2B / eB / ptB) - pCpB / ptB; + if (reso) { + return std::hypot(kineC, kineB) / invMass; + } + return (kineC + kineB) / invMass; +} } // namespace struct CandidateV0 { @@ -145,7 +164,7 @@ struct CandidateV0 { int64_t globalIndexNeg = -999; }; -struct LFStrangeTreeCreator { +struct StrangeTreeCreator { Produces lambdaTableML; Produces v0TableAP; Produces mcLambdaTableML; @@ -156,16 +175,19 @@ struct LFStrangeTreeCreator { o2::vertexing::DCAFitterN<2> fitter; int mRunNumber; - float d_bz; + float mBz; o2::base::MatLayerCylSet* lut = nullptr; Configurable cfgMaterialCorrection{"cfgMaterialCorrection", static_cast(o2::base::Propagator::MatCorrType::USEMatCorrLUT), "Type of material correction"}; ConfigurableAxis centAxis{"centAxis", {106, 0, 106}, "binning for the centrality"}; ConfigurableAxis zVtxAxis{"zVtxBins", {100, -20.f, 20.f}, "Binning for the vertex z in cm"}; + ConfigurableAxis etaAxis{"etaAxis", {8, -0.8f, 0.8f}, "binning for pseudorapidity"}; + ConfigurableAxis massKineAxis{"kineAxis", {3000, -3.f, 3.f}, "binning for the kinematic-transofrmed mass shift distributions"}; // binning of (anti)lambda mass QA histograms ConfigurableAxis massLambdaAxis{"massLambdaAxis", {400, o2::constants::physics::MassLambda0 - 0.03f, o2::constants::physics::MassLambda0 + 0.03f}, "binning for the lambda invariant-mass"}; ConfigurableAxis massXiAxis{"massXiAxis", {400, o2::constants::physics::MassXiMinus - 0.05f, o2::constants::physics::MassXiMinus + 0.05f}, "binning for the Xi invariant-mass"}; + ConfigurableAxis massK0sAxis{"massK0sAxis", {400, o2::constants::physics::MassK0 - 0.1f, o2::constants::physics::MassK0 + 0.1f}, "binning for the K0s invariant-mass"}; Configurable zVtxMax{"zVtxMax", 10.0f, "maximum z position of the primary vertex"}; Configurable etaMax{"etaMax", 0.8f, "maximum eta"}; @@ -184,21 +206,24 @@ struct LFStrangeTreeCreator { Configurable v0trackNsharedClusTpc{"v0trackNsharedClusTpc", 5, "Maximum number of shared TPC clusters for V0 daughter"}; Configurable vetoMassK0Short{"vetoMassK0Short", 0.01f, "veto for V0 compatible with K0s mass"}; Configurable v0radiusMax{"v0radiusMax", 100.f, "maximum V0 radius eccepted"}; - - Configurable v0setting_dcav0dau{"v0setting_dcav0dau", 0.5f, "DCA V0 Daughters"}; - Configurable v0setting_dcav0pv{"v0setting_dcav0pv", 1.f, "DCA V0 to Pv"}; - Configurable v0setting_dcadaughtopv{"v0setting_dcadaughtopv", 0.1f, "DCA Pos To PV"}; - Configurable v0setting_cospa{"v0setting_cospa", 0.99f, "V0 CosPA"}; - Configurable v0setting_radius{"v0setting_radius", 5.f, "v0radius"}; - Configurable v0setting_lifetime{"v0setting_lifetime", 40.f, "v0 lifetime cut"}; - Configurable v0setting_nsigmatpc{"v0setting_nsigmatpc", 4.f, "nsigmatpc"}; - Configurable cascsetting_dcabachpv{"cascsetting_dcabachpv", 0.1f, "cascdcabachpv"}; - Configurable cascsetting_cospa{"cascsetting_cospa", 0.99f, "casc cospa cut"}; - Configurable cascsetting_dcav0bach{"cascsetting_dcav0bach", 1.0f, "dcav0bach"}; - Configurable cascsetting_vetoOm{"cascsetting_vetoOm", 0.01f, "vetoOm"}; - Configurable cascsetting_mXi{"cascsetting_mXi", 0.02f, "mXi"}; + Configurable v0alphaMax{"v0alphaMax", 10.f, "maximum Armenteros alpha (longitdinal momentum asymmetry)"}; + Configurable v0qtMin{"v0qtMin", 0.f, "minimum Armenteros qt (transverse momentum)"}; + + Configurable v0settingDcav0dau{"v0setting_dcav0dau", 0.5f, "DCA V0 Daughters"}; + Configurable v0settingDcav0pv{"v0setting_dcav0pv", 1.f, "DCA V0 to Pv"}; + Configurable v0settingDcadaughtopv{"v0setting_dcadaughtopv", 0.1f, "DCA Pos To PV"}; + Configurable v0settingCospa{"v0setting_cospa", 0.99f, "V0 CosPA"}; + Configurable v0settingRadius{"v0setting_radius", 5.f, "v0radius"}; + Configurable v0settingLifetime{"v0setting_lifetime", 40.f, "v0 lifetime cut"}; + Configurable v0settingNsigmatpc{"v0setting_nsigmatpc", 4.f, "nsigmatpc"}; + Configurable cascsettingDcabachpv{"cascsetting_dcabachpv", 0.1f, "cascdcabachpv"}; + Configurable cascsettingCospa{"cascsetting_cospa", 0.99f, "casc cospa cut"}; + Configurable cascsettingDcav0bach{"cascsetting_dcav0bach", 1.0f, "dcav0bach"}; + Configurable cascsettingVetoOm{"cascsetting_vetoOm", 0.01f, "vetoOm"}; + Configurable cascsettingMXi{"cascsetting_mXi", 0.02f, "mXi"}; Configurable lambdaMassCut{"lambdaMassCut", 0.02f, "maximum deviation from PDG mass (for QA histograms)"}; Configurable k0short{"k0short", false, "process for k0short (true) or lambda (false)"}; + Configurable tpcFindableClsOverCR{"tpcFindableClsOverCR", 0.8, "fraction of findable clusters over crossed rows in TPC"}; HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; @@ -218,7 +243,7 @@ struct LFStrangeTreeCreator { if (track.itsNCls() < v0trackNclusItsCut || track.tpcNClsFound() < v0trackNclusTpcCut || track.tpcNClsCrossedRows() < v0trackNclusTpcCut || - track.tpcNClsCrossedRows() < 0.8 * track.tpcNClsFindable() || + track.tpcNClsCrossedRows() < tpcFindableClsOverCR * track.tpcNClsFindable() || track.tpcNClsShared() > v0trackNsharedClusTpc) { return false; } @@ -243,10 +268,10 @@ struct LFStrangeTreeCreator { o2::base::Propagator::initFieldFromGRP(grpmag); // Fetch magnetic field from ccdb for current collision - d_bz = o2::base::Propagator::Instance()->getNominalBz(); - LOG(info) << "Retrieved GRP for timestamp " << timestamp << " with magnetic field of " << d_bz << " kG"; + mBz = o2::base::Propagator::Instance()->getNominalBz(); + LOG(info) << "Retrieved GRP for timestamp " << timestamp << " with magnetic field of " << mBz << " kG"; mRunNumber = bc.runNumber(); - fitter.setBz(d_bz); + fitter.setBz(mBz); lut = o2::base::MatLayerCylSet::rectifyPtrFromFile(ccdb->get("GLO/Param/MatLUT")); o2::base::Propagator::Instance()->setMatLUT(lut); @@ -259,7 +284,7 @@ struct LFStrangeTreeCreator { { mRunNumber = 0; - d_bz = 0; + mBz = 0; ccdb->setURL("http://alice-ccdb.cern.ch"); ccdb->setCaching(true); @@ -282,6 +307,11 @@ struct LFStrangeTreeCreator { // v0 QA histos.add("QA/massLambda", ";Centrality (%);#it{p}_{T} (GeV/#it{c});#it{M}(p + #pi^{-}) (GeV/#it{c}^{2});Entries", HistType::kTH3F, {centAxis, momAxis, massLambdaAxis}); histos.add("QA/massXi", ";Centrality (%);#it{p}_{T} (GeV/#it{c});#it{M}(#Lambda + #pi^{-}) (GeV/#it{c}^{2});Entries", HistType::kTH3F, {centAxis, momAxis, massXiAxis}); + histos.add("QA/massK0s", ";#it{p}_{T} (GeV/#it{c});#it{M}(#pi^{+} + #pi^{-}) (GeV/#it{c}^{2});Entries", HistType::kTH2F, {momAxis, massK0sAxis}); + + // histograms for momentum shift/resolution extraction + histos.add("massKineBias", ";#eta;#it{p}_{T} (GeV/#it{c});#delta#it{M}/#Sigma_{i}#partial#it{M}/#partial#it{p}^{i}_{T}", HistType::kTH3F, {etaAxis, momAxis, massKineAxis}); + histos.add("massKineReso", ";#eta;#it{p}_{T} (GeV/#it{c});#delta#it{M}/#Sigma_{i}(#partial#it{M}/#partial#it{p}^{i}_{T})^{2}", HistType::kTH3F, {etaAxis, momAxis, massKineAxis}); } template @@ -335,12 +365,21 @@ struct LFStrangeTreeCreator { } auto alpha = alphaAP(momV0, momPos, momNeg); + if (std::abs(alpha) > v0alphaMax) { + continue; + } + bool matter = alpha > 0; auto massPos = matter ? o2::constants::physics::MassProton : o2::constants::physics::MassPionCharged; auto massNeg = matter ? o2::constants::physics::MassPionCharged : o2::constants::physics::MassProton; auto mLambda = invMass2Body(momV0, momPos, momNeg, massPos, massNeg); auto mK0Short = invMass2Body(momV0, momPos, momNeg, o2::constants::physics::MassPionCharged, o2::constants::physics::MassPionCharged); + auto qt = qtAP(momV0, momPos); + if (std::abs(qt) < v0qtMin) { + continue; + } + // pid selections auto nSigmaTPCPos = matter ? posTrack.tpcNSigmaPr() : posTrack.tpcNSigmaPi(); auto nSigmaTPCNeg = matter ? negTrack.tpcNSigmaPi() : negTrack.tpcNSigmaPr(); @@ -350,7 +389,7 @@ struct LFStrangeTreeCreator { nSigmaTPCNeg = negTrack.tpcNSigmaPi(); } - if (std::abs(nSigmaTPCPos) > v0setting_nsigmatpc || std::abs(nSigmaTPCNeg) > v0setting_nsigmatpc) { + if (std::abs(nSigmaTPCPos) > v0settingNsigmatpc || std::abs(nSigmaTPCNeg) > v0settingNsigmatpc) { continue; } @@ -360,7 +399,7 @@ struct LFStrangeTreeCreator { } float dcaV0dau = std::sqrt(fitter.getChi2AtPCACandidate()); - if (dcaV0dau > v0setting_dcav0dau) { + if (dcaV0dau > v0settingDcav0dau) { continue; } @@ -368,22 +407,22 @@ struct LFStrangeTreeCreator { const auto& vtx = fitter.getPCACandidate(); float radiusV0 = std::hypot(vtx[0], vtx[1]); - if (radiusV0 < v0setting_radius || radiusV0 > v0radiusMax) { + if (radiusV0 < v0settingRadius || radiusV0 > v0radiusMax) { continue; } - float dcaV0Pv = CalculateDCAStraightToPV( + float dcaV0Pv = calculateDCAStraightToPV( vtx[0], vtx[1], vtx[2], momPos[0] + momNeg[0], momPos[1] + momNeg[1], momPos[2] + momNeg[2], collision.posX(), collision.posY(), collision.posZ()); - if (std::abs(dcaV0Pv) > v0setting_dcav0pv) { + if (std::abs(dcaV0Pv) > v0settingDcav0pv) { continue; } double cosPA = RecoDecay::cpa(primVtx, vtx, momV0); - if (cosPA < v0setting_cospa) { + if (cosPA < v0settingCospa) { continue; } @@ -396,38 +435,47 @@ struct LFStrangeTreeCreator { } else { particlemass = o2::constants::physics::MassLambda; } - float ML2P = particlemass * lengthTraveled / ptotal; - if (ML2P > v0setting_lifetime) { + float mL2P = particlemass * lengthTraveled / ptotal; + if (mL2P > v0settingLifetime) { continue; } o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, posTrackCov, 2.f, fitter.getMatCorrType(), &dcaInfo); auto posDcaToPv = std::hypot(dcaInfo[0], dcaInfo[1]); - if (posDcaToPv < v0setting_dcadaughtopv && std::abs(dcaInfo[0]) < v0setting_dcadaughtopv) { + if (posDcaToPv < v0settingDcadaughtopv && std::abs(dcaInfo[0]) < v0settingDcadaughtopv) { continue; } o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, negTrackCov, 2.f, fitter.getMatCorrType(), &dcaInfo); auto negDcaToPv = std::hypot(dcaInfo[0], dcaInfo[1]); - if (negDcaToPv < v0setting_dcadaughtopv && std::abs(dcaInfo[0]) < v0setting_dcadaughtopv) { + if (negDcaToPv < v0settingDcadaughtopv && std::abs(dcaInfo[0]) < v0settingDcadaughtopv) { continue; } if (std::abs(mLambda - o2::constants::physics::MassLambda0) > lambdaMassCut) { // for QA histograms continue; } + + float ptPos = std::hypot(momPos[0], momPos[1]); + float deltaMass = mK0Short - o2::constants::physics::MassK0; + float massKineBias = deltaMass / kineFactor(momV0, momPos, momNeg, o2::constants::physics::MassPiMinus, o2::constants::physics::MassPiMinus, false); + float massKineReso = deltaMass / kineFactor(momV0, momPos, momNeg, o2::constants::physics::MassPiMinus, o2::constants::physics::MassPiMinus, true); + histos.fill(HIST("QA/massLambda"), centrality, ptV0, mLambda); + histos.fill(HIST("QA/massK0s"), ptV0, mK0Short); + histos.fill(HIST("massKineBias"), ptPos, massKineBias); + histos.fill(HIST("massKineReso"), ptPos, massKineReso); CandidateV0 candV0; candV0.pt = matter > 0. ? ptV0 : -ptV0; candV0.eta = etaV0; - candV0.ct = ML2P; + candV0.ct = mL2P; candV0.len = lengthTraveled; candV0.mass = mLambda; candV0.radius = radiusV0; candV0.cpa = cosPA; candV0.alphaAP = alpha; - candV0.qtAP = qtAP(momV0, momPos); + candV0.qtAP = qt; candV0.trackv0 = fitter.createParentTrackParCov(); candV0.mompos = std::array{momPos[0], momPos[1], momPos[2]}; candV0.momneg = std::array{momNeg[0], momNeg[1], momNeg[2]}; @@ -443,7 +491,7 @@ struct LFStrangeTreeCreator { candidateV0s.push_back(candV0); } - for (auto& casc : cascades) { + for (const auto& casc : cascades) { auto v0 = casc.template v0_as(); auto itv0 = find_if(candidateV0s.begin(), candidateV0s.end(), [&](CandidateV0 v0cand) { return v0cand.globalIndex == v0.globalIndex(); }); if (itv0 == candidateV0s.end()) { @@ -453,7 +501,7 @@ struct LFStrangeTreeCreator { auto bachTrackPar = getTrackPar(bachTrack); o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, bachTrackPar, 2.f, fitter.getMatCorrType(), &dcaInfo); - if (TMath::Abs(dcaInfo[0]) < cascsetting_dcabachpv) + if (std::abs(dcaInfo[0]) < cascsettingDcabachpv) continue; auto bachelorTrack = getTrackParCov(bachTrack); @@ -477,23 +525,23 @@ struct LFStrangeTreeCreator { bachelorTrack.getPxPyPzGlo(momBach); momTotXYZ(momCasc, momV0, momBach); - auto dcacascv0bach = TMath::Sqrt(fitter.getChi2AtPCACandidate()); - if (dcacascv0bach > cascsetting_dcav0bach) + auto dcacascv0bach = std::sqrt(fitter.getChi2AtPCACandidate()); + if (dcacascv0bach > cascsettingDcav0bach) continue; std::array primVtx = {collision.posX(), collision.posY(), collision.posZ()}; const auto& vtx = fitter.getPCACandidate(); double cosPA = RecoDecay::cpa(primVtx, vtx, momCasc); - if (cosPA < cascsetting_cospa) + if (cosPA < cascsettingCospa) continue; float mXi = invMass2Body(momCasc, momV0, momBach, o2::constants::physics::MassLambda0, o2::constants::physics::MassPionCharged); float mOm = invMass2Body(momCasc, momV0, momBach, o2::constants::physics::MassLambda0, o2::constants::physics::MassKaonCharged); - if (std::abs(mOm - o2::constants::physics::MassOmegaMinus) < cascsetting_vetoOm) + if (std::abs(mOm - o2::constants::physics::MassOmegaMinus) < cascsettingVetoOm) continue; - if (std::abs(mXi - o2::constants::physics::MassXiMinus) > cascsetting_mXi) + if (std::abs(mXi - o2::constants::physics::MassXiMinus) > cascsettingMXi) continue; histos.fill(HIST("QA/massXi"), centrality, std::hypot(momCasc[0], momCasc[1]), mXi); @@ -506,7 +554,7 @@ struct LFStrangeTreeCreator { { fillRecoEvent(collision, tracks, V0s, V0s_all, cascades, centrality); - for (auto& candidateV0 : candidateV0s) { + for (auto& candidateV0 : candidateV0s) { // o2-linter disable=const-red-in-for-loops (non const) candidateV0.isreco = true; auto mcLabPos = mcLabels.rawIteratorAt(candidateV0.globalIndexPos); auto mcLabNeg = mcLabels.rawIteratorAt(candidateV0.globalIndexNeg); @@ -520,23 +568,23 @@ struct LFStrangeTreeCreator { auto pdgCodeMotherDauNeg = -999; auto pdgMatchMotherSecondMother = -999; if (mcTrackPos.has_mothers() && mcTrackNeg.has_mothers()) { - for (auto& negMother : mcTrackNeg.template mothers_as()) { - for (auto& posMother : mcTrackPos.template mothers_as()) { + for (const auto& negMother : mcTrackNeg.template mothers_as()) { + for (const auto& posMother : mcTrackPos.template mothers_as()) { if (posMother.globalIndex() != negMother.globalIndex()) { pdgCodeMotherDauPos = posMother.pdgCode(); pdgCodeMotherDauNeg = negMother.pdgCode(); - if (negMother.pdgCode() == -211) { + if (negMother.pdgCode() == PDG_t::kPiMinus) { if (negMother.has_mothers()) { - for (auto& negSecondMother : negMother.template mothers_as()) { + for (const auto& negSecondMother : negMother.template mothers_as()) { if (negSecondMother.globalIndex() == posMother.globalIndex()) { pdgMatchMotherSecondMother = negSecondMother.pdgCode(); } } } } - if (posMother.pdgCode() == 211) { + if (posMother.pdgCode() == PDG_t::kPiPlus) { if (posMother.has_mothers()) { - for (auto& posSecondMother : posMother.template mothers_as()) { + for (const auto& posSecondMother : posMother.template mothers_as()) { if (posSecondMother.globalIndex() == negMother.globalIndex()) { pdgMatchMotherSecondMother = posSecondMother.pdgCode(); } @@ -551,13 +599,13 @@ struct LFStrangeTreeCreator { bool mother; bool daughter; if (k0short) { - // mother is k0short (310) and daughters are pions (211/-211) - mother = posMother.pdgCode() == 310; - daughter = (mcTrackPos.pdgCode() == 211 && mcTrackNeg.pdgCode() == -211); + // mother is k0short and daughters are pions + mother = posMother.pdgCode() == PDG_t::kK0Short; + daughter = (mcTrackPos.pdgCode() == PDG_t::kPiPlus && mcTrackNeg.pdgCode() == PDG_t::kPiMinus); } else { - // mother is lambda (3122) and daughters are proton (2212) and pion(211) - mother = posMother.pdgCode() == 3122; - daughter = ((mcTrackPos.pdgCode() == 2212 && mcTrackNeg.pdgCode() == -211) || (mcTrackPos.pdgCode() == 211 && mcTrackNeg.pdgCode() == -2212)); + // mother is lambda and daughters are proton and pion + mother = posMother.pdgCode() == PDG_t::kLambda0; + daughter = ((mcTrackPos.pdgCode() == PDG_t::kProton && mcTrackNeg.pdgCode() == PDG_t::kPiMinus) || (mcTrackPos.pdgCode() == PDG_t::kPiPlus && mcTrackNeg.pdgCode() == PDG_t::kProtonBar)); } // check conditions if (!mother || !daughter) { @@ -571,9 +619,9 @@ struct LFStrangeTreeCreator { if (posMother.isPhysicalPrimary()) { pdgCodeMother = 0; } else if (posMother.has_mothers()) { - for (auto& mcMother : posMother.mothers_as()) { + for (const auto& mcMother : posMother.mothers_as()) { // feed-down: xi and omega decaying to lambda, ignore for k0 - if (!k0short && (std::abs(mcMother.pdgCode()) == 3322 || std::abs(mcMother.pdgCode()) == 3312 || std::abs(mcMother.pdgCode()) == 3334)) { + if (!k0short && (std::abs(mcMother.pdgCode()) == o2::constants::physics::Pdg::kXi0 || std::abs(mcMother.pdgCode()) == PDG_t::kXiMinus || std::abs(mcMother.pdgCode()) == PDG_t::kOmegaMinus)) { pdgCodeMother = mcMother.pdgCode(); break; } @@ -596,13 +644,13 @@ struct LFStrangeTreeCreator { } if ((!mcTrackPos.has_mothers()) && mcTrackNeg.has_mothers()) { pdgCodeMotherDauPos = -999; - for (auto& negMother : mcTrackNeg.template mothers_as()) { + for (const auto& negMother : mcTrackNeg.template mothers_as()) { pdgCodeMotherDauNeg = negMother.pdgCode(); } } if ((!mcTrackNeg.has_mothers()) && mcTrackPos.has_mothers()) { pdgCodeMotherDauNeg = -999; - for (auto& posMother : mcTrackPos.template mothers_as()) { + for (const auto& posMother : mcTrackPos.template mothers_as()) { pdgCodeMotherDauPos = posMother.pdgCode(); } } @@ -630,8 +678,8 @@ struct LFStrangeTreeCreator { void fillMcGen(aod::McParticles const& mcParticles, aod::McTrackLabels const& /*mcLab*/, uint64_t const& collisionId) { - auto mcParticles_thisCollision = mcParticles.sliceBy(perCollisionMcParts, collisionId); - for (auto& mcPart : mcParticles_thisCollision) { + auto mcParticlesThisCollision = mcParticles.sliceBy(perCollisionMcParts, collisionId); + for (const auto& mcPart : mcParticlesThisCollision) { auto genEta = mcPart.eta(); if (std::abs(genEta) > etaMax) { continue; @@ -642,23 +690,23 @@ struct LFStrangeTreeCreator { std::array momPosMC = std::array{static_cast(-999.), static_cast(-999.), static_cast(-999.)}; std::array momNegMC = std::array{static_cast(-999.), static_cast(-999.), static_cast(-999.)}; - // look for lambda (3122) or k0short (310) - int pdg_test = 3122; + // look for lambda or k0short + int pdg_test = PDG_t::kLambda0; if (k0short) - pdg_test = 310; + pdg_test = PDG_t::kK0Short; if (std::abs(pdgCode) == pdg_test) { if (!mcPart.isPhysicalPrimary() && !mcPart.has_mothers()) continue; - // check if its the right decay containing proton (2122) for lambda and charged pion (211) for k0short + // check if its the right decay containing proton for lambda and charged pion for k0short int pdg_particle; if (k0short) { - pdg_particle = 211; + pdg_particle = PDG_t::kPiPlus; } else { - pdg_particle = 2212; + pdg_particle = PDG_t::kProton; } bool foundParticle = false; - for (auto& mcDaught : mcPart.daughters_as()) { + for (const auto& mcDaught : mcPart.daughters_as()) { if (std::abs(mcDaught.pdgCode()) == pdg_particle) { foundParticle = true; secVtx = std::array{mcDaught.vx(), mcDaught.vy(), mcDaught.vz()}; @@ -666,7 +714,7 @@ struct LFStrangeTreeCreator { } } // momentum of daughters - for (auto& mcDaught : mcPart.daughters_as()) { + for (const auto& mcDaught : mcPart.daughters_as()) { if (mcDaught.pdgCode() < 0) { momNegMC[0] = mcDaught.px(); momNegMC[1] = mcDaught.py(); @@ -684,9 +732,9 @@ struct LFStrangeTreeCreator { if (mcPart.isPhysicalPrimary()) { pdgCodeMother = 0; } else if (mcPart.has_mothers()) { - for (auto& mcMother : mcPart.mothers_as()) { + for (const auto& mcMother : mcPart.mothers_as()) { // feed-down: xi and omega decaying to lambda, ignore for k0 - if (!k0short && (std::abs(mcMother.pdgCode()) == 3322 || std::abs(mcMother.pdgCode()) == 3312 || std::abs(mcMother.pdgCode()) == 3334)) { + if (!k0short && (std::abs(mcMother.pdgCode()) == o2::constants::physics::Pdg::kXi0 || std::abs(mcMother.pdgCode()) == PDG_t::kXiMinus || std::abs(mcMother.pdgCode()) == PDG_t::kOmegaMinus)) { pdgCodeMother = mcMother.pdgCode(); break; } @@ -741,16 +789,16 @@ struct LFStrangeTreeCreator { histos.fill(HIST("QA/zVtx"), collision.posZ()); const uint64_t collIdx = collision.globalIndex(); - auto V0Table_thisCollision = V0s.sliceBy(perCollisionV0, collIdx); - auto CascTable_thisCollision = cascades.sliceBy(perCollisionCasc, collIdx); - V0Table_thisCollision.bindExternalIndices(&tracks); - CascTable_thisCollision.bindExternalIndices(&tracks); - CascTable_thisCollision.bindExternalIndices(&V0s); + auto V0TableThisCollision = V0s.sliceBy(perCollisionV0, collIdx); + auto CascTableThisCollision = cascades.sliceBy(perCollisionCasc, collIdx); + V0TableThisCollision.bindExternalIndices(&tracks); + CascTableThisCollision.bindExternalIndices(&tracks); + CascTableThisCollision.bindExternalIndices(&V0s); auto centrality = collision.centFT0C(); - fillRecoEvent(collision, tracks, V0Table_thisCollision, V0s, CascTable_thisCollision, centrality); + fillRecoEvent(collision, tracks, V0TableThisCollision, V0s, CascTableThisCollision, centrality); - for (auto& candidateV0 : candidateV0s) { + for (const auto& candidateV0 : candidateV0s) { lambdaTableML( candidateV0.pt, candidateV0.eta, @@ -786,11 +834,11 @@ struct LFStrangeTreeCreator { } } } - PROCESS_SWITCH(LFStrangeTreeCreator, processRun3, "process (Run 3)", false); + PROCESS_SWITCH(StrangeTreeCreator, processRun3, "process (Run 3)", false); void processMcRun3(soa::Join const& collisions, aod::McCollisions const& /*mcCollisions*/, TracksFullIU const& tracks, aod::V0s const& V0s, aod::Cascades const& cascades, aod::McParticles const& mcParticles, aod::McTrackLabels const& mcLab, aod::BCsWithTimestamps const&) { - for (auto& collision : collisions) { + for (const auto& collision : collisions) { auto bc = collision.bc_as(); initCCDB(bc); @@ -808,16 +856,16 @@ struct LFStrangeTreeCreator { histos.fill(HIST("QA/zVtx"), collision.posZ()); const uint64_t collIdx = collision.globalIndex(); - auto V0Table_thisCollision = V0s.sliceBy(perCollisionV0, collIdx); - auto CascTable_thisCollision = cascades.sliceBy(perCollisionCasc, collIdx); - V0Table_thisCollision.bindExternalIndices(&tracks); - CascTable_thisCollision.bindExternalIndices(&tracks); - CascTable_thisCollision.bindExternalIndices(&V0s); + auto V0TableThisCollision = V0s.sliceBy(perCollisionV0, collIdx); + auto CascTableThisCollision = cascades.sliceBy(perCollisionCasc, collIdx); + V0TableThisCollision.bindExternalIndices(&tracks); + CascTableThisCollision.bindExternalIndices(&tracks); + CascTableThisCollision.bindExternalIndices(&V0s); - fillMcEvent(collision, tracks, V0Table_thisCollision, V0s, CascTable_thisCollision, centrality, mcParticles, mcLab); + fillMcEvent(collision, tracks, V0TableThisCollision, V0s, CascTableThisCollision, centrality, mcParticles, mcLab); fillMcGen(mcParticles, mcLab, collision.mcCollisionId()); - for (auto& candidateV0 : candidateV0s) { + for (const auto& candidateV0 : candidateV0s) { mcLambdaTableML( candidateV0.pt, candidateV0.eta, @@ -873,11 +921,11 @@ struct LFStrangeTreeCreator { } } } - PROCESS_SWITCH(LFStrangeTreeCreator, processMcRun3, "process MC (Run 3)", false); + PROCESS_SWITCH(StrangeTreeCreator, processMcRun3, "process MC (Run 3)", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{ - adaptAnalysisTask(cfgc)}; + adaptAnalysisTask(cfgc)}; } From 0b726a205567362cf62752084118ad381cc7707b Mon Sep 17 00:00:00 2001 From: omvazque Date: Fri, 20 Jun 2025 19:44:47 -0500 Subject: [PATCH 168/871] [PWGLF] CCDB gets Nch-dependent tracking eff. correction (#11710) --- PWGLF/Tasks/GlobalEventProperties/uccZdc.cxx | 51 +++++++++++++++++--- 1 file changed, 45 insertions(+), 6 deletions(-) diff --git a/PWGLF/Tasks/GlobalEventProperties/uccZdc.cxx b/PWGLF/Tasks/GlobalEventProperties/uccZdc.cxx index 12dd8e34fa6..261a5a0284e 100644 --- a/PWGLF/Tasks/GlobalEventProperties/uccZdc.cxx +++ b/PWGLF/Tasks/GlobalEventProperties/uccZdc.cxx @@ -703,7 +703,7 @@ struct UccZdc { return; } - auto efficiency = ccdb->getForTimeStamp(paTHEff.value, foundBC.timestamp()); + auto efficiency = ccdb->getForTimeStamp(paTHEff.value, foundBC.timestamp()); if (!efficiency) { return; } @@ -723,9 +723,11 @@ struct UccZdc { } float pt{track.pt()}; + int foundNchBin{efficiency->GetXaxis()->FindBin(glbTracks)}; + int foundPtBin{efficiency->GetYaxis()->FindBin(pt)}; float effValue{1.0}; if (applyEff) { - effValue = efficiency->GetBinContent(efficiency->FindBin(pt)); + effValue = efficiency->GetBinContent(foundNchBin, foundPtBin); } if (effValue > 0.) { vecOneOverEff.emplace_back(1. / effValue); @@ -756,10 +758,12 @@ struct UccZdc { } float pt{track.pt()}; + int foundNchBin{efficiency->GetXaxis()->FindBin(glbTracks)}; + int foundPtBin{efficiency->GetYaxis()->FindBin(pt)}; float effValue{1.}; float fdValue{1.}; if (applyEff) { - effValue = efficiency->GetBinContent(efficiency->FindBin(pt)); + effValue = efficiency->GetBinContent(foundNchBin, foundPtBin); fdValue = fd->GetBinContent(fd->FindBin(pt)); } if (applyEff && !applyFD) { @@ -870,7 +874,7 @@ struct UccZdc { registry.fill(HIST("EvtsDivided"), 0); // To use run-by-run efficiency - auto efficiency = ccdb->getForTimeStamp(paTHEff.value, foundBC.timestamp()); + auto efficiency = ccdb->getForTimeStamp(paTHEff.value, foundBC.timestamp()); if (!efficiency) { return; } @@ -880,20 +884,43 @@ struct UccZdc { std::vector vecOneOverEff; // std::vector wIs; const auto& groupedTracks{simTracks.sliceBy(perCollision, collision.globalIndex())}; + + // Calculates the event's Nch to evaluate the efficiency + for (const auto& track : groupedTracks) { + // Track Selection + if (track.eta() < minEta || track.eta() > maxEta) { + continue; + } + if (track.pt() < minPt || track.pt() > maxPt) { + continue; + } + if (!track.isGlobalTrack()) { + continue; + } + nchRaw++; + } + // Calculates the event weight, W_k for (const auto& track : groupedTracks) { // Track Selection + if (track.eta() < minEta || track.eta() > maxEta) { + continue; + } + if (track.pt() < minPt || track.pt() > maxPt) { + continue; + } if (!track.isGlobalTrack()) { continue; } float pt{track.pt()}; + int foundNchBin{efficiency->GetXaxis()->FindBin(nchRaw)}; + int foundPtBin{efficiency->GetYaxis()->FindBin(pt)}; float effValue{1.}; float fdValue{1.}; - nchRaw++; if (applyEff) { - effValue = efficiency->GetBinContent(efficiency->FindBin(pt)); + effValue = efficiency->GetBinContent(foundNchBin, foundPtBin); fdValue = fd->GetBinContent(fd->FindBin(pt)); } if ((effValue > 0.) && (fdValue > 0.)) { @@ -987,6 +1014,12 @@ struct UccZdc { const auto& groupedTracks{simTracks.sliceBy(perCollision, collision.globalIndex())}; for (const auto& track : groupedTracks) { // Track Selection + if (track.eta() < minEta || track.eta() > maxEta) { + continue; + } + if (track.pt() < minPt || track.pt() > maxPt) { + continue; + } if (!track.isGlobalTrack()) { continue; } @@ -998,6 +1031,12 @@ struct UccZdc { for (const auto& track : groupedTracks) { // Track Selection + if (track.eta() < minEta || track.eta() > maxEta) { + continue; + } + if (track.pt() < minPt || track.pt() > maxPt) { + continue; + } if (!track.isGlobalTrack()) { continue; } From 9db231fa9297e7ba7ff5afc66b3444a4f3056f39 Mon Sep 17 00:00:00 2001 From: Rahul Verma <110929992+rahulverma012@users.noreply.github.com> Date: Sat, 21 Jun 2025 12:33:25 +0530 Subject: [PATCH 169/871] [Common] Index tables for Tracks, TracksQA and TrackMeanOccupancies (#11602) Co-authored-by: Anton Alkin --- Common/DataModel/OccupancyTables.h | 20 ++- .../TableProducer/occupancyTableProducer.cxx | 158 +++++++++++++++++- 2 files changed, 175 insertions(+), 3 deletions(-) diff --git a/Common/DataModel/OccupancyTables.h b/Common/DataModel/OccupancyTables.h index 4828183a269..9e14fd8f4f2 100644 --- a/Common/DataModel/OccupancyTables.h +++ b/Common/DataModel/OccupancyTables.h @@ -209,6 +209,8 @@ namespace trackmeanocc { DECLARE_SOA_INDEX_COLUMN(Track, track); +// DECLARE_SOA_INDEX_COLUMN(TracksQA, tracksQA);// this is not working + DECLARE_SOA_COLUMN(TmoPrimUnfm80, tmoPrimUnfm80, float); DECLARE_SOA_COLUMN(TmoFV0AUnfm80, tmoFV0AUnfm80, float); DECLARE_SOA_COLUMN(TmoFV0CUnfm80, tmoFV0CUnfm80, float); @@ -281,7 +283,7 @@ DECLARE_SOA_COLUMN(TwmoRobustMultExtraTableUnfm80, twmoRobustMultExtraTableUnfm8 // using Tracks = aod::Tracks; // DECLARE_SOA_INDEX_TABLE_USER(TrackMeanOccs0, Tracks, "TRACKMEANOCCS0", o2::aod::trackmeanocc::TrackId); -DECLARE_SOA_TABLE(TmoTrackId, "AOD", "TMOTRACKID", o2::aod::trackmeanocc::TrackId); +DECLARE_SOA_TABLE(TmoTrackIds, "AOD", "TMOTRACKIDS", o2::aod::trackmeanocc::TrackId); DECLARE_SOA_TABLE(TmoPrim, "AOD", "TMOPRIM", o2::soa::Index<>, // TrackMeanOccDet o2::aod::trackmeanocc::TmoPrimUnfm80); @@ -377,5 +379,21 @@ DECLARE_SOA_TABLE(TwmoRNtrackDet, "AOD", "TWMORNTRACKDET", o2::soa::Index<>, DECLARE_SOA_TABLE(TwmoRMultExtra, "AOD", "TWMORMULTEXTRA", o2::soa::Index<>, o2::aod::trackmeanocc::TwmoRobustMultExtraTableUnfm80); +using Tmo = aod::TmoTrackIds::iterator; + +using TrackQA = TracksQAVersion::iterator; + +namespace trackmeanocc +{ +DECLARE_SOA_INDEX_COLUMN_FULL(Tmo, tmo, int64_t, TmoTrackIds, ""); +DECLARE_SOA_INDEX_COLUMN_FULL(TrackQA, trackQA, int64_t, TracksQAVersion, ""); +} // namespace trackmeanocc + +DECLARE_SOA_TABLE(TrackToTracksQA, "AOD", "TRACKTOTRACKSQA", o2::aod::trackmeanocc::TrackQAId); +DECLARE_SOA_TABLE(TrackToTmo, "AOD", "TRACKTOTMO", o2::aod::trackmeanocc::TmoId); + +DECLARE_SOA_TABLE(TrackQAToTmo, "AOD", "TRACKQATOTMO", o2::aod::trackmeanocc::TmoId); +DECLARE_SOA_TABLE(TmoToTrackQA, "AOD", "TMOTOTRACKQA", o2::aod::trackmeanocc::TrackQAId); + } // namespace o2::aod #endif // COMMON_DATAMODEL_OCCUPANCYTABLES_H_ diff --git a/Common/TableProducer/occupancyTableProducer.cxx b/Common/TableProducer/occupancyTableProducer.cxx index 95d1ca72dea..a700b394772 100644 --- a/Common/TableProducer/occupancyTableProducer.cxx +++ b/Common/TableProducer/occupancyTableProducer.cxx @@ -52,6 +52,24 @@ int32_t nBCsPerOrbit = o2::constants::lhc::LHCMaxBunches; // const int nBCinTF = 114048; /// CCDB value // to be obtained from CCDB in future const int nBCinDrift = 114048 / 32; /// to get from ccdb in future +template +void sortVectorOfArray(std::vector>& myVector, const int& myIDX) +{ + std::sort(myVector.begin(), myVector.end(), [myIDX](const std::array& a, const std::array& b) { + return a[myIDX] < b[myIDX]; // sort at the required index + }); +} + +template +void checkUniqueness(const std::vector>& myVector, const int& myIDX) +{ + for (size_t i = 1; i < myVector.size(); i++) { + if (myVector[i][myIDX] <= myVector[i - 1][myIDX]) { + LOG(error) << "Duplicate Entries while creating Index tables :: (vec[" << i << "][" << myIDX << "]) " << myVector[i][myIDX] << " >= " << myVector[i - 1][myIDX] << " (vec[" << i - 1 << "][" << myIDX << "])"; + } + } +} + struct OccupancyTableProducer { Service ccdb; @@ -1208,7 +1226,9 @@ struct OccupancyTableProducer { struct TrackMeanOccTableProducer { // //declare production of tables - Produces genTmoTrackId; + Produces genTmoTrackId; + Produces genTmoToTrackQA; + Produces genTrackQAToTmo; Produces genTmoPrim; Produces genTmoT0V0; @@ -1262,6 +1282,9 @@ struct TrackMeanOccTableProducer { Configurable fillQA1{"fillQA1", true, "fill QA LOG Ratios"}; Configurable fillQA2{"fillQA2", true, "fill QA condition dependent QAs"}; + Configurable buildPointerTrackQAToTMOTable{"buildPointerTrackQAToTMOTable", true, "buildPointerTrackQAToTMOTable"}; + Configurable buildPointerTMOToTrackQATable{"buildPointerTMOToTrackQATable", true, "buildPointerTMOToTrackQATable"}; + // vectors to be used for occupancy estimation std::vector occPrimUnfm80; @@ -1727,6 +1750,7 @@ struct TrackMeanOccTableProducer { fillWeightMeanOccTable }; + std::vector> trackQAGIListforTMOList; template void executeTrackOccProducerProcessing(B const& BCs, C const& collisions, T const& tracks, U const& tracksQA, O const& occsRobustT0V0Prim, V const& occs, bool const& executeInThisBlock) { @@ -1871,6 +1895,9 @@ struct TrackMeanOccTableProducer { float weightMeanOccRobustNtrackDetUnfm80 = 0; float weightMeanOccRobustMultTableUnfm80 = 0; + int trackTMOcounter = -1; + trackQAGIListforTMOList.clear(); + for (const auto& trackQA : tracksQA) { auto const& track = trackQA.template track_as(); auto collision = collisions.begin(); @@ -2034,7 +2061,9 @@ struct TrackMeanOccTableProducer { // If multiple process are on, fill this table only once if (executeInThisBlock) { + trackTMOcounter++; genTmoTrackId(track.globalIndex()); + trackQAGIListforTMOList.push_back({trackQA.globalIndex(), trackTMOcounter}); } if constexpr (qaMode == fillOccRobustT0V0dependentQA) { @@ -2320,6 +2349,52 @@ struct TrackMeanOccTableProducer { } } } // end of trackQA loop + + // build the IndexTables here + if (executeInThisBlock) { + if (buildPointerTrackQAToTMOTable) { + // create pointer table from trackQA to TrackMeanOcc + sortVectorOfArray(trackQAGIListforTMOList, 0); // sort the list //Its easy to search in a sorted list + checkUniqueness(trackQAGIListforTMOList, 0); // check the uniqueness of track.globalIndex() + + int currentIDXforCheck = 0; + int listSize = trackQAGIListforTMOList.size(); + for (const auto& trackQA : tracksQA) { + while (trackQA.globalIndex() > trackQAGIListforTMOList[currentIDXforCheck][0]) { + currentIDXforCheck++; // increment the currentIDXforCheck for missing or invalid cases e.g. value = -1; + if (currentIDXforCheck >= listSize) { + break; + } + } + if (trackQA.globalIndex() == trackQAGIListforTMOList[currentIDXforCheck][0]) { + genTrackQAToTmo(trackQAGIListforTMOList[currentIDXforCheck][1]); + } else { + genTrackQAToTmo(-1); // put a dummy index when track is not found in trackQA + } + } + } + if (buildPointerTMOToTrackQATable) { + // create pointer table from TrackMeanOcc to trackQA + sortVectorOfArray(trackQAGIListforTMOList, 1); // sort the list //Its easy to search in a sorted list + checkUniqueness(trackQAGIListforTMOList, 1); // check the uniqueness of track.globalIndex() + + int currentIDXforCheck = 0; + int listSize = trackQAGIListforTMOList.size(); + for (int iCounter = 0; iCounter <= trackTMOcounter; iCounter++) { + while (iCounter > trackQAGIListforTMOList[currentIDXforCheck][1]) { + currentIDXforCheck++; // increment the currentIDXforCheck for missing or invalid cases e.g. value = -1; + if (currentIDXforCheck >= listSize) { + break; + } + } + if (iCounter == trackQAGIListforTMOList[currentIDXforCheck][1]) { + genTmoToTrackQA(trackQAGIListforTMOList[currentIDXforCheck][0]); + } else { + genTmoToTrackQA(-1); // put a dummy index when track is not found in trackQA + } + } + } + } // end of executeInThisBlock } // end of else block of constexpr } @@ -2602,9 +2677,88 @@ struct TrackMeanOccTableProducer { PROCESS_SWITCH(TrackMeanOccTableProducer, processFullOccTableProduer, "processFullOccTableProduer", false); }; +struct CreatePointerTables { + + Produces genTrackToTracksQA; + Produces genTrackToTmo; + + void processNothing(aod::Collisions const&) + { + return; + } + PROCESS_SWITCH(CreatePointerTables, processNothing, "process Nothing", true); + + std::vector> trackGIForTrackQAIndexList; + using MyTracksQA = aod::TracksQAVersion; + void processTrackToTrackQAPointer(aod::Tracks const& tracks, MyTracksQA const& tracksQA) + { + trackGIForTrackQAIndexList.clear(); + for (const auto& trackQA : tracksQA) { + auto const& track = trackQA.template track_as(); + trackGIForTrackQAIndexList.push_back({track.globalIndex(), trackQA.globalIndex()}); + } + + sortVectorOfArray(trackGIForTrackQAIndexList, 0); // sort the list //Its easy to search in a sorted list + checkUniqueness(trackGIForTrackQAIndexList, 0); // check the uniqueness of track.globalIndex() + + // create pointer table + int currentIDXforCheck = 0; + int listSize = trackGIForTrackQAIndexList.size(); + + for (const auto& track : tracks) { + while (track.globalIndex() > trackGIForTrackQAIndexList[currentIDXforCheck][0]) { + currentIDXforCheck++; // increment the currentIDXforCheck for missing or invalid cases e.g. value = -1; + if (currentIDXforCheck >= listSize) { + break; + } + } + if (track.globalIndex() == trackGIForTrackQAIndexList[currentIDXforCheck][0]) { + genTrackToTracksQA(trackGIForTrackQAIndexList[currentIDXforCheck][1]); + } else { + genTrackToTracksQA(-1); // put a dummy index when track is not found in trackQA + } + } + } + PROCESS_SWITCH(CreatePointerTables, processTrackToTrackQAPointer, "processTrackToTrackQAPointer", false); + + std::vector> trackGIForTMOIndexList; + void processTrackToTrackMeanOccsPointer(aod::Tracks const& tracks, aod::TmoTrackIds const& tmoTrackIds) + { + trackGIForTMOIndexList.clear(); + int tmoCounter = -1; + for (const auto& tmoTrackId : tmoTrackIds) { + tmoCounter++; + auto const& track = tmoTrackId.template track_as(); + trackGIForTMOIndexList.push_back({track.globalIndex(), tmoCounter}); // tmoTrackId Global Index is not working :: tmoTrackId.globalIndex()}); + } + sortVectorOfArray(trackGIForTMOIndexList, 0); // sort the list //Its easy to search in a sorted list + checkUniqueness(trackGIForTMOIndexList, 0); // check the uniqueness of track.globalIndex() + + // create pointer table + int currentIDXforCheck = 0; + int listSize = trackGIForTMOIndexList.size(); + + for (const auto& track : tracks) { + while (track.globalIndex() > trackGIForTMOIndexList[currentIDXforCheck][0]) { + currentIDXforCheck++; // increment the currentIDXforCheck for missing or invalid cases e.g. value = -1; + if (currentIDXforCheck >= listSize) { + break; + } + } + if (track.globalIndex() == trackGIForTMOIndexList[currentIDXforCheck][0]) { + genTrackToTmo(trackGIForTMOIndexList[currentIDXforCheck][1]); + } else { + genTrackToTmo(-1); // put a dummy index when track is not found in trackQA + } + } + } + PROCESS_SWITCH(CreatePointerTables, processTrackToTrackMeanOccsPointer, "processTrackToTrackMeanOccsPointer", false); +}; + WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{ adaptAnalysisTask(cfgc), - adaptAnalysisTask(cfgc)}; + adaptAnalysisTask(cfgc), + adaptAnalysisTask(cfgc)}; } From 74ff42c13ca31fb99bceb1d29990009212831788 Mon Sep 17 00:00:00 2001 From: Marcello Di Costanzo <96481191+Marcellocosti@users.noreply.github.com> Date: Sat, 21 Jun 2025 14:03:12 +0200 Subject: [PATCH 170/871] [PWGHF] Fix issues in correlated bkg matching (#11712) --- PWGHF/Utils/utilsMcGen.h | 10 +++++----- PWGHF/Utils/utilsMcMatching.h | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/PWGHF/Utils/utilsMcGen.h b/PWGHF/Utils/utilsMcGen.h index 6f9ed6f4fed..6c95b10b493 100644 --- a/PWGHF/Utils/utilsMcGen.h +++ b/PWGHF/Utils/utilsMcGen.h @@ -219,7 +219,7 @@ void fillMcMatchGen3Prong(T const& mcParticles, U const& mcParticlesPerMcColl, V // D± → π± K∓ π± if (flag == 0) { if (RecoDecay::isMatchedMCGen(mcParticles, particle, Pdg::kDPlus, std::array{+kPiPlus, -kKPlus, +kPiPlus}, true, &sign, 2)) { - flag = sign * (1 << o2::aod::hf_cand_3prong::DecayType::DplusToPiKPi); + flag = sign * o2::hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi; } } @@ -229,11 +229,11 @@ void fillMcMatchGen3Prong(T const& mcParticles, U const& mcParticlesPerMcColl, V if (RecoDecay::isMatchedMCGen(mcParticles, particle, Pdg::kDS, std::array{+kKPlus, -kKPlus, +kPiPlus}, true, &sign, 2)) { // DecayType::DsToKKPi is used to flag both Ds± → K± K∓ π± and D± → K± K∓ π± // TODO: move to different and explicit flags - flag = sign * (1 << o2::aod::hf_cand_3prong::DecayType::DsToKKPi); + flag = sign * o2::hf_decay::hf_cand_3prong::DecayChannelMain::DsToPiKK; } else if (RecoDecay::isMatchedMCGen(mcParticles, particle, Pdg::kDPlus, std::array{+kKPlus, -kKPlus, +kPiPlus}, true, &sign, 2)) { // DecayType::DsToKKPi is used to flag both Ds± → K± K∓ π± and D± → K± K∓ π± // TODO: move to different and explicit flags - flag = sign * (1 << o2::aod::hf_cand_3prong::DecayType::DsToKKPi); + flag = sign * o2::hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKK; isDplus = true; } if (flag != 0) { @@ -244,9 +244,9 @@ void fillMcMatchGen3Prong(T const& mcParticles, U const& mcParticlesPerMcColl, V arrPDGDaugh[jProng] = std::abs(daughJ.pdgCode()); } if ((arrPDGDaugh[0] == arrPDGResonantDPhiPi[0] && arrPDGDaugh[1] == arrPDGResonantDPhiPi[1]) || (arrPDGDaugh[0] == arrPDGResonantDPhiPi[1] && arrPDGDaugh[1] == arrPDGResonantDPhiPi[0])) { - channel = isDplus ? o2::aod::hf_cand_3prong::DecayChannelDToKKPi::DplusToPhiPi : o2::aod::hf_cand_3prong::DecayChannelDToKKPi::DsToPhiPi; + channel = isDplus ? o2::hf_decay::hf_cand_3prong::DecayChannelResonant::DplusToPhiPi : o2::hf_decay::hf_cand_3prong::DecayChannelResonant::DsToPhiPi; } else if ((arrPDGDaugh[0] == arrPDGResonantDKstarK[0] && arrPDGDaugh[1] == arrPDGResonantDKstarK[1]) || (arrPDGDaugh[0] == arrPDGResonantDKstarK[1] && arrPDGDaugh[1] == arrPDGResonantDKstarK[0])) { - channel = isDplus ? o2::aod::hf_cand_3prong::DecayChannelDToKKPi::DplusToK0starK : o2::aod::hf_cand_3prong::DecayChannelDToKKPi::DsToK0starK; + channel = isDplus ? o2::hf_decay::hf_cand_3prong::DecayChannelResonant::DplusToKstar0K : o2::hf_decay::hf_cand_3prong::DecayChannelResonant::DsToKstar0K; } } } diff --git a/PWGHF/Utils/utilsMcMatching.h b/PWGHF/Utils/utilsMcMatching.h index 5736e6ab278..7718fe6ff39 100644 --- a/PWGHF/Utils/utilsMcMatching.h +++ b/PWGHF/Utils/utilsMcMatching.h @@ -57,8 +57,8 @@ namespace hf_cand_3prong // D± static const std::unordered_map> daughtersDplusMain{ - {DecayChannelMain::DplusToPiKPi, {+kKMinus, +kKPlus, +kPiPlus}}, - {DecayChannelMain::DplusToPiKK, {+kKMinus, +kPiPlus, +kPiPlus}}, + {DecayChannelMain::DplusToPiKPi, {+kKMinus, +kPiPlus, +kPiPlus}}, + {DecayChannelMain::DplusToPiKK, {+kKMinus, +kKPlus, +kPiPlus}}, {DecayChannelMain::DplusToPiKPiPi0, {+kKMinus, +kPiPlus, +kPiPlus, +kPi0}}, {DecayChannelMain::DplusToPiPiPi, {+kPiMinus, +kPiPlus, +kPiPlus}}, }; @@ -66,7 +66,7 @@ static const std::unordered_map> daught static const std::unordered_map> daughtersDplusResonant{ {DecayChannelResonant::DplusToPhiPi, {+o2::constants::physics::kPhi, +kPiPlus}}, {DecayChannelResonant::DplusToKstar0K, {-o2::constants::physics::kK0Star892, +kKPlus}}, - {DecayChannelResonant::DplusToKstar1430_0K, {+10311, +kKPlus}}, + {DecayChannelResonant::DplusToKstar1430_0K, {-10311, +kKPlus}}, {DecayChannelResonant::DplusToRho0Pi, {+kRho770_0, +kPiPlus}}, {DecayChannelResonant::DplusToF2_1270Pi, {+225, +kPiPlus}}, }; @@ -110,7 +110,7 @@ static const std::unordered_map> {DecayChannelResonant::DstarToD0ToKstarPi, {-o2::constants::physics::kKPlusStar892, +kPiPlus}}, {DecayChannelResonant::DstarToDplusToPhiPi, {+o2::constants::physics::kPhi, +kPiPlus}}, {DecayChannelResonant::DstarToDplusToKstar0K, {-o2::constants::physics::kK0Star892, +kKPlus}}, - {DecayChannelResonant::DstarToDplusToKstar1430_0K, {+10311, +kKPlus}}, + {DecayChannelResonant::DstarToDplusToKstar1430_0K, {-10311, +kKPlus}}, {DecayChannelResonant::DstarToDplusToRho0Pi, {+kRho770_0, +kPiPlus}}, {DecayChannelResonant::DstarToDplusToF2_1270Pi, {+225, +kPiPlus}}, }; @@ -123,7 +123,7 @@ static const std::unordered_map> daught {DecayChannelMain::LcToPKK, {+kProton, +kKMinus, +kKPlus}}}; static const std::unordered_map> daughtersLcResonant{ - {DecayChannelResonant::LcToPKstar0, {+o2::constants::physics::kK0Star892, +kProton}}, + {DecayChannelResonant::LcToPKstar0, {-o2::constants::physics::kK0Star892, +kProton}}, {DecayChannelResonant::LcToDeltaplusplusK, {+2224, +kKMinus}}, {DecayChannelResonant::LcToL1520Pi, {+102134, +kPiPlus}}, }; From e39b3af6e4f2d13ed7d920d55c5a0a4f4ede75b6 Mon Sep 17 00:00:00 2001 From: ddobrigk Date: Sat, 21 Jun 2025 14:06:45 +0200 Subject: [PATCH 171/871] [Common] Add files for derived data analysis of sel. bias study (#11713) Co-authored-by: ALICE Builder --- Common/DataModel/SelectionStudyTables.h | 57 ++++++++ Common/TableProducer/CMakeLists.txt | 4 + Common/TableProducer/selectionStudyTable.cxx | 133 +++++++++++++++++++ 3 files changed, 194 insertions(+) create mode 100644 Common/DataModel/SelectionStudyTables.h create mode 100644 Common/TableProducer/selectionStudyTable.cxx diff --git a/Common/DataModel/SelectionStudyTables.h b/Common/DataModel/SelectionStudyTables.h new file mode 100644 index 00000000000..3a62c30b267 --- /dev/null +++ b/Common/DataModel/SelectionStudyTables.h @@ -0,0 +1,57 @@ +// 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 SelectionStudyTables +/// \brief tables meant to do event selection studies for O-O / light systems +/// +/// \author ALICE + +#include "Framework/ASoA.h" +#include "Framework/AnalysisDataModel.h" + +#include + +#ifndef COMMON_DATAMODEL_SELECTIONSTUDYTABLES_H_ +#define COMMON_DATAMODEL_SELECTIONSTUDYTABLES_H_ + +namespace o2::aod +{ +namespace selectionstudy +{ +DECLARE_SOA_COLUMN(PtPions, ptPions, std::vector); +DECLARE_SOA_COLUMN(PtKaons, ptKaons, std::vector); +DECLARE_SOA_COLUMN(PtProtons, ptProtons, std::vector); +DECLARE_SOA_COLUMN(PtK0s, ptPK0s, std::vector); +DECLARE_SOA_COLUMN(PtLambdas, ptLambdas, std::vector); +DECLARE_SOA_COLUMN(PtXis, ptXis, std::vector); +DECLARE_SOA_COLUMN(PtOmegas, ptOmegas, std::vector); +DECLARE_SOA_COLUMN(PtPhis, ptPhis, std::vector); +DECLARE_SOA_COLUMN(PtKStars, ptKStars, std::vector); +DECLARE_SOA_COLUMN(PtDs, ptDs, std::vector); +DECLARE_SOA_COLUMN(PtLambdaCs, ptLambdaCs, std::vector); +DECLARE_SOA_COLUMN(PtJPsis, ptJPsis, std::vector); +} // namespace selectionstudy + +DECLARE_SOA_TABLE(PIDPts, "AOD", "PIDPTS", o2::soa::Index<>, + o2::aod::selectionstudy::PtPions, + o2::aod::selectionstudy::PtKaons, + o2::aod::selectionstudy::PtProtons, + o2::aod::selectionstudy::PtK0s, + o2::aod::selectionstudy::PtLambdas, + o2::aod::selectionstudy::PtXis, + o2::aod::selectionstudy::PtOmegas, + o2::aod::selectionstudy::PtPhis, + o2::aod::selectionstudy::PtKStars, + o2::aod::selectionstudy::PtDs, + o2::aod::selectionstudy::PtLambdaCs, + o2::aod::selectionstudy::PtJPsis); +} // namespace o2::aod +#endif // COMMON_DATAMODEL_SELECTIONSTUDYTABLES_H_ diff --git a/Common/TableProducer/CMakeLists.txt b/Common/TableProducer/CMakeLists.txt index 62211406807..502f3c3d076 100644 --- a/Common/TableProducer/CMakeLists.txt +++ b/Common/TableProducer/CMakeLists.txt @@ -160,3 +160,7 @@ o2physics_add_dpl_workflow(muon-realignment PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::DetectorsBase O2::DetectorsCommonDataFormats O2::MathUtils O2::MCHTracking O2::DataFormatsMCH O2::GlobalTracking O2::MCHBase O2::MCHGeometryTransformer O2::CommonUtils COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(selectionstudytable + SOURCES selectionStudyTable.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) diff --git a/Common/TableProducer/selectionStudyTable.cxx b/Common/TableProducer/selectionStudyTable.cxx new file mode 100644 index 00000000000..4d27e358ed1 --- /dev/null +++ b/Common/TableProducer/selectionStudyTable.cxx @@ -0,0 +1,133 @@ +// 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 selectionStudyTable.cxx +/// \brief Produces tables for centrality selection bias studies +/// +/// \author ALICE +/// + +#include "Common/DataModel/SelectionStudyTables.h" + +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/ConfigParamSpec.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/O2DatabasePDGPlugin.h" +#include "Framework/runDataProcessing.h" + +#include +#include +#include +#include + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +struct SelectionStudyTable { + Produces pidpts; + + // could be done in a vector of vectors + // left for future iteration + std::vector ptpi; + std::vector ptka; + std::vector ptpr; + std::vector ptk0; + std::vector ptla; + std::vector ptxi; + std::vector ptom; + std::vector ptph; + std::vector ptks; + std::vector ptd; + std::vector ptlc; + std::vector ptjp; + + void init(InitContext&) + { + } + + void process(aod::McCollision const&, aod::McParticles const& mcParticles) + { + ptpi.clear(); + ptka.clear(); + ptpr.clear(); + ptk0.clear(); + ptla.clear(); + ptxi.clear(); + ptom.clear(); + ptph.clear(); + ptks.clear(); + ptd.clear(); + ptlc.clear(); + ptjp.clear(); + for (auto const& mcPart : mcParticles) { + if (std::fabs(mcPart.y()) > 0.5) { + continue; // only do midrapidity particles + } + + // handle resonances first to make sure phys prim crit does not reject them + if (mcPart.pdgCode() == 333) { + ptph.push_back(mcPart.pt()); + } + if (std::abs(mcPart.pdgCode()) == 313) { + ptks.push_back(mcPart.pt()); + } + + // resonances handled, move to primaries + if (!mcPart.isPhysicalPrimary()) { + continue; + } + if (std::abs(mcPart.pdgCode()) == 211) { + ptpi.push_back(mcPart.pt()); + } + if (std::abs(mcPart.pdgCode()) == 321) { + ptka.push_back(mcPart.pt()); + } + if (std::abs(mcPart.pdgCode()) == 2212) { + ptpr.push_back(mcPart.pt()); + } + if (std::abs(mcPart.pdgCode()) == 310) { + ptk0.push_back(mcPart.pt()); + } + if (std::abs(mcPart.pdgCode()) == 3122) { + ptla.push_back(mcPart.pt()); + } + if (std::abs(mcPart.pdgCode()) == 3312) { + ptxi.push_back(mcPart.pt()); + } + if (std::abs(mcPart.pdgCode()) == 3334) { + ptom.push_back(mcPart.pt()); + } + if (std::abs(mcPart.pdgCode()) == 3334) { + ptom.push_back(mcPart.pt()); + } + // inclusive HF for now + if (std::abs(mcPart.pdgCode()) == 421) { + ptd.push_back(mcPart.pt()); + } + if (std::abs(mcPart.pdgCode()) == 4122) { + ptd.push_back(mcPart.pt()); + } + if (std::abs(mcPart.pdgCode()) == 443) { + ptjp.push_back(mcPart.pt()); + } + } + + pidpts(ptpi, ptka, ptpr, ptk0, ptla, ptxi, ptom, ptph, ptks, ptd, ptlc, ptjp); + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} From f10c7eab9a29d6159958debb91fc783e0a914f0d Mon Sep 17 00:00:00 2001 From: Daiki Sekihata Date: Sat, 21 Jun 2025 16:09:17 +0200 Subject: [PATCH 172/871] [PWGEM/Dilepton] update for ITSsa and include headers (#11715) --- PWGEM/Dilepton/Core/DielectronCut.cxx | 19 ++-- PWGEM/Dilepton/Core/DielectronCut.h | 97 +++++++++++-------- PWGEM/Dilepton/Core/Dilepton.h | 7 +- PWGEM/Dilepton/Core/DileptonMC.h | 7 +- PWGEM/Dilepton/Core/PhotonHBT.h | 7 +- PWGEM/Dilepton/Core/SingleTrackQC.h | 7 +- PWGEM/Dilepton/Core/SingleTrackQCMC.h | 7 +- .../TableProducer/skimmerPrimaryElectron.cxx | 18 ++-- PWGEM/Dilepton/Tasks/prefilterDielectron.cxx | 7 +- PWGEM/Dilepton/Tasks/vpPairQC.cxx | 43 ++++---- PWGEM/Dilepton/Tasks/vpPairQCMC.cxx | 47 ++++----- PWGEM/Dilepton/Utils/EventHistograms.h | 3 + PWGEM/Dilepton/Utils/MCUtilities.h | 5 +- PWGEM/PhotonMeson/Core/DalitzEECut.cxx | 13 ++- PWGEM/PhotonMeson/Core/DalitzEECut.h | 82 +++++++++------- PWGEM/PhotonMeson/Core/Pi0EtaToGammaGamma.h | 74 +++++++------- PWGEM/PhotonMeson/Core/Pi0EtaToGammaGammaMC.h | 54 ++++++----- .../skimmerPrimaryElectronFromDalitzEE.cxx | 9 +- PWGEM/PhotonMeson/Tasks/dalitzEEQC.cxx | 34 ++++--- PWGEM/PhotonMeson/Tasks/dalitzEEQCMC.cxx | 40 ++++---- PWGEM/PhotonMeson/Utils/EventHistograms.h | 3 + PWGEM/PhotonMeson/Utils/MCUtilities.h | 6 +- PWGEM/PhotonMeson/Utils/NMHistograms.h | 10 +- 23 files changed, 343 insertions(+), 256 deletions(-) diff --git a/PWGEM/Dilepton/Core/DielectronCut.cxx b/PWGEM/Dilepton/Core/DielectronCut.cxx index cd0ae3f5078..9407e6413eb 100644 --- a/PWGEM/Dilepton/Core/DielectronCut.cxx +++ b/PWGEM/Dilepton/Core/DielectronCut.cxx @@ -13,11 +13,12 @@ // Class for dielectron Cut // -#include -#include +#include "PWGEM/Dilepton/Core/DielectronCut.h" #include "Framework/Logger.h" -#include "PWGEM/Dilepton/Core/DielectronCut.h" + +#include +#include ClassImp(DielectronCut); @@ -141,12 +142,12 @@ void DielectronCut::SetChi2PerClusterITS(float min, float max) mMaxChi2PerClusterITS = max; LOG(info) << "Dielectron Cut, set chi2 per cluster ITS range: " << mMinChi2PerClusterITS << " - " << mMaxChi2PerClusterITS; } -void DielectronCut::SetMeanClusterSizeITS(float min, float max, float minP, float maxP) +void DielectronCut::SetMeanClusterSizeITS(float min, float max) { mMinMeanClusterSizeITS = min; mMaxMeanClusterSizeITS = max; - mMinP_ITSClusterSize = minP; - mMaxP_ITSClusterSize = maxP; + // 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) @@ -341,3 +342,9 @@ void DielectronCut::RequireITSib1st(bool flag) mRequireITSib1st = flag; LOG(info) << "Dielectron Cut, require ITS ib 1st: " << mRequireITSib1st; } +void DielectronCut::IncludeITSsa(bool flag, float max) +{ + mIncludeITSsa = flag; + mMaxPtITSsa = max; + LOG(info) << "Dielectron Cut, include ITSsa tracks: " << mIncludeITSsa << ", mMaxPtITSsa = " << mMaxPtITSsa; +} diff --git a/PWGEM/Dilepton/Core/DielectronCut.h b/PWGEM/Dilepton/Core/DielectronCut.h index eec8c0928b9..b69bd4b047f 100644 --- a/PWGEM/Dilepton/Core/DielectronCut.h +++ b/PWGEM/Dilepton/Core/DielectronCut.h @@ -16,21 +16,22 @@ #ifndef PWGEM_DILEPTON_CORE_DIELECTRONCUT_H_ #define PWGEM_DILEPTON_CORE_DIELECTRONCUT_H_ -#include -#include -#include -#include -#include -#include "TNamed.h" -#include "Math/Vector4D.h" - +#include "PWGEM/Dilepton/Utils/EMTrackUtilities.h" #include "PWGEM/Dilepton/Utils/MlResponseDielectronSingleTrack.h" +#include "PWGEM/Dilepton/Utils/PairUtilities.h" -#include "Framework/Logger.h" -#include "Framework/DataTypes.h" #include "CommonConstants/PhysicsConstants.h" -#include "PWGEM/Dilepton/Utils/PairUtilities.h" -#include "PWGEM/Dilepton/Utils/EMTrackUtilities.h" +#include "Framework/DataTypes.h" +#include "Framework/Logger.h" + +#include "Math/Vector4D.h" +#include "TNamed.h" + +#include +#include +#include +#include +#include using namespace o2::aod::pwgem::dilepton::utils::emtrackutil; using namespace o2::aod::pwgem::dilepton::utils::pairutil; @@ -64,7 +65,7 @@ class DielectronCut : public TNamed kDCAz, kITSNCls, kITSChi2NDF, - kITSClusterSize, + // kITSClusterSize, kPrefilter, kNCuts }; @@ -149,7 +150,7 @@ class DielectronCut : public TNamed template bool IsSelectedTrack(TTrack const& track, TCollision const& collision = 0) const { - if (!track.hasITS() || !track.hasTPC()) { // track has to be ITS-TPC matched track + if (!track.hasITS()) { return false; } @@ -182,9 +183,10 @@ class DielectronCut : public TNamed if (!IsSelectedTrack(track, DielectronCuts::kITSChi2NDF)) { return false; } - if (!IsSelectedTrack(track, DielectronCuts::kITSClusterSize)) { - return false; - } + + // if (!IsSelectedTrack(track, DielectronCuts::kITSClusterSize)) { + // return false; + // } if (mRequireITSibAny) { auto hits_ib = std::count_if(its_ib_any_Requirement.second.begin(), its_ib_any_Requirement.second.end(), [&](auto&& requiredLayer) { return track.itsClusterMap() & (1 << requiredLayer); }); @@ -200,24 +202,34 @@ class DielectronCut : public TNamed } } - // TPC cuts - if (!IsSelectedTrack(track, DielectronCuts::kTPCNCls)) { - return false; - } - if (!IsSelectedTrack(track, DielectronCuts::kTPCCrossedRows)) { + if (!mIncludeITSsa && (!track.hasITS() || !track.hasTPC())) { // track has to be ITS-TPC matched track return false; } - if (!IsSelectedTrack(track, DielectronCuts::kTPCCrossedRowsOverNCls)) { - return false; - } - if (!IsSelectedTrack(track, DielectronCuts::kTPCFracSharedClusters)) { - return false; - } - if (!IsSelectedTrack(track, DielectronCuts::kRelDiffPin)) { + + if ((track.hasITS() && !track.hasTPC() && !track.hasTRD() && !track.hasTOF()) && track.pt() > mMaxPtITSsa) { // ITSsa return false; } - if (!IsSelectedTrack(track, DielectronCuts::kTPCChi2NDF)) { - return false; + + // TPC cuts + if (track.hasTPC()) { + if (!IsSelectedTrack(track, DielectronCuts::kTPCNCls)) { + return false; + } + if (!IsSelectedTrack(track, DielectronCuts::kTPCCrossedRows)) { + return false; + } + if (!IsSelectedTrack(track, DielectronCuts::kTPCCrossedRowsOverNCls)) { + return false; + } + if (!IsSelectedTrack(track, DielectronCuts::kTPCFracSharedClusters)) { + return false; + } + if (!IsSelectedTrack(track, DielectronCuts::kRelDiffPin)) { + return false; + } + if (!IsSelectedTrack(track, DielectronCuts::kTPCChi2NDF)) { + return false; + } } if (mApplyPF && !IsSelectedTrack(track, DielectronCuts::kPrefilter)) { @@ -230,8 +242,15 @@ class DielectronCut : public TNamed return false; } } else { - if (!PassPID(track)) { - return false; + if (track.hasITS() && !track.hasTPC() && !track.hasTRD() && !track.hasTOF()) { // ITSsa + float meanClusterSizeITS = track.meanClusterSizeITS() * std::cos(std::atan(track.tgl())); + if (meanClusterSizeITS < mMinMeanClusterSizeITS || mMaxMeanClusterSizeITS < meanClusterSizeITS) { + return false; + } + } else { // not ITSsa + if (!PassPID(track)) { + return false; + } } } @@ -400,9 +419,6 @@ class DielectronCut : public TNamed case DielectronCuts::kITSChi2NDF: return mMinChi2PerClusterITS < track.itsChi2NCl() && track.itsChi2NCl() < mMaxChi2PerClusterITS; - case DielectronCuts::kITSClusterSize: - return ((mMinP_ITSClusterSize < track.p() && track.p() < mMaxP_ITSClusterSize) ? (mMinMeanClusterSizeITS < track.meanClusterSizeITS() * std::cos(std::atan(track.tgl())) && track.meanClusterSizeITS() * std::cos(std::atan(track.tgl())) < mMaxMeanClusterSizeITS) : true); - case DielectronCuts::kPrefilter: return track.pfb() <= 0; @@ -433,7 +449,7 @@ class DielectronCut : public TNamed void SetChi2PerClusterTPC(float min, float max); void SetNClustersITS(int min, int max); void SetChi2PerClusterITS(float min, float max); - void SetMeanClusterSizeITS(float min, float max, float minP = 0.f, float maxP = 0.f); + void SetMeanClusterSizeITS(float min, float max); void SetChi2TOF(float min, float max); void SetPIDScheme(int scheme); @@ -470,6 +486,7 @@ class DielectronCut : public TNamed void SetTrackMaxDcaXYPtDep(std::function ptDepCut); void ApplyPrefilter(bool flag); void ApplyPhiV(bool flag); + void IncludeITSsa(bool flag, float maxpt); void SetPIDMlResponse(o2::analysis::MlResponseDielectronSingleTrack* mlResponse) { @@ -523,8 +540,10 @@ class DielectronCut : public TNamed std::function mMaxDcaXYPtDep{}; // max dca in xy plane as function of pT bool mApplyPhiV{true}; bool mApplyPF{false}; - float mMinMeanClusterSizeITS{-1e10f}, mMaxMeanClusterSizeITS{1e10f}; // max x cos(Lmabda) - float mMinP_ITSClusterSize{0.0}, mMaxP_ITSClusterSize{0.0}; + float mMinMeanClusterSizeITS{0.0}, mMaxMeanClusterSizeITS{1e10f}; // x cos(lmabda) + // float mMinP_ITSClusterSize{0.0}, mMaxP_ITSClusterSize{0.0}; + bool mIncludeITSsa{false}; + float mMaxPtITSsa{0.15}; // pid cuts int mPIDScheme{-1}; diff --git a/PWGEM/Dilepton/Core/Dilepton.h b/PWGEM/Dilepton/Core/Dilepton.h index 69e5d074fc0..0abb72b615e 100644 --- a/PWGEM/Dilepton/Core/Dilepton.h +++ b/PWGEM/Dilepton/Core/Dilepton.h @@ -210,8 +210,6 @@ struct Dilepton { Configurable cfg_require_itsib_1st{"cfg_require_itsib_1st", true, "flag to require ITS ib 1st hit"}; Configurable cfg_min_its_cluster_size{"cfg_min_its_cluster_size", 0.f, "min ITS cluster size"}; Configurable cfg_max_its_cluster_size{"cfg_max_its_cluster_size", 16.f, "max ITS cluster size"}; - Configurable cfg_min_p_its_cluster_size{"cfg_min_p_its_cluster_size", 0.0, "min p to apply ITS cluster size cut"}; - Configurable cfg_max_p_its_cluster_size{"cfg_max_p_its_cluster_size", 0.0, "max p to apply ITS cluster size cut"}; Configurable cfg_min_rel_diff_pin{"cfg_min_rel_diff_pin", -1e+10, "min rel. diff. between pin and ppv"}; Configurable cfg_max_rel_diff_pin{"cfg_max_rel_diff_pin", +1e+10, "max rel. diff. between pin and ppv"}; @@ -239,6 +237,8 @@ struct Dilepton { Configurable cfg_min_p_ITSNsigmaPr{"cfg_min_p_ITSNsigmaPr", 0.0, "min p for proton exclusion in ITS"}; Configurable cfg_max_p_ITSNsigmaPr{"cfg_max_p_ITSNsigmaPr", 0.0, "max p for proton exclusion in ITS"}; Configurable enableTTCA{"enableTTCA", true, "Flag to enable or disable TTCA"}; + Configurable includeITSsa{"includeITSsa", false, "Flag to enable ITSsa tracks"}; + Configurable cfg_max_pt_track_ITSsa{"cfg_max_pt_track_ITSsa", 0.15, "max pt for ITSsa tracks"}; // configuration for PID ML Configurable> onnxFileNames{"onnxFileNames", std::vector{"filename"}, "ONNX file names for each bin (if not from CCDB full path)"}; @@ -683,13 +683,14 @@ struct Dilepton { fDielectronCut.SetChi2PerClusterTPC(0.0, dielectroncuts.cfg_max_chi2tpc); 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, dielectroncuts.cfg_min_p_its_cluster_size, dielectroncuts.cfg_max_p_its_cluster_size); + fDielectronCut.SetMeanClusterSizeITS(dielectroncuts.cfg_min_its_cluster_size, dielectroncuts.cfg_max_its_cluster_size); fDielectronCut.SetTrackMaxDcaXY(dielectroncuts.cfg_max_dcaxy); fDielectronCut.SetTrackMaxDcaZ(dielectroncuts.cfg_max_dcaz); fDielectronCut.RequireITSibAny(dielectroncuts.cfg_require_itsib_any); fDielectronCut.RequireITSib1st(dielectroncuts.cfg_require_itsib_1st); fDielectronCut.SetChi2TOF(0, dielectroncuts.cfg_max_chi2tof); fDielectronCut.SetRelDiffPin(dielectroncuts.cfg_min_rel_diff_pin, dielectroncuts.cfg_max_rel_diff_pin); + fDielectronCut.IncludeITSsa(dielectroncuts.includeITSsa, dielectroncuts.cfg_max_pt_track_ITSsa); // for eID fDielectronCut.SetPIDScheme(dielectroncuts.cfg_pid_scheme); diff --git a/PWGEM/Dilepton/Core/DileptonMC.h b/PWGEM/Dilepton/Core/DileptonMC.h index 964ac885cb8..150d4971fbf 100644 --- a/PWGEM/Dilepton/Core/DileptonMC.h +++ b/PWGEM/Dilepton/Core/DileptonMC.h @@ -201,8 +201,6 @@ struct DileptonMC { Configurable cfg_require_itsib_1st{"cfg_require_itsib_1st", true, "flag to require ITS ib 1st hit"}; Configurable cfg_min_its_cluster_size{"cfg_min_its_cluster_size", 0.f, "min ITS cluster size"}; Configurable cfg_max_its_cluster_size{"cfg_max_its_cluster_size", 16.f, "max ITS cluster size"}; - Configurable cfg_min_p_its_cluster_size{"cfg_min_p_its_cluster_size", 0.0, "min p to apply ITS cluster size cut"}; - Configurable cfg_max_p_its_cluster_size{"cfg_max_p_its_cluster_size", 0.0, "max p to apply ITS cluster size cut"}; Configurable cfg_min_rel_diff_pin{"cfg_min_rel_diff_pin", -1e+10, "min rel. diff. between pin and ppv"}; Configurable cfg_max_rel_diff_pin{"cfg_max_rel_diff_pin", +1e+10, "max rel. diff. between pin and ppv"}; @@ -230,6 +228,8 @@ struct DileptonMC { Configurable cfg_min_p_ITSNsigmaPr{"cfg_min_p_ITSNsigmaPr", 0.0, "min p for proton exclusion in ITS"}; Configurable cfg_max_p_ITSNsigmaPr{"cfg_max_p_ITSNsigmaPr", 0.0, "max p for proton exclusion in ITS"}; Configurable enableTTCA{"enableTTCA", true, "Flag to enable or disable TTCA"}; + Configurable includeITSsa{"includeITSsa", false, "Flag to enable ITSsa tracks"}; + Configurable cfg_max_pt_track_ITSsa{"cfg_max_pt_track_ITSsa", 0.15, "max pt for ITSsa tracks"}; // configuration for PID ML Configurable> onnxFileNames{"onnxFileNames", std::vector{"filename"}, "ONNX file names for each bin (if not from CCDB full path)"}; @@ -648,13 +648,14 @@ struct DileptonMC { fDielectronCut.SetChi2PerClusterTPC(0.0, dielectroncuts.cfg_max_chi2tpc); 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, dielectroncuts.cfg_min_p_its_cluster_size, dielectroncuts.cfg_max_p_its_cluster_size); + fDielectronCut.SetMeanClusterSizeITS(dielectroncuts.cfg_min_its_cluster_size, dielectroncuts.cfg_max_its_cluster_size); fDielectronCut.SetTrackMaxDcaXY(dielectroncuts.cfg_max_dcaxy); fDielectronCut.SetTrackMaxDcaZ(dielectroncuts.cfg_max_dcaz); fDielectronCut.RequireITSibAny(dielectroncuts.cfg_require_itsib_any); fDielectronCut.RequireITSib1st(dielectroncuts.cfg_require_itsib_1st); fDielectronCut.SetChi2TOF(0.0, dielectroncuts.cfg_max_chi2tof); fDielectronCut.SetRelDiffPin(dielectroncuts.cfg_min_rel_diff_pin, dielectroncuts.cfg_max_rel_diff_pin); + fDielectronCut.IncludeITSsa(dielectroncuts.includeITSsa, dielectroncuts.cfg_max_pt_track_ITSsa); // for eID fDielectronCut.SetPIDScheme(dielectroncuts.cfg_pid_scheme); diff --git a/PWGEM/Dilepton/Core/PhotonHBT.h b/PWGEM/Dilepton/Core/PhotonHBT.h index 88a7dd2d60b..bd37690eb24 100644 --- a/PWGEM/Dilepton/Core/PhotonHBT.h +++ b/PWGEM/Dilepton/Core/PhotonHBT.h @@ -209,8 +209,6 @@ struct PhotonHBT { Configurable cfg_max_dcaz{"cfg_max_dcaz", 0.2, "max dca Z for single track in cm"}; Configurable cfg_min_its_cluster_size{"cfg_min_its_cluster_size", 0.f, "min ITS cluster size"}; Configurable cfg_max_its_cluster_size{"cfg_max_its_cluster_size", 16.f, "max ITS cluster size"}; - Configurable cfg_min_p_its_cluster_size{"cfg_min_p_its_cluster_size", 0.0, "min p to apply ITS cluster size cut"}; - Configurable cfg_max_p_its_cluster_size{"cfg_max_p_its_cluster_size", 0.0, "max p to apply ITS cluster size cut"}; Configurable cfg_min_rel_diff_pin{"cfg_min_rel_diff_pin", -1e+10, "min rel. diff. between pin and ppv"}; Configurable cfg_max_rel_diff_pin{"cfg_max_rel_diff_pin", +1e+10, "max rel. diff. between pin and ppv"}; Configurable cfg_require_itsib_any{"cfg_require_itsib_any", false, "flag to require ITS ib any hits"}; @@ -240,6 +238,8 @@ struct PhotonHBT { Configurable cfg_min_p_ITSNsigmaPr{"cfg_min_p_ITSNsigmaPr", 0.0, "min p for proton exclusion in ITS"}; Configurable cfg_max_p_ITSNsigmaPr{"cfg_max_p_ITSNsigmaPr", 0.0, "max p for proton exclusion in ITS"}; Configurable enableTTCA{"enableTTCA", true, "Flag to enable or disable TTCA"}; + Configurable includeITSsa{"includeITSsa", false, "Flag to enable ITSsa tracks"}; + Configurable cfg_max_pt_track_ITSsa{"cfg_max_pt_track_ITSsa", 0.15, "max pt for ITSsa tracks"}; // configuration for PID ML Configurable> onnxFileNames{"onnxFileNames", std::vector{"filename"}, "ONNX file names for each bin (if not from CCDB full path)"}; @@ -568,11 +568,12 @@ struct PhotonHBT { fDielectronCut.SetChi2PerClusterTPC(0.0, dielectroncuts.cfg_max_chi2tpc); 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, dielectroncuts.cfg_min_p_its_cluster_size, dielectroncuts.cfg_max_p_its_cluster_size); + fDielectronCut.SetMeanClusterSizeITS(dielectroncuts.cfg_min_its_cluster_size, dielectroncuts.cfg_max_its_cluster_size); fDielectronCut.SetTrackMaxDcaXY(dielectroncuts.cfg_max_dcaxy); fDielectronCut.SetTrackMaxDcaZ(dielectroncuts.cfg_max_dcaz); fDielectronCut.SetChi2TOF(0.0, dielectroncuts.cfg_max_chi2tof); fDielectronCut.SetRelDiffPin(dielectroncuts.cfg_min_rel_diff_pin, dielectroncuts.cfg_max_rel_diff_pin); + fDielectronCut.IncludeITSsa(dielectroncuts.includeITSsa, dielectroncuts.cfg_max_pt_track_ITSsa); // for eID fDielectronCut.SetPIDScheme(dielectroncuts.cfg_pid_scheme); diff --git a/PWGEM/Dilepton/Core/SingleTrackQC.h b/PWGEM/Dilepton/Core/SingleTrackQC.h index c0782033a39..4209184cc01 100644 --- a/PWGEM/Dilepton/Core/SingleTrackQC.h +++ b/PWGEM/Dilepton/Core/SingleTrackQC.h @@ -142,8 +142,6 @@ struct SingleTrackQC { Configurable cfg_require_itsib_1st{"cfg_require_itsib_1st", true, "flag to require ITS ib 1st hit"}; Configurable cfg_min_its_cluster_size{"cfg_min_its_cluster_size", 0.f, "min ITS cluster size"}; Configurable cfg_max_its_cluster_size{"cfg_max_its_cluster_size", 16.f, "max ITS cluster size"}; - Configurable cfg_min_p_its_cluster_size{"cfg_min_p_its_cluster_size", 0.0, "min p to apply ITS cluster size cut"}; - Configurable cfg_max_p_its_cluster_size{"cfg_max_p_its_cluster_size", 0.0, "max p to apply ITS cluster size cut"}; Configurable cfg_min_rel_diff_pin{"cfg_min_rel_diff_pin", -1e+10, "min rel. diff. between pin and ppv"}; Configurable cfg_max_rel_diff_pin{"cfg_max_rel_diff_pin", +1e+10, "max rel. diff. between pin and ppv"}; @@ -171,6 +169,8 @@ struct SingleTrackQC { Configurable cfg_min_p_ITSNsigmaPr{"cfg_min_p_ITSNsigmaPr", 0.0, "min p for proton exclusion in ITS"}; Configurable cfg_max_p_ITSNsigmaPr{"cfg_max_p_ITSNsigmaPr", 0.0, "max p for proton exclusion in ITS"}; Configurable enableTTCA{"enableTTCA", true, "Flag to enable or disable TTCA"}; + Configurable includeITSsa{"includeITSsa", false, "Flag to enable ITSsa tracks"}; + Configurable cfg_max_pt_track_ITSsa{"cfg_max_pt_track_ITSsa", 0.15, "max pt for ITSsa tracks"}; // configuration for PID ML Configurable> onnxFileNames{"onnxFileNames", std::vector{"filename"}, "ONNX file names for each bin (if not from CCDB full path)"}; @@ -391,13 +391,14 @@ struct SingleTrackQC { fDielectronCut.SetChi2PerClusterTPC(0.0, dielectroncuts.cfg_max_chi2tpc); 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, dielectroncuts.cfg_min_p_its_cluster_size, dielectroncuts.cfg_max_p_its_cluster_size); + fDielectronCut.SetMeanClusterSizeITS(dielectroncuts.cfg_min_its_cluster_size, dielectroncuts.cfg_max_its_cluster_size); fDielectronCut.SetTrackMaxDcaXY(dielectroncuts.cfg_max_dcaxy); fDielectronCut.SetTrackMaxDcaZ(dielectroncuts.cfg_max_dcaz); fDielectronCut.RequireITSibAny(dielectroncuts.cfg_require_itsib_any); fDielectronCut.RequireITSib1st(dielectroncuts.cfg_require_itsib_1st); fDielectronCut.SetChi2TOF(0.0, dielectroncuts.cfg_max_chi2tof); fDielectronCut.SetRelDiffPin(dielectroncuts.cfg_min_rel_diff_pin, dielectroncuts.cfg_max_rel_diff_pin); + fDielectronCut.IncludeITSsa(dielectroncuts.includeITSsa, dielectroncuts.cfg_max_pt_track_ITSsa); // for eID fDielectronCut.SetPIDScheme(dielectroncuts.cfg_pid_scheme); diff --git a/PWGEM/Dilepton/Core/SingleTrackQCMC.h b/PWGEM/Dilepton/Core/SingleTrackQCMC.h index 4e33091a70f..5f63fb7acd7 100644 --- a/PWGEM/Dilepton/Core/SingleTrackQCMC.h +++ b/PWGEM/Dilepton/Core/SingleTrackQCMC.h @@ -149,8 +149,6 @@ struct SingleTrackQCMC { Configurable cfg_require_itsib_1st{"cfg_require_itsib_1st", true, "flag to require ITS ib 1st hit"}; Configurable cfg_min_its_cluster_size{"cfg_min_its_cluster_size", 0.f, "min ITS cluster size"}; Configurable cfg_max_its_cluster_size{"cfg_max_its_cluster_size", 16.f, "max ITS cluster size"}; - Configurable cfg_min_p_its_cluster_size{"cfg_min_p_its_cluster_size", 0.0, "min p to apply ITS cluster size cut"}; - Configurable cfg_max_p_its_cluster_size{"cfg_max_p_its_cluster_size", 0.0, "max p to apply ITS cluster size cut"}; Configurable cfg_min_rel_diff_pin{"cfg_min_rel_diff_pin", -1e+10, "min rel. diff. between pin and ppv"}; Configurable cfg_max_rel_diff_pin{"cfg_max_rel_diff_pin", +1e+10, "max rel. diff. between pin and ppv"}; @@ -178,6 +176,8 @@ struct SingleTrackQCMC { Configurable cfg_min_p_ITSNsigmaPr{"cfg_min_p_ITSNsigmaPr", 0.0, "min p for proton exclusion in ITS"}; Configurable cfg_max_p_ITSNsigmaPr{"cfg_max_p_ITSNsigmaPr", 0.0, "max p for proton exclusion in ITS"}; Configurable enableTTCA{"enableTTCA", true, "Flag to enable or disable TTCA"}; + Configurable includeITSsa{"includeITSsa", false, "Flag to enable ITSsa tracks"}; + Configurable cfg_max_pt_track_ITSsa{"cfg_max_pt_track_ITSsa", 0.15, "max pt for ITSsa tracks"}; // configuration for PID ML Configurable> onnxFileNames{"onnxFileNames", std::vector{"filename"}, "ONNX file names for each bin (if not from CCDB full path)"}; @@ -450,13 +450,14 @@ struct SingleTrackQCMC { fDielectronCut.SetChi2PerClusterTPC(0.0, dielectroncuts.cfg_max_chi2tpc); 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, dielectroncuts.cfg_min_p_its_cluster_size, dielectroncuts.cfg_max_p_its_cluster_size); + fDielectronCut.SetMeanClusterSizeITS(dielectroncuts.cfg_min_its_cluster_size, dielectroncuts.cfg_max_its_cluster_size); fDielectronCut.SetTrackMaxDcaXY(dielectroncuts.cfg_max_dcaxy); fDielectronCut.SetTrackMaxDcaZ(dielectroncuts.cfg_max_dcaz); fDielectronCut.RequireITSibAny(dielectroncuts.cfg_require_itsib_any); fDielectronCut.RequireITSib1st(dielectroncuts.cfg_require_itsib_1st); fDielectronCut.SetChi2TOF(0.0, dielectroncuts.cfg_max_chi2tof); fDielectronCut.SetRelDiffPin(dielectroncuts.cfg_min_rel_diff_pin, dielectroncuts.cfg_max_rel_diff_pin); + fDielectronCut.IncludeITSsa(dielectroncuts.includeITSsa, dielectroncuts.cfg_max_pt_track_ITSsa); // for eID fDielectronCut.SetPIDScheme(dielectroncuts.cfg_pid_scheme); diff --git a/PWGEM/Dilepton/TableProducer/skimmerPrimaryElectron.cxx b/PWGEM/Dilepton/TableProducer/skimmerPrimaryElectron.cxx index 3a88c448c15..39a5700db60 100644 --- a/PWGEM/Dilepton/TableProducer/skimmerPrimaryElectron.cxx +++ b/PWGEM/Dilepton/TableProducer/skimmerPrimaryElectron.cxx @@ -81,8 +81,7 @@ struct skimmerPrimaryElectron { Configurable min_ncluster_itsib{"min_ncluster_itsib", 1, "min ncluster itsib"}; Configurable maxchi2tpc{"maxchi2tpc", 5.0, "max. chi2/NclsTPC"}; Configurable maxchi2its{"maxchi2its", 6.0, "max. chi2/NclsITS"}; - Configurable minpt_itstpc{"minpt_itstpc", 0.1, "min pt for ITS-TPC track"}; - Configurable minpt_itssa{"minpt_itssa", 0.05, "min pt for ITSsa track"}; + Configurable minpt{"minpt", 0.15, "min pt for ITS-TPC track"}; Configurable maxeta{"maxeta", 0.9, "eta acceptance"}; Configurable dca_xy_max{"dca_xy_max", 1.0, "max DCAxy in cm"}; Configurable dca_z_max{"dca_z_max", 1.0, "max DCAz in cm"}; @@ -348,11 +347,11 @@ struct skimmerPrimaryElectron { return false; } - if ((track.hasITS() && track.hasTPC()) && track_par_cov_recalc.getPt() < minpt_itstpc) { + if ((track.hasITS() && track.hasTPC()) && track_par_cov_recalc.getPt() < minpt) { return false; } - if ((track.hasITS() && !track.hasTPC() && !track.hasTOF() && !track.hasTRD()) && (track_par_cov_recalc.getPt() < minpt_itssa || maxpt_itssa < track_par_cov_recalc.getPt())) { + if ((track.hasITS() && !track.hasTPC() && !track.hasTOF() && !track.hasTRD()) && maxpt_itssa < track_par_cov_recalc.getPt()) { return false; } @@ -558,7 +557,7 @@ struct skimmerPrimaryElectron { Preslice trackIndicesPerCollision = aod::track_association::collisionId; std::vector> stored_trackIds; - Filter trackFilter = o2::aod::track::pt > minpt_itssa&& nabs(o2::aod::track::eta) < maxeta&& o2::aod::track::itsChi2NCl < maxchi2its&& ncheckbit(aod::track::v001::detectorMap, (uint8_t)o2::aod::track::ITS) == true; + Filter trackFilter = o2::aod::track::pt > minpt&& nabs(o2::aod::track::eta) < maxeta&& o2::aod::track::itsChi2NCl < maxchi2its&& ncheckbit(aod::track::v001::detectorMap, (uint8_t)o2::aod::track::ITS) == true; using MyFilteredTracks = soa::Filtered; Partition posTracks = o2::aod::track::signed1Pt > 0.f; @@ -779,8 +778,7 @@ struct prefilterPrimaryElectron { Configurable fillQAHistogram{"fillQAHistogram", false, "flag to fill QA histograms"}; Configurable max_dcaxy{"max_dcaxy", 0.3, "DCAxy To PV for loose track sample"}; Configurable max_dcaz{"max_dcaz", 0.3, "DCAz To PV for loose track sample"}; - Configurable minpt_itstpc{"minpt_itstpc", 0.1, "min pt for ITS-TPC track"}; - Configurable minpt_itssa{"minpt_itssa", 0.05, "min pt for ITSsa track"}; + Configurable minpt{"minpt", 0.1, "min pt for ITS-TPC track"}; Configurable maxeta{"maxeta", 1.2, "eta acceptance for loose track sample"}; Configurable min_ncluster_tpc{"min_ncluster_tpc", 0, "min ncluster tpc"}; Configurable mincrossedrows{"mincrossedrows", 70, "min crossed rows"}; @@ -954,11 +952,11 @@ struct prefilterPrimaryElectron { return false; } - if ((track.hasITS() && track.hasTPC()) && track_par_cov_recalc.getPt() < minpt_itstpc) { + if ((track.hasITS() && track.hasTPC()) && track_par_cov_recalc.getPt() < minpt) { return false; } - if ((track.hasITS() && !track.hasTPC() && !track.hasTOF() && !track.hasTRD()) && (track_par_cov_recalc.getPt() < minpt_itssa || maxpt_itssa < track_par_cov_recalc.getPt())) { + if ((track.hasITS() && !track.hasTPC() && !track.hasTOF() && !track.hasTRD()) && maxpt_itssa < track_par_cov_recalc.getPt()) { return false; } @@ -1021,7 +1019,7 @@ struct prefilterPrimaryElectron { Preslice trackIndicesPerCollision = aod::track_association::collisionId; - Filter trackFilter = o2::aod::track::pt > minpt_itssa&& nabs(o2::aod::track::eta) < maxeta&& o2::aod::track::itsChi2NCl < maxchi2its&& ncheckbit(aod::track::v001::detectorMap, (uint8_t)o2::aod::track::ITS) == true; + Filter trackFilter = o2::aod::track::pt > minpt&& nabs(o2::aod::track::eta) < maxeta&& o2::aod::track::itsChi2NCl < maxchi2its&& ncheckbit(aod::track::v001::detectorMap, (uint8_t)o2::aod::track::ITS) == true; using MyFilteredTracks = soa::Filtered; Partition posTracks = o2::aod::track::signed1Pt > 0.f; Partition negTracks = o2::aod::track::signed1Pt < 0.f; diff --git a/PWGEM/Dilepton/Tasks/prefilterDielectron.cxx b/PWGEM/Dilepton/Tasks/prefilterDielectron.cxx index 5ac01703a06..45a00ae9889 100644 --- a/PWGEM/Dilepton/Tasks/prefilterDielectron.cxx +++ b/PWGEM/Dilepton/Tasks/prefilterDielectron.cxx @@ -127,8 +127,6 @@ struct prefilterDielectron { Configurable cfg_require_itsib_1st{"cfg_require_itsib_1st", false, "flag to require ITS ib 1st hit"}; Configurable cfg_min_its_cluster_size{"cfg_min_its_cluster_size", 0.f, "min ITS cluster size"}; Configurable cfg_max_its_cluster_size{"cfg_max_its_cluster_size", 16.f, "max ITS cluster size"}; - Configurable cfg_min_p_its_cluster_size{"cfg_min_p_its_cluster_size", 0.0, "min p to apply ITS cluster size cut"}; - Configurable cfg_max_p_its_cluster_size{"cfg_max_p_its_cluster_size", 0.0, "max p to apply ITS cluster size cut"}; Configurable cfg_min_rel_diff_pin{"cfg_min_rel_diff_pin", -1e+10, "min rel. diff. between pin and ppv"}; Configurable cfg_max_rel_diff_pin{"cfg_max_rel_diff_pin", +1e+10, "max rel. diff. between pin and ppv"}; @@ -146,6 +144,8 @@ struct prefilterDielectron { Configurable cfg_min_TOFNsigmaEl{"cfg_min_TOFNsigmaEl", -3.0, "min. TOF n sigma for electron inclusion"}; Configurable cfg_max_TOFNsigmaEl{"cfg_max_TOFNsigmaEl", +3.0, "max. TOF n sigma for electron inclusion"}; Configurable enableTTCA{"enableTTCA", true, "Flag to enable or disable TTCA"}; + Configurable includeITSsa{"includeITSsa", false, "Flag to enable ITSsa tracks"}; + Configurable cfg_max_pt_track_ITSsa{"cfg_max_pt_track_ITSsa", 0.15, "max pt for ITSsa tracks"}; // configuration for PID ML Configurable> onnxFileNames{"onnxFileNames", std::vector{"filename"}, "ONNX file names for each bin (if not from CCDB full path)"}; @@ -280,13 +280,14 @@ struct prefilterDielectron { fDielectronCut.SetChi2PerClusterTPC(0.0, dielectroncuts.cfg_max_chi2tpc); 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, dielectroncuts.cfg_min_p_its_cluster_size, dielectroncuts.cfg_max_p_its_cluster_size); + fDielectronCut.SetMeanClusterSizeITS(dielectroncuts.cfg_min_its_cluster_size, dielectroncuts.cfg_max_its_cluster_size); fDielectronCut.SetTrackMaxDcaXY(dielectroncuts.cfg_max_dcaxy); fDielectronCut.SetTrackMaxDcaZ(dielectroncuts.cfg_max_dcaz); fDielectronCut.RequireITSibAny(dielectroncuts.cfg_require_itsib_any); fDielectronCut.RequireITSib1st(dielectroncuts.cfg_require_itsib_1st); fDielectronCut.SetChi2TOF(0, dielectroncuts.cfg_max_chi2tof); fDielectronCut.SetRelDiffPin(dielectroncuts.cfg_min_rel_diff_pin, dielectroncuts.cfg_max_rel_diff_pin); + fDielectronCut.IncludeITSsa(dielectroncuts.includeITSsa, dielectroncuts.cfg_max_pt_track_ITSsa); // for eID fDielectronCut.SetPIDScheme(dielectroncuts.cfg_pid_scheme); diff --git a/PWGEM/Dilepton/Tasks/vpPairQC.cxx b/PWGEM/Dilepton/Tasks/vpPairQC.cxx index b9fe093e9f5..bb597751be4 100644 --- a/PWGEM/Dilepton/Tasks/vpPairQC.cxx +++ b/PWGEM/Dilepton/Tasks/vpPairQC.cxx @@ -14,30 +14,31 @@ // This code runs loop over ULS ee pars for virtual photon QC. // Please write to: daiki.sekihata@cern.ch -#include -#include -#include - -#include "TString.h" -#include "Math/Vector4D.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/ASoAHelpers.h" -#include "Common/Core/RecoDecay.h" - -#include "DetectorsBase/GeometryManager.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "CCDB/BasicCCDBManager.h" - -#include "PWGEM/Dilepton/DataModel/dileptonTables.h" #include "PWGEM/Dilepton/Core/DielectronCut.h" #include "PWGEM/Dilepton/Core/EMEventCut.h" +#include "PWGEM/Dilepton/DataModel/dileptonTables.h" #include "PWGEM/Dilepton/Utils/EMTrack.h" #include "PWGEM/Dilepton/Utils/EMTrackUtilities.h" #include "PWGEM/Dilepton/Utils/EventHistograms.h" -#include "PWGEM/Dilepton/Utils/PairUtilities.h" #include "PWGEM/Dilepton/Utils/MlResponseDielectronSingleTrack.h" +#include "PWGEM/Dilepton/Utils/PairUtilities.h" + +#include "Common/Core/RecoDecay.h" + +#include "CCDB/BasicCCDBManager.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "DataFormatsParameters/GRPObject.h" +#include "DetectorsBase/GeometryManager.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" + +#include "Math/Vector4D.h" +#include "TString.h" + +#include +#include +#include using namespace o2; using namespace o2::aod; @@ -123,7 +124,6 @@ struct vpPairQC { Configurable cfg_max_dcaz{"cfg_max_dcaz", 1.0, "max dca Z for single track in cm"}; Configurable cfg_min_its_cluster_size{"cfg_min_its_cluster_size", 0.f, "min ITS cluster size"}; Configurable cfg_max_its_cluster_size{"cfg_max_its_cluster_size", 16.f, "max ITS cluster size"}; - Configurable cfg_max_p_its_cluster_size{"cfg_max_p_its_cluster_size", 0.2, "max p to apply ITS cluster size cut"}; Configurable cfg_min_rel_diff_pin{"cfg_min_rel_diff_pin", -1e+10, "min rel. diff. between pin and ppv"}; Configurable cfg_max_rel_diff_pin{"cfg_max_rel_diff_pin", +1e+10, "max rel. diff. between pin and ppv"}; @@ -143,6 +143,8 @@ struct vpPairQC { Configurable cfg_min_pin_pirejTPC{"cfg_min_pin_pirejTPC", 0.5, "min. pin for pion rejection in TPC"}; Configurable cfg_max_pin_pirejTPC{"cfg_max_pin_pirejTPC", 0.5, "max. pin for pion rejection in TPC"}; Configurable enableTTCA{"enableTTCA", true, "Flag to enable or disable TTCA"}; + Configurable includeITSsa{"includeITSsa", false, "Flag to enable ITSsa tracks"}; + Configurable cfg_max_pt_track_ITSsa{"cfg_max_pt_track_ITSsa", 0.15, "max pt for ITSsa tracks"}; // configuration for PID ML Configurable> onnxFileNames{"onnxFileNames", std::vector{"filename"}, "ONNX file names for each bin (if not from CCDB full path)"}; @@ -323,11 +325,12 @@ struct vpPairQC { fDielectronCut.SetChi2PerClusterTPC(0.0, dielectroncuts.cfg_max_chi2tpc); 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, dielectroncuts.cfg_max_p_its_cluster_size); + fDielectronCut.SetMeanClusterSizeITS(dielectroncuts.cfg_min_its_cluster_size, dielectroncuts.cfg_max_its_cluster_size); fDielectronCut.SetTrackMaxDcaXY(dielectroncuts.cfg_max_dcaxy); fDielectronCut.SetTrackMaxDcaZ(dielectroncuts.cfg_max_dcaz); fDielectronCut.SetChi2TOF(0.0, dielectroncuts.cfg_max_chi2tof); fDielectronCut.SetRelDiffPin(dielectroncuts.cfg_min_rel_diff_pin, dielectroncuts.cfg_max_rel_diff_pin); + fDielectronCut.IncludeITSsa(dielectroncuts.includeITSsa, dielectroncuts.cfg_max_pt_track_ITSsa); // for eID fDielectronCut.SetPIDScheme(dielectroncuts.cfg_pid_scheme); diff --git a/PWGEM/Dilepton/Tasks/vpPairQCMC.cxx b/PWGEM/Dilepton/Tasks/vpPairQCMC.cxx index 58e47abad1d..0fa6fb85b75 100644 --- a/PWGEM/Dilepton/Tasks/vpPairQCMC.cxx +++ b/PWGEM/Dilepton/Tasks/vpPairQCMC.cxx @@ -14,30 +14,31 @@ // This code runs loop over ULS ee pars for virtual photon QC. // Please write to: daiki.sekihata@cern.ch -#include -#include -#include - -#include "TString.h" -#include "Math/Vector4D.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/ASoAHelpers.h" - -#include "DetectorsBase/GeometryManager.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "CCDB/BasicCCDBManager.h" -#include "Common/Core/RecoDecay.h" - -#include "PWGEM/Dilepton/DataModel/dileptonTables.h" #include "PWGEM/Dilepton/Core/DielectronCut.h" #include "PWGEM/Dilepton/Core/EMEventCut.h" -#include "PWGEM/Dilepton/Utils/MCUtilities.h" -#include "PWGEM/Dilepton/Utils/EventHistograms.h" +#include "PWGEM/Dilepton/DataModel/dileptonTables.h" #include "PWGEM/Dilepton/Utils/EMTrackUtilities.h" -#include "PWGEM/Dilepton/Utils/PairUtilities.h" +#include "PWGEM/Dilepton/Utils/EventHistograms.h" +#include "PWGEM/Dilepton/Utils/MCUtilities.h" #include "PWGEM/Dilepton/Utils/MlResponseDielectronSingleTrack.h" +#include "PWGEM/Dilepton/Utils/PairUtilities.h" + +#include "Common/Core/RecoDecay.h" + +#include "CCDB/BasicCCDBManager.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "DataFormatsParameters/GRPObject.h" +#include "DetectorsBase/GeometryManager.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" + +#include "Math/Vector4D.h" +#include "TString.h" + +#include +#include +#include using namespace o2; using namespace o2::aod; @@ -123,7 +124,6 @@ struct vpPairQCMC { Configurable cfg_max_dcaz{"cfg_max_dcaz", 1.0, "max dca Z for single track in cm"}; Configurable cfg_min_its_cluster_size{"cfg_min_its_cluster_size", 0.f, "min ITS cluster size"}; Configurable cfg_max_its_cluster_size{"cfg_max_its_cluster_size", 16.f, "max ITS cluster size"}; - Configurable cfg_max_p_its_cluster_size{"cfg_max_p_its_cluster_size", 0.2, "max p to apply ITS cluster size cut"}; Configurable cfg_min_rel_diff_pin{"cfg_min_rel_diff_pin", -1e+10, "min rel. diff. between pin and ppv"}; Configurable cfg_max_rel_diff_pin{"cfg_max_rel_diff_pin", +1e+10, "max rel. diff. between pin and ppv"}; @@ -143,6 +143,8 @@ struct vpPairQCMC { Configurable cfg_min_pin_pirejTPC{"cfg_min_pin_pirejTPC", 0.5, "min. pin for pion rejection in TPC"}; Configurable cfg_max_pin_pirejTPC{"cfg_max_pin_pirejTPC", 0.5, "max. pin for pion rejection in TPC"}; Configurable enableTTCA{"enableTTCA", true, "Flag to enable or disable TTCA"}; + Configurable includeITSsa{"includeITSsa", false, "Flag to enable ITSsa tracks"}; + Configurable cfg_max_pt_track_ITSsa{"cfg_max_pt_track_ITSsa", 0.15, "max pt for ITSsa tracks"}; // configuration for PID ML Configurable> onnxFileNames{"onnxFileNames", std::vector{"filename"}, "ONNX file names for each bin (if not from CCDB full path)"}; @@ -329,11 +331,12 @@ struct vpPairQCMC { fDielectronCut.SetChi2PerClusterTPC(0.0, dielectroncuts.cfg_max_chi2tpc); 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, dielectroncuts.cfg_max_p_its_cluster_size); + fDielectronCut.SetMeanClusterSizeITS(dielectroncuts.cfg_min_its_cluster_size, dielectroncuts.cfg_max_its_cluster_size); fDielectronCut.SetTrackMaxDcaXY(dielectroncuts.cfg_max_dcaxy); fDielectronCut.SetTrackMaxDcaZ(dielectroncuts.cfg_max_dcaz); fDielectronCut.SetChi2TOF(0.0, dielectroncuts.cfg_max_chi2tof); fDielectronCut.SetRelDiffPin(dielectroncuts.cfg_min_rel_diff_pin, dielectroncuts.cfg_max_rel_diff_pin); + fDielectronCut.IncludeITSsa(dielectroncuts.includeITSsa, dielectroncuts.cfg_max_pt_track_ITSsa); // for eID fDielectronCut.SetPIDScheme(dielectroncuts.cfg_pid_scheme); diff --git a/PWGEM/Dilepton/Utils/EventHistograms.h b/PWGEM/Dilepton/Utils/EventHistograms.h index 7c1d2fe687e..c7940350ac6 100644 --- a/PWGEM/Dilepton/Utils/EventHistograms.h +++ b/PWGEM/Dilepton/Utils/EventHistograms.h @@ -14,6 +14,9 @@ #ifndef PWGEM_DILEPTON_UTILS_EVENTHISTOGRAMS_H_ #define PWGEM_DILEPTON_UTILS_EVENTHISTOGRAMS_H_ + +#include "Framework/HistogramRegistry.h" + using namespace o2::framework; namespace o2::aod::pwgem::dilepton::utils::eventhistogram diff --git a/PWGEM/Dilepton/Utils/MCUtilities.h b/PWGEM/Dilepton/Utils/MCUtilities.h index c6c1aacfe04..dd12d2576f2 100644 --- a/PWGEM/Dilepton/Utils/MCUtilities.h +++ b/PWGEM/Dilepton/Utils/MCUtilities.h @@ -15,9 +15,12 @@ #ifndef PWGEM_DILEPTON_UTILS_MCUTILITIES_H_ #define PWGEM_DILEPTON_UTILS_MCUTILITIES_H_ +#include "Framework/AnalysisDataModel.h" +#include "Framework/Logger.h" + +#include #include #include -#include //_______________________________________________________________________ namespace o2::aod::pwgem::dilepton::utils::mcutil diff --git a/PWGEM/PhotonMeson/Core/DalitzEECut.cxx b/PWGEM/PhotonMeson/Core/DalitzEECut.cxx index 99ac9ee356a..df6418474a1 100644 --- a/PWGEM/PhotonMeson/Core/DalitzEECut.cxx +++ b/PWGEM/PhotonMeson/Core/DalitzEECut.cxx @@ -13,11 +13,12 @@ // Class for dilepton Cut // -#include -#include +#include "PWGEM/PhotonMeson/Core/DalitzEECut.h" #include "Framework/Logger.h" -#include "PWGEM/PhotonMeson/Core/DalitzEECut.h" + +#include +#include ClassImp(DalitzEECut); @@ -179,3 +180,9 @@ void DalitzEECut::SetPIDScheme(int scheme) mPIDScheme = scheme; LOG(info) << "DalitzEE Cut, PID scheme: " << static_cast(mPIDScheme); } +void DalitzEECut::IncludeITSsa(bool flag, float max) +{ + mIncludeITSsa = flag; + mMaxPtITSsa = max; + LOG(info) << "DalitzEE Cut, include ITSsa tracks: " << mIncludeITSsa << ", mMaxPtITSsa = " << mMaxPtITSsa; +} diff --git a/PWGEM/PhotonMeson/Core/DalitzEECut.h b/PWGEM/PhotonMeson/Core/DalitzEECut.h index 60dff1786d1..ee94b84c19c 100644 --- a/PWGEM/PhotonMeson/Core/DalitzEECut.h +++ b/PWGEM/PhotonMeson/Core/DalitzEECut.h @@ -16,22 +16,24 @@ #ifndef PWGEM_PHOTONMESON_CORE_DALITZEECUT_H_ #define PWGEM_PHOTONMESON_CORE_DALITZEECUT_H_ -#include -#include -#include -#include -#include -#include "TNamed.h" -#include "Math/Vector4D.h" +#include "PWGEM/Dilepton/Utils/EMTrackUtilities.h" +#include "PWGEM/Dilepton/Utils/PairUtilities.h" #include "Tools/ML/MlResponse.h" #include "Tools/ML/model.h" -#include "Framework/Logger.h" -#include "Framework/DataTypes.h" #include "CommonConstants/PhysicsConstants.h" -#include "PWGEM/Dilepton/Utils/PairUtilities.h" -#include "PWGEM/Dilepton/Utils/EMTrackUtilities.h" +#include "Framework/DataTypes.h" +#include "Framework/Logger.h" + +#include "Math/Vector4D.h" +#include "TNamed.h" + +#include +#include +#include +#include +#include using namespace o2::aod::pwgem::dilepton::utils::emtrackutil; @@ -62,7 +64,6 @@ class DalitzEECut : public TNamed kDCAz, kITSNCls, kITSChi2NDF, - kITSCluserSize, kNCuts }; static const char* mCutNames[static_cast(DalitzEECuts::kNCuts)]; @@ -116,7 +117,7 @@ class DalitzEECut : public TNamed template bool IsSelectedTrack(TTrack const& track, TCollision const& = 0) const { - if (!track.hasITS() || !track.hasTPC()) { // track has to be ITS-TPC matched track + if (!track.hasITS()) { return false; } @@ -143,9 +144,6 @@ class DalitzEECut : public TNamed if (!IsSelectedTrack(track, DalitzEECuts::kITSChi2NDF)) { return false; } - if (!IsSelectedTrack(track, DalitzEECuts::kITSCluserSize)) { - return false; - } if (mRequireITSibAny) { auto hits_ib = std::count_if(its_ib_any_Requirement.second.begin(), its_ib_any_Requirement.second.end(), [&](auto&& requiredLayer) { return track.itsClusterMap() & (1 << requiredLayer); }); @@ -161,28 +159,44 @@ class DalitzEECut : public TNamed } } - // TPC cuts - if (!IsSelectedTrack(track, DalitzEECuts::kTPCNCls)) { - return false; - } - if (!IsSelectedTrack(track, DalitzEECuts::kTPCCrossedRows)) { + if (!mIncludeITSsa && (!track.hasITS() || !track.hasTPC())) { // track has to be ITS-TPC matched track return false; } - if (!IsSelectedTrack(track, DalitzEECuts::kTPCCrossedRowsOverNCls)) { - return false; - } - if (!IsSelectedTrack(track, DalitzEECuts::kTPCFracSharedClusters)) { + + if ((track.hasITS() && !track.hasTPC() && !track.hasTRD() && !track.hasTOF()) && track.pt() > mMaxPtITSsa) { // ITSsa return false; } - if (!IsSelectedTrack(track, DalitzEECuts::kTPCChi2NDF)) { - return false; + + // TPC cuts + if (track.hasTPC()) { + if (!IsSelectedTrack(track, DalitzEECuts::kTPCNCls)) { + return false; + } + if (!IsSelectedTrack(track, DalitzEECuts::kTPCCrossedRows)) { + return false; + } + if (!IsSelectedTrack(track, DalitzEECuts::kTPCCrossedRowsOverNCls)) { + return false; + } + if (!IsSelectedTrack(track, DalitzEECuts::kTPCFracSharedClusters)) { + return false; + } + if (!IsSelectedTrack(track, DalitzEECuts::kTPCChi2NDF)) { + return false; + } } // PID cuts - if (!PassPID(track)) { - return false; + if (track.hasITS() && !track.hasTPC() && !track.hasTRD() && !track.hasTOF()) { // ITSsa + float meanClusterSizeITS = track.meanClusterSizeITS() * std::cos(std::atan(track.tgl())); + if (meanClusterSizeITS < mMinMeanClusterSizeITS || mMaxMeanClusterSizeITS < meanClusterSizeITS) { + return false; + } + } else { + if (!PassPID(track)) { + return false; + } } - return true; } @@ -261,9 +275,6 @@ class DalitzEECut : public TNamed case DalitzEECuts::kITSChi2NDF: return mMinChi2PerClusterITS < track.itsChi2NCl() && track.itsChi2NCl() < mMaxChi2PerClusterITS; - case DalitzEECuts::kITSCluserSize: - return mMinMeanClusterSizeITS < track.meanClusterSizeITS() * std::cos(std::atan(track.tgl())) && track.meanClusterSizeITS() * std::cos(std::atan(track.tgl())) < mMaxMeanClusterSizeITS; - default: return false; } @@ -301,6 +312,7 @@ class DalitzEECut : public TNamed void SetMaxDcaXYPtDep(std::function ptDepCut); void ApplyPrefilter(bool flag); void ApplyPhiV(bool flag); + void IncludeITSsa(bool flag, float maxpt); // Getters bool IsPhotonConversionSelected() const { return mSelectPC; } @@ -338,8 +350,10 @@ class DalitzEECut : public TNamed float mMaxDcaZ{1.0f}; // max dca in z direction std::function mMaxDcaXYPtDep{}; // max dca in xy plane as function of pT bool mApplyPhiV{true}; - float mMinMeanClusterSizeITS{-1e10f}, mMaxMeanClusterSizeITS{1e10f}; // max x cos(Lmabda) + float mMinMeanClusterSizeITS{-1e10f}, mMaxMeanClusterSizeITS{1e10f}; // x cos(lmabda) float mMinChi2TOF{-1e10f}, mMaxChi2TOF{1e10f}; // max tof chi2 per + bool mIncludeITSsa{false}; + float mMaxPtITSsa{0.15}; // pid cuts int mPIDScheme{-1}; diff --git a/PWGEM/PhotonMeson/Core/Pi0EtaToGammaGamma.h b/PWGEM/PhotonMeson/Core/Pi0EtaToGammaGamma.h index e4bc8414601..4b37b306f95 100644 --- a/PWGEM/PhotonMeson/Core/Pi0EtaToGammaGamma.h +++ b/PWGEM/PhotonMeson/Core/Pi0EtaToGammaGamma.h @@ -19,46 +19,47 @@ #ifndef PWGEM_PHOTONMESON_CORE_PI0ETATOGAMMAGAMMA_H_ #define PWGEM_PHOTONMESON_CORE_PI0ETATOGAMMAGAMMA_H_ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "TString.h" -#include "Math/Vector4D.h" -#include "Math/Vector3D.h" -#include "Math/LorentzRotation.h" -#include "Math/Rotation3D.h" -#include "Math/AxisAngle.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.h" - -#include "DetectorsBase/GeometryManager.h" -#include "EMCALBase/Geometry.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "CCDB/BasicCCDBManager.h" - -#include "Common/Core/RecoDecay.h" -#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" -#include "PWGEM/PhotonMeson/Core/V0PhotonCut.h" +#include "PWGEM/Dilepton/Utils/EMTrack.h" +#include "PWGEM/Dilepton/Utils/EMTrackUtilities.h" +#include "PWGEM/Dilepton/Utils/EventMixingHandler.h" #include "PWGEM/PhotonMeson/Core/DalitzEECut.h" -#include "PWGEM/PhotonMeson/Core/PHOSPhotonCut.h" #include "PWGEM/PhotonMeson/Core/EMCPhotonCut.h" #include "PWGEM/PhotonMeson/Core/EMPhotonEventCut.h" -#include "PWGEM/PhotonMeson/Utils/PairUtilities.h" -#include "PWGEM/Dilepton/Utils/EMTrack.h" -#include "PWGEM/Dilepton/Utils/EventMixingHandler.h" +#include "PWGEM/PhotonMeson/Core/PHOSPhotonCut.h" +#include "PWGEM/PhotonMeson/Core/V0PhotonCut.h" +#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" #include "PWGEM/PhotonMeson/Utils/EventHistograms.h" #include "PWGEM/PhotonMeson/Utils/NMHistograms.h" -#include "PWGEM/Dilepton/Utils/EMTrackUtilities.h" +#include "PWGEM/PhotonMeson/Utils/PairUtilities.h" + +#include "Common/Core/RecoDecay.h" + +#include "CCDB/BasicCCDBManager.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "DataFormatsParameters/GRPObject.h" +#include "DetectorsBase/GeometryManager.h" +#include "EMCALBase/Geometry.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" + +#include "Math/AxisAngle.h" +#include "Math/LorentzRotation.h" +#include "Math/Rotation3D.h" +#include "Math/Vector3D.h" +#include "Math/Vector4D.h" +#include "TString.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include using namespace o2; using namespace o2::aod; @@ -182,6 +183,8 @@ struct Pi0EtaToGammaGamma { Configurable cfg_max_dca3dsigma_track{"cfg_max_dca3dsigma_track", 1.5, "max DCA 3D in sigma"}; Configurable cfg_max_frac_shared_clusters_tpc{"cfg_max_frac_shared_clusters_tpc", 999.f, "max fraction of shared clusters in TPC"}; Configurable cfg_apply_cuts_from_prefilter_derived{"cfg_apply_cuts_from_prefilter_derived", false, "flag to apply prefilter to electron"}; + Configurable includeITSsa{"includeITSsa", false, "Flag to enable ITSsa tracks"}; + Configurable cfg_max_pt_track_ITSsa{"cfg_max_pt_track_ITSsa", 0.15, "max pt for ITSsa tracks"}; Configurable cfg_pid_scheme{"cfg_pid_scheme", static_cast(DalitzEECut::PIDSchemes::kTOFif), "pid scheme [kTOFif : 0, kTPConly : 1]"}; Configurable cfg_min_TPCNsigmaEl{"cfg_min_TPCNsigmaEl", -2.0, "min. TPC n sigma for electron inclusion"}; @@ -400,6 +403,7 @@ struct Pi0EtaToGammaGamma { fDileptonCut.SetMaxDcaXY(dileptoncuts.cfg_max_dcaxy); fDileptonCut.SetMaxDcaZ(dileptoncuts.cfg_max_dcaz); fDileptonCut.SetTrackDca3DRange(0.f, dileptoncuts.cfg_max_dca3dsigma_track); // in sigma + fDileptonCut.IncludeITSsa(dileptoncuts.includeITSsa, dileptoncuts.cfg_max_pt_track_ITSsa); // for eID fDileptonCut.SetPIDScheme(dileptoncuts.cfg_pid_scheme); diff --git a/PWGEM/PhotonMeson/Core/Pi0EtaToGammaGammaMC.h b/PWGEM/PhotonMeson/Core/Pi0EtaToGammaGammaMC.h index 87e2f7b04d4..bb83f7aa0ea 100644 --- a/PWGEM/PhotonMeson/Core/Pi0EtaToGammaGammaMC.h +++ b/PWGEM/PhotonMeson/Core/Pi0EtaToGammaGammaMC.h @@ -17,35 +17,36 @@ #ifndef PWGEM_PHOTONMESON_CORE_PI0ETATOGAMMAGAMMAMC_H_ #define PWGEM_PHOTONMESON_CORE_PI0ETATOGAMMAGAMMAMC_H_ -#include -#include -#include +#include "PWGEM/Dilepton/Utils/MCUtilities.h" +#include "PWGEM/PhotonMeson/Core/DalitzEECut.h" +#include "PWGEM/PhotonMeson/Core/EMCPhotonCut.h" +#include "PWGEM/PhotonMeson/Core/EMPhotonEventCut.h" +#include "PWGEM/PhotonMeson/Core/PHOSPhotonCut.h" +#include "PWGEM/PhotonMeson/Core/V0PhotonCut.h" +#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" +#include "PWGEM/PhotonMeson/Utils/EventHistograms.h" +#include "PWGEM/PhotonMeson/Utils/MCUtilities.h" +#include "PWGEM/PhotonMeson/Utils/NMHistograms.h" +#include "PWGEM/PhotonMeson/Utils/PairUtilities.h" -#include "TF1.h" -#include "TString.h" -#include "Math/Vector4D.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.h" +#include "Common/Core/RecoDecay.h" -#include "DetectorsBase/GeometryManager.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DataFormatsParameters/GRPMagField.h" #include "CCDB/BasicCCDBManager.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "DataFormatsParameters/GRPObject.h" +#include "DetectorsBase/GeometryManager.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" -#include "Common/Core/RecoDecay.h" -#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" -#include "PWGEM/PhotonMeson/Utils/PairUtilities.h" -#include "PWGEM/PhotonMeson/Utils/MCUtilities.h" -#include "PWGEM/PhotonMeson/Utils/EventHistograms.h" -#include "PWGEM/PhotonMeson/Utils/NMHistograms.h" -#include "PWGEM/PhotonMeson/Core/V0PhotonCut.h" -#include "PWGEM/PhotonMeson/Core/DalitzEECut.h" -#include "PWGEM/PhotonMeson/Core/PHOSPhotonCut.h" -#include "PWGEM/PhotonMeson/Core/EMCPhotonCut.h" -#include "PWGEM/PhotonMeson/Core/EMPhotonEventCut.h" -#include "PWGEM/Dilepton/Utils/MCUtilities.h" +#include "Math/Vector4D.h" +#include "TF1.h" +#include "TString.h" + +#include +#include +#include using namespace o2; using namespace o2::aod; @@ -168,6 +169,8 @@ struct Pi0EtaToGammaGammaMC { Configurable cfg_max_dcaz{"cfg_max_dcaz", 0.05, "max dca Z for single track in cm"}; Configurable cfg_max_dca3dsigma_track{"cfg_max_dca3dsigma_track", 1.5, "max DCA 3D in sigma"}; Configurable cfg_apply_cuts_from_prefilter_derived{"cfg_apply_cuts_from_prefilter_derived", false, "flag to apply prefilter to electron"}; + Configurable includeITSsa{"includeITSsa", false, "Flag to enable ITSsa tracks"}; + Configurable cfg_max_pt_track_ITSsa{"cfg_max_pt_track_ITSsa", 0.15, "max pt for ITSsa tracks"}; Configurable cfg_pid_scheme{"cfg_pid_scheme", static_cast(DalitzEECut::PIDSchemes::kTOFif), "pid scheme [kTOFif : 0, kTPConly : 1]"}; Configurable cfg_min_TPCNsigmaEl{"cfg_min_TPCNsigmaEl", -2.0, "min. TPC n sigma for electron inclusion"}; @@ -359,6 +362,7 @@ struct Pi0EtaToGammaGammaMC { fDileptonCut.SetMaxDcaXY(dileptoncuts.cfg_max_dcaxy); fDileptonCut.SetMaxDcaZ(dileptoncuts.cfg_max_dcaz); fDileptonCut.SetTrackDca3DRange(0.f, dileptoncuts.cfg_max_dca3dsigma_track); // in sigma + fDileptonCut.IncludeITSsa(dileptoncuts.includeITSsa, dileptoncuts.cfg_max_pt_track_ITSsa); // for eID fDileptonCut.SetPIDScheme(dileptoncuts.cfg_pid_scheme); diff --git a/PWGEM/PhotonMeson/TableProducer/skimmerPrimaryElectronFromDalitzEE.cxx b/PWGEM/PhotonMeson/TableProducer/skimmerPrimaryElectronFromDalitzEE.cxx index 91b22a88100..986bfba6bd6 100644 --- a/PWGEM/PhotonMeson/TableProducer/skimmerPrimaryElectronFromDalitzEE.cxx +++ b/PWGEM/PhotonMeson/TableProducer/skimmerPrimaryElectronFromDalitzEE.cxx @@ -70,8 +70,7 @@ struct skimmerPrimaryElectronFromDalitzEE { Configurable min_ncluster_itsib{"min_ncluster_itsib", 1, "min ncluster itsib"}; Configurable maxchi2tpc{"maxchi2tpc", 5.0, "max. chi2/NclsTPC"}; Configurable maxchi2its{"maxchi2its", 6.0, "max. chi2/NclsITS"}; - Configurable minpt_itstpc{"minpt_itstpc", 0.05, "min pt for ITS-TPC track"}; - Configurable minpt_itssa{"minpt_itssa", 0.05, "min pt for ITSsa track"}; + Configurable minpt{"minpt", 0.05, "min pt for ITS-TPC track"}; Configurable maxeta{"maxeta", 2.0, "max eta acceptance"}; Configurable dca_xy_max{"dca_xy_max", 1, "max DCAxy in cm"}; Configurable dca_z_max{"dca_z_max", 1, "max DCAz in cm"}; @@ -259,10 +258,10 @@ struct skimmerPrimaryElectronFromDalitzEE { if (std::fabs(track.eta()) > maxeta) { return false; } - if ((track.hasITS() && track.hasTPC()) && track.pt() < minpt_itstpc) { + if ((track.hasITS() && track.hasTPC()) && track.pt() < minpt) { return false; } - if ((track.hasITS() && !track.hasTPC() && !track.hasTRD() && !track.hasTOF()) && (track.pt() < minpt_itssa || maxpt_itssa < track.pt())) { + if ((track.hasITS() && !track.hasTPC() && !track.hasTRD() && !track.hasTOF()) && maxpt_itssa < track.pt()) { return false; } @@ -422,7 +421,7 @@ struct skimmerPrimaryElectronFromDalitzEE { } std::vector> stored_trackIds; - Filter trackFilter = o2::aod::track::pt > minpt_itssa&& nabs(o2::aod::track::eta) < maxeta&& o2::aod::track::itsChi2NCl < maxchi2its&& ncheckbit(aod::track::v001::detectorMap, (uint8_t)o2::aod::track::ITS) == true && nabs(o2::aod::track::dcaXY) < dca_xy_max&& nabs(o2::aod::track::dcaZ) < dca_z_max; + Filter trackFilter = o2::aod::track::pt > minpt&& nabs(o2::aod::track::eta) < maxeta&& o2::aod::track::itsChi2NCl < maxchi2its&& ncheckbit(aod::track::v001::detectorMap, (uint8_t)o2::aod::track::ITS) == true && nabs(o2::aod::track::dcaXY) < dca_xy_max&& nabs(o2::aod::track::dcaZ) < dca_z_max; using MyFilteredTracks = soa::Filtered; Partition posTracks = o2::aod::track::signed1Pt > 0.f; Partition negTracks = o2::aod::track::signed1Pt < 0.f; diff --git a/PWGEM/PhotonMeson/Tasks/dalitzEEQC.cxx b/PWGEM/PhotonMeson/Tasks/dalitzEEQC.cxx index 74c97448baf..184af6ab659 100644 --- a/PWGEM/PhotonMeson/Tasks/dalitzEEQC.cxx +++ b/PWGEM/PhotonMeson/Tasks/dalitzEEQC.cxx @@ -14,26 +14,27 @@ // This code runs loop over dalitz ee table for dalitz QC. // Please write to: daiki.sekihata@cern.ch -#include -#include +#include "PWGEM/Dilepton/Utils/PairUtilities.h" +#include "PWGEM/PhotonMeson/Core/DalitzEECut.h" +#include "PWGEM/PhotonMeson/Core/EMPhotonEventCut.h" +#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" +#include "PWGEM/PhotonMeson/Utils/EventHistograms.h" -#include "TString.h" -#include "Math/Vector4D.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/ASoAHelpers.h" #include "Common/Core/RecoDecay.h" -#include "DetectorsBase/GeometryManager.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DataFormatsParameters/GRPMagField.h" #include "CCDB/BasicCCDBManager.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "DataFormatsParameters/GRPObject.h" +#include "DetectorsBase/GeometryManager.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" -#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" -#include "PWGEM/PhotonMeson/Core/DalitzEECut.h" -#include "PWGEM/PhotonMeson/Core/EMPhotonEventCut.h" -#include "PWGEM/Dilepton/Utils/PairUtilities.h" -#include "PWGEM/PhotonMeson/Utils/EventHistograms.h" +#include "Math/Vector4D.h" +#include "TString.h" + +#include +#include using namespace o2; using namespace o2::aod; @@ -98,6 +99,8 @@ struct DalitzEEQC { Configurable cfg_max_dcaxy{"cfg_max_dcaxy", 1.0, "max dca XY for single track in cm"}; Configurable cfg_max_dcaz{"cfg_max_dcaz", 1.0, "max dca Z for single track in cm"}; Configurable cfg_max_dca3dsigma_track{"cfg_max_dca3dsigma_track", 1.5, "max DCA 3D in sigma"}; + Configurable includeITSsa{"includeITSsa", false, "Flag to enable ITSsa tracks"}; + Configurable cfg_max_pt_track_ITSsa{"cfg_max_pt_track_ITSsa", 0.15, "max pt for ITSsa tracks"}; Configurable cfg_pid_scheme{"cfg_pid_scheme", static_cast(DalitzEECut::PIDSchemes::kTOFif), "pid scheme [kTOFif : 0, kTPConly : 1]"}; Configurable cfg_min_TPCNsigmaEl{"cfg_min_TPCNsigmaEl", -2.0, "min. TPC n sigma for electron inclusion"}; @@ -250,6 +253,7 @@ struct DalitzEEQC { fDileptonCut.SetMaxDcaXY(dileptoncuts.cfg_max_dcaxy); fDileptonCut.SetMaxDcaZ(dileptoncuts.cfg_max_dcaz); fDileptonCut.SetTrackDca3DRange(0.f, dileptoncuts.cfg_max_dca3dsigma_track); // in sigma + fDileptonCut.IncludeITSsa(dileptoncuts.includeITSsa, dileptoncuts.cfg_max_pt_track_ITSsa); // for eID fDileptonCut.SetPIDScheme(dileptoncuts.cfg_pid_scheme); diff --git a/PWGEM/PhotonMeson/Tasks/dalitzEEQCMC.cxx b/PWGEM/PhotonMeson/Tasks/dalitzEEQCMC.cxx index 4e2e33c2d18..790ee738991 100644 --- a/PWGEM/PhotonMeson/Tasks/dalitzEEQCMC.cxx +++ b/PWGEM/PhotonMeson/Tasks/dalitzEEQCMC.cxx @@ -14,28 +14,29 @@ // This code runs loop over dalitz ee table for dalitz QC. // Please write to: daiki.sekihata@cern.ch -#include -#include +#include "PWGEM/Dilepton/Utils/MCUtilities.h" +#include "PWGEM/Dilepton/Utils/PairUtilities.h" +#include "PWGEM/PhotonMeson/Core/DalitzEECut.h" +#include "PWGEM/PhotonMeson/Core/EMPhotonEventCut.h" +#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" +#include "PWGEM/PhotonMeson/Utils/EventHistograms.h" +#include "PWGEM/PhotonMeson/Utils/MCUtilities.h" -#include "TString.h" -#include "Math/Vector4D.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/ASoAHelpers.h" +#include "Common/Core/RecoDecay.h" -#include "DetectorsBase/GeometryManager.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DataFormatsParameters/GRPMagField.h" #include "CCDB/BasicCCDBManager.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "DataFormatsParameters/GRPObject.h" +#include "DetectorsBase/GeometryManager.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" -#include "Common/Core/RecoDecay.h" -#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" -#include "PWGEM/PhotonMeson/Core/DalitzEECut.h" -#include "PWGEM/PhotonMeson/Core/EMPhotonEventCut.h" -#include "PWGEM/PhotonMeson/Utils/MCUtilities.h" -#include "PWGEM/Dilepton/Utils/MCUtilities.h" -#include "PWGEM/PhotonMeson/Utils/EventHistograms.h" -#include "PWGEM/Dilepton/Utils/PairUtilities.h" +#include "Math/Vector4D.h" +#include "TString.h" + +#include +#include using namespace o2; using namespace o2::aod; @@ -103,6 +104,8 @@ struct DalitzEEQCMC { Configurable cfg_max_dcaxy{"cfg_max_dcaxy", 1.0, "max dca XY for single track in cm"}; Configurable cfg_max_dcaz{"cfg_max_dcaz", 1.0, "max dca Z for single track in cm"}; Configurable cfg_max_dca3dsigma_track{"cfg_max_dca3dsigma_track", 1.5, "max DCA 3D in sigma"}; + Configurable includeITSsa{"includeITSsa", false, "Flag to enable ITSsa tracks"}; + Configurable cfg_max_pt_track_ITSsa{"cfg_max_pt_track_ITSsa", 0.15, "max pt for ITSsa tracks"}; Configurable cfg_pid_scheme{"cfg_pid_scheme", static_cast(DalitzEECut::PIDSchemes::kTOFif), "pid scheme [kTOFif : 0, kTPConly : 1]"}; Configurable cfg_min_TPCNsigmaEl{"cfg_min_TPCNsigmaEl", -2.0, "min. TPC n sigma for electron inclusion"}; @@ -282,6 +285,7 @@ struct DalitzEEQCMC { fDileptonCut.SetMaxDcaXY(dileptoncuts.cfg_max_dcaxy); fDileptonCut.SetMaxDcaZ(dileptoncuts.cfg_max_dcaz); fDileptonCut.SetTrackDca3DRange(0.f, dileptoncuts.cfg_max_dca3dsigma_track); // in sigma + fDileptonCut.IncludeITSsa(dileptoncuts.includeITSsa, dileptoncuts.cfg_max_pt_track_ITSsa); // for eID fDileptonCut.SetPIDScheme(dileptoncuts.cfg_pid_scheme); diff --git a/PWGEM/PhotonMeson/Utils/EventHistograms.h b/PWGEM/PhotonMeson/Utils/EventHistograms.h index 49d8ff05cdb..779f2701888 100644 --- a/PWGEM/PhotonMeson/Utils/EventHistograms.h +++ b/PWGEM/PhotonMeson/Utils/EventHistograms.h @@ -14,6 +14,9 @@ #ifndef PWGEM_PHOTONMESON_UTILS_EVENTHISTOGRAMS_H_ #define PWGEM_PHOTONMESON_UTILS_EVENTHISTOGRAMS_H_ + +#include "Framework/HistogramRegistry.h" + using namespace o2::framework; namespace o2::aod::pwgem::photonmeson::utils::eventhistogram diff --git a/PWGEM/PhotonMeson/Utils/MCUtilities.h b/PWGEM/PhotonMeson/Utils/MCUtilities.h index 19432c66475..c72a8a0b06d 100644 --- a/PWGEM/PhotonMeson/Utils/MCUtilities.h +++ b/PWGEM/PhotonMeson/Utils/MCUtilities.h @@ -15,9 +15,11 @@ #ifndef PWGEM_PHOTONMESON_UTILS_MCUTILITIES_H_ #define PWGEM_PHOTONMESON_UTILS_MCUTILITIES_H_ -#include -#include #include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" + +#include +#include //_______________________________________________________________________ namespace o2::aod::pwgem::photonmeson::utils::mcutil diff --git a/PWGEM/PhotonMeson/Utils/NMHistograms.h b/PWGEM/PhotonMeson/Utils/NMHistograms.h index 88df03a3aed..8915c6624b5 100644 --- a/PWGEM/PhotonMeson/Utils/NMHistograms.h +++ b/PWGEM/PhotonMeson/Utils/NMHistograms.h @@ -15,10 +15,14 @@ #ifndef PWGEM_PHOTONMESON_UTILS_NMHISTOGRAMS_H_ #define PWGEM_PHOTONMESON_UTILS_NMHISTOGRAMS_H_ -#include -#include "TF1.h" -#include "PWGEM/PhotonMeson/Utils/PairUtilities.h" #include "PWGEM/PhotonMeson/Utils/MCUtilities.h" +#include "PWGEM/PhotonMeson/Utils/PairUtilities.h" + +#include "Framework/HistogramRegistry.h" + +#include "TF1.h" + +#include using namespace o2::framework; using namespace o2::aod::pwgem::photonmeson::utils::mcutil; From b102b1699ae28454a99040a460ac5cd9d482141b Mon Sep 17 00:00:00 2001 From: prottayCMT <61418725+prottayCMT@users.noreply.github.com> Date: Sat, 21 Jun 2025 22:26:56 +0200 Subject: [PATCH 173/871] [PWGLF] added K0s measurement in derived data as a closure test and hist to monitor no. of events after each selections for Calib (#11670) Co-authored-by: Prottay Das --- PWGLF/TableProducer/Common/spvector.cxx | 68 ++-- PWGLF/Tasks/Strangeness/lambdapolsp.cxx | 435 ++++++++++++++---------- 2 files changed, 308 insertions(+), 195 deletions(-) diff --git a/PWGLF/TableProducer/Common/spvector.cxx b/PWGLF/TableProducer/Common/spvector.cxx index 99a54d63c64..e5940962e1f 100644 --- a/PWGLF/TableProducer/Common/spvector.cxx +++ b/PWGLF/TableProducer/Common/spvector.cxx @@ -13,54 +13,57 @@ // \email: prottay.das@cern.ch // C++/ROOT includes. -#include -#include -#include -#include +#include "Math/Vector4D.h" +#include "TF1.h" +#include "TRandom3.h" #include +#include #include + #include +#include #include #include -#include "Math/Vector4D.h" -#include "TRandom3.h" -#include "TF1.h" +#include +#include // o2Physics includes. -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/StepTHn.h" -#include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "CommonConstants/PhysicsConstants.h" +#include "PWGLF/DataModel/SPCalibrationTables.h" + +#include "Common/CCDB/ctpRateFetcher.h" +#include "Common/Core/EventPlaneHelper.h" +#include "Common/Core/PID/PIDTOF.h" #include "Common/Core/TrackSelection.h" -#include "Common/DataModel/FT0Corrected.h" -#include "FT0Base/Geometry.h" -#include "FV0Base/Geometry.h" #include "Common/Core/trackUtilities.h" #include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/FT0Corrected.h" +#include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/PIDResponse.h" -#include "Common/Core/PID/PIDTOF.h" -#include "Common/TableProducer/PID/pidTOFBase.h" -#include "Common/Core/EventPlaneHelper.h" #include "Common/DataModel/Qvectors.h" -#include "Common/CCDB/ctpRateFetcher.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "Common/TableProducer/PID/pidTOFBase.h" + +#include "CommonConstants/PhysicsConstants.h" #include "DataFormatsParameters/GRPMagField.h" #include "DataFormatsParameters/GRPObject.h" #include "DataFormatsTPC/BetheBlochAleph.h" #include "DetectorsBase/GeometryManager.h" #include "DetectorsBase/Propagator.h" +#include "FT0Base/Geometry.h" +#include "FV0Base/Geometry.h" #include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/StepTHn.h" +#include "Framework/runDataProcessing.h" #include "ReconstructionDataFormats/Track.h" -#include "PWGLF/DataModel/SPCalibrationTables.h" // #include "SPCalibrationTableswrite.h" // o2 includes. -#include "CCDB/CcdbApi.h" #include "CCDB/BasicCCDBManager.h" +#include "CCDB/CcdbApi.h" #include "DetectorsCommonDataFormats/AlignParam.h" using namespace o2; @@ -227,6 +230,7 @@ struct spvector { AxisSpec basisAxis = {2, 0, 2, "basis"}; AxisSpec VxyAxis = {2, 0, 2, "Vxy"}; + histos.add("hEvtSelInfo", "hEvtSelInfo", kTH1F, {{10, 0, 10.0}}); histos.add("hCentrality", "hCentrality", kTH1F, {{centfineAxis}}); histos.add("Vz", "Vz", kTH1F, {vzfineAxis}); histos.add("hpQxZDCAC", "hpQxZDCAC", kTProfile, {centfineAxis}); @@ -410,6 +414,7 @@ struct spvector { void process(MyCollisions::iterator const& collision, aod::FT0s const& /*ft0s*/, aod::FV0As const& /*fv0s*/, BCsRun3 const& bcs, aod::Zdcs const&) { + histos.fill(HIST("hEvtSelInfo"), 0.5); auto centrality = collision.centFT0C(); bool triggerevent = false; @@ -439,6 +444,8 @@ struct spvector { return; } + histos.fill(HIST("hEvtSelInfo"), 1.5); + auto zdc = bc.zdc(); auto zncEnergy = zdc.energySectorZNC(); auto znaEnergy = zdc.energySectorZNA(); @@ -451,35 +458,47 @@ struct spvector { return; } + histos.fill(HIST("hEvtSelInfo"), 2.5); + if (znaEnergy[0] <= 0.0 || znaEnergy[1] <= 0.0 || znaEnergy[2] <= 0.0 || znaEnergy[3] <= 0.0) { triggerevent = false; spcalibrationtable(triggerevent, currentRunNumber, centrality, vx, vy, vz, znaEnergycommon, zncEnergycommon, znaEnergy[0], znaEnergy[1], znaEnergy[2], znaEnergy[3], zncEnergy[0], zncEnergy[1], zncEnergy[2], zncEnergy[3], qxZDCA, qxZDCC, qyZDCA, qyZDCC, psiZDCC, psiZDCA); 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; spcalibrationtable(triggerevent, currentRunNumber, centrality, vx, vy, vz, znaEnergycommon, zncEnergycommon, znaEnergy[0], znaEnergy[1], znaEnergy[2], znaEnergy[3], zncEnergy[0], zncEnergy[1], zncEnergy[2], zncEnergy[3], qxZDCA, qxZDCC, qyZDCA, qyZDCC, psiZDCC, psiZDCA); return; } + histos.fill(HIST("hEvtSelInfo"), 4.5); + if (rctCut.requireRCTFlagChecker && !rctChecker(collision)) { triggerevent = false; spcalibrationtable(triggerevent, currentRunNumber, centrality, vx, vy, vz, znaEnergycommon, zncEnergycommon, znaEnergy[0], znaEnergy[1], znaEnergy[2], znaEnergy[3], zncEnergy[0], zncEnergy[1], zncEnergy[2], zncEnergy[3], qxZDCA, qxZDCC, qyZDCA, qyZDCC, psiZDCC, psiZDCA); return; } + histos.fill(HIST("hEvtSelInfo"), 5.5); + if (additionalEvSel && (!collision.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV))) { triggerevent = false; spcalibrationtable(triggerevent, currentRunNumber, centrality, vx, vy, vz, znaEnergycommon, zncEnergycommon, znaEnergy[0], znaEnergy[1], znaEnergy[2], znaEnergy[3], zncEnergy[0], zncEnergy[1], zncEnergy[2], zncEnergy[3], qxZDCA, qxZDCC, qyZDCA, qyZDCC, psiZDCC, psiZDCA); return; } + histos.fill(HIST("hEvtSelInfo"), 6.5); + if (collision.sel8() && centrality > cfgCutCentralityMin && centrality < cfgCutCentralityMax && TMath::Abs(vz) < cfgCutVertex && collision.has_foundFT0() && collision.selection_bit(aod::evsel::kNoTimeFrameBorder) && collision.selection_bit(aod::evsel::kNoITSROFrameBorder)) { triggerevent = true; if (useGainCallib && (currentRunNumber != lastRunNumber)) { gainprofile = ccdb->getForTimeStamp(ConfGainPath.value, bc.timestamp()); } + histos.fill(HIST("hEvtSelInfo"), 7.5); + auto gainequal = 1.0; auto alphaZDC = 0.395; constexpr double x[4] = {-1.75, 1.75, -1.75, 1.75}; @@ -547,6 +566,7 @@ struct spvector { return; } + histos.fill(HIST("hEvtSelInfo"), 8.5); histos.fill(HIST("hCentrality"), centrality); histos.fill(HIST("Vz"), vz); diff --git a/PWGLF/Tasks/Strangeness/lambdapolsp.cxx b/PWGLF/Tasks/Strangeness/lambdapolsp.cxx index 270415766a0..0a5596b8684 100644 --- a/PWGLF/Tasks/Strangeness/lambdapolsp.cxx +++ b/PWGLF/Tasks/Strangeness/lambdapolsp.cxx @@ -11,53 +11,54 @@ // Lambda polarisation task // prottay.das@cern.ch -#include -#include -#include +#include "PWGLF/DataModel/LFStrangenessPIDTables.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" +#include "PWGLF/DataModel/SPCalibrationTables.h" + +#include "Common/Core/RecoDecay.h" +#include "Common/Core/TrackSelection.h" +#include "Common/Core/trackUtilities.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/FT0Corrected.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include "CCDB/BasicCCDBManager.h" +#include "CommonConstants/PhysicsConstants.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "DataFormatsParameters/GRPObject.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/O2DatabasePDGPlugin.h" +#include "Framework/StepTHn.h" +#include "Framework/runDataProcessing.h" +#include "ReconstructionDataFormats/Track.h" + +#include "Math/GenVector/Boost.h" +#include "Math/Vector3D.h" +#include "Math/Vector4D.h" +#include "TF1.h" +#include "TRandom3.h" #include +#include +#include +#include #include #include #include #include -#include -#include -#include #include -#include + +#include #include +#include #include -#include -#include "Common/Core/RecoDecay.h" - -#include "TRandom3.h" -#include "Math/Vector3D.h" -#include "Math/Vector4D.h" -#include "Math/GenVector/Boost.h" -#include "TF1.h" - -#include "PWGLF/DataModel/SPCalibrationTables.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/StepTHn.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "Common/DataModel/PIDResponse.h" -#include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/Centrality.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/Core/trackUtilities.h" -#include "CommonConstants/PhysicsConstants.h" -#include "Common/Core/TrackSelection.h" -#include "Framework/ASoAHelpers.h" -#include "ReconstructionDataFormats/Track.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "CCDB/BasicCCDBManager.h" -#include "PWGLF/DataModel/LFStrangenessTables.h" -#include "PWGLF/DataModel/LFStrangenessPIDTables.h" -#include "Common/DataModel/FT0Corrected.h" +#include +#include using namespace o2; using namespace o2::framework; @@ -115,11 +116,15 @@ struct lambdapolsp { Configurable cMinV0DCAPr{"cMinV0DCAPr", 0.05, "Minimum V0 daughters DCA to PV for Pr"}; Configurable cMinV0DCAPi{"cMinV0DCAPi", 0.05, "Minimum V0 daughters DCA to PV for Pi"}; Configurable cMaxV0LifeTime{"cMaxV0LifeTime", 20, "Maximum V0 life time"}; + Configurable analyzeLambda{"analyzeLambda", true, "flag for lambda analysis"}; + Configurable analyzeK0s{"analyzeK0s", false, "flag for K0s analysis"}; + Configurable qtArmenterosMinForK0{"qtArmenterosMinForK0", 0.2, "Armenterous cut for K0s"}; // config for V0 daughters Configurable ConfDaughEta{"ConfDaughEta", 0.8f, "V0 Daugh sel: max eta"}; Configurable cfgDaughPrPt{"cfgDaughPrPt", 0.4, "minimum daughter proton pt"}; Configurable cfgDaughPiPt{"cfgDaughPiPt", 0.2, "minimum daughter pion pt"}; + Configurable rcrfc{"rcrfc", 0.8f, "Ratio of CR to FC"}; Configurable ConfDaughTPCnclsMin{"ConfDaughTPCnclsMin", 50.f, "V0 Daugh sel: Min. nCls TPC"}; Configurable ConfDaughPIDCuts{"ConfDaughPIDCuts", 3, "PID selections for Lambda daughters"}; Configurable usesubdet{"usesubdet", false, "use subdet"}; @@ -127,9 +132,9 @@ struct lambdapolsp { Configurable ConfAccPathL{"ConfAccPathL", "Users/p/prottay/My/Object/From379780/Fulldata/NewPbPbpass4_28032025/acccorrL", "Path to acceptance correction for Lambda"}; Configurable ConfAccPathAL{"ConfAccPathAL", "Users/p/prottay/My/Object/From379780/Fulldata/NewPbPbpass4_28032025/acccorrAL", "Path to acceptance correction for AntiLambda"}; - Configurable CentNbins{"CentNbins", 16, "Number of bins in cent histograms"}; - Configurable lbinCent{"lbinCent", 0.0, "lower bin value in cent histograms"}; - Configurable hbinCent{"hbinCent", 80.0, "higher bin value in cent histograms"}; + // Configurable CentNbins{"CentNbins", 16, "Number of bins in cent histograms"}; + // Configurable lbinCent{"lbinCent", 0.0, "lower bin value in cent histograms"}; + // Configurable hbinCent{"hbinCent", 80.0, "higher bin value in cent histograms"}; Configurable SANbins{"SANbins", 20, "Number of bins in costhetastar"}; Configurable lbinSA{"lbinSA", -1.0, "lower bin value in costhetastar histograms"}; Configurable hbinSA{"hbinSA", 1.0, "higher bin value in costhetastar histograms"}; @@ -145,12 +150,13 @@ struct lambdapolsp { Configurable spNbins{"spNbins", 2000, "Number of bins in sp"}; Configurable lbinsp{"lbinsp", -1.0, "lower bin value in sp histograms"}; Configurable hbinsp{"hbinsp", 1.0, "higher bin value in sp histograms"}; - + /* ConfigurableAxis configcentAxis{"configcentAxis", {VARIABLE_WIDTH, 0.0, 10.0, 40.0, 80.0}, "Cent V0M"}; ConfigurableAxis configthnAxispT{"configthnAxisPt", {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, 100.0}, "#it{p}_{T} (GeV/#it{c})"}; ConfigurableAxis configetaAxis{"configetaAxis", {VARIABLE_WIDTH, -0.8, -0.4, -0.2, 0, 0.2, 0.4, 0.8}, "Eta"}; ConfigurableAxis configthnAxisPol{"configthnAxisPol", {VARIABLE_WIDTH, -1.0, -0.6, -0.2, 0, 0.2, 0.4, 0.8}, "Pol"}; ConfigurableAxis configbinAxis{"configbinAxis", {VARIABLE_WIDTH, -0.8, -0.4, -0.2, 0, 0.2, 0.4, 0.8}, "BA"}; + */ // ConfigurableAxis configphiAxis{"configphiAxis", {VARIABLE_WIDTH, 0.0, 0.2, 0.4, 0.8, 1.0, 2.0, 2.5, 3.0, 4.0, 5.0, 5.5, 6.28}, "PhiAxis"}; struct : ConfigurableGroup { Configurable requireRCTFlagChecker{"requireRCTFlagChecker", true, "Check event quality in run condition table"}; @@ -158,6 +164,13 @@ struct lambdapolsp { 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; + struct : ConfigurableGroup { + ConfigurableAxis configcentAxis{"configcentAxis", {VARIABLE_WIDTH, 0.0, 10.0, 40.0, 80.0}, "Cent V0M"}; + ConfigurableAxis configthnAxispT{"configthnAxisPt", {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, 100.0}, "#it{p}_{T} (GeV/#it{c})"}; + ConfigurableAxis configetaAxis{"configetaAxis", {VARIABLE_WIDTH, -0.8, -0.4, -0.2, 0, 0.2, 0.4, 0.8}, "Eta"}; + ConfigurableAxis configthnAxisPol{"configthnAxisPol", {VARIABLE_WIDTH, -1.0, -0.6, -0.2, 0, 0.2, 0.4, 0.8}, "Pol"}; + ConfigurableAxis configbinAxis{"configbinAxis", {VARIABLE_WIDTH, -0.8, -0.4, -0.2, 0, 0.2, 0.4, 0.8}, "BA"}; + } axisGrp; RCTFlagsChecker rctChecker; @@ -172,115 +185,115 @@ struct lambdapolsp { AxisSpec thnAxisres{resNbins, lbinres, hbinres, "Reso"}; AxisSpec thnAxisInvMass{IMNbins, lbinIM, hbinIM, "#it{M} (GeV/#it{c}^{2})"}; AxisSpec thnAxisCosThetaStar{SANbins, lbinSA, hbinSA, "SA"}; - AxisSpec centAxis = {CentNbins, lbinCent, hbinCent, "V0M (%)"}; + // AxisSpec centAxis = {CentNbins, lbinCent, hbinCent, "V0M (%)"}; AxisSpec spAxis = {spNbins, lbinsp, hbinsp, "Sp"}; AxisSpec qxZDCAxis = {QxyNbins, lbinQxy, hbinQxy, "Qx"}; - std::vector runaxes = {thnAxisInvMass, configthnAxispT, configthnAxisPol, configcentAxis}; + std::vector runaxes = {thnAxisInvMass, axisGrp.configthnAxispT, axisGrp.configthnAxisPol, axisGrp.configcentAxis}; if (needetaaxis) - runaxes.insert(runaxes.end(), {configbinAxis}); + runaxes.insert(runaxes.end(), {axisGrp.configbinAxis}); if (checkwithpub) { if (useprofile == 2) { - histos.add("hpuxQxpvscentpteta", "hpuxQxpvscentpteta", HistType::kTHnSparseF, {centAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpuyQypvscentpteta", "hpuyQypvscentpteta", HistType::kTHnSparseF, {centAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpuxQxtvscentpteta", "hpuxQxtvscentpteta", HistType::kTHnSparseF, {centAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpuyQytvscentpteta", "hpuyQytvscentpteta", HistType::kTHnSparseF, {centAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpuxyQxytvscentpteta", "hpuxyQxytvscentpteta", HistType::kTHnSparseF, {centAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpuxyQxypvscentpteta", "hpuxyQxypvscentpteta", HistType::kTHnSparseF, {centAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpoddv1vscentpteta", "hpoddv1vscentpteta", HistType::kTHnSparseF, {centAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpevenv1vscentpteta", "hpevenv1vscentpteta", HistType::kTHnSparseF, {centAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpv21", "hpv21", HistType::kTHnSparseF, {centAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpv22", "hpv22", HistType::kTHnSparseF, {centAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpv23", "hpv23", HistType::kTHnSparseF, {centAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpx2Tx1Ax1Cvscentpteta", "hpx2Tx1Ax1Cvscentpteta", HistType::kTHnSparseF, {centAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpx2Ty1Ay1Cvscentpteta", "hpx2Ty1Ay1Cvscentpteta", HistType::kTHnSparseF, {centAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpy2Tx1Ay1Cvscentpteta", "hpy2Tx1Ay1Cvscentpteta", HistType::kTHnSparseF, {centAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpy2Ty1Ax1Cvscentpteta", "hpy2Ty1Ax1Cvscentpteta", HistType::kTHnSparseF, {centAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpx1Ax1Cvscentpteta", "hpx1Ax1Cvscentpteta", HistType::kTHnSparseF, {centAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpy1Ay1Cvscentpteta", "hpy1Ay1Cvscentpteta", HistType::kTHnSparseF, {centAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpx1Avscentpteta", "hpx1Avscentpteta", HistType::kTHnSparseF, {centAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpx1Cvscentpteta", "hpx1Cvscentpteta", HistType::kTHnSparseF, {centAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpy1Avscentpteta", "hpy1Avscentpteta", HistType::kTHnSparseF, {centAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpy1Cvscentpteta", "hpy1Cvscentpteta", HistType::kTHnSparseF, {centAxis, configthnAxispT, configetaAxis, spAxis}, true); - - histos.add("hpx2Tx1Avscentpteta", "hpx2Tx1Avscentpteta", HistType::kTHnSparseF, {centAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpx2Tx1Cvscentpteta", "hpx2Tx1Cvscentpteta", HistType::kTHnSparseF, {centAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpx2Ty1Avscentpteta", "hpx2Ty1Avscentpteta", HistType::kTHnSparseF, {centAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpx2Ty1Cvscentpteta", "hpx2Ty1Cvscentpteta", HistType::kTHnSparseF, {centAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpy2Tx1Avscentpteta", "hpy2Tx1Avscentpteta", HistType::kTHnSparseF, {centAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpy2Ty1Cvscentpteta", "hpy2Ty1Cvscentpteta", HistType::kTHnSparseF, {centAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpy2Ty1Avscentpteta", "hpy2Ty1Avscentpteta", HistType::kTHnSparseF, {centAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpy2Tx1Cvscentpteta", "hpy2Tx1Cvscentpteta", HistType::kTHnSparseF, {centAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpx1Ay1Cvscentpteta", "hpx1Ay1Cvscentpteta", HistType::kTHnSparseF, {centAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpy1Ax1Cvscentpteta", "hpy1Ax1Cvscentpteta", HistType::kTHnSparseF, {centAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpx2Tvscentpteta", "hpx2Tvscentpteta", HistType::kTHnSparseF, {centAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpy2Tvscentpteta", "hpy2Tvscentpteta", HistType::kTHnSparseF, {centAxis, configthnAxispT, configetaAxis, spAxis}, true); - - histos.add("hpuxvscentpteta", "hpuxvscentpteta", HistType::kTHnSparseF, {centAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpuyvscentpteta", "hpuyvscentpteta", HistType::kTHnSparseF, {centAxis, configthnAxispT, configetaAxis, spAxis}, true); + histos.add("hpuxQxpvscentpteta", "hpuxQxpvscentpteta", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + histos.add("hpuyQypvscentpteta", "hpuyQypvscentpteta", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + histos.add("hpuxQxtvscentpteta", "hpuxQxtvscentpteta", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + histos.add("hpuyQytvscentpteta", "hpuyQytvscentpteta", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + histos.add("hpuxyQxytvscentpteta", "hpuxyQxytvscentpteta", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + histos.add("hpuxyQxypvscentpteta", "hpuxyQxypvscentpteta", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + histos.add("hpoddv1vscentpteta", "hpoddv1vscentpteta", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + histos.add("hpevenv1vscentpteta", "hpevenv1vscentpteta", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + histos.add("hpv21", "hpv21", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + histos.add("hpv22", "hpv22", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + histos.add("hpv23", "hpv23", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + histos.add("hpx2Tx1Ax1Cvscentpteta", "hpx2Tx1Ax1Cvscentpteta", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + histos.add("hpx2Ty1Ay1Cvscentpteta", "hpx2Ty1Ay1Cvscentpteta", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + histos.add("hpy2Tx1Ay1Cvscentpteta", "hpy2Tx1Ay1Cvscentpteta", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + histos.add("hpy2Ty1Ax1Cvscentpteta", "hpy2Ty1Ax1Cvscentpteta", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + histos.add("hpx1Ax1Cvscentpteta", "hpx1Ax1Cvscentpteta", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + histos.add("hpy1Ay1Cvscentpteta", "hpy1Ay1Cvscentpteta", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + histos.add("hpx1Avscentpteta", "hpx1Avscentpteta", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + histos.add("hpx1Cvscentpteta", "hpx1Cvscentpteta", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + histos.add("hpy1Avscentpteta", "hpy1Avscentpteta", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + histos.add("hpy1Cvscentpteta", "hpy1Cvscentpteta", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + + histos.add("hpx2Tx1Avscentpteta", "hpx2Tx1Avscentpteta", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + histos.add("hpx2Tx1Cvscentpteta", "hpx2Tx1Cvscentpteta", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + histos.add("hpx2Ty1Avscentpteta", "hpx2Ty1Avscentpteta", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + histos.add("hpx2Ty1Cvscentpteta", "hpx2Ty1Cvscentpteta", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + histos.add("hpy2Tx1Avscentpteta", "hpy2Tx1Avscentpteta", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + histos.add("hpy2Ty1Cvscentpteta", "hpy2Ty1Cvscentpteta", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + histos.add("hpy2Ty1Avscentpteta", "hpy2Ty1Avscentpteta", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + histos.add("hpy2Tx1Cvscentpteta", "hpy2Tx1Cvscentpteta", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + histos.add("hpx1Ay1Cvscentpteta", "hpx1Ay1Cvscentpteta", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + histos.add("hpy1Ax1Cvscentpteta", "hpy1Ax1Cvscentpteta", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + histos.add("hpx2Tvscentpteta", "hpx2Tvscentpteta", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + histos.add("hpy2Tvscentpteta", "hpy2Tvscentpteta", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + + histos.add("hpuxvscentpteta", "hpuxvscentpteta", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + histos.add("hpuyvscentpteta", "hpuyvscentpteta", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); /* - histos.add("hpuxvscentptetaneg", "hpuxvscentptetaneg", HistType::kTHnSparseF, {centAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpuyvscentptetaneg", "hpuyvscentptetaneg", HistType::kTHnSparseF, {centAxis, configthnAxispT, configetaAxis, spAxis}, true); - - histos.add("hpuxQxpvscentptetaneg", "hpuxQxpvscentptetaneg", HistType::kTHnSparseF, {centAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpuyQypvscentptetaneg", "hpuyQypvscentptetaneg", HistType::kTHnSparseF, {centAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpuxQxtvscentptetaneg", "hpuxQxtvscentptetaneg", HistType::kTHnSparseF, {centAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpuyQytvscentptetaneg", "hpuyQytvscentptetaneg", HistType::kTHnSparseF, {centAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpuxyQxytvscentptetaneg", "hpuxyQxytvscentptetaneg", HistType::kTHnSparseF, {centAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpuxyQxypvscentptetaneg", "hpuxyQxypvscentptetaneg", HistType::kTHnSparseF, {centAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpoddv1vscentptetaneg", "hpoddv1vscentptetaneg", HistType::kTHnSparseF, {centAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpevenv1vscentptetaneg", "hpevenv1vscentptetaneg", HistType::kTHnSparseF, {centAxis, configthnAxispT, configetaAxis, spAxis}, true); + histos.add("hpuxvscentptetaneg", "hpuxvscentptetaneg", HistType::kTHnSparseF, {axisGrp.configcentAxis, configthnAxispT, configetaAxis, spAxis}, true); + histos.add("hpuyvscentptetaneg", "hpuyvscentptetaneg", HistType::kTHnSparseF, {axisGrp.configcentAxis, configthnAxispT, configetaAxis, spAxis}, true); + + histos.add("hpuxQxpvscentptetaneg", "hpuxQxpvscentptetaneg", HistType::kTHnSparseF, {axisGrp.configcentAxis, configthnAxispT, configetaAxis, spAxis}, true); + histos.add("hpuyQypvscentptetaneg", "hpuyQypvscentptetaneg", HistType::kTHnSparseF, {axisGrp.configcentAxis, configthnAxispT, configetaAxis, spAxis}, true); + histos.add("hpuxQxtvscentptetaneg", "hpuxQxtvscentptetaneg", HistType::kTHnSparseF, {axisGrp.configcentAxis, configthnAxispT, configetaAxis, spAxis}, true); + histos.add("hpuyQytvscentptetaneg", "hpuyQytvscentptetaneg", HistType::kTHnSparseF, {axisGrp.configcentAxis, configthnAxispT, configetaAxis, spAxis}, true); + histos.add("hpuxyQxytvscentptetaneg", "hpuxyQxytvscentptetaneg", HistType::kTHnSparseF, {axisGrp.configcentAxis, configthnAxispT, configetaAxis, spAxis}, true); + histos.add("hpuxyQxypvscentptetaneg", "hpuxyQxypvscentptetaneg", HistType::kTHnSparseF, {axisGrp.configcentAxis, configthnAxispT, configetaAxis, spAxis}, true); + histos.add("hpoddv1vscentptetaneg", "hpoddv1vscentptetaneg", HistType::kTHnSparseF, {axisGrp.configcentAxis, configthnAxispT, configetaAxis, spAxis}, true); + histos.add("hpevenv1vscentptetaneg", "hpevenv1vscentptetaneg", HistType::kTHnSparseF, {axisGrp.configcentAxis, configthnAxispT, configetaAxis, spAxis}, true); */ - histos.add("hpQxtQxpvscent", "hpQxtQxpvscent", HistType::kTHnSparseF, {centAxis, spAxis}, true); - histos.add("hpQytQypvscent", "hpQytQypvscent", HistType::kTHnSparseF, {centAxis, spAxis}, true); - histos.add("hpQxytpvscent", "hpQxytpvscent", HistType::kTHnSparseF, {centAxis, spAxis}, true); - histos.add("hpQxtQypvscent", "hpQxtQypvscent", HistType::kTHnSparseF, {centAxis, spAxis}, true); - histos.add("hpQxpQytvscent", "hpQxpQytvscent", HistType::kTHnSparseF, {centAxis, spAxis}, true); + histos.add("hpQxtQxpvscent", "hpQxtQxpvscent", HistType::kTHnSparseF, {axisGrp.configcentAxis, spAxis}, true); + histos.add("hpQytQypvscent", "hpQytQypvscent", HistType::kTHnSparseF, {axisGrp.configcentAxis, spAxis}, true); + histos.add("hpQxytpvscent", "hpQxytpvscent", HistType::kTHnSparseF, {axisGrp.configcentAxis, spAxis}, true); + histos.add("hpQxtQypvscent", "hpQxtQypvscent", HistType::kTHnSparseF, {axisGrp.configcentAxis, spAxis}, true); + histos.add("hpQxpQytvscent", "hpQxpQytvscent", HistType::kTHnSparseF, {axisGrp.configcentAxis, spAxis}, true); - histos.add("hpQxpvscent", "hpQxpvscent", HistType::kTHnSparseF, {centAxis, spAxis}, true); - histos.add("hpQxtvscent", "hpQxtvscent", HistType::kTHnSparseF, {centAxis, spAxis}, true); - histos.add("hpQypvscent", "hpQypvscent", HistType::kTHnSparseF, {centAxis, spAxis}, true); - histos.add("hpQytvscent", "hpQytvscent", HistType::kTHnSparseF, {centAxis, spAxis}, true); + histos.add("hpQxpvscent", "hpQxpvscent", HistType::kTHnSparseF, {axisGrp.configcentAxis, spAxis}, true); + histos.add("hpQxtvscent", "hpQxtvscent", HistType::kTHnSparseF, {axisGrp.configcentAxis, spAxis}, true); + histos.add("hpQypvscent", "hpQypvscent", HistType::kTHnSparseF, {axisGrp.configcentAxis, spAxis}, true); + histos.add("hpQytvscent", "hpQytvscent", HistType::kTHnSparseF, {axisGrp.configcentAxis, spAxis}, true); } else { - histos.add("hpuxQxpvscentpteta", "hpuxQxpvscentpteta", HistType::kTHnSparseF, {configcentAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpuyQypvscentpteta", "hpuyQypvscentpteta", HistType::kTHnSparseF, {configcentAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpuxQxtvscentpteta", "hpuxQxtvscentpteta", HistType::kTHnSparseF, {configcentAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpuyQytvscentpteta", "hpuyQytvscentpteta", HistType::kTHnSparseF, {configcentAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpuxyQxytvscentpteta", "hpuxyQxytvscentpteta", HistType::kTHnSparseF, {configcentAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpuxyQxypvscentpteta", "hpuxyQxypvscentpteta", HistType::kTHnSparseF, {configcentAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpoddv1vscentpteta", "hpoddv1vscentpteta", HistType::kTHnSparseF, {configcentAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpevenv1vscentpteta", "hpevenv1vscentpteta", HistType::kTHnSparseF, {configcentAxis, configthnAxispT, configetaAxis, spAxis}, true); - - histos.add("hpuxvscentpteta", "hpuxvscentpteta", HistType::kTHnSparseF, {configcentAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpuyvscentpteta", "hpuyvscentpteta", HistType::kTHnSparseF, {configcentAxis, configthnAxispT, configetaAxis, spAxis}, true); - /*histos.add("hpuxvscentptetaneg", "hpuxvscentptetaneg", HistType::kTHnSparseF, {configcentAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpuyvscentptetaneg", "hpuyvscentptetaneg", HistType::kTHnSparseF, {configcentAxis, configthnAxispT, configetaAxis, spAxis}, true); - - histos.add("hpuxQxpvscentptetaneg", "hpuxQxpvscentptetaneg", HistType::kTHnSparseF, {configcentAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpuyQypvscentptetaneg", "hpuyQypvscentptetaneg", HistType::kTHnSparseF, {configcentAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpuxQxtvscentptetaneg", "hpuxQxtvscentptetaneg", HistType::kTHnSparseF, {configcentAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpuyQytvscentptetaneg", "hpuyQytvscentptetaneg", HistType::kTHnSparseF, {configcentAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpuxyQxytvscentptetaneg", "hpuxyQxytvscentptetaneg", HistType::kTHnSparseF, {configcentAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpuxyQxypvscentptetaneg", "hpuxyQxypvscentptetaneg", HistType::kTHnSparseF, {configcentAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpoddv1vscentptetaneg", "hpoddv1vscentptetaneg", HistType::kTHnSparseF, {configcentAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpevenv1vscentptetaneg", "hpevenv1vscentptetaneg", HistType::kTHnSparseF, {configcentAxis, configthnAxispT, configetaAxis, spAxis}, true);*/ - - histos.add("hpQxtQxpvscent", "hpQxtQxpvscent", HistType::kTHnSparseF, {configcentAxis, spAxis}, true); - histos.add("hpQytQypvscent", "hpQytQypvscent", HistType::kTHnSparseF, {configcentAxis, spAxis}, true); - histos.add("hpQxytpvscent", "hpQxytpvscent", HistType::kTHnSparseF, {configcentAxis, spAxis}, true); - histos.add("hpQxtQypvscent", "hpQxtQypvscent", HistType::kTHnSparseF, {configcentAxis, spAxis}, true); - histos.add("hpQxpQytvscent", "hpQxpQytvscent", HistType::kTHnSparseF, {configcentAxis, spAxis}, true); - - histos.add("hpQxpvscent", "hpQxpvscent", HistType::kTHnSparseF, {configcentAxis, spAxis}, true); - histos.add("hpQxtvscent", "hpQxtvscent", HistType::kTHnSparseF, {configcentAxis, spAxis}, true); - histos.add("hpQypvscent", "hpQypvscent", HistType::kTHnSparseF, {configcentAxis, spAxis}, true); - histos.add("hpQytvscent", "hpQytvscent", HistType::kTHnSparseF, {configcentAxis, spAxis}, true); + histos.add("hpuxQxpvscentpteta", "hpuxQxpvscentpteta", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + histos.add("hpuyQypvscentpteta", "hpuyQypvscentpteta", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + histos.add("hpuxQxtvscentpteta", "hpuxQxtvscentpteta", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + histos.add("hpuyQytvscentpteta", "hpuyQytvscentpteta", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + histos.add("hpuxyQxytvscentpteta", "hpuxyQxytvscentpteta", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + histos.add("hpuxyQxypvscentpteta", "hpuxyQxypvscentpteta", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + histos.add("hpoddv1vscentpteta", "hpoddv1vscentpteta", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + histos.add("hpevenv1vscentpteta", "hpevenv1vscentpteta", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + + histos.add("hpuxvscentpteta", "hpuxvscentpteta", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + histos.add("hpuyvscentpteta", "hpuyvscentpteta", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + /*histos.add("hpuxvscentptetaneg", "hpuxvscentptetaneg", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + histos.add("hpuyvscentptetaneg", "hpuyvscentptetaneg", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + + histos.add("hpuxQxpvscentptetaneg", "hpuxQxpvscentptetaneg", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + histos.add("hpuyQypvscentptetaneg", "hpuyQypvscentptetaneg", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + histos.add("hpuxQxtvscentptetaneg", "hpuxQxtvscentptetaneg", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + histos.add("hpuyQytvscentptetaneg", "hpuyQytvscentptetaneg", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + histos.add("hpuxyQxytvscentptetaneg", "hpuxyQxytvscentptetaneg", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + histos.add("hpuxyQxypvscentptetaneg", "hpuxyQxypvscentptetaneg", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + histos.add("hpoddv1vscentptetaneg", "hpoddv1vscentptetaneg", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + histos.add("hpevenv1vscentptetaneg", "hpevenv1vscentptetaneg", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true);*/ + + histos.add("hpQxtQxpvscent", "hpQxtQxpvscent", HistType::kTHnSparseF, {axisGrp.configcentAxis, spAxis}, true); + histos.add("hpQytQypvscent", "hpQytQypvscent", HistType::kTHnSparseF, {axisGrp.configcentAxis, spAxis}, true); + histos.add("hpQxytpvscent", "hpQxytpvscent", HistType::kTHnSparseF, {axisGrp.configcentAxis, spAxis}, true); + histos.add("hpQxtQypvscent", "hpQxtQypvscent", HistType::kTHnSparseF, {axisGrp.configcentAxis, spAxis}, true); + histos.add("hpQxpQytvscent", "hpQxpQytvscent", HistType::kTHnSparseF, {axisGrp.configcentAxis, spAxis}, true); + + histos.add("hpQxpvscent", "hpQxpvscent", HistType::kTHnSparseF, {axisGrp.configcentAxis, spAxis}, true); + histos.add("hpQxtvscent", "hpQxtvscent", HistType::kTHnSparseF, {axisGrp.configcentAxis, spAxis}, true); + histos.add("hpQypvscent", "hpQypvscent", HistType::kTHnSparseF, {axisGrp.configcentAxis, spAxis}, true); + histos.add("hpQytvscent", "hpQytvscent", HistType::kTHnSparseF, {axisGrp.configcentAxis, spAxis}, true); } } - histos.add("hCentrality", "Centrality distribution", kTH1F, {{centAxis}}); + histos.add("hCentrality", "Centrality distribution", kTH1F, {{axisGrp.configcentAxis}}); // histos.add("hpsiApsiC", "hpsiApsiC", kTHnSparseF, {psiACAxis, psiACAxis}); // histos.add("hpsiApsiC", "hpsiApsiC", kTH2F, {psiACAxis, psiACAxis}); // histos.add("hphiminuspsiA", "hphiminuspisA", kTH1F, {{50, 0, 6.28}}, true); @@ -292,12 +305,12 @@ struct lambdapolsp { if (!checkwithpub) { // histos.add("hVtxZ", "Vertex distribution in Z;Z (cm)", kTH1F, {{20, -10.0, 10.0}}); - histos.add("hpRes", "hpRes", HistType::kTHnSparseF, {configcentAxis, thnAxisres}); - histos.add("hpResSin", "hpResSin", HistType::kTHnSparseF, {configcentAxis, thnAxisres}); - /*histos.add("hpCosPsiA", "hpCosPsiA", HistType::kTHnSparseF, {configcentAxis, thnAxisres}); - histos.add("hpCosPsiC", "hpCosPsiC", HistType::kTHnSparseF, {configcentAxis, thnAxisres}); - histos.add("hpSinPsiA", "hpSinPsiA", HistType::kTHnSparseF, {configcentAxis, thnAxisres}); - histos.add("hpSinPsiC", "hpSinPsiC", HistType::kTHnSparseF, {configcentAxis, thnAxisres});*/ + histos.add("hpRes", "hpRes", HistType::kTHnSparseF, {axisGrp.configcentAxis, thnAxisres}); + histos.add("hpResSin", "hpResSin", HistType::kTHnSparseF, {axisGrp.configcentAxis, thnAxisres}); + /*histos.add("hpCosPsiA", "hpCosPsiA", HistType::kTHnSparseF, {axisGrp.configcentAxis, thnAxisres}); + histos.add("hpCosPsiC", "hpCosPsiC", HistType::kTHnSparseF, {axisGrp.configcentAxis, thnAxisres}); + histos.add("hpSinPsiA", "hpSinPsiA", HistType::kTHnSparseF, {axisGrp.configcentAxis, thnAxisres}); + histos.add("hpSinPsiC", "hpSinPsiC", HistType::kTHnSparseF, {axisGrp.configcentAxis, thnAxisres});*/ /*histos.add("hcentQxZDCA", "hcentQxZDCA", kTH2F, {{centAxis}, {qxZDCAxis}}); histos.add("hcentQyZDCA", "hcentQyZDCA", kTH2F, {{centAxis}, {qxZDCAxis}}); histos.add("hcentQxZDCC", "hcentQxZDCC", kTH2F, {{centAxis}, {qxZDCAxis}}); @@ -367,6 +380,7 @@ struct lambdapolsp { const float cpav0 = candidate.v0cosPA(); float CtauLambda = candidate.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * massLambda; + float CtauK0s = candidate.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * massK0s; // float lowmasscutlambda = cMinLambdaMass; // float highmasscutlambda = cMaxLambdaMass; @@ -385,21 +399,28 @@ struct lambdapolsp { if (tranRad > ConfV0TranRadV0Max) { return false; } - if (TMath::Abs(CtauLambda) > cMaxV0LifeTime) { + if (analyzeLambda && TMath::Abs(CtauLambda) > cMaxV0LifeTime) { + return false; + } + if (analyzeK0s && TMath::Abs(CtauK0s) > cMaxV0LifeTime) { + return false; + } + if (analyzeLambda && TMath::Abs(candidate.yLambda()) > ConfV0Rap) { return false; } - if (TMath::Abs(candidate.yLambda()) > ConfV0Rap) { + if (analyzeK0s && TMath::Abs(candidate.yK0Short()) > ConfV0Rap) { return false; } return true; } + template bool isSelectedV0Daughter(V0 const& candidate, T const& track, int pid) { // const auto eta = track.eta(); // const auto pt = track.pt(); const auto tpcNClsF = track.tpcNClsFound(); - if (track.tpcNClsCrossedRows() < 70) { + if (track.tpcNClsCrossedRows() < cfgTPCcluster) { return false; } /*if (TMath::Abs(eta) > ConfDaughEta) { @@ -408,7 +429,7 @@ struct lambdapolsp { if (tpcNClsF < ConfDaughTPCnclsMin) { return false; } - if (track.tpcCrossedRowsOverFindableCls() < 0.8) { + if (track.tpcCrossedRowsOverFindableCls() < rcrfc) { return false; } @@ -459,13 +480,13 @@ struct lambdapolsp { } // check TPC tracking properties - if (posTrackExtra.tpcNClsCrossedRows() < 70 || negTrackExtra.tpcNClsCrossedRows() < 70) { + if (posTrackExtra.tpcNClsCrossedRows() < cfgTPCcluster || negTrackExtra.tpcNClsCrossedRows() < cfgTPCcluster) { return false; } if (posTrackExtra.tpcNClsFound() < ConfDaughTPCnclsMin || negTrackExtra.tpcNClsFound() < ConfDaughTPCnclsMin) { return false; } - if (posTrackExtra.tpcCrossedRowsOverFindableCls() < 0.8 || negTrackExtra.tpcCrossedRowsOverFindableCls() < 0.8) { + if (posTrackExtra.tpcCrossedRowsOverFindableCls() < rcrfc || negTrackExtra.tpcCrossedRowsOverFindableCls() < rcrfc) { return false; } @@ -488,10 +509,49 @@ struct lambdapolsp { return true; } + template + bool isCompatibleK0s(TV0 const& v0) + { + // checks if this V0 is compatible with the requested hypothesis + + // de-ref track extras + auto posTrackExtra = v0.template posTrackExtra_as(); + auto negTrackExtra = v0.template negTrackExtra_as(); + + // check for desired kinematics + if ((v0.positivept() < cfgDaughPrPt || v0.negativept() < cfgDaughPiPt)) { + return false; // doesn´t pass lambda pT sels + } + if (std::abs(v0.positiveeta()) > ConfDaughEta || std::abs(v0.negativeeta()) > ConfDaughEta) { + return false; + } + // check TPC tracking properties + if (posTrackExtra.tpcNClsCrossedRows() < cfgTPCcluster || negTrackExtra.tpcNClsCrossedRows() < cfgTPCcluster) { + return false; + } + if (posTrackExtra.tpcNClsFound() < ConfDaughTPCnclsMin || negTrackExtra.tpcNClsFound() < ConfDaughTPCnclsMin) { + return false; + } + if (posTrackExtra.tpcCrossedRowsOverFindableCls() < rcrfc || negTrackExtra.tpcCrossedRowsOverFindableCls() < rcrfc) { + return false; + } + // check TPC PID + if (((std::abs(posTrackExtra.tpcNSigmaPi()) > ConfDaughPIDCuts) || (std::abs(negTrackExtra.tpcNSigmaPi()) > ConfDaughPIDCuts))) { + return false; + } + if ((TMath::Abs(v0.dcapostopv()) < cMinV0DCAPi || TMath::Abs(v0.dcanegtopv()) < cMinV0DCAPi)) { + return false; + } + if ((v0.qtarm() / (std::abs(v0.alpha()))) < qtArmenterosMinForK0) { + return false; + } + // if we made it this far, it's good + return true; + } + double GetPhiInRange(double phi) { double result = RecoDecay::constrainAngle(phi); - /* double result = phi; while (result < 0) { @@ -634,12 +694,13 @@ struct lambdapolsp { } } - ROOT::Math::PxPyPzMVector Lambda, AntiLambda, Lambdadummy, AntiLambdadummy, Proton, Pion, AntiProton, AntiPion, fourVecDauCM; + ROOT::Math::PxPyPzMVector Lambda, AntiLambda, Lambdadummy, AntiLambdadummy, Proton, Pion, AntiProton, AntiPion, fourVecDauCM, K0sdummy, K0s; ROOT::Math::XYZVector threeVecDauCM, threeVecDauCMXY; double phiangle = 0.0; // double angleLambda=0.0; // double angleAntiLambda=0.0; double massLambda = o2::constants::physics::MassLambda; + double massK0s = o2::constants::physics::MassK0Short; double massPr = o2::constants::physics::MassProton; double massPi = o2::constants::physics::MassPionCharged; @@ -1036,7 +1097,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&, BCsRun3 const&) + void processDerivedData(soa::Join::iterator const& collision, v0Candidates const& V0s, dauTracks const&) { //___________________________________________________________________________________________________ // event selection @@ -1048,6 +1109,10 @@ struct lambdapolsp { return; } + if (rctCut.requireRCTFlagChecker && !rctChecker(collision)) { + return; + } + if (additionalEvSel && (!collision.selection_bit(aod::evsel::kNoSameBunchPileup) || !collision.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV))) { return; } @@ -1115,31 +1180,51 @@ struct lambdapolsp { //___________________________________________________________________________________________________ // loop over V0s as necessary for (const auto& v0 : V0s) { + + if (analyzeLambda && analyzeK0s) + continue; + if (!analyzeLambda && !analyzeK0s) + continue; + bool LambdaTag = isCompatible(v0, 0); bool aLambdaTag = isCompatible(v0, 1); - if (!LambdaTag && !aLambdaTag) + bool K0sTag = isCompatibleK0s(v0); + + if (analyzeLambda && !LambdaTag && !aLambdaTag) + continue; + + if (analyzeK0s && !K0sTag) continue; if (!SelectionV0(collision, v0)) { continue; } + if (analyzeLambda) { + if (LambdaTag) { + Proton = ROOT::Math::PxPyPzMVector(v0.pxpos(), v0.pypos(), v0.pzpos(), massPr); + AntiPion = ROOT::Math::PxPyPzMVector(v0.pxneg(), v0.pyneg(), v0.pzneg(), massPi); + Lambdadummy = Proton + AntiPion; + // angleLambda = calculateAngleBetweenLorentzVectors(Proton, AntiPion); + } + if (aLambdaTag) { + AntiProton = ROOT::Math::PxPyPzMVector(v0.pxneg(), v0.pyneg(), v0.pzneg(), massPr); + Pion = ROOT::Math::PxPyPzMVector(v0.pxpos(), v0.pypos(), v0.pzpos(), massPi); + AntiLambdadummy = AntiProton + Pion; + // angleAntiLambda = calculateAngleBetweenLorentzVectors(AntiProton, Pion); + } - if (LambdaTag) { - Proton = ROOT::Math::PxPyPzMVector(v0.pxpos(), v0.pypos(), v0.pzpos(), massPr); - AntiPion = ROOT::Math::PxPyPzMVector(v0.pxneg(), v0.pyneg(), v0.pzneg(), massPi); - Lambdadummy = Proton + AntiPion; - // angleLambda = calculateAngleBetweenLorentzVectors(Proton, AntiPion); - } - if (aLambdaTag) { - AntiProton = ROOT::Math::PxPyPzMVector(v0.pxneg(), v0.pyneg(), v0.pzneg(), massPr); - Pion = ROOT::Math::PxPyPzMVector(v0.pxpos(), v0.pypos(), v0.pzpos(), massPi); - AntiLambdadummy = AntiProton + Pion; - // angleAntiLambda = calculateAngleBetweenLorentzVectors(AntiProton, Pion); + if (shouldReject(LambdaTag, aLambdaTag, Lambdadummy, AntiLambdadummy)) { + continue; + } } - if (shouldReject(LambdaTag, aLambdaTag, Lambdadummy, AntiLambdadummy)) { - continue; + if (analyzeK0s) { + if (K0sTag) { + Pion = ROOT::Math::PxPyPzMVector(v0.pxpos(), v0.pypos(), v0.pzpos(), massPi); + AntiPion = ROOT::Math::PxPyPzMVector(v0.pxneg(), v0.pyneg(), v0.pzneg(), massPi); + K0sdummy = Pion + AntiPion; + } } if (TMath::Abs(v0.eta()) > 0.8) @@ -1147,9 +1232,17 @@ struct lambdapolsp { int taga = LambdaTag; int tagb = aLambdaTag; + int tagc = K0sTag; float desbinvalue = 0.0; - if (dosystematic) { + + if (analyzeK0s && K0sTag) { + K0s = Pion + AntiPion; + double acvalue = 1.0; + fillHistograms(tagc, 0, K0s, Pion, psiZDCC, psiZDCA, psiZDC, centrality, v0.mK0Short(), v0.pt(), v0.eta(), acvalue); + } + + if (analyzeLambda && dosystematic) { //////////////////////////////////////////////////// float LTsys = TMath::Abs(v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * massLambda); float CPAsys = v0.v0cosPA(); @@ -1199,7 +1292,7 @@ struct lambdapolsp { } /////////////////////////////////////////////////// - if (LambdaTag) { + if (analyzeLambda && LambdaTag) { Lambda = Proton + AntiPion; tagb = 0; double acvalue = 1.0; @@ -1207,7 +1300,7 @@ struct lambdapolsp { } tagb = aLambdaTag; - if (aLambdaTag) { + if (analyzeLambda && aLambdaTag) { AntiLambda = AntiProton + Pion; taga = 0; double acvalue = 1.0; @@ -1215,7 +1308,7 @@ struct lambdapolsp { } } } else { - if (LambdaTag) { + if (analyzeLambda && LambdaTag) { Lambda = Proton + AntiPion; tagb = 0; double acvalue = 1.0; @@ -1223,7 +1316,7 @@ struct lambdapolsp { } tagb = aLambdaTag; - if (aLambdaTag) { + if (analyzeLambda && aLambdaTag) { AntiLambda = AntiProton + Pion; taga = 0; double acvalue = 1.0; From b5699e6b720526e7d5224635d330a91110b334ff Mon Sep 17 00:00:00 2001 From: Daiki Sekihata Date: Sat, 21 Jun 2025 23:44:27 +0200 Subject: [PATCH 174/871] [PWGEM/Dilepton] update treeCreatorElectronMLDDA.cxx for ITSsa (#11718) --- PWGEM/Dilepton/DataModel/lmeeMLTables.h | 38 +-- .../treeCreatorElectronMLDDA.cxx | 267 ++++++++++-------- 2 files changed, 172 insertions(+), 133 deletions(-) diff --git a/PWGEM/Dilepton/DataModel/lmeeMLTables.h b/PWGEM/Dilepton/DataModel/lmeeMLTables.h index 8e0104daf90..a18978a5dda 100644 --- a/PWGEM/Dilepton/DataModel/lmeeMLTables.h +++ b/PWGEM/Dilepton/DataModel/lmeeMLTables.h @@ -9,13 +9,15 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#include -#include "Framework/AnalysisDataModel.h" -#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" #include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include "Framework/AnalysisDataModel.h" + +#include #ifndef PWGEM_DILEPTON_DATAMODEL_LMEEMLTABLES_H_ #define PWGEM_DILEPTON_DATAMODEL_LMEEMLTABLES_H_ @@ -23,10 +25,9 @@ namespace o2::aod { -namespace pwgem::dilepton +namespace pwgem::dilepton::ml { -enum class PID_Label : int { - kUnDef = -1, +enum class PID_Label : uint8_t { kElectron = 0, kMuon = 1, kPion = 2, @@ -34,21 +35,22 @@ enum class PID_Label : int { kProton = 4, }; // this can be used for eID. -enum class Track_Type : int { +enum class Track_Type : uint8_t { kPrimary = 0, kSecondary = 1, }; // this can be used for selecting electron from primary or photon conversion. -} // namespace pwgem::dilepton +} // namespace pwgem::dilepton::ml namespace emprimarytrack { -DECLARE_SOA_COLUMN(CollisionId, collisionId, int); //! -DECLARE_SOA_COLUMN(PIDLabel, pidlabel, int); //! -DECLARE_SOA_COLUMN(TrackType, tracktype, int); //! -DECLARE_SOA_COLUMN(TPCNClsFound, tpcNClsFound, int); //! -DECLARE_SOA_COLUMN(TPCNClsCrossedRows, tpcNClsCrossedRows, int); //! -DECLARE_SOA_COLUMN(IsForValidation, isForValidation, bool); //! +// DECLARE_SOA_COLUMN(CollisionId, collisionId, int); //! +DECLARE_SOA_COLUMN(PIDLabel, pidlabel, uint8_t); //! +DECLARE_SOA_COLUMN(TrackType, tracktype, uint8_t); //! +DECLARE_SOA_COLUMN(TPCNClsFound, tpcNClsFound, uint8_t); //! +DECLARE_SOA_COLUMN(TPCNClsCrossedRows, tpcNClsCrossedRows, uint8_t); //! +DECLARE_SOA_COLUMN(IsForValidation, isForValidation, bool); //! +DECLARE_SOA_COLUMN(Sign, sign, short); //! DECLARE_SOA_DYNAMIC_COLUMN(P, p, [](float pt, float eta) -> float { return pt * std::cosh(eta); }); DECLARE_SOA_DYNAMIC_COLUMN(MeanClusterSizeITS, meanClusterSizeITS, [](uint32_t itsClusterSizes) -> float { int total_cluster_size = 0, nl = 0; @@ -84,8 +86,8 @@ DECLARE_SOA_DYNAMIC_COLUMN(MeanClusterSizeITSob, meanClusterSizeITSob, [](uint32 // reconstructed track information DECLARE_SOA_TABLE(EMPrimaryTracks, "AOD", "EMPTRACK", //! - o2::soa::Index<>, emprimarytrack::CollisionId, collision::PosZ, collision::NumContrib, evsel::NumTracksInTimeRange, evsel::SumAmpFT0CInTimeRange, - track::Pt, track::Eta, track::Phi, track::Tgl, track::Signed1Pt, + o2::soa::Index<>, collision::PosZ, collision::NumContrib, evsel::NumTracksInTimeRange, evsel::SumAmpFT0CInTimeRange, + track::Pt, track::Eta, track::Phi, track::Tgl, emprimarytrack::Sign, track::DcaXY, track::DcaZ, track::CYY, track::CZZ, track::CZY, track::TPCNClsFindable, emprimarytrack::TPCNClsFound, emprimarytrack::TPCNClsCrossedRows, track::TPCChi2NCl, track::TPCInnerParam, diff --git a/PWGEM/Dilepton/TableProducer/treeCreatorElectronMLDDA.cxx b/PWGEM/Dilepton/TableProducer/treeCreatorElectronMLDDA.cxx index b94716a5fda..13d7e8c6b6d 100644 --- a/PWGEM/Dilepton/TableProducer/treeCreatorElectronMLDDA.cxx +++ b/PWGEM/Dilepton/TableProducer/treeCreatorElectronMLDDA.cxx @@ -120,7 +120,7 @@ struct TreeCreatorElectronMLDDA { Configurable skipGRPOquery{"skipGRPOquery", true, "skip grpo query"}; // Operation and minimisation criteria Configurable d_bz_input{"d_bz_input", -999, "bz field, -999 is automatic"}; - Configurable useMatCorrType{"useMatCorrType", 0, "0: none, 1: TGeo, 2: LUT"}; + Configurable useMatCorrType{"useMatCorrType", 2, "0: none, 1: TGeo, 2: LUT"}; Configurable downscaling_electron_primary{"downscaling_electron_primary", 1.1, "down scaling factor to store primary electron for validation"}; Configurable downscaling_electron{"downscaling_electron", 0.005, "down scaling factor to store electron"}; @@ -198,6 +198,8 @@ struct TreeCreatorElectronMLDDA { Configurable cfg_max_chi2tpc{"cfg_max_chi2tpc", 5.0, "max chi2/NclsTPC"}; Configurable cfg_max_chi2its{"cfg_max_chi2its", 6.0, "max chi2/NclsITS"}; Configurable cfg_min_dcaxy_v0leg{"cfg_min_dcaxy_v0leg", 0.1, "min dca XY for v0 legs in cm"}; + Configurable cfg_includeITSsa{"cfg_includeITSsa", false, "Flag to include ITSsa tracks"}; + Configurable cfg_max_pt_itssa{"cfg_max_pt_itssa", 0.15, "mix pt for ITSsa track"}; Configurable cfg_min_TPCNsigmaEl{"cfg_min_TPCNsigmaEl", -4, "min n sigma e in TPC"}; Configurable cfg_max_TPCNsigmaEl{"cfg_max_TPCNsigmaEl", +4, "max n sigma e in TPC"}; @@ -382,7 +384,7 @@ struct TreeCreatorElectronMLDDA { template bool isSelectedTrack(TCollision const& collision, TTrack const& track) { - if (!track.hasITS() || !track.hasTPC()) { + if (!track.hasITS()) { return false; } @@ -396,20 +398,26 @@ struct TreeCreatorElectronMLDDA { return false; } - if (track.tpcNClsCrossedRows() < trackcuts.cfg_min_ncrossedrows_tpc) { + if (!v0cuts.cfg_includeITSsa && (!track.hasITS() || !track.hasTPC())) { return false; } - if (track.tpcNClsFound() < trackcuts.cfg_min_ncluster_tpc) { - return false; - } - if (track.tpcChi2NCl() > trackcuts.cfg_max_chi2tpc) { - return false; - } - if (track.tpcCrossedRowsOverFindableCls() < trackcuts.cfg_min_cr2findable_ratio_tpc) { - return false; - } - if (track.tpcFractionSharedCls() > trackcuts.cfg_max_frac_shared_clusters_tpc) { - return false; + + if (track.hasTPC()) { + if (track.tpcNClsCrossedRows() < trackcuts.cfg_min_ncrossedrows_tpc) { + return false; + } + if (track.tpcNClsFound() < trackcuts.cfg_min_ncluster_tpc) { + return false; + } + if (track.tpcChi2NCl() > trackcuts.cfg_max_chi2tpc) { + return false; + } + if (track.tpcCrossedRowsOverFindableCls() < trackcuts.cfg_min_cr2findable_ratio_tpc) { + return false; + } + if (track.tpcFractionSharedCls() > trackcuts.cfg_max_frac_shared_clusters_tpc) { + return false; + } } mDcaInfoCov.set(999, 999, 999, 999, 999); @@ -421,10 +429,6 @@ struct TreeCreatorElectronMLDDA { float dcaXY = mDcaInfoCov.getY(); float dcaZ = mDcaInfoCov.getZ(); - if (std::fabs(trackParCov.getEta()) > trackcuts.cfg_max_eta || trackParCov.getPt() < trackcuts.cfg_min_pt) { - return false; - } - if (std::fabs(dcaXY) > trackcuts.cfg_max_dcaxy) { return false; } @@ -432,13 +436,20 @@ struct TreeCreatorElectronMLDDA { return false; } + if (std::fabs(trackParCov.getEta()) > trackcuts.cfg_max_eta || trackParCov.getPt() < trackcuts.cfg_min_pt) { + return false; + } + if ((track.hasITS() && !track.hasTPC() && !track.hasTRD() && !track.hasTOF()) && v0cuts.cfg_max_pt_itssa < trackParCov.getPt()) { + return true; + } + return true; } template bool isSelectedV0Leg(TCollision const& collision, TTrack const& track) { - if (!track.hasITS() || !track.hasTPC()) { + if (!track.hasITS()) { return false; } @@ -452,20 +463,26 @@ struct TreeCreatorElectronMLDDA { return false; } - if (track.tpcNClsCrossedRows() < v0cuts.cfg_min_ncrossedrows_tpc) { - return false; - } - if (track.tpcNClsFound() < v0cuts.cfg_min_ncluster_tpc) { - return false; - } - if (track.tpcChi2NCl() > v0cuts.cfg_max_chi2tpc) { - return false; - } - if (track.tpcCrossedRowsOverFindableCls() < v0cuts.cfg_min_cr2findable_ratio_tpc) { + if (!v0cuts.cfg_includeITSsa && (!track.hasITS() || !track.hasTPC())) { return false; } - if (track.tpcFractionSharedCls() > v0cuts.cfg_max_frac_shared_clusters_tpc) { - return false; + + if (track.hasTPC()) { + if (track.tpcNClsCrossedRows() < v0cuts.cfg_min_ncrossedrows_tpc) { + return false; + } + if (track.tpcNClsFound() < v0cuts.cfg_min_ncluster_tpc) { + return false; + } + if (track.tpcChi2NCl() > v0cuts.cfg_max_chi2tpc) { + return false; + } + if (track.tpcCrossedRowsOverFindableCls() < v0cuts.cfg_min_cr2findable_ratio_tpc) { + return false; + } + if (track.tpcFractionSharedCls() > v0cuts.cfg_max_frac_shared_clusters_tpc) { + return false; + } } mDcaInfoCov.set(999, 999, 999, 999, 999); @@ -477,20 +494,27 @@ struct TreeCreatorElectronMLDDA { float dcaXY = mDcaInfoCov.getY(); // float dcaZ = mDcaInfoCov.getZ(); - if (std::fabs(trackParCov.getEta()) > v0cuts.cfg_max_eta || trackParCov.getPt() < v0cuts.cfg_min_pt) { + if (std::fabs(dcaXY) < v0cuts.cfg_min_dcaxy_v0leg) { // this is applied in filter. return false; } - if (std::fabs(dcaXY) < v0cuts.cfg_min_dcaxy_v0leg) { // this is applied in filter. + if (std::fabs(trackParCov.getEta()) > v0cuts.cfg_max_eta || trackParCov.getPt() < v0cuts.cfg_min_pt) { return false; } + if ((track.hasITS() && !track.hasTPC() && !track.hasTRD() && !track.hasTOF()) && v0cuts.cfg_max_pt_itssa < track.pt()) { + return true; + } + return true; } template bool isElectron(TTrack const& track) { + if (v0cuts.cfg_includeITSsa && (track.hasITS() && !track.hasTPC() && !track.hasTRD() && !track.hasTOF())) { + return true; + } bool is_El_TPC = v0cuts.cfg_min_TPCNsigmaEl < track.tpcNSigmaEl() && track.tpcNSigmaEl() < v0cuts.cfg_max_TPCNsigmaEl; bool is_El_TOF = track.hasTOF() ? v0cuts.cfg_min_TOFNsigmaEl < track.tofNSigmaEl() && track.tofNSigmaEl() < v0cuts.cfg_max_TOFNsigmaEl : true; // TOFif return is_El_TPC && is_El_TOF; @@ -499,6 +523,9 @@ struct TreeCreatorElectronMLDDA { template bool isPion(TTrack const& track) { + if (v0cuts.cfg_includeITSsa && (track.hasITS() && !track.hasTPC() && !track.hasTRD() && !track.hasTOF())) { + return true; + } bool is_Pi_TPC = v0cuts.cfg_min_TPCNsigmaPi < track.tpcNSigmaPi() && track.tpcNSigmaPi() < v0cuts.cfg_max_TPCNsigmaPi; bool is_Pi_TOF = track.hasTOF() ? v0cuts.cfg_min_TOFNsigmaPi < track.tofNSigmaPi() && track.tofNSigmaPi() < v0cuts.cfg_max_TOFNsigmaPi : true; // TOFif return is_Pi_TPC && is_Pi_TOF; @@ -507,6 +534,9 @@ struct TreeCreatorElectronMLDDA { template bool isKaon(TTrack const& track) { + if (v0cuts.cfg_includeITSsa && (track.hasITS() && !track.hasTPC() && !track.hasTRD() && !track.hasTOF())) { + return true; + } bool is_Ka_TPC = v0cuts.cfg_min_TPCNsigmaKa < track.tpcNSigmaKa() && track.tpcNSigmaKa() < v0cuts.cfg_max_TPCNsigmaKa; bool is_Ka_TOF = track.hasTOF() ? v0cuts.cfg_min_TOFNsigmaKa < track.tofNSigmaKa() && track.tofNSigmaKa() < v0cuts.cfg_max_TOFNsigmaKa : true; // TOFif return is_Ka_TPC && is_Ka_TOF; @@ -515,6 +545,9 @@ struct TreeCreatorElectronMLDDA { template bool isProton(TTrack const& track) { + if (v0cuts.cfg_includeITSsa && (track.hasITS() && !track.hasTPC() && !track.hasTRD() && !track.hasTOF())) { + return true; + } bool is_Pr_TPC = v0cuts.cfg_min_TPCNsigmaPr < track.tpcNSigmaPr() && track.tpcNSigmaPr() < v0cuts.cfg_max_TPCNsigmaPr; bool is_Pr_TOF = track.hasTOF() ? v0cuts.cfg_min_TOFNsigmaPr < track.tofNSigmaPr() && track.tofNSigmaPr() < v0cuts.cfg_max_TOFNsigmaPr : true; // TOFif return is_Pr_TPC && is_Pr_TOF; @@ -545,7 +578,7 @@ struct TreeCreatorElectronMLDDA { } template - void fillTrackTable(TCollision const& collision, TTrack const& track, const int pidlabel, const int tracktype, const bool isForValidation) + void fillTrackTable(TCollision const& collision, TTrack const& track, const uint8_t pidlabel, const uint8_t tracktype, const bool isForValidation) { if (store_ele_band_only && !isElectron(track)) { return; @@ -561,8 +594,8 @@ struct TreeCreatorElectronMLDDA { float dcaXY = mDcaInfoCov.getY(); float dcaZ = mDcaInfoCov.getZ(); - emprimarytracks(collision.globalIndex(), collision.posZ(), collision.numContrib(), collision.trackOccupancyInTimeRange(), collision.ft0cOccupancyInTimeRange(), - trackParCov.getPt(), trackParCov.getEta(), trackParCov.getPhi() > 0.f ? trackParCov.getPhi() : trackParCov.getPhi() + 2 * M_PI, trackParCov.getTgl(), trackParCov.getQ2Pt(), + emprimarytracks(collision.posZ(), collision.numContrib(), collision.trackOccupancyInTimeRange(), collision.ft0cOccupancyInTimeRange(), + trackParCov.getPt(), trackParCov.getEta(), trackParCov.getPhi() > 0.f ? trackParCov.getPhi() : trackParCov.getPhi() + 2 * M_PI, trackParCov.getTgl(), track.sign(), dcaXY, dcaZ, trackParCov.getSigmaY2(), trackParCov.getSigmaZ2(), trackParCov.getSigmaZY(), track.tpcNClsFindable(), track.tpcNClsFound(), track.tpcNClsCrossedRows(), track.tpcChi2NCl(), track.tpcInnerParam(), @@ -671,8 +704,8 @@ struct TreeCreatorElectronMLDDA { Preslice perCollision_cascade = o2::aod::cascdata::collisionId; Preslice perCollision_track = o2::aod::track::collisionId; - Partition posTracks = o2::aod::track::signed1Pt > 0.f && ncheckbit(aod::track::v001::detectorMap, (uint8_t)o2::aod::track::ITS) == true && ncheckbit(aod::track::v001::detectorMap, (uint8_t)o2::aod::track::TPC) == true; - Partition negTracks = o2::aod::track::signed1Pt < 0.f && ncheckbit(aod::track::v001::detectorMap, (uint8_t)o2::aod::track::ITS) == true && ncheckbit(aod::track::v001::detectorMap, (uint8_t)o2::aod::track::TPC) == true; + Partition posTracks = o2::aod::track::signed1Pt > 0.f && ncheckbit(aod::track::v001::detectorMap, (uint8_t)o2::aod::track::ITS) == true; + Partition negTracks = o2::aod::track::signed1Pt < 0.f && ncheckbit(aod::track::v001::detectorMap, (uint8_t)o2::aod::track::ITS) == true; std::vector stored_trackIds; void processPID(filteredMyCollisions const& collisions, aod::BCsWithTimestamps const&, filteredV0s const& v0s, filteredCascades const& cascades, MyTracks const& tracks) @@ -698,6 +731,8 @@ struct TreeCreatorElectronMLDDA { auto pos = v0.template posTrack_as(); auto neg = v0.template negTrack_as(); // LOGF(info, "v0.globalIndex() = %d, v0.collisionId() = %d, v0.posTrackId() = %d, v0.negTrackId() = %d", v0.globalIndex(), v0.collisionId(), v0.posTrackId(), v0.negTrackId()); + // LOGF(info, "is pos ITSsa = %d", pos.hasITS() && !pos.hasTPC() && !pos.hasTRD() && !pos.hasTOF()); + // LOGF(info, "is neg ITSsa = %d", neg.hasITS() && !neg.hasTPC() && !neg.hasTRD() && !neg.hasTOF()); if (v0.dcaV0daughters() > v0cuts.cfg_max_dcadau) { continue; @@ -724,10 +759,10 @@ struct TreeCreatorElectronMLDDA { registry.fill(HIST("V0/hTPCdEdx_P_Pi"), pos.tpcInnerParam(), pos.tpcSignal()); registry.fill(HIST("V0/hTOFbeta_P_Pi"), pos.tpcInnerParam(), pos.beta()); if (dist01(engine) < downscaling_pion || pos.tpcInnerParam() > max_pin_for_downscaling_pion) { - fillTrackTable(collision, pos, static_cast(o2::aod::pwgem::dilepton::PID_Label::kPion), static_cast(o2::aod::pwgem::dilepton::Track_Type::kSecondary), false); + fillTrackTable(collision, pos, static_cast(o2::aod::pwgem::dilepton::ml::PID_Label::kPion), static_cast(o2::aod::pwgem::dilepton::ml::Track_Type::kSecondary), false); } if (dist01(engine) < downscaling_pion || neg.tpcInnerParam() > max_pin_for_downscaling_pion) { - fillTrackTable(collision, neg, static_cast(o2::aod::pwgem::dilepton::PID_Label::kPion), static_cast(o2::aod::pwgem::dilepton::Track_Type::kSecondary), false); + fillTrackTable(collision, neg, static_cast(o2::aod::pwgem::dilepton::ml::PID_Label::kPion), static_cast(o2::aod::pwgem::dilepton::ml::Track_Type::kSecondary), false); } } } @@ -735,7 +770,7 @@ struct TreeCreatorElectronMLDDA { registry.fill(HIST("V0/hMassLambda"), v0.mLambda()); if (v0cuts.cfg_min_mass_lambda < v0.mLambda() && v0.mLambda() < v0cuts.cfg_max_mass_lambda) { if (dist01(engine) < downscaling_proton || pos.tpcInnerParam() > max_pin_for_downscaling_proton) { - fillTrackTable(collision, pos, static_cast(o2::aod::pwgem::dilepton::PID_Label::kProton), static_cast(o2::aod::pwgem::dilepton::Track_Type::kSecondary), false); + fillTrackTable(collision, pos, static_cast(o2::aod::pwgem::dilepton::ml::PID_Label::kProton), static_cast(o2::aod::pwgem::dilepton::ml::Track_Type::kSecondary), false); } registry.fill(HIST("V0/hTPCdEdx_P_Pr"), pos.tpcInnerParam(), pos.tpcSignal()); registry.fill(HIST("V0/hTOFbeta_P_Pr"), pos.tpcInnerParam(), pos.beta()); @@ -745,7 +780,7 @@ struct TreeCreatorElectronMLDDA { registry.fill(HIST("V0/hMassAntiLambda"), v0.mAntiLambda()); if (v0cuts.cfg_min_mass_lambda < v0.mAntiLambda() && v0.mAntiLambda() < v0cuts.cfg_max_mass_lambda) { if (dist01(engine) < downscaling_proton || neg.tpcInnerParam() > max_pin_for_downscaling_proton) { - fillTrackTable(collision, neg, static_cast(o2::aod::pwgem::dilepton::PID_Label::kProton), static_cast(o2::aod::pwgem::dilepton::Track_Type::kSecondary), false); + fillTrackTable(collision, neg, static_cast(o2::aod::pwgem::dilepton::ml::PID_Label::kProton), static_cast(o2::aod::pwgem::dilepton::ml::Track_Type::kSecondary), false); } registry.fill(HIST("V0/hTPCdEdx_P_Pr"), neg.tpcInnerParam(), neg.tpcSignal()); registry.fill(HIST("V0/hTOFbeta_P_Pr"), neg.tpcInnerParam(), neg.beta()); @@ -757,10 +792,10 @@ struct TreeCreatorElectronMLDDA { registry.fill(HIST("V0/hMassGamma_Rxy"), v0.v0radius(), v0.mGamma()); if ((v0cuts.cfg_min_mass_photon < v0.mGamma() && v0.mGamma() < v0cuts.cfg_max_mass_photon)) { if (dist01(engine) < downscaling_electron || pos.tpcInnerParam() > max_pin_for_downscaling_electron) { - fillTrackTable(collision, pos, static_cast(o2::aod::pwgem::dilepton::PID_Label::kElectron), static_cast(o2::aod::pwgem::dilepton::Track_Type::kSecondary), false); + fillTrackTable(collision, pos, static_cast(o2::aod::pwgem::dilepton::ml::PID_Label::kElectron), static_cast(o2::aod::pwgem::dilepton::ml::Track_Type::kSecondary), false); } if (dist01(engine) < downscaling_electron || neg.tpcInnerParam() > max_pin_for_downscaling_electron) { - fillTrackTable(collision, neg, static_cast(o2::aod::pwgem::dilepton::PID_Label::kElectron), static_cast(o2::aod::pwgem::dilepton::Track_Type::kSecondary), false); + fillTrackTable(collision, neg, static_cast(o2::aod::pwgem::dilepton::ml::PID_Label::kElectron), static_cast(o2::aod::pwgem::dilepton::ml::Track_Type::kSecondary), false); } registry.fill(HIST("V0/hTPCdEdx_P_El"), neg.tpcInnerParam(), neg.tpcSignal()); registry.fill(HIST("V0/hTOFbeta_P_El"), neg.tpcInnerParam(), neg.beta()); @@ -849,59 +884,61 @@ struct TreeCreatorElectronMLDDA { registry.fill(HIST("V0/hTPCdEdx_P_Ka"), bachelor.tpcInnerParam(), bachelor.tpcSignal()); registry.fill(HIST("V0/hTOFbeta_P_Ka"), bachelor.tpcInnerParam(), bachelor.beta()); if (dist01(engine) < downscaling_kaon || bachelor.tpcInnerParam() > max_pin_for_downscaling_kaon) { - fillTrackTable(collision, bachelor, static_cast(o2::aod::pwgem::dilepton::PID_Label::kKaon), static_cast(o2::aod::pwgem::dilepton::Track_Type::kPrimary), false); + fillTrackTable(collision, bachelor, static_cast(o2::aod::pwgem::dilepton::ml::PID_Label::kKaon), static_cast(o2::aod::pwgem::dilepton::ml::Track_Type::kPrimary), false); } } } } // end of cascade loop - std::array ppos{0, 0, 0}; - std::array pneg{0, 0, 0}; + if (downscaling_electron_primary > 0.0) { + std::array ppos{0, 0, 0}; + std::array pneg{0, 0, 0}; - // for electron sample for validation - auto posTracks_per_coll = posTracks->sliceByCached(o2::aod::track::collisionId, collision.globalIndex(), cache); - auto negTracks_per_coll = negTracks->sliceByCached(o2::aod::track::collisionId, collision.globalIndex(), cache); - for (const auto& [pos, neg] : combinations(CombinationsFullIndexPolicy(posTracks_per_coll, negTracks_per_coll))) { - if (!isElectron(pos) || !isElectron(neg)) { - continue; - } - if (!isSelectedTrack(collision, pos) || !isSelectedTrack(collision, neg)) { - continue; - } + // for electron sample for validation + auto posTracks_per_coll = posTracks->sliceByCached(o2::aod::track::collisionId, collision.globalIndex(), cache); + auto negTracks_per_coll = negTracks->sliceByCached(o2::aod::track::collisionId, collision.globalIndex(), cache); + for (const auto& [pos, neg] : combinations(CombinationsFullIndexPolicy(posTracks_per_coll, negTracks_per_coll))) { + if (!isElectron(pos) || !isElectron(neg)) { + continue; + } + if (!isSelectedTrack(collision, pos) || !isSelectedTrack(collision, neg)) { + continue; + } - auto posParCov = getTrackParCov(pos); - posParCov.setPID(pos.pidForTracking()); - 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, posParCov, 2.f, matCorr, &mDcaInfoCov); - getPxPyPz(posParCov, ppos); - - auto negParCov = getTrackParCov(neg); - negParCov.setPID(pos.pidForTracking()); - 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, negParCov, 2.f, matCorr, &mDcaInfoCov); - getPxPyPz(negParCov, pneg); - - ROOT::Math::PtEtaPhiMVector v1(negParCov.getPt(), negParCov.getEta(), negParCov.getPhi() > 0.f ? negParCov.getPhi() : negParCov.getPhi() + 2 * M_PI, o2::constants::physics::MassElectron); - ROOT::Math::PtEtaPhiMVector v2(posParCov.getPt(), posParCov.getEta(), posParCov.getPhi() > 0.f ? posParCov.getPhi() : posParCov.getPhi() + 2 * M_PI, o2::constants::physics::MassElectron); - ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; - float phiv = o2::aod::pwgem::dilepton::utils::pairutil::getPhivPair(ppos[0], ppos[1], ppos[2], pneg[0], pneg[1], pneg[2], pos.sign(), neg.sign(), d_bz); - registry.fill(HIST("hMvsPhiV"), phiv, v12.M()); - - if ((dalitzcuts.cfg_min_mass_ee < v12.M() && v12.M() < dalitzcuts.cfg_max_mass_ee) && (dalitzcuts.cfg_min_phiv_ee < phiv && phiv < dalitzcuts.cfg_max_phiv_ee)) { // ee from pi0 dalitz decay is found. - if (isElectronTight(pos) && isElectron(neg)) { - if (dist01(engine) < downscaling_electron_primary || neg.tpcInnerParam() > max_pin_for_downscaling_electron_primary) { - fillTrackTable(collision, neg, static_cast(o2::aod::pwgem::dilepton::PID_Label::kElectron), static_cast(o2::aod::pwgem::dilepton::Track_Type::kPrimary), true); // primary electron candidates + auto posParCov = getTrackParCov(pos); + posParCov.setPID(pos.pidForTracking()); + 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, posParCov, 2.f, matCorr, &mDcaInfoCov); + getPxPyPz(posParCov, ppos); + + auto negParCov = getTrackParCov(neg); + negParCov.setPID(pos.pidForTracking()); + 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, negParCov, 2.f, matCorr, &mDcaInfoCov); + getPxPyPz(negParCov, pneg); + + ROOT::Math::PtEtaPhiMVector v1(negParCov.getPt(), negParCov.getEta(), negParCov.getPhi() > 0.f ? negParCov.getPhi() : negParCov.getPhi() + 2 * M_PI, o2::constants::physics::MassElectron); + ROOT::Math::PtEtaPhiMVector v2(posParCov.getPt(), posParCov.getEta(), posParCov.getPhi() > 0.f ? posParCov.getPhi() : posParCov.getPhi() + 2 * M_PI, o2::constants::physics::MassElectron); + ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; + float phiv = o2::aod::pwgem::dilepton::utils::pairutil::getPhivPair(ppos[0], ppos[1], ppos[2], pneg[0], pneg[1], pneg[2], pos.sign(), neg.sign(), d_bz); + registry.fill(HIST("hMvsPhiV"), phiv, v12.M()); + + if ((dalitzcuts.cfg_min_mass_ee < v12.M() && v12.M() < dalitzcuts.cfg_max_mass_ee) && (dalitzcuts.cfg_min_phiv_ee < phiv && phiv < dalitzcuts.cfg_max_phiv_ee)) { // ee from pi0 dalitz decay is found. + if (isElectronTight(pos) && isElectron(neg)) { + if (dist01(engine) < downscaling_electron_primary || neg.tpcInnerParam() > max_pin_for_downscaling_electron_primary) { + fillTrackTable(collision, neg, static_cast(o2::aod::pwgem::dilepton::ml::PID_Label::kElectron), static_cast(o2::aod::pwgem::dilepton::ml::Track_Type::kPrimary), true); // primary electron candidates + } } - } - if (isElectron(pos) && isElectronTight(neg)) { - if (dist01(engine) < downscaling_electron_primary || pos.tpcInnerParam() > max_pin_for_downscaling_electron_primary) { - fillTrackTable(collision, pos, static_cast(o2::aod::pwgem::dilepton::PID_Label::kElectron), static_cast(o2::aod::pwgem::dilepton::Track_Type::kPrimary), true); // primary electron candidates + if (isElectron(pos) && isElectronTight(neg)) { + if (dist01(engine) < downscaling_electron_primary || pos.tpcInnerParam() > max_pin_for_downscaling_electron_primary) { + fillTrackTable(collision, pos, static_cast(o2::aod::pwgem::dilepton::ml::PID_Label::kElectron), static_cast(o2::aod::pwgem::dilepton::ml::Track_Type::kPrimary), true); // primary electron candidates + } } } - } - } // end of ULS pair loop + } // end of ULS pair loop + } } // end of collision loop stored_trackIds.clear(); @@ -920,30 +957,30 @@ struct MLTrackQC { HistogramRegistry registry{ "registry", { - {"hTPCdEdx_P_All", "TPC dE/dx vs. p;p^{ITS-TPC} (GeV/c);TPC dE/dx", {HistType::kTH2F, {{500, 0.f, 5.f}, {200, 0, 200}}}}, - {"hTOFbeta_P_All", "TOF beta vs. p;p^{ITS-TPC} (GeV/c);TOF #beta", {HistType::kTH2F, {{500, 0.f, 5.f}, {220, 0.0, 1.1}}}}, - {"hITSobClusterSize_P_All", "mean ITSob cluster size vs. p;p^{ITS-TPC} (GeV/c); #times cos(#lambda)", {HistType::kTH2F, {{500, 0.f, 5.f}, {150, 0.0, 15}}}}, - {"hTPCdEdx_P_Electron", "TPC dE/dx vs. p;p^{ITS-TPC} (GeV/c);TPC dE/dx", {HistType::kTH2F, {{500, 0.f, 5.f}, {200, 0, 200}}}}, - {"hTOFbeta_P_Electron", "TOF beta vs. p;p^{ITS-TPC} (GeV/c);TOF #beta", {HistType::kTH2F, {{500, 0.f, 5.f}, {220, 0.0, 1.1}}}}, - {"hITSobClusterSize_P_Electron", "mean ITSob cluster size vs. p;p^{ITS-TPC} (GeV/c); #times cos(#lambda)", {HistType::kTH2F, {{500, 0.f, 5.f}, {150, 0.0, 15}}}}, - {"hTPCdEdx_P_Pion", "TPC dE/dx vs. p;p^{ITS-TPC} (GeV/c);TPC dE/dx", {HistType::kTH2F, {{500, 0.f, 5.f}, {200, 0, 200}}}}, - {"hTOFbeta_P_Pion", "TOF beta vs. p;p^{ITS-TPC} (GeV/c);TOF #beta", {HistType::kTH2F, {{500, 0.f, 5.f}, {220, 0.0, 1.1}}}}, - {"hITSobClusterSize_P_Pion", "mean ITSob cluster size vs. p;p^{ITS-TPC} (GeV/c); #times cos(#lambda)", {HistType::kTH2F, {{500, 0.f, 5.f}, {150, 0.0, 15}}}}, - {"hTPCdEdx_P_Kaon", "TPC dE/dx vs. p;p^{ITS-TPC} (GeV/c);TPC dE/dx", {HistType::kTH2F, {{500, 0.f, 5.f}, {200, 0, 200}}}}, - {"hTOFbeta_P_Kaon", "TOF beta vs. p;p^{ITS-TPC} (GeV/c);TOF #beta", {HistType::kTH2F, {{500, 0.f, 5.f}, {220, 0.0, 1.1}}}}, - {"hITSobClusterSize_P_Kaon", "mean ITSob cluster size vs. p;p^{ITS-TPC} (GeV/c); #times cos(#lambda)", {HistType::kTH2F, {{500, 0.f, 5.f}, {150, 0.0, 15}}}}, - {"hTPCdEdx_P_Proton", "TPC dE/dx vs. p;p^{ITS-TPC} (GeV/c);TPC dE/dx", {HistType::kTH2F, {{500, 0.f, 5.f}, {200, 0, 200}}}}, - {"hTOFbeta_P_Proton", "TOF beta vs. p;p^{ITS-TPC} (GeV/c);TOF #beta", {HistType::kTH2F, {{500, 0.f, 5.f}, {220, 0.0, 1.1}}}}, - {"hITSobClusterSize_P_Proton", "mean ITSob cluster size vs. p;p^{ITS-TPC} (GeV/c); #times cos(#lambda)", {HistType::kTH2F, {{500, 0.f, 5.f}, {150, 0.0, 15}}}}, - - {"hTPCNsigmaEl_P", "TPC n#sigma_{e} vs. p;p^{ITS-TPC} (GeV/c);n #sigma_{e}^{TPC}", {HistType::kTH2F, {{500, 0.f, 5.f}, {100, -5, +5}}}}, - {"hTPCNsigmaPi_P", "TPC n#sigma_{#pi} vs. p;p^{ITS-TPC} (GeV/c);n #sigma_{#pi}^{TPC}", {HistType::kTH2F, {{500, 0.f, 5.f}, {100, -5, +5}}}}, - {"hTPCNsigmaKa_P", "TPC n#sigma_{K} vs. p;p^{ITS-TPC} (GeV/c);n #sigma_{K}^{TPC}", {HistType::kTH2F, {{500, 0.f, 5.f}, {100, -5, +5}}}}, - {"hTPCNsigmaPr_P", "TPC n#sigma_{p} vs. p;p^{ITS-TPC} (GeV/c);n #sigma_{p}^{TPC}", {HistType::kTH2F, {{500, 0.f, 5.f}, {100, -5, +5}}}}, - {"hTOFNsigmaEl_P", "TOF n#sigma_{e} vs. p;p^{ITS-TOF} (GeV/c);n #sigma_{e}^{TOF}", {HistType::kTH2F, {{500, 0.f, 5.f}, {100, -5, +5}}}}, - {"hTOFNsigmaPi_P", "TOF n#sigma_{#pi} vs. p;p^{ITS-TOF} (GeV/c);n #sigma_{#pi}^{TOF}", {HistType::kTH2F, {{500, 0.f, 5.f}, {100, -5, +5}}}}, - {"hTOFNsigmaKa_P", "TOF n#sigma_{K} vs. p;p^{ITS-TOF} (GeV/c);n #sigma_{K}^{TOF}", {HistType::kTH2F, {{500, 0.f, 5.f}, {100, -5, +5}}}}, - {"hTOFNsigmaPr_P", "TOF n#sigma_{p} vs. p;p^{ITS-TOF} (GeV/c);n #sigma_{p}^{TOF}", {HistType::kTH2F, {{500, 0.f, 5.f}, {100, -5, +5}}}}, + {"hTPCdEdx_P_All", "TPC dE/dx vs. p;p_{pv} (GeV/c);TPC dE/dx", {HistType::kTH2F, {{500, 0.f, 5.f}, {200, 0, 200}}}}, + {"hTOFbeta_P_All", "TOF beta vs. p;p_{pv} (GeV/c);TOF #beta", {HistType::kTH2F, {{500, 0.f, 5.f}, {220, 0.0, 1.1}}}}, + {"hITSobClusterSize_P_All", "mean ITSob cluster size vs. p;p_{pv} (GeV/c); #times cos(#lambda)", {HistType::kTH2F, {{500, 0.f, 5.f}, {150, 0.0, 15}}}}, + {"hTPCdEdx_P_Electron", "TPC dE/dx vs. p;p_{pv} (GeV/c);TPC dE/dx", {HistType::kTH2F, {{500, 0.f, 5.f}, {200, 0, 200}}}}, + {"hTOFbeta_P_Electron", "TOF beta vs. p;p_{pv} (GeV/c);TOF #beta", {HistType::kTH2F, {{500, 0.f, 5.f}, {220, 0.0, 1.1}}}}, + {"hITSobClusterSize_P_Electron", "mean ITSob cluster size vs. p;p_{pv} (GeV/c); #times cos(#lambda)", {HistType::kTH2F, {{500, 0.f, 5.f}, {150, 0.0, 15}}}}, + {"hTPCdEdx_P_Pion", "TPC dE/dx vs. p;p_{pv} (GeV/c);TPC dE/dx", {HistType::kTH2F, {{500, 0.f, 5.f}, {200, 0, 200}}}}, + {"hTOFbeta_P_Pion", "TOF beta vs. p;p_{pv} (GeV/c);TOF #beta", {HistType::kTH2F, {{500, 0.f, 5.f}, {220, 0.0, 1.1}}}}, + {"hITSobClusterSize_P_Pion", "mean ITSob cluster size vs. p;p_{pv} (GeV/c); #times cos(#lambda)", {HistType::kTH2F, {{500, 0.f, 5.f}, {150, 0.0, 15}}}}, + {"hTPCdEdx_P_Kaon", "TPC dE/dx vs. p;p_{pv} (GeV/c);TPC dE/dx", {HistType::kTH2F, {{500, 0.f, 5.f}, {200, 0, 200}}}}, + {"hTOFbeta_P_Kaon", "TOF beta vs. p;p_{pv} (GeV/c);TOF #beta", {HistType::kTH2F, {{500, 0.f, 5.f}, {220, 0.0, 1.1}}}}, + {"hITSobClusterSize_P_Kaon", "mean ITSob cluster size vs. p;p_{pv} (GeV/c); #times cos(#lambda)", {HistType::kTH2F, {{500, 0.f, 5.f}, {150, 0.0, 15}}}}, + {"hTPCdEdx_P_Proton", "TPC dE/dx vs. p;p_{pv} (GeV/c);TPC dE/dx", {HistType::kTH2F, {{500, 0.f, 5.f}, {200, 0, 200}}}}, + {"hTOFbeta_P_Proton", "TOF beta vs. p;p_{pv} (GeV/c);TOF #beta", {HistType::kTH2F, {{500, 0.f, 5.f}, {220, 0.0, 1.1}}}}, + {"hITSobClusterSize_P_Proton", "mean ITSob cluster size vs. p;p_{pv} (GeV/c); #times cos(#lambda)", {HistType::kTH2F, {{500, 0.f, 5.f}, {150, 0.0, 15}}}}, + + {"hTPCNsigmaEl_P", "TPC n#sigma_{e} vs. p;p_{pv} (GeV/c);n #sigma_{e}^{TPC}", {HistType::kTH2F, {{500, 0.f, 5.f}, {100, -5, +5}}}}, + {"hTPCNsigmaPi_P", "TPC n#sigma_{#pi} vs. p;p_{pv} (GeV/c);n #sigma_{#pi}^{TPC}", {HistType::kTH2F, {{500, 0.f, 5.f}, {100, -5, +5}}}}, + {"hTPCNsigmaKa_P", "TPC n#sigma_{K} vs. p;p_{pv} (GeV/c);n #sigma_{K}^{TPC}", {HistType::kTH2F, {{500, 0.f, 5.f}, {100, -5, +5}}}}, + {"hTPCNsigmaPr_P", "TPC n#sigma_{p} vs. p;p_{pv} (GeV/c);n #sigma_{p}^{TPC}", {HistType::kTH2F, {{500, 0.f, 5.f}, {100, -5, +5}}}}, + {"hTOFNsigmaEl_P", "TOF n#sigma_{e} vs. p;p_{pv} (GeV/c);n #sigma_{e}^{TOF}", {HistType::kTH2F, {{500, 0.f, 5.f}, {100, -5, +5}}}}, + {"hTOFNsigmaPi_P", "TOF n#sigma_{#pi} vs. p;p_{pv} (GeV/c);n #sigma_{#pi}^{TOF}", {HistType::kTH2F, {{500, 0.f, 5.f}, {100, -5, +5}}}}, + {"hTOFNsigmaKa_P", "TOF n#sigma_{K} vs. p;p_{pv} (GeV/c);n #sigma_{K}^{TOF}", {HistType::kTH2F, {{500, 0.f, 5.f}, {100, -5, +5}}}}, + {"hTOFNsigmaPr_P", "TOF n#sigma_{p} vs. p;p_{pv} (GeV/c);n #sigma_{p}^{TOF}", {HistType::kTH2F, {{500, 0.f, 5.f}, {100, -5, +5}}}}, }, }; @@ -953,25 +990,25 @@ struct MLTrackQC { registry.fill(HIST("hTPCdEdx_P_All"), track.p(), track.tpcSignal()); registry.fill(HIST("hTOFbeta_P_All"), track.p(), track.beta()); registry.fill(HIST("hITSobClusterSize_P_All"), track.p(), track.meanClusterSizeITSob() * std::cos(std::atan(track.tgl()))); - if (track.pidlabel() == static_cast(o2::aod::pwgem::dilepton::PID_Label::kElectron)) { + if (track.pidlabel() == static_cast(o2::aod::pwgem::dilepton::ml::PID_Label::kElectron)) { registry.fill(HIST("hTPCdEdx_P_Electron"), track.p(), track.tpcSignal()); registry.fill(HIST("hTOFbeta_P_Electron"), track.p(), track.beta()); registry.fill(HIST("hITSobClusterSize_P_Electron"), track.p(), track.meanClusterSizeITSob() * std::cos(std::atan(track.tgl()))); registry.fill(HIST("hTPCNsigmaEl_P"), track.p(), track.tpcNSigmaEl()); registry.fill(HIST("hTOFNsigmaEl_P"), track.p(), track.tofNSigmaEl()); - } else if (track.pidlabel() == static_cast(o2::aod::pwgem::dilepton::PID_Label::kPion)) { + } else if (track.pidlabel() == static_cast(o2::aod::pwgem::dilepton::ml::PID_Label::kPion)) { registry.fill(HIST("hTPCdEdx_P_Pion"), track.p(), track.tpcSignal()); registry.fill(HIST("hTOFbeta_P_Pion"), track.p(), track.beta()); registry.fill(HIST("hITSobClusterSize_P_Pion"), track.p(), track.meanClusterSizeITSob() * std::cos(std::atan(track.tgl()))); registry.fill(HIST("hTPCNsigmaPi_P"), track.p(), track.tpcNSigmaPi()); registry.fill(HIST("hTOFNsigmaPi_P"), track.p(), track.tofNSigmaPi()); - } else if (track.pidlabel() == static_cast(o2::aod::pwgem::dilepton::PID_Label::kKaon)) { + } else if (track.pidlabel() == static_cast(o2::aod::pwgem::dilepton::ml::PID_Label::kKaon)) { registry.fill(HIST("hTPCdEdx_P_Kaon"), track.p(), track.tpcSignal()); registry.fill(HIST("hTOFbeta_P_Kaon"), track.p(), track.beta()); registry.fill(HIST("hITSobClusterSize_P_Kaon"), track.p(), track.meanClusterSizeITSob() * std::cos(std::atan(track.tgl()))); registry.fill(HIST("hTPCNsigmaKa_P"), track.p(), track.tpcNSigmaKa()); registry.fill(HIST("hTOFNsigmaKa_P"), track.p(), track.tofNSigmaKa()); - } else if (track.pidlabel() == static_cast(o2::aod::pwgem::dilepton::PID_Label::kProton)) { + } else if (track.pidlabel() == static_cast(o2::aod::pwgem::dilepton::ml::PID_Label::kProton)) { registry.fill(HIST("hTPCdEdx_P_Proton"), track.p(), track.tpcSignal()); registry.fill(HIST("hTOFbeta_P_Proton"), track.p(), track.beta()); registry.fill(HIST("hITSobClusterSize_P_Proton"), track.p(), track.meanClusterSizeITSob() * std::cos(std::atan(track.tgl()))); From b1c4a26551040f0adad1989647d5b7e0bc90c7c9 Mon Sep 17 00:00:00 2001 From: nzardosh Date: Sun, 22 Jun 2025 01:56:47 +0100 Subject: [PATCH 175/871] [PWGJE] Adding Outlier rejection task for MC (#11720) --- PWGJE/DataModel/JetReducedData.h | 12 +- PWGJE/TableProducer/CMakeLists.txt | 5 + PWGJE/TableProducer/derivedDataProducer.cxx | 4 +- PWGJE/TableProducer/derivedDataWriter.cxx | 2 +- PWGJE/TableProducer/mcOutlierRejector.cxx | 132 ++++++++++++++++++++ 5 files changed, 151 insertions(+), 4 deletions(-) create mode 100644 PWGJE/TableProducer/mcOutlierRejector.cxx diff --git a/PWGJE/DataModel/JetReducedData.h b/PWGJE/DataModel/JetReducedData.h index 4d5e401fe7d..08fba650bfe 100644 --- a/PWGJE/DataModel/JetReducedData.h +++ b/PWGJE/DataModel/JetReducedData.h @@ -99,6 +99,7 @@ DECLARE_SOA_COLUMN(ReadCountsWithTVXAndZVertexAndSel7KINT7, readCountsWithTVXAnd DECLARE_SOA_COLUMN(ReadCountsWithCustom, readCountsWithCustom, std::vector); DECLARE_SOA_COLUMN(IsAmbiguous, isAmbiguous, bool); DECLARE_SOA_COLUMN(IsEMCALReadout, isEmcalReadout, bool); +DECLARE_SOA_COLUMN(IsOutlier, isOutlier, bool); } // namespace jcollision DECLARE_SOA_TABLE_STAGED(JCollisions, "JCOLLISION", @@ -122,6 +123,9 @@ DECLARE_SOA_TABLE_STAGED(JCollisionMcInfos, "JCOLLISIONMCINFO", jcollision::Weight, jcollision::SubGeneratorId); +DECLARE_SOA_TABLE_STAGED(JCollisionOutliers, "JCOLLISIONOUTLR", + jcollision::IsOutlier); + DECLARE_SOA_TABLE_STAGED(JEMCCollisionLbs, "JEMCCOLLISIONLB", jcollision::IsAmbiguous, jcollision::IsEMCALReadout); @@ -170,6 +174,8 @@ DECLARE_SOA_COLUMN(Accepted, accepted, uint64_t); DECLARE_SOA_COLUMN(Attempted, attempted, uint64_t); DECLARE_SOA_COLUMN(XsectGen, xsectGen, float); DECLARE_SOA_COLUMN(XsectErr, xsectErr, float); +DECLARE_SOA_COLUMN(PtHard, ptHard, float); +DECLARE_SOA_COLUMN(IsOutlier, isOutlier, bool); } // namespace jmccollision DECLARE_SOA_TABLE_STAGED(JMcCollisions, "JMCCOLLISION", o2::soa::Index<>, @@ -181,7 +187,8 @@ DECLARE_SOA_TABLE_STAGED(JMcCollisions, "JMCCOLLISION", jmccollision::Accepted, jmccollision::Attempted, jmccollision::XsectGen, - jmccollision::XsectErr); + jmccollision::XsectErr, + jmccollision::PtHard); using JMcCollision = JMcCollisions::iterator; using StoredJMcCollision = StoredJMcCollisions::iterator; @@ -197,6 +204,9 @@ DECLARE_SOA_INDEX_COLUMN(JMcCollision, mcCollision); DECLARE_SOA_TABLE_STAGED(JMcCollisionLbs, "JMCCOLLISIONLB", jmccollisionlb::JMcCollisionId); +DECLARE_SOA_TABLE_STAGED(JMcCollisionOutliers, "JMCCOLLISIONOUTLR", + jmccollision::IsOutlier); + namespace jtrack { DECLARE_SOA_INDEX_COLUMN(JCollision, collision); diff --git a/PWGJE/TableProducer/CMakeLists.txt b/PWGJE/TableProducer/CMakeLists.txt index 2a82a7f0466..5413eef70db 100644 --- a/PWGJE/TableProducer/CMakeLists.txt +++ b/PWGJE/TableProducer/CMakeLists.txt @@ -53,6 +53,11 @@ o2physics_add_dpl_workflow(jet-eventweight-mcp PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(mc-outlier-rejector + SOURCES mcOutlierRejector.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(jet-track-derived SOURCES jetTrackDerived.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore diff --git a/PWGJE/TableProducer/derivedDataProducer.cxx b/PWGJE/TableProducer/derivedDataProducer.cxx index a759b76a2b1..d7684932bad 100644 --- a/PWGJE/TableProducer/derivedDataProducer.cxx +++ b/PWGJE/TableProducer/derivedDataProducer.cxx @@ -256,14 +256,14 @@ struct JetDerivedDataProducerTask { void processMcCollisions(aod::McCollision const& mcCollision) { - products.jMcCollisionsTable(mcCollision.posX(), mcCollision.posY(), mcCollision.posZ(), mcCollision.weight(), mcCollision.getSubGeneratorId(), 1, 1, 1.0, 1.0); + products.jMcCollisionsTable(mcCollision.posX(), mcCollision.posY(), mcCollision.posZ(), mcCollision.weight(), mcCollision.getSubGeneratorId(), 1, 1, 1.0, 1.0, 999.0); products.jMcCollisionsParentIndexTable(mcCollision.globalIndex()); } PROCESS_SWITCH(JetDerivedDataProducerTask, processMcCollisions, "produces derived MC collision table", false); void processMcCollisionsWithXsection(soa::Join::iterator const& mcCollision) { - products.jMcCollisionsTable(mcCollision.posX(), mcCollision.posY(), mcCollision.posZ(), mcCollision.weight(), mcCollision.getSubGeneratorId(), mcCollision.accepted(), mcCollision.attempted(), mcCollision.xsectGen(), mcCollision.xsectErr()); + products.jMcCollisionsTable(mcCollision.posX(), mcCollision.posY(), mcCollision.posZ(), mcCollision.weight(), mcCollision.getSubGeneratorId(), mcCollision.accepted(), mcCollision.attempted(), mcCollision.xsectGen(), mcCollision.xsectErr(), mcCollision.ptHard()); products.jMcCollisionsParentIndexTable(mcCollision.globalIndex()); } PROCESS_SWITCH(JetDerivedDataProducerTask, processMcCollisionsWithXsection, "produces derived MC collision table with cross section information", false); diff --git a/PWGJE/TableProducer/derivedDataWriter.cxx b/PWGJE/TableProducer/derivedDataWriter.cxx index 2742c848f83..a1d2346fd7d 100644 --- a/PWGJE/TableProducer/derivedDataWriter.cxx +++ b/PWGJE/TableProducer/derivedDataWriter.cxx @@ -432,7 +432,7 @@ struct JetDerivedDataWriter { mcCollisionMapping.resize(mcCollisions.size(), -1); for (auto const& mcCollision : mcCollisions) { if (mcCollision.isMcCollisionSelected()) { - products.storedJMcCollisionsTable(mcCollision.posX(), mcCollision.posY(), mcCollision.posZ(), mcCollision.weight(), mcCollision.subGeneratorId(), mcCollision.accepted(), mcCollision.attempted(), mcCollision.xsectGen(), mcCollision.xsectErr()); + products.storedJMcCollisionsTable(mcCollision.posX(), mcCollision.posY(), mcCollision.posZ(), mcCollision.weight(), mcCollision.subGeneratorId(), mcCollision.accepted(), mcCollision.attempted(), mcCollision.xsectGen(), mcCollision.xsectErr(), mcCollision.ptHard()); products.storedJMcCollisionsParentIndexTable(mcCollision.mcCollisionId()); mcCollisionMapping[mcCollision.globalIndex()] = products.storedJMcCollisionsTable.lastIndex(); } diff --git a/PWGJE/TableProducer/mcOutlierRejector.cxx b/PWGJE/TableProducer/mcOutlierRejector.cxx new file mode 100644 index 00000000000..427a5afdfad --- /dev/null +++ b/PWGJE/TableProducer/mcOutlierRejector.cxx @@ -0,0 +1,132 @@ +// 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. + +// Task to produce a table joinable to the jcollision table which contains an outlier rejector +// +/// \author Nima Zardoshti + +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" + +#include "Framework/ASoA.h" +#include "Framework/AnalysisTask.h" +#include "Framework/O2DatabasePDGPlugin.h" +#include +#include +#include +#include + +#include + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +struct McOutlierRejectorTask { + Produces collisionOutliers; + Produces mcCollisionOutliers; + + Configurable checkmcCollisionForCollision{"checkmcCollisionForCollision", true, "additionally reject collision based on mcCollision"}; + Configurable ptHatMax{"ptHatMax", 4.0, "maximum factor of pt hat the leading jet in the event is allowed"}; + + std::vector collisionFlag; + std::vector mcCollisionFlag; + + void processSetupCollisionSelection(aod::JCollisions const& collisions) + { + collisionFlag.clear(); + collisionFlag.resize(collisions.size(), false); + } + PROCESS_SWITCH(McOutlierRejectorTask, processSetupCollisionSelection, "Setup collision processing", true); + + void processSetupMcCollisionSelection(aod::JMcCollisions const& mcCollisions) + { + mcCollisionFlag.clear(); + mcCollisionFlag.resize(mcCollisions.size(), false); + } + PROCESS_SWITCH(McOutlierRejectorTask, processSetupMcCollisionSelection, "Setup MC Collision processing", true); + + template + void collisionSelection(int32_t collisionIndex, T const& selectionObjects, float ptHard, std::vector& flagArray) + { + + if (selectionObjects.size() != 0) { + float maxSelectionObjectPt = 0.0; + if constexpr (std::is_same_v, aod::JetTracks> || std::is_same_v, aod::JetParticles>) { + for (auto selectionObject : selectionObjects) { + if (selectionObject.pt() > maxSelectionObjectPt) { + maxSelectionObjectPt = selectionObject.pt(); + } + } + } else { + maxSelectionObjectPt = selectionObjects.iteratorAt(0).pt(); + } + + if (maxSelectionObjectPt > ptHatMax * ptHard) { + flagArray[collisionIndex] = true; // Currently if running multiple different jet finders, then a single type of jet can veto an event for others. Decide if this is the best way + } + } + } + + template + void processSelectionObjects(aod::JetCollisionMCD const& collision, T const& selectionObjects, aod::JetMcCollisions const&) + { + auto mcCollision = collision.mcCollision_as(); + collisionSelection(collision.globalIndex(), selectionObjects, mcCollision.ptHard(), collisionFlag); + } + + template + void processSelectionMcObjects(aod::JetMcCollision const& mcCollision, T const& selectionMcObjects) + { + collisionSelection(mcCollision.globalIndex(), selectionMcObjects, mcCollision.ptHard(), mcCollisionFlag); + } + + PROCESS_SWITCH_FULL(McOutlierRejectorTask, processSelectionObjects, processSelectingChargedMCDetectorLevelJets, "process mc detector level charged jets", true); + PROCESS_SWITCH_FULL(McOutlierRejectorTask, processSelectionObjects, processSelectingNeutralMCDetectorLevelJets, "process mc detector level neutral jets", false); + PROCESS_SWITCH_FULL(McOutlierRejectorTask, processSelectionObjects, processSelectingFullMCDetectorLevelJets, "process mc detector level full jets", false); + PROCESS_SWITCH_FULL(McOutlierRejectorTask, processSelectionObjects, processSelectingD0ChargedMCDetectorLevelJets, "process mc detector level D0 charged jets", false); + PROCESS_SWITCH_FULL(McOutlierRejectorTask, processSelectionObjects, processSelectingDplusChargedMCDetectorLevelJets, "process mc detector level Dplus charged jets", false); + // PROCESS_SWITCH_FULL(McOutlierRejectorTask, processSelectionObjects, processSelectingDstarChargedMCDetectorLevelJets, "process mc detector level Dstar charged jets", false); + PROCESS_SWITCH_FULL(McOutlierRejectorTask, processSelectionObjects, processSelectingLcChargedMCDetectorLevelJets, "process mc detector level Lc charged jets", false); + // PROCESS_SWITCH_FULL(McOutlierRejectorTask, processSelectionObjects, processSelectingB0ChargedMCDetectorLevelJets, "process mc detector level B0 charged jets", false); + PROCESS_SWITCH_FULL(McOutlierRejectorTask, processSelectionObjects, processSelectingBplusChargedMCDetectorLevelJets, "process mc detector level Bplus charged jets", false); + PROCESS_SWITCH_FULL(McOutlierRejectorTask, processSelectionObjects, processSelectingDielectronChargedMCDetectorLevelJets, "process mc detector level Dielectron charged jets", false); + PROCESS_SWITCH_FULL(McOutlierRejectorTask, processSelectionObjects, processSelectingTracks, "process tracks", false); + PROCESS_SWITCH_FULL(McOutlierRejectorTask, processSelectionMcObjects, processSelectingChargedMCParticleLevelJets, "process mc particle level charged jets", true); + PROCESS_SWITCH_FULL(McOutlierRejectorTask, processSelectionMcObjects, processSelectingNeutralMCParticleLevelJets, "process mc particle level neutral jets", false); + PROCESS_SWITCH_FULL(McOutlierRejectorTask, processSelectionMcObjects, processSelectingFullMCParticleLevelJets, "process mc particle level full jets", false); + PROCESS_SWITCH_FULL(McOutlierRejectorTask, processSelectionMcObjects, processSelectingD0ChargedMCParticleLevelJets, "process mc particle level D0 charged jets", false); + PROCESS_SWITCH_FULL(McOutlierRejectorTask, processSelectionMcObjects, processSelectingDplusChargedMCParticleLevelJets, "process mc particle level Dplus charged jets", false); + // PROCESS_SWITCH_FULL(McOutlierRejectorTask, processSelectionMcObjects, processSelectingDstarChargedMCParticleLevelJets, "process mc particle level Dstar charged jets", false); + PROCESS_SWITCH_FULL(McOutlierRejectorTask, processSelectionMcObjects, processSelectingLcChargedMCParticleLevelJets, "process mc particle level Lc charged jets", false); + // PROCESS_SWITCH_FULL(McOutlierRejectorTask, processSelectionMcObjects, processSelectingB0ChargedMCParticleLevelJets, "process mc particle level B0 charged jets", false); + PROCESS_SWITCH_FULL(McOutlierRejectorTask, processSelectionMcObjects, processSelectingBplusChargedMCParticleLevelJets, "process mc particle level Bplus charged jets", false); + PROCESS_SWITCH_FULL(McOutlierRejectorTask, processSelectionMcObjects, processSelectingDielectronChargedMCParticleLevelJets, "process mc particle level Dielectron charged jets", false); + PROCESS_SWITCH_FULL(McOutlierRejectorTask, processSelectionMcObjects, processSelectingParticles, "process mc particles", false); + + void processStoreCollisionDecision(aod::JetCollisionMCD const& collision) + { + bool rejectCollision = collisionFlag[collision.globalIndex()]; + if (!rejectCollision && checkmcCollisionForCollision && collision.has_mcCollision()) { + rejectCollision = mcCollisionFlag[collision.mcCollisionId()]; + } + collisionOutliers(rejectCollision); + } + PROCESS_SWITCH(McOutlierRejectorTask, processStoreCollisionDecision, "write out decision of rejecting collision", true); + + void processStoreMcCollisionDecision(aod::JetMcCollision const& mcCollision) + { + mcCollisionOutliers(mcCollisionFlag[mcCollision.globalIndex()]); + } + PROCESS_SWITCH(McOutlierRejectorTask, processStoreMcCollisionDecision, "write out decision of rejecting mcCollision", true); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{adaptAnalysisTask(cfgc, TaskName{"mc-outlier-rejector"})}; } From 1ca4757cb6bbac3af1b4a3ec4ccc3c42046d3620 Mon Sep 17 00:00:00 2001 From: Samuele Cattaruzzi <124249902+scattaru@users.noreply.github.com> Date: Sun, 22 Jun 2025 12:40:34 +0200 Subject: [PATCH 176/871] [PWGHF] Adding missing histogram in correlatorDsHadrons (#11722) --- .../HFC/TableProducer/correlatorDsHadrons.cxx | 29 ++++++++++--------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/PWGHF/HFC/TableProducer/correlatorDsHadrons.cxx b/PWGHF/HFC/TableProducer/correlatorDsHadrons.cxx index 5460fede3e9..4a6c458b7e9 100644 --- a/PWGHF/HFC/TableProducer/correlatorDsHadrons.cxx +++ b/PWGHF/HFC/TableProducer/correlatorDsHadrons.cxx @@ -14,13 +14,12 @@ /// \author Grazia Luparello /// \author Samuele Cattaruzzi -#include -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" +#include "PWGHF/Core/HfHelper.h" +#include "PWGHF/Core/SelectorCuts.h" +#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "PWGHF/HFC/DataModel/CorrelationTables.h" +#include "PWGHF/HFC/DataModel/DerivedDataCorrelationTables.h" #include "Common/Core/TrackSelection.h" #include "Common/DataModel/Centrality.h" @@ -28,12 +27,13 @@ #include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "PWGHF/Core/HfHelper.h" -#include "PWGHF/Core/SelectorCuts.h" -#include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" -#include "PWGHF/HFC/DataModel/CorrelationTables.h" -#include "PWGHF/HFC/DataModel/DerivedDataCorrelationTables.h" +#include "CommonConstants/PhysicsConstants.h" +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/runDataProcessing.h" + +#include +#include using namespace o2; using namespace o2::analysis; @@ -233,6 +233,7 @@ struct HfCorrelatorDsHadrons { AxisSpec axisStatus = {15, 0.5, 15.5, "Selection status"}; // Histograms for data analysis + registry.add("hCollisionPoolBin", "Ds candidates collision pool bin", {HistType::kTH1F, {axisPoolBin}}); if (fillHistoData) { registry.add("hPtCand", "Ds candidates pt", {HistType::kTH1F, {axisPtD}}); registry.add("hSelectionStatusDsToKKPi", "Ds candidates selection", {HistType::kTH1F, {axisStatus}}); @@ -249,7 +250,6 @@ struct HfCorrelatorDsHadrons { registry.add("hZVtx", "z vertex", {HistType::kTH1F, {axisPosZ}}); registry.add("hMassDsVsPt", "Ds candidates massVsPt", {HistType::kTH2F, {{axisMassD}, {axisPtD}}}); registry.add("hMassDsData", "Ds candidates mass", {HistType::kTH1F, {axisMassD}}); - registry.add("hCollisionPoolBin", "Ds candidates collision pool bin", {HistType::kTH1F, {axisPoolBin}}); registry.add("hDsPoolBin", "Ds candidates pool bin", {HistType::kTH1F, {axisPoolBin}}); registry.add("hTracksPoolBin", "Particles associated pool bin", {HistType::kTH1F, {axisPoolBin}}); } @@ -291,6 +291,7 @@ struct HfCorrelatorDsHadrons { registry.add("hCorrAllPrimaryPions", "Ds-pion correlations MC Gen", {HistType::kTH3F, {{axisPhi}, {axisPtD}, {axisPtHadron}}}); registry.add("hCorrAllPrimaryKaons", "Ds-kaon correlations MC Gen", {HistType::kTH3F, {{axisPhi}, {axisPtD}, {axisPtHadron}}}); registry.add("hCorrAllPrimaryProtons", "Ds-proton correlations MC Gen", {HistType::kTH3F, {{axisPhi}, {axisPtD}, {axisPtHadron}}}); + registry.add("hFakeCollision", "Fake collision counter", {HistType::kTH1F, {{1, -0.5, 0.5, "n fake coll"}}}); } } From 25e206db787007cdf27d6f7f61be251a20fb72de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dawid=20Karpi=C5=84ski?= <40724893+davkk@users.noreply.github.com> Date: Sun, 22 Jun 2025 12:47:17 +0200 Subject: [PATCH 177/871] [PWGCF/FemtoUniverse] Fix: do swapping also for same particles (#11723) --- .../Tasks/femtoUniversePairTaskTrackTrackExtended.cxx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrackExtended.cxx b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrackExtended.cxx index 852fb802d68..06665491396 100644 --- a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrackExtended.cxx +++ b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrackExtended.cxx @@ -567,7 +567,12 @@ struct FemtoUniversePairTaskTrackTrackExtended { weight *= effCorrection.getWeight(ParticleNo::TWO, p2); } - sameEventCont.setPair(p1, p2, multCol, twotracksconfigs.confUse3D, weight); + if (swpart) + sameEventCont.setPair(p1, p2, multCol, twotracksconfigs.confUse3D, weight); + else + sameEventCont.setPair(p2, p1, multCol, twotracksconfigs.confUse3D, weight); + + swpart = !swpart; } } } From c3c2641d8250058c01d2bf5bff45350443d12ee2 Mon Sep 17 00:00:00 2001 From: hernasab Date: Sun, 22 Jun 2025 11:56:25 -0500 Subject: [PATCH 178/871] [PWGCF] removed obsolete variables and added new variables to process (#11711) Co-authored-by: Sabrina Hernandez --- PWGCF/Flow/Tasks/flowZdcTask.cxx | 179 +++++++++++++++++++++---------- 1 file changed, 125 insertions(+), 54 deletions(-) diff --git a/PWGCF/Flow/Tasks/flowZdcTask.cxx b/PWGCF/Flow/Tasks/flowZdcTask.cxx index 3daec8cf2c7..341b93aaa12 100644 --- a/PWGCF/Flow/Tasks/flowZdcTask.cxx +++ b/PWGCF/Flow/Tasks/flowZdcTask.cxx @@ -22,6 +22,7 @@ #include "Common/DataModel/PIDResponse.h" #include "Common/DataModel/TrackSelectionTables.h" +#include "CommonConstants/MathConstants.h" #include "Framework/ASoAHelpers.h" #include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" @@ -46,6 +47,7 @@ using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; using namespace o2::aod::mult; +using namespace o2::constants::math; using namespace o2::aod::evsel; #define O2_DEFINE_CONFIGURABLE(NAME, TYPE, DEFAULT, HELP) Configurable NAME{#NAME, DEFAULT, HELP}; @@ -54,29 +56,21 @@ struct FlowZdcTask { SliceCache cache; O2_DEFINE_CONFIGURABLE(cfgCutVertex, float, 10.0f, "Accepted z-vertex range") - O2_DEFINE_CONFIGURABLE(cfgCutPtPOIMin, float, 0.2f, "Minimal pT for poi tracks") - O2_DEFINE_CONFIGURABLE(cfgCutPtPOIMax, float, 10.0f, "Maximal pT for poi tracks") O2_DEFINE_CONFIGURABLE(cfgCutPtMin, float, 0.2f, "Minimal pT for ref tracks") O2_DEFINE_CONFIGURABLE(cfgCutPtMax, float, 10.0f, "Maximal pT for ref tracks") O2_DEFINE_CONFIGURABLE(cfgCutEta, float, 0.8f, "Eta range for tracks") O2_DEFINE_CONFIGURABLE(cfgCutChi2prTPCcls, float, 2.5, "Chi2 per TPC clusters") - O2_DEFINE_CONFIGURABLE(cfgUseNch, bool, false, "Use Nch for flow observables") - O2_DEFINE_CONFIGURABLE(cfgNbootstrap, int, 10, "Number of subsamples") O2_DEFINE_CONFIGURABLE(cfgCutDCAz, float, 2, "DCA Z cut") O2_DEFINE_CONFIGURABLE(cfgCutDCAxy, float, 0.2f, "DCA XY cut") - Configurable nBinsPt{"nBinsPt", 500, "N bins in pT histo"}; Configurable eventSelection{"eventSelection", 1, "event selection"}; Configurable maxZp{"maxZp", 3099.5, "Max ZP signal"}; - Configurable minTpcNcrossedRows{"minTpcNcrossedRows", 20, "minTpcNcrossedRows"}; Configurable maxZem{"maxZem", 3099.5, "Max ZEM signal"}; // for ZDC info and analysis Configurable nBinsAmp{"nBinsAmp", 1025, "nbinsAmp"}; - Configurable nBinsFT0Amp{"nBinsFT0Amp", 250000, "nbinsAmp"}; Configurable maxZn{"maxZn", 4099.5, "Max ZN signal"}; Configurable vtxRange{"vtxRange", 10.0f, "Vertex Z range to consider"}; Configurable etaRange{"etaRange", 1.0f, "Eta range to consider"}; - Configurable npvTracksCut{"npvTracksCut", 1.0f, "Apply extra NPVtracks cut"}; // configs for process QA Configurable nBinsNch{"nBinsNch", 2501, "N bins Nch (|eta|<0.8)"}; Configurable nBinsAmpFT0{"nBinsAmpFT0", 100, "N bins FT0 amp"}; @@ -84,7 +78,8 @@ struct FlowZdcTask { Configurable nBinsAmpFV0{"nBinsAmpFV0", 100, "N bins FV0 amp"}; Configurable maxAmpFV0{"maxAmpFV0", 2000, "Max FV0 amp"}; Configurable nBinsZDC{"nBinsZDC", 400, "nBinsZDC"}; - Configurable nBinsZEM{"nBinsZEM", 100, "nBinsZEM"}; + Configurable nBinsZN{"nBinsZN", 400, "N bins ZN"}; + Configurable nBinsZP{"nBinsZP", 160, "N bins ZP"}; Configurable minNch{"minNch", 0, "Min Nch (|eta|<0.8)"}; Configurable maxNch{"maxNch", 2500, "Max Nch (|eta|<0.8)"}; Configurable nBinsTDC{"nBinsTDC", 150, "nbinsTDC"}; @@ -104,6 +99,8 @@ struct FlowZdcTask { Configurable isZEMcut{"isZEMcut", true, "Use ZEM cut?"}; Configurable useMidRapNchSel{"useMidRapNchSel", true, "Use mid-rapidit Nch selection"}; Configurable applyEff{"applyEff", true, "Apply track-by-track efficiency correction"}; + Configurable applyFD{"applyFD", false, "Apply track-by-track feed down correction"}; + Configurable correctNch{"correctNch", true, "Correct also Nch"}; Configurable nSigmaNchCut{"nSigmaNchCut", 1., "nSigma Nch selection"}; Configurable minNchSel{"minNchSel", 5., "min Nch Selection"}; @@ -112,28 +109,21 @@ struct FlowZdcTask { Configurable tdcCut{"tdcCut", 1., "TDC cut"}; Configurable minOccCut{"minOccCut", 0, "min Occu cut"}; Configurable maxOccCut{"maxOccCut", 500, "max Occu cut"}; - Configurable minITSnCls{"minITSnCls", 5, "min ITSnCls"}; Configurable minPt{"minPt", 0.1, "minimum pt of the tracks"}; Configurable maxPt{"maxPt", 3., "maximum pt of the tracks"}; Configurable maxPtSpectra{"maxPtSpectra", 50., "maximum pt of the tracks"}; - Configurable minEta{"minEta", -0.8, "minimum eta"}; - Configurable maxEta{"maxEta", +0.8, "maximum eta"}; // axis configs - ConfigurableAxis axisVertex{"axisVertex", {20, -10, 10}, "vertex axis for histograms"}; ConfigurableAxis axisPhi{"axisPhi", {60, 0.0, constants::math::TwoPI}, "phi axis for histograms"}; - ConfigurableAxis axisEta{"axisEta", {40, -1., 1.}, "eta axis for histograms"}; - ConfigurableAxis axisPt{"axisPt", {VARIABLE_WIDTH, 0.2, 0.25, 0.30, 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.20, 2.40, 2.60, 2.80, 3.00}, "pt axis for histograms"}; ConfigurableAxis axisMultiplicity{"axisMultiplicity", {3500, 0, 3500}, "centrality axis for histograms"}; - ConfigurableAxis axisEnergy{"axisEnergy", {100, 0, 700}, "energy axis for zdc histos"}; - ConfigurableAxis axisMultTpc{"axisMultTpc", {2000, -0.5f, 2999.5f}, "TPCmultiplicity"}; ConfigurableAxis axisZN{"axisZN", {5000, 0, 500}, "axisZN"}; ConfigurableAxis axisZP{"axisZP", {5000, 0, 500}, "axisZP"}; ConfigurableAxis axisFT0CAmp{"axisFT0CAmp", {5000, 0, 5000}, "axisFT0CAmp"}; ConfigurableAxis axisFT0AAmp{"axisFT0AAmp", {5000, 0, 5000}, "axisFT0AAmp"}; ConfigurableAxis axisFT0MAmp{"axisFT0MAmp", {10000, 0, 10000}, "axisFT0MAmp"}; - ConfigurableAxis ft0cMultHistBin{"ft0cMultHistBin", {501, -0.5, 500.5}, ""}; ConfigurableAxis multHistBin{"multHistBin", {501, -0.5, 500.5}, ""}; ConfigurableAxis axisCent{"axisCent", {10, 0, 100}, "axisCent"}; + ConfigurableAxis ft0cMultHistBin{"ft0cMultHistBin", {501, -0.5, 500.5}, ""}; + ConfigurableAxis binsPt{"binsPt", {VARIABLE_WIDTH, 0.0, 0.1, 0.12}, "pT binning"}; Configurable posZcut{"posZcut", +10.0, "z-vertex position cut"}; Configurable minT0CcentCut{"minT0CcentCut", 0.0, "Min T0C Cent. cut"}; Configurable maxT0CcentCut{"maxT0CcentCut", 90.0, "Max T0C Cent. cut"}; @@ -155,6 +145,7 @@ struct FlowZdcTask { Configurable paTH{"paTH", "Users/s/sahernan/test", "base path to the ccdb object"}; Configurable paTHmeanNch{"paTHmeanNch", "Users/s/shernan/test", "base path to the ccdb object"}; Configurable paTHsigmaNch{"paTHsigmaNch", "Users/s/shernan/testSigma", "base path to the ccdb object"}; + Configurable paTHEff{"paTHEff", "Users/s/shernan/TrackingEff", "base path to the ccdb object"}; Configurable ccdbNoLaterThan{"ccdbNoLaterThan", std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(), "latest acceptable timestamp of creation for the object"}; enum EvCutLabel { @@ -191,6 +182,8 @@ struct FlowZdcTask { const AxisSpec axisCounter{1, 0, +1, ""}; const AxisSpec axisEvent{18, 0.5, 18.5, ""}; const AxisSpec axisZpos{48, -12., 12., "Vtx_{z} (cm)"}; + const AxisSpec axisEta{40, -1., +1., "#eta"}; + const AxisSpec axisPt{binsPt, "#it{p}_{T} (GeV/#it{c})"}; AxisSpec axisVtxZ{40, -20, 20, "Vertex Z", "VzAxis"}; AxisSpec axisMult = {multHistBin, "Mult", "MultAxis"}; @@ -201,9 +194,6 @@ struct FlowZdcTask { histos.add("zPos", ";;Entries;", kTH1F, {axisZpos}); histos.add("eventCounter", "eventCounter", kTH1F, {axisCounter}); - histos.add("centHistogram", "centHistogram", kTH1F, {axisCent}); - histos.add("multHistogram", "multHistogram", kTH1F, {axisMultiplicity}); - histos.add("phiHistogram", "phiHistogram", kTH1F, {axisPhi}); histos.add("hZNvsFT0Ccent", "ZN Energy vs FT0C Centrality", kTH2F, @@ -215,8 +205,18 @@ struct FlowZdcTask { histos.add("hNchvsNPV", ";NPVTracks (|#eta|<1);N_{ch} (|#eta|<0.8);", kTH2F, {{{nBinsNch, -0.5, maxNch}, {nBinsNch, -0.5, maxNch}}}); - histos.add("hYield", "Nch vs pT", kTH2F, {axisMultiplicity, axisPt}); - histos.add("hGlobalTracks", "hGlobalTracks", kTH1F, {axisMultiplicity}); + histos.add("T0Ccent", ";;Entries", kTH1F, {axisCent}); + histos.add("NchUncorrected", ";#it{N}_{ch} (|#eta| < 0.8);Entries;", kTH1F, {{300, 0., 3000.}}); + histos.add("ZNamp", ";ZNA+ZNC;Entries;", kTH1F, {{nBinsZN, -0.5, maxZn}}); + histos.add("ExcludedEvtVsFT0M", ";T0A+T0C (#times 1/100, -3.3 < #eta < -2.1 and 3.5 < #eta < 4.9);Entries;", kTH1F, {{nBinsAmpFT0, 0., maxAmpFT0}}); + histos.add("ExcludedEvtVsNch", ";#it{N}_{ch} (|#eta|<0.8);Entries;", kTH1F, {{300, 0, 3000}}); + histos.add("Nch", ";#it{N}_{ch} (|#eta| < 0.8, Corrected);", kTH1F, {{nBinsNch, minNch, maxNch}}); + histos.add("NchVsOneParCorr", ";#it{N}_{ch} (|#eta| < 0.8, Corrected);#LT[#it{p}_{T}^{(1)}]#GT (GeV/#it{c})", kTProfile, {{nBinsNch, minNch, maxNch}}); + histos.add("EtaVsPhi", ";#eta;#varphi", kTH2F, {{{axisEta}, {100, -0.1 * PI, +2.1 * PI}}}); + histos.add("ZposVsEta", "", kTProfile, {axisZpos}); + histos.add("sigma1Pt", ";;#sigma(p_{T})/p_{T};", kTProfile, {axisPt}); + histos.add("dcaXYvspT", ";DCA_{xy} (cm);;", kTH2F, {{{50, -1., 1.}, {axisPt}}}); + // event selection steps histos.add("eventSelectionSteps", "eventSelectionSteps", kTH1D, {axisEvent}); auto hstat = histos.get(HIST("eventSelectionSteps")); @@ -251,25 +251,14 @@ struct FlowZdcTask { histos.add("ZEM2coll", "ZEM2coll; ZEM2 amplitude; Entries", {HistType::kTH1F, {{nBinsAmp, -0.5, maxZem}}}); histos.add("ZNvsZEMcoll", "ZNvsZEMcoll; ZEM; ZNA+ZNC", {HistType::kTH2F, {{{nBinsAmp, -0.5, maxZem}, {nBinsAmp, -0.5, 2. * maxZn}}}}); histos.add("ZNAvsZNCcoll", "ZNAvsZNCcoll; ZNC; ZNA", {HistType::kTH2F, {{{nBinsAmp, -0.5, maxZn}, {nBinsAmp, -0.5, maxZn}}}}); - - histos.add("SPAngleZNA", "Spectator Plane Angle ZNA;Angle (radians);Entries", {HistType::kTH1F, {{100, -o2::constants::math::PI, o2::constants::math::PI}}}); - histos.add("SPAngleZNC", "Spectator Plane Angle ZNC;Angle (radians);Entries", {HistType::kTH1F, {{100, -o2::constants::math::PI, o2::constants::math::PI}}}); - - histos.add("RunningAverageCosPsiDiff", "Running Average of cos(psi) Differences;Running Average;Entries", {HistType::kTH1F, {{100, -1, 1}}}); - - histos.add("CosPsiDifferences", "Differences in cos(psi);cos(psiZNC) - cos(psiZNA);Entries", {HistType::kTH1F, {{100, -2, 2}}}); - histos.add("hSinDifferences", "Differences in sin(psi);sin(psiZNC) - sin(psiZNA);Entries", {HistType::kTH1F, {{100, -2, 2}}}); histos.add("ZDC_energy_vs_ZEM", "ZDCvsZEM; ZEM; ZNA+ZNC+ZPA+ZPC", {HistType::kTH2F, {{{nBinsAmp, -0.5, maxZem}, {nBinsAmp, -0.5, 2. * maxZn}}}}); // common energies information for ZDC - histos.add("ZNCenergy", "ZN energy side c", kTH1F, {axisEnergy}); - histos.add("ZNAenergy", "ZN energy side a", kTH1F, {axisEnergy}); - histos.add("ZPCenergy", "ZP energy side c", kTH1F, {axisEnergy}); - histos.add("ZPAenergy", "ZP energy side a", kTH1F, {axisEnergy}); - histos.add("ZNenergy", "common zn (a + c sides) energy", kTH1F, {axisEnergy}); - histos.add("ZPenergy", "common zp energy (a + c sides)", kTH1F, {axisEnergy}); - histos.add("hFT0CAmp", ";Amplitude;counts", kTH1F, {axisFT0CAmp}); - histos.add("hFT0AAmp", ";Amplitude;counts", kTH1F, {axisFT0AAmp}); - histos.add("hFT0MAmp", ";Amplitude;counts", kTH1F, {axisFT0MAmp}); + histos.add("ZNCenergy", "common sum ZN energy side c", kTH1F, {axisZN}); + histos.add("ZNAenergy", "common sum ZN energy side a", kTH1F, {axisZN}); + histos.add("ZPCenergy", "common sum ZP energy side c", kTH1F, {axisZP}); + histos.add("ZPAenergy", "common sum ZP energy side a", kTH1F, {axisZP}); + histos.add("ZNenergy", "common sum zn (a + c sides) energy", kTH1F, {axisZN}); + histos.add("ZPenergy", "common sum zp energy (a + c sides)", kTH1F, {axisZP}); histos.add("hZNvsFT0CAmp", "ZN Energy vs FT0C Amplitude", kTH2F, {axisFT0CAmp, axisZN}); histos.add("hZPvsFT0CAmp", "ZP Energy vs FT0C Amplitude", kTH2F, {axisFT0CAmp, axisZP}); histos.add("hZNvsMult", "ZN Energy vs Multiplicity", kTH2F, {axisMultiplicity, axisZN}); @@ -277,12 +266,9 @@ struct FlowZdcTask { } if (doprocessQA) { - histos.add("T0Ccent", ";;Entries", kTH1F, {axisCent}); - histos.add("ZNVsFT0A", ";T0A (#times 1/100);ZNA+ZNC;", kTH2F, {{{nBinsAmpFT0, 0., maxAmpFT0}, {nBinsZDC, -0.5, maxZn}}}); histos.add("ZNVsFT0C", ";T0C (#times 1/100);ZNA+ZNC;", kTH2F, {{{nBinsAmpFT0, 0., maxAmpFT0}, {nBinsZDC, -0.5, maxZn}}}); histos.add("ZNVsFT0M", ";T0A+T0C (#times 1/100);ZNA+ZNC;", kTH2F, {{{nBinsAmpFT0, 0., 3000.}, {nBinsZDC, -0.5, maxZn}}}); - histos.add("ZN", ";ZNA+ZNC;Entries;", kTH1F, {{nBinsZDC, -0.5, maxZn}}); histos.add("ZNA", ";ZNA;Entries;", kTH1F, {{nBinsZDC, -0.5, maxZn}}); histos.add("ZPA", ";ZPA;Entries;", kTH1F, {{nBinsZDC, -0.5, maxZp}}); @@ -612,6 +598,9 @@ struct FlowZdcTask { return; } const auto& foundBC = collision.foundBC_as(); + if (!foundBC.has_zdc()) { + return; + } int nTot = tracks.size(); double ft0aAmp = 0; double ft0cAmp = 0; @@ -625,13 +614,8 @@ struct FlowZdcTask { } } const double normT0M{(ft0aAmp + ft0aAmp) / 100.}; - histos.fill(HIST("hFT0AAmp"), ft0aAmp); - histos.fill(HIST("hFT0CAmp"), ft0aAmp); histos.fill(HIST("hFT0MAmp"), normT0M); - if (!foundBC.has_zdc()) { - return; - } const auto& zdcread = foundBC.zdc(); const auto cent = collision.centFT0C(); @@ -656,6 +640,8 @@ struct FlowZdcTask { znC /= cfgCollisionEnergy; zpA /= cfgCollisionEnergy; zpC /= cfgCollisionEnergy; + float sumZNs{znA + znC}; + float sumZPs{zpA + zpC}; // TDC cut if (isTDCcut) { if (std::sqrt(std::pow(tZDCdif, 2.) + std::pow(tZDCsum, 2.)) > tdcCut) { @@ -676,12 +662,88 @@ struct FlowZdcTask { float commonSumZpa = (zdcread.energyCommonZPA()); float sumZN = (sumZNC) + (sumZNA); float sumZP = (sumZPC) + (sumZPA); - histos.fill(HIST("zPos"), collision.posZ()); - histos.fill(HIST("T0Ccent"), collision.centFT0C()); - histos.fill(HIST("ZNAcoll"), znA); - histos.fill(HIST("ZNCcoll"), znC); - histos.fill(HIST("ZPAcoll"), zpA); - histos.fill(HIST("ZPCcoll"), zpC); + + int itsTracks = 0, glbTracks = 0; + for (const auto& track : tracks) { + // Track Selection + if (track.hasITS()) { + itsTracks++; + } + if (!track.isGlobalTrack()) { + continue; + } + if ((track.pt() < minPt) || (track.pt() > maxPt)) { + continue; + } + histos.fill(HIST("ZposVsEta"), collision.posZ(), track.eta()); + histos.fill(HIST("EtaVsPhi"), track.eta(), track.phi()); + histos.fill(HIST("dcaXYvspT"), track.dcaXY(), track.pt()); + glbTracks++; + } + bool skipEvent{false}; + if (useMidRapNchSel) { + auto hMeanNch = ccdb->getForTimeStamp(paTHmeanNch.value, foundBC.timestamp()); + auto hSigmaNch = ccdb->getForTimeStamp(paTHsigmaNch.value, foundBC.timestamp()); + if (!hMeanNch) { + LOGF(info, "hMeanNch NOT LOADED!"); + return; + } + if (!hSigmaNch) { + LOGF(info, "hSigmaNch NOT LOADED!"); + return; + } + const int binT0M{hMeanNch->FindBin(normT0M)}; + const double meanNch{hMeanNch->GetBinContent(binT0M)}; + const double sigmaNch{hSigmaNch->GetBinContent(binT0M)}; + const double nSigmaSelection{nSigmaNchCut * sigmaNch}; + const double diffMeanNch{meanNch - glbTracks}; + if (!(std::abs(diffMeanNch) < nSigmaSelection)) { + histos.fill(HIST("ExcludedEvtVsFT0M"), normT0M); + histos.fill(HIST("ExcludedEvtVsNch"), glbTracks); + } else { + skipEvent = true; + } + } + // Skip event based on number of Nch sigmas + if (!skipEvent) { + return; + } + std::vector pTs; + std::vector vecFD; + std::vector vecOneOverEff; + auto efficiency = ccdb->getForTimeStamp(paTHEff.value, foundBC.timestamp()); + if (!efficiency) { + return; + } + // Calculates the Nch multiplicity + for (const auto& track : tracks) { + // Track Selection + if (!track.isGlobalTrack()) { + continue; + } + if ((track.pt() < minPt) || (track.pt() > maxPt)) { + continue; + } + + float pt{track.pt()}; + float effValue{1.0}; + if (applyEff) { + effValue = efficiency->GetBinContent(efficiency->FindBin(pt)); + } + if (effValue > 0.) { + vecOneOverEff.emplace_back(1. / effValue); + } + } + + double nchMult{0.}; + nchMult = std::accumulate(vecOneOverEff.begin(), vecOneOverEff.end(), 0); + if (!applyEff) + nchMult = static_cast(glbTracks); + if (applyEff && !correctNch) + nchMult = static_cast(glbTracks); + if (nchMult < minNchSel) { + return; + } histos.get(HIST("ZNvsZEMcoll"))->Fill(zdcread.amplitudeZEM1() + zdcread.amplitudeZEM2(), zdcread.amplitudeZNA() + zdcread.amplitudeZNC()); histos.get(HIST("ZNAvsZNCcoll"))->Fill(zdcread.amplitudeZNC(), zdcread.amplitudeZNA()); histos.get(HIST("ZEM1coll"))->Fill(zdcread.amplitudeZEM1()); @@ -699,6 +761,15 @@ struct FlowZdcTask { histos.fill(HIST("hZNvsMult"), nTot, sumZN); histos.fill(HIST("hZPvsMult"), nTot, sumZP); histos.fill(HIST("hNchvsNPV"), collision.multNTracksPVeta1(), nTot); + histos.fill(HIST("Nch"), nchMult); + histos.fill(HIST("ZNamp"), sumZNs); + histos.fill(HIST("NchVsZN"), nchMult, sumZNs); + histos.fill(HIST("NchVsZP"), nchMult, sumZPs); + histos.fill(HIST("NITSTacksVsZN"), itsTracks, sumZNs); + histos.fill(HIST("NITSTacksVsZP"), itsTracks, sumZPs); + histos.fill(HIST("T0MVsZN"), normT0M, sumZNs); + histos.fill(HIST("T0MVsZP"), normT0M, sumZPs); + histos.fill(HIST("NchUncorrected"), glbTracks); float ratioZN = sumZNC / sumZNA; float ratioZP = sumZPC / sumZPA; From 9f5aad7b469d2d2ee653b5875b154c7616b6f142 Mon Sep 17 00:00:00 2001 From: Tanu Gahlaut <154991749+TGahlaut1@users.noreply.github.com> Date: Sun, 22 Jun 2025 22:33:04 +0530 Subject: [PATCH 179/871] [PWGCF] Update meanPtFlucId.cxx (#11716) --- PWGCF/EbyEFluctuations/Tasks/meanPtFlucId.cxx | 1342 +++++++---------- 1 file changed, 531 insertions(+), 811 deletions(-) diff --git a/PWGCF/EbyEFluctuations/Tasks/meanPtFlucId.cxx b/PWGCF/EbyEFluctuations/Tasks/meanPtFlucId.cxx index c2b1a3d71ab..9f1187560f2 100644 --- a/PWGCF/EbyEFluctuations/Tasks/meanPtFlucId.cxx +++ b/PWGCF/EbyEFluctuations/Tasks/meanPtFlucId.cxx @@ -45,18 +45,18 @@ using namespace std; struct MeanPtFlucId { Configurable nPBins{"nPBins", 300, ""}; - Configurable nPartBins{"nPartBins", 250, ""}; - Configurable nCentBins{"nCentBins", 101, ""}; - Configurable nRapBins{"nRapBins", 100, ""}; + Configurable nPartBins{"nPartBins", 100, ""}; Configurable nPhiBins{"nPhiBins", 100, ""}; - Configurable cfgCutPtMax{"cfgCutPtMax", 3.0, "maximum pT"}; - Configurable cfgCutPtMin{"cfgCutPtMin", 0.15, "minimum pT"}; + Configurable cfgCutPtMax{"cfgCutPtMax", 2.0, "maximum pT"}; + Configurable cfgCutPtMin{"cfgCutPtMin", 0.2, "minimum pT"}; Configurable cfgCutEta{"cfgCutEta", 0.8, "Eta cut"}; Configurable cfgCutRap{"cfgCutRap", 0.5, "Rapidity Cut"}; - Configurable cfgCutDcaZ{"cfgCutDcaZ", 0.3, "DCAz cut"}; - Configurable cfgCutPosZ{"cfgCutPosZ", 10.0, "cut for vertex Z"}; + Configurable cfgCutDcaZ{"cfgCutDcaZ", 0.15, "DCAz cut"}; + Configurable cfgCutPosZ{"cfgCutPosZ", 7.0, "cut for vertex Z"}; + Configurable cfgPosZ{"cfgPosZ", true, "Position Z"}; Configurable cfgCutNSig2{"cfgCutNSig2", 2.0, "nSigma cut (2)"}; Configurable cfgCutNSig3{"cfgCutNSig3", 3.0, "nSigma cut (3)"}; + Configurable cfgCutNSig5{"cfgCutNSig5", 5.0, "nSigma cut (3)"}; Configurable cfgCutPiPtMin{"cfgCutPiPtMin", 0.2, "Minimum pion p_{T} cut"}; Configurable cfgCutKaPtMin{"cfgCutKaPtMin", 0.3, "Minimum kaon p_{T} cut"}; Configurable cfgCutPrPtMin{"cfgCutPrPtMin", 0.5, "Minimum proton p_{T} cut"}; @@ -70,67 +70,98 @@ struct MeanPtFlucId { Configurable cfgCutKaP3{"cfgCutKaP3", 1.2, "kaon p cut-3"}; Configurable cfgCutPrP1{"cfgCutPrP1", 0.9, "proton p cut-1"}; Configurable cfgCutPrP2{"cfgCutPrP2", 1.0, "proton p cut-2"}; - Configurable cfgLoadEff{"cfgLoadEff", true, "Load efficiency"}; - Configurable cfgWeightPtCh{"cfgWeightPtCh", true, "Efficiency correction (pT) for charged particles"}; - Configurable cfgWeightPtId{"cfgWeightPtId", false, "Efficiency correction (pT) "}; - Configurable cfgWeightPtYId{"cfgWeightPtYId", false, "Efficiency correction (pT, rap) "}; - Configurable cfgWeightPtEtaId{"cfgWeightPtEtaId", true, "Efficiency correction (pT, Eta) "}; - Configurable cfgPurityId{"cfgPurityId", false, "Purity correction"}; - Configurable cfgMCReco{"cfgMCReco", false, ""}; - Configurable cfgMCTruth{"cfgMCTruth", false, ""}; - Configurable cfgPosZ{"cfgPosZ", true, "Position Z"}; Configurable cfgSel8{"cfgSel8", true, "Sel8 trigger"}; + Configurable cfgMinWeight{"cfgMinWeight", 1e-6, "Minimum weight for efficiency correction"}; Configurable cfgNoSameBunchPileup{"cfgNoSameBunchPileup", true, "kNoSameBunchPileup"}; Configurable cfgIsVertexITSTPC{"cfgIsVertexITSTPC", true, "kIsVertexITSTPC"}; Configurable cfgRejTrk{"cfgRejTrk", true, "Rejected Tracks"}; + Configurable cfgLoadEff{"cfgLoadEff", true, "Load efficiency"}; + Configurable cfgCorrection{"cfgCorrection", true, "Correction"}; + Configurable cfgWeightPtCh{"cfgWeightPtCh", true, "Efficiency correction (pT) for charged particles"}; + Configurable cfgWeightPtId{"cfgWeightPtId", false, "Efficiency correction (pT) "}; + Configurable cfgWeightPtEtaId{"cfgWeightPtEtaId", false, "Efficiency correction (pT) "}; + Configurable cfgPurityId{"cfgPurityId", false, "Purity correction"}; ConfigurableAxis multTPCBins{"multTPCBins", {150, 0, 150}, "TPC Multiplicity bins"}; ConfigurableAxis multFT0MBins{"multFT0MBins", {1000, 0, 5000}, "Forward Multiplicity bins"}; - ConfigurableAxis multFT0MMCBins{"multFT0MMCBins", {250, 0, 250}, "Forward Multiplicity bins"}; - ConfigurableAxis dcaXYBins{"dcaXYBins", {100, -0.15, 0.15}, "dcaXY bins"}; - ConfigurableAxis dcaZBins{"dcaZBins", {100, -1.2, 1.2}, "dcaZ bins"}; ConfigurableAxis qNBins{"qNBins", {1000, 0., 100.}, "nth moments bins"}; - ConfigurableAxis tpNBins{"tpNBins", {300, 0., 3000.}, ""}; - ConfigurableAxis tpDBins{"tpDBins", {100, 0., 2000.}, ""}; + ConfigurableAxis nPairBins{"nPairBins", {2000, 0, 10000}, "nPair bins"}; + ConfigurableAxis dcaXYBins{"dcaXYBins", {100, -0.15, 0.15}, "dcaXY bins"}; + ConfigurableAxis dcaZBins{"dcaZBins", {500, -1.2, 1.2}, "dcaZ bins"}; + Configurable> ptBins{"ptBins", {0.15, 0.20, 0.25, 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.05, 1.10, 1.15, 1.20, 1.25, 1.30, 1.35, 1.40, 1.45, 1.50, 1.55, 1.60, 1.65, 1.70, 1.75, 1.80, 1.85, 1.90, 1.95, 2.00}, "p_{T} bins"}; Configurable> etaBins{"etaBins", {-0.8, -0.75, -0.7, -0.65, -0.6, -0.55, -0.5, -0.45, -0.4, -0.35, -0.3, -0.25, -0.2, -0.15, -0.1, -0.05, 0.0, 0.05, 0.1, 0.15, 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}, "#eta bins"}; - Configurable> rapBins{"rapBins", {-0.6, -0.55, -0.5, -0.45, -0.4, -0.35, -0.3, -0.25, -0.2, -0.15, -0.1, -0.05, 0.0, 0.05, 0.1, 0.15, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5, 0.55, 0.6}, "#rap bins"}; Configurable cfgUrlCCDB{"cfgUrlCCDB", "http://ccdb-test.cern.ch:8080", "url of ccdb"}; Configurable cfgPathCCDB{"cfgPathCCDB", "Users/t/tgahlaut/weightCorr/", "Path for ccdb-object"}; Service ccdb; - - using MyAllTracks = soa::Join; - using MyRun3Collisions = soa::Join; - using MyRun3MCCollisions = soa::Join; - using MyMCTracks = soa::Join; - Service pdg; HistogramRegistry hist{"hist", {}, OutputObjHandlingPolicy::AnalysisObject}; TH1D* hWeightPt = nullptr; TH1D* hPurePt = nullptr; - TH2D* hWeightPtRap = nullptr; - TH2D* hWeightPtEta = nullptr; TH1D* hWeightPtPi = nullptr; TH1D* hWeightPtKa = nullptr; TH1D* hWeightPtPr = nullptr; TH1D* hPurePtPi = nullptr; TH1D* hPurePtKa = nullptr; TH1D* hPurePtPr = nullptr; - TH2D* hWeightPtRapPi = nullptr; - TH2D* hWeightPtRapKa = nullptr; - TH2D* hWeightPtRapPr = nullptr; - TH2D* hWeightPtEtaPi = nullptr; - TH2D* hWeightPtEtaKa = nullptr; - TH2D* hWeightPtEtaPr = nullptr; + + enum CollisionLabels { + kTotCol = 1, + kPassSelCol + }; + + enum TrackLabels { + kTracksBeforeHasMcParticle = 1, + kAllTracks, + kAllSelPassed + }; + + enum SelCollisionLabels { + kBeforeSelCol = 1, + kSelColPosZ, + kSelColSel8, + kSelColNoSameBunchPileup, + kSelColIsVertexITSTPC, + }; + + enum class PIDType { + kNone, + kPions, + kKaons, + kProtons + }; + + enum Mode { + QA_Charged = 0, + QA_Pion, + QA_Kaon, + QA_Proton, + Analysis_Charged, + Analysis_Pion, + Analysis_Kaon, + Analysis_Proton, + Gen_Charged, + Gen_Pion, + Gen_Kaon, + Gen_Proton + }; + + static constexpr std::string_view Dire[] = { + "QA/after/", + "QA/Pion/", + "QA/Kaon/", + "QA/Proton/", + "Analysis/Charged/", + "Analysis/Pion/", + "Analysis/Kaon/", + "Analysis/Proton/", + "Gen/Charged/", + "Gen/Pion/", + "Gen/Kaon/", + "Gen/Proton/"}; void init(InitContext const&) { @@ -147,37 +178,29 @@ struct MeanPtFlucId { hPurePtPi = reinterpret_cast(lst->FindObject("hPurePtPi")); hPurePtKa = reinterpret_cast(lst->FindObject("hPurePtKa")); hPurePtPr = reinterpret_cast(lst->FindObject("hPurePtPr")); - hWeightPtRapPi = reinterpret_cast(lst->FindObject("hWeightPtRapPi")); - hWeightPtRapKa = reinterpret_cast(lst->FindObject("hWeightPtRapKa")); - hWeightPtRapPr = reinterpret_cast(lst->FindObject("hWeightPtRapPr")); - hWeightPtEtaPi = reinterpret_cast(lst->FindObject("hWeightPtEtaPi")); - hWeightPtEtaKa = reinterpret_cast(lst->FindObject("hWeightPtEtaKa")); - hWeightPtEtaPr = reinterpret_cast(lst->FindObject("hWeightPtEtaPr")); - - if (!hWeightPt || !hWeightPtPi || !hWeightPtKa || !hWeightPtPr || !hWeightPtRapPi || !hWeightPtRapKa || !hWeightPtRapPr || !hWeightPtEtaPi || !hWeightPtEtaKa || !hWeightPtEtaPr || !hPurePtPi || !hPurePtKa || !hPurePtPr) { + + if (!hWeightPt || !hWeightPtPi || !hWeightPtKa || !hWeightPtPr || !hPurePtPi || !hPurePtKa || !hPurePtPr) { LOGF(info, "FATAL!! Could not find required histograms in CCDB"); } } - const AxisSpec axisEvents{10, 0, 10, "Counts"}; + const AxisSpec axisCol{3, 1, 4, ""}; + const AxisSpec axisTrack{5, 1, 6, ""}; + const AxisSpec axisEvents{10, 1, 11, "Counts"}; const AxisSpec axisEta{etaBins, "#eta"}; const AxisSpec axisPhi{nPhiBins, 0., +7., "#phi (rad)"}; - const AxisSpec axisY{rapBins, "y"}; + const AxisSpec axisY{100, -0.6, 0.6, "y"}; const AxisSpec axisPt{ptBins, "p_{T} (GeV/c)"}; - const AxisSpec axisPt2{40, 0., 4., "p_{T}^2 (GeV/c)^2"}; const AxisSpec axisP{nPBins, 0., 3., "p (GeV/c)"}; const AxisSpec axisInnerParam{nPBins, 0., 3., "p_{InnerParam } (GeV/c)"}; const AxisSpec axisPart{nPartBins, 0., 18., " "}; const AxisSpec axisQn{qNBins, ""}; - const AxisSpec axisTpN{tpNBins, "(Q_{1}^{2} - Q_{2})"}; - const AxisSpec axisTpD{tpDBins, "N_{pairs}"}; - const AxisSpec axisDeno{100, 1., 2.0, "#frac{1}{#sqrt{1 - #frac{1}{N}}}"}; + const AxisSpec axisNpair{nPairBins, "N_{pairs}"}; const AxisSpec axisMeanPt{100, 0., 3., "M(p_{T}) (GeV/c)"}; const AxisSpec axisMult{100, 0, 100, "N_{ch}"}; const AxisSpec axisMultTPC{multTPCBins, "N_{TPC} "}; const AxisSpec axisMultFT0M{multFT0MBins, "N_{FT0M}"}; - const AxisSpec axisMultFT0MMC{multFT0MMCBins, "N_{FT0M}"}; - const AxisSpec axisCentFT0C{nCentBins, 0, 101, "FT0C (%)"}; + const AxisSpec axisCentFT0M{101, 0, 101, "FT0M (%)"}; const AxisSpec axisVtxZ{80, -20., 20., "V_{Z} (cm)"}; const AxisSpec axisDCAz{dcaZBins, "DCA_{Z} (cm)"}; const AxisSpec axisDCAxy{dcaXYBins, "DCA_{XY} (cm)"}; @@ -188,168 +211,104 @@ struct MeanPtFlucId { const AxisSpec axisChi2{40, 0., 40., "Chi2"}; const AxisSpec axisCrossedTPC{300, 0, 300, "Crossed TPC"}; const AxisSpec axisM2{100, 0., 1.4, "#it{m}^{2} (GeV/#it{c}^{2})^{2}"}; + const AxisSpec axisPid{300, 0, 3000, "PID"}; - HistogramConfigSpec qNHist({HistType::kTHnSparseD, {axisMultTPC, axisQn, axisMultFT0M}}); - HistogramConfigSpec partHist({HistType::kTHnSparseD, {axisMultTPC, axisPart, axisMultFT0M}}); - HistogramConfigSpec denoHist({HistType::kTHnSparseD, {axisMultTPC, axisDeno, axisMultFT0M}}); - HistogramConfigSpec qNMCHist({HistType::kTHnSparseD, {axisMultTPC, axisQn, axisMultFT0M}}); - HistogramConfigSpec partMCHist({HistType::kTHnSparseD, {axisMultTPC, axisPart, axisMultFT0M}}); - HistogramConfigSpec denoMCHist({HistType::kTHnSparseD, {axisMultTPC, axisDeno, axisMultFT0M}}); + HistogramConfigSpec qNHist({HistType::kTHnSparseD, {axisCentFT0M, axisQn}}); + HistogramConfigSpec partHist({HistType::kTHnSparseD, {axisCentFT0M, axisPart}}); + HistogramConfigSpec qNMCHist({HistType::kTHnSparseD, {axisCentFT0M, axisQn}}); + HistogramConfigSpec partMCHist({HistType::kTHnSparseD, {axisCentFT0M, axisPart}}); HistogramConfigSpec tofNSigmaHist({HistType::kTH2D, {axisP, axisTOFNsigma}}); HistogramConfigSpec tofSignalHist({HistType::kTH2D, {axisP, axisTOFSignal}}); HistogramConfigSpec tpcNSigmaHist({HistType::kTH2D, {axisP, axisTPCNsigma}}); HistogramConfigSpec tpcSignalHist({HistType::kTH2D, {axisP, axisTPCSignal}}); HistogramConfigSpec tpcTofHist({HistType::kTH2D, {axisTPCNsigma, axisTOFNsigma}}); HistogramConfigSpec pvsM2Hist({HistType::kTH2D, {axisM2, axisP}}); - - HistogramConfigSpec tofNSigmaHist1({HistType::kTH2D, {axisInnerParam, axisTOFNsigma}}); - HistogramConfigSpec tofSignalHist1({HistType::kTH2D, {axisInnerParam, axisTOFSignal}}); - HistogramConfigSpec tpcNSigmaHist1({HistType::kTH2D, {axisInnerParam, axisTPCNsigma}}); HistogramConfigSpec tpcSignalHist1({HistType::kTH2D, {axisInnerParam, axisTPCSignal}}); - HistogramConfigSpec tpcTofHist1({HistType::kTH2D, {axisTPCNsigma, axisTOFNsigma}}); HistogramConfigSpec pvsM2Hist1({HistType::kTH2D, {axisM2, axisInnerParam}}); - // QA Plots: + // QA Plots hist.add("QA/before/h_Counts", "Counts", kTH1D, {axisEvents}); hist.add("QA/before/h_VtxZ", "V_{Z}", kTH1D, {axisVtxZ}); - hist.add("QA/before/h_Pt", "p_{T}", kTH1D, {axisPt}); - hist.add("QA/before/h_Eta", "#eta ", kTH1D, {axisEta}); - hist.add("QA/before/h_Phi", "#phi ", kTH1D, {axisPhi}); - hist.add("QA/before/h_DcaZ", "DCA_{Z}", kTH1D, {axisDCAz}); - hist.add("QA/before/h_DcaXY", "DCA_{XY}", kTH1D, {axisDCAxy}); - hist.add("QA/before/h2_DcaZ", "DCA_{Z}", kTH2D, {{axisPt}, {axisDCAz}}); - hist.add("QA/before/h2_DcaXY", "DCA_{XY}", kTH2D, {{axisPt}, {axisDCAxy}}); hist.add("QA/before/h_NTPC", "N_{TPC}", kTH1D, {axisMultTPC}); hist.add("QA/before/h_NFT0M", "FT0M Multiplicity", kTH1D, {axisMultFT0M}); - hist.add("QA/before/h_Cent", "FT0C (%)", kTH1D, {axisCentFT0C}); - hist.add("QA/before/h_CentM", "FT0M (%)", kTH1D, {axisCentFT0C}); + hist.add("QA/before/h_CentM", "FT0M (%)", kTH1D, {axisCentFT0M}); hist.add("QA/before/h2_TPCSignal", "TPC Signal", tpcSignalHist); hist.add("QA/before/h2_TOFSignal", "TOF Signal", tofSignalHist); hist.add("QA/before/h2_pvsm2", "p vs m^{2}", pvsM2Hist); - hist.add("QA/before/innerParam/h2_TPCSignal", "TPC Signal", tpcSignalHist1); - hist.add("QA/before/innerParam/h2_TOFSignal", "TOF Signal", tofSignalHist1); - hist.add("QA/before/innerParam/h2_pvsm2", "p vs m^{2}", pvsM2Hist1); - hist.addClone("QA/before/", "QA/after/"); + hist.add("QA/before/h_Pt", "p_{T}", kTH1D, {axisPt}); + hist.add("QA/before/h_Eta", "#eta ", kTH1D, {axisEta}); + hist.add("QA/before/h_Phi", "#phi ", kTH1D, {axisPhi}); + hist.add("QA/before/h_DcaZ", "DCA_{Z}", kTH1D, {axisDCAz}); + hist.add("QA/before/h_DcaXY", "DCA_{XY}", kTH1D, {axisDCAxy}); + hist.add("QA/before/h2_DcaZ", "DCA_{Z}", kTH2D, {{axisPt}, {axisDCAz}}); + hist.add("QA/before/h2_DcaXY", "DCA_{XY}", kTH2D, {{axisPt}, {axisDCAxy}}); + + hist.add("QA/after/h_counts_evSelCuts", "Event selection cuts", kTH1D, {axisEvents}); hist.add("QA/after/h_TPCChi2perCluster", "TPC #Chi^{2}/Cluster", kTH1D, {axisChi2}); hist.add("QA/after/h_ITSChi2perCluster", "ITS #Chi^{2}/Cluster", kTH1D, {axisChi2}); hist.add("QA/after/h_crossedTPC", "Crossed TPC", kTH1D, {axisCrossedTPC}); - hist.add("QA/after/h_counts_evSelCuts", "Event selection cuts", kTH1D, {axisEvents}); - hist.add("QA/after/h_VtxZReco", "Simulated Vertex Z", kTH1D, {axisVtxZ}); - - hist.add("QA/after/h2_PvsPinner", "p_{InnerParam} vs p", kTH2D, {{axisP}, {axisInnerParam}}); - hist.add("QA/after/h2_Pt_Eta", "p_{T} vs #eta ", kTH2D, {{axisEta}, {axisPt}}); - hist.add("QA/after/h2_NTPC_Cent", "N_{TPC} vs FT0C(%)", kTH2D, {{axisCentFT0C}, {axisMultTPC}}); - hist.add("QA/after/h2_NTPC_CentM", "N_{TPC} vs FT0M(%)", kTH2D, {{axisCentFT0C}, {axisMultTPC}}); + hist.add("QA/after/h2_NTPC_CentM", "N_{TPC} vs FT0M(%)", kTH2D, {{axisCentFT0M}, {axisMultTPC}}); hist.add("QA/after/h2_NTPC_NFT0M", "N_{TPC} vs N_{FT0M}", kTH2D, {{axisMultFT0M}, {axisMultTPC}}); - hist.add("QA/after/p_NTPC_NFT0M", "N_{TPC} vs N_{FT0M} (Profile)", kTProfile, {axisMultFT0M}); - hist.add("QA/after/p_NTPC_Cent", "N_{TPC} vs FT0C(%) (Profile)", kTProfile, {axisCentFT0C}); - - hist.add("QA/after/h_Pt2", "p_{T}^2", kTH1D, {axisPt2}); - hist.add("QA/after/h_Pt_weighted", "weighted pT distribution", kTH1D, {axisPt}); - hist.add("QA/after/h_Pt2_weighted", "weighted pT distribution", kTH1D, {axisPt2}); - hist.add("QA/after/h2_Pt_NFT0M", "p_{T} in Multiplicity Classes ", kTH2D, {{axisPt}, {axisMultFT0M}}); - hist.add("QA/after/h_PtEtaPhi_NFT0M", "p_{T}, #eta, #phi in Multiplicity Classes ", kTHnSparseD, {{axisPt}, {axisEta}, {axisPhi}, {axisMultFT0M}}); - hist.add("QA/after/h_PtEtaPhi_centFT0M", "p_{T}, #eta, #phi in centrality Classes ", kTHnSparseD, {{axisPt}, {axisEta}, {axisPhi}, {axisCentFT0C}}); - hist.add("QA/after/h2_pt_nch", "Truth", kTH2D, {{axisMult}, {axisPt}}); - hist.add("QA/after/h3_nft0m_pt_nch", "Reco", kTHnSparseD, {{axisMult}, {axisPt}, {axisMultFT0M}}); - hist.add("QA/after/h2_pt_nch_prof", "Truth", kTProfile, {axisMult}); + hist.add("QA/after/p_NTPC_CentM", "N_{TPC} vs FT0M(%) (Profile)", kTProfile, {axisCentFT0M}); + hist.add("QA/after/h_DCAxy_primary", "DCA_{XY} (Primary)", kTH1D, {axisDCAxy}); + hist.add("QA/after/h_DCAz_primary", "DCA_{Z} (Primary)", kTH1D, {axisDCAz}); + hist.add("QA/after/h_DCAxy_secondary", "DCA_{XY} (Secondary)", kTH1D, {axisDCAxy}); + hist.add("QA/after/h_DCAz_secondary", "DCA_{Z} (Secondary)", kTH1D, {axisDCAz}); + hist.add("QA/after/innerParam/h2_TPCSignal", "TPC Signal", tpcSignalHist1); + + hist.add("QA/Charged/h_Pt", "p_{T}", kTH1D, {axisPt}); + hist.add("QA/Charged/h_Eta", "#eta ", kTH1D, {axisEta}); + hist.add("QA/Charged/h_Phi", "#phi ", kTH1D, {axisPhi}); + hist.add("QA/Charged/h_DcaZ", "DCA_{Z}", kTH1D, {axisDCAz}); + hist.add("QA/Charged/h_DcaXY", "DCA_{XY}", kTH1D, {axisDCAxy}); + hist.add("QA/Charged/h2_DcaZ", "DCA_{Z}", kTH2D, {{axisPt}, {axisDCAz}}); + hist.add("QA/Charged/h2_DcaXY", "DCA_{XY}", kTH2D, {{axisPt}, {axisDCAxy}}); + hist.add("QA/Charged/h_Pt_weighted", "weighted pT distribution", kTH1D, {axisPt}); + hist.add("QA/Charged/h2_Pt_Eta", "p_{T} vs #eta ", kTH2D, {{axisEta}, {axisPt}}); + hist.add("QA/Charged/h2_Pt_centFT0M", "p_{T} in centrality Classes ", kTH2D, {{axisCentFT0M}, {axisPt}}); + hist.add("QA/Charged/h3_PtEtaPhi", "p_{T}, #eta, #phi ", kTHnSparseD, {{axisPt}, {axisEta}, {axisPhi}}); + + hist.addClone("QA/Charged/", "QA/Pion/"); hist.add("QA/Pion/before/h2_TPCNsigma", "n #sigma_{TPC}", tpcNSigmaHist); + hist.add("QA/Pion/before/h2_TPCNsigma_tof", "n #sigma_{TPC}", tpcNSigmaHist); hist.add("QA/Pion/before/h2_TOFNsigma", "n #sigma_{TOF}", tofNSigmaHist); hist.add("QA/Pion/before/h2_TpcTofNsigma", "n #sigma_{TPC} vs n #sigma_{TOF}", tpcTofHist); hist.add("QA/Pion/h_Rap", "y ", kTH1D, {axisY}); - hist.add("QA/Pion/h_RapTruth", "y ", kTH1D, {axisY}); - hist.add("QA/Pion/h_Eta", "Pseudorapidity ", kTH1D, {axisEta}); - hist.add("QA/Pion/h_EtaTruth", "Pseudorapidity (Reco Truth) ", kTH1D, {axisEta}); - hist.add("QA/Pion/h_Phi", "Azimuthal Distribution ", kTH1D, {axisPhi}); - hist.add("QA/Pion/h_DcaZ", "DCA_{z}", kTH1D, {axisDCAz}); - hist.add("QA/Pion/h_DcaXY", "DCA_{xy}", kTH1D, {axisDCAxy}); - hist.add("QA/Pion/h_Pt", "p_{T} ", kTH1D, {axisPt}); - hist.add("QA/Pion/h_Pt2", "p_{T}^2 ", kTH1D, {axisPt2}); hist.add("QA/Pion/h_PtPos", "p_{T} (positive) ", kTH1D, {axisPt}); hist.add("QA/Pion/h_PtNeg", "p_{T} (negative) ", kTH1D, {axisPt}); - hist.add("QA/Pion/h_PtTruth", "p_{T} ", kTH1D, {axisPt}); - hist.add("QA/Pion/h_PtTruth2", "p_{T}^2 ", kTH1D, {axisPt2}); - hist.add("QA/Pion/h_PtPosTruth", "p_{T} (positive) ", kTH1D, {axisPt}); - hist.add("QA/Pion/h_PtNegTruth", "p_{T} (negative) ", kTH1D, {axisPt}); - hist.add("QA/Pion/h_Pt_weighted", "weighted pT distribution", kTH1D, {axisPt}); - hist.add("QA/Pion/h_Pt2_weighted", "weighted pT distribution", kTH1D, {axisPt2}); - - hist.add("QA/Pion/h2_Pt_Rap", "p_{T} vs y", kTH2D, {{axisY}, {axisPt}}); - hist.add("QA/Pion/h2_PtTruth_Rap", "p_{T} vs y", kTH2D, {{axisY}, {axisPt}}); - hist.add("QA/Pion/h2_PtTruth_Eta", "p_{T} vs #eta", kTH2D, {{axisEta}, {axisPt}}); - hist.add("QA/Pion/h2_Pt_Eta", "p_{T} vs #eta", kTH2D, {{axisEta}, {axisPt}}); - hist.add("QA/Pion/h2_DcaZ", "DCA_{z}", kTH2D, {{axisPt}, {axisDCAz}}); - hist.add("QA/Pion/h2_DcaXY", "DCA_{xy}", kTH2D, {{axisPt}, {axisDCAxy}}); - hist.add("QA/Pion/h2_Pt_Rap_weighted", "p_{T} vs y weighted", kTH2D, {{axisY}, {axisPt}}); - hist.add("QA/Pion/h2_Pt_Eta_weighted", "p_{T} vs #eta weighted", kTH2D, {{axisEta}, {axisPt}}); - hist.add("QA/Pion/h2_Pt_NFT0M", "p_{T} in Multiplicity Classes ", kTH2D, {{axisPt}, {axisMultFT0M}}); - - hist.add("QA/Pion/h_PtEtaPhi_NFT0M", "p_{T}, #eta, #phi in Multiplicity Classes ", kTHnSparseD, {{axisPt}, {axisEta}, {axisPhi}, {axisMultFT0M}}); - hist.add("QA/Pion/h_PtEtaPhi_centFT0M", "p_{T}, #eta, #phi in centrality Classes ", kTHnSparseD, {{axisPt}, {axisEta}, {axisPhi}, {axisCentFT0C}}); - - hist.add("QA/Pion/h2_PtTruth_NFT0M", "p_{T} in Multiplicity Classes ", kTH2D, {{axisPt}, {axisMultFT0M}}); - hist.add("QA/Pion/h2_pt_nch", "Reco", kTH2D, {{axisMult}, {axisPt}}); - hist.add("QA/Pion/h3_nft0m_pt_nch", "Reco", kTHnSparseD, {{axisMult}, {axisPt}, {axisMultFT0M}}); - hist.add("QA/Pion/h2_pt_nch_prof", "Reco", kTProfile, {axisMult}); - + hist.add("QA/Pion/h_PtTruth", "p_{T} (Truth)", kTH1D, {axisPt}); + hist.add("QA/Pion/h_PtPosTruth", "p_{T} (positive) (Truth)", kTH1D, {axisPt}); + hist.add("QA/Pion/h_PtNegTruth", "p_{T} (negative) (Truth) ", kTH1D, {axisPt}); hist.add("QA/Pion/h2_TPCNsigma", "n #sigma_{TPC}", tpcNSigmaHist); - hist.add("QA/Pion/h2_TPCNsigma_El", "n #sigma_{TPC, El}", tpcNSigmaHist); - hist.add("QA/Pion/h2_TOFNsigma_El", "n #sigma_{TOF, El}", tofNSigmaHist); hist.add("QA/Pion/h2_TOFNsigma", "n #sigma_{TOF}", tofNSigmaHist); hist.add("QA/Pion/h2_TpcTofNsigma", "n #sigma_{TPC} vs n #sigma_{TOF}", tpcTofHist); hist.add("QA/Pion/h2_TPCSignal", "TPC Signal ", tpcSignalHist); hist.add("QA/Pion/h2_TOFSignal", "TOF Signal", tofSignalHist); + hist.add("QA/Pion/innerParam/h2_TPCSignal", "TPC Signal", tpcSignalHist1); hist.add("QA/Pion/h2_pvsm2", "p vs m^{2}", pvsM2Hist); - - hist.add("QA/Pion/innerParam/before/h2_TPCNsigma", "n #sigma_{TPC}", tpcNSigmaHist1); - hist.add("QA/Pion/innerParam/before/h2_TOFNsigma", "n #sigma_{TOF}", tofNSigmaHist1); - hist.add("QA/Pion/innerParam/before/h2_TpcTofNsigma", "n #sigma_{TPC} vs n #sigma_{TOF}", tpcTofHist1); - hist.add("QA/Pion/innerParam/h2_TPCNsigma", "n #sigma_{TPC}", tpcNSigmaHist1); - hist.add("QA/Pion/innerParam/h2_TPCNsigma_El", "n #sigma_{TPC, El}", tpcNSigmaHist1); - hist.add("QA/Pion/innerParam/h2_TOFNsigma_El", "n #sigma_{TOF, El}", tofNSigmaHist1); - hist.add("QA/Pion/innerParam/h2_TOFNsigma", "n #sigma_{TOF}", tofNSigmaHist1); - hist.add("QA/Pion/innerParam/h2_TpcTofNsigma", "n #sigma_{TPC} vs n #sigma_{TOF}", tpcTofHist1); - hist.add("QA/Pion/innerParam/h2_TPCSignal", "TPC Signal ", tpcSignalHist1); - hist.add("QA/Pion/innerParam/h2_TOFSignal", "TOF Signal", tofSignalHist1); - hist.add("QA/Pion/innerParam/h2_pvsm2", "p vs m^{2}", pvsM2Hist1); - + hist.add("QA/Pion/h_PtTruth_primary", "p_{T} (Truth Primary)", kTH1D, {axisPt}); + hist.add("QA/Pion/h_PtTruth_secondary", "p_{T} (Truth Secondary)", kTH1D, {axisPt}); hist.addClone("QA/Pion/", "QA/Kaon/"); hist.addClone("QA/Pion/", "QA/Proton/"); - // Analysis Plots: + // AnalysisPlots hist.add("Analysis/Charged/h_Mult", "Multiplicity", kTH1D, {axisMult}); - hist.add("Analysis/Charged/h_Mult_weighted", "Multiplicity", kTH1D, {axisMult}); - hist.add("Analysis/Charged/h_Q1", "Q1", qNHist); - hist.add("Analysis/Charged/h_Q2", "Q2", qNHist); - hist.add("Analysis/Charged/h_Q3", "Q3", qNHist); - hist.add("Analysis/Charged/h_Q4", "Q4", qNHist); - hist.add("Analysis/Charged/h_mean_pT", " ", kTH1D, {axisMeanPt}); - hist.add("Analysis/Charged/p_mean_pT_Mult_var", " ", kTProfile, {axisMultTPC}); - hist.add("Analysis/Charged/p_CheckNCh", " 1/denominator vs N_{TPC} ", kTProfile, {axisMultTPC}); - hist.add("Analysis/Charged/h_CheckNCh", " 1/denominator vs N_{TPC} ", denoHist); - hist.add("Analysis/Charged/h_Q1_var", "Q1 vs N_{TPC}", qNHist); - hist.add("Analysis/Charged/h_N_var", "N vs N_{TPC}", kTHnSparseD, {axisMultTPC, axisMult, axisMultFT0M}); - hist.add("Analysis/Charged/h_twopart_nume_Mult_var", "twopart numerator", kTHnSparseD, {axisMultTPC, axisTpN, axisMultFT0M}); - hist.add("Analysis/Charged/h_twopart_deno_Mult_var", "twopart denominator", kTHnSparseD, {axisMultTPC, axisTpD, axisMultFT0M}); + hist.add("Analysis/Charged/h_N_CentFT0M", "Multiplicity vs CentFT0M", kTHnSparseD, {axisCentFT0M, axisMult}); + hist.add("Analysis/Charged/h_Npair_CentFT0M", "Npair vs CentFT0M", kTHnSparseD, {axisCentFT0M, axisNpair}); + hist.add("Analysis/Charged/h_Q1_CentFT0M", "Q1 vs CentFT0M", qNHist); + hist.add("Analysis/Charged/h_Q2_CentFT0M", "Q2 vs CentFT0M", qNHist); + hist.add("Analysis/Charged/h_twopart1_CentFT0M", "twopart (neum)", qNMCHist); hist.add("Analysis/Charged/h_mean_pT_Mult_var", " vs N_{TPC} ", partHist); - hist.add("Analysis/Charged/h_mean_pT_Mult_skew", " vs N_{TPC} ", partHist); - hist.add("Analysis/Charged/h_mean_pT_Mult_kurto", " vs N_{TPC} ", partHist); hist.add("Analysis/Charged/h_twopart_Mult_var", "Twopart vs N_{TPC} ", partHist); - hist.add("Analysis/Charged/h_twopart_Mult_skew", "Twopart vs N_{TPC} ", partHist); - hist.add("Analysis/Charged/h_twopart_Mult_kurto", "Twopart vs N_{TPC} ", partHist); - hist.add("Analysis/Charged/h_threepart_Mult_skew", "Threepart vs N_{TPC} ", partHist); - hist.add("Analysis/Charged/h_threepart_Mult_kurto", "Threepart vs N_{TPC} ", partHist); - hist.add("Analysis/Charged/h_fourpart_Mult_kurto", "Fourpart vs N_{TPC} ", partHist); - - hist.add("Analysis/Charged/p_twopart_MultFT0M", "Twopart vs N_{FT0M} ", kTProfile, {axisMultFT0M}); - hist.add("Analysis/Charged/p_mean_pT_MultFT0M", " vs N_{FT0M} ", kTProfile, {axisMultFT0M}); + hist.add("Analysis/Charged/p_twopart_CentFT0M", "Twopart vs cent_{FT0M} ", kTProfile, {axisCentFT0M}); + hist.add("Analysis/Charged/p_mean_pT_CentFT0M", " vs cent_{FT0M} ", kTProfile, {axisCentFT0M}); hist.addClone("Analysis/Charged/", "Analysis/Pion/"); hist.addClone("Analysis/Charged/", "Analysis/Kaon/"); @@ -359,126 +318,95 @@ struct MeanPtFlucId { hist.add("Gen/h_Counts", "Counts", kTH1D, {axisEvents}); hist.add("Gen/h_VtxZ", "Vertex Z ", kTH1D, {axisVtxZ}); hist.add("Gen/h_VtxZ_b", "Vertex Z ", kTH1D, {axisVtxZ}); - hist.add("Gen/h_NTPC", "Mid rapidity Multiplicity", kTH1D, {axisMultTPC}); - hist.add("Gen/h_NFT0C", "Forward Multiplicity", kTH1D, {axisMultFT0MMC}); - hist.add("Gen/h2_NTPC_NFT0M", "NTPC vs Forward Multiplicity", kTH2D, {{axisMultFT0M}, {axisMultTPC}}); - hist.add("Gen/h_NSim", "Truth Multiplicity TPC", kTH1D, {axisMultTPC}); hist.add("Gen/h2_NTPC_NSim", "Reco vs Truth Multiplicty TPC", kTH2D, {{axisMultTPC}, {axisMultTPC}}); - hist.add("Gen/h2_NChSim_NSim", "Truth Multiplicty NCh vs NTPC", kTH2D, {{axisMultTPC}, {axisMultTPC}}); - hist.add("Gen/Charged/h_PtEtaPhi_NFT0M", "p_{T}, #eta, #phi in Multiplicity Classes ", kTHnSparseD, {{axisPt}, {axisEta}, {axisPhi}, {axisMultFT0M}}); - hist.add("Gen/Charged/h_PtEtaPhi_centFT0M", "p_{T}, #eta, #phi in centrality Classes ", kTHnSparseD, {{axisPt}, {axisEta}, {axisPhi}, {axisCentFT0C}}); hist.add("Gen/Charged/h_EtaTruth", "#eta ", kTH1D, {axisEta}); hist.add("Gen/Charged/h_PhiTruth", "#phi ", kTH1D, {axisPhi}); hist.add("Gen/Charged/h_PtTruth", "p_{T} ", kTH1D, {axisPt}); - hist.add("Gen/Charged/h_PtTruth2", "p_{T}^2 ", kTH1D, {axisPt2}); - hist.add("Gen/Charged/h2_PtTruth_Eta", "p_{T} vs #eta", kTH2D, {{axisEta}, {axisPt}}); - hist.add("Gen/Charged/h2_PtTruth_NFT0M", "p_{T} in Multiplicity Classes", kTH2D, {{axisPt}, {axisMultFT0M}}); + hist.add("Gen/Charged/h2_Pt_EtaTruth", "p_{T} vs #eta", kTH2D, {{axisEta}, {axisPt}}); + hist.add("Gen/Charged/h2_PtTruth_centFT0M", "p_{T} in centrality Classes ", kTH2D, {{axisCentFT0M}, {axisPt}}); + hist.add("Gen/Charged/h_PtEtaPhiTruth", "p_{T}, #eta, #phi ", kTHnSparseD, {{axisPt}, {axisEta}, {axisPhi}}); hist.add("Gen/Charged/h_Mult", "Multiplicity", kTH1D, {axisMult}); - hist.add("Gen/Charged/h_Mult_weighted", "Multiplicity", kTH1D, {axisMult}); - - hist.add("Gen/Charged/h2_pt_nch", "Truth", kTH2D, {{axisMult}, {axisPt}}); - hist.add("Gen/Charged/h3_nft0m_pt_nch", "Truth", kTHnSparseD, {{axisMult}, {axisPt}, {axisMultFT0M}}); - hist.add("Gen/Charged/h2_pt_nch_prof", "Truth", kTProfile, {axisMult}); - hist.add("Gen/Charged/h_mean_pT", " ", kTH1D, {axisMeanPt}); - - hist.add("Gen/Charged/h_Q1", "Q1", qNMCHist); - hist.add("Gen/Charged/h_Q2", "Q2", qNMCHist); - hist.add("Gen/Charged/h_Q3", "Q3", qNMCHist); - hist.add("Gen/Charged/h_Q4", "Q4", qNMCHist); - hist.add("Gen/Charged/h_Q1_var", "Q1 vs N_{TPC}", qNMCHist); - hist.add("Gen/Charged/h_N_var", "N vs N_{TPC}", kTHnSparseD, {axisMultTPC, axisMult, axisMultFT0M}); - hist.add("Gen/Charged/h_twopart_nume_Mult_var", "twopart numerator", kTHnSparseD, {axisMultTPC, axisTpN, axisMultFT0M}); - hist.add("Gen/Charged/h_twopart_deno_Mult_var", "twopart denominator", kTHnSparseD, {axisMultTPC, axisTpD, axisMultFT0M}); - - hist.add("Gen/Charged/p_mean_pT_Mult_var", " ", kTProfile, {axisMultTPC}); - hist.add("Gen/Charged/p_CheckNCh", " 1/denominator vs N_{TPC} ", kTProfile, {axisMultTPC}); - hist.add("Gen/Charged/h_CheckNCh", " 1/denominator vs N_{TPC} ", denoMCHist); + hist.add("Gen/Charged/h_N_CentFT0M", "Multiplicity vs CentFT0M", kTHnSparseD, {axisCentFT0M, axisMult}); + hist.add("Gen/Charged/h_Npair_CentFT0M", "Npair vs CentFT0M", kTHnSparseD, {axisCentFT0M, axisNpair}); + hist.add("Gen/Charged/h_Q1_CentFT0M", "Q1", qNMCHist); + hist.add("Gen/Charged/h_Q2_CentFT0M", "Q2", qNMCHist); + hist.add("Gen/Charged/h_twopart1_CentFT0M", "twopart (neum)", qNMCHist); hist.add("Gen/Charged/h_mean_pT_Mult_var", " vs N_{TPC} ", partMCHist); - hist.add("Gen/Charged/h_mean_pT_Mult_skew", " vs N_{TPC} ", partMCHist); - hist.add("Gen/Charged/h_mean_pT_Mult_kurto", " vs N_{TPC} ", partMCHist); hist.add("Gen/Charged/h_twopart_Mult_var", "Twopart vs N_{TPC} ", partMCHist); - hist.add("Gen/Charged/h_twopart_Mult_skew", "Twopart vs N_{TPC} ", partMCHist); - hist.add("Gen/Charged/h_twopart_Mult_kurto", "Twopart vs N_{TPC} ", partMCHist); - hist.add("Gen/Charged/h_threepart_Mult_skew", "Threepart vs N_{TPC} ", partMCHist); - hist.add("Gen/Charged/h_threepart_Mult_kurto", "Threepart vs N_{TPC} ", partMCHist); - hist.add("Gen/Charged/h_fourpart_Mult_kurto", "Fourpart vs N_{TPC} ", partMCHist); - hist.add("Gen/Charged/p_twopart_MultFT0M", "Twopart vs N_{TPC} ", kTProfile, {axisMultFT0M}); - hist.add("Gen/Charged/p_mean_pT_MultFT0M", " vs N_{TPC} ", kTProfile, {axisMultFT0M}); + hist.add("Gen/Charged/p_twopart_CentFT0M", "Twopart vs CentFT0M ", kTProfile, {axisCentFT0M}); + hist.add("Gen/Charged/p_mean_pT_CentFT0M", " vs CentFT0M ", kTProfile, {axisCentFT0M}); hist.addClone("Gen/Charged/", "Gen/Pion/"); hist.add("Gen/Pion/h_RapTruth", "y", kTH1D, {axisY}); - hist.add("Gen/Pion/h2_PtTruth_Rap", "p_{T} vs y", kTH2D, {{axisY}, {axisPt}}); hist.add("Gen/Pion/h_PtPosTruth", "p_{T} (positive) ", kTH1D, {axisPt}); hist.add("Gen/Pion/h_PtNegTruth", "p_{T} (negative) ", kTH1D, {axisPt}); hist.addClone("Gen/Pion/", "Gen/Kaon/"); hist.addClone("Gen/Pion/", "Gen/Proton/"); + + hist.add("QA/h_collisions_info", "Collisions info", kTH1D, {axisCol}); + hist.add("Gen/h_collisions_info", "Collisions info", kTH1D, {axisCol}); + hist.add("Gen/h_collision_recgen", "Number of Collisions ", kTH1D, {axisCol}); + hist.add("Gen/h2_collision_posZ", "Reco vs truth posZ ", kTH2D, {{axisVtxZ}, {axisVtxZ}}); + hist.add("Tracks/h_tracks_info", "Track info", kTH1D, {axisTrack}); + hist.add("Tracks/h2_tracks_pid_before_sel", "Track pid info before selection", kTH2D, {{axisPid}, {axisPt}}); + + hist.get(HIST("QA/h_collisions_info"))->GetXaxis()->SetBinLabel(CollisionLabels::kTotCol, "kTotCol"); + hist.get(HIST("QA/h_collisions_info"))->GetXaxis()->SetBinLabel(CollisionLabels::kPassSelCol, "kPassSelCol"); + hist.get(HIST("Gen/h_collisions_info"))->GetXaxis()->SetBinLabel(CollisionLabels::kTotCol, "kTotCol"); + hist.get(HIST("Gen/h_collisions_info"))->GetXaxis()->SetBinLabel(CollisionLabels::kPassSelCol, "kPassSelCol"); + hist.get(HIST("Tracks/h_tracks_info"))->GetXaxis()->SetBinLabel(TrackLabels::kTracksBeforeHasMcParticle, "kTracksBeforeHasMcParticle"); + hist.get(HIST("Tracks/h_tracks_info"))->GetXaxis()->SetBinLabel(TrackLabels::kAllTracks, "kAllTracks"); + hist.get(HIST("Tracks/h_tracks_info"))->GetXaxis()->SetBinLabel(TrackLabels::kAllSelPassed, "kAllSelPassed"); + hist.get(HIST("QA/after/h_counts_evSelCuts"))->GetXaxis()->SetBinLabel(SelCollisionLabels::kBeforeSelCol, "kBeforeSelCol"); + hist.get(HIST("QA/after/h_counts_evSelCuts"))->GetXaxis()->SetBinLabel(SelCollisionLabels::kSelColPosZ, "kSelColPosZ"); + hist.get(HIST("QA/after/h_counts_evSelCuts"))->GetXaxis()->SetBinLabel(SelCollisionLabels::kSelColSel8, "kSelColSel8"); + hist.get(HIST("QA/after/h_counts_evSelCuts"))->GetXaxis()->SetBinLabel(SelCollisionLabels::kSelColNoSameBunchPileup, "kSelColNoSameBunchPileup"); + hist.get(HIST("QA/after/h_counts_evSelCuts"))->GetXaxis()->SetBinLabel(SelCollisionLabels::kSelColIsVertexITSTPC, "kSelColIsVertexITSTPC"); } - enum Mode { - QA_Charged = 0, - QA_Pion, - QA_Kaon, - QA_Proton, - Analysis_Charged, - Analysis_Pion, - Analysis_Kaon, - Analysis_Proton, - Gen_Charged, - Gen_Pion, - Gen_Kaon, - Gen_Proton - }; - - static constexpr std::string_view Dire[] = { - "QA/after/", - "QA/Pion/", - "QA/Kaon/", - "QA/Proton/", - "Analysis/Charged/", - "Analysis/Pion/", - "Analysis/Kaon/", - "Analysis/Proton/", - "Gen/Charged/", - "Gen/Pion/", - "Gen/Kaon/", - "Gen/Proton/"}; + float centFT0M = 0.; + int nTPC = 0, nFT0M = 0; // Event selection cuts: template bool selRun3Col(T const& col) { - hist.fill(HIST("QA/after/h_counts_evSelCuts"), 0); + hist.fill(HIST("QA/after/h_counts_evSelCuts"), kBeforeSelCol); if (cfgPosZ) { if (std::abs(col.posZ()) > cfgCutPosZ) { return false; } - hist.fill(HIST("QA/after/h_counts_evSelCuts"), 1); + hist.fill(HIST("QA/after/h_counts_evSelCuts"), kSelColPosZ); } + centFT0M = col.centFT0M(); + nTPC = col.multNTracksHasTPC(); + nFT0M = col.multFT0M(); + if (cfgSel8) { if (!col.sel8()) { return false; } - hist.fill(HIST("QA/after/h_counts_evSelCuts"), 2); + hist.fill(HIST("QA/after/h_counts_evSelCuts"), kSelColSel8); } if (cfgNoSameBunchPileup) { if (!col.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { return false; } - hist.fill(HIST("QA/after/h_counts_evSelCuts"), 4); + hist.fill(HIST("QA/after/h_counts_evSelCuts"), kSelColNoSameBunchPileup); } if (cfgIsVertexITSTPC) { if (!col.selection_bit(o2::aod::evsel::kIsVertexITSTPC)) { return false; } - hist.fill(HIST("QA/after/h_counts_evSelCuts"), 5); + hist.fill(HIST("QA/after/h_counts_evSelCuts"), kSelColIsVertexITSTPC); } return true; @@ -494,7 +422,7 @@ struct MeanPtFlucId { if (track.pt() < cfgCutPtMin) return false; - if (track.pt() > cfgCutPtMax) + if (track.pt() >= cfgCutPtMax) return false; if (track.sign() == 0) @@ -504,9 +432,10 @@ struct MeanPtFlucId { return false; if (std::fabs(track.dcaZ()) > (0.0105 + 0.035 / std::pow(track.p(), 1.1))) + return false; - if (std::abs(track.eta()) >= cfgCutEta) - return false; + if (std::abs(track.eta()) >= cfgCutEta) + return false; return true; } @@ -515,11 +444,11 @@ struct MeanPtFlucId { template bool rejectTracks(T const& track) { - if (((track.tpcNSigmaEl()) > -3. && - (track.tpcNSigmaEl()) < 5.) && - (std::fabs(track.tpcNSigmaPi()) > 3 && - std::fabs(track.tpcNSigmaKa()) > 3 && - std::fabs(track.tpcNSigmaPr()) > 3)) { + if (((track.tpcNSigmaEl()) > -cfgCutNSig3 && + (track.tpcNSigmaEl()) < cfgCutNSig5) && + (std::fabs(track.tpcNSigmaPi()) > cfgCutNSig3 && + std::fabs(track.tpcNSigmaKa()) > cfgCutNSig3 && + std::fabs(track.tpcNSigmaPr()) > cfgCutNSig3)) { return true; } @@ -527,97 +456,65 @@ struct MeanPtFlucId { } template - bool selElectrons(T const& track) + PIDType identifyParticle(const T& track) { - if (std::fabs(track.tpcNSigmaEl()) < cfgCutNSig3) { - return true; + const float pt = track.pt(); + const float p = track.p(); + + // Check pion + const bool tpcPi = std::fabs(track.tpcNSigmaPi()) < cfgCutNSig3 && std::fabs(track.tpcNSigmaPi()) < std::fabs(track.tpcNSigmaKa()) && std::fabs(track.tpcNSigmaPi()) < std::fabs(track.tpcNSigmaPr()); + const bool tofPi = track.hasTOF() && std::fabs(track.tofNSigmaPi()) < cfgCutNSig3 && std::fabs(track.tofNSigmaPi()) < std::fabs(track.tofNSigmaKa()) && std::fabs(track.tofNSigmaPi()) < std::fabs(track.tofNSigmaPr()); + const bool isPi = (pt >= cfgCutPiPtMin && + ((p <= cfgCutPiThrsldP && ((tpcPi && !track.hasTOF()) || (tpcPi && tofPi))) || + (p > cfgCutPiThrsldP && tpcPi && tofPi))); + + // Check kaon + const bool tpcKa = std::fabs(track.tpcNSigmaKa()) < cfgCutNSig3 && std::fabs(track.tpcNSigmaKa()) < std::fabs(track.tpcNSigmaPi()) && std::fabs(track.tpcNSigmaKa()) < std::fabs(track.tpcNSigmaPr()); + const bool tofKa = track.hasTOF() && std::fabs(track.tofNSigmaKa()) < cfgCutNSig3 && std::fabs(track.tofNSigmaKa()) < std::fabs(track.tofNSigmaPi()) && std::fabs(track.tofNSigmaKa()) < std::fabs(track.tofNSigmaPr()); + const bool tofKaTight = track.hasTOF() && std::fabs(track.tofNSigmaKa()) < cfgCutNSig2; + const bool isKa = (pt >= cfgCutKaPtMin && + ((p <= cfgCutKaThrsldP && ((tpcKa && !track.hasTOF()) || (tpcKa && tofKa))) || + (p > cfgCutKaThrsldP && tpcKa && + ((tofKa && p <= cfgCutKaP3) || (tofKaTight && p > cfgCutKaP3))))); + + // Check proton + const bool tpcPr = std::fabs(track.tpcNSigmaPr()) < cfgCutNSig3 && std::fabs(track.tpcNSigmaPr()) < std::fabs(track.tpcNSigmaPi()) && std::fabs(track.tpcNSigmaPr()) < std::fabs(track.tpcNSigmaKa()); + const bool tofPr = track.hasTOF() && std::fabs(track.tofNSigmaPr()) < cfgCutNSig3 && std::fabs(track.tofNSigmaPr()) < std::fabs(track.tofNSigmaPi()) && std::fabs(track.tofNSigmaPr()) < std::fabs(track.tofNSigmaKa()); + const bool isPr = (pt >= cfgCutPrPtMin && + ((p <= cfgCutPrThrsldP && ((tpcPr && !track.hasTOF()) || (tpcPr && tofPr))) || + (p > cfgCutPrThrsldP && tpcPr && tofPr))); + + if (!isPi && !isKa && !isPr) { // Reject tracks that are not identified as any particle + return PIDType::kNone; } - return false; - } - - // PID selction cuts for Low momentum Pions - template - bool selPi(T const& track) - { - if (track.pt() >= cfgCutPiPtMin && - track.p() <= cfgCutPiThrsldP) { - if (!track.hasTOF() && - std::fabs(track.tpcNSigmaPi()) < cfgCutNSig2) { - return true; - } - - if (track.hasTOF() && - std::fabs(track.tpcNSigmaPi()) < cfgCutNSig2 && - std::fabs(track.tofNSigmaPi()) < cfgCutNSig3) { - return true; - } - } else if (track.hasTOF() && - track.p() > cfgCutPiThrsldP && - std::fabs(track.tpcNSigmaPi()) < cfgCutNSig3 && - std::fabs(track.tofNSigmaPi()) < cfgCutNSig3) { - - return true; + if (isPi) { + return PIDType::kPions; + } else if (isKa) { + return PIDType::kKaons; + } else if (isPr) { + return PIDType::kProtons; } - return false; + return PIDType::kNone; } - // PID selction cuts for Low momentum Kaons - template - bool selKa(T const& track) + template + float getCorrectedWeight(T1 hWeightPt, T1 hPurePt, float pt, bool cfgWeightPt, bool cfgPurity) { - if (track.pt() >= cfgCutKaPtMin && - track.p() <= cfgCutKaThrsldP) { - if (!track.hasTOF() && - std::fabs(track.tpcNSigmaKa()) < cfgCutNSig2) { - return true; - } - - if (track.hasTOF() && - std::fabs(track.tpcNSigmaKa()) < cfgCutNSig2 && - std::fabs(track.tofNSigmaKa()) < cfgCutNSig3) { - return true; - } - } - if (track.hasTOF() && - track.p() > cfgCutKaThrsldP && - std::fabs(track.tpcNSigmaKa()) < cfgCutNSig3 && - ((std::fabs(track.tofNSigmaKa()) < cfgCutNSig3 && track.p() <= cfgCutKaP3) || - (std::fabs(track.tofNSigmaKa()) < cfgCutNSig2 && track.p() > cfgCutKaP3))) { + float weight = 1.0; + float purity = 1.0; - return true; + if (cfgPurity) { + purity = hPurePt->GetBinContent(hPurePt->FindBin(pt)); } - return false; - } - - // PID selction cuts for Low momentum Protons - template - bool selPr(T const& track) - { - - if (track.pt() >= cfgCutPrPtMin && - track.p() <= cfgCutPrThrsldP) { - if (!track.hasTOF() && - std::fabs(track.tpcNSigmaPr()) < cfgCutNSig2) { - return true; - } - - if (track.hasTOF() && - std::fabs(track.tpcNSigmaPr()) < cfgCutNSig2 && - std::fabs(track.tofNSigmaPr()) < cfgCutNSig3) { - return true; - } - } else if (track.hasTOF() && - track.p() > cfgCutPrThrsldP && - std::fabs(track.tpcNSigmaPr()) < cfgCutNSig3 && - std::fabs(track.tofNSigmaPr()) < cfgCutNSig3) { - - return true; + if (cfgWeightPt) { + float weightPt = hWeightPt->GetBinContent(hWeightPt->FindBin(pt)); + weight = purity * weightPt; } - return false; + return weight; } // Fill hist before selection cuts: @@ -636,8 +533,7 @@ struct MeanPtFlucId { hist.fill(HIST("QA/before/h_VtxZ"), col.posZ()); hist.fill(HIST("QA/before/h_Counts"), 2); hist.fill(HIST("QA/before/h_NTPC"), col.multNTracksHasTPC()); - hist.fill(HIST("QA/before/h_Cent"), col.centFT0C()); - hist.fill(HIST("QA/after/h_CentM"), col.centFT0M()); + hist.fill(HIST("QA/before/h_CentM"), col.centFT0M()); hist.fill(HIST("QA/before/h_NFT0M"), col.multFT0M()); } @@ -647,34 +543,28 @@ struct MeanPtFlucId { { hist.fill(HIST("QA/after/h_VtxZ"), col.posZ()); hist.fill(HIST("QA/after/h_Counts"), 2); - hist.fill(HIST("QA/after/h_NTPC"), col.multNTracksHasTPC()); - hist.fill(HIST("QA/after/h_Cent"), col.centFT0C()); - hist.fill(HIST("QA/after/h_CentM"), col.centFT0M()); - hist.fill(HIST("QA/after/h_NFT0M"), col.multFT0M()); - hist.fill(HIST("QA/after/h2_NTPC_NFT0M"), col.multFT0M(), col.multNTracksHasTPC()); - hist.fill(HIST("QA/after/h2_NTPC_Cent"), col.centFT0C(), col.multNTracksHasTPC()); - hist.fill(HIST("QA/after/h2_NTPC_CentM"), col.centFT0M(), col.multNTracksHasTPC()); - hist.fill(HIST("QA/after/p_NTPC_Cent"), col.centFT0C(), col.multNTracksHasTPC()); - hist.fill(HIST("QA/after/p_NTPC_NFT0M"), col.multFT0M(), col.multNTracksHasTPC()); + hist.fill(HIST("QA/after/h_NTPC"), nTPC); + hist.fill(HIST("QA/after/h_CentM"), centFT0M); + hist.fill(HIST("QA/after/h_NFT0M"), nFT0M); + hist.fill(HIST("QA/after/h2_NTPC_NFT0M"), nFT0M, nTPC); + hist.fill(HIST("QA/after/h2_NTPC_CentM"), centFT0M, nTPC); + hist.fill(HIST("QA/after/p_NTPC_CentM"), centFT0M, nTPC); + hist.fill(HIST("QA/after/p_NTPC_NFT0M"), nFT0M, nTPC); } // Fill Charged particles QA: template - void fillChargedQAHistos(T const& track, int nFT0M, double centFT0M) + void fillChargedQAHistos(T const& track, float centFT0M) { - hist.fill(HIST("QA/after/h_Eta"), track.eta()); - hist.fill(HIST("QA/after/h_Phi"), track.phi()); - hist.fill(HIST("QA/after/h_Pt"), track.pt()); - hist.fill(HIST("QA/after/h_Pt2"), track.pt() * track.pt()); - hist.fill(HIST("QA/after/h2_Pt_NFT0M"), track.pt(), nFT0M); - hist.fill(HIST("QA/after/h_PtEtaPhi_NFT0M"), track.pt(), track.eta(), track.phi(), nFT0M); - hist.fill(HIST("QA/after/h_PtEtaPhi_centFT0M"), track.pt(), track.eta(), track.phi(), centFT0M); - hist.fill(HIST("QA/after/h2_PvsPinner"), track.p(), track.tpcInnerParam()); - hist.fill(HIST("QA/after/h2_Pt_Eta"), track.eta(), track.pt()); - hist.fill(HIST("QA/after/h_DcaZ"), track.dcaZ()); - hist.fill(HIST("QA/after/h_DcaXY"), track.dcaXY()); - hist.fill(HIST("QA/after/h2_DcaXY"), track.pt(), track.dcaXY()); - hist.fill(HIST("QA/after/h2_DcaZ"), track.pt(), track.dcaZ()); + hist.fill(HIST("QA/Charged/h_Eta"), track.eta()); + hist.fill(HIST("QA/Charged/h_Phi"), track.phi()); + hist.fill(HIST("QA/Charged/h2_Pt_centFT0M"), centFT0M, track.pt()); + hist.fill(HIST("QA/Charged/h3_PtEtaPhi"), track.pt(), track.eta(), track.phi()); + hist.fill(HIST("QA/Charged/h2_Pt_Eta"), track.eta(), track.pt()); + hist.fill(HIST("QA/Charged/h_DcaZ"), track.dcaZ()); + hist.fill(HIST("QA/Charged/h_DcaXY"), track.dcaXY()); + hist.fill(HIST("QA/Charged/h2_DcaXY"), track.pt(), track.dcaXY()); + hist.fill(HIST("QA/Charged/h2_DcaZ"), track.pt(), track.dcaZ()); hist.fill(HIST("QA/after/h_TPCChi2perCluster"), track.tpcChi2NCl()); hist.fill(HIST("QA/after/h_ITSChi2perCluster"), track.itsChi2NCl()); @@ -689,95 +579,48 @@ struct MeanPtFlucId { hist.fill(HIST("QA/before/h2_TPCSignal"), track.p(), track.tpcSignal()); hist.fill(HIST("QA/before/h2_pvsm2"), track.mass() * track.mass(), track.p()); - hist.fill(HIST("QA/Pion/before/h2_TPCNsigma"), track.p(), track.tpcNSigmaPi()); + if (!track.hasTOF()) + hist.fill(HIST("QA/Pion/before/h2_TPCNsigma"), track.p(), track.tpcNSigmaPi()); + if (track.hasTOF()) + hist.fill(HIST("QA/Pion/before/h2_TPCNsigma_tof"), track.p(), track.tpcNSigmaPi()); hist.fill(HIST("QA/Pion/before/h2_TOFNsigma"), track.p(), track.tofNSigmaPi()); hist.fill(HIST("QA/Pion/before/h2_TpcTofNsigma"), track.tpcNSigmaPi(), track.tofNSigmaPi()); - hist.fill(HIST("QA/Proton/before/h2_TPCNsigma"), track.p(), track.tpcNSigmaPr()); + if (!track.hasTOF()) + hist.fill(HIST("QA/Proton/before/h2_TPCNsigma"), track.p(), track.tpcNSigmaPr()); + if (track.hasTOF()) + hist.fill(HIST("QA/Proton/before/h2_TPCNsigma_tof"), track.p(), track.tpcNSigmaPr()); hist.fill(HIST("QA/Proton/before/h2_TOFNsigma"), track.p(), track.tofNSigmaPr()); hist.fill(HIST("QA/Proton/before/h2_TpcTofNsigma"), track.tpcNSigmaPr(), track.tofNSigmaPr()); - hist.fill(HIST("QA/Kaon/before/h2_TPCNsigma"), track.p(), track.tpcNSigmaKa()); + if (!track.hasTOF()) + hist.fill(HIST("QA/Kaon/before/h2_TPCNsigma"), track.p(), track.tpcNSigmaKa()); + if (track.hasTOF()) + hist.fill(HIST("QA/Kaon/before/h2_TPCNsigma_tof"), track.p(), track.tpcNSigmaKa()); hist.fill(HIST("QA/Kaon/before/h2_TOFNsigma"), track.p(), track.tofNSigmaKa()); hist.fill(HIST("QA/Kaon/before/h2_TpcTofNsigma"), track.tpcNSigmaKa(), track.tofNSigmaKa()); - - hist.fill(HIST("QA/before/innerParam/h2_TOFSignal"), track.tpcInnerParam(), track.beta()); - hist.fill(HIST("QA/before/innerParam/h2_TPCSignal"), track.tpcInnerParam(), track.tpcSignal()); - hist.fill(HIST("QA/before/innerParam/h2_pvsm2"), track.mass() * track.mass(), track.tpcInnerParam()); - - hist.fill(HIST("QA/Pion/innerParam/before/h2_TPCNsigma"), track.tpcInnerParam(), track.tpcNSigmaPi()); - hist.fill(HIST("QA/Pion/innerParam/before/h2_TOFNsigma"), track.tpcInnerParam(), track.tofNSigmaPi()); - hist.fill(HIST("QA/Pion/innerParam/before/h2_TpcTofNsigma"), track.tpcNSigmaPi(), track.tofNSigmaPi()); - hist.fill(HIST("QA/Proton/innerParam/before/h2_TPCNsigma"), track.tpcInnerParam(), track.tpcNSigmaPr()); - hist.fill(HIST("QA/Proton/innerParam/before/h2_TOFNsigma"), track.tpcInnerParam(), track.tofNSigmaPr()); - hist.fill(HIST("QA/Proton/innerParam/before/h2_TpcTofNsigma"), track.tpcNSigmaPr(), track.tofNSigmaPr()); - hist.fill(HIST("QA/Kaon/innerParam/before/h2_TPCNsigma"), track.tpcInnerParam(), track.tpcNSigmaKa()); - hist.fill(HIST("QA/Kaon/innerParam/before/h2_TOFNsigma"), track.tpcInnerParam(), track.tofNSigmaKa()); - hist.fill(HIST("QA/Kaon/innerParam/before/h2_TpcTofNsigma"), track.tpcNSigmaKa(), track.tofNSigmaKa()); } // Moments Calculation: - void moments(double pt, double weight, double& Q1, double& Q2, double& Q3, double& Q4) + void moments(float pt, float weight, double& Q1, double& Q2) { Q1 += pt * weight; - Q2 += pt * pt * weight; - Q3 += pt * pt * pt * weight; - Q4 += pt * pt * pt * pt * weight; + Q2 += pt * pt * weight * weight; } - template - float getCorrectedWeight(T1 hWeightPt, T1 hPurePt, T2 hWeightPtY, T2 hWeightPtEta, double pt, double rap, double eta, bool cfgWeightPt, bool cfgWeightPtY, bool cfgWeightPtEta, bool cfgPurity) + template + void fillIdParticleQAHistos(T const& track, float rap, float nSigmaTPC, float nSigmaTOF, float centFT0M, T1 hWeightPt, T1 hPurePt, bool cfgWeightPtId, bool cfgPurityId, double& NW, double& NW2, double& Q1, double& Q2) { - float weight = 1.0; - float purity = 1.0; - if (cfgPurity) { - purity = hPurePt->GetBinContent(hPurePt->FindBin(pt)); - } else { - purity = 1.0; - } - - if (cfgWeightPt) { - float weightPt = hWeightPt->GetBinContent(hWeightPt->FindBin(pt)); - weight = purity * weightPt; - } else if (cfgWeightPtY) { - float weightPtY = hWeightPtY->GetBinContent(hWeightPtY->FindBin(rap, pt)); - weight = purity * weightPtY; - } else if (cfgWeightPtEta) { - float weightPtEta = hWeightPtEta->GetBinContent(hWeightPtEta->FindBin(eta, pt)); - weight = purity * weightPtEta; - } else { - weight = 1.0; - } - return weight; - } + float pt = track.pt(); + float eta = track.eta(); + float phi = track.phi(); + float weight = getCorrectedWeight(hWeightPt, hPurePt, pt, cfgWeightPtId, cfgPurityId); - // Fill after PID cut QA hist: - template - void fillIdParticleQAHistos(T const& track, double rap, double nSigmaTPC, double nSigmaTOF, int nFT0M, double centFT0M, T1 hWeightPt, T1 hPurePt, T2 hWeightPtY, T2 hWeightPtEta, bool cfgWeightPtId, bool cfgWeightPtYId, bool cfgWeightPtEtaId, bool cfgPurityId, int& N, double& NW, double& Q1, double& Q2, double& Q3, double& Q4, float& weight) - { - double pt = track.pt(); - double eta = track.eta(); - weight = getCorrectedWeight(hWeightPt, hPurePt, hWeightPtY, hWeightPtEta, pt, rap, eta, cfgWeightPtId, cfgWeightPtYId, cfgWeightPtEtaId, cfgPurityId); - if (weight == 0) + if (std::abs(weight) < cfgMinWeight) return; NW += weight; - N++; - moments(pt, weight, Q1, Q2, Q3, Q4); - - if (cfgWeightPtYId) - hist.fill(HIST(Dire[Mode]) + HIST("h2_Pt_Rap_weighted"), rap, pt, weight); - - if (cfgWeightPtEtaId) - hist.fill(HIST(Dire[Mode]) + HIST("h2_Pt_Eta_weighted"), eta, pt, weight); - - hist.fill(HIST(Dire[Mode]) + HIST("h_Pt_weighted"), pt, weight); - hist.fill(HIST(Dire[Mode]) + HIST("h_Pt2_weighted"), pt * pt, weight); + NW2 += weight * weight; + moments(pt, weight, Q1, Q2); - hist.fill(HIST(Dire[Mode]) + HIST("h_Pt"), pt); - hist.fill(HIST(Dire[Mode]) + HIST("h_Pt2"), pt * pt); - hist.fill(HIST(Dire[Mode]) + HIST("h2_Pt_NFT0M"), pt, nFT0M); - hist.fill(HIST(Dire[Mode]) + HIST("h_PtEtaPhi_NFT0M"), pt, eta, track.phi(), nFT0M); - hist.fill(HIST(Dire[Mode]) + HIST("h_PtEtaPhi_centFT0M"), pt, eta, track.phi(), centFT0M); - hist.fill(HIST(Dire[Mode]) + HIST("h2_Pt_Eta"), eta, pt); if (track.sign() > 0) { hist.fill(HIST(Dire[Mode]) + HIST("h_PtPos"), pt); } @@ -785,50 +628,46 @@ struct MeanPtFlucId { hist.fill(HIST(Dire[Mode]) + HIST("h_PtNeg"), pt); } + if (cfgWeightPtEtaId) + hist.fill(HIST(Dire[Mode]) + HIST("h2_Pt_Eta_weighted"), eta, pt, weight); + + hist.fill(HIST(Dire[Mode]) + HIST("h_Pt_weighted"), pt, weight); + hist.fill(HIST(Dire[Mode]) + HIST("h2_Pt_centFT0M"), centFT0M, pt); + hist.fill(HIST(Dire[Mode]) + HIST("h3_PtEtaPhi"), pt, eta, phi); + hist.fill(HIST(Dire[Mode]) + HIST("h2_Pt_Eta"), eta, pt); hist.fill(HIST(Dire[Mode]) + HIST("h_Eta"), eta); - hist.fill(HIST(Dire[Mode]) + HIST("h_Phi"), track.phi()); + hist.fill(HIST(Dire[Mode]) + HIST("h_Phi"), phi); hist.fill(HIST(Dire[Mode]) + HIST("h_Rap"), rap); - hist.fill(HIST(Dire[Mode]) + HIST("h2_Pt_Rap"), rap, pt); hist.fill(HIST(Dire[Mode]) + HIST("h_DcaZ"), track.dcaZ()); hist.fill(HIST(Dire[Mode]) + HIST("h_DcaXY"), track.dcaXY()); hist.fill(HIST(Dire[Mode]) + HIST("h2_DcaZ"), pt, track.dcaZ()); hist.fill(HIST(Dire[Mode]) + HIST("h2_DcaXY"), pt, track.dcaXY()); - hist.fill(HIST(Dire[Mode]) + HIST("h2_TPCNsigma_El"), track.p(), track.tpcNSigmaEl()); - hist.fill(HIST(Dire[Mode]) + HIST("h2_TOFNsigma_El"), track.p(), track.tofNSigmaEl()); hist.fill(HIST(Dire[Mode]) + HIST("h2_TPCNsigma"), track.p(), nSigmaTPC); hist.fill(HIST(Dire[Mode]) + HIST("h2_TOFNsigma"), track.p(), nSigmaTOF); hist.fill(HIST(Dire[Mode]) + HIST("h2_TpcTofNsigma"), nSigmaTPC, nSigmaTOF); hist.fill(HIST(Dire[Mode]) + HIST("h2_TPCSignal"), track.p(), track.tpcSignal()); + hist.fill(HIST(Dire[Mode]) + HIST("innerParam/h2_TPCSignal"), track.p(), track.tpcSignal()); hist.fill(HIST(Dire[Mode]) + HIST("h2_TOFSignal"), track.p(), track.beta()); hist.fill(HIST(Dire[Mode]) + HIST("h2_pvsm2"), track.mass() * track.mass(), track.p()); + hist.fill(HIST("QA/after/h2_TPCSignal"), track.p(), track.tpcSignal()); + hist.fill(HIST("QA/after/innerParam/h2_TPCSignal"), track.p(), track.tpcSignal()); hist.fill(HIST("QA/after/h2_TOFSignal"), track.p(), track.beta()); hist.fill(HIST("QA/after/h2_pvsm2"), track.mass() * track.mass(), track.p()); - - hist.fill(HIST(Dire[Mode]) + HIST("innerParam/h2_TPCNsigma_El"), track.tpcInnerParam(), track.tpcNSigmaEl()); - hist.fill(HIST(Dire[Mode]) + HIST("innerParam/h2_TOFNsigma_El"), track.tpcInnerParam(), track.tofNSigmaEl()); - hist.fill(HIST(Dire[Mode]) + HIST("innerParam/h2_TPCNsigma"), track.tpcInnerParam(), nSigmaTPC); - hist.fill(HIST(Dire[Mode]) + HIST("innerParam/h2_TOFNsigma"), track.tpcInnerParam(), nSigmaTOF); - hist.fill(HIST(Dire[Mode]) + HIST("innerParam/h2_TpcTofNsigma"), nSigmaTPC, nSigmaTOF); - hist.fill(HIST(Dire[Mode]) + HIST("innerParam/h2_TPCSignal"), track.tpcInnerParam(), track.tpcSignal()); - hist.fill(HIST(Dire[Mode]) + HIST("innerParam/h2_TOFSignal"), track.tpcInnerParam(), track.beta()); - hist.fill(HIST(Dire[Mode]) + HIST("innerParam/h2_pvsm2"), track.mass() * track.mass(), track.tpcInnerParam()); - hist.fill(HIST("QA/after/innerParam/h2_TPCSignal"), track.tpcInnerParam(), track.tpcSignal()); - hist.fill(HIST("QA/after/innerParam/h2_TOFSignal"), track.tpcInnerParam(), track.beta()); - hist.fill(HIST("QA/after/innerParam/h2_pvsm2"), track.mass() * track.mass(), track.tpcInnerParam()); } template - void fillPtMCHist(double pt, double eta, double rap, int nFT0M, int pid, int pdgCodePos, int pdgCodeNeg) + void fillPtMCHist(bool cfgGen, float pt, float eta, float rap, float phi, float centFT0M, int pid, int pdgCodePos, int pdgCodeNeg) { - hist.fill(HIST(Dire[Mode]) + HIST("h_PtTruth"), pt); - hist.fill(HIST(Dire[Mode]) + HIST("h_PtTruth2"), pt * pt); - hist.fill(HIST(Dire[Mode]) + HIST("h_EtaTruth"), eta); - hist.fill(HIST(Dire[Mode]) + HIST("h_RapTruth"), rap); - hist.fill(HIST(Dire[Mode]) + HIST("h2_PtTruth_NFT0M"), pt, nFT0M); - hist.fill(HIST(Dire[Mode]) + HIST("h2_PtTruth_Rap"), rap, pt); - hist.fill(HIST(Dire[Mode]) + HIST("h2_PtTruth_Eta"), eta, pt); + if (cfgGen) { + hist.fill(HIST(Dire[Mode]) + HIST("h_EtaTruth"), eta); + hist.fill(HIST(Dire[Mode]) + HIST("h_RapTruth"), rap); + hist.fill(HIST(Dire[Mode]) + HIST("h2_PtTruth_centFT0M"), centFT0M, pt); + hist.fill(HIST(Dire[Mode]) + HIST("h2_Pt_EtaTruth"), eta, pt); + hist.fill(HIST(Dire[Mode]) + HIST("h_PhiTruth"), phi); + hist.fill(HIST(Dire[Mode]) + HIST("h_PtEtaPhiTruth"), pt, eta, phi); + } if (pid == pdgCodePos) { hist.fill(HIST(Dire[Mode]) + HIST("h_PtPosTruth"), pt); @@ -839,420 +678,301 @@ struct MeanPtFlucId { } template - void fillAnalysisHistos(int nTPC, int nFT0M, int N, double NW, double Q1, double Q2, double Q3, double Q4) + void fillAnalysisHistos(bool cfgCorrection, float centFT0M, double nW, double nW2, double Q1, double Q2) { - if (NW == 0) { + if (nW == 0) { return; } - double twopart1 = ((Q1 * Q1) - Q2); - double threepart1 = ((Q1 * Q1 * Q1) - (3 * Q2 * Q1) + 2 * Q3); - double fourpart1 = ((Q1 * Q1 * Q1 * Q1) - (6 * Q2 * Q1 * Q1) + (3 * Q2 * Q2) + (8 * Q3 * Q1) - 6 * Q4); - - hist.fill(HIST(Dire[Mode]) + HIST("h_Mult"), N); - hist.fill(HIST(Dire[Mode]) + HIST("h_Mult_weighted"), NW); - hist.fill(HIST(Dire[Mode]) + HIST("h_Q1"), nTPC, Q1, nFT0M); - hist.fill(HIST(Dire[Mode]) + HIST("h_Q2"), nTPC, Q2, nFT0M); - hist.fill(HIST(Dire[Mode]) + HIST("h_Q3"), nTPC, Q3, nFT0M); - hist.fill(HIST(Dire[Mode]) + HIST("h_Q4"), nTPC, Q4, nFT0M); - - if (NW > 1) { - double meanPt = Q1 / NW; - double nPair = (NW * (NW - 1)); - double twopart = twopart1 / nPair; - double checkNDenoVar = (1 / std::sqrt(1 - (1 / NW))); - hist.fill(HIST(Dire[Mode]) + HIST("h_mean_pT"), meanPt); - hist.fill(HIST(Dire[Mode]) + HIST("p_mean_pT_Mult_var"), nTPC, meanPt); - hist.fill(HIST(Dire[Mode]) + HIST("p_mean_pT_MultFT0M"), nFT0M, meanPt); - hist.fill(HIST(Dire[Mode]) + HIST("h_mean_pT_Mult_var"), nTPC, meanPt, nFT0M); - - hist.fill(HIST(Dire[Mode]) + HIST("h_Q1_var"), nTPC, Q1, nFT0M); - hist.fill(HIST(Dire[Mode]) + HIST("h_N_var"), nTPC, N, nFT0M); - hist.fill(HIST(Dire[Mode]) + HIST("h_twopart_nume_Mult_var"), nTPC, twopart1, nFT0M); - hist.fill(HIST(Dire[Mode]) + HIST("h_twopart_deno_Mult_var"), nTPC, nPair, nFT0M); - hist.fill(HIST(Dire[Mode]) + HIST("h_twopart_Mult_var"), nTPC, twopart, nFT0M); - hist.fill(HIST(Dire[Mode]) + HIST("p_CheckNCh"), nTPC, checkNDenoVar); - hist.fill(HIST(Dire[Mode]) + HIST("h_CheckNCh"), nTPC, checkNDenoVar, nFT0M); - hist.fill(HIST(Dire[Mode]) + HIST("p_twopart_MultFT0M"), nFT0M, twopart); - - if (NW > 2) { - double nTriplet = (NW * (NW - 1) * (NW - 2)); - double threepart = threepart1 / nTriplet; - hist.fill(HIST(Dire[Mode]) + HIST("h_mean_pT_Mult_skew"), nTPC, meanPt, nFT0M); - hist.fill(HIST(Dire[Mode]) + HIST("h_twopart_Mult_skew"), nTPC, twopart, nFT0M); - hist.fill(HIST(Dire[Mode]) + HIST("h_threepart_Mult_skew"), nTPC, threepart, nFT0M); - - if (NW > 3) { - double nQuad = (NW * (NW - 1) * (NW - 2) * (NW - 3)); - double fourpart = fourpart1 / nQuad; - hist.fill(HIST(Dire[Mode]) + HIST("h_mean_pT_Mult_kurto"), nTPC, meanPt, nFT0M); - hist.fill(HIST(Dire[Mode]) + HIST("h_twopart_Mult_kurto"), nTPC, twopart, nFT0M); - hist.fill(HIST(Dire[Mode]) + HIST("h_threepart_Mult_kurto"), nTPC, threepart, nFT0M); - hist.fill(HIST(Dire[Mode]) + HIST("h_fourpart_Mult_kurto"), nTPC, fourpart, nFT0M); - } - } - } - } - template - void fillMeanPt(int N, int nFT0M, double pt, float w) - { - hist.fill(HIST(Dire[Mode]) + HIST("h2_pt_nch"), N, pt, w); - hist.fill(HIST(Dire[Mode]) + HIST("h2_pt_nch_prof"), N, pt, w); - hist.fill(HIST(Dire[Mode]) + HIST("h3_nft0m_pt_nch"), N, pt, nFT0M, w); - } + hist.fill(HIST(Dire[Mode]) + HIST("h_Mult"), nW); - template - void fillHistos(T const& col, U const& tracks) - { - int nCh = 0, nTPC = 0, nFT0M = 0; - double centFT0M = 0, vtxZ = 0, vtxZSim = 0; - double nChW = 0; - - int nPi = 0, nKa = 0, nPr = 0; - double nPiW = 0, nKaW = 0, nPrW = 0; - double ptCh = 0, q1Ch = 0, q2Ch = 0, q3Ch = 0, q4Ch = 0; - double ptPi = 0, q1Pi = 0, q2Pi = 0, q3Pi = 0, q4Pi = 0; - double ptPr = 0, q1Pr = 0, q2Pr = 0, q3Pr = 0, q4Pr = 0; - double ptKa = 0, q1Ka = 0, q2Ka = 0, q3Ka = 0, q4Ka = 0; - - int nChSim = 0, nSim = 0, nFT0CSim = 0; - int nPiSim = 0, nKaSim = 0, nPrSim = 0; - double eta = 0, etaSim = -999, rapSim = -999; - double ptChSim = 0, q1ChSim = 0, q2ChSim = 0, q3ChSim = 0, q4ChSim = 0; - double ptPiSim = 0, q1PiSim = 0, q2PiSim = 0, q3PiSim = 0, q4PiSim = 0; - double ptPrSim = 0, q1PrSim = 0, q2PrSim = 0, q3PrSim = 0, q4PrSim = 0; - double ptKaSim = 0, q1KaSim = 0, q2KaSim = 0, q3KaSim = 0, q4KaSim = 0; - - float wghtCh = 1.0, wghtPi = 1.0, wghtKa = 1.0, wghtPr = 1.0; + double nPair = 0., meanPt = 0., twopart1 = 0., twopart = 0.; - if constexpr (DataFlag) { - nTPC = col.multNTracksHasTPC(); - nFT0M = col.multFT0M(); - centFT0M = col.centFT0M(); - vtxZ = col.posZ(); - - fillAfterQAHistos(col); - for (const auto& track : tracks) { - if (!selTrack(track)) { - continue; - } - - double nSigmaTPCPi = track.tpcNSigmaPi(); - double nSigmaTPCKa = track.tpcNSigmaKa(); - double nSigmaTPCPr = track.tpcNSigmaPr(); - double nSigmaTOFPi = track.tofNSigmaPi(); - double nSigmaTOFKa = track.tofNSigmaKa(); - double nSigmaTOFPr = track.tofNSigmaPr(); - double rapPi = track.rapidity(MassPiPlus); - double rapKa = track.rapidity(MassKPlus); - double rapPr = track.rapidity(MassProton); - - if (std::fabs(track.eta()) < 0.8) { - ptCh = track.pt(); - wghtCh = getCorrectedWeight(hWeightPt, hPurePt, hWeightPtRap, hWeightPtEta, ptCh, 0.0, eta, cfgWeightPtCh, false, false, false); - nChW += wghtCh; - nCh++; - moments(ptCh, wghtCh, q1Ch, q2Ch, q3Ch, q4Ch); - - hist.fill(HIST("QA/after/h_Pt_weighted"), ptCh, wghtCh); - hist.fill(HIST("QA/after/h_Pt2_weighted"), ptCh * ptCh, wghtCh); + if (cfgCorrection) { + nPair = nW * nW - nW2; + } else { + if (nW > 1) { + nPair = nW * (nW - 1); + } + } - fillChargedQAHistos(track, nFT0M, centFT0M); + if (nPair > 0) { + meanPt = Q1 / nW; + twopart1 = (Q1 * Q1 - Q2); + twopart = twopart1 / nPair; - fillBeforePIDQAHistos(track); + hist.fill(HIST(Dire[Mode]) + HIST("h_mean_pT_Mult_var"), centFT0M, meanPt); + hist.fill(HIST(Dire[Mode]) + HIST("h_twopart_Mult_var"), centFT0M, twopart); + hist.fill(HIST(Dire[Mode]) + HIST("p_mean_pT_CentFT0M"), centFT0M, meanPt); + hist.fill(HIST(Dire[Mode]) + HIST("p_twopart_CentFT0M"), centFT0M, twopart); + hist.fill(HIST(Dire[Mode]) + HIST("h_twopart1_CentFT0M"), centFT0M, twopart1); + } - if (rejectTracks(track)) { - return; - } + hist.fill(HIST(Dire[Mode]) + HIST("h_Mult"), nW); + hist.fill(HIST(Dire[Mode]) + HIST("h_N_CentFT0M"), centFT0M, nW); + hist.fill(HIST(Dire[Mode]) + HIST("h_Npair_CentFT0M"), centFT0M, nPair); + hist.fill(HIST(Dire[Mode]) + HIST("h_Q1_CentFT0M"), centFT0M, Q1); + hist.fill(HIST(Dire[Mode]) + HIST("h_Q2_CentFT0M"), centFT0M, Q2); + } - if (selPi(track)) { - fillIdParticleQAHistos(track, rapPi, nSigmaTPCPi, nSigmaTOFPi, nFT0M, centFT0M, hWeightPtPi, hPurePtPi, hWeightPtRapPi, hWeightPtEtaPi, cfgWeightPtId, cfgWeightPtYId, cfgWeightPtEtaId, cfgPurityId, nPi, nPiW, q1Pi, q2Pi, q3Pi, q4Pi, wghtPi); - } + template + void fillRecoHistos(C const& col, T const& tracks) + { + double nChW = 0., nChW2 = 0., q1Ch = 0., q2Ch = 0.; + float wghtCh = 1.0; + double nPiW = 0., nPiW2 = 0., q1Pi = 0., q2Pi = 0.; + double nKaW = 0., nKaW2 = 0., q1Ka = 0., q2Ka = 0.; + double nPrW = 0., nPrW2 = 0., q1Pr = 0., q2Pr = 0.; + float pt = 0., eta = 0., phi = 0.; - if (selKa(track)) { - fillIdParticleQAHistos(track, rapKa, nSigmaTPCKa, nSigmaTOFKa, nFT0M, centFT0M, hWeightPtKa, hPurePtKa, hWeightPtRapKa, hWeightPtEtaKa, cfgWeightPtId, cfgWeightPtYId, cfgWeightPtEtaId, cfgPurityId, nKa, nKaW, q1Ka, q2Ka, q3Ka, q4Ka, wghtKa); - } + hist.fill(HIST("QA/h_collisions_info"), kTotCol); - if (selPr(track)) { - fillIdParticleQAHistos(track, rapPr, nSigmaTPCPr, nSigmaTOFPr, nFT0M, centFT0M, hWeightPtPr, hPurePtPr, hWeightPtRapPr, hWeightPtEtaPr, cfgWeightPtId, cfgWeightPtYId, cfgWeightPtEtaId, cfgPurityId, nPr, nPrW, q1Pr, q2Pr, q3Pr, q4Pr, wghtPr); - } - } - } - } else if constexpr (RecoFlag) { - if (!col.has_mcCollision()) { - LOGF(warning, "No MC collision for this collision, skip..."); + if constexpr (DataFlag) { + if (!selRun3Col(col)) { return; } - nTPC = col.multNTracksHasTPC(); - nFT0M = col.multFT0M(); - centFT0M = col.centFT0M(); - vtxZ = col.posZ(); - - fillAfterQAHistos(col); + } - vtxZSim = col.mcCollision().posZ(); - for (const auto& track : tracks) { - if (!track.has_mcParticle()) { - LOGF(warning, "No MC Particle for this track, skip..."); - continue; - } - auto mcPart = track.mcParticle(); - int pid = mcPart.pdgCode(); - - double nSigmaTPCPi = track.tpcNSigmaPi(); - double nSigmaTPCKa = track.tpcNSigmaKa(); - double nSigmaTPCPr = track.tpcNSigmaPr(); - double nSigmaTOFPi = track.tofNSigmaPi(); - double nSigmaTOFKa = track.tofNSigmaKa(); - double nSigmaTOFPr = track.tofNSigmaPr(); - double rapPi = track.rapidity(MassPiPlus); - double rapKa = track.rapidity(MassKPlus); - double rapPr = track.rapidity(MassProton); - - //______________________________Reconstructed Level____________________________________________________// - - if (selTrack(track)) { - - eta = track.eta(); - ptCh = track.pt(); - wghtCh = getCorrectedWeight(hWeightPt, hPurePt, hWeightPtRap, hWeightPtEta, ptCh, 0.0, eta, cfgWeightPtCh, false, false, false); - nChW += wghtCh; - nCh++; - moments(ptCh, wghtCh, q1Ch, q2Ch, q3Ch, q4Ch); - fillChargedQAHistos(track, nFT0M, centFT0M); - - hist.fill(HIST("QA/after/h_Pt_weighted"), ptCh, wghtCh); - hist.fill(HIST("QA/after/h_Pt2_weighted"), ptCh * ptCh, wghtCh); - - fillBeforePIDQAHistos(track); - - if (cfgRejTrk == true && rejectTracks(track)) { - return; - } + hist.fill(HIST("QA/h_collisions_info"), kPassSelCol); - if (selPi(track)) { - ptPi = track.pt(); - fillIdParticleQAHistos(track, rapPi, nSigmaTPCPi, nSigmaTOFPi, nFT0M, centFT0M, hWeightPtPi, hPurePtPi, hWeightPtRapPi, hWeightPtEtaPi, cfgWeightPtId, cfgWeightPtYId, cfgWeightPtEtaId, cfgPurityId, nPi, nPiW, q1Pi, q2Pi, q3Pi, q4Pi, wghtPi); - if (std::abs(pid) == kPiPlus) { - fillPtMCHist(ptPi, eta, rapPi, nFT0M, pid, kPiPlus, kPiMinus); - } - } - if (selKa(track)) { - ptKa = track.pt(); - fillIdParticleQAHistos(track, rapKa, nSigmaTPCKa, nSigmaTOFKa, nFT0M, centFT0M, hWeightPtKa, hPurePtKa, hWeightPtRapKa, hWeightPtEtaKa, cfgWeightPtId, cfgWeightPtYId, cfgWeightPtEtaId, cfgPurityId, nKa, nKaW, q1Ka, q2Ka, q3Ka, q4Ka, wghtKa); - if (std::abs(pid) == kKPlus) { - fillPtMCHist(ptKa, eta, rapKa, nFT0M, pid, kKPlus, kKMinus); - } - } + fillAfterQAHistos(col); - if (selPr(track)) { - ptPr = track.pt(); - fillIdParticleQAHistos(track, rapPr, nSigmaTPCPr, nSigmaTOFPr, nFT0M, centFT0M, hWeightPtPr, hPurePtPr, hWeightPtRapPr, hWeightPtEtaPr, cfgWeightPtId, cfgWeightPtYId, cfgWeightPtEtaId, cfgPurityId, nPr, nPrW, q1Pr, q2Pr, q3Pr, q4Pr, wghtPr); - if (std::abs(pid) == kProton) { - fillPtMCHist(ptPr, eta, rapPr, nFT0M, pid, kProton, kProtonBar); - } - } - } + for (auto const& track : tracks) { + float nSigmaTPCPi = track.tpcNSigmaPi(); + float nSigmaTPCKa = track.tpcNSigmaKa(); + float nSigmaTPCPr = track.tpcNSigmaPr(); + float nSigmaTOFPi = track.tofNSigmaPi(); + float nSigmaTOFKa = track.tofNSigmaKa(); + float nSigmaTOFPr = track.tofNSigmaPr(); + float rapPi = track.rapidity(MassPiPlus); + float rapKa = track.rapidity(MassKPlus); + float rapPr = track.rapidity(MassProton); - //___________________________________Truth Level____________________________________________________// - if (!mcPart.isPhysicalPrimary()) { - continue; - } - auto charge = 0.; - auto* pd = pdg->GetParticle(pid); - if (pd != nullptr) { - charge = pd->Charge(); - } - if (std::fabs(charge) < 1e-3) { - continue; - } - if (std::abs(pid) != kElectron && std::abs(pid) != kMuonMinus && std::abs(pid) != kPiPlus && std::abs(pid) != kKPlus && std::abs(pid) != kProton) { + if constexpr (RecoFlag) { + if (!track.has_mcParticle()) { + hist.fill(HIST("Tracks/h_tracks_info"), kTracksBeforeHasMcParticle); continue; } + } + hist.fill(HIST("Tracks/h_tracks_info"), kAllTracks); - if (std::fabs(mcPart.eta()) < 0.8) { - nSim++; + if (!selTrack(track)) { + continue; + } + hist.fill(HIST("Tracks/h_tracks_info"), kAllSelPassed); + + pt = track.pt(); + if constexpr (RecoFlag) { + hist.fill(HIST("Tracks/h2_tracks_pid_before_sel"), track.mcParticle().pdgCode(), track.pt()); + + auto mc = track.template mcParticle_as(); + pt = mc.pt(); + eta = mc.eta(); + phi = mc.phi(); + + if (mc.isPhysicalPrimary()) { + hist.fill(HIST("QA/after/h_DCAxy_primary"), track.dcaXY()); + hist.fill(HIST("QA/after/h_DCAz_primary"), track.dcaZ()); + } else { + hist.fill(HIST("QA/after/h_DCAxy_secondary"), track.dcaXY()); + hist.fill(HIST("QA/after/h_DCAz_secondary"), track.dcaZ()); } + } - if (mcPart.eta() > -3.3 || mcPart.eta() < -2.1) { - nFT0CSim++; - } + // Charged particles: + wghtCh = getCorrectedWeight(hWeightPt, hPurePt, pt, cfgWeightPtCh, false); - if (mcPart.pt() > cfgCutPtMin && mcPart.pt() < cfgCutPtMax) { - - if (std::abs(mcPart.eta()) < 0.8) { - nChSim++; - ptChSim = mcPart.pt(); - etaSim = mcPart.eta(); - moments(ptChSim, 1.0, q1ChSim, q2ChSim, q3ChSim, q4ChSim); - hist.fill(HIST("Gen/Charged/h_PtTruth"), ptChSim); - hist.fill(HIST("Gen/Charged/h_PtTruth2"), ptChSim * ptChSim); - hist.fill(HIST("Gen/Charged/h2_PtTruth_NFT0M"), ptChSim, nFT0M); - hist.fill(HIST("Gen/Charged/h2_PtTruth_Eta"), etaSim, ptChSim); - hist.fill(HIST("Gen/Charged/h_EtaTruth"), etaSim); - hist.fill(HIST("Gen/Charged/h_PhiTruth"), mcPart.phi()); - - hist.fill(HIST("Gen/Charged/h_PhiTruth"), mcPart.phi()); - hist.fill(HIST("Gen/Charged/h_PtEtaPhi_NFT0M"), ptChSim, etaSim, mcPart.phi(), nFT0M); - hist.fill(HIST("Gen/Charged/h_PtEtaPhi_centFT0M"), ptChSim, etaSim, mcPart.phi(), centFT0M); - - if (std::abs(pid) == kPiPlus && mcPart.pt() >= cfgCutPiPtMin) { - rapSim = mcPart.y(); - nPiSim++; - ptPiSim = mcPart.pt(); - moments(ptPiSim, 1.0, q1PiSim, q2PiSim, q3PiSim, q4PiSim); - fillPtMCHist(ptPiSim, etaSim, rapSim, nFT0M, pid, kPiPlus, kPiMinus); - - hist.fill(HIST("Gen/Pion/h_PhiTruth"), mcPart.phi()); - hist.fill(HIST("Gen/Pion/h_PtEtaPhi_NFT0M"), ptPiSim, etaSim, mcPart.phi(), nFT0M); - hist.fill(HIST("Gen/Pion/h_PtEtaPhi_centFT0M"), ptPiSim, etaSim, mcPart.phi(), centFT0M); - } + if (std::abs(wghtCh) < cfgMinWeight) + return; - if (std::abs(pid) == kKPlus && mcPart.pt() >= cfgCutKaPtMin) { - nKaSim++; - ptKaSim = mcPart.pt(); - moments(ptKaSim, 1.0, q1KaSim, q2KaSim, q3KaSim, q4KaSim); - fillPtMCHist(ptKaSim, etaSim, rapSim, nFT0M, pid, kKPlus, kKMinus); + nChW += wghtCh; + nChW2 += wghtCh * wghtCh; + moments(pt, wghtCh, q1Ch, q2Ch); + hist.fill(HIST("QA/Charged/h_Pt"), track.pt()); + fillChargedQAHistos(track, centFT0M); - hist.fill(HIST("Gen/Kaon/h_PhiTruth"), mcPart.phi()); - hist.fill(HIST("Gen/Kaon/h_PtEtaPhi_NFT0M"), ptKaSim, etaSim, mcPart.phi(), nFT0M); - hist.fill(HIST("Gen/Kaon/h_PtEtaPhi_centFT0M"), ptKaSim, etaSim, mcPart.phi(), centFT0M); - } + fillBeforePIDQAHistos(track); - if (std::abs(pid) == kProton && mcPart.pt() >= cfgCutPrPtMin) { - nPrSim++; - ptPrSim = mcPart.pt(); - moments(ptPrSim, 1.0, q1PrSim, q2PrSim, q3PrSim, q4PrSim); - fillPtMCHist(ptPrSim, etaSim, rapSim, nFT0M, pid, kProton, kProtonBar); + // identified particles: + if (cfgRejTrk && rejectTracks(track)) { + continue; + } + auto selID = identifyParticle(track); + if (selID == PIDType::kPions && pt >= cfgCutPiPtMin) { + hist.fill(HIST("QA/Pion/h_Pt"), track.pt()); + fillIdParticleQAHistos(track, rapPi, nSigmaTPCPi, nSigmaTOFPi, centFT0M, hWeightPtPi, hPurePtPi, cfgWeightPtId, cfgPurityId, nPiW, nPiW2, q1Pi, q2Pi); + } + if (selID == PIDType::kKaons && pt >= cfgCutKaPtMin) { + hist.fill(HIST("QA/Kaon/h_Pt"), track.pt()); + fillIdParticleQAHistos(track, rapKa, nSigmaTPCKa, nSigmaTOFKa, centFT0M, hWeightPtKa, hPurePtKa, cfgWeightPtId, cfgPurityId, nKaW, nKaW2, q1Ka, q2Ka); + } + if (selID == PIDType::kProtons && pt >= cfgCutPrPtMin) { + hist.fill(HIST("QA/Proton/h_Pt"), track.pt()); + fillIdParticleQAHistos(track, rapPr, nSigmaTPCPr, nSigmaTOFPr, centFT0M, hWeightPtPr, hPurePtPr, cfgWeightPtId, cfgPurityId, nPrW, nPrW2, q1Pr, q2Pr); + } - hist.fill(HIST("Gen/Proton/h_PhiTruth"), mcPart.phi()); - hist.fill(HIST("Gen/Proton/h_PtEtaPhi_NFT0M"), ptPrSim, etaSim, mcPart.phi(), nFT0M); - hist.fill(HIST("Gen/Proton/h_PtEtaPhi_centFT0M"), ptPrSim, etaSim, mcPart.phi(), centFT0M); + if constexpr (RecoFlag) { + auto mc = track.template mcParticle_as(); + int pid = mc.pdgCode(); + if (selID == PIDType::kPions && pt >= cfgCutPiPtMin) { + if (std::abs(pid) == kPiPlus) { + hist.fill(HIST("QA/Pion/h_PtTruth"), pt); + fillPtMCHist(false, pt, eta, rapPi, phi, centFT0M, pid, kPiPlus, kPiMinus); + if (mc.isPhysicalPrimary()) { + hist.fill(HIST("QA/Pion/h_PtTruth_primary"), pt); + } else { + hist.fill(HIST("QA/Pion/h_PtTruth_secondary"), pt); } } } - } - - for (const auto& track : tracks) { - if (!track.has_mcParticle()) { - LOGF(warning, "No MC Particle for this track, skip..."); - continue; - } - auto mcPart = track.mcParticle(); - int pid = mcPart.pdgCode(); - - if (selTrack(track)) { - double pt = track.pt(); - double eta = track.eta(); - float wght = getCorrectedWeight(hWeightPt, hPurePt, hWeightPtRap, hWeightPtEta, pt, 0.0, eta, cfgWeightPtCh, false, false, false); - fillMeanPt(nCh, nFT0M, pt, wght); - - if (selPi(track)) { - float wghtId = getCorrectedWeight(hWeightPtPi, hPurePtPi, hWeightPtRapPi, hWeightPtEtaPi, pt, 0.0, eta, cfgWeightPtId, cfgWeightPtYId, cfgWeightPtEtaId, cfgPurityId); - fillMeanPt(nPi, nFT0M, pt, wghtId); - } - if (selKa(track)) { - float wghtId = getCorrectedWeight(hWeightPtKa, hPurePtKa, hWeightPtRapKa, hWeightPtEtaKa, pt, 0.0, eta, cfgWeightPtId, cfgWeightPtYId, cfgWeightPtEtaId, cfgPurityId); - fillMeanPt(nKa, nFT0M, pt, wghtId); - } - if (selPr(track)) { - float wghtId = getCorrectedWeight(hWeightPtPr, hPurePtPr, hWeightPtRapPr, hWeightPtEtaPr, pt, 0.0, eta, cfgWeightPtId, cfgWeightPtYId, cfgWeightPtEtaId, cfgPurityId); - fillMeanPt(nPr, nFT0M, pt, wghtId); + if (selID == PIDType::kKaons && pt >= cfgCutKaPtMin) { + if (std::abs(pid) == kKPlus) { + hist.fill(HIST("QA/Kaon/h_PtTruth"), pt); + fillPtMCHist(false, pt, eta, rapKa, phi, centFT0M, pid, kKPlus, kKMinus); + if (mc.isPhysicalPrimary()) { + hist.fill(HIST("QA/Kaon/h_PtTruth_primary"), pt); + } else { + hist.fill(HIST("QA/Kaon/h_PtTruth_secondary"), pt); + } } } - - if (!mcPart.isPhysicalPrimary()) { - continue; - } - auto charge = 0.; - auto* pd = pdg->GetParticle(pid); - if (pd != nullptr) { - charge = pd->Charge(); - } - if (std::fabs(charge) < 1e-3) { - continue; - } - if (std::abs(pid) != kElectron && std::abs(pid) != kMuonMinus && std::abs(pid) != kPiPlus && std::abs(pid) != kKPlus && std::abs(pid) != kProton) { - continue; - } - - if (mcPart.pt() > cfgCutPtMin && mcPart.pt() < cfgCutPtMax) { - - if (std::abs(mcPart.eta()) < 0.8) { - double pt = mcPart.pt(); - float wght = 1.0; - fillMeanPt(nChSim, nFT0M, pt, wght); - - if (std::abs(pid) == kPiPlus && mcPart.pt() >= cfgCutPiPtMin) { - fillMeanPt(nPiSim, nFT0M, pt, wght); - } - if (std::abs(pid) == kKPlus && mcPart.pt() >= cfgCutKaPtMin) { - fillMeanPt(nKaSim, nFT0M, pt, wght); - } - if (std::abs(pid) == kProton && mcPart.pt() >= cfgCutPrPtMin) { - fillMeanPt(nPrSim, nFT0M, pt, wght); + if (selID == PIDType::kProtons && pt >= cfgCutPrPtMin) { + if (std::abs(pid) == kProton) { + hist.fill(HIST("QA/Proton/h_PtTruth"), pt); + fillPtMCHist(false, pt, eta, rapPr, phi, centFT0M, pid, kProton, kProtonBar); + if (mc.isPhysicalPrimary()) { + hist.fill(HIST("QA/Proton/h_PtTruth_primary"), pt); + } else { + hist.fill(HIST("QA/Proton/h_PtTruth_secondary"), pt); } } } } + } + fillAnalysisHistos(cfgCorrection, centFT0M, nChW, nChW2, q1Ch, q2Ch); + fillAnalysisHistos(cfgCorrection, centFT0M, nPiW, nPiW2, q1Pi, q2Pi); + fillAnalysisHistos(cfgCorrection, centFT0M, nKaW, nKaW2, q1Ka, q2Ka); + fillAnalysisHistos(cfgCorrection, centFT0M, nPrW, nPrW2, q1Pr, q2Pr); + } - hist.fill(HIST("Gen/h_Counts"), 2); - hist.fill(HIST("QA/after/h_VtxZReco"), vtxZ); - hist.fill(HIST("Gen/h_VtxZ"), vtxZSim); - - if (nSim > 0) - hist.fill(HIST("Gen/h_NSim"), nSim); + template + void fillGenHistos(C const& mcCol, M const& mcParticles) + { + int nSim = 0; + double nChSim = 0., q1ChSim = 0., q2ChSim = 0.; + double nPiSim = 0., q1PiSim = 0., q2PiSim = 0.; + double nKaSim = 0., q1KaSim = 0., q2KaSim = 0.; + double nPrSim = 0., q1PrSim = 0., q2PrSim = 0.; + float pt = 0, eta = 0, phi = 0, rap = 0; + for (auto const& mcPart : mcParticles) { + if (!mcPart.isPhysicalPrimary()) { + continue; + } - if (nSim > 0 && nChSim > 0) - hist.fill(HIST("Gen/h2_NChSim_NSim"), nSim, nChSim); + auto pid = mcPart.pdgCode(); + if (std::abs(pid) != kElectron && std::abs(pid) != kMuonMinus && std::abs(pid) != kPiPlus && std::abs(pid) != kKPlus && std::abs(pid) != kProton) { + continue; + } - if (nSim > 0 && nTPC > 0) - hist.fill(HIST("Gen/h2_NTPC_NSim"), nSim, nTPC); + pt = mcPart.pt(); + eta = mcPart.eta(); + phi = mcPart.phi(); + if (std::abs(eta) < cfgCutEta) { + nSim++; + } - hist.fill(HIST("Gen/h_NTPC"), nTPC); - hist.fill(HIST("Gen/h_NFT0C"), nFT0CSim); - hist.fill(HIST("Gen/h2_NTPC_NFT0M"), nFT0M, nTPC); + if (pt >= cfgCutPtMin && pt < cfgCutPtMax && std::abs(eta) < cfgCutEta) { + nChSim++; + moments(pt, 1.0, q1ChSim, q2ChSim); + hist.fill(HIST("Gen/Charged/h_PtTruth"), pt); + hist.fill(HIST("Gen/Charged/h_EtaTruth"), eta); + hist.fill(HIST("Gen/Charged/h_PhiTruth"), phi); + hist.fill(HIST("Gen/Charged/h2_Pt_EtaTruth"), eta, pt); + hist.fill(HIST("Gen/Charged/h2_PtTruth_centFT0M"), centFT0M, pt); + hist.fill(HIST("Gen/Charged/h_PtEtaPhiTruth"), pt, eta, phi); + + rap = mcPart.y(); + if (std::abs(pid) == kPiPlus && mcPart.pt() > cfgCutPiPtMin) { + nPiSim++; + moments(pt, 1.0, q1PiSim, q2PiSim); + hist.fill(HIST("Gen/Pion/h_PtTruth"), pt); + fillPtMCHist(true, pt, eta, rap, phi, centFT0M, pid, kPiMinus, kPiMinus); + } + if (std::abs(pid) == kKPlus && mcPart.pt() > cfgCutKaPtMin) { + nKaSim++; + moments(pt, 1.0, q1KaSim, q2KaSim); + hist.fill(HIST("Gen/Kaon/h_PtTruth"), pt); + fillPtMCHist(true, pt, eta, rap, phi, centFT0M, pid, kKMinus, kKMinus); + } + if (std::abs(pid) == kProton && mcPart.pt() > cfgCutPrPtMin) { + nPrSim++; + moments(pt, 1.0, q1PrSim, q2PrSim); + hist.fill(HIST("Gen/Proton/h_PtTruth"), pt); + fillPtMCHist(true, pt, eta, rap, phi, centFT0M, pid, kProtonBar, kProtonBar); + } + } + } + fillAnalysisHistos(false, centFT0M, nChSim, nChSim, q1ChSim, q2ChSim); + fillAnalysisHistos(false, centFT0M, nPiSim, nPiSim, q1PiSim, q2PiSim); + fillAnalysisHistos(false, centFT0M, nKaSim, nKaSim, q1KaSim, q2KaSim); + fillAnalysisHistos(false, centFT0M, nPrSim, nPrSim, q1PrSim, q2PrSim); + hist.fill(HIST("Gen/h_Counts"), 2); + hist.fill(HIST("Gen/h_VtxZ"), mcCol.posZ()); + hist.fill(HIST("Gen/h_NSim"), nSim); + hist.fill(HIST("Gen/h2_NTPC_NSim"), nSim, nTPC); + } - double nChSim1 = static_cast(nChSim); - double nPiSim1 = static_cast(nPiSim); - double nKaSim1 = static_cast(nKaSim); - double nPrSim1 = static_cast(nPrSim); + template + void analyzeMC(M const& mcCol, C const& cols, T const& tracks, P const& mcParts) + { + // fillBeforeQAHistos(cols.begin(), tracks); + hist.fill(HIST("Gen/h_VtxZ_b"), mcCol.posZ()); + int nRecCols = cols.size(); + if (nRecCols == 0) { + hist.fill(HIST("Gen/h_collision_recgen"), nRecCols); + } + // Do not analyze if more than one reco collision is accociated to one mc gen collision + if (nRecCols != 1) { + return; + } + hist.fill(HIST("Gen/h_collisions_info"), kTotCol); - fillAnalysisHistos(nTPC, nFT0M, nChSim, nChSim1, q1ChSim, q2ChSim, q3ChSim, q4ChSim); - fillAnalysisHistos(nTPC, nFT0M, nPiSim, nPiSim1, q1PiSim, q2PiSim, q3PiSim, q4PiSim); - fillAnalysisHistos(nTPC, nFT0M, nKaSim, nKaSim1, q1KaSim, q2KaSim, q3KaSim, q4KaSim); - fillAnalysisHistos(nTPC, nFT0M, nPrSim, nPrSim1, q1PrSim, q2PrSim, q3PrSim, q4PrSim); + // Check the reco collision + if (!cols.begin().has_mcCollision() || !selRun3Col(cols.begin()) || cols.begin().mcCollisionId() != mcCol.globalIndex()) { + return; } - fillAnalysisHistos(nTPC, nFT0M, nCh, nChW, q1Ch, q2Ch, q3Ch, q4Ch); - fillAnalysisHistos(nTPC, nFT0M, nPi, nPiW, q1Pi, q2Pi, q3Pi, q4Pi); - fillAnalysisHistos(nTPC, nFT0M, nKa, nKaW, q1Ka, q2Ka, q3Ka, q4Ka); - fillAnalysisHistos(nTPC, nFT0M, nPr, nPrW, q1Pr, q2Pr, q3Pr, q4Pr); + hist.fill(HIST("Gen/h_collisions_info"), kPassSelCol); + hist.fill(HIST("Gen/h2_collision_posZ"), mcCol.posZ(), cols.begin().posZ()); + + auto sTracks = tracks.sliceBy(perCollision, cols.begin().globalIndex()); + fillRecoHistos(cols.begin(), sTracks); + fillGenHistos(mcCol, mcParts); } + using MyAllTracks = soa::Join; + using MyRun3Collisions = soa::Join; + using MyRun3MCCollisions = soa::Join; + using MyMCTracks = soa::Join; + SliceCache cache; + Preslice perCollision = aod::track::collisionId; + void processRun3(MyRun3Collisions::iterator const& col, MyAllTracks const& tracks) { - // Before Collision and Track Cuts: fillBeforeQAHistos(col, tracks); - - // After Collision and Track Cuts: - if (selRun3Col(col)) { - fillHistos(col, tracks); - } + fillRecoHistos(col, tracks); } PROCESS_SWITCH(MeanPtFlucId, processRun3, "Process for Run-3", false); - void processMCRecoSimRun3(MyRun3MCCollisions::iterator const& col, aod::McCollisions const&, MyMCTracks const& tracks, aod::McParticles const&) + void processMCRecoSimRun3(aod::McCollisions::iterator const& mcCol, soa::SmallGroups const& cols, MyMCTracks const& tracks, aod::McParticles const& mcParts) { - // Before Collision and Track Cuts: - fillBeforeQAHistos(col, tracks); - - hist.fill(HIST("Gen/h_VtxZ_b"), col.mcCollision().posZ()); - - // After Collision and Track Cuts: - if (selRun3Col(col)) { - fillHistos(col, tracks); - } + analyzeMC(mcCol, cols, tracks, mcParts); } PROCESS_SWITCH(MeanPtFlucId, processMCRecoSimRun3, "process MC Reconstructed & Truth Run-3", true); }; From 70c8704eedb3a389ccfc853c08374695455a8973 Mon Sep 17 00:00:00 2001 From: Anantha Padmanabhan M Nair <82643666+ananthapadmanabhan18@users.noreply.github.com> Date: Sun, 22 Jun 2025 22:41:06 +0530 Subject: [PATCH 180/871] [PWGUD] Modified Occupancy and TOF COnditions (#11717) --- PWGUD/Tasks/exclusiveRhoTo4Pi.cxx | 281 ++++++++++++++++-------------- 1 file changed, 153 insertions(+), 128 deletions(-) diff --git a/PWGUD/Tasks/exclusiveRhoTo4Pi.cxx b/PWGUD/Tasks/exclusiveRhoTo4Pi.cxx index ac0a9459569..2c82c90a38b 100644 --- a/PWGUD/Tasks/exclusiveRhoTo4Pi.cxx +++ b/PWGUD/Tasks/exclusiveRhoTo4Pi.cxx @@ -13,26 +13,30 @@ /// \brief Task for analyzing exclusive rho decays to 4 pions /// \author Anantha Padmanabhan M Nair -#include -#include -#include -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoA.h" -#include "Framework/ASoAHelpers.h" -#include "PWGUD/DataModel/UDTables.h" #include "PWGUD/Core/SGSelector.h" -#include "PWGUD/Core/UDHelpers.h" #include "PWGUD/Core/SGTrackSelector.h" +#include "PWGUD/Core/UDHelpers.h" +#include "PWGUD/DataModel/UDTables.h" + #include "Common/DataModel/PIDResponse.h" -#include -#include -#include "Math/Vector4D.h" -#include "Math/Vector3D.h" -#include "Math/GenVector/Boost.h" + #include "CommonConstants/PhysicsConstants.h" +#include "Framework/ASoA.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" + +#include "Math/GenVector/Boost.h" +#include "Math/Vector3D.h" +#include "Math/Vector4D.h" #include "TPDGCode.h" +#include +#include + +#include +#include +#include using namespace std; using namespace o2; @@ -515,18 +519,24 @@ struct ExclusiveRhoTo4Pi { HistogramRegistry histosMCreco{"histosMCreco", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; //---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + // Event Selection Cuts Configurable vZCut{"vZCut", 10., "Vertex Cut"}; Configurable fv0Cut{"fv0Cut", 50., "FV0A threshold"}; Configurable ft0aCut{"ft0aCut", 150., "FT0A threshold"}; Configurable ft0cCut{"ft0cCut", 50., "FT0C threshold"}; Configurable zdcCut{"zdcCut", 0., "ZDC threshold"}; + Configurable occupancyCut{"occupancyCut", 20000, "Occupancy Cut"}; + Configurable numPVContrib{"numPVContrib", 4, "Number of PV Contributors"}; + Configurable checkOneTof{"checkOneTof", 1, " (1 or 0)Check if event has at least 1 TOF"}; + + // bc selection cuts Configurable sbpCut{"sbpCut", 1, "Sbp"}; Configurable itsROFbCut{"itsROFbCut", 1, "itsROFbCut"}; Configurable vtxITSTPCcut{"vtxITSTPCcut", 1, "vtxITSTPCcut"}; Configurable tfbCut{"tfbCut", 1, "tfbCut"}; + // Track Selection Cuts Configurable pvCut{"pvCut", 1.0, "Use Only PV tracks"}; - Configurable numPVContrib{"numPVContrib", 4, "Number of PV Contributors"}; Configurable dcaZcut{"dcaZcut", 2, "dcaZ cut"}; Configurable dcaXYcut{"dcaXYcut", 0, "dcaXY cut"}; Configurable tpcChi2Cut{"tpcChi2Cut", 4, "Max tpcChi2NCl"}; @@ -535,19 +545,20 @@ struct ExclusiveRhoTo4Pi { Configurable etaCut{"etaCut", 0.9, "Track Pseudorapidity"}; Configurable pTcut{"pTcut", 0.15, "Track Pt"}; + // PID Selection Cuts Configurable nSigmaTPCcut{"nSigmaTPCcut", 3, "TPC cut"}; Configurable nSigmaTOFcut{"nSigmaTOFcut", 3, "TOF cut"}; + // Kinematics Cuts Configurable rhoRapCut{"rhoRapCut", 0.5, "Max abs Rapidity of rho"}; Configurable rhoPtCut{"rhoPtCut", 0.15, "Min Pt of rho"}; - Configurable nBinsPt{"nBinsPt", 1000, "Number of bins for pT"}; - Configurable nBinsInvariantMass{"nBinsInvariantMass", 1000, "Number of bins for Invariant Mass"}; - Configurable invariantMassMin{"invariantMassMin", 0.8, "Minimum Invariant Mass"}; - Configurable invariantMassMax{"invariantMassMax", 2.5, "Maximum Invariant Mass"}; - Configurable nBinsRapidity{"nBinsRapidity", 1000, "Number of bins for Rapidity"}; - Configurable nBinsPhi{"nBinsPhi", 360, "Number of bins for Phi"}; - Configurable nBinsCosTheta{"nBinsCosTheta", 360, "Number of bins for cos Theta"}; + // Axis Configurations + ConfigurableAxis pTAxis{"pTAxis", {1000, 0, 2}, "Axis for pT histograms"}; + ConfigurableAxis rapidityAxis{"rapidityAxis", {1000, -2.5, 2.5}, "Axis for Rapidity histograms"}; + ConfigurableAxis invMassAxis{"invMassAxis", {1000, 1, 2.5}, "Axis for Phi histograms"}; + ConfigurableAxis phiAxis{"phiAxis", {360, -1 * o2::constants::math::PI, o2::constants::math::PI}, "Axis for Phi histograms"}; + ConfigurableAxis cosThetaAxis{"cosThetaAxis", {360, -1, 1}, "Axis for cos Theta histograms"}; //---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- // Begin of Init Function----------------------------------------------------------------------------------------------------------------------------------------------------- @@ -557,49 +568,49 @@ struct ExclusiveRhoTo4Pi { histosData.add("GapSide", "Gap Side; Events", kTH1F, {{4, -1.5, 2.5}}); histosData.add("TrueGapSide", "Gap Side; Events", kTH1F, {{4, -1.5, 2.5}}); histosData.add("EventCounts", "Total Events; Events", kTH1F, {{10, 0, 10}}); - histosData.add("vertexZ", "Vertex Z; Vertex Z [cm]; Counts", kTH1F, {{1000, -20, 20}}); - histosData.add("occupancy", "Occupancy; Occupancy; Counts", kTH1F, {{1500, 0, 1500}}); - histosData.add("dcaXY", "dcaXY; dcaXY [cm]; Counts", kTH1F, {{10000, -5, 5}}); - histosData.add("dcaZ", "dcaZ; dcaZ [cm]; Counts", kTH1F, {{10000, -10, 10}}); - histosData.add("tpcChi2NCl", "TPC Chi2/NCl; Chi2/NCl; Counts", kTH1F, {{200, 0, 200}}); - histosData.add("itsChi2NCl", "ITS Chi2/NCl; Chi2/NCl; Counts", kTH1F, {{200, 0, 200}}); + histosData.add("vertexZ", "Vertex Z; Vertex Z [cm]; Counts", kTH1F, {{2000, -15, 15}}); + histosData.add("occupancy", "Occupancy; Occupancy; Counts", kTH1F, {{20000, 0, 20000}}); + histosData.add("dcaXY", "dcaXY; dcaXY [cm]; Counts", kTH1F, {{5000, -0.5, 0.5}}); + histosData.add("dcaZ", "dcaZ; dcaZ [cm]; Counts", kTH1F, {{5000, -0.5, 0.5}}); + histosData.add("tpcChi2NCl", "TPC Chi2/NCl; Chi2/NCl; Counts", kTH1F, {{250, 0, 50}}); + histosData.add("itsChi2NCl", "ITS Chi2/NCl; Chi2/NCl; Counts", kTH1F, {{250, 0, 50}}); histosData.add("tpcNClsFindable", "TPC N Cls Findable; N Cls Findable; Counts", kTH1F, {{200, 0, 200}}); // TPC nSigma - histosData.add("tpcNSigmaPi_all", "TPC nSigma Pion with track selection; Events", kTH2F, {{1000, -15, 15}, {nBinsPt, 0, 10}}); - histosData.add("tpcNSigmaPi_pions", "TPC nSigma Pion with track selection and PID Selection of Pi; Entries", kTH2F, {{1000, -15, 15}, {nBinsPt, 0, 10}}); + histosData.add("tpcNSigmaPi_all", "TPC nSigma Pion with track selection; Events", kTH2F, {{1000, -15, 15}, {1000, 0, 10}}); + histosData.add("tpcNSigmaPi_pions", "TPC nSigma Pion with track selection and PID Selection of Pi; Entries", kTH2F, {{1000, -15, 15}, {1000, 0, 10}}); // TPC nSigma of other particles with selected pion tracks - histosData.add("tpcNSigmaKa_pions", "TPC nSigma Kaon with track selection and PID Selection of Pion; Entries", kTH2F, {{1000, -15, 15}, {nBinsPt, 0, 10}}); - histosData.add("tpcNSigmaPr_pions", "TPC nSigma Proton with track selection and PID Selection of Pion; Entries", kTH2F, {{1000, -15, 15}, {nBinsPt, 0, 10}}); - histosData.add("tpcNSigmaEl_pions", "TPC nSigma Electron with track selection and PID Selection of Pion; Entries", kTH2F, {{1000, -15, 15}, {nBinsPt, 0, 10}}); - histosData.add("tpcNSigmaMu_pions", "TPC nSigma Muon with track selection and PID Selection of Pion; Entries", kTH2F, {{1000, -15, 15}, {nBinsPt, 0, 10}}); + histosData.add("tpcNSigmaKa_pions", "TPC nSigma Kaon with track selection and PID Selection of Pion; Entries", kTH2F, {{1000, -15, 15}, {1000, 0, 10}}); + histosData.add("tpcNSigmaPr_pions", "TPC nSigma Proton with track selection and PID Selection of Pion; Entries", kTH2F, {{1000, -15, 15}, {1000, 0, 10}}); + histosData.add("tpcNSigmaEl_pions", "TPC nSigma Electron with track selection and PID Selection of Pion; Entries", kTH2F, {{1000, -15, 15}, {1000, 0, 10}}); + histosData.add("tpcNSigmaMu_pions", "TPC nSigma Muon with track selection and PID Selection of Pion; Entries", kTH2F, {{1000, -15, 15}, {1000, 0, 10}}); // TOF nSigma - histosData.add("tofNSigmaPi_all", "TOF nSigma Pion with track selection; Events", kTH2F, {{1000, -15, 15}, {nBinsPt, 0, 10}}); - histosData.add("tofNSigmaPi_pions", "TOF nSigma Pion with track selection and PID Selection of Pi; Entries", kTH2F, {{1000, -15, 15}, {nBinsPt, 0, 10}}); + histosData.add("tofNSigmaPi_all", "TOF nSigma Pion with track selection; Events", kTH2F, {{1000, -15, 15}, {1000, 0, 10}}); + histosData.add("tofNSigmaPi_pions", "TOF nSigma Pion with track selection and PID Selection of Pi; Entries", kTH2F, {{1000, -15, 15}, {1000, 0, 10}}); // TOF nSigma of other particles with selected pion tracks - histosData.add("tofNSigmaKa_pions", "TOF nSigma Kaon with track selection and PID Selection of Pion; Entries", kTH2F, {{1000, -15, 15}, {nBinsPt, 0, 10}}); - histosData.add("tofNSigmaPr_pions", "TOF nSigma Proton with track selection and PID Selection of Pion; Entries", kTH2F, {{1000, -15, 15}, {nBinsPt, 0, 10}}); - histosData.add("tofNSigmaEl_pions", "TOF nSigma Electron with track selection and PID Selection of Pion; Entries", kTH2F, {{1000, -15, 15}, {nBinsPt, 0, 10}}); - histosData.add("tofNSigmaMu_pions", "TOF nSigma Muon with track selection and PID Selection of Pion; Entries", kTH2F, {{1000, -15, 15}, {nBinsPt, 0, 10}}); + histosData.add("tofNSigmaKa_pions", "TOF nSigma Kaon with track selection and PID Selection of Pion; Entries", kTH2F, {{1000, -15, 15}, {1000, 0, 10}}); + histosData.add("tofNSigmaPr_pions", "TOF nSigma Proton with track selection and PID Selection of Pion; Entries", kTH2F, {{1000, -15, 15}, {1000, 0, 10}}); + histosData.add("tofNSigmaEl_pions", "TOF nSigma Electron with track selection and PID Selection of Pion; Entries", kTH2F, {{1000, -15, 15}, {1000, 0, 10}}); + histosData.add("tofNSigmaMu_pions", "TOF nSigma Muon with track selection and PID Selection of Pion; Entries", kTH2F, {{1000, -15, 15}, {1000, 0, 10}}); // Track Transverse Momentum - histosData.add("pT_track_all", "pT with track selection; pT [GeV/c]; Counts", kTH1F, {{nBinsPt, 0, 2}}); - histosData.add("pT_track_pions", "pT with track selection and PID selection of Pi; pT [GeV/c]; Events", kTH1F, {{nBinsPt, 0, 2}}); - histosData.add("pT_track_pions_contributed", "pT with track selection and PID selection of Pi which are contributed to selected event; pT [GeV/c]; Events", kTH1F, {{nBinsPt, 0, 2}}); + histosData.add("pT_track_all", "pT with track selection; pT [GeV/c]; Counts", kTH1F, {pTAxis}); + histosData.add("pT_track_pions", "pT with track selection and PID selection of Pi; pT [GeV/c]; Events", kTH1F, {pTAxis}); + histosData.add("pT_track_pions_contributed", "pT with track selection and PID selection of Pi which are contributed to selected event; pT [GeV/c]; Events", kTH1F, {pTAxis}); // Track Rapidity - histosData.add("rapidity_track_all", "Rapidity with track selection; y; Counts", kTH1F, {{nBinsRapidity, -2.5, 2.5}}); - histosData.add("rapidity_track_pions", "Rapidity with track selection and PID selection of Pi; y; Events", kTH1F, {{nBinsRapidity, -2.5, 2.5}}); - histosData.add("rapidity_track_pions_contributed", "Rapidity with track selection and PID selection of Pi which are contributed to selected event; y; Events", kTH1F, {{nBinsRapidity, -2.5, 2.5}}); + histosData.add("rapidity_track_all", "Rapidity with track selection; y; Counts", kTH1F, {rapidityAxis}); + histosData.add("rapidity_track_pions", "Rapidity with track selection and PID selection of Pi; y; Events", kTH1F, {rapidityAxis}); + histosData.add("rapidity_track_pions_contributed", "Rapidity with track selection and PID selection of Pi which are contributed to selected event; y; Events", kTH1F, {rapidityAxis}); // Zero charge Event Transverse Momentum - histosData.add("fourpion_pT_0_charge", "Event pT in 0 Charge Events With Track Selection and PID Selection of Pi; pT [GeV/c]; Events", kTH1F, {{nBinsPt, 0, 2}}); + histosData.add("fourpion_pT_0_charge", "Event pT in 0 Charge Events With Track Selection and PID Selection of Pi; pT [GeV/c]; Events", kTH1F, {pTAxis}); // Non Zero charge Event Transverse Momentum - histosData.add("fourpion_pT_non_0_charge", "Event pT in Non 0 Charge Events With Track Selection and PID Selection of Pi; pT [GeV/c]; Events", kTH1F, {{nBinsPt, 0, 2}}); + histosData.add("fourpion_pT_non_0_charge", "Event pT in Non 0 Charge Events With Track Selection and PID Selection of Pi; pT [GeV/c]; Events", kTH1F, {pTAxis}); // Rapidity of 0 charge Events histosData.add("fourpion_rap_0_charge_domA", "Rapidity of Events With Track Selection and PID Selection of Pi for p_{T} < 0.15 GeV/c; y; Events", kTH1F, {{1000, -2.5, 2.5}}); @@ -607,9 +618,9 @@ struct ExclusiveRhoTo4Pi { histosData.add("fourpion_rap_0_charge_domC", "Rapidity of Events With Track Selection and PID Selection of Pi for p_{T} > 0.80 GeV/c; y; Events", kTH1F, {{1000, -2.5, 2.5}}); // Rapidity of non 0 charge Events - histosData.add("fourpion_rap_non_0_charge_domA", "Rapidity of Events With Track Selection and PID Selection of Pi for p_{T} < 0.15 GeV/c; y; Events", kTH1F, {{nBinsRapidity, -2.5, 2.5}}); - histosData.add("fourpion_rap_non_0_charge_domB", "Rapidity of Events With Track Selection and PID Selection of Pi for 0.15< p_{T} < 0.80 GeV/c$; y; Events", kTH1F, {{nBinsRapidity, -2.5, 2.5}}); - histosData.add("fourpion_rap_non_0_charge_domC", "Rapidity of Events With Track Selection and PID Selection of Pi for p_{T} > 0.80 GeV/c; y; Events", kTH1F, {{nBinsRapidity, -2.5, 2.5}}); + histosData.add("fourpion_rap_non_0_charge_domA", "Rapidity of Events With Track Selection and PID Selection of Pi for p_{T} < 0.15 GeV/c; y; Events", kTH1F, {rapidityAxis}); + histosData.add("fourpion_rap_non_0_charge_domB", "Rapidity of Events With Track Selection and PID Selection of Pi for 0.15< p_{T} < 0.80 GeV/c$; y; Events", kTH1F, {rapidityAxis}); + histosData.add("fourpion_rap_non_0_charge_domC", "Rapidity of Events With Track Selection and PID Selection of Pi for p_{T} > 0.80 GeV/c; y; Events", kTH1F, {rapidityAxis}); // Pair Invariant Mass histosData.add("twopion_mass_1", "Invariant Mass Distribution of 2 pions 1 ; m(#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {{5000, 0, 5}}); @@ -618,22 +629,22 @@ struct ExclusiveRhoTo4Pi { histosData.add("twopion_mass_4", "Invariant Mass Distribution of 2 pions 4 ; m(#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {{5000, 0, 5}}); // Invariant Mass of 0 charge events - histosData.add("fourpion_mass_0_charge_domA", "Invariant Mass Distribution of 0 charge Events with PID Selection of Pi for p_{T} < 0.15 GeV/c; m(#pi^{+}#pi^{-}#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {{nBinsInvariantMass, invariantMassMin, invariantMassMax}}); // pT < 0.15GeV - histosData.add("fourpion_mass_0_charge_domB", "Invariant Mass Distribution of 0 charge Events with PID Selection of Pi for 0.15< p_{T} < 0.80 GeV/c; m(#pi^{+}#pi^{-}#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {{nBinsInvariantMass, invariantMassMin, invariantMassMax}}); // 0.15GeV < pT < 0.8GeV - histosData.add("fourpion_mass_0_charge_domC", "Invariant Mass Distribution of 0 charge Events with PID Selection of Pi for p_{T} > 0.80 GeV/c; m(#pi^{+}#pi^{-}#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {{nBinsInvariantMass, invariantMassMin, invariantMassMax}}); // 0.8GeV < pT + histosData.add("fourpion_mass_0_charge_domA", "Invariant Mass Distribution of 0 charge Events with PID Selection of Pi for p_{T} < 0.15 GeV/c; m(#pi^{+}#pi^{-}#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {invMassAxis}); // pT < 0.15GeV + histosData.add("fourpion_mass_0_charge_domB", "Invariant Mass Distribution of 0 charge Events with PID Selection of Pi for 0.15< p_{T} < 0.80 GeV/c; m(#pi^{+}#pi^{-}#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {invMassAxis}); // 0.15GeV < pT < 0.8GeV + histosData.add("fourpion_mass_0_charge_domC", "Invariant Mass Distribution of 0 charge Events with PID Selection of Pi for p_{T} > 0.80 GeV/c; m(#pi^{+}#pi^{-}#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {invMassAxis}); // 0.8GeV < pT // Invariant mass of non 0 charge events - histosData.add("fourpion_mass_non_0_charge_domA", "Invariant Mass Distribution of non 0 charge Events with PID Selection of Pi for p_{T} < 0.15 GeV/c; m(#pi^{+}#pi^{-}#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {{nBinsInvariantMass, invariantMassMin, invariantMassMax}}); // pT < 0.15GeV - histosData.add("fourpion_mass_non_0_charge_domB", "Invariant Mass Distribution of non 0 charge Events with PID Selection of Pi for 0.15< p_{T} < 0.80 GeV/c; m(#pi^{+}#pi^{-}#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {{nBinsInvariantMass, invariantMassMin, invariantMassMax}}); // 0.15GeV < pT < 0.8GeV - histosData.add("fourpion_mass_non_0_charge_domC", "Invariant Mass Distribution of non 0 charge Events with PID Selection of Pi for p_{T} > 0.80 GeV/c; m(#pi^{+}#pi^{-}#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {{nBinsInvariantMass, invariantMassMin, invariantMassMax}}); // 0.8GeV < pT + histosData.add("fourpion_mass_non_0_charge_domA", "Invariant Mass Distribution of non 0 charge Events with PID Selection of Pi for p_{T} < 0.15 GeV/c; m(#pi^{+}#pi^{-}#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {invMassAxis}); // pT < 0.15GeV + histosData.add("fourpion_mass_non_0_charge_domB", "Invariant Mass Distribution of non 0 charge Events with PID Selection of Pi for 0.15< p_{T} < 0.80 GeV/c; m(#pi^{+}#pi^{-}#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {invMassAxis}); // 0.15GeV < pT < 0.8GeV + histosData.add("fourpion_mass_non_0_charge_domC", "Invariant Mass Distribution of non 0 charge Events with PID Selection of Pi for p_{T} > 0.80 GeV/c; m(#pi^{+}#pi^{-}#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {invMassAxis}); // 0.8GeV < pT // tpc signal histosData.add("tpcSignal", "TPC dEdx vs p; p [GeV/c]; dEdx [a.u.]", kTH2F, {{500, 0, 10}, {5000, 0.0, 5000.0}}); - histosData.add("tpcSignal_Pi", "TPC dEdx vs p for pions; p [GeV/c]; dEdx [a.u.]", kTH2F, {{500, 0, 10}, {5000, 0.0, 5000.0}}); + histosData.add("tpcSignal_pions", "TPC dEdx vs p for pions; p [GeV/c]; dEdx [a.u.]", kTH2F, {{500, 0, 10}, {5000, 0.0, 5000.0}}); // tof beta histosData.add("tofBeta", "TOF beta vs p; p [GeV/c]; #beta", kTH2F, {{500, 0, 10}, {500, 0.0, 1.0}}); - histosData.add("tofBeta_Pi", "TOF beta vs p for pions; p [GeV/c]; #beta", kTH2F, {{500, 0, 10}, {500, 0.0, 1.0}}); + histosData.add("tofBeta_pions", "TOF beta vs p for pions; p [GeV/c]; #beta", kTH2F, {{500, 0, 10}, {500, 0.0, 1.0}}); // Other signals histosData.add("FT0A", "T0A amplitude", kTH1F, {{2000, 0.0, 500.0}}); @@ -643,12 +654,12 @@ struct ExclusiveRhoTo4Pi { histosData.add("V0A", "V0A amplitude", kTH1F, {{1000, 0.0, 100}}); // Collin Soper Theta and Phi - histosData.add("collin_soper_phi_1", "#phi Distribution; #phi; Events", kTH1F, {{nBinsPhi, -3.2, 3.2}}); - histosData.add("collin_soper_phi_2", "#phi Distribution; #phi; Events", kTH1F, {{nBinsPhi, -3.2, 3.2}}); - histosData.add("collin_soper_costheta_1", "#theta Distribution;cos(#theta); Counts", kTH1F, {{nBinsCosTheta, -1, 1}}); - histosData.add("collin_soper_costheta_2", "#theta Distribution;cos(#theta); Counts", kTH1F, {{nBinsCosTheta, -1, 1}}); - histosData.add("phi_vs_costheta_1", "Phi vs cosTheta; #phi; cos(#theta)", kTH2F, {{nBinsPhi, -3.2, 3.2}, {nBinsCosTheta, -1, 1}}); - histosData.add("phi_vs_costheta_2", "Phi vs cosTheta; #phi; cos(#theta)", kTH2F, {{nBinsPhi, -3.2, 3.2}, {nBinsCosTheta, -1, 1}}); + histosData.add("collin_soper_phi_1", "#phi Distribution; #phi; Events", kTH1F, {phiAxis}); + histosData.add("collin_soper_phi_2", "#phi Distribution; #phi; Events", kTH1F, {phiAxis}); + histosData.add("collin_soper_costheta_1", "#theta Distribution;cos(#theta); Counts", kTH1F, {cosThetaAxis}); + histosData.add("collin_soper_costheta_2", "#theta Distribution;cos(#theta); Counts", kTH1F, {cosThetaAxis}); + histosData.add("phi_vs_costheta_1", "Phi vs cosTheta; #phi; cos(#theta)", kTH2F, {phiAxis, cosThetaAxis}); + histosData.add("phi_vs_costheta_2", "Phi vs cosTheta; #phi; cos(#theta)", kTH2F, {phiAxis, cosThetaAxis}); // MC Gen Stuff @@ -656,9 +667,9 @@ struct ExclusiveRhoTo4Pi { histosMCgen.add("rhoPrimeCounts", "Total Rho prime Events; Events", kTH1F, {{10, 0, 10}}); // Track Stuff - histosMCgen.add("pion_pT", "Generated pT; pT [GeV/c]; Events", kTH1F, {{nBinsPt, 0, 10}}); + histosMCgen.add("pion_pT", "Generated pT; pT [GeV/c]; Events", kTH1F, {{1000, 0, 10}}); histosMCgen.add("pion_eta", "Generated Pseudorapidity; #eta; Events", kTH1F, {{1000, -2.5, 2.5}}); - histosMCgen.add("pion_rapidity", "Generated Rapidity; y; Events", kTH1F, {{nBinsRapidity, -2.5, 2.5}}); + histosMCgen.add("pion_rapidity", "Generated Rapidity; y; Events", kTH1F, {rapidityAxis}); // Pair Invariant Mass histosMCgen.add("twoPion_invMass_pair_1", "Invariant Mass Distribution of 2 pions 1 ; m(#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {{5000, 0, 5}}); @@ -667,23 +678,23 @@ struct ExclusiveRhoTo4Pi { histosMCgen.add("twoPion_invMass_pair_4", "Invariant Mass Distribution of 2 pions 4 ; m(#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {{5000, 0, 5}}); // Generated Transverse Momentum, Rapidty and Invariant Mass - histosMCgen.add("rhoPrime_pT", "Generated pT; pT [GeV/c]; Events", kTH1F, {{nBinsPt, 0, 2}}); - histosMCgen.add("rhoPrime_eta", "Generated pT; pT [GeV/c]; Events", kTH1F, {{nBinsPt, 0, 2}}); - histosMCgen.add("rhoPrime_rapidity", "Generated pT; pT [GeV/c]; Events", kTH1F, {{nBinsPt, 0, 2}}); - histosMCgen.add("rhoPrime_invmass", "Generated pT; pT [GeV/c]; Events", kTH1F, {{nBinsPt, 0, 2}}); + histosMCgen.add("rhoPrime_pT", "Generated pT; pT [GeV/c]; Events", kTH1F, {pTAxis}); + histosMCgen.add("rhoPrime_eta", "Generated pT; pT [GeV/c]; Events", kTH1F, {pTAxis}); + histosMCgen.add("rhoPrime_rapidity", "Generated pT; pT [GeV/c]; Events", kTH1F, {pTAxis}); + histosMCgen.add("rhoPrime_invmass", "Generated pT; pT [GeV/c]; Events", kTH1F, {pTAxis}); - histosMCgen.add("fourPion_pT", "Generated pT; pT [GeV/c]; Events", kTH1F, {{nBinsPt, 0, 2}}); + histosMCgen.add("fourPion_pT", "Generated pT; pT [GeV/c]; Events", kTH1F, {pTAxis}); histosMCgen.add("fourPion_eta", "Generated Pseudorapidity; #eta; Events", kTH1F, {{1000, -2.5, 2.5}}); - histosMCgen.add("fourPion_rapidity", "Generated Rapidity; y; Events", kTH1F, {{nBinsRapidity, -2.5, 2.5}}); - histosMCgen.add("fourPion_invmass", "Invariant Mass of 4-Pions; m(4-pion); Events", kTH1F, {{nBinsInvariantMass, invariantMassMin, invariantMassMax}}); + histosMCgen.add("fourPion_rapidity", "Generated Rapidity; y; Events", kTH1F, {rapidityAxis}); + histosMCgen.add("fourPion_invmass", "Invariant Mass of 4-Pions; m(4-pion); Events", kTH1F, {invMassAxis}); // Collin Soper Theta and Phi - histosMCgen.add("fourPion_phi_pair_1", "#phi Distribution; #phi; Events", kTH1F, {{nBinsPhi, -3.2, 3.2}}); - histosMCgen.add("fourPion_phi_pair_2", "#phi Distribution; #phi; Events", kTH1F, {{nBinsPhi, -3.2, 3.2}}); - histosMCgen.add("fourPion_costheta_pair_1", "#theta Distribution;cos(#theta); Events", kTH1F, {{nBinsCosTheta, -1, 1}}); - histosMCgen.add("fourPion_costheta_pair_2", "#theta Distribution;cos(#theta); Events", kTH1F, {{nBinsCosTheta, -1, 1}}); - histosMCgen.add("phi_vs_costheta_1", "Phi vs cosTheta; #phi; cos(#theta)", kTH2F, {{nBinsPhi, -3.2, 3.2}, {nBinsCosTheta, -1, 1}}); - histosMCgen.add("phi_vs_costheta_2", "Phi vs cosTheta; #phi; cos(#theta)", kTH2F, {{nBinsPhi, -3.2, 3.2}, {nBinsCosTheta, -1, 1}}); + histosMCgen.add("fourPion_phi_pair_1", "#phi Distribution; #phi; Events", kTH1F, {phiAxis}); + histosMCgen.add("fourPion_phi_pair_2", "#phi Distribution; #phi; Events", kTH1F, {phiAxis}); + histosMCgen.add("fourPion_costheta_pair_1", "#theta Distribution;cos(#theta); Events", kTH1F, {cosThetaAxis}); + histosMCgen.add("fourPion_costheta_pair_2", "#theta Distribution;cos(#theta); Events", kTH1F, {cosThetaAxis}); + histosMCgen.add("phi_vs_costheta_1", "Phi vs cosTheta; #phi; cos(#theta)", kTH2F, {phiAxis, cosThetaAxis}); + histosMCgen.add("phi_vs_costheta_2", "Phi vs cosTheta; #phi; cos(#theta)", kTH2F, {phiAxis, cosThetaAxis}); // MC Reco Stuff @@ -700,40 +711,40 @@ struct ExclusiveRhoTo4Pi { histosMCreco.add("EventCounts", "Total Events; Events", kTH1F, {{10, 0, 10}}); // TPC nSigma - histosMCreco.add("tpcNSigmaPi_all", "TPC nSigma Pion with track selection; Events", kTH2F, {{1000, -15, 15}, {nBinsPt, 0, 10}}); - histosMCreco.add("tpcNSigmaPi_pions", "TPC nSigma Pion with track selection and PID Selection of Pi; Entries", kTH2F, {{1000, -15, 15}, {nBinsPt, 0, 10}}); + histosMCreco.add("tpcNSigmaPi_all", "TPC nSigma Pion with track selection; Events", kTH2F, {{1000, -15, 15}, {1000, 0, 10}}); + histosMCreco.add("tpcNSigmaPi_pions", "TPC nSigma Pion with track selection and PID Selection of Pi; Entries", kTH2F, {{1000, -15, 15}, {1000, 0, 10}}); // TPC nSigma of other particles with selected pion tracks - histosMCreco.add("tpcNSigmaKa_pions", "TPC nSigma Kaon with track selection and PID Selection of Pion; Entries", kTH2F, {{1000, -15, 15}, {nBinsPt, 0, 10}}); - histosMCreco.add("tpcNSigmaPr_pions", "TPC nSigma Proton with track selection and PID Selection of Pion; Entries", kTH2F, {{1000, -15, 15}, {nBinsPt, 0, 10}}); - histosMCreco.add("tpcNSigmaEl_pions", "TPC nSigma Electron with track selection and PID Selection of Pion; Entries", kTH2F, {{1000, -15, 15}, {nBinsPt, 0, 10}}); - histosMCreco.add("tpcNSigmaMu_pions", "TPC nSigma Muon with track selection and PID Selection of Pion; Entries", kTH2F, {{1000, -15, 15}, {nBinsPt, 0, 10}}); + histosMCreco.add("tpcNSigmaKa_pions", "TPC nSigma Kaon with track selection and PID Selection of Pion; Entries", kTH2F, {{1000, -15, 15}, {1000, 0, 10}}); + histosMCreco.add("tpcNSigmaPr_pions", "TPC nSigma Proton with track selection and PID Selection of Pion; Entries", kTH2F, {{1000, -15, 15}, {1000, 0, 10}}); + histosMCreco.add("tpcNSigmaEl_pions", "TPC nSigma Electron with track selection and PID Selection of Pion; Entries", kTH2F, {{1000, -15, 15}, {1000, 0, 10}}); + histosMCreco.add("tpcNSigmaMu_pions", "TPC nSigma Muon with track selection and PID Selection of Pion; Entries", kTH2F, {{1000, -15, 15}, {1000, 0, 10}}); // TOF nSigma - histosMCreco.add("tofNSigmaPi_all", "TOF nSigma Pion with track selection; Events", kTH2F, {{1000, -15, 15}, {nBinsPt, 0, 10}}); - histosMCreco.add("tofNSigmaPi_pions", "TOF nSigma Pion with track selection and PID Selection of Pi; Entries", kTH2F, {{1000, -15, 15}, {nBinsPt, 0, 10}}); + histosMCreco.add("tofNSigmaPi_all", "TOF nSigma Pion with track selection; Events", kTH2F, {{1000, -15, 15}, {1000, 0, 10}}); + histosMCreco.add("tofNSigmaPi_pions", "TOF nSigma Pion with track selection and PID Selection of Pi; Entries", kTH2F, {{1000, -15, 15}, {1000, 0, 10}}); // TOF nSigma of other particles with selected pion tracks - histosMCreco.add("tofNSigmaKa_pions", "TOF nSigma Kaon with track selection and PID Selection of Pion; Entries", kTH2F, {{1000, -15, 15}, {nBinsPt, 0, 10}}); - histosMCreco.add("tofNSigmaPr_pions", "TOF nSigma Proton with track selection and PID Selection of Pion; Entries", kTH2F, {{1000, -15, 15}, {nBinsPt, 0, 10}}); - histosMCreco.add("tofNSigmaEl_pions", "TOF nSigma Electron with track selection and PID Selection of Pion; Entries", kTH2F, {{1000, -15, 15}, {nBinsPt, 0, 10}}); - histosMCreco.add("tofNSigmaMu_pions", "TOF nSigma Muon with track selection and PID Selection of Pion; Entries", kTH2F, {{1000, -15, 15}, {nBinsPt, 0, 10}}); + histosMCreco.add("tofNSigmaKa_pions", "TOF nSigma Kaon with track selection and PID Selection of Pion; Entries", kTH2F, {{1000, -15, 15}, {1000, 0, 10}}); + histosMCreco.add("tofNSigmaPr_pions", "TOF nSigma Proton with track selection and PID Selection of Pion; Entries", kTH2F, {{1000, -15, 15}, {1000, 0, 10}}); + histosMCreco.add("tofNSigmaEl_pions", "TOF nSigma Electron with track selection and PID Selection of Pion; Entries", kTH2F, {{1000, -15, 15}, {1000, 0, 10}}); + histosMCreco.add("tofNSigmaMu_pions", "TOF nSigma Muon with track selection and PID Selection of Pion; Entries", kTH2F, {{1000, -15, 15}, {1000, 0, 10}}); // Track Transverse Momentum - histosMCreco.add("pT_track_all", "pT with track selection; pT [GeV/c]; Counts", kTH1F, {{nBinsPt, 0, 2}}); - histosMCreco.add("pT_track_pions", "pT with track selection and PID selection of Pi; pT [GeV/c]; Events", kTH1F, {{nBinsPt, 0, 2}}); - histosMCreco.add("pT_track_pions_contributed", "pT with track selection and PID selection of Pi which are contributed to selected event; pT [GeV/c]; Events", kTH1F, {{nBinsPt, 0, 2}}); + histosMCreco.add("pT_track_all", "pT with track selection; pT [GeV/c]; Counts", kTH1F, {pTAxis}); + histosMCreco.add("pT_track_pions", "pT with track selection and PID selection of Pi; pT [GeV/c]; Events", kTH1F, {pTAxis}); + histosMCreco.add("pT_track_pions_contributed", "pT with track selection and PID selection of Pi which are contributed to selected event; pT [GeV/c]; Events", kTH1F, {pTAxis}); // Track Rapidity - histosMCreco.add("rapidity_track_all", "Rapidity with track selection; y; Counts", kTH1F, {{nBinsRapidity, -2.5, 2.5}}); - histosMCreco.add("rapidity_track_pions", "Rapidity with track selection and PID selection of Pi; y; Events", kTH1F, {{nBinsRapidity, -2.5, 2.5}}); - histosMCreco.add("rapidity_track_pions_contributed", "Rapidity with track selection and PID selection of Pi which are contributed to selected event; y; Events", kTH1F, {{nBinsRapidity, -2.5, 2.5}}); + histosMCreco.add("rapidity_track_all", "Rapidity with track selection; y; Counts", kTH1F, {rapidityAxis}); + histosMCreco.add("rapidity_track_pions", "Rapidity with track selection and PID selection of Pi; y; Events", kTH1F, {rapidityAxis}); + histosMCreco.add("rapidity_track_pions_contributed", "Rapidity with track selection and PID selection of Pi which are contributed to selected event; y; Events", kTH1F, {rapidityAxis}); // Zero charge Event Transverse Momentum - histosMCreco.add("fourpion_pT_0_charge", "Event pT in 0 Charge Events With Track Selection and PID Selection of Pi; pT [GeV/c]; Events", kTH1F, {{nBinsPt, 0, 2}}); + histosMCreco.add("fourpion_pT_0_charge", "Event pT in 0 Charge Events With Track Selection and PID Selection of Pi; pT [GeV/c]; Events", kTH1F, {pTAxis}); // Non Zero charge Event Transverse Momentum - histosMCreco.add("fourpion_pT_non_0_charge", "Event pT in Non 0 Charge Events With Track Selection and PID Selection of Pi; pT [GeV/c]; Events", kTH1F, {{nBinsPt, 0, 2}}); + histosMCreco.add("fourpion_pT_non_0_charge", "Event pT in Non 0 Charge Events With Track Selection and PID Selection of Pi; pT [GeV/c]; Events", kTH1F, {pTAxis}); // Rapidity of 0 charge Events histosMCreco.add("fourpion_rap_0_charge_domA", "Rapidity of Events With Track Selection and PID Selection of Pi for p_{T} < 0.15 GeV/c; y; Events", kTH1F, {{1000, -2.5, 2.5}}); @@ -741,9 +752,9 @@ struct ExclusiveRhoTo4Pi { histosMCreco.add("fourpion_rap_0_charge_domC", "Rapidity of Events With Track Selection and PID Selection of Pi for p_{T} > 0.80 GeV/c; y; Events", kTH1F, {{1000, -2.5, 2.5}}); // Rapidity of non 0 charge Events - histosMCreco.add("fourpion_rap_non_0_charge_domA", "Rapidity of Events With Track Selection and PID Selection of Pi for p_{T} < 0.15 GeV/c; y; Events", kTH1F, {{nBinsRapidity, -2.5, 2.5}}); - histosMCreco.add("fourpion_rap_non_0_charge_domB", "Rapidity of Events With Track Selection and PID Selection of Pi for 0.15< p_{T} < 0.80 GeV/c$; y; Events", kTH1F, {{nBinsRapidity, -2.5, 2.5}}); - histosMCreco.add("fourpion_rap_non_0_charge_domC", "Rapidity of Events With Track Selection and PID Selection of Pi for p_{T} > 0.80 GeV/c; y; Events", kTH1F, {{nBinsRapidity, -2.5, 2.5}}); + histosMCreco.add("fourpion_rap_non_0_charge_domA", "Rapidity of Events With Track Selection and PID Selection of Pi for p_{T} < 0.15 GeV/c; y; Events", kTH1F, {rapidityAxis}); + histosMCreco.add("fourpion_rap_non_0_charge_domB", "Rapidity of Events With Track Selection and PID Selection of Pi for 0.15< p_{T} < 0.80 GeV/c$; y; Events", kTH1F, {rapidityAxis}); + histosMCreco.add("fourpion_rap_non_0_charge_domC", "Rapidity of Events With Track Selection and PID Selection of Pi for p_{T} > 0.80 GeV/c; y; Events", kTH1F, {rapidityAxis}); // Pair Invariant Mass histosMCreco.add("twopion_mass_1", "Invariant Mass Distribution of 2 pions 1 ; m(#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {{5000, 0, 5}}); @@ -752,22 +763,22 @@ struct ExclusiveRhoTo4Pi { histosMCreco.add("twopion_mass_4", "Invariant Mass Distribution of 2 pions 4 ; m(#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {{5000, 0, 5}}); // Invariant Mass of 0 charge events - histosMCreco.add("fourpion_mass_0_charge_domA", "Invariant Mass Distribution of 0 charge Events with PID Selection of Pi for p_{T} < 0.15 GeV/c; m(#pi^{+}#pi^{-}#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {{nBinsInvariantMass, invariantMassMin, invariantMassMax}}); // pT < 0.15GeV - histosMCreco.add("fourpion_mass_0_charge_domB", "Invariant Mass Distribution of 0 charge Events with PID Selection of Pi for 0.15< p_{T} < 0.80 GeV/c; m(#pi^{+}#pi^{-}#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {{nBinsInvariantMass, invariantMassMin, invariantMassMax}}); // 0.15GeV < pT < 0.8GeV - histosMCreco.add("fourpion_mass_0_charge_domC", "Invariant Mass Distribution of 0 charge Events with PID Selection of Pi for p_{T} > 0.80 GeV/c; m(#pi^{+}#pi^{-}#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {{nBinsInvariantMass, invariantMassMin, invariantMassMax}}); // 0.8GeV < pT + histosMCreco.add("fourpion_mass_0_charge_domA", "Invariant Mass Distribution of 0 charge Events with PID Selection of Pi for p_{T} < 0.15 GeV/c; m(#pi^{+}#pi^{-}#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {invMassAxis}); // pT < 0.15GeV + histosMCreco.add("fourpion_mass_0_charge_domB", "Invariant Mass Distribution of 0 charge Events with PID Selection of Pi for 0.15< p_{T} < 0.80 GeV/c; m(#pi^{+}#pi^{-}#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {invMassAxis}); // 0.15GeV < pT < 0.8GeV + histosMCreco.add("fourpion_mass_0_charge_domC", "Invariant Mass Distribution of 0 charge Events with PID Selection of Pi for p_{T} > 0.80 GeV/c; m(#pi^{+}#pi^{-}#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {invMassAxis}); // 0.8GeV < pT // Invariant mass of non 0 charge events - histosMCreco.add("fourpion_mass_non_0_charge_domA", "Invariant Mass Distribution of non 0 charge Events with PID Selection of Pi for p_{T} < 0.15 GeV/c; m(#pi^{+}#pi^{-}#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {{nBinsInvariantMass, invariantMassMin, invariantMassMax}}); // pT < 0.15GeV - histosMCreco.add("fourpion_mass_non_0_charge_domB", "Invariant Mass Distribution of non 0 charge Events with PID Selection of Pi for 0.15< p_{T} < 0.80 GeV/c; m(#pi^{+}#pi^{-}#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {{nBinsInvariantMass, invariantMassMin, invariantMassMax}}); // 0.15GeV < pT < 0.8GeV - histosMCreco.add("fourpion_mass_non_0_charge_domC", "Invariant Mass Distribution of non 0 charge Events with PID Selection of Pi for p_{T} > 0.80 GeV/c; m(#pi^{+}#pi^{-}#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {{nBinsInvariantMass, invariantMassMin, invariantMassMax}}); // 0.8GeV < pT + histosMCreco.add("fourpion_mass_non_0_charge_domA", "Invariant Mass Distribution of non 0 charge Events with PID Selection of Pi for p_{T} < 0.15 GeV/c; m(#pi^{+}#pi^{-}#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {invMassAxis}); // pT < 0.15GeV + histosMCreco.add("fourpion_mass_non_0_charge_domB", "Invariant Mass Distribution of non 0 charge Events with PID Selection of Pi for 0.15< p_{T} < 0.80 GeV/c; m(#pi^{+}#pi^{-}#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {invMassAxis}); // 0.15GeV < pT < 0.8GeV + histosMCreco.add("fourpion_mass_non_0_charge_domC", "Invariant Mass Distribution of non 0 charge Events with PID Selection of Pi for p_{T} > 0.80 GeV/c; m(#pi^{+}#pi^{-}#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {invMassAxis}); // 0.8GeV < pT // tpc signal histosMCreco.add("tpcSignal", "TPC dEdx vs p; p [GeV/c]; dEdx [a.u.]", kTH2F, {{500, 0, 10}, {5000, 0.0, 5000.0}}); - histosMCreco.add("tpcSignal_Pi", "TPC dEdx vs p for pions; p [GeV/c]; dEdx [a.u.]", kTH2F, {{500, 0, 10}, {5000, 0.0, 5000.0}}); + histosMCreco.add("tpcSignal_pions", "TPC dEdx vs p for pions; p [GeV/c]; dEdx [a.u.]", kTH2F, {{500, 0, 10}, {5000, 0.0, 5000.0}}); // tof beta histosMCreco.add("tofBeta", "TOF beta vs p; p [GeV/c]; #beta", kTH2F, {{500, 0, 10}, {500, 0.0, 1.0}}); - histosMCreco.add("tofBeta_Pi", "TOF beta vs p for pions; p [GeV/c]; #beta", kTH2F, {{500, 0, 10}, {500, 0.0, 1.0}}); + histosMCreco.add("tofBeta_pions", "TOF beta vs p for pions; p [GeV/c]; #beta", kTH2F, {{500, 0, 10}, {500, 0.0, 1.0}}); // Other signals histosMCreco.add("FT0A", "T0A amplitude", kTH1F, {{2000, 0.0, 500.0}}); @@ -777,12 +788,12 @@ struct ExclusiveRhoTo4Pi { histosMCreco.add("V0A", "V0A amplitude", kTH1F, {{1000, 0.0, 100}}); // Collin Soper Theta and Phi - histosMCreco.add("collin_soper_phi_1", "#phi Distribution; #phi; Events", kTH1F, {{nBinsPhi, -3.2, 3.2}}); - histosMCreco.add("collin_soper_phi_2", "#phi Distribution; #phi; Events", kTH1F, {{nBinsPhi, -3.2, 3.2}}); - histosMCreco.add("collin_soper_costheta_1", "#theta Distribution;cos(#theta); Counts", kTH1F, {{nBinsCosTheta, -1, 1}}); - histosMCreco.add("collin_soper_costheta_2", "#theta Distribution;cos(#theta); Counts", kTH1F, {{nBinsCosTheta, -1, 1}}); - histosMCreco.add("phi_vs_costheta_1", "Phi vs cosTheta; #phi; cos(#theta)", kTH2F, {{nBinsPhi, -3.2, 3.2}, {nBinsCosTheta, -1, 1}}); - histosMCreco.add("phi_vs_costheta_2", "Phi vs cosTheta; #phi; cos(#theta)", kTH2F, {{nBinsPhi, -3.2, 3.2}, {nBinsCosTheta, -1, 1}}); + histosMCreco.add("collin_soper_phi_1", "#phi Distribution; #phi; Events", kTH1F, {phiAxis}); + histosMCreco.add("collin_soper_phi_2", "#phi Distribution; #phi; Events", kTH1F, {phiAxis}); + histosMCreco.add("collin_soper_costheta_1", "#theta Distribution;cos(#theta); Counts", kTH1F, {cosThetaAxis}); + histosMCreco.add("collin_soper_costheta_2", "#theta Distribution;cos(#theta); Counts", kTH1F, {cosThetaAxis}); + histosMCreco.add("phi_vs_costheta_1", "Phi vs cosTheta; #phi; cos(#theta)", kTH2F, {phiAxis, cosThetaAxis}); + histosMCreco.add("phi_vs_costheta_2", "Phi vs cosTheta; #phi; cos(#theta)", kTH2F, {phiAxis, cosThetaAxis}); } // End of init function //---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- @@ -850,6 +861,7 @@ struct ExclusiveRhoTo4Pi { Filter zdcCuts = (o2::aod::udzdc::energyCommonZNA < zdcCut) && (o2::aod::udzdc::energyCommonZNC < zdcCut); Filter bcSelectionCut = (o2::aod::udcollision::sbp == sbpCut) && (o2::aod::udcollision::itsROFb == itsROFbCut) && (o2::aod::udcollision::vtxITSTPC == vtxITSTPCcut) && (o2::aod::udcollision::tfb == tfbCut); Filter onlyPVtracks = o2::aod::udtrack::isPVContributor == true; + Filter occupCut = nabs(o2::aod::udcollision::occupancyInTime) < occupancyCut; using UDtracks = soa::Filtered>; using UDCollisions = soa::Filtered>; // using UDCollision = UDCollisions::iterator; @@ -915,8 +927,8 @@ struct ExclusiveRhoTo4Pi { for (int i = 0; i < numSelectedPionTracks; i++) { ROOT::Math::PxPyPzMVector selectedPionTrackVector(selectedPionTracks[i].px(), selectedPionTracks[i].py(), selectedPionTracks[i].pz(), o2::constants::physics::MassPionCharged); - histosData.fill(HIST("tpcSignal_Pi"), selectedPionTrackVector.P(), selectedPionTracks[i].tpcSignal()); - histosData.fill(HIST("tofBeta_Pi"), selectedPionTrackVector.P(), selectedPionTracks[i].beta()); + histosData.fill(HIST("tpcSignal_pions"), selectedPionTrackVector.P(), selectedPionTracks[i].tpcSignal()); + histosData.fill(HIST("tofBeta_pions"), selectedPionTrackVector.P(), selectedPionTracks[i].beta()); histosData.fill(HIST("tpcNSigmaPi_pions"), selectedPionTracks[i].tpcNSigmaPi(), selectedPionTrackVector.Pt()); histosData.fill(HIST("tpcNSigmaKa_pions"), selectedPionTracks[i].tpcNSigmaKa(), selectedPionTrackVector.Pt()); histosData.fill(HIST("tpcNSigmaPr_pions"), selectedPionTracks[i].tpcNSigmaPr(), selectedPionTrackVector.Pt()); @@ -945,7 +957,7 @@ struct ExclusiveRhoTo4Pi { break; } } - if (!hasAtleastOneTOF) { + if ((!hasAtleastOneTOF) && (checkOneTof == 1)) { return; } histosData.fill(HIST("EventCounts"), 3); @@ -1107,7 +1119,7 @@ struct ExclusiveRhoTo4Pi { } // End of Rapidity range selection } // End of Analysis for non 0 charge events } // End of 4 Pion Analysis Process function for Data - PROCESS_SWITCH(ExclusiveRhoTo4Pi, processData, "The Process for 4 Pion Analysis from data", true); + PROCESS_SWITCH(ExclusiveRhoTo4Pi, processData, "The Process for 4 Pion Analysis from data", false); //---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- // Begin of MC Generation function----------------------------------------------------------------------------------------------------------------------------------------------- @@ -1206,10 +1218,10 @@ struct ExclusiveRhoTo4Pi { histosMCgen.fill(HIST("phi_vs_costheta_2"), phiPair2, cosThetaPair2); } // End of 4 Pion MC Generation Process function - PROCESS_SWITCH(ExclusiveRhoTo4Pi, processMCgen, "The Process for 4 Pion Analysis from MC Generation", false); + PROCESS_SWITCH(ExclusiveRhoTo4Pi, processMCgen, "The Process for 4 Pion Analysis from MC Generation", true); // Begin of MC Reconstruction function----------------------------------------------------------------------------------------------------------------------------------------------- - using CollisionStuff = soa::Filtered>; + using CollisionStuff = soa::Join; using CollisionTotal = CollisionStuff::iterator; using TrackStuff = soa::Join; @@ -1227,7 +1239,7 @@ struct ExclusiveRhoTo4Pi { histosMCreco.fill(HIST("TrueGapSide"), truegapSide); histosMCreco.fill(HIST("EventCounts"), 1); histosMCreco.fill(HIST("vertexZ"), collision.posZ()); - histosMCreco.fill(HIST("occupancy"), collision.occupancyInTime()); + // histosMCreco.fill(HIST("occupancy"), collision.occupancyInTime()); histosMCreco.fill(HIST("V0A"), collision.totalFV0AmplitudeA()); histosMCreco.fill(HIST("FT0A"), collision.totalFT0AmplitudeA()); histosMCreco.fill(HIST("FT0C"), collision.totalFT0AmplitudeC()); @@ -1276,8 +1288,8 @@ struct ExclusiveRhoTo4Pi { for (int i = 0; i < numSelectedPionTracks; i++) { ROOT::Math::PxPyPzMVector selectedPionTrackVector(selectedPionTracks[i].px(), selectedPionTracks[i].py(), selectedPionTracks[i].pz(), o2::constants::physics::MassPionCharged); - histosMCreco.fill(HIST("tpcSignal_Pi"), selectedPionTrackVector.P(), selectedPionTracks[i].tpcSignal()); - histosMCreco.fill(HIST("tofBeta_Pi"), selectedPionTrackVector.P(), selectedPionTracks[i].beta()); + histosMCreco.fill(HIST("tpcSignal_pions"), selectedPionTrackVector.P(), selectedPionTracks[i].tpcSignal()); + histosMCreco.fill(HIST("tofBeta_pions"), selectedPionTrackVector.P(), selectedPionTracks[i].beta()); histosMCreco.fill(HIST("tpcNSigmaPi_pions"), selectedPionTracks[i].tpcNSigmaPi(), selectedPionTrackVector.Pt()); histosMCreco.fill(HIST("tpcNSigmaKa_pions"), selectedPionTracks[i].tpcNSigmaKa(), selectedPionTrackVector.Pt()); histosMCreco.fill(HIST("tpcNSigmaPr_pions"), selectedPionTracks[i].tpcNSigmaPr(), selectedPionTrackVector.Pt()); @@ -1296,6 +1308,19 @@ struct ExclusiveRhoTo4Pi { return; } + // Check if there is at least one track with TOF in the selected events, otherwise return + bool hasAtleastOneTOF = false; + for (int i = 0; i < numPiPlusTracks; i++) { + if (selectedPionPlusTracks[i].hasTOF() == true) { + hasAtleastOneTOF = true; + break; + } + } + if ((!hasAtleastOneTOF) && (checkOneTof == 1)) { + return; + } + histosMCreco.fill(HIST("EventCounts"), 3); + // Selecting Events with net charge = 0 if (numPionMinusTRacks == numPiMinus && numPiPlusTracks == numPiPlus) { @@ -1338,7 +1363,7 @@ struct ExclusiveRhoTo4Pi { collision.posX(), collision.posY(), collision.posZ(), collision.totalFV0AmplitudeA(), collision.totalFT0AmplitudeA(), collision.totalFT0AmplitudeC(), collision.totalFDDAmplitudeA(), collision.totalFDDAmplitudeC(), collision.timeFV0A(), collision.timeFT0A(), collision.timeFT0C(), collision.timeFDDA(), collision.timeFDDC(), - collision.timeZNA(), collision.timeZNC(), collision.occupancyInTime(), + collision.timeZNA(), collision.timeZNC(), 100, selectedPionPlusTracks[0].dcaXY(), selectedPionPlusTracks[1].dcaXY(), selectedPionMinusTracks[0].dcaXY(), selectedPionMinusTracks[1].dcaXY(), selectedPionPlusTracks[0].dcaZ(), selectedPionPlusTracks[1].dcaZ(), selectedPionMinusTracks[0].dcaZ(), selectedPionMinusTracks[1].dcaZ(), selectedPionPlusTracks[0].tpcNSigmaPi(), selectedPionPlusTracks[1].tpcNSigmaPi(), selectedPionMinusTracks[0].tpcNSigmaPi(), selectedPionMinusTracks[1].tpcNSigmaPi(), From 0e37ae3febfe6d080a03b92d739aebb20dce8dfd Mon Sep 17 00:00:00 2001 From: ddobrigk Date: Sun, 22 Jun 2025 21:35:56 +0200 Subject: [PATCH 181/871] [Common] Single-device, autodetecting-enabled event selection refactor (#11613) Co-authored-by: David Dobrigkeit Chinellato Co-authored-by: ALICE Builder --- Common/TableProducer/CMakeLists.txt | 5 + .../TableProducer/eventSelectionService.cxx | 191 ++ Common/Tools/EventSelectionTools.h | 1624 +++++++++++++++++ 3 files changed, 1820 insertions(+) create mode 100644 Common/TableProducer/eventSelectionService.cxx create mode 100644 Common/Tools/EventSelectionTools.h diff --git a/Common/TableProducer/CMakeLists.txt b/Common/TableProducer/CMakeLists.txt index 502f3c3d076..40cb408511e 100644 --- a/Common/TableProducer/CMakeLists.txt +++ b/Common/TableProducer/CMakeLists.txt @@ -27,6 +27,11 @@ o2physics_add_dpl_workflow(event-selection PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCCDB COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(event-selection-service + SOURCES eventSelectionService.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCCDB + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(multiplicity-table SOURCES multiplicityTable.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore diff --git a/Common/TableProducer/eventSelectionService.cxx b/Common/TableProducer/eventSelectionService.cxx new file mode 100644 index 00000000000..996317e1ab3 --- /dev/null +++ b/Common/TableProducer/eventSelectionService.cxx @@ -0,0 +1,191 @@ +// 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 eventSelectionTester.cxx +/// \brief unified, self-configuring event selection task +/// \author ALICE + +//=============================================================== +// +// Unified, self-configuring event selection task +// +//=============================================================== + +#include "MetadataHelper.h" + +#include "Common/Core/trackUtilities.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "Common/Tools/EventSelectionTools.h" + +#include "CCDB/BasicCCDBManager.h" +#include "CCDB/CcdbApi.h" +#include "CommonConstants/GeomConstants.h" +#include "CommonUtils/NameConf.h" +#include "DataFormatsCalibration/MeanVertexObject.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "DetectorsBase/GeometryManager.h" +#include "DetectorsBase/Propagator.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/RunningWorkflowInfo.h" +#include "Framework/runDataProcessing.h" +#include "ReconstructionDataFormats/DCA.h" + +using namespace o2; +using namespace o2::framework; + +MetadataHelper metadataInfo; // Metadata helper + +using BCsWithRun2InfosTimestampsAndMatches = soa::Join; +using BCsWithRun3Matchings = soa::Join; +using FullTracks = soa::Join; +using FullTracksIU = soa::Join; + +struct eventselectionRun2 { + o2::common::eventselection::bcselConfigurables bcselOpts; + o2::common::eventselection::BcSelectionModule bcselmodule; + + o2::common::eventselection::evselConfigurables evselOpts; + o2::common::eventselection::EventSelectionModule evselmodule; + + Produces bcsel; + Produces evsel; + + // for slicing + SliceCache cache; + + // CCDB boilerplate declarations + o2::framework::Configurable ccdburl{"ccdburl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Service ccdb; + + HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + + // the best: have readable cursors + // this: a stopgap solution to avoid spawning yet another device + std::vector bcselsbuffer; + + // auxiliary + Partition tracklets = (aod::track::trackType == static_cast(o2::aod::track::TrackTypeEnum::Run2Tracklet)); + Preslice perCollision = aod::track::collisionId; + + void init(o2::framework::InitContext& context) + { + // CCDB boilerplate init + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + ccdb->setURL(ccdburl.value); + + // task-specific + bcselmodule.init(context, bcselOpts, histos); + evselmodule.init(context, evselOpts, histos, metadataInfo); + } + + void process(BCsWithRun2InfosTimestampsAndMatches const& bcs, + aod::Collisions const& collisions, + aod::Zdcs const&, + aod::FV0As const&, + aod::FV0Cs const&, + aod::FT0s const&, + aod::FDDs const&, + FullTracks const&) + { + bcselmodule.processRun2(ccdb, bcs, bcselsbuffer, bcsel); + evselmodule.processRun2(ccdb, histos, collisions, tracklets, cache, bcselsbuffer, evsel); + } +}; + +struct eventselectionRun3 { + o2::common::eventselection::bcselConfigurables bcselOpts; + o2::common::eventselection::BcSelectionModule bcselmodule; + + o2::common::eventselection::evselConfigurables evselOpts; + o2::common::eventselection::EventSelectionModule evselmodule; + + o2::common::eventselection::lumiConfigurables lumiOpts; + o2::common::eventselection::LumiModule lumimodule; + + Produces bcsel; + Produces evsel; + + // for slicing + SliceCache cache; + + // CCDB boilerplate declarations + o2::framework::Configurable ccdburl{"ccdburl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Service ccdb; + + HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + + // the best: have readable cursors + // this: a stopgap solution to avoid spawning yet another device + std::vector bcselsbuffer; + + // auxiliary + Partition pvTracks = ((aod::track::flags & static_cast(o2::aod::track::PVContributor)) == static_cast(o2::aod::track::PVContributor)); + Preslice perCollisionIU = aod::track::collisionId; + + void init(o2::framework::InitContext& context) + { + // CCDB boilerplate init + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + ccdb->setURL(ccdburl.value); + + // task-specific + bcselmodule.init(context, bcselOpts, histos); + evselmodule.init(context, evselOpts, histos, metadataInfo); + lumimodule.init(context, lumiOpts, histos); + } + + void process(aod::Collisions const& collisions, + BCsWithRun3Matchings const& bcs, + aod::Zdcs const&, + aod::FV0As const&, + aod::FT0s const& ft0s, // to resolve iterator + aod::FDDs const&, + FullTracksIU const&) + { + bcselmodule.processRun3(ccdb, histos, bcs, bcselsbuffer, bcsel); + evselmodule.processRun3(ccdb, histos, bcs, collisions, pvTracks, ft0s, cache, bcselsbuffer, evsel); + lumimodule.process(ccdb, histos, bcs, bcselsbuffer); + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + // Parse the metadata for later too + metadataInfo.initMetadata(cfgc); + + bool isRun3 = true, hasRunInfo = false; + if (cfgc.options().hasOption("aod-metadata-Run") == true) { + hasRunInfo = true; + if (cfgc.options().get("aod-metadata-Run") == "2") { + isRun3 = false; + } + } + + LOGF(info, "Event selection autoconfiguring from metadata. Availability of info for Run 2/3 is %i", hasRunInfo); + if (!hasRunInfo) { + LOGF(info, "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(info, "Initializing with Run 3 data as default. Please note you will not be able to change settings manually."); + LOGF(info, "You should instead make sure the metadata is read in correctly."); + 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)}; + } else { + return WorkflowSpec{adaptAnalysisTask(cfgc)}; + } + } + throw std::runtime_error("Unsupported run type / problem when configuring event selection!"); +} diff --git a/Common/Tools/EventSelectionTools.h b/Common/Tools/EventSelectionTools.h new file mode 100644 index 00000000000..e7822a61556 --- /dev/null +++ b/Common/Tools/EventSelectionTools.h @@ -0,0 +1,1624 @@ +// 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 EventSelectionModule.h +/// \brief +/// \author ALICE + +#ifndef COMMON_TOOLS_EVENTSELECTIONTOOLS_H_ +#define COMMON_TOOLS_EVENTSELECTIONTOOLS_H_ + +#define bitcheck(var, nbit) ((var) & (static_cast(1) << (nbit))) +#define bitcheck64(var, nbit) ((var) & (static_cast(1) << (nbit))) + +#include "MetadataHelper.h" +#include "TableHelper.h" + +#include "Common/CCDB/EventSelectionParams.h" +#include "Common/CCDB/TriggerAliases.h" +#include "Common/DataModel/EventSelection.h" + +#include "CCDB/BasicCCDBManager.h" +#include "CommonConstants/LHCConstants.h" +#include "DataFormatsCTP/Configuration.h" +#include "DataFormatsCTP/Scalers.h" +#include "DataFormatsFT0/Digit.h" +#include "DataFormatsITSMFT/NoiseMap.h" // missing include in TimeDeadMap.h +#include "DataFormatsITSMFT/TimeDeadMap.h" +#include "DataFormatsParameters/AggregatedRunInfo.h" +#include "DataFormatsParameters/GRPECSObject.h" +#include "DataFormatsParameters/GRPLHCIFData.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/HistogramRegistry.h" +#include "ITSMFTBase/DPLAlpideParam.h" +#include "ITSMFTReconstruction/ChipMappingITS.h" + +#include +#include +#include +#include +#include + +//__________________________________________ +// MultModule + +namespace o2 +{ +namespace common +{ +namespace eventselection +{ +static const double bcNS = o2::constants::lhc::LHCBunchSpacingNS; +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 { + uint32_t alias{0}; + uint64_t selection{0}; + uint32_t rct{0}; + int foundFT0Id = -1; + int foundFV0Id = -1; + int foundFDDId = -1; + int foundZDCId = -1; +}; + +// bc selection configurables +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 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> maxInactiveChipsPerLayer{"maxInactiveChipsPerLayer", {8, 8, 8, 111, 111, 195, 195}, "Maximum allowed number of inactive ITS chips per layer"}; + 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 { + std::string prefix = "evselOpts"; + bool isMC_metadata = false; + 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"}; + o2::framework::Configurable isMC{"isMC", -1, "-1 - autoset, 0 - data, 1 - MC"}; + o2::framework::Configurable confSigmaBCforHighPtTracks{"confSigmaBCforHighPtTracks", 4, "Custom sigma (in bcs) for collisions with high-pt tracks"}; + + // configurables for occupancy-based event selection + o2::framework::Configurable confTimeIntervalForOccupancyCalculationMin{"TimeIntervalForOccupancyCalculationMin", -40, "Min time diff window for TPC occupancy calculation, us"}; // o2-linter: disable=name/configurable (temporary fix) + o2::framework::Configurable confTimeIntervalForOccupancyCalculationMax{"TimeIntervalForOccupancyCalculationMax", 100, "Max time diff window for TPC occupancy calculation, us"}; // o2-linter: disable=name/configurable (temporary fix) + o2::framework::Configurable confTimeRangeVetoOnCollStandard{"TimeRangeVetoOnCollStandard", 10.0, "Exclusion of a collision if there are other collisions nearby, +/- us"}; // o2-linter: disable=name/configurable (temporary fix) + o2::framework::Configurable confTimeRangeVetoOnCollNarrow{"TimeRangeVetoOnCollNarrow", 2.0, "Exclusion of a collision if there are other collisions nearby, +/- us"}; // o2-linter: disable=name/configurable (temporary fix) + o2::framework::Configurable confFT0CamplCutVetoOnCollInTimeRange{"FT0CamplPerCollCutVetoOnCollInTimeRange", 8000, "Max allowed FT0C amplitude for each nearby collision in +/- time range"}; // o2-linter: disable=name/configurable (temporary fix) + o2::framework::Configurable confFT0CamplCutVetoOnCollInROF{"FT0CamplPerCollCutVetoOnCollInROF", 5000, "Max allowed FT0C amplitude for each nearby collision inside this ITS ROF"}; // o2-linter: disable=name/configurable (temporary fix) + o2::framework::Configurable confEpsilonVzDiffVetoInROF{"EpsilonVzDiffVetoInROF", 0.3, "Minumum distance to nearby collisions along z inside this ITS ROF, cm"}; // o2-linter: disable=name/configurable (temporary fix) + o2::framework::Configurable confUseWeightsForOccupancyVariable{"UseWeightsForOccupancyEstimator", 1, "Use or not the delta-time weights for the occupancy estimator"}; // 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) +}; + +// luminosity configurables +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) +}; + +class BcSelectionModule +{ + public: + BcSelectionModule() + { + // constructor + } + // declaration of structs here + // (N.B.: will be invisible to the outside, create your own copies) + o2::common::eventselection::bcselConfigurables bcselOpts; + + int lastRun = -1; + int64_t lastTF = -1; + uint32_t lastRCT = 0; + uint64_t sorTimestamp = 0; // default SOR timestamp + uint64_t eorTimestamp = 1; // default EOR timestamp + int64_t bcSOR = -1; // global bc of the start of run + int64_t nBCsPerTF = -1; // duration of TF in bcs, should be 128*3564 or 32*3564 + int rofOffset = -1; // ITS ROF offset, in bc + int rofLength = -1; // ITS ROF length, in bc + int mITSROFrameStartBorderMargin = 10; // default value + int mITSROFrameEndBorderMargin = 20; // default value + int mTimeFrameStartBorderMargin = 300; // default value + int mTimeFrameEndBorderMargin = 4000; // default value + TriggerAliases* aliases = nullptr; + EventSelectionParams* par = nullptr; + std::map* mapRCT = nullptr; + std::map> mapInactiveChips; // number of inactive chips vs orbit per layer + int64_t prevOrbitForInactiveChips = 0; // cached next stored orbit in the inactive chip map + int64_t nextOrbitForInactiveChips = 0; // cached previous stored orbit in the inactive chip map + bool isGoodITSLayer3 = true; // default value + bool isGoodITSLayer0123 = true; // default value + bool isGoodITSLayersAll = true; // default value + + template + void init(TContext& context, TBcSelOpts const& external_bcselopts, THistoRegistry& histos) + { + // read in configurations from the task where it's used + bcselOpts = external_bcselopts; + + if (bcselOpts.amIneeded.value < 0) { + int bcSelNeeded = -1, evSelNeeded = -1; + bcselOpts.amIneeded.value = 0; + enableFlagIfTableRequired(context, "BcSels", bcSelNeeded); + enableFlagIfTableRequired(context, "EvSels", evSelNeeded); + if (bcSelNeeded == 1) { + bcselOpts.amIneeded.value = 1; + LOGF(info, "BC Selection / Autodetection for aod::BcSels: subscription present, will generate."); + } + if (evSelNeeded == 1 && bcSelNeeded == 0) { + bcselOpts.amIneeded.value = 1; + LOGF(info, "BC Selection / Autodetection for aod::BcSels: not there, but EvSel needed. Will generate."); + } + if (bcSelNeeded == 0 && evSelNeeded == 0) { + LOGF(info, "BC Selection / Autodetection for aod::BcSels: not required. Skipping generation."); + return; + } + } + + // add counter + histos.add("bcselection/hCounterInvalidBCTimestamp", "", o2::framework::kTH1D, {{1, 0., 1.}}); + } + + //__________________________________________________ + template + bool configure(TCCDB& ccdb, TBCs const& bcs) + { + if (bcs.size() == 0) + return false; + int run = bcs.iteratorAt(0).runNumber(); + if (run != lastRun) { + lastRun = run; + int run3min = 500000; + if (run < run3min) { // unanchored Run3 MC + auto runDuration = ccdb->getRunDuration(run, true); // fatalise if timestamps are not found + // SOR and EOR timestamps + sorTimestamp = runDuration.first; // timestamp of the SOR/SOX/STF in ms + eorTimestamp = runDuration.second; // timestamp of the EOR/EOX/ETF in ms + auto ctp = ccdb->template getForTimeStamp>("CTP/Calib/OrbitReset", sorTimestamp / 2 + eorTimestamp / 2); + auto orbitResetMUS = (*ctp)[0]; + // first bc of the first orbit + bcSOR = static_cast((sorTimestamp * 1000 - orbitResetMUS) / o2::constants::lhc::LHCOrbitMUS) * nBCsPerOrbit; + // duration of TF in bcs + nBCsPerTF = 32; // hard-coded for Run3 MC (no info from ccdb at the moment) + } else { + auto runInfo = o2::parameters::AggregatedRunInfo::buildAggregatedRunInfo(o2::ccdb::BasicCCDBManager::instance(), run); + // SOR and EOR timestamps + sorTimestamp = runInfo.sor; + eorTimestamp = runInfo.eor; + // first bc of the first orbit + bcSOR = runInfo.orbitSOR * nBCsPerOrbit; + // duration of TF in bcs + nBCsPerTF = bcselOpts.confNumberOfOrbitsPerTF < 0 ? runInfo.orbitsPerTF * nBCsPerOrbit : bcselOpts.confNumberOfOrbitsPerTF * nBCsPerOrbit; + } + + // timestamp of the middle of the run used to access run-wise CCDB entries + int64_t ts = sorTimestamp / 2 + eorTimestamp / 2; + // access ITSROF and TF border margins + par = ccdb->template getForTimeStamp("EventSelection/EventSelectionParams", ts); + mITSROFrameStartBorderMargin = bcselOpts.confITSROFrameStartBorderMargin < 0 ? par->fITSROFrameStartBorderMargin : bcselOpts.confITSROFrameStartBorderMargin; + mITSROFrameEndBorderMargin = bcselOpts.confITSROFrameEndBorderMargin < 0 ? par->fITSROFrameEndBorderMargin : bcselOpts.confITSROFrameEndBorderMargin; + mTimeFrameStartBorderMargin = bcselOpts.confTimeFrameStartBorderMargin < 0 ? par->fTimeFrameStartBorderMargin : bcselOpts.confTimeFrameStartBorderMargin; + mTimeFrameEndBorderMargin = bcselOpts.confTimeFrameEndBorderMargin < 0 ? par->fTimeFrameEndBorderMargin : bcselOpts.confTimeFrameEndBorderMargin; + // ITSROF parameters + auto alppar = ccdb->template getForTimeStamp>("ITS/Config/AlpideParam", ts); + rofOffset = alppar->roFrameBiasInBC; + rofLength = alppar->roFrameLengthInBC; + // Trigger aliases + aliases = ccdb->template getForTimeStamp("EventSelection/TriggerAliases", ts); + + // prepare map of inactive chips + auto itsDeadMap = ccdb->template getForTimeStamp("ITS/Calib/TimeDeadMap", ts); + auto itsDeadMapOrbits = itsDeadMap->getEvolvingMapKeys(); // roughly every second, ~350 TFs = 350x32 orbits + std::vector vClosest; // temporary vector of inactive chip ids for the current orbit range + for (const auto& orbit : itsDeadMapOrbits) { + itsDeadMap->getMapAtOrbit(orbit, vClosest); + // insert initial (orbit,vector) pair for each layer + mapInactiveChips[orbit].resize(o2::itsmft::ChipMappingITS::NLayers, 0); + + // fill map of inactive chips + for (size_t iel = 0; iel < vClosest.size(); iel++) { + uint16_t w1 = vClosest[iel]; + bool isLastInSequence = (w1 & 0x8000) == 0; + uint16_t w2 = isLastInSequence ? w1 + 1 : vClosest[iel + 1]; + uint16_t chipId1 = w1 & 0x7FFF; + uint16_t chipId2 = w2 & 0x7FFF; + for (int chipId = chipId1; chipId < chipId2; chipId++) { + auto layer = o2::itsmft::ChipMappingITS::getLayer(chipId); + mapInactiveChips[orbit][layer]++; + } + } // loop over vector of inactive chip ids + } // loop over orbits + + // QC info + std::map metadata; + metadata["run"] = Form("%d", run); + ccdb->setFatalWhenNull(0); + mapRCT = ccdb->template getSpecific>("RCT/Flags/RunFlags", ts, metadata); + ccdb->setFatalWhenNull(1); + if (mapRCT == nullptr) { + LOGP(info, "rct object missing... inserting dummy rct flags"); + mapRCT = new std::map; + uint32_t dummyValue = 1 << 31; // setting bit 31 to indicate that rct object is missing + mapRCT->insert(std::pair(sorTimestamp, dummyValue)); + } + } + return true; + } + + //__________________________________________________ + template + void processRun2(TCCDB const& ccdb, TBCs const& bcs, TBcSelBuffer& bcselbuffer, TBcSelCursor& bcsel) + { + if (bcselOpts.amIneeded.value == 0) { + bcselbuffer.clear(); + return; + } + bcselbuffer.clear(); + for (const auto& bc : bcs) { + par = ccdb->template getForTimeStamp("EventSelection/EventSelectionParams", bc.timestamp()); + aliases = ccdb->template getForTimeStamp("EventSelection/TriggerAliases", bc.timestamp()); + // fill fired aliases + uint32_t alias{0}; + uint64_t triggerMask = bc.triggerMask(); + for (const auto& al : aliases->GetAliasToTriggerMaskMap()) { + if (triggerMask & al.second) { + alias |= BIT(al.first); + } + } + uint64_t triggerMaskNext50 = bc.triggerMaskNext50(); + for (const auto& al : aliases->GetAliasToTriggerMaskNext50Map()) { + if (triggerMaskNext50 & al.second) { + alias |= BIT(al.first); + } + } + alias |= BIT(kALL); + + // get timing info from ZDC, FV0, FT0 and FDD + float timeZNA = bc.has_zdc() ? bc.zdc().timeZNA() : -999.f; + float timeZNC = bc.has_zdc() ? bc.zdc().timeZNC() : -999.f; + float timeV0A = bc.has_fv0a() ? bc.fv0a().time() : -999.f; + float timeV0C = bc.has_fv0c() ? bc.fv0c().time() : -999.f; + float timeT0A = bc.has_ft0() ? bc.ft0().timeA() : -999.f; + float timeT0C = bc.has_ft0() ? bc.ft0().timeC() : -999.f; + float timeFDA = bc.has_fdd() ? bc.fdd().timeA() : -999.f; + float timeFDC = bc.has_fdd() ? bc.fdd().timeC() : -999.f; + + LOGF(debug, "timeZNA=%f timeZNC=%f", timeZNA, timeZNC); + LOGF(debug, "timeV0A=%f timeV0C=%f", timeV0A, timeV0C); + LOGF(debug, "timeFDA=%f timeFDC=%f", timeFDA, timeFDC); + LOGF(debug, "timeT0A=%f timeT0C=%f", timeT0A, timeT0C); + + // fill time-based selection criteria + uint64_t selection{0}; + selection |= timeV0A > par->fV0ABBlower && timeV0A < par->fV0ABBupper ? BIT(aod::evsel::kIsBBV0A) : 0; + selection |= timeV0C > par->fV0CBBlower && timeV0C < par->fV0CBBupper ? BIT(aod::evsel::kIsBBV0C) : 0; + selection |= timeFDA > par->fFDABBlower && timeFDA < par->fFDABBupper ? BIT(aod::evsel::kIsBBFDA) : 0; + selection |= timeFDC > par->fFDCBBlower && timeFDC < par->fFDCBBupper ? BIT(aod::evsel::kIsBBFDC) : 0; + selection |= !(timeV0A > par->fV0ABGlower && timeV0A < par->fV0ABGupper) ? BIT(aod::evsel::kNoBGV0A) : 0; + selection |= !(timeV0C > par->fV0CBGlower && timeV0C < par->fV0CBGupper) ? BIT(aod::evsel::kNoBGV0C) : 0; + selection |= !(timeFDA > par->fFDABGlower && timeFDA < par->fFDABGupper) ? BIT(aod::evsel::kNoBGFDA) : 0; + selection |= !(timeFDC > par->fFDCBGlower && timeFDC < par->fFDCBGupper) ? BIT(aod::evsel::kNoBGFDC) : 0; + selection |= (timeT0A > par->fT0ABBlower && timeT0A < par->fT0ABBupper) ? BIT(aod::evsel::kIsBBT0A) : 0; + selection |= (timeT0C > par->fT0CBBlower && timeT0C < par->fT0CBBupper) ? BIT(aod::evsel::kIsBBT0C) : 0; + selection |= (timeZNA > par->fZNABBlower && timeZNA < par->fZNABBupper) ? BIT(aod::evsel::kIsBBZNA) : 0; + selection |= (timeZNC > par->fZNCBBlower && timeZNC < par->fZNCBBupper) ? BIT(aod::evsel::kIsBBZNC) : 0; + selection |= !(std::fabs(timeZNA) > par->fZNABGlower && std::fabs(timeZNA) < par->fZNABGupper) ? BIT(aod::evsel::kNoBGZNA) : 0; + selection |= !(std::fabs(timeZNC) > par->fZNCBGlower && std::fabs(timeZNC) < par->fZNCBGupper) ? BIT(aod::evsel::kNoBGZNC) : 0; + selection |= (std::pow((timeZNA + timeZNC - par->fZNSumMean) / par->fZNSumSigma, 2) + std::pow((timeZNA - timeZNC - par->fZNDifMean) / par->fZNDifSigma, 2) < 1) ? BIT(aod::evsel::kIsBBZAC) : 0; + + // Calculate V0 multiplicity per ring + float multRingV0A[5] = {0.}; + float multRingV0C[4] = {0.}; + float multFV0A = 0; + float multFV0C = 0; + if (bc.has_fv0a()) { + for (unsigned int i = 0; i < bc.fv0a().amplitude().size(); ++i) { + int ring = bc.fv0a().channel()[i] / 8; + multRingV0A[ring] += bc.fv0a().amplitude()[i]; + multFV0A += bc.fv0a().amplitude()[i]; + } + } + + if (bc.has_fv0c()) { + for (unsigned int i = 0; i < bc.fv0c().amplitude().size(); ++i) { + int ring = bc.fv0c().channel()[i] / 8; + multRingV0C[ring] += bc.fv0c().amplitude()[i]; + multFV0C += bc.fv0c().amplitude()[i]; + } + } + + // Calculate pileup and background related selection flags + // V0A0 excluded from online V0A charge sum => excluding also from offline sum for consistency + float ofV0M = multFV0A + multFV0C - multRingV0A[0]; + float onV0M = bc.v0TriggerChargeA() + bc.v0TriggerChargeC(); + float ofSPD = bc.spdFiredChipsL0() + bc.spdFiredChipsL1(); + float onSPD = bc.spdFiredFastOrL0() + bc.spdFiredFastOrL1(); + float multV0C012 = multRingV0C[0] + multRingV0C[1] + multRingV0C[2]; + + selection |= (onV0M > par->fV0MOnVsOfA + par->fV0MOnVsOfB * ofV0M) ? BIT(aod::evsel::kNoV0MOnVsOfPileup) : 0; + selection |= (onSPD > par->fSPDOnVsOfA + par->fSPDOnVsOfB * ofSPD) ? BIT(aod::evsel::kNoSPDOnVsOfPileup) : 0; + selection |= (multRingV0C[3] > par->fV0CasymA + par->fV0CasymB * multV0C012) ? BIT(aod::evsel::kNoV0Casymmetry) : 0; + selection |= (TESTBIT(selection, aod::evsel::kIsBBV0A) || TESTBIT(selection, aod::evsel::kIsBBV0C) || ofSPD) ? BIT(aod::evsel::kIsINT1) : 0; + selection |= (bc.has_ft0() ? TESTBIT(bc.ft0().triggerMask(), o2::ft0::Triggers::bitVertex) : 0) ? BIT(aod::evsel::kIsTriggerTVX) : 0; + + // copy remaining selection decisions from eventCuts + uint32_t eventCuts = bc.eventCuts(); + selection |= (eventCuts & 1 << aod::kTimeRangeCut) ? BIT(aod::evsel::kIsGoodTimeRange) : 0; + selection |= (eventCuts & 1 << aod::kIncompleteDAQ) ? BIT(aod::evsel::kNoIncompleteDAQ) : 0; + selection |= !(eventCuts & 1 << aod::kIsTPCLaserWarmUp) ? BIT(aod::evsel::kNoTPCLaserWarmUp) : 0; + selection |= !(eventCuts & 1 << aod::kIsTPCHVdip) ? BIT(aod::evsel::kNoTPCHVdip) : 0; + selection |= !(eventCuts & 1 << aod::kIsPileupFromSPD) ? BIT(aod::evsel::kNoPileupFromSPD) : 0; + selection |= !(eventCuts & 1 << aod::kIsV0PFPileup) ? BIT(aod::evsel::kNoV0PFPileup) : 0; + selection |= (eventCuts & 1 << aod::kConsistencySPDandTrackVertices) ? BIT(aod::evsel::kNoInconsistentVtx) : 0; + selection |= (eventCuts & 1 << aod::kPileupInMultBins) ? BIT(aod::evsel::kNoPileupInMultBins) : 0; + selection |= (eventCuts & 1 << aod::kPileUpMV) ? BIT(aod::evsel::kNoPileupMV) : 0; + selection |= (eventCuts & 1 << aod::kTPCPileUp) ? BIT(aod::evsel::kNoPileupTPC) : 0; + + int32_t foundFT0 = bc.has_ft0() ? bc.ft0().globalIndex() : -1; + int32_t foundFV0 = bc.has_fv0a() ? bc.fv0a().globalIndex() : -1; + int32_t foundFDD = bc.has_fdd() ? bc.fdd().globalIndex() : -1; + int32_t foundZDC = bc.has_zdc() ? bc.zdc().globalIndex() : -1; + + // // Fill TVX (T0 vertex) counters FIXME - this is a bug, there's no hCounterTVX in this task + // if (TESTBIT(selection, aod::evsel::kIsTriggerTVX)) { + // histos.get(HIST("hCounterTVX"))->Fill(Form("%d", bc.runNumber()), 1); + // } + + uint32_t rct = 0; + + // initialize properties + o2::common::eventselection::bcselEntry entry; + entry.alias = alias; + entry.selection = selection; + entry.rct = rct; + entry.foundFT0Id = foundFT0; + entry.foundFV0Id = foundFV0; + entry.foundFDDId = foundFDD; + entry.foundZDCId = foundZDC; + bcselbuffer.push_back(entry); + + // Fill bc selection columns + bcsel(alias, selection, rct, foundFT0, foundFV0, foundFDD, foundZDC); + } // end bc loop + } // end processRun2 + + //__________________________________________________ + template + void processRun3(TCCDB const& ccdb, THistoRegistry& histos, TBCs const& bcs, TBcSelBuffer& bcselbuffer, TBcSelCursor& bcsel) + { + if (bcselOpts.amIneeded.value == 0) { + bcselbuffer.clear(); + return; + } + bcselbuffer.clear(); + if (!configure(ccdb, bcs)) + 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) + // store rct flags + uint32_t rct = lastRCT; + int64_t thisTF = (bc.globalBC() - bcSOR) / nBCsPerTF; + if (mapRCT != nullptr && thisTF != lastTF) { // skip for unanchored runs; do it once per TF + auto itrct = mapRCT->upper_bound(bc.timestamp()); + if (itrct != mapRCT->begin()) + itrct--; + rct = itrct->second; + LOGP(debug, "sor={} eor={} ts={} rct={}", sorTimestamp, eorTimestamp, bc.timestamp(), rct); + lastRCT = rct; + lastTF = thisTF; + } + + 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(); + for (const auto& al : aliases->GetAliasToTriggerMaskMap()) { + if (triggerMask & al.second) { + alias |= BIT(al.first); + } + } + } + alias |= BIT(kALL); + + // get timing info from ZDC, FV0, FT0 and FDD + float timeZNA = bc.has_zdc() ? bc.zdc().timeZNA() : -999.f; + float timeZNC = bc.has_zdc() ? bc.zdc().timeZNC() : -999.f; + float timeV0A = bc.has_fv0a() ? bc.fv0a().time() : -999.f; + float timeT0A = bc.has_ft0() ? bc.ft0().timeA() : -999.f; + float timeT0C = bc.has_ft0() ? bc.ft0().timeC() : -999.f; + float timeFDA = bc.has_fdd() ? bc.fdd().timeA() : -999.f; + float timeFDC = bc.has_fdd() ? bc.fdd().timeC() : -999.f; + float timeV0ABG = -999.f; + float timeT0ABG = -999.f; + float timeT0CBG = -999.f; + float timeFDABG = -999.f; + float timeFDCBG = -999.f; + + uint64_t globalBC = bc.globalBC(); + // move to previous bcs to check beam-gas in FT0, FV0 and FDD + int64_t backwardMoveCount = 0; + int64_t deltaBC = 6; // up to 6 bcs back + while (bc.globalBC() + deltaBC >= globalBC) { + if (bc == bcs.begin()) { + break; + } + --bc; + backwardMoveCount++; + int bcDistanceToBeamGasForFT0 = 1; + int bcDistanceToBeamGasForFDD = 5; + if (bc.globalBC() + bcDistanceToBeamGasForFT0 == globalBC) { + timeV0ABG = bc.has_fv0a() ? bc.fv0a().time() : -999.f; + timeT0ABG = bc.has_ft0() ? bc.ft0().timeA() : -999.f; + timeT0CBG = bc.has_ft0() ? bc.ft0().timeC() : -999.f; + } + if (bc.globalBC() + bcDistanceToBeamGasForFDD == globalBC) { + timeFDABG = bc.has_fdd() ? bc.fdd().timeA() : -999.f; + timeFDCBG = bc.has_fdd() ? bc.fdd().timeC() : -999.f; + } + } + // move back to initial position + bc.moveByIndex(backwardMoveCount); + + // fill time-based selection criteria + uint64_t selection{0}; + selection |= timeV0A > par->fV0ABBlower && timeV0A < par->fV0ABBupper ? BIT(aod::evsel::kIsBBV0A) : 0; + selection |= timeFDA > par->fFDABBlower && timeFDA < par->fFDABBupper ? BIT(aod::evsel::kIsBBFDA) : 0; + selection |= timeFDC > par->fFDCBBlower && timeFDC < par->fFDCBBupper ? BIT(aod::evsel::kIsBBFDC) : 0; + selection |= !(timeV0ABG > par->fV0ABGlower && timeV0ABG < par->fV0ABGupper) ? BIT(aod::evsel::kNoBGV0A) : 0; + selection |= !(timeFDABG > par->fFDABGlower && timeFDABG < par->fFDABGupper) ? BIT(aod::evsel::kNoBGFDA) : 0; + selection |= !(timeFDCBG > par->fFDCBGlower && timeFDCBG < par->fFDCBGupper) ? BIT(aod::evsel::kNoBGFDC) : 0; + selection |= !(timeT0ABG > par->fT0ABGlower && timeT0ABG < par->fT0ABGupper) ? BIT(aod::evsel::kNoBGT0A) : 0; + selection |= !(timeT0CBG > par->fT0CBGlower && timeT0CBG < par->fT0CBGupper) ? BIT(aod::evsel::kNoBGT0C) : 0; + selection |= (timeT0A > par->fT0ABBlower && timeT0A < par->fT0ABBupper) ? BIT(aod::evsel::kIsBBT0A) : 0; + selection |= (timeT0C > par->fT0CBBlower && timeT0C < par->fT0CBBupper) ? BIT(aod::evsel::kIsBBT0C) : 0; + selection |= (timeZNA > par->fZNABBlower && timeZNA < par->fZNABBupper) ? BIT(aod::evsel::kIsBBZNA) : 0; + selection |= (timeZNC > par->fZNCBBlower && timeZNC < par->fZNCBBupper) ? BIT(aod::evsel::kIsBBZNC) : 0; + selection |= (std::pow((timeZNA + timeZNC - par->fZNSumMean) / par->fZNSumSigma, 2) + std::pow((timeZNA - timeZNC - par->fZNDifMean) / par->fZNDifSigma, 2) < 1) ? BIT(aod::evsel::kIsBBZAC) : 0; + selection |= !(std::fabs(timeZNA) > par->fZNABGlower && std::fabs(timeZNA) < par->fZNABGupper) ? BIT(aod::evsel::kNoBGZNA) : 0; + selection |= !(std::fabs(timeZNC) > par->fZNCBGlower && std::fabs(timeZNC) < par->fZNCBGupper) ? BIT(aod::evsel::kNoBGZNC) : 0; + selection |= (bc.has_ft0() ? (bc.ft0().triggerMask() & BIT(o2::ft0::Triggers::bitVertex)) > 0 : 0) ? BIT(aod::evsel::kIsTriggerTVX) : 0; + + // check if bc is far from start and end of the ITS RO Frame border + uint16_t bcInITSROF = (globalBC + nBCsPerOrbit - rofOffset) % rofLength; + LOGP(debug, "bcInITSROF={}", bcInITSROF); + selection |= bcInITSROF > mITSROFrameStartBorderMargin && bcInITSROF < rofLength - mITSROFrameEndBorderMargin ? BIT(aod::evsel::kNoITSROFrameBorder) : 0; + + // check if bc is far from the Time Frame borders + int64_t bcInTF = (globalBC - bcSOR) % nBCsPerTF; + LOGP(debug, "bcInTF={}", bcInTF); + selection |= bcInTF > mTimeFrameStartBorderMargin && bcInTF < nBCsPerTF - mTimeFrameEndBorderMargin ? BIT(aod::evsel::kNoTimeFrameBorder) : 0; + + // check number of inactive chips and set kIsGoodITSLayer3, kIsGoodITSLayer0123, kIsGoodITSLayersAll flags + int64_t orbit = globalBC / nBCsPerOrbit; + if (mapInactiveChips.size() > 0 && (orbit < prevOrbitForInactiveChips || orbit > nextOrbitForInactiveChips)) { + auto it = mapInactiveChips.upper_bound(orbit); + bool isEnd = (it == mapInactiveChips.end()); + if (isEnd) + it--; + nextOrbitForInactiveChips = isEnd ? orbit : it->first; // setting current orbit in case we reached the end of mapInactiveChips + auto vNextInactiveChips = it->second; + if (it != mapInactiveChips.begin() && !isEnd) + it--; + prevOrbitForInactiveChips = it->first; + auto vPrevInactiveChips = it->second; + LOGP(debug, "orbit: {}, previous orbit: {}, next orbit: {} ", orbit, prevOrbitForInactiveChips, nextOrbitForInactiveChips); + LOGP(debug, "next inactive chips: {} {} {} {} {} {} {}", vNextInactiveChips[0], vNextInactiveChips[1], vNextInactiveChips[2], vNextInactiveChips[3], vNextInactiveChips[4], vNextInactiveChips[5], vNextInactiveChips[6]); + LOGP(debug, "prev inactive chips: {} {} {} {} {} {} {}", vPrevInactiveChips[0], vPrevInactiveChips[1], vPrevInactiveChips[2], vPrevInactiveChips[3], vPrevInactiveChips[4], vPrevInactiveChips[5], vPrevInactiveChips[6]); + isGoodITSLayer3 = vPrevInactiveChips[3] <= bcselOpts.maxInactiveChipsPerLayer->at(3) && vNextInactiveChips[3] <= bcselOpts.maxInactiveChipsPerLayer->at(3); + isGoodITSLayer0123 = true; + for (int i = 0; i < 4; i++) { // o2-linter: disable=magic-number (counting first 4 ITS layers) + isGoodITSLayer0123 &= vPrevInactiveChips[i] <= bcselOpts.maxInactiveChipsPerLayer->at(i) && vNextInactiveChips[i] <= bcselOpts.maxInactiveChipsPerLayer->at(i); + } + isGoodITSLayersAll = true; + for (int i = 0; i < o2::itsmft::ChipMappingITS::NLayers; i++) { + isGoodITSLayersAll &= vPrevInactiveChips[i] <= bcselOpts.maxInactiveChipsPerLayer->at(i) && vNextInactiveChips[i] <= bcselOpts.maxInactiveChipsPerLayer->at(i); + } + } + + selection |= isGoodITSLayer3 ? BIT(aod::evsel::kIsGoodITSLayer3) : 0; + selection |= isGoodITSLayer0123 ? BIT(aod::evsel::kIsGoodITSLayer0123) : 0; + selection |= isGoodITSLayersAll ? BIT(aod::evsel::kIsGoodITSLayersAll) : 0; + + // fill found indices + int32_t foundFT0 = bc.has_ft0() ? bc.ft0().globalIndex() : -1; + int32_t foundFV0 = bc.has_fv0a() ? bc.fv0a().globalIndex() : -1; + int32_t foundFDD = bc.has_fdd() ? bc.fdd().globalIndex() : -1; + int32_t foundZDC = bc.has_zdc() ? bc.zdc().globalIndex() : -1; + LOGP(debug, "foundFT0={}", foundFT0); + + const char* srun = Form("%d", run); + if (bc.timestamp() < sorTimestamp || bc.timestamp() > eorTimestamp) { + histos.template get(HIST("bcselection/hCounterInvalidBCTimestamp"))->Fill(srun, 1); + if (bcselOpts.confCheckRunDurationLimits.value) { + LOGF(warn, "Invalid BC timestamp: %d, run: %d, sor: %d, eor: %d", bc.timestamp(), run, sorTimestamp, eorTimestamp); + alias = 0u; + selection = 0u; + } + } + + // initialize properties + o2::common::eventselection::bcselEntry entry; + entry.alias = alias; + entry.selection = selection; + entry.rct = rct; + entry.foundFT0Id = foundFT0; + entry.foundFV0Id = foundFV0; + entry.foundFDDId = foundFDD; + entry.foundZDCId = foundZDC; + bcselbuffer.push_back(entry); + + // Fill bc selection columns + bcsel(alias, selection, rct, foundFT0, foundFV0, foundFDD, foundZDC); + } // end bc loop + } // end processRun3 +}; // end BcSelectionModule + +class EventSelectionModule +{ + public: + EventSelectionModule() + { + // constructor + } + + int run3min = 500000; + int lastRun = -1; // last run number (needed to access ccdb only if run!=lastRun) + std::bitset bcPatternB; // bc pattern of colliding bunches + + int64_t bcSOR = -1; // global bc of the start of the first orbit + int64_t nBCsPerTF = -1; // duration of TF in bcs, should be 128*3564 or 32*3564 + int rofOffset = -1; // ITS ROF offset, in bc + int rofLength = -1; // ITS ROF length, in bc + + int32_t findClosest(int64_t globalBC, std::map& bcs) + { + auto it = bcs.lower_bound(globalBC); + int64_t bc1 = it->first; + int32_t index1 = it->second; + if (it != bcs.begin()) + --it; + int64_t bc2 = it->first; + int32_t index2 = it->second; + int64_t dbc1 = std::abs(bc1 - globalBC); + int64_t dbc2 = std::abs(bc2 - globalBC); + return (dbc1 <= dbc2) ? index1 : index2; + } + + // helper function to find median time in the vector of TOF or TRD-track times + float getMedian(std::vector v) + { + int medianIndex = v.size() / 2; + std::nth_element(v.begin(), v.begin() + medianIndex, v.end()); + return v[medianIndex]; + } + + // helper function to find closest TVX signal in time and in zVtx + int64_t findBestGlobalBC(int64_t meanBC, int64_t sigmaBC, int32_t nContrib, float zVtxCol, std::map& mapGlobalBcVtxZ) + { + // protection against + if (sigmaBC < 1) + sigmaBC = 1; + + int64_t minBC = meanBC - 3 * sigmaBC; + int64_t maxBC = meanBC + 3 * sigmaBC; + // TODO: use ITS ROF bounds to reduce the search range? + + float zVtxSigma = 2.7 * std::pow(nContrib, -0.466) + 0.024; + zVtxSigma += 1.0; // additional uncertainty due to imperfectections of FT0 time calibration + + auto itMin = mapGlobalBcVtxZ.lower_bound(minBC); + auto itMax = mapGlobalBcVtxZ.upper_bound(maxBC); + + float bestChi2 = 1e+10; + int64_t bestGlobalBC = 0; + for (std::map::iterator it = itMin; it != itMax; ++it) { + float chi2 = std::pow((it->second - zVtxCol) / zVtxSigma, 2) + std::pow(static_cast(it->first - meanBC) / sigmaBC, 2.); + if (chi2 < bestChi2) { + bestChi2 = chi2; + bestGlobalBC = it->first; + } + } + + return bestGlobalBC; + } + + // declaration of structs here + // (N.B.: will be invisible to the outside, create your own copies) + o2::common::eventselection::evselConfigurables evselOpts; + + template + void init(TContext& context, TEvSelOpts const& external_evselopts, THistoRegistry& histos, TMetadataInfo const& metadataInfo) + { + // read in configurations from the task where it's used + evselOpts = external_evselopts; + + if (evselOpts.amIneeded.value < 0) { + enableFlagIfTableRequired(context, "EvSels", evselOpts.amIneeded.value); + if (evselOpts.amIneeded.value == 0) { + LOGF(info, "Event Selection / Autodetecting for aod::EvSels: not required, won't generate."); + return; + } else { + LOGF(info, "Event Selection / Autodetecting for aod::EvSels: subscription present, will generate."); + } + } + + if (metadataInfo.isFullyDefined()) { // Check if the metadata is initialized (only if not forced from the workflow configuration) + if (evselOpts.isMC == -1) { + LOGF(info, "Autosetting the MC mode based on metadata (isMC? %i)", metadataInfo.isMC()); + if (metadataInfo.isMC()) { + evselOpts.isMC.value = 1; + } else { + evselOpts.isMC.value = 0; + } + } + } + + histos.add("eventselection/hColCounterAll", "", framework::kTH1D, {{1, 0., 1.}}); + histos.add("eventselection/hColCounterTVX", "", framework::kTH1D, {{1, 0., 1.}}); + histos.add("eventselection/hColCounterAcc", "", framework::kTH1D, {{1, 0., 1.}}); + } + + //__________________________________________________ + template + bool configure(TCCDB& ccdb, TBCs const& bcs) + { + int run = bcs.iteratorAt(0).runNumber(); + // extract bc pattern from CCDB for data or anchored MC only + if (run != lastRun && run >= run3min) { + lastRun = run; + auto runInfo = o2::parameters::AggregatedRunInfo::buildAggregatedRunInfo(o2::ccdb::BasicCCDBManager::instance(), run); + // first bc of the first orbit + bcSOR = runInfo.orbitSOR * nBCsPerOrbit; + // duration of TF in bcs + nBCsPerTF = evselOpts.confNumberOfOrbitsPerTF < 0 ? runInfo.orbitsPerTF * nBCsPerOrbit : evselOpts.confNumberOfOrbitsPerTF * nBCsPerOrbit; + // colliding bc pattern + int64_t ts = bcs.iteratorAt(0).timestamp(); + // getForTimeStamp replaced with getSpecific to set metadata to zero + // avoids crash related to specific run number + auto grplhcif = ccdb->template getSpecific("GLO/Config/GRPLHCIF", ts); + bcPatternB = grplhcif->getBunchFilling().getBCPattern(); + + // extract ITS ROF parameters + auto alppar = ccdb->template getForTimeStamp>("ITS/Config/AlpideParam", ts); + rofOffset = alppar->roFrameBiasInBC; + rofLength = alppar->roFrameLengthInBC; + LOGP(debug, "ITS ROF Offset={} ITS ROF Length={}", rofOffset, rofLength); + } // if run != lastRun + return true; + } + + //__________________________________________________ + template + void processRun2(TCCDB const& ccdb, THistoRegistry& histos, TCollisions const& collisions, TTracklets const& tracklets, TSlicecache& cache, TBcSelBuffer const& bcselbuffer, TEvselCursor& evsel) + { + if (evselOpts.amIneeded.value == 0) { + return; // dummy process + } + for (const auto& col : collisions) { + auto bc = col.template bc_as>(); + EventSelectionParams* par = ccdb->template getForTimeStamp("EventSelection/EventSelectionParams", bc.timestamp()); + bool* applySelection = par->getSelection(evselOpts.muonSelection); + if (evselOpts.isMC == 1) { + applySelection[aod::evsel::kIsBBZAC] = 0; + applySelection[aod::evsel::kNoV0MOnVsOfPileup] = 0; + applySelection[aod::evsel::kNoSPDOnVsOfPileup] = 0; + applySelection[aod::evsel::kNoV0Casymmetry] = 0; + applySelection[aod::evsel::kNoV0PFPileup] = 0; + } + + int32_t foundBC = bc.globalIndex(); + int32_t foundFT0 = bcselbuffer[foundBC].foundFT0Id; + int32_t foundFV0 = bcselbuffer[foundBC].foundFV0Id; + int32_t foundFDD = bcselbuffer[foundBC].foundFDDId; + int32_t foundZDC = bcselbuffer[foundBC].foundZDCId; + + // copy alias decisions from bcsel table + uint32_t alias = bcselbuffer[foundBC].alias; + + // copy selection decisions from bcsel table + uint64_t selection = bcselbuffer[foundBC].selection; + + // copy rct flags from bcsel table + uint32_t rct = bcselbuffer[foundBC].rct; + + // calculate V0C012 multiplicity + float multRingV0C[4] = {0.}; + if (bc.has_fv0c()) { + for (unsigned int i = 0; i < bc.fv0c().amplitude().size(); ++i) { + int ring = bc.fv0c().channel()[i] / 8; + multRingV0C[ring] += bc.fv0c().amplitude()[i]; + } + } + float multV0C012 = multRingV0C[0] + multRingV0C[1] + multRingV0C[2]; + + // applying selections depending on the number of tracklets + auto trackletsGrouped = tracklets.sliceByCached(aod::track::collisionId, col.globalIndex(), cache); + int nTkl = trackletsGrouped.size(); + int spdClusters = bc.spdClustersL0() + bc.spdClustersL1(); + + selection |= (spdClusters < par->fSPDClsVsTklA + nTkl * par->fSPDClsVsTklB) ? BIT(aod::evsel::kNoSPDClsVsTklBG) : 0; + selection |= !(nTkl < 6 && multV0C012 > par->fV0C012vsTklA + nTkl * par->fV0C012vsTklB) ? BIT(aod::evsel::kNoV0C012vsTklBG) : 0; // o2-linter: disable=magic-number (nTkl dependent parameterization) + + // apply int7-like selections + bool sel7 = 1; + for (int i = 0; i < aod::evsel::kNsel; i++) { + sel7 = sel7 && (applySelection[i] ? TESTBIT(selection, i) : 1); + } + + // 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); + + // 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))) { + 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); + } + } + + evsel(alias, selection, rct, sel7, sel8, foundBC, foundFT0, foundFV0, foundFDD, foundZDC, 0, 0); + } + } // end processRun2 + + //__________________________________________________ + template + void processRun3(TCCDB const& ccdb, THistoRegistry& histos, TBCs const& bcs, TCollisions const& cols, TPVTracks const& pvTracks, TFT0s const& ft0s, TSlicecache& cache, TBcSelBuffer const& bcselbuffer, TEvselCursor& evsel) + { + if (evselOpts.amIneeded.value == 0) { + return; // dummy process + } + if (!configure(ccdb, bcs)) + return; // don't do anything in case configuration reported not ok + + int run = bcs.iteratorAt(0).runNumber(); + // create maps from globalBC to bc index for TVX-fired bcs + // to be used for closest TVX searches + std::map mapGlobalBcWithTVX; + std::map mapGlobalBcVtxZ; + for (const auto& bc : bcs) { + int64_t globalBC = bc.globalBC(); + // skip non-colliding bcs for data and anchored runs + if (run >= run3min && bcPatternB[globalBC % nBCsPerOrbit] == 0) { + continue; + } + auto selection = bcselbuffer[bc.globalIndex()].selection; + if (bitcheck64(selection, aod::evsel::kIsTriggerTVX)) { + mapGlobalBcWithTVX[globalBC] = bc.globalIndex(); + mapGlobalBcVtxZ[globalBC] = bc.has_ft0() ? bc.ft0().posZ() : 0; + } + } + + // protection against empty FT0 maps + if (mapGlobalBcWithTVX.size() == 0) { + LOGP(error, "FT0 table is empty or corrupted. Filling evsel table with dummy values"); + for (const auto& col : cols) { + auto bc = col.template bc_as>(); + int32_t foundBC = bc.globalIndex(); + int32_t foundFT0 = bcselbuffer[bc.globalIndex()].foundFT0Id; + int32_t foundFV0 = bcselbuffer[bc.globalIndex()].foundFV0Id; + int32_t foundFDD = bcselbuffer[bc.globalIndex()].foundFDDId; + int32_t foundZDC = bcselbuffer[bc.globalIndex()].foundZDCId; + uint32_t rct = 0; + evsel(bcselbuffer[bc.globalIndex()].alias, bcselbuffer[bc.globalIndex()].selection, rct, kFALSE, kFALSE, foundBC, foundFT0, foundFV0, foundFDD, foundZDC, -1, -1); + } + return; + } + std::vector vTracksITS567perColl(cols.size(), 0); // counter of tracks per collision for occupancy studies + std::vector vAmpFT0CperColl(cols.size(), 0); // amplitude FT0C per collision + std::vector vCollVz(cols.size(), 0); // vector with vZ positions for each collision + std::vector vIsFullInfoForOccupancy(cols.size(), 0); // info for occupancy in +/- windows is available (i.e. a given coll is not too close to the TF borders) + const float timeWinOccupancyCalcMinNS = evselOpts.confTimeIntervalForOccupancyCalculationMin * 1e3; // ns + const float timeWinOccupancyCalcMaxNS = evselOpts.confTimeIntervalForOccupancyCalculationMax * 1e3; // ns + std::vector vIsVertexITSTPC(cols.size(), 0); // at least one of vertex contributors is ITS-TPC track + std::vector vIsVertexTOFmatched(cols.size(), 0); // at least one of vertex contributors is matched to TOF + std::vector vIsVertexTRDmatched(cols.size(), 0); // at least one of vertex contributors is matched to TRD + + std::vector vCollisionsPerBc(bcs.size(), 0); // counter of collisions per found bc for pileup checks + std::vector vFoundBCindex(cols.size(), -1); // indices of found bcs + std::vector vFoundGlobalBC(cols.size(), 0); // global BCs for collisions + + std::vector vIsVertexTOF(cols.size(), 0); + std::vector vIsVertexTRD(cols.size(), 0); + std::vector vIsVertexTPC(cols.size(), 0); + std::vector vIsVertexHighPtTPC(cols.size(), 0); + std::vector vNcontributors(cols.size(), 0); + std::vector vWeightedTimesTPCnoTOFnoTRD(cols.size(), 0); + std::vector vWeightedSigmaTPCnoTOFnoTRD(cols.size(), 0); + + // temporary vectors to find tracks with median time + std::vector vTrackTimesTOF; + std::vector vTrackTimesTRDnoTOF; + + // first loop to match collisions to TVX, also extract other per-collision information for further use + for (const auto& col : cols) { + int32_t colIndex = col.globalIndex(); + auto bc = col.template bc_as>(); + + vCollVz[colIndex] = col.posZ(); + + int64_t globalBC = bc.globalBC(); + int bcInTF = (bc.globalBC() - bcSOR) % nBCsPerTF; + vIsFullInfoForOccupancy[colIndex] = ((bcInTF - 300) * bcNS > -timeWinOccupancyCalcMinNS) && ((nBCsPerTF - 4000 - bcInTF) * bcNS > timeWinOccupancyCalcMaxNS) ? true : false; + + const auto& colPvTracks = pvTracks.sliceByCached(aod::track::collisionId, col.globalIndex(), cache); + vTrackTimesTOF.clear(); + vTrackTimesTRDnoTOF.clear(); + int nPvTracksTPCnoTOFnoTRD = 0; + int nPvTracksHighPtTPCnoTOFnoTRD = 0; + float sumTime = 0, sumW = 0, sumHighPtTime = 0, sumHighPtW = 0; + for (const auto& track : colPvTracks) { + float trackTime = track.trackTime(); + if (track.itsNCls() >= 5) // o2-linter: disable=magic-number (indeed counting layers 5 6 7) + vTracksITS567perColl[colIndex]++; + if (track.hasTRD()) + vIsVertexTRDmatched[colIndex] = 1; + if (track.hasTPC()) + vIsVertexITSTPC[colIndex] = 1; + if (track.hasTOF()) { + vTrackTimesTOF.push_back(trackTime); + vIsVertexTOFmatched[colIndex] = 1; + } else if (track.hasTRD()) { + vTrackTimesTRDnoTOF.push_back(trackTime); + } else if (track.hasTPC()) { + float trackTimeRes = track.trackTimeRes(); + float trackPt = track.pt(); + float w = 1. / (trackTimeRes * trackTimeRes); + sumTime += trackTime * w; + sumW += w; + nPvTracksTPCnoTOFnoTRD++; + if (trackPt > 1) { + sumHighPtTime += trackTime * w; + sumHighPtW += w; + nPvTracksHighPtTPCnoTOFnoTRD++; + } + } + } + vWeightedTimesTPCnoTOFnoTRD[colIndex] = sumW > 0 ? sumTime / sumW : 0; + vWeightedSigmaTPCnoTOFnoTRD[colIndex] = sumW > 0 ? std::sqrt(1. / sumW) : 0; + vNcontributors[colIndex] = colPvTracks.size(); + int nPvTracksTOF = vTrackTimesTOF.size(); + int nPvTracksTRDnoTOF = vTrackTimesTRDnoTOF.size(); + // collision type + vIsVertexTOF[colIndex] = nPvTracksTOF > 0; + vIsVertexTRD[colIndex] = nPvTracksTRDnoTOF > 0; + vIsVertexTPC[colIndex] = nPvTracksTPCnoTOFnoTRD > 0; + vIsVertexHighPtTPC[colIndex] = nPvTracksHighPtTPCnoTOFnoTRD > 0; + + int64_t foundGlobalBC = 0; + int32_t foundBCindex = -1; + + if (nPvTracksTOF > 0) { + // for collisions with TOF tracks: + // take bc corresponding to TOF track with median time + int64_t tofGlobalBC = globalBC + TMath::Nint(getMedian(vTrackTimesTOF) / bcNS); + std::map::iterator it = mapGlobalBcWithTVX.find(tofGlobalBC); + if (it != mapGlobalBcWithTVX.end()) { + foundGlobalBC = it->first; + foundBCindex = it->second; + } + } else if (nPvTracksTPCnoTOFnoTRD == 0 && nPvTracksTRDnoTOF > 0) { + // for collisions with TRD tracks but without TOF or ITSTPC-only tracks: + // take bc corresponding to TRD track with median time + int64_t trdGlobalBC = globalBC + TMath::Nint(getMedian(vTrackTimesTRDnoTOF) / bcNS); + std::map::iterator it = mapGlobalBcWithTVX.find(trdGlobalBC); + if (it != mapGlobalBcWithTVX.end()) { + foundGlobalBC = it->first; + foundBCindex = it->second; + } + } else if (nPvTracksHighPtTPCnoTOFnoTRD > 0) { + // for collisions with high-pt ITSTPC-nonTOF-nonTRD tracks + // search in 3*confSigmaBCforHighPtTracks range (3*4 bcs by default) + int64_t meanBC = globalBC + TMath::Nint(sumHighPtTime / sumHighPtW / bcNS); + int64_t bestGlobalBC = findBestGlobalBC(meanBC, evselOpts.confSigmaBCforHighPtTracks, vNcontributors[colIndex], col.posZ(), mapGlobalBcVtxZ); + if (bestGlobalBC > 0) { + foundGlobalBC = bestGlobalBC; + foundBCindex = mapGlobalBcWithTVX[bestGlobalBC]; + } + } + + // fill foundBC indices and global BCs + // keep current bc if TVX matching failed at this step + vFoundBCindex[colIndex] = foundBCindex >= 0 ? foundBCindex : bc.globalIndex(); + vFoundGlobalBC[colIndex] = foundGlobalBC > 0 ? foundGlobalBC : globalBC; + + // erase found global BC with TVX from the pool of bcs for the next loop over low-pt TPCnoTOFnoTRD collisions + if (foundBCindex >= 0) + mapGlobalBcVtxZ.erase(foundGlobalBC); + } + + // second loop to match remaining low-pt TPCnoTOFnoTRD collisions + for (const auto& col : cols) { + int32_t colIndex = col.globalIndex(); + if (vIsVertexTPC[colIndex] > 0 && vIsVertexTOF[colIndex] == 0 && vIsVertexHighPtTPC[colIndex] == 0) { + float weightedTime = vWeightedTimesTPCnoTOFnoTRD[colIndex]; + float weightedSigma = vWeightedSigmaTPCnoTOFnoTRD[colIndex]; + auto bc = col.template bc_as>(); + int64_t globalBC = bc.globalBC(); + int64_t meanBC = globalBC + TMath::Nint(weightedTime / bcNS); + int64_t sigmaBC = TMath::CeilNint(weightedSigma / bcNS); + int64_t bestGlobalBC = findBestGlobalBC(meanBC, sigmaBC, vNcontributors[colIndex], col.posZ(), mapGlobalBcVtxZ); + vFoundGlobalBC[colIndex] = bestGlobalBC > 0 ? bestGlobalBC : globalBC; + vFoundBCindex[colIndex] = bestGlobalBC > 0 ? mapGlobalBcWithTVX[bestGlobalBC] : bc.globalIndex(); + } + // fill pileup counter + vCollisionsPerBc[vFoundBCindex[colIndex]]++; + } + + // save indices of collisions for occupancy calculation (both in ROF and in time range) + std::vector> vCollsInSameITSROF; + std::vector> vCollsInPrevITSROF; + std::vector> vCollsInTimeWin; + std::vector> vTimeDeltaForColls; // delta time wrt a given collision + for (const auto& col : cols) { + int32_t colIndex = col.globalIndex(); + int64_t foundGlobalBC = vFoundGlobalBC[colIndex]; + auto bcselEntr = bcselbuffer[vFoundBCindex[colIndex]]; + if (bcselEntr.foundFT0Id > -1) { + // required: explicit ft0s table + auto foundFT0 = ft0s.rawIteratorAt(bcselEntr.foundFT0Id); + vAmpFT0CperColl[colIndex] = foundFT0.sumAmpC(); + } + + int64_t tfId = (foundGlobalBC - bcSOR) / nBCsPerTF; + int64_t rofId = (foundGlobalBC + nBCsPerOrbit - rofOffset) / rofLength; + + // ### for in-ROF occupancy + std::vector vAssocCollInSameROF; + // find all collisions in the same ROF before a given collision + int32_t minColIndex = colIndex - 1; + while (minColIndex >= 0) { + int64_t thisBC = vFoundGlobalBC[minColIndex]; + // check if this is still the same TF + int64_t thisTFid = (thisBC - bcSOR) / nBCsPerTF; + if (thisTFid != tfId) + break; + // int thisRofIdInTF = (thisBC - rofOffset) / rofLength; + int64_t thisRofId = (thisBC + nBCsPerOrbit - rofOffset) / rofLength; + + // check if we are within the same ROF + if (thisRofId != rofId) + break; + vAssocCollInSameROF.push_back(minColIndex); + minColIndex--; + } + // find all collisions in the same ROF after the current one + int32_t maxColIndex = colIndex + 1; + while (maxColIndex < cols.size()) { + int64_t thisBC = vFoundGlobalBC[maxColIndex]; + int64_t thisTFid = (thisBC - bcSOR) / nBCsPerTF; + if (thisTFid != tfId) + break; + int64_t thisRofId = (thisBC + nBCsPerOrbit - rofOffset) / rofLength; + if (thisRofId != rofId) + break; + vAssocCollInSameROF.push_back(maxColIndex); + maxColIndex++; + } + vCollsInSameITSROF.push_back(vAssocCollInSameROF); + + // ### bookkeep collisions in previous ROF + std::vector vAssocCollInPrevROF; + minColIndex = colIndex - 1; + while (minColIndex >= 0) { + int64_t thisBC = vFoundGlobalBC[minColIndex]; + // check if this is still the same TF + int64_t thisTFid = (thisBC - bcSOR) / nBCsPerTF; + if (thisTFid != tfId) + break; + int64_t thisRofId = (thisBC + nBCsPerOrbit - rofOffset) / rofLength; + if (thisRofId == rofId - 1) + vAssocCollInPrevROF.push_back(minColIndex); + else if (thisRofId < rofId - 1) + break; + minColIndex--; + } + vCollsInPrevITSROF.push_back(vAssocCollInPrevROF); + + // ### for occupancy in time windows + std::vector vAssocToThisCol; + std::vector vCollsTimeDeltaWrtGivenColl; + // protection against the TF borders + if (!vIsFullInfoForOccupancy[colIndex]) { + vCollsInTimeWin.push_back(vAssocToThisCol); + vTimeDeltaForColls.push_back(vCollsTimeDeltaWrtGivenColl); + continue; + } + // find all collisions in time window before the current one + minColIndex = colIndex - 1; + while (minColIndex >= 0) { + int64_t thisBC = vFoundGlobalBC[minColIndex]; + // check if this is still the same TF + int64_t thisTFid = (thisBC - bcSOR) / nBCsPerTF; + if (thisTFid != tfId) + break; + float dt = (thisBC - foundGlobalBC) * bcNS; // ns + // check if we are within the chosen time range + if (dt < timeWinOccupancyCalcMinNS) + break; + vAssocToThisCol.push_back(minColIndex); + vCollsTimeDeltaWrtGivenColl.push_back(dt); + minColIndex--; + } + // find all collisions in time window after the current one + maxColIndex = colIndex + 1; + while (maxColIndex < cols.size()) { + int64_t thisBC = vFoundGlobalBC[maxColIndex]; + int64_t thisTFid = (thisBC - bcSOR) / nBCsPerTF; + if (thisTFid != tfId) + break; + float dt = (thisBC - foundGlobalBC) * bcNS; // ns + if (dt > timeWinOccupancyCalcMaxNS) + break; + vAssocToThisCol.push_back(maxColIndex); + vCollsTimeDeltaWrtGivenColl.push_back(dt); + maxColIndex++; + } + vCollsInTimeWin.push_back(vAssocToThisCol); + vTimeDeltaForColls.push_back(vCollsTimeDeltaWrtGivenColl); + } + + // perform the occupancy calculation per ITS ROF and also in the pre-defined time window + std::vector vNumTracksITS567inFullTimeWin(cols.size(), 0); // counter of tracks in full time window for occupancy studies (excluding given event) + std::vector vSumAmpFT0CinFullTimeWin(cols.size(), 0); // sum of FT0C of tracks in full time window for occupancy studies (excluding given event) + + std::vector vNoCollInTimeRangeStrict(cols.size(), 0); // no collisions in a specified time range + std::vector vNoCollInTimeRangeNarrow(cols.size(), 0); // no collisions in a specified time range (narrow) + std::vector vNoHighMultCollInTimeRange(cols.size(), 0); // no high-mult collisions in a specified time range + + std::vector vNoCollInSameRofStrict(cols.size(), 0); // to veto events with other collisions in the same ITS ROF + std::vector vNoCollInSameRofStandard(cols.size(), 0); // to veto events with other collisions in the same ITS ROF, with per-collision multiplicity above threshold + std::vector vNoCollInSameRofWithCloseVz(cols.size(), 0); // to veto events with nearby collisions with close vZ + std::vector vNoHighMultCollInPrevRof(cols.size(), 0); // veto events if FT0C amplitude in previous ITS ROF is above threshold + + for (const auto& col : cols) { + int32_t colIndex = col.globalIndex(); + float vZ = col.posZ(); + + // ### in-ROF occupancy + std::vector vAssocCollInSameROF = vCollsInSameITSROF[colIndex]; + int nITS567tracksForSameRofVetoStrict = 0; // to veto events with other collisions in the same ITS ROF + int nCollsInRofWithFT0CAboveVetoStandard = 0; // to veto events with other collisions in the same ITS ROF, with per-collision multiplicity above threshold + int nITS567tracksForRofVetoOnCloseVz = 0; // to veto events with nearby collisions with close vZ + for (uint32_t iCol = 0; iCol < vAssocCollInSameROF.size(); iCol++) { + int thisColIndex = vAssocCollInSameROF[iCol]; + nITS567tracksForSameRofVetoStrict += vTracksITS567perColl[thisColIndex]; + if (vAmpFT0CperColl[thisColIndex] > evselOpts.confFT0CamplCutVetoOnCollInROF) + nCollsInRofWithFT0CAboveVetoStandard++; + if (std::fabs(vCollVz[thisColIndex] - vZ) < evselOpts.confEpsilonVzDiffVetoInROF) + nITS567tracksForRofVetoOnCloseVz += vTracksITS567perColl[thisColIndex]; + } + // in-ROF occupancy flags + vNoCollInSameRofStrict[colIndex] = (nITS567tracksForSameRofVetoStrict == 0); + vNoCollInSameRofStandard[colIndex] = (nCollsInRofWithFT0CAboveVetoStandard == 0); + vNoCollInSameRofWithCloseVz[colIndex] = (nITS567tracksForRofVetoOnCloseVz == 0); + + // ### occupancy in previous ROF + std::vector vAssocCollInPrevROF = vCollsInPrevITSROF[colIndex]; + float totalFT0amplInPrevROF = 0; + for (uint32_t iCol = 0; iCol < vAssocCollInPrevROF.size(); iCol++) { + int thisColIndex = vAssocCollInPrevROF[iCol]; + totalFT0amplInPrevROF += vAmpFT0CperColl[thisColIndex]; + } + // veto events if FT0C amplitude in previous ITS ROF is above threshold + vNoHighMultCollInPrevRof[colIndex] = (totalFT0amplInPrevROF < evselOpts.confFT0CamplCutVetoOnCollInROF); + + // ### occupancy in time windows + // protection against TF borders + if (!vIsFullInfoForOccupancy[colIndex]) { // occupancy in undefined (too close to TF borders) + vNumTracksITS567inFullTimeWin[colIndex] = -1; + vSumAmpFT0CinFullTimeWin[colIndex] = -1; + continue; + } + std::vector vAssocToThisCol = vCollsInTimeWin[colIndex]; + std::vector vCollsTimeDeltaWrtGivenColl = vTimeDeltaForColls[colIndex]; + int nITS567tracksInFullTimeWindow = 0; + float sumAmpFT0CInFullTimeWindow = 0; + int nITS567tracksForVetoNarrow = 0; // to veto events with nearby collisions (narrower range) + int nITS567tracksForVetoStrict = 0; // to veto events with nearby collisions + int nCollsWithFT0CAboveVetoStandard = 0; // to veto events with per-collision multiplicity above threshold + for (uint32_t iCol = 0; iCol < vAssocToThisCol.size(); iCol++) { + int thisColIndex = vAssocToThisCol[iCol]; + float dt = vCollsTimeDeltaWrtGivenColl[iCol] / 1e3; // ns -> us + float wOccup = 1.; + if (evselOpts.confUseWeightsForOccupancyVariable) { + // weighted occupancy + wOccup = 0; + if (dt >= -40 && dt < -5) // collisions in the past // o2-linter: disable=magic-number (to be checked by Igor) + wOccup = 1. / 1225 * (dt + 40) * (dt + 40); // o2-linter: disable=magic-number (to be checked by Igor) + else if (dt >= -5 && dt < 15) // collisions near a given one // o2-linter: disable=magic-number (to be checked by Igor) + wOccup = 1; + // else if (dt >= 15 && dt < 100) // collisions from the future + // wOccup = -1. / 85 * dt + 20. / 17; + else if (dt >= 15 && dt < 40) // collisions from the future // o2-linter: disable=magic-number (to be checked by Igor) + wOccup = -0.4 / 25 * dt + 1.24; // o2-linter: disable=magic-number (to be checked by Igor) + else if (dt >= 40 && dt < 100) // collisions from the distant future // o2-linter: disable=magic-number (to be checked by Igor) + wOccup = -0.4 / 60 * dt + 0.6 + 0.8 / 3; // o2-linter: disable=magic-number (to be checked by Igor) + } + nITS567tracksInFullTimeWindow += wOccup * vTracksITS567perColl[thisColIndex]; + sumAmpFT0CInFullTimeWindow += wOccup * vAmpFT0CperColl[thisColIndex]; + + // counting tracks from other collisions in fixed time windows + if (std::fabs(dt) < evselOpts.confTimeRangeVetoOnCollNarrow) + nITS567tracksForVetoNarrow += vTracksITS567perColl[thisColIndex]; + if (std::fabs(dt) < evselOpts.confTimeRangeVetoOnCollStandard) + nITS567tracksForVetoStrict += vTracksITS567perColl[thisColIndex]; + + // standard cut on other collisions vs delta-times + const float driftV = 2.5; // drift velocity in cm/us, TPC drift_length / drift_time = 250 cm / 100 us + if (std::fabs(dt) < 2.0) { // us, complete veto on other collisions // o2-linter: disable=magic-number (to be checked by Igor) + nCollsWithFT0CAboveVetoStandard++; + } else if (dt > -4.0 && dt <= -2.0) { // us, strict veto to suppress fake ITS-TPC matches more // o2-linter: disable=magic-number (to be checked by Igor) + if (vAmpFT0CperColl[thisColIndex] > evselOpts.confFT0CamplCutVetoOnCollInTimeRange / 5) + nCollsWithFT0CAboveVetoStandard++; + } else if (std::fabs(dt) < 8 + std::fabs(vZ) / driftV) { // loose veto, 8 us corresponds to maximum possible |vZ|, which is ~20 cm // o2-linter: disable=magic-number (to be checked by Igor) + // counting number of other collisions with multiplicity above threshold + if (vAmpFT0CperColl[thisColIndex] > evselOpts.confFT0CamplCutVetoOnCollInTimeRange) + nCollsWithFT0CAboveVetoStandard++; + } + } + vNumTracksITS567inFullTimeWin[colIndex] = nITS567tracksInFullTimeWindow; // occupancy by a sum of number of ITS tracks (without a current collision) + vSumAmpFT0CinFullTimeWin[colIndex] = sumAmpFT0CInFullTimeWindow; // occupancy by a sum of FT0C amplitudes (without a current collision) + // occupancy flags based on nearby collisions + vNoCollInTimeRangeNarrow[colIndex] = (nITS567tracksForVetoNarrow == 0); + vNoCollInTimeRangeStrict[colIndex] = (nITS567tracksForVetoStrict == 0); + vNoHighMultCollInTimeRange[colIndex] = (nCollsWithFT0CAboveVetoStandard == 0); + } + + for (const auto& col : cols) { + int32_t colIndex = col.globalIndex(); + int32_t foundBC = vFoundBCindex[colIndex]; + auto bc = bcs.iteratorAt(foundBC); + auto bcselEntry = bcselbuffer[foundBC]; + int32_t foundFT0 = bcselEntry.foundFT0Id; + int32_t foundFV0 = bcselEntry.foundFV0Id; + int32_t foundFDD = bcselEntry.foundFDDId; + int32_t foundZDC = bcselEntry.foundZDCId; + + // compare zVtx from FT0 and from PV + bool isGoodZvtxFT0vsPV = 0; + if (bcselEntry.foundFT0Id > -1) { + auto foundFT0 = ft0s.rawIteratorAt(bcselEntry.foundFT0Id); + isGoodZvtxFT0vsPV = std::fabs(foundFT0.posZ() - col.posZ()) < evselOpts.maxDiffZvtxFT0vsPV; + } + + // copy alias decisions from bcsel table + uint32_t alias = bcselEntry.alias; + + // copy selection decisions from bcsel table + uint64_t selection = bcselbuffer[bc.globalIndex()].selection; + selection |= vCollisionsPerBc[foundBC] <= 1 ? BIT(aod::evsel::kNoSameBunchPileup) : 0; + selection |= vIsVertexITSTPC[colIndex] ? BIT(aod::evsel::kIsVertexITSTPC) : 0; + selection |= vIsVertexTOFmatched[colIndex] ? BIT(aod::evsel::kIsVertexTOFmatched) : 0; + selection |= vIsVertexTRDmatched[colIndex] ? BIT(aod::evsel::kIsVertexTRDmatched) : 0; + selection |= isGoodZvtxFT0vsPV ? BIT(aod::evsel::kIsGoodZvtxFT0vsPV) : 0; + + // selection bits based on occupancy time pattern + selection |= vNoCollInTimeRangeNarrow[colIndex] ? BIT(aod::evsel::kNoCollInTimeRangeNarrow) : 0; + selection |= vNoCollInTimeRangeStrict[colIndex] ? BIT(aod::evsel::kNoCollInTimeRangeStrict) : 0; + selection |= vNoHighMultCollInTimeRange[colIndex] ? BIT(aod::evsel::kNoCollInTimeRangeStandard) : 0; + + // selection bits based on ITS in-ROF occupancy + selection |= vNoCollInSameRofStrict[colIndex] ? BIT(aod::evsel::kNoCollInRofStrict) : 0; + selection |= (vNoCollInSameRofStandard[colIndex] && vNoCollInSameRofWithCloseVz[colIndex]) ? BIT(aod::evsel::kNoCollInRofStandard) : 0; + selection |= vNoHighMultCollInPrevRof[colIndex] ? BIT(aod::evsel::kNoHighMultCollInPrevRof) : 0; + + // copy rct flags from bcsel table + uint32_t rct = bcselEntry.rct; + + // apply int7-like selections + bool sel7 = 0; + + // TODO apply other cuts for sel8 + // TODO introduce sel1 etc? + // TODO introduce array of sel[0]... sel[8] or similar? + bool sel8 = bitcheck64(bcselEntry.selection, aod::evsel::kIsTriggerTVX) && bitcheck64(bcselEntry.selection, aod::evsel::kNoTimeFrameBorder) && bitcheck64(bcselEntry.selection, aod::evsel::kNoITSROFrameBorder); + + // fill counters + histos.template get(HIST("eventselection/hColCounterAll"))->Fill(Form("%d", bc.runNumber()), 1); + if (bitcheck64(bcselEntry.selection, aod::evsel::kIsTriggerTVX)) { + histos.template get(HIST("eventselection/hColCounterTVX"))->Fill(Form("%d", bc.runNumber()), 1); + } + if (sel8) { + histos.template get(HIST("eventselection/hColCounterAcc"))->Fill(Form("%d", bc.runNumber()), 1); + } + + evsel(alias, selection, rct, sel7, sel8, foundBC, foundFT0, foundFV0, foundFDD, foundZDC, + vNumTracksITS567inFullTimeWin[colIndex], vSumAmpFT0CinFullTimeWin[colIndex]); + } + } // end processRun3 +}; // end EventSelectionModule + +class LumiModule +{ + public: + LumiModule() + { + // constructor + } + + int lastRun = -1; // last run number (needed to access ccdb only if run!=lastRun) + float csTVX = -1; // dummy -1 for the visible TVX cross section (in ub) used in lumi accounting + float csTCE = -1; // dummy -1 for the visible TCE cross section (in ub) used in lumi accounting + float csZEM = -1; // dummy -1 for the visible ZEM cross section (in ub) used in lumi accounting + float csZNC = -1; // dummy -1 for the visible ZNC cross section (in ub) used in lumi accounting + + std::vector mOrbits; + std::vector mPileupCorrectionTVX; + std::vector mPileupCorrectionTCE; + std::vector mPileupCorrectionZEM; + std::vector mPileupCorrectionZNC; + + int64_t minOrbitInRange = std::numeric_limits::max(); + int64_t maxOrbitInRange = 0; + uint32_t currentOrbitIndex = 0; + std::bitset bcPatternB; // bc pattern of colliding bunches + std::vector mRCTFlagsCheckers; + + // declaration of structs here + // (N.B.: will be invisible to the outside, create your own copies) + o2::common::eventselection::lumiConfigurables lumiOpts; + + template + void init(TContext& context, TLumiOpts const& external_lumiopts, THistoRegistry& histos) + { + lumiOpts = external_lumiopts; + + if (lumiOpts.amIneeded.value < 0) { + int bcSelNeeded = -1, evSelNeeded = -1; + lumiOpts.amIneeded.value = 0; + enableFlagIfTableRequired(context, "BcSels", bcSelNeeded); + enableFlagIfTableRequired(context, "EvSels", evSelNeeded); + if (bcSelNeeded == 1) { + lumiOpts.amIneeded.value = 1; + LOGF(info, "Luminosity / Autodetection for aod::BcSels: subscription present, will generate."); + } + if (evSelNeeded == 1 && bcSelNeeded == 0) { + lumiOpts.amIneeded.value = 1; + LOGF(info, "Luminosity / Autodetection for aod::BcSels: not there, but EvSel needed. Will generate."); + } + if (bcSelNeeded == 0 && evSelNeeded == 0) { + LOGF(info, "Luminosity / Autodetection for aod::BcSels: not required. Skipping generation."); + return; + } + } + + histos.add("luminosity/hCounterTVX", "", framework::kTH1D, {{1, 0., 1.}}); + histos.add("luminosity/hCounterTCE", "", framework::kTH1D, {{1, 0., 1.}}); + histos.add("luminosity/hCounterZEM", "", framework::kTH1D, {{1, 0., 1.}}); + histos.add("luminosity/hCounterZNC", "", framework::kTH1D, {{1, 0., 1.}}); + histos.add("luminosity/hCounterTVXafterBCcuts", "", framework::kTH1D, {{1, 0., 1.}}); + histos.add("luminosity/hCounterTCEafterBCcuts", "", framework::kTH1D, {{1, 0., 1.}}); + histos.add("luminosity/hCounterZEMafterBCcuts", "", framework::kTH1D, {{1, 0., 1.}}); + histos.add("luminosity/hCounterZNCafterBCcuts", "", framework::kTH1D, {{1, 0., 1.}}); + histos.add("luminosity/hLumiTVX", ";;Luminosity, 1/#mub", framework::kTH1D, {{1, 0., 1.}}); + histos.add("luminosity/hLumiTCE", ";;Luminosity, 1/#mub", framework::kTH1D, {{1, 0., 1.}}); + histos.add("luminosity/hLumiZEM", ";;Luminosity, 1/#mub", framework::kTH1D, {{1, 0., 1.}}); + histos.add("luminosity/hLumiZNC", ";;Luminosity, 1/#mub", framework::kTH1D, {{1, 0., 1.}}); + histos.add("luminosity/hLumiTVXafterBCcuts", ";;Luminosity, 1/#mub", framework::kTH1D, {{1, 0., 1.}}); + histos.add("luminosity/hLumiTCEafterBCcuts", ";;Luminosity, 1/#mub", framework::kTH1D, {{1, 0., 1.}}); + histos.add("luminosity/hLumiZEMafterBCcuts", ";;Luminosity, 1/#mub", framework::kTH1D, {{1, 0., 1.}}); + histos.add("luminosity/hLumiZNCafterBCcuts", ";;Luminosity, 1/#mub", framework::kTH1D, {{1, 0., 1.}}); + + const int nLists = 6; + TString rctListNames[] = {"CBT", "CBT_hadronPID", "CBT_electronPID", "CBT_calo", "CBT_muon", "CBT_muon_glo"}; + histos.add("luminosity/hLumiTVXafterBCcutsRCT", ";;Luminosity, 1/#mub", framework::kTH2D, {{1, 0., 1.}, {4 * nLists, -0.5, 4. * nLists - 0.5}}); + histos.add("luminosity/hLumiTCEafterBCcutsRCT", ";;Luminosity, 1/#mub", framework::kTH2D, {{1, 0., 1.}, {4 * nLists, -0.5, 4. * nLists - 0.5}}); + histos.add("luminosity/hLumiZEMafterBCcutsRCT", ";;Luminosity, 1/#mub", framework::kTH2D, {{1, 0., 1.}, {4 * nLists, -0.5, 4. * nLists - 0.5}}); + histos.add("luminosity/hLumiZNCafterBCcutsRCT", ";;Luminosity, 1/#mub", framework::kTH2D, {{1, 0., 1.}, {4 * nLists, -0.5, 4. * nLists - 0.5}}); + + for (int i = 0; i < nLists; i++) { + const auto& rctListName = rctListNames[i]; + mRCTFlagsCheckers.emplace_back(rctListName.Data(), false, false); // disable zdc check, disable lim. acc. check + mRCTFlagsCheckers.emplace_back(rctListName.Data(), false, true); // disable zdc check, enable lim. acc. check + mRCTFlagsCheckers.emplace_back(rctListName.Data(), true, false); // enable zdc check, disable lim. acc. check + mRCTFlagsCheckers.emplace_back(rctListName.Data(), true, true); // enable zdc check, enable lim. acc. check + histos.template get(HIST("luminosity/hLumiTVXafterBCcutsRCT"))->GetYaxis()->SetBinLabel(4 * i + 1, rctListName.Data()); + histos.template get(HIST("luminosity/hLumiTCEafterBCcutsRCT"))->GetYaxis()->SetBinLabel(4 * i + 1, rctListName.Data()); + histos.template get(HIST("luminosity/hLumiZEMafterBCcutsRCT"))->GetYaxis()->SetBinLabel(4 * i + 1, rctListName.Data()); + histos.template get(HIST("luminosity/hLumiZNCafterBCcutsRCT"))->GetYaxis()->SetBinLabel(4 * i + 1, rctListName.Data()); + histos.template get(HIST("luminosity/hLumiTVXafterBCcutsRCT"))->GetYaxis()->SetBinLabel(4 * i + 2, (rctListName + "_fullacc").Data()); + histos.template get(HIST("luminosity/hLumiTCEafterBCcutsRCT"))->GetYaxis()->SetBinLabel(4 * i + 2, (rctListName + "_fullacc").Data()); + histos.template get(HIST("luminosity/hLumiZEMafterBCcutsRCT"))->GetYaxis()->SetBinLabel(4 * i + 2, (rctListName + "_fullacc").Data()); + histos.template get(HIST("luminosity/hLumiZNCafterBCcutsRCT"))->GetYaxis()->SetBinLabel(4 * i + 2, (rctListName + "_fullacc").Data()); + histos.template get(HIST("luminosity/hLumiTVXafterBCcutsRCT"))->GetYaxis()->SetBinLabel(4 * i + 3, (rctListName + "_zdc").Data()); + histos.template get(HIST("luminosity/hLumiTCEafterBCcutsRCT"))->GetYaxis()->SetBinLabel(4 * i + 3, (rctListName + "_zdc").Data()); + histos.template get(HIST("luminosity/hLumiZEMafterBCcutsRCT"))->GetYaxis()->SetBinLabel(4 * i + 3, (rctListName + "_zdc").Data()); + histos.template get(HIST("luminosity/hLumiZNCafterBCcutsRCT"))->GetYaxis()->SetBinLabel(4 * i + 3, (rctListName + "_zdc").Data()); + histos.template get(HIST("luminosity/hLumiTVXafterBCcutsRCT"))->GetYaxis()->SetBinLabel(4 * i + 4, (rctListName + "_zdc" + "_fullacc").Data()); + histos.template get(HIST("luminosity/hLumiTCEafterBCcutsRCT"))->GetYaxis()->SetBinLabel(4 * i + 4, (rctListName + "_zdc" + "_fullacc").Data()); + histos.template get(HIST("luminosity/hLumiZEMafterBCcutsRCT"))->GetYaxis()->SetBinLabel(4 * i + 4, (rctListName + "_zdc" + "_fullacc").Data()); + histos.template get(HIST("luminosity/hLumiZNCafterBCcutsRCT"))->GetYaxis()->SetBinLabel(4 * i + 4, (rctListName + "_zdc" + "_fullacc").Data()); + } + } + + template + bool configure(TCCDB& ccdb, TBCs const& bcs) + { + if (bcs.size() == 0) + return false; + int run = bcs.iteratorAt(0).runNumber(); + if (run < 500000) // o2-linter: disable=magic-number (skip for unanchored MCs) + return false; + if (run != lastRun && run >= 520259) { // o2-linter: disable=magic-number (scalers available for runs above 520120) + lastRun = run; + int64_t ts = bcs.iteratorAt(0).timestamp(); + + // getting GRP LHCIF object to extract colliding system, energy and colliding bc pattern + auto grplhcif = ccdb->template getForTimeStamp("GLO/Config/GRPLHCIF", ts); + int beamZ1 = grplhcif->getBeamZ(constants::lhc::BeamA); + int beamZ2 = grplhcif->getBeamZ(constants::lhc::BeamC); + float sqrts = grplhcif->getSqrtS(); + int nCollidingBCs = grplhcif->getBunchFilling().getNBunches(); + bcPatternB = grplhcif->getBunchFilling().getBCPattern(); + + // visible cross sections in ub. Using dummy -1 if lumi estimator is not reliable for this colliding system + csTVX = -1; + csTCE = -1; + csZEM = -1; + csZNC = -1; + // Temporary workaround to get visible cross section. TODO: store run-by-run visible cross sections in CCDB + 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 + } else if (std::fabs(sqrts - 5360.) < 100.) { // pp-ref // o2-linter: disable=magic-number (TODO store and extract cross sections from ccdb) + csTVX = 0.0503e6; // ub + } else if (std::fabs(sqrts - 13600.) < 300.) { // o2-linter: disable=magic-number (TODO store and extract cross sections from ccdb) + csTVX = 0.0594e6; // ub + } else { + LOGP(warn, "Cross section for pp @ {} GeV is not defined", sqrts); + } + } else if (beamZ1 == 82 && beamZ2 == 82) { // o2-linter: disable=magic-number (PbPb colliding system) + // see AN: https://alice-notes.web.cern.ch/node/1515 + if (std::fabs(sqrts - 5360) < 20) { // o2-linter: disable=magic-number (TODO store and extract cross sections from ccdb) + csZNC = 214.5e6; // ub + csZEM = 415.2e6; // ub + csTCE = 10.36e6; // ub + if (run > 543437 && run < 543514) { // o2-linter: disable=magic-number (TODO store and extract cross sections from ccdb) + csTCE = 8.3e6; // ub + } else if (run >= 543514 && run < 545367) { // o2-linter: disable=magic-number (TODO store and extract cross sections from ccdb) + csTCE = 4.10e6; // ub + } else if (run >= 559544) { // o2-linter: disable=magic-number (TODO store and extract cross sections from ccdb) + csTCE = 3.86e6; // ub + } + } else { + LOGP(warn, "Cross section for PbPb @ {} GeV is not defined", sqrts); + } + } else { + LOGP(warn, "Cross section for z={} + z={} @ {} GeV is not defined", beamZ1, beamZ2, sqrts); + } + // getting CTP config to extract lumi class indices (used for rate fetching and pileup correction) + std::map metadata; + metadata["runNumber"] = std::to_string(run); + auto config = ccdb->template getSpecific("CTP/Config/Config", ts, metadata); + auto classes = config->getCTPClasses(); + TString lumiClassNameZNC = "C1ZNC-B-NOPF-CRU"; + TString lumiClassNameTCE = "CMTVXTCE-B-NOPF-CRU"; + TString lumiClassNameTVX1 = "MINBIAS_TVX"; // run >= 534467 + TString lumiClassNameTVX2 = "MINBIAS_TVX_NOMASK"; // run >= 534468 + TString lumiClassNameTVX3 = "CMTVX-NONE-NOPF-CRU"; // run >= 534996 + TString lumiClassNameTVX4 = "CMTVX-B-NOPF-CRU"; // run >= 543437 + + // find class indices + int classIdZNC = -1; + int classIdTCE = -1; + int classIdTVX = -1; + for (unsigned int i = 0; i < classes.size(); i++) { + TString clname = classes[i].name; + clname.ToUpper(); + // using position (i) in the vector of classes instead of classes[i].getIndex() + // due to bug or inconsistencies in scaler record and class indices + if (clname == lumiClassNameZNC) + classIdZNC = i; + if (clname == lumiClassNameTCE) + classIdTCE = i; + if (clname == lumiClassNameTVX4 || clname == lumiClassNameTVX3 || clname == lumiClassNameTVX2 || clname == lumiClassNameTVX1) + classIdTVX = i; + } + + // extract trigger counts from CTP scalers + auto scalers = ccdb->template getSpecific("CTP/Calib/Scalers", ts, metadata); + scalers->convertRawToO2(); + std::vector mCounterTVX; + std::vector mCounterTCE; + std::vector mCounterZNC; + std::vector mCounterZEM; + mOrbits.clear(); + for (const auto& record : scalers->getScalerRecordO2()) { + mOrbits.push_back(record.intRecord.orbit); + mCounterTVX.push_back(classIdTVX >= 0 ? record.scalers[classIdTVX].lmBefore : 0); + mCounterTCE.push_back(classIdTCE >= 0 ? record.scalers[classIdTCE].lmBefore : 0); + if (run >= 543437 && run < 544448 && record.scalersInps.size() >= 26) { // o2-linter: disable=magic-number (ZNC class not defined for this run range) + mCounterZNC.push_back(record.scalersInps[25]); // see ZNC=1ZNC input index in https://indico.cern.ch/event/1153630/contributions/4844362/ + } else { + mCounterZNC.push_back(classIdZNC >= 0 ? record.scalers[classIdZNC].l1Before : 0); + } + // ZEM class not defined, using inputs instead + uint32_t indexZEM = 24; // see ZEM=1ZED input index in https://indico.cern.ch/event/1153630/contributions/4844362/ + mCounterZEM.push_back(record.scalersInps.size() >= indexZEM + 1 ? record.scalersInps[indexZEM] : 0); + } + + // calculate pileup corrections + mPileupCorrectionTVX.clear(); + mPileupCorrectionTCE.clear(); + mPileupCorrectionZEM.clear(); + mPileupCorrectionZNC.clear(); + for (uint32_t i = 0; i < mOrbits.size() - 1; i++) { + int64_t nOrbits = mOrbits[i + 1] - mOrbits[i]; + if (nOrbits <= 0 || nCollidingBCs == 0) + continue; + double perBcRateTVX = static_cast(mCounterTVX[i + 1] - mCounterTVX[i]) / nOrbits / nCollidingBCs; + 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; + 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); + } + // filling last orbit range using previous orbit range + mPileupCorrectionTVX.push_back(mPileupCorrectionTVX.back()); + mPileupCorrectionTCE.push_back(mPileupCorrectionTCE.back()); + mPileupCorrectionZNC.push_back(mPileupCorrectionZNC.back()); + mPileupCorrectionZEM.push_back(mPileupCorrectionZEM.back()); + } // access ccdb once per run + return true; // carry on, please + } + + //__________________________________________________ + template + void process(TCCDB& ccdb, THistoRegistry& histos, TBCs const& bcs, TBcSelBuffer const& bcselBuffer) + { + if (lumiOpts.amIneeded.value == 0) { + return; + } + + if (!configure(ccdb, bcs)) + return; // don't do anything in case configuration reported not ok + + int run = bcs.iteratorAt(0).runNumber(); + const char* srun = Form("%d", run); + + // processing loop + for (const auto& bc : bcs) { + auto selection = bcselBuffer[bc.globalIndex()].selection; + if (bcPatternB[bc.globalBC() % nBCsPerOrbit] == 0) // skip non-colliding bcs + continue; + + bool noBorder = TESTBIT(selection, aod::evsel::kNoTimeFrameBorder) && TESTBIT(selection, aod::evsel::kNoITSROFrameBorder); + bool isTriggerTVX = TESTBIT(selection, aod::evsel::kIsTriggerTVX); + bool isTriggerTCE = bc.has_ft0() ? (TESTBIT(selection, aod::evsel::kIsTriggerTVX) && TESTBIT(bc.ft0().triggerMask(), o2::ft0::Triggers::bitCen)) : 0; + bool isTriggerZNA = TESTBIT(selection, aod::evsel::kIsBBZNA); + bool isTriggerZNC = TESTBIT(selection, aod::evsel::kIsBBZNC); + bool isTriggerZEM = isTriggerZNA || isTriggerZNC; + + // determine pileup correction + int64_t orbit = bc.globalBC() / nBCsPerOrbit; + if ((orbit < minOrbitInRange || orbit > maxOrbitInRange) && mOrbits.size() > 1) { + auto it = std::lower_bound(mOrbits.begin(), mOrbits.end(), orbit); + uint32_t nextOrbitIndex = std::distance(mOrbits.begin(), it); + if (nextOrbitIndex == 0) // if orbit is below stored scaler orbits + nextOrbitIndex = 1; + else if (nextOrbitIndex == mOrbits.size()) // if orbit is above stored scaler orbits + nextOrbitIndex = mOrbits.size() - 1; + currentOrbitIndex = nextOrbitIndex - 1; + minOrbitInRange = mOrbits[currentOrbitIndex]; + maxOrbitInRange = mOrbits[nextOrbitIndex]; + } + double pileupCorrectionTVX = currentOrbitIndex < mPileupCorrectionTVX.size() ? mPileupCorrectionTVX[currentOrbitIndex] : 1.; + double pileupCorrectionTCE = currentOrbitIndex < mPileupCorrectionTCE.size() ? mPileupCorrectionTCE[currentOrbitIndex] : 1.; + double pileupCorrectionZNC = currentOrbitIndex < mPileupCorrectionZNC.size() ? mPileupCorrectionZNC[currentOrbitIndex] : 1.; + double pileupCorrectionZEM = currentOrbitIndex < mPileupCorrectionZEM.size() ? mPileupCorrectionZEM[currentOrbitIndex] : 1.; + + double lumiTVX = 1. / csTVX * pileupCorrectionTVX; + double lumiTCE = 1. / csTCE * pileupCorrectionTCE; + double lumiZNC = 1. / csZNC * pileupCorrectionZNC; + double lumiZEM = 1. / csZEM * pileupCorrectionZEM; + + auto rct = bcselBuffer[bc.globalIndex()].rct; + + if (isTriggerTVX) { + histos.template get(HIST("luminosity/hCounterTVX"))->Fill(srun, 1); + histos.template get(HIST("luminosity/hLumiTVX"))->Fill(srun, lumiTVX); + if (noBorder) { + histos.template get(HIST("luminosity/hCounterTVXafterBCcuts"))->Fill(srun, 1); + histos.template get(HIST("luminosity/hLumiTVXafterBCcuts"))->Fill(srun, lumiTVX); + for (size_t i = 0; i < mRCTFlagsCheckers.size(); i++) { + if ((rct & mRCTFlagsCheckers[i].value()) == 0) + histos.template get(HIST("luminosity/hLumiTVXafterBCcutsRCT"))->Fill(srun, i, lumiTVX); + } + } + } + + if (isTriggerTCE) { + histos.template get(HIST("luminosity/hCounterTCE"))->Fill(srun, 1); + histos.template get(HIST("luminosity/hLumiTCE"))->Fill(srun, lumiTCE); + if (noBorder) { + histos.template get(HIST("luminosity/hCounterTCEafterBCcuts"))->Fill(srun, 1); + histos.template get(HIST("luminosity/hLumiTCEafterBCcuts"))->Fill(srun, lumiTCE); + for (size_t i = 0; i < mRCTFlagsCheckers.size(); i++) { + if ((rct & mRCTFlagsCheckers[i].value()) == 0) + histos.template get(HIST("luminosity/hLumiTCEafterBCcutsRCT"))->Fill(srun, i, lumiTCE); + } + } + } + + if (isTriggerZEM) { + histos.template get(HIST("luminosity/hCounterZEM"))->Fill(srun, 1); + histos.template get(HIST("luminosity/hLumiZEM"))->Fill(srun, lumiZEM); + if (noBorder) { + histos.template get(HIST("luminosity/hCounterZEMafterBCcuts"))->Fill(srun, 1); + histos.template get(HIST("luminosity/hLumiZEMafterBCcuts"))->Fill(srun, lumiZEM); + for (size_t i = 0; i < mRCTFlagsCheckers.size(); i++) { + if ((rct & mRCTFlagsCheckers[i].value()) == 0) + histos.template get(HIST("luminosity/hLumiZEMafterBCcutsRCT"))->Fill(srun, i, lumiZEM); + } + } + } + + if (isTriggerZNC) { + histos.template get(HIST("luminosity/hCounterZNC"))->Fill(srun, 1); + histos.template get(HIST("luminosity/hLumiZNC"))->Fill(srun, lumiZNC); + if (noBorder) { + histos.template get(HIST("luminosity/hCounterZNCafterBCcuts"))->Fill(srun, 1); + histos.template get(HIST("luminosity/hLumiZNCafterBCcuts"))->Fill(srun, lumiZNC); + for (size_t i = 0; i < mRCTFlagsCheckers.size(); i++) { + if ((rct & mRCTFlagsCheckers[i].value()) == 0) + histos.template get(HIST("luminosity/hLumiZNCafterBCcutsRCT"))->Fill(srun, i, lumiZNC); + } + } + } + } // bcs + } // process +}; // end LumiModule + +} // namespace eventselection +} // namespace common +} // namespace o2 + +#endif // COMMON_TOOLS_EVENTSELECTIONTOOLS_H_ From 20d1e4e6be9c20d3c06b639340d97eaf4e22010e Mon Sep 17 00:00:00 2001 From: Yash Patley <52608802+yashpatley@users.noreply.github.com> Date: Mon, 23 Jun 2025 03:28:23 +0530 Subject: [PATCH 182/871] [PWGCF] Update lambdaR2Correlation.cxx (#11725) --- .../Tasks/lambdaR2Correlation.cxx | 30 +++++++++++++++++-- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/PWGCF/TwoParticleCorrelations/Tasks/lambdaR2Correlation.cxx b/PWGCF/TwoParticleCorrelations/Tasks/lambdaR2Correlation.cxx index 9a299ed8950..7c9bbc6ad67 100644 --- a/PWGCF/TwoParticleCorrelations/Tasks/lambdaR2Correlation.cxx +++ b/PWGCF/TwoParticleCorrelations/Tasks/lambdaR2Correlation.cxx @@ -339,7 +339,7 @@ struct LambdaTableProducer { const AxisSpec axisV0Phi(36, 0., TwoPI, "#phi (rad)"); const AxisSpec axisRadius(2000, 0, 200, "r(cm)"); - const AxisSpec axisCosPA(500, 0.995, 1.0, "cos(#theta_{PA})"); + const AxisSpec axisCosPA(300, 0.97, 1.0, "cos(#theta_{PA})"); const AxisSpec axisDcaV0PV(1000, 0., 10., "dca (cm)"); const AxisSpec axisDcaProngPV(5000, -50., 50., "dca (cm)"); const AxisSpec axisDcaDau(75, 0., 1.5, "Daug DCA (#sigma)"); @@ -404,7 +404,7 @@ struct LambdaTableProducer { histos.addClone("McRec/Lambda/", "McRec/AntiLambda/"); // MC Generated Histograms - if (doprocessMCRun3 || doprocessMCRun2) { + if (doprocessMCRun3 || doprocessMCRun2 || doprocessMCRecoRun3 || doprocessMCRecoRun2) { // 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}); @@ -1172,7 +1172,7 @@ struct LambdaTableProducer { using CollisionsRun3 = soa::Join; using CollisionsRun2 = soa::Join; - using Tracks = soa::Join; + using Tracks = soa::Join; using McV0Tracks = soa::Join; using TracksMC = soa::Join; @@ -1190,6 +1190,30 @@ struct LambdaTableProducer { PROCESS_SWITCH(LambdaTableProducer, processDataRun2, "Process for Run2 DATA", 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, TracksMC const& tracks, aod::McParticles const&) + { + // check collision + if (!selCollision(collision)) { + return; + } + fillLambdaRecoTables(collision, V0s, tracks); + } + + PROCESS_SWITCH(LambdaTableProducer, processMCRecoRun2, "Process for Run2 McReco DATA", false); + void processMCRun3(aod::McCollisions::iterator const& mcCollision, soa::SmallGroups> const& collisions, McV0Tracks const& V0s, TracksMC const& tracks, From c3f1440424913e031f414f0c5af7daed91b23c98 Mon Sep 17 00:00:00 2001 From: yuanzhe <90246048+wang-yuanzhe@users.noreply.github.com> Date: Mon, 23 Jun 2025 11:07:03 +0200 Subject: [PATCH 183/871] [PWGLF] Fix bug in getting ITSNSigma and update datamodel for hyphe4s (#11706) --- PWGLF/DataModel/LFHyperhelium4sigmaTables.h | 7 ++- .../Nuspex/hyperhelium4sigmaRecoTask.cxx | 55 +++++++++++++------ 2 files changed, 41 insertions(+), 21 deletions(-) diff --git a/PWGLF/DataModel/LFHyperhelium4sigmaTables.h b/PWGLF/DataModel/LFHyperhelium4sigmaTables.h index 71e04a281cf..5d50a007f66 100644 --- a/PWGLF/DataModel/LFHyperhelium4sigmaTables.h +++ b/PWGLF/DataModel/LFHyperhelium4sigmaTables.h @@ -13,8 +13,8 @@ /// \brief Slim hyperhelium4sigma tables /// \author Yuanzhe Wang -#include "Framework/AnalysisDataModel.h" #include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" #ifndef PWGLF_DATAMODEL_LFHYPERHELIUM4SIGMATABLES_H_ #define PWGLF_DATAMODEL_LFHYPERHELIUM4SIGMATABLES_H_ @@ -44,6 +44,7 @@ DECLARE_SOA_COLUMN(ItsChi2Moth, itsChi2Moth, float); // ITS DECLARE_SOA_COLUMN(ItsClusterSizesMoth, itsClusterSizesMoth, uint32_t); // ITS cluster size of the mother track DECLARE_SOA_COLUMN(ItsClusterSizesAlpha, itsClusterSizesAlpha, uint32_t); // ITS cluster size of the daughter alpha track DECLARE_SOA_COLUMN(NSigmaTPCAlpha, nSigmaTPCAlpha, float); // Number of tpc sigmas of the daughter alpha track +DECLARE_SOA_COLUMN(NSigmaITSAlpha, nSigmaITSAlpha, float); // Number of ITS sigmas of the daughter alpha track DECLARE_SOA_COLUMN(IsSignal, isSignal, bool); // bool: true for hyperhelium4signal DECLARE_SOA_COLUMN(IsSignalReco, isSignalReco, bool); // bool: true if the signal is reconstructed @@ -71,7 +72,7 @@ DECLARE_SOA_TABLE(He4S2BCands, "AOD", "HE4S2BCANDS", he4scand::PxAlpha, he4scand::PyAlpha, he4scand::PzAlpha, he4scand::DcaMothPv, he4scand::DcaAlphaPv, he4scand::DcaKinkTopo, he4scand::ItsChi2Moth, he4scand::ItsClusterSizesMoth, he4scand::ItsClusterSizesAlpha, - he4scand::NSigmaTPCAlpha); + he4scand::NSigmaTPCAlpha, he4scand::NSigmaITSAlpha); DECLARE_SOA_TABLE(MCHe4S2BCands, "AOD", "MCHE4S2BCANDS", o2::soa::Index<>, @@ -81,7 +82,7 @@ DECLARE_SOA_TABLE(MCHe4S2BCands, "AOD", "MCHE4S2BCANDS", he4scand::PxAlpha, he4scand::PyAlpha, he4scand::PzAlpha, he4scand::DcaMothPv, he4scand::DcaAlphaPv, he4scand::DcaKinkTopo, he4scand::ItsChi2Moth, he4scand::ItsClusterSizesMoth, he4scand::ItsClusterSizesAlpha, - he4scand::NSigmaTPCAlpha, + he4scand::NSigmaTPCAlpha, he4scand::NSigmaITSAlpha, he4scand::IsSignal, he4scand::IsSignalReco, he4scand::IsCollReco, he4scand::IsSurvEvSelection, he4scand::TrueXDecVtx, he4scand::TrueYDecVtx, he4scand::TrueZDecVtx, he4scand::GenPxMoth, he4scand::GenPyMoth, he4scand::GenPzMoth, diff --git a/PWGLF/TableProducer/Nuspex/hyperhelium4sigmaRecoTask.cxx b/PWGLF/TableProducer/Nuspex/hyperhelium4sigmaRecoTask.cxx index 3215e5578d4..cb0b35d8376 100644 --- a/PWGLF/TableProducer/Nuspex/hyperhelium4sigmaRecoTask.cxx +++ b/PWGLF/TableProducer/Nuspex/hyperhelium4sigmaRecoTask.cxx @@ -242,6 +242,7 @@ struct Hyphe4sCandidate { uint32_t itsClusterSizeMoth = 0u; uint32_t itsClusterSizeDau = 0u; float nSigmaTPCDau = -999.f; + float nSigmaITSDau = -999.f; // mc information bool isSignal = false; @@ -290,6 +291,8 @@ struct Hyperhelium4sigmaRecoTask { float mBz; o2::base::MatLayerCylSet* lut = nullptr; + o2::aod::ITSResponse itsResponse; + void init(InitContext const&) { // Axes @@ -297,6 +300,8 @@ struct Hyperhelium4sigmaRecoTask { const AxisSpec ptAxis{50, -10, 10, "#it{p}_{T} (GeV/#it{c})"}; const AxisSpec nSigmaAxis{120, -6.f, 6.f, "n#sigma_{#alpha}"}; const AxisSpec massAxis{100, 3.85, 4.25, "m (GeV/#it{c}^{2})"}; + const AxisSpec diffPxAxis{200, -10.f, 10.f, "#Delta #it{p}_{x} (GeV/#it{c})"}; + const AxisSpec diffPyAxis{200, -10.f, 10.f, "#Delta #it{p}_{y} (GeV/#it{c})"}; const AxisSpec diffPtAxis{200, -10.f, 10.f, "#Delta #it{p}_{T} (GeV/#it{c})"}; const AxisSpec diffPzAxis{200, -10.f, 10.f, "#Delta #it{p}_{z} (GeV/#it{c})"}; const AxisSpec radiusAxis{40, 0.f, 40.f, "R (cm)"}; @@ -306,11 +311,15 @@ struct Hyperhelium4sigmaRecoTask { registry.add("hCandidateCounter", "hCandidateCounter", HistType::kTH1F, {{3, 0, 3}}); if (doprocessMC == true) { + itsResponse.setMCDefaultParameters(); + registry.add("hTrueCandidateCounter", "hTrueCandidateCounter", HistType::kTH1F, {{3, 0, 3}}); registry.add("hDiffSVx", ";#Delta x (cm);", HistType::kTH1F, {{200, -10, 10}}); registry.add("hDiffSVy", ";#Delta y (cm);", HistType::kTH1F, {{200, -10, 10}}); registry.add("hDiffSVz", ";#Delta z (cm);", HistType::kTH1F, {{200, -10, 10}}); registry.add("h2RecSVRVsTrueSVR", ";Reconstruced SV R (cm);True SV R (cm);", HistType::kTH2F, {radiusAxis, radiusAxis}); + registry.add("h2TrueMotherDiffPxVsRecSVR", ";Reconstruced SV R (cm);#Delta #it{p}_{T} (GeV/#it{c});", HistType::kTH2F, {radiusAxis, diffPxAxis}); + registry.add("h2TrueMotherDiffPyVsRecSVR", ";Reconstruced SV R (cm);#Delta #it{p}_{T} (GeV/#it{c});", HistType::kTH2F, {radiusAxis, diffPyAxis}); registry.add("h2TrueMotherDiffPtVsRecSVR", ";Reconstruced SV R (cm);#Delta #it{p}_{T} (GeV/#it{c});", HistType::kTH2F, {radiusAxis, diffPtAxis}); registry.add("h2TrueMotherDiffPzVsRecSVR", ";Reconstruced SV R (cm);#Delta #it{p}_{z} (GeV/#it{c});", HistType::kTH2F, {radiusAxis, diffPzAxis}); registry.add("h2TrueMotherDiffTglVsRecSVR", ";Reconstruced SV R (cm);#Delta tan#lambda;", HistType::kTH2F, {radiusAxis, {200, -1.f, 1.f}}); @@ -384,6 +393,7 @@ struct Hyperhelium4sigmaRecoTask { hyphe4sCand.itsClusterSizeDau = trackDau.itsClusterSizes(); hyphe4sCand.nSigmaTPCDau = trackDau.tpcNSigmaAl(); + hyphe4sCand.nSigmaITSDau = itsResponse.nSigmaITS(trackDau); } template @@ -449,7 +459,7 @@ struct Hyperhelium4sigmaRecoTask { hyphe4sCand.momDaug[0], hyphe4sCand.momDaug[1], hyphe4sCand.momDaug[2], hyphe4sCand.dcaXYMothPv, hyphe4sCand.dcaXYDauPv, hyphe4sCand.dcaKinkTopo, hyphe4sCand.chi2ITSMoth, hyphe4sCand.itsClusterSizeMoth, hyphe4sCand.itsClusterSizeDau, - hyphe4sCand.nSigmaTPCDau); + hyphe4sCand.nSigmaTPCDau, hyphe4sCand.nSigmaITSDau); } } PROCESS_SWITCH(Hyperhelium4sigmaRecoTask, processData, "process data", true); @@ -550,22 +560,26 @@ struct Hyperhelium4sigmaRecoTask { o2::base::Propagator::Instance()->propagateToDCABxByBz({kinkCand.xDecVtx(), kinkCand.yDecVtx(), kinkCand.zDecVtx()}, mcMotherTrackPar, 2.f, matCorr, &dcaInfo); registry.fill(HIST("hDCAXYMothToRecSV"), dcaInfo[0]); registry.fill(HIST("hDCAZMothToRecSV"), dcaInfo[1]); + std::array pMotherAtSV = {-999.f, -999.f, -999.f}; + mcMotherTrackPar.getPxPyPzGlo(pMotherAtSV); + registry.fill(HIST("h2TrueMotherDiffPxVsRecSVR"), recSVR, pMotherAtSV[0] - kinkCand.pxMoth()); + registry.fill(HIST("h2TrueMotherDiffPyVsRecSVR"), recSVR, pMotherAtSV[1] - kinkCand.pyMoth()); - float spKink = kinkCand.pxMoth() * kinkCand.pxDaug() + kinkCand.pyMoth() * kinkCand.pyDaug() + kinkCand.pzMoth() * kinkCand.pzDaug(); - float sptKink = kinkCand.pxMoth() * kinkCand.pxDaug() + kinkCand.pyMoth() * kinkCand.pyDaug(); + float spKinkXY = kinkCand.pxMoth() * kinkCand.pxDaug() + kinkCand.pyMoth() * kinkCand.pyDaug(); + float spKink = spKinkXY + kinkCand.pzMoth() * kinkCand.pzDaug(); float pMoth = std::hypot(kinkCand.pxMoth(), kinkCand.pyMoth(), kinkCand.pzMoth()); float pDaug = std::hypot(kinkCand.pxDaug(), kinkCand.pyDaug(), kinkCand.pzDaug()); - float pMothDirVector[3] = {kinkCand.xDecVtx() - collision.posX(), kinkCand.yDecVtx() - collision.posY(), kinkCand.zDecVtx() - collision.posZ()}; - float epMothDirVector = std::hypot(pMothDirVector[0], pMothDirVector[1], pMothDirVector[2]); - float eptMothDirVector = std::hypot(pMothDirVector[0], pMothDirVector[1]); - float spKinkSV = pMothDirVector[0] * kinkCand.pxDaug() + pMothDirVector[1] * kinkCand.pyDaug() + pMothDirVector[2] * kinkCand.pzDaug(); - float sptKinkSV = pMothDirVector[0] * kinkCand.pxDaug() + pMothDirVector[1] * kinkCand.pyDaug(); + float mothPDir[3] = {kinkCand.xDecVtx() - collision.posX(), kinkCand.yDecVtx() - collision.posY(), kinkCand.zDecVtx() - collision.posZ()}; + float magMothPDirXY = std::hypot(mothPDir[0], mothPDir[1]); + float magMothPDir = std::hypot(mothPDir[0], mothPDir[1], mothPDir[2]); + float spKinkSV = mothPDir[0] * kinkCand.pxDaug() + mothPDir[1] * kinkCand.pyDaug() + mothPDir[2] * kinkCand.pzDaug(); + float sptKinkSV = mothPDir[0] * kinkCand.pxDaug() + mothPDir[1] * kinkCand.pyDaug(); float kinkAngle = spKink / (pMoth * pDaug); - float kinkAngleSV = spKinkSV / (epMothDirVector * pDaug); - float kinkAngleXY = sptKink / (kinkCand.ptMoth() * kinkCand.ptDaug()); - float kinkAngleXYSV = sptKinkSV / (eptMothDirVector * kinkCand.ptDaug()); + float kinkAngleSV = spKinkSV / (magMothPDir * pDaug); + float kinkAngleXY = spKinkXY / (kinkCand.ptMoth() * kinkCand.ptDaug()); + float kinkAngleXYSV = sptKinkSV / (magMothPDirXY * kinkCand.ptDaug()); registry.fill(HIST("h2TrueMotherDiffPtVsKinkAngle"), kinkAngle, (mcMotherTrack.pt() - kinkCand.ptMoth()) / kinkCand.ptMoth()); registry.fill(HIST("h2TrueMotherDiffPtVsKinkAngleSV"), kinkAngleSV, (mcMotherTrack.pt() - kinkCand.ptMoth()) / kinkCand.ptMoth()); @@ -580,7 +594,7 @@ struct Hyperhelium4sigmaRecoTask { hyphe4sCand.momDaug[0], hyphe4sCand.momDaug[1], hyphe4sCand.momDaug[2], hyphe4sCand.dcaXYMothPv, hyphe4sCand.dcaXYDauPv, hyphe4sCand.dcaKinkTopo, hyphe4sCand.chi2ITSMoth, hyphe4sCand.itsClusterSizeMoth, hyphe4sCand.itsClusterSizeDau, - hyphe4sCand.nSigmaTPCDau, + hyphe4sCand.nSigmaTPCDau, hyphe4sCand.nSigmaITSDau, hyphe4sCand.isSignal, hyphe4sCand.isSignalReco, hyphe4sCand.isCollReco, hyphe4sCand.isSurvEvSelection, hyphe4sCand.trueDecVtx[0], hyphe4sCand.trueDecVtx[1], hyphe4sCand.trueDecVtx[2], hyphe4sCand.gMomMoth[0], hyphe4sCand.gMomMoth[1], hyphe4sCand.gMomMoth[2], @@ -614,7 +628,7 @@ struct Hyperhelium4sigmaRecoTask { -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, + -1, -1, true, false, isReconstructedMCCollisions[mcparticle.mcCollisionId()], isSelectedMCCollisions[mcparticle.mcCollisionId()], hyphe4sCand.trueDecVtx[0], hyphe4sCand.trueDecVtx[1], hyphe4sCand.trueDecVtx[2], hyphe4sCand.gMomMoth[0], hyphe4sCand.gMomMoth[1], hyphe4sCand.gMomMoth[2], @@ -651,6 +665,7 @@ struct Hyperhelium4sigmaQa { const AxisSpec ctAxis{ctBins, "c#it{t} (cm)"}; const AxisSpec rigidityAxis{rigidityBins, "p/z (GeV/#it{c})"}; const AxisSpec nsigmaAxis{nsigmaBins, "TPC n#sigma"}; + const AxisSpec itsnsigmaAxis{nsigmaBins, "ITS n#sigma"}; const AxisSpec invMassAxis{invMassBins, "Inv Mass (GeV/#it{c}^{2})"}; const AxisSpec diffPtAxis{200, -10.f, 10.f, "#Delta p_{T} (GeV/#it{c})"}; const AxisSpec diffPzAxis{200, -10.f, 10.f, "#Delta p_{z} (GeV/#it{c})"}; @@ -731,9 +746,11 @@ struct Hyperhelium4sigmaQa { } recoQAHist.add("hMotherIsPVContributer", "", HistType::kTH1F, {{2, 0.f, 2.f}}); + recoQAHist.add("hMotherITSCls", "", HistType::kTH1F, {{8, 0.f, 8.f}}); recoQAHist.add("hDauAlphaIsPVContributer", "", HistType::kTH1F, {{2, 0.f, 2.f}}); - recoQAHist.add("hDauAlphaPVsITSNSigma", "", HistType::kTH2F, {pAxis, nsigmaAxis}); - recoQAHist.add("h2BCandDauAlphaPVsITSNSigma", "", HistType::kTH2F, {pAxis, nsigmaAxis}); + recoQAHist.add("hDauAlphaITSCls", "", HistType::kTH1F, {{8, 0.f, 8.f}}); + recoQAHist.add("hDauAlphaPVsITSNSigma", "", HistType::kTH2F, {rigidityAxis, itsnsigmaAxis}); + recoQAHist.add("h2BCandDauAlphaPVsITSNSigma", "", HistType::kTH2F, {rigidityAxis, nsigmaAxis}); recoQAHist.add("hReco2BCandidateCount", "", HistType::kTH1F, {{4, 0.f, 4.f}}); } } @@ -975,12 +992,14 @@ struct Hyperhelium4sigmaQa { recoQAHist.fill(HIST("hReco2BCandidateCount"), 0.5); recoQAHist.fill(HIST("hRecoMotherCounter"), 0.5); + recoQAHist.fill(HIST("hMotherITSCls"), motherTrack.itsNCls()); recoQAHist.fill(HIST("hRecoDauAlphaCounter"), 0.5); recoQAHist.fill(HIST("hMotherIsPVContributer"), motherTrack.isPVContributor() ? 1.5 : 0.5); recoQAHist.fill(HIST("hDauAlphaIsPVContributer"), daughterTrack.isPVContributor() ? 1.5 : 0.5); - float itsNSigma = itsResponse.nSigmaITS(daughterTrack.itsClusterSizes(), 2 * daughterTrack.p(), daughterTrack.eta()); - recoQAHist.fill(HIST("hDauAlphaPVsITSNSigma"), 2 * daughterTrack.p(), itsNSigma); + float itsNSigma = itsResponse.nSigmaITS(daughterTrack); + recoQAHist.fill(HIST("hDauAlphaPVsITSNSigma"), daughterTrack.sign() * daughterTrack.p(), itsNSigma); + recoQAHist.fill(HIST("hDauAlphaITSCls"), daughterTrack.itsNCls()); if (motherTrack.has_collision() && daughterTrack.has_collision()) { recoQAHist.fill(HIST("hReco2BCandidateCount"), 1.5); @@ -991,7 +1010,7 @@ struct Hyperhelium4sigmaQa { if (isMoth && isDaug) { recoQAHist.fill(HIST("hReco2BCandidateCount"), 3.5); - recoQAHist.fill(HIST("h2BCandDauAlphaPVsITSNSigma"), 2 * daughterTrack.p(), itsNSigma); + recoQAHist.fill(HIST("h2BCandDauAlphaPVsITSNSigma"), daughterTrack.sign() * daughterTrack.p(), itsNSigma); } } } From 5ba4d37c7f48424068d353df00c72b9ea9dd23ab Mon Sep 17 00:00:00 2001 From: sawan <124118453+sawankumawat@users.noreply.github.com> Date: Mon, 23 Jun 2025 14:42:08 +0530 Subject: [PATCH 184/871] [PWGLF] Minor correction in histogram axes (#11721) Co-authored-by: Sawan Sawan --- PWGLF/Tasks/Resonances/higherMassResonances.cxx | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/PWGLF/Tasks/Resonances/higherMassResonances.cxx b/PWGLF/Tasks/Resonances/higherMassResonances.cxx index edb1c0dae08..e9f40c66f05 100644 --- a/PWGLF/Tasks/Resonances/higherMassResonances.cxx +++ b/PWGLF/Tasks/Resonances/higherMassResonances.cxx @@ -163,7 +163,7 @@ struct HigherMassResonances { ConfigurableAxis configThnAxisPOL{"configThnAxisPOL", {20, -1.0, 1.0}, "Costheta axis"}; ConfigurableAxis configThnAxisPhi{"configThnAxisPhi", {70, 0.0f, 7.0f}, "Phi axis"}; // 0 to 2pi ConfigurableAxis ksMassBins{"ksMassBins", {200, 0.45f, 0.55f}, "K0s invariant mass axis"}; - ConfigurableAxis cMassBins{"cMassBins", {200, 0.9f, 3.0f}, "Glueball 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"}; // ConfigurableAxis axisdEdx{"axisdEdx", {20000, 0.0f, 200.0f}, "dE/dx (a.u.)"}; // ConfigurableAxis axisPtfordEbydx{"axisPtfordEbydx", {2000, 0, 20}, "pT (GeV/c)"}; @@ -193,7 +193,7 @@ struct HigherMassResonances { // Axes AxisSpec k0ShortMassAxis = {config.ksMassBins, "#it{M}_{inv} [GeV/#it{c}^{2}]"}; - AxisSpec glueballMassAxis = {config.ksMassBins, "#it{M}_{inv} [GeV/#it{c}^{2}]"}; + AxisSpec glueballMassAxis = {config.cGlueMassBins, "#it{M}_{inv} [GeV/#it{c}^{2}]"}; AxisSpec vertexZAxis = {60, -15.f, 15.f, "vrtx_{Z} [cm]"}; // for histogram AxisSpec ptAxis = {config.cPtBins, "#it{p}_{T} (GeV/#it{c})"}; AxisSpec multiplicityAxis = {config.binsCent, "Multiplicity Axis"}; @@ -559,7 +559,9 @@ struct HigherMassResonances { phi2 = candidate2.phi(); double angle = std::sqrt(std::pow(eta1 - eta2, 2) + std::pow(phi1 - phi2, 2)); - rKzeroShort.fill(HIST("angularSeparation"), angle); + if (config.qAv0) { + rKzeroShort.fill(HIST("angularSeparation"), angle); + } if (config.applyAngSepCut && angle > config.angSepCut) { return false; } From e0b6647689008612e2b37afdfbeee78b96161c5d Mon Sep 17 00:00:00 2001 From: yuanzhe <90246048+wang-yuanzhe@users.noreply.github.com> Date: Mon, 23 Jun 2025 11:17:50 +0200 Subject: [PATCH 185/871] [PWGLF] Enable event selection based on trigger and add like-sign analysis (#11659) Co-authored-by: ALICE Action Bot --- PWGLF/DataModel/Reduced3BodyTables.h | 1 + .../Nuspex/decay3bodybuilder.cxx | 107 ++++++++++-------- .../Nuspex/reduced3bodyCreator.cxx | 100 ++++++++-------- PWGLF/Utils/decay3bodyBuilderHelper.h | 19 +++- 4 files changed, 123 insertions(+), 104 deletions(-) diff --git a/PWGLF/DataModel/Reduced3BodyTables.h b/PWGLF/DataModel/Reduced3BodyTables.h index aeabfb92c0b..3b221d17539 100644 --- a/PWGLF/DataModel/Reduced3BodyTables.h +++ b/PWGLF/DataModel/Reduced3BodyTables.h @@ -86,6 +86,7 @@ DECLARE_SOA_TABLE_FULL(StoredRedIUTracks, "RedIUTracks", "AOD", "REDIUTRACK", // track::HasITS, track::HasTPC, track::HasTOF, + track::HasTRD, track::TPCNClsFound, track::TPCNClsCrossedRows, track::v001::ITSClsSizeInLayer, diff --git a/PWGLF/TableProducer/Nuspex/decay3bodybuilder.cxx b/PWGLF/TableProducer/Nuspex/decay3bodybuilder.cxx index 77c3e5668a7..e7ddcd7b471 100644 --- a/PWGLF/TableProducer/Nuspex/decay3bodybuilder.cxx +++ b/PWGLF/TableProducer/Nuspex/decay3bodybuilder.cxx @@ -8,7 +8,6 @@ // 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 decay3bodybuilder.cxx /// \brief Builder task for 3-body hypertriton decay reconstruction (proton + pion + deuteron) @@ -16,49 +15,50 @@ /// \author Carolina Reetz // ======================== -#include -#include -#include -#include -#include -#include -#include -#include +#include "TableHelper.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.h" -#include "ReconstructionDataFormats/Track.h" -#include "Common/Core/RecoDecay.h" -#include "Common/Core/trackUtilities.h" #include "PWGLF/DataModel/Reduced3BodyTables.h" #include "PWGLF/DataModel/Vtx3BodyTables.h" #include "PWGLF/DataModel/pidTOFGeneric.h" #include "PWGLF/Utils/decay3bodyBuilderHelper.h" + +#include "Common/Core/PID/PIDTOF.h" +#include "Common/Core/RecoDecay.h" +#include "Common/Core/trackUtilities.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/PIDResponse.h" -#include "Common/Core/PID/PIDTOF.h" -#include "TableHelper.h" -#include "Tools/KFparticle/KFUtilities.h" - #include "EventFiltering/Zorro.h" #include "EventFiltering/ZorroSummary.h" +#include "Tools/KFparticle/KFUtilities.h" -#include "DetectorsBase/Propagator.h" -#include "DetectorsBase/GeometryManager.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DataFormatsParameters/GRPMagField.h" #include "CCDB/BasicCCDBManager.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "DataFormatsParameters/GRPObject.h" +#include "DetectorsBase/GeometryManager.h" +#include "DetectorsBase/Propagator.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" +#include "ReconstructionDataFormats/Track.h" + +#include +#include +#include +#include +#include +#include +#include +#include #ifndef HomogeneousField #define HomogeneousField #endif // includes KFParticle -#include "KFParticle.h" #include "KFPTrack.h" #include "KFPVertex.h" +#include "KFParticle.h" #include "KFParticleBase.h" #include "KFVertex.h" @@ -125,6 +125,7 @@ struct decay3bodyBuilder { Configurable doSkimmedProcessing{"doSkimmedProcessing", false, "Apply Zoroo counting in case of skimmed data input"}; Configurable triggerList{"triggerList", "fTriggerEventF1Proton, fTrackedOmega, fTrackedXi, fOmegaLargeRadius, fDoubleOmega, fOmegaHighMult, fSingleXiYN, fQuadrupleXi, fDoubleXi, fhadronOmega, fOmegaXi, fTripleXi, fOmega, fGammaVeryLowPtEMCAL, fGammaVeryLowPtDCAL, fGammaHighPtEMCAL, fGammaLowPtEMCAL, fGammaVeryHighPtDCAL, fGammaVeryHighPtEMCAL, fGammaLowPtDCAL, fJetNeutralLowPt, fJetNeutralHighPt, fGammaHighPtDCAL, fJetFullLowPt, fJetFullHighPt, fEMCALReadout, fPCMandEE, fPHOSnbar, fPCMHighPtPhoton, fPHOSPhoton, fLD, fPPPHI, fPD, fLLL, fPLL, fPPL, fPPP, fLeadingPtTrack, fHighFt0cFv0Flat, fHighFt0cFv0Mult, fHighFt0Flat, fHighFt0Mult, fHighMultFv0, fHighTrackMult, fHfSingleNonPromptCharm3P, fHfSingleNonPromptCharm2P, fHfSingleCharm3P, fHfPhotonCharm3P, fHfHighPt2P, fHfSigmaC0K0, fHfDoubleCharm2P, fHfBeauty3P, fHfFemto3P, fHfFemto2P, fHfHighPt3P, fHfSigmaCPPK, fHfDoubleCharm3P, fHfDoubleCharmMix, fHfPhotonCharm2P, fHfV0Charm2P, fHfBeauty4P, fHfV0Charm3P, fHfSingleCharm2P, fHfCharmBarToXiBach, fSingleMuHigh, fSingleMuLow, fLMeeHMR, fDiMuon, fDiElectron, fLMeeIMR, fSingleE, fTrackHighPt, fTrackLowPt, fJetChHighPt, fJetChLowPt, fUDdiffLarge, fUDdiffSmall, fITSextremeIonisation, fITSmildIonisation, fH3L3Body, fHe, fH2", "List of triggers used to select events"}; Configurable onlyKeepInterestedTrigger{"onlyKeepInterestedTrigger", false, "Flag to keep only interested trigger"}; + Configurable doLikeSign{"doLikeSign", false, "Flag to produce like-sign background. If true, require the sign of pion is as same as deuteron but not proton."}; // CCDB options struct : ConfigurableGroup { @@ -145,6 +146,7 @@ struct decay3bodyBuilder { Configurable useSelections{"useSelections", true, "Apply selections during decay3body building"}; Configurable useTPCforPion{"useTPCforPion", false, "Flag to ask for TPC info for pion track (PID, nClusters), false: pion track can be ITS only"}; Configurable acceptTPCOnly{"acceptTPCOnly", false, "Accept TPC only tracks as daughters"}; + Configurable askOnlyITSMatch{"askOnlyITSMatch", true, "ask only ITS match to distinguish TPC only tracks"}; Configurable calculateCovariance{"calculateCovariance", true, "Calculate candidate and daughter covariance matrices"}; // daughter track selections Configurable maxEtaDaughters{"maxEtaDaughters", 0.9, "Max eta of daughters"}; @@ -182,7 +184,7 @@ struct decay3bodyBuilder { Configurable n3bodyMixing{"n3bodyMixing", 0, "Number of decay3bodys to mix: 0 - value set to maximum bin entry in hDecay3BodyRadiusPhi, > 0 - manual setting"}; Configurable mixingType{"mixingType", 0, "0: mix V0 from one event with bachelor from another, 1: mix pion and bachelor from one event with proton from another, 1: mix proton and bachelor from one event with pion from another "}; ConfigurableAxis bins3BodyRadius{"mixingOpts.bins3BodyRadius", {VARIABLE_WIDTH, 0.0f, 2.0f, 4.0f, 7.0f, 10.0f, 14.0f, 18.0f, 22.0f, 30.0f, 40.0f}, "Mixing bins - 3body radius"}; - ConfigurableAxis bins3BodyPhi{"mixingOpts.bins3BodyPhi", {VARIABLE_WIDTH, -180 * TMath::Pi() / 180, -120 * TMath::Pi() / 180, -60 * TMath::Pi() / 180, 0, 60 * TMath::Pi() / 180, 120 * TMath::Pi() / 180, 180 * TMath::Pi() / 180}, "Mixing bins - 3body phi (rad)"}; + ConfigurableAxis bins3BodyPhi{"mixingOpts.bins3BodyPhi", {VARIABLE_WIDTH, -180 * o2::constants::math::Deg2Rad, -120 * o2::constants::math::Deg2Rad, -60 * o2::constants::math::Deg2Rad, 0, 60 * o2::constants::math::Deg2Rad, 120 * o2::constants::math::Deg2Rad, 180 * o2::constants::math::Deg2Rad}, "Mixing bins - 3body phi (rad)"}; ConfigurableAxis bins3BodyPhiDegree{"mixingOpts.bins3BodyPhiDegree", {VARIABLE_WIDTH, -180, -120, -60, 0, 60, 120, 180}, "Mixing bins - 3body phi (degree)"}; ConfigurableAxis bins3BodyPosZ{"mixingOpts.bins3BodyPosZ", {VARIABLE_WIDTH, -500.0f, -200.0f, -100.0f, -70.0f, -60.0f, -50.0f, -40.0f, -35.0f, -30.0f, -25.0f, -20.0f, -15.0f, -13.0f, -10.0f, -8.0f, -6.0f, -4.0f, -2.0f, 0.0f, 2.0f, 4.0f, 6.0f, 8.0f, 10.0f, 13.0f, 15.0f, 20.0f, 25.0f, 30.0f, 35.0f, 40.0f, 50.0f, 60.0f, 70.0f, 100.0f, 200.0f, 500.0f}, "3body SV z position"}; Configurable selectPVPosZ3bodyMixing{"selectPVPosZ3bodyMixing", true, "Select same pvPosZ events in case of 3body mixing"}; @@ -264,6 +266,8 @@ struct decay3bodyBuilder { // tracked cluster size std::vector fTrackedClSizeVector; + // trigger info + std::vector isTriggeredCollision; // MC info std::vector isGoodCollision; @@ -652,8 +656,14 @@ struct decay3bodyBuilder { // prepare MC container (not necessarily used) std::vector mcParticleIsReco; + if constexpr (soa::is_table) { + isTriggeredCollision.clear(); + isTriggeredCollision.resize(collisions.size(), false); + } // clear and reserve size for MC info vectors if constexpr (soa::is_table) { + isGoodCollision.clear(); + mcParticleIsReco.clear(); isGoodCollision.resize(mcCollisions.size(), false); mcParticleIsReco.resize(mcParticles.size(), false); } @@ -670,6 +680,7 @@ struct decay3bodyBuilder { } } + isTriggeredCollision[collision.globalIndex()] = true; // event counting registry.fill(HIST("Counters/hEventCounter"), 0.5); if (doSel8selection && !collision.sel8()) { @@ -711,7 +722,7 @@ struct decay3bodyBuilder { // skip decay3body without assigned collision /// TODO: do we want this?? if (decay3body.collisionId() < 0) { - return; + continue; } // aquire collision @@ -727,8 +738,11 @@ struct decay3bodyBuilder { } // event selection - if constexpr (soa::is_table) { - if (doSel8selection && !collision.sel8()) { // only when NOT running over reduced data + if constexpr (soa::is_table) { // only when NOT running over reduced data + if (doSel8selection && !collision.sel8()) { + continue; + } + if (onlyKeepInterestedTrigger && !isTriggeredCollision[collision.globalIndex()]) { continue; } } @@ -740,12 +754,9 @@ struct decay3bodyBuilder { auto trackPos = decay3body.template track0_as(); auto trackNeg = decay3body.template track1_as(); auto trackDeuteron = decay3body.template track2_as(); - auto trackProton = trackPos; - auto trackPion = trackNeg; - if (trackDeuteron.sign() < 0) { - trackProton = trackNeg; - trackPion = trackPos; - } + int protonSign = doLikeSign ? -trackDeuteron.sign() : trackDeuteron.sign(); + auto trackProton = protonSign > 0 ? trackPos : trackNeg; + auto trackPion = protonSign > 0 ? trackNeg : trackPos; // get deuteron TOF PID float tofNSigmaDeuteron; @@ -772,6 +783,7 @@ struct decay3bodyBuilder { decay3bodyBuilderOpts.useSelections, decay3bodyBuilderOpts.useTPCforPion, decay3bodyBuilderOpts.acceptTPCOnly, + decay3bodyBuilderOpts.askOnlyITSMatch, decay3bodyBuilderOpts.calculateCovariance, false /*isEventMixing*/)) { continue; @@ -863,7 +875,7 @@ struct decay3bodyBuilder { // MC handling part: generated information of non-reco candidates // ____________________________________________________________________ if constexpr (soa::is_table) { - for (auto& mcparticle : mcParticles) { + for (const auto& mcparticle : mcParticles) { // MC info resetMCInfo(this3BodyMCInfo); this3BodyMCInfo.isReco = false; @@ -877,14 +889,14 @@ struct decay3bodyBuilder { this3BodyMCInfo.survivedEventSel = isGoodCollision[mcparticle.mcCollisionId()]; // check if MC particle is hypertriton - if (std::abs(mcparticle.pdgCode()) != 1010010030) { + if (std::abs(mcparticle.pdgCode()) != o2::constants::physics::Pdg::kHyperTriton) { continue; } // check daughter identities bool haveProton = false, havePion = false, haveDeuteron = false; bool haveAntiProton = false, haveAntiPion = false, haveAntiDeuteron = false; - for (auto& mcparticleDaughter : mcparticle.template daughters_as()) { + for (const auto& mcparticleDaughter : mcparticle.template daughters_as()) { if (mcparticleDaughter.pdgCode() == PDG_t::kProton) haveProton = true; if (mcparticleDaughter.pdgCode() == PDG_t::kProtonBar) @@ -893,9 +905,9 @@ struct decay3bodyBuilder { havePion = true; if (mcparticleDaughter.pdgCode() == PDG_t::kPiMinus) haveAntiPion = true; - if (mcparticleDaughter.pdgCode() == 1000010020) + if (mcparticleDaughter.pdgCode() == o2::constants::physics::Pdg::kDeuteron) haveDeuteron = true; - if (mcparticleDaughter.pdgCode() == -1000010020) + if (mcparticleDaughter.pdgCode() == -o2::constants::physics::Pdg::kDeuteron) haveAntiDeuteron = true; } @@ -907,7 +919,7 @@ struct decay3bodyBuilder { this3BodyMCInfo.isTrueAntiH3L = true; } // get daughters - for (auto& mcparticleDaughter : mcparticle.template daughters_as()) { + for (const auto& mcparticleDaughter : mcparticle.template daughters_as()) { if (std::abs(mcparticleDaughter.pdgCode()) == PDG_t::kProton) { // proton this3BodyMCInfo.genMomProton = mcparticleDaughter.p(); this3BodyMCInfo.genPtProton = mcparticleDaughter.pt(); @@ -917,7 +929,7 @@ struct decay3bodyBuilder { this3BodyMCInfo.genMomPion = mcparticleDaughter.p(); this3BodyMCInfo.genPtPion = mcparticleDaughter.pt(); this3BodyMCInfo.daughterPiPdgCode = mcparticleDaughter.pdgCode(); - } else if (std::abs(mcparticleDaughter.pdgCode()) == 1000010020) { // deuteron + } else if (std::abs(mcparticleDaughter.pdgCode()) == o2::constants::physics::Pdg::kDeuteron) { // deuteron this3BodyMCInfo.genMomDeuteron = mcparticleDaughter.p(); this3BodyMCInfo.genPtDeuteron = mcparticleDaughter.pt(); this3BodyMCInfo.daughterDePdgCode = mcparticleDaughter.pdgCode(); @@ -1168,6 +1180,7 @@ struct decay3bodyBuilder { decay3bodyBuilderOpts.useSelections, decay3bodyBuilderOpts.useTPCforPion, decay3bodyBuilderOpts.acceptTPCOnly, + decay3bodyBuilderOpts.askOnlyITSMatch, decay3bodyBuilderOpts.calculateCovariance, true /*isEventMixing*/)) { // fill analysis tables with built candidate @@ -1183,14 +1196,14 @@ struct decay3bodyBuilder { template int checkH3LTruth(MCTrack3B const& mcParticlePr, MCTrack3B const& mcParticlePi, MCTrack3B const& mcParticleDe, bool& isMuonReco) { - if (std::abs(mcParticlePr.pdgCode()) != 2212 || std::abs(mcParticleDe.pdgCode()) != 1000010020) { + if (std::abs(mcParticlePr.pdgCode()) != PDG_t::kProton || std::abs(mcParticleDe.pdgCode()) != o2::constants::physics::Pdg::kDeuteron) { return -1; } // check proton and deuteron mother int prDeMomID = -1; for (const auto& motherPr : mcParticlePr.template mothers_as()) { for (const auto& motherDe : mcParticleDe.template mothers_as()) { - if (motherPr.globalIndex() == motherDe.globalIndex() && std::abs(motherPr.pdgCode()) == 1010010030) { + if (motherPr.globalIndex() == motherDe.globalIndex() && std::abs(motherPr.pdgCode()) == o2::constants::physics::Pdg::kHyperTriton) { prDeMomID = motherPr.globalIndex(); break; } @@ -1199,14 +1212,14 @@ struct decay3bodyBuilder { if (prDeMomID == -1) { return -1; } - if (std::abs(mcParticlePi.pdgCode()) != 211 && std::abs(mcParticlePi.pdgCode()) != 13) { + if (std::abs(mcParticlePi.pdgCode()) != PDG_t::kPiPlus && std::abs(mcParticlePi.pdgCode()) != PDG_t::kMuonMinus) { return -1; } // check if the pion track is a muon coming from a pi -> mu + vu decay, if yes, take the mother pi auto mcParticlePiTmp = mcParticlePi; - if (std::abs(mcParticlePiTmp.pdgCode()) == 13) { + if (std::abs(mcParticlePiTmp.pdgCode()) == PDG_t::kMuonMinus) { for (const auto& motherPi : mcParticlePiTmp.template mothers_as()) { - if (std::abs(motherPi.pdgCode()) == 211) { + if (std::abs(motherPi.pdgCode()) == PDG_t::kPiPlus) { mcParticlePiTmp = motherPi; isMuonReco = true; break; diff --git a/PWGLF/TableProducer/Nuspex/reduced3bodyCreator.cxx b/PWGLF/TableProducer/Nuspex/reduced3bodyCreator.cxx index 4f52fdd8066..091f0b03580 100644 --- a/PWGLF/TableProducer/Nuspex/reduced3bodyCreator.cxx +++ b/PWGLF/TableProducer/Nuspex/reduced3bodyCreator.cxx @@ -14,48 +14,49 @@ /// \author Yuanzhe Wang /// \author Carolina Reetz -#include -#include -#include -#include -#include -#include +#include "TableHelper.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.h" -#include "DCAFitter/DCAFitterN.h" -#include "ReconstructionDataFormats/Track.h" +#include "PWGLF/DataModel/Reduced3BodyTables.h" +#include "PWGLF/DataModel/pidTOFGeneric.h" + +#include "Common/Core/PID/PIDTOF.h" +#include "Common/Core/RecoDecay.h" #include "Common/Core/trackUtilities.h" -#include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/Centrality.h" -#include "PWGLF/DataModel/pidTOFGeneric.h" -#include "PWGLF/DataModel/Reduced3BodyTables.h" #include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/PIDResponse.h" -#include "Common/Core/PID/PIDTOF.h" -#include "Common/Core/RecoDecay.h" -#include "TableHelper.h" -#include "Tools/KFparticle/KFUtilities.h" - #include "EventFiltering/Zorro.h" #include "EventFiltering/ZorroSummary.h" +#include "Tools/KFparticle/KFUtilities.h" -#include "DetectorsBase/Propagator.h" -#include "DetectorsBase/GeometryManager.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DataFormatsParameters/GRPMagField.h" #include "CCDB/BasicCCDBManager.h" +#include "DCAFitter/DCAFitterN.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "DataFormatsParameters/GRPObject.h" +#include "DetectorsBase/GeometryManager.h" +#include "DetectorsBase/Propagator.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" +#include "ReconstructionDataFormats/Track.h" + +#include +#include +#include +#include +#include +#include #ifndef HomogeneousField #define HomogeneousField #endif // includes KFParticle -#include "KFParticle.h" #include "KFPTrack.h" #include "KFPVertex.h" +#include "KFParticle.h" #include "KFParticleBase.h" #include "KFVertex.h" @@ -87,8 +88,8 @@ struct reduced3bodyCreator { o2::vertexing::DCAFitterN<3> fitter3body; o2::aod::pidtofgeneric::TofPidNewCollision bachelorTOFPID; - Configurable event_sel8_selection{"event_sel8_selection", true, "event selection count post sel8 cut"}; - Configurable event_posZ_selection{"event_posZ_selection", true, "event selection count post poZ cut"}; + Configurable doSel8selection{"doSel8selection", true, "flag for sel8 event selection"}; + Configurable doPosZselection{"doPosZselection", true, "flag for posZ event selection"}; // CCDB options 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"}; @@ -110,7 +111,7 @@ struct reduced3bodyCreator { Configurable cfgMaterialCorrection{"cfgMaterialCorrection", static_cast(o2::base::Propagator::MatCorrType::USEMatCorrNONE), "Type of material correction for DCAFitter"}; int mRunNumber; - float d_bz; + float mBz; o2::pid::tof::TOFResoParamsV2 mRespParamsV2; // tracked cluster size @@ -171,27 +172,18 @@ struct reduced3bodyCreator { // In case override, don't proceed, please - no CCDB access required auto run3grp_timestamp = bc.timestamp(); - o2::parameters::GRPObject* grpo = ccdb->getForTimeStamp(grpPath, run3grp_timestamp); - o2::parameters::GRPMagField* grpmag = 0x0; - if (grpo) { - o2::base::Propagator::initFieldFromGRP(grpo); - // 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(grpmagPath, run3grp_timestamp); - if (!grpmag) { - LOG(fatal) << "Got nullptr from CCDB for path " << grpmagPath << " of object GRPMagField and " << grpPath << " of object GRPObject for timestamp " << run3grp_timestamp; - } - o2::base::Propagator::initFieldFromGRP(grpmag); - // Fetch magnetic field from ccdb for current collision - // d_bz = std::lround(5.f * grpmag->getL3Current() / 30000.f); - d_bz = o2::base::Propagator::Instance()->getNominalBz(); - LOG(info) << "Retrieved GRP for timestamp " << run3grp_timestamp << " with magnetic field of " << d_bz << " kZG"; + o2::parameters::GRPMagField* grpmag = ccdb->getForTimeStamp(grpmagPath, run3grp_timestamp); + if (!grpmag) { + LOG(fatal) << "Got nullptr from CCDB for path " << grpmagPath << " of object GRPMagField and " << grpPath << " of object GRPObject for timestamp " << run3grp_timestamp; } + o2::base::Propagator::initFieldFromGRP(grpmag); + // Fetch magnetic field from ccdb for current collision + // mBz = std::lround(5.f * grpmag->getL3Current() / 30000.f); + mBz = o2::base::Propagator::Instance()->getNominalBz(); + LOG(info) << "Retrieved GRP for timestamp " << run3grp_timestamp << " with magnetic field of " << mBz << " kZG"; // Set magnetic field for KF vertexing #ifdef HomogeneousField - KFParticle::SetField(d_bz); + KFParticle::SetField(mBz); #endif // Initial TOF PID Paras, copied from PIDTOF.h @@ -252,7 +244,7 @@ struct reduced3bodyCreator { } } - fitter3body.setBz(d_bz); + fitter3body.setBz(mBz); bachelorTOFPID.SetParams(mRespParamsV2); } @@ -302,7 +294,7 @@ struct reduced3bodyCreator { void process(ColwithEvTimesMultsCents const& collisions, TrackExtPIDIUwithEvTimes const&, aod::Decay3Bodys const& decay3bodys, aod::Tracked3Bodys const& tracked3bodys, aod::BCsWithTimestamps const&) { - std::vector triggeredCollisions(collisions.size(), false); + std::vector isTriggeredCollision(collisions.size(), false); int lastRunNumber = -1; // RunNumber of last collision, used for zorro counting // Event counting @@ -320,17 +312,17 @@ struct reduced3bodyCreator { isZorroSelected = zorro.isSelected(bc.globalBC()); if (isZorroSelected) { registry.fill(HIST("hEventCounterZorro"), 0.5); - triggeredCollisions[collision.globalIndex()] = true; + isTriggeredCollision[collision.globalIndex()] = true; } } // Event selection registry.fill(HIST("hEventCounter"), 0.5); - if (event_sel8_selection && !collision.sel8()) { + if (doSel8selection && !collision.sel8()) { continue; } registry.fill(HIST("hEventCounter"), 1.5); - if (event_posZ_selection && (collision.posZ() >= 10.0f || collision.posZ() <= -10.0f)) { // 10cm + if (doPosZselection && (collision.posZ() >= 10.0f || collision.posZ() <= -10.0f)) { // 10cm continue; } registry.fill(HIST("hEventCounter"), 2.5); @@ -355,17 +347,17 @@ struct reduced3bodyCreator { auto collision = d3body.template collision_as(); - if (event_sel8_selection && !collision.sel8()) { + if (doSel8selection && !collision.sel8()) { continue; } - if (event_posZ_selection && (collision.posZ() >= 10.0f || collision.posZ() <= -10.0f)) { // 10cm + if (doPosZselection && (collision.posZ() >= 10.0f || collision.posZ() <= -10.0f)) { // 10cm continue; } auto bc = collision.bc_as(); initCCDB(bc); if (cfgSkimmedProcessing && cfgOnlyKeepInterestedTrigger) { - if (triggeredCollisions[collision.globalIndex()] == false) { + if (isTriggeredCollision[collision.globalIndex()] == false) { continue; } } diff --git a/PWGLF/Utils/decay3bodyBuilderHelper.h b/PWGLF/Utils/decay3bodyBuilderHelper.h index 550625f2fc6..03a5b98aa08 100644 --- a/PWGLF/Utils/decay3bodyBuilderHelper.h +++ b/PWGLF/Utils/decay3bodyBuilderHelper.h @@ -186,6 +186,7 @@ class decay3bodyBuilderHelper bool useSelections = true, bool useTPCforPion = false, bool acceptTPCOnly = false, + bool askOnlyITSMatch = true, bool calculateCovariance = true, bool isEventMixing = false) { @@ -240,9 +241,21 @@ class decay3bodyBuilderHelper } // TPC only - if (!acceptTPCOnly && (!trackProton.hasITS() || !trackPion.hasITS() || !trackDeuteron.hasITS())) { - decay3body = {}; - return false; + if (!acceptTPCOnly) { + if (askOnlyITSMatch) { + if (!trackProton.hasITS() || !trackPion.hasITS() || !trackDeuteron.hasITS()) { + decay3body = {}; + return false; + } + } else { + bool isProtonTPCOnly = !trackProton.hasITS() && !trackProton.hasTOF() && !trackProton.hasTRD(); + bool isPionTPCOnly = !trackPion.hasITS() && !trackPion.hasTOF() && !trackPion.hasTRD(); + bool isDeuteronTPCOnly = !trackDeuteron.hasITS() && !trackDeuteron.hasTOF() && !trackDeuteron.hasTRD(); + if (isProtonTPCOnly || isPionTPCOnly || isDeuteronTPCOnly) { + decay3body = {}; + return false; + } + } } // daughter TPC PID From 3363702d9808751ebb8397359b3991504390f48b Mon Sep 17 00:00:00 2001 From: Bhagyarathi Sahoo Date: Mon, 23 Jun 2025 16:41:57 +0530 Subject: [PATCH 186/871] [PWGDQ] Optimize the histograms to avoid memory issue (#11730) --- PWGDQ/Core/HistogramsLibrary.cxx | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/PWGDQ/Core/HistogramsLibrary.cxx b/PWGDQ/Core/HistogramsLibrary.cxx index a375775f796..bfd83ec9a53 100644 --- a/PWGDQ/Core/HistogramsLibrary.cxx +++ b/PWGDQ/Core/HistogramsLibrary.cxx @@ -1232,39 +1232,24 @@ void o2::aod::dqhistograms::DefineHistograms(HistogramManager* hm, const char* h } if (subGroupStr.Contains("dimuon-polarization-he")) { int varspTHE[4] = {VarManager::kMass, VarManager::kPt, VarManager::kCosThetaHE, VarManager::kPhiHE}; - int varsrapHE[4] = {VarManager::kMass, VarManager::kRap, VarManager::kCosThetaHE, VarManager::kPhiHE}; int binspT[4] = {100, 40, 20, 20}; - int binsy[4] = {100, 10, 20, 20}; double xminpT[4] = {1., 0., -1., -3.14}; double xmaxpT[4] = {5., 20., 1., +3.14}; - double xminy[4] = {1., 2.5, -1., -3.14}; - double xmaxy[4] = {5., 4.0, 1., +3.14}; hm->AddHistogram(histClass, "Mass_Pt_cosThetaHE_phiHE", "", 4, varspTHE, binspT, xminpT, xmaxpT, 0, -1, kFALSE); - hm->AddHistogram(histClass, "Mass_y_cosThetaHE_phiHE", "", 4, varsrapHE, binsy, xminy, xmaxy, 0, -1, kFALSE); } if (subGroupStr.Contains("dimuon-polarization-cs")) { int varspTCS[4] = {VarManager::kMass, VarManager::kPt, VarManager::kCosThetaCS, VarManager::kPhiCS}; - int varsrapCS[4] = {VarManager::kMass, VarManager::kRap, VarManager::kCosThetaCS, VarManager::kPhiCS}; int binspT[4] = {100, 40, 20, 20}; - int binsy[4] = {100, 10, 20, 20}; double xminpT[4] = {1., 0., -1., -3.14}; double xmaxpT[4] = {5., 20., 1., +3.14}; - double xminy[4] = {1., 2.5, -1., -3.14}; - double xmaxy[4] = {5., 4.0, 1., +3.14}; hm->AddHistogram(histClass, "Mass_Pt_cosThetaCS_phiCS", "", 4, varspTCS, binspT, xminpT, xmaxpT, 0, -1, kFALSE); - hm->AddHistogram(histClass, "Mass_y_cosThetaCS_phiCS", "", 4, varsrapCS, binsy, xminy, xmaxy, 0, -1, kFALSE); } if (subGroupStr.Contains("dimuon-polarization-pp")) { int varspTPP[4] = {VarManager::kMass, VarManager::kPt, VarManager::kCosThetaPP, VarManager::kPhiPP}; - int varsrapPP[4] = {VarManager::kMass, VarManager::kRap, VarManager::kCosThetaPP, VarManager::kPhiPP}; int binspT[4] = {100, 40, 20, 20}; - int binsy[4] = {100, 10, 20, 20}; double xminpT[4] = {1., 0., -1., -3.14}; double xmaxpT[4] = {5., 20., 1., +3.14}; - double xminy[4] = {1., 2.5, -1., -3.14}; - double xmaxy[4] = {5., 4.0, 1., +3.14}; hm->AddHistogram(histClass, "Mass_Pt_cosThetaPP_phiPP", "", 4, varspTPP, binspT, xminpT, xmaxpT, 0, -1, kFALSE); - hm->AddHistogram(histClass, "Mass_y_cosThetaPP_phiPP", "", 4, varsrapPP, binsy, xminy, xmaxy, 0, -1, kFALSE); } if (subGroupStr.Contains("dimuon-polarization-lowmass-pp")) { int varspTPP[4] = {VarManager::kMass, VarManager::kPt, VarManager::kCosThetaPP, VarManager::kPhiPP}; From 92796d1334e894522ddba3a0a7a84d8805814b01 Mon Sep 17 00:00:00 2001 From: rolavick Date: Mon, 23 Jun 2025 15:31:17 +0200 Subject: [PATCH 187/871] [PWGUD] Small improvements in personal tasks + new table maker (#11728) Co-authored-by: ALICE Action Bot --- PWGUD/Core/UPCTauCentralBarrelHelperRL.h | 25 +- PWGUD/DataModel/TwoTracksEventTables.h | 226 ++++++ PWGUD/TableProducer/CMakeLists.txt | 5 + PWGUD/TableProducer/tauEventTableProducer.cxx | 29 +- .../twoTracksEventTableProducer.cxx | 757 ++++++++++++++++++ PWGUD/Tasks/testMCstdTabsRL.cxx | 22 +- PWGUD/Tasks/upcTauRl.cxx | 39 +- 7 files changed, 1079 insertions(+), 24 deletions(-) create mode 100644 PWGUD/DataModel/TwoTracksEventTables.h create mode 100644 PWGUD/TableProducer/twoTracksEventTableProducer.cxx diff --git a/PWGUD/Core/UPCTauCentralBarrelHelperRL.h b/PWGUD/Core/UPCTauCentralBarrelHelperRL.h index 55a13a0e9c5..052ff71acce 100644 --- a/PWGUD/Core/UPCTauCentralBarrelHelperRL.h +++ b/PWGUD/Core/UPCTauCentralBarrelHelperRL.h @@ -8,10 +8,12 @@ // 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 + +/// \file UPCTauCentralBarrelHelperRL.h +/// \brief Personal helper file to analyze tau events from UPC collisions /// \author Roman Lavicka, roman.lavicka@cern.ch /// \since 27.10.2022 +/// #ifndef PWGUD_CORE_UPCTAUCENTRALBARRELHELPERRL_H_ #define PWGUD_CORE_UPCTAUCENTRALBARRELHELPERRL_H_ @@ -156,6 +158,25 @@ int enumMyParticle(int valuePDG) } } +int trackPDGfromEnum(int trackEnum) +// reads pdg value and returns particle number as in enumMyParticle +{ + if (trackEnum == P_ELECTRON) { + return 11; + } else if (trackEnum == P_MUON) { + return 13; + } else if (trackEnum == P_PION) { + return 211; + } else if (trackEnum == P_KAON) { + return 321; + } else if (trackEnum == P_PROTON) { + return 2212; + } else { + printDebugMessage("PDG value not found in enumMyParticle. Returning -1."); + return -1.; + } +} + float pt(float px, float py) // Just a simple function to return pt { diff --git a/PWGUD/DataModel/TwoTracksEventTables.h b/PWGUD/DataModel/TwoTracksEventTables.h new file mode 100644 index 00000000000..73be3f3c438 --- /dev/null +++ b/PWGUD/DataModel/TwoTracksEventTables.h @@ -0,0 +1,226 @@ +// 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 TwoTracksEventTables.h +/// \author Roman Lavička +/// \since 2025-06-20 +/// \brief A table to store information about events preselected to have exactly two tracks. +/// \brief Good for UPC gammagamma (->elel,mumu,tautau) and gammalead (vector mesons) +/// \brief If MC, careful with filling the mother +/// + +#ifndef PWGUD_DATAMODEL_TWOTRACKSEVENTTABLES_H_ +#define PWGUD_DATAMODEL_TWOTRACKSEVENTTABLES_H_ + +#include "Framework/AnalysisDataModel.h" + +namespace o2::aod +{ +namespace two_tracks_tree +{ +// event info +DECLARE_SOA_COLUMN(RunNumber, runNumber, int32_t); +DECLARE_SOA_COLUMN(Bc, bc, int); +DECLARE_SOA_COLUMN(TotalTracks, totalTracks, int); +DECLARE_SOA_COLUMN(NumContrib, numContrib, int); +DECLARE_SOA_COLUMN(GlobalNonPVtracks, globalNonPVtracks, int); +DECLARE_SOA_COLUMN(PosX, posX, float); +DECLARE_SOA_COLUMN(PosY, posY, float); +DECLARE_SOA_COLUMN(PosZ, posZ, float); +DECLARE_SOA_COLUMN(RecoMode, recoMode, int); +DECLARE_SOA_COLUMN(OccupancyInTime, occupancyInTime, int); +DECLARE_SOA_COLUMN(HadronicRate, hadronicRate, double); +DECLARE_SOA_COLUMN(Trs, trs, int); +DECLARE_SOA_COLUMN(Trofs, trofs, int); +DECLARE_SOA_COLUMN(Hmpr, hmpr, int); +DECLARE_SOA_COLUMN(Tfb, tfb, int); +DECLARE_SOA_COLUMN(ItsRofb, itsRofb, int); +DECLARE_SOA_COLUMN(Sbp, sbp, int); +DECLARE_SOA_COLUMN(ZvtxFT0vsPv, zvtxFT0vsPv, int); +DECLARE_SOA_COLUMN(VtxITSTPC, vtxITSTPC, int); +// FIT info +DECLARE_SOA_COLUMN(TotalFT0AmplitudeA, totalFT0AmplitudeA, float); +DECLARE_SOA_COLUMN(TotalFT0AmplitudeC, totalFT0AmplitudeC, float); +DECLARE_SOA_COLUMN(TotalFV0AmplitudeA, totalFV0AmplitudeA, float); +DECLARE_SOA_COLUMN(EnergyCommonZNA, energyCommonZNA, float); +DECLARE_SOA_COLUMN(EnergyCommonZNC, energyCommonZNC, float); +DECLARE_SOA_COLUMN(TimeFT0A, timeFT0A, float); +DECLARE_SOA_COLUMN(TimeFT0C, timeFT0C, float); +DECLARE_SOA_COLUMN(TimeFV0A, timeFV0A, float); +DECLARE_SOA_COLUMN(TimeZNA, timeZNA, float); +DECLARE_SOA_COLUMN(TimeZNC, timeZNC, float); +// tracks +DECLARE_SOA_COLUMN(TrkPx, trkPx, float[2]); +DECLARE_SOA_COLUMN(TrkPy, trkPy, float[2]); +DECLARE_SOA_COLUMN(TrkPz, trkPz, float[2]); +DECLARE_SOA_COLUMN(TrkSign, trkSign, int[2]); +DECLARE_SOA_COLUMN(TrkDCAxy, trkDCAxy, float[2]); +DECLARE_SOA_COLUMN(TrkDCAz, trkDCAz, float[2]); +DECLARE_SOA_COLUMN(TrkTimeRes, trkTimeRes, float[2]); +DECLARE_SOA_COLUMN(Trk1ITSclusterSizes, trk1ITSclusterSizes, uint32_t); +DECLARE_SOA_COLUMN(Trk2ITSclusterSizes, trk2ITSclusterSizes, uint32_t); +DECLARE_SOA_COLUMN(TrkTPCsignal, trkTPCsignal, float[2]); +DECLARE_SOA_COLUMN(TrkTPCnSigmaEl, trkTPCnSigmaEl, float[2]); +DECLARE_SOA_COLUMN(TrkTPCnSigmaMu, trkTPCnSigmaMu, float[2]); +DECLARE_SOA_COLUMN(TrkTPCnSigmaPi, trkTPCnSigmaPi, float[2]); +DECLARE_SOA_COLUMN(TrkTPCnSigmaKa, trkTPCnSigmaKa, float[2]); +DECLARE_SOA_COLUMN(TrkTPCnSigmaPr, trkTPCnSigmaPr, float[2]); +DECLARE_SOA_COLUMN(TrkTPCinnerParam, trkTPCinnerParam, float[2]); +DECLARE_SOA_COLUMN(TrkTOFsignal, trkTOFsignal, float[2]); +DECLARE_SOA_COLUMN(TrkTOFnSigmaEl, trkTOFnSigmaEl, float[2]); +DECLARE_SOA_COLUMN(TrkTOFnSigmaMu, trkTOFnSigmaMu, float[2]); +DECLARE_SOA_COLUMN(TrkTOFnSigmaPi, trkTOFnSigmaPi, float[2]); +DECLARE_SOA_COLUMN(TrkTOFnSigmaKa, trkTOFnSigmaKa, float[2]); +DECLARE_SOA_COLUMN(TrkTOFnSigmaPr, trkTOFnSigmaPr, float[2]); +DECLARE_SOA_COLUMN(TrkTOFexpMom, trkTOFexpMom, float[2]); +// truth event +DECLARE_SOA_COLUMN(TrueChannel, trueChannel, int); +DECLARE_SOA_COLUMN(TrueHasRecoColl, trueHasRecoColl, bool); +DECLARE_SOA_COLUMN(TruePosX, truePosX, float); +DECLARE_SOA_COLUMN(TruePosY, truePosY, float); +DECLARE_SOA_COLUMN(TruePosZ, truePosZ, float); +// truth particles +DECLARE_SOA_COLUMN(TrueMotherPx, trueMotherPx, float[2]); +DECLARE_SOA_COLUMN(TrueMotherPy, trueMotherPy, float[2]); +DECLARE_SOA_COLUMN(TrueMotherPz, trueMotherPz, float[2]); +DECLARE_SOA_COLUMN(TrueDaugPx, trueDaugPx, float[2]); +DECLARE_SOA_COLUMN(TrueDaugPy, trueDaugPy, float[2]); +DECLARE_SOA_COLUMN(TrueDaugPz, trueDaugPz, float[2]); +DECLARE_SOA_COLUMN(TrueDaugPdgCode, trueDaugPdgCode, int[2]); +// additional info +DECLARE_SOA_COLUMN(ProblematicEvent, problematicEvent, bool); + +} // namespace two_tracks_tree +DECLARE_SOA_TABLE(TwoTracks, "AOD", "TWOTRACK", + two_tracks_tree::RunNumber, + two_tracks_tree::Bc, + two_tracks_tree::TotalTracks, + two_tracks_tree::NumContrib, + two_tracks_tree::GlobalNonPVtracks, + two_tracks_tree::PosX, + two_tracks_tree::PosY, + two_tracks_tree::PosZ, + two_tracks_tree::RecoMode, + two_tracks_tree::OccupancyInTime, + two_tracks_tree::HadronicRate, + two_tracks_tree::Trs, + two_tracks_tree::Trofs, + two_tracks_tree::Hmpr, + two_tracks_tree::Tfb, + two_tracks_tree::ItsRofb, + two_tracks_tree::Sbp, + two_tracks_tree::ZvtxFT0vsPv, + two_tracks_tree::VtxITSTPC, + two_tracks_tree::TotalFT0AmplitudeA, + two_tracks_tree::TotalFT0AmplitudeC, + two_tracks_tree::TotalFV0AmplitudeA, + two_tracks_tree::EnergyCommonZNA, + two_tracks_tree::EnergyCommonZNC, + two_tracks_tree::TimeFT0A, + two_tracks_tree::TimeFT0C, + two_tracks_tree::TimeFV0A, + two_tracks_tree::TimeZNA, + two_tracks_tree::TimeZNC, + two_tracks_tree::TrkPx, + two_tracks_tree::TrkPy, + two_tracks_tree::TrkPz, + two_tracks_tree::TrkSign, + two_tracks_tree::TrkDCAxy, + two_tracks_tree::TrkDCAz, + two_tracks_tree::TrkTimeRes, + two_tracks_tree::Trk1ITSclusterSizes, + two_tracks_tree::Trk2ITSclusterSizes, + two_tracks_tree::TrkTPCsignal, + two_tracks_tree::TrkTPCnSigmaEl, + two_tracks_tree::TrkTPCnSigmaMu, + two_tracks_tree::TrkTPCnSigmaPi, + two_tracks_tree::TrkTPCnSigmaKa, + two_tracks_tree::TrkTPCnSigmaPr, + two_tracks_tree::TrkTPCinnerParam, + two_tracks_tree::TrkTOFsignal, + two_tracks_tree::TrkTOFnSigmaEl, + two_tracks_tree::TrkTOFnSigmaMu, + two_tracks_tree::TrkTOFnSigmaPi, + two_tracks_tree::TrkTOFnSigmaKa, + two_tracks_tree::TrkTOFnSigmaPr, + two_tracks_tree::TrkTOFexpMom); + +DECLARE_SOA_TABLE(TrueTwoTracks, "AOD", "TRUETWOTRACK", + two_tracks_tree::RunNumber, + two_tracks_tree::Bc, + two_tracks_tree::TotalTracks, + two_tracks_tree::NumContrib, + two_tracks_tree::GlobalNonPVtracks, + two_tracks_tree::PosX, + two_tracks_tree::PosY, + two_tracks_tree::PosZ, + two_tracks_tree::RecoMode, + two_tracks_tree::OccupancyInTime, + two_tracks_tree::HadronicRate, + two_tracks_tree::Trs, + two_tracks_tree::Trofs, + two_tracks_tree::Hmpr, + two_tracks_tree::Tfb, + two_tracks_tree::ItsRofb, + two_tracks_tree::Sbp, + two_tracks_tree::ZvtxFT0vsPv, + two_tracks_tree::VtxITSTPC, + two_tracks_tree::TotalFT0AmplitudeA, + two_tracks_tree::TotalFT0AmplitudeC, + two_tracks_tree::TotalFV0AmplitudeA, + two_tracks_tree::EnergyCommonZNA, + two_tracks_tree::EnergyCommonZNC, + two_tracks_tree::TimeFT0A, + two_tracks_tree::TimeFT0C, + two_tracks_tree::TimeFV0A, + two_tracks_tree::TimeZNA, + two_tracks_tree::TimeZNC, + two_tracks_tree::TrkPx, + two_tracks_tree::TrkPy, + two_tracks_tree::TrkPz, + two_tracks_tree::TrkSign, + two_tracks_tree::TrkDCAxy, + two_tracks_tree::TrkDCAz, + two_tracks_tree::TrkTimeRes, + two_tracks_tree::Trk1ITSclusterSizes, + two_tracks_tree::Trk2ITSclusterSizes, + two_tracks_tree::TrkTPCsignal, + two_tracks_tree::TrkTPCnSigmaEl, + two_tracks_tree::TrkTPCnSigmaMu, + two_tracks_tree::TrkTPCnSigmaPi, + two_tracks_tree::TrkTPCnSigmaKa, + two_tracks_tree::TrkTPCnSigmaPr, + two_tracks_tree::TrkTPCinnerParam, + two_tracks_tree::TrkTOFsignal, + two_tracks_tree::TrkTOFnSigmaEl, + two_tracks_tree::TrkTOFnSigmaMu, + two_tracks_tree::TrkTOFnSigmaPi, + two_tracks_tree::TrkTOFnSigmaKa, + two_tracks_tree::TrkTOFnSigmaPr, + two_tracks_tree::TrkTOFexpMom, + two_tracks_tree::TrueChannel, + two_tracks_tree::TrueHasRecoColl, + two_tracks_tree::TruePosX, + two_tracks_tree::TruePosY, + two_tracks_tree::TruePosZ, + two_tracks_tree::TrueMotherPx, + two_tracks_tree::TrueMotherPy, + two_tracks_tree::TrueMotherPz, + two_tracks_tree::TrueDaugPx, + two_tracks_tree::TrueDaugPy, + two_tracks_tree::TrueDaugPz, + two_tracks_tree::TrueDaugPdgCode, + two_tracks_tree::ProblematicEvent); + +} // namespace o2::aod + +#endif // PWGUD_DATAMODEL_TWOTRACKSEVENTTABLES_H_ diff --git a/PWGUD/TableProducer/CMakeLists.txt b/PWGUD/TableProducer/CMakeLists.txt index 16dd0773aed..548b052e667 100644 --- a/PWGUD/TableProducer/CMakeLists.txt +++ b/PWGUD/TableProducer/CMakeLists.txt @@ -36,6 +36,11 @@ o2physics_add_dpl_workflow(tau-event-table-producer PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(two-tracks-event-table-producer + SOURCES twoTracksEventTableProducer.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(fwdtrack-propagation SOURCES fwdTrackPropagation.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::GlobalTracking diff --git a/PWGUD/TableProducer/tauEventTableProducer.cxx b/PWGUD/TableProducer/tauEventTableProducer.cxx index 8293a76fd4a..4cda2b55a43 100644 --- a/PWGUD/TableProducer/tauEventTableProducer.cxx +++ b/PWGUD/TableProducer/tauEventTableProducer.cxx @@ -43,10 +43,6 @@ #include "PWGUD/DataModel/TauEventTables.h" #include "PWGUD/Core/SGSelector.h" -// ROOT headers -#include "TLorentzVector.h" -#include "TPDGCode.h" - using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; @@ -77,6 +73,11 @@ struct TauEventTableProducer { Configurable cutTrueGapSideFT0C{"cutTrueGapSideFT0C", 50., "FT0C threshold for SG selector"}; Configurable cutTrueGapSideZDC{"cutTrueGapSideZDC", 10000., "ZDC threshold for SG selector. 0 is <1n, 4.2 is <2n, 6.7 is <3n, 9.5 is <4n, 12.5 is <5n"}; Configurable cutFITtime{"cutFITtime", 40., "Maximum FIT time allowed. Default is 40ns"}; + Configurable cutEvTFb{"cutEvTFb", true, {"Event selection bit kNoTimeFrameBorder"}}; + Configurable cutEvITSROFb{"cutEvITSROFb", true, {"Event selection bit kNoITSROFrameBorder"}}; + Configurable cutEvSbp{"cutEvSbp", true, {"Event selection bit kNoSameBunchPileup"}}; + Configurable cutEvZvtxFT0vPV{"cutEvZvtxFT0vPV", false, {"Event selection bit kIsGoodZvtxFT0vsPV"}}; + Configurable cutEvVtxITSTPC{"cutEvVtxITSTPC", true, {"Event selection bit kIsVertexITSTPC"}}; Configurable cutEvOccupancy{"cutEvOccupancy", 100000., "Maximum allowed occupancy"}; Configurable cutEvTrs{"cutEvTrs", false, {"Event selection bit kNoCollInTimeRangeStandard"}}; Configurable cutEvTrofs{"cutEvTrofs", false, {"Event selection bit kNoCollInRofStandard"}}; @@ -156,6 +157,26 @@ struct TauEventTableProducer { bool isGoodROFtime(C const& coll) { + // kNoTimeFrameBorder + if (cutSample.cutEvTFb && !coll.tfb()) + return false; + + // kNoITSROFrameBorder + if (cutSample.cutEvITSROFb && !coll.itsROFb()) + return false; + + // kNoSameBunchPileup + if (cutSample.cutEvSbp && !coll.sbp()) + return false; + + // kIsGoodZvtxFT0vsPV + if (cutSample.cutEvZvtxFT0vPV && !coll.zVtxFT0vPV()) + return false; + + // kIsVertexITSTPC + if (cutSample.cutEvVtxITSTPC && !coll.vtxITSTPC()) + return false; + // Occupancy if (coll.occupancyInTime() > cutSample.cutEvOccupancy) return false; diff --git a/PWGUD/TableProducer/twoTracksEventTableProducer.cxx b/PWGUD/TableProducer/twoTracksEventTableProducer.cxx new file mode 100644 index 00000000000..95b8c6629e1 --- /dev/null +++ b/PWGUD/TableProducer/twoTracksEventTableProducer.cxx @@ -0,0 +1,757 @@ +// 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 twoTracksEventTableProducer.cxx +/// \brief Produces derived table from UD tables +/// +/// \author Roman Lavicka , Austrian Academy of Sciences & SMI +/// \since 20.06.2025 +// + +// C++ headers +#include +#include +#include +#include +#include + +// O2 headers +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/O2DatabasePDGPlugin.h" +#include "Framework/runDataProcessing.h" + +// O2Physics headers +#include "PWGUD/Core/SGSelector.h" +#include "PWGUD/Core/UPCTauCentralBarrelHelperRL.h" +#include "PWGUD/DataModel/TwoTracksEventTables.h" +#include "PWGUD/DataModel/UDTables.h" + +#include "Common/CCDB/EventSelectionParams.h" +#include "Common/Core/TrackSelection.h" +#include "Common/Core/TrackSelectionDefaults.h" +#include "Common/Core/trackUtilities.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/TrackSelectionTables.h" + +// ROOT +#include "Math/Vector4D.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::constants::physics; + +struct TwoTracksEventTableProducer { + Produces twoTracks; + Produces trueTwoTracks; + + // Global varialbes + Service pdg; + SGSelector sgSelector; + int nSelection{0}; + + HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + + // declare configurables + Configurable verboseInfo{"verboseInfo", false, {"Print general info to terminal; default it false."}}; + + struct : ConfigurableGroup { + Configurable whichGapSide{"whichGapSide", 2, {"0 for side A, 1 for side C, 2 for both sides"}}; + Configurable useTrueGap{"useTrueGap", true, {"Calculate gapSide for a given FV0/FT0/ZDC thresholds"}}; + Configurable cutNumContribs{"cutNumContribs", 2, {"How many contributors event has"}}; + Configurable useNumContribs{"useNumContribs", true, {"Use coll.numContribs as event cut"}}; + Configurable cutRecoFlag{"cutRecoFlag", 1, {"0 = std mode, 1 = upc mode"}}; + Configurable useRecoFlag{"useRecoFlag", false, {"Use coll.flags as event cut"}}; + Configurable cutTrueGapSideFV0{"cutTrueGapSideFV0", 180000, "FV0A threshold for SG selector"}; + Configurable cutTrueGapSideFT0A{"cutTrueGapSideFT0A", 150., "FT0A threshold for SG selector"}; + Configurable cutTrueGapSideFT0C{"cutTrueGapSideFT0C", 50., "FT0C threshold for SG selector"}; + Configurable cutTrueGapSideZDC{"cutTrueGapSideZDC", 10000., "ZDC threshold for SG selector. 0 is <1n, 4.2 is <2n, 6.7 is <3n, 9.5 is <4n, 12.5 is <5n"}; + Configurable cutFITtime{"cutFITtime", 40., "Maximum FIT time allowed. Default is 40ns"}; + Configurable cutEvTFb{"cutEvTFb", true, {"Event selection bit kNoTimeFrameBorder"}}; + Configurable cutEvITSROFb{"cutEvITSROFb", true, {"Event selection bit kNoITSROFrameBorder"}}; + Configurable cutEvSbp{"cutEvSbp", true, {"Event selection bit kNoSameBunchPileup"}}; + Configurable cutEvZvtxFT0vPV{"cutEvZvtxFT0vPV", false, {"Event selection bit kIsGoodZvtxFT0vsPV"}}; + Configurable cutEvVtxITSTPC{"cutEvVtxITSTPC", true, {"Event selection bit kIsVertexITSTPC"}}; + Configurable cutEvOccupancy{"cutEvOccupancy", 100000., "Maximum allowed occupancy"}; + Configurable cutEvTrs{"cutEvTrs", false, {"Event selection bit kNoCollInTimeRangeStandard"}}; + Configurable cutEvTrofs{"cutEvTrofs", false, {"Event selection bit kNoCollInRofStandard"}}; + Configurable cutEvHmpr{"cutEvHmpr", false, {"Event selection bit kNoHighMultCollInPrevRof"}}; + } cutSample; + + struct : ConfigurableGroup { + Configurable applyGlobalTrackSelection{"applyGlobalTrackSelection", false, {"Applies cut on here defined global tracks"}}; + Configurable cutMinPt{"cutMinPt", 0.1f, {"Global track cut"}}; + Configurable cutMaxPt{"cutMaxPt", 1e10f, {"Global track cut"}}; + Configurable cutMinEta{"cutMinEta", -0.8f, {"Global track cut"}}; + Configurable cutMaxEta{"cutMaxEta", 0.8f, {"Global track cut"}}; + Configurable cutMaxDCAz{"cutMaxDCAz", 2.f, {"Global track cut"}}; + Configurable cutMaxDCAxy{"cutMaxDCAxy", 1e10f, {"Global track cut"}}; + Configurable applyPtDependentDCAxy{"applyPtDependentDCAxy", false, {"Global track cut"}}; + Configurable cutHasITS{"cutHasITS", true, {"Global track cut"}}; + Configurable cutMinITSnCls{"cutMinITSnCls", 1, {"Global track cut"}}; + Configurable cutMaxITSchi2{"cutMaxITSchi2", 36.f, {"Global track cut"}}; + Configurable cutITShitsRule{"cutITShitsRule", 0, {"Global track cut"}}; + Configurable cutHasTPC{"cutHasTPC", true, {"Global track cut"}}; + Configurable cutMinTPCnCls{"cutMinTPCnCls", 1, {"Global track cut"}}; + Configurable cutMinTPCnClsXrows{"cutMinTPCnClsXrows", 70, {"Global track cut"}}; + Configurable cutMinTPCnClsXrowsOverNcls{"cutMinTPCnClsXrowsOverNcls", 0.8f, {"Global track cut"}}; + Configurable cutMaxTPCchi2{"cutMaxTPCchi2", 4.f, {"Global track cut"}}; + Configurable cutGoodITSTPCmatching{"cutGoodITSTPCmatching", true, {"Global track cut"}}; + Configurable cutMaxTOFchi2{"cutMaxTOFchi2", 3.f, {"Global track cut"}}; + } cutGlobalTrack; + + struct : ConfigurableGroup { + Configurable preselAtLeastOneTOFtrack{"preselAtLeastOneTOFtrack", false, {"At least one track is required to hit TOF."}}; + Configurable preselBothAreTOFtracks{"preselBothAreTOFtracks", false, {"Both tracks are required to hit TOF."}}; + Configurable preselUseMinMomentumOnBothTracks{"preselUseMinMomentumOnBothTracks", false, {"Both tracks are required to fill requirement on minimum momentum."}}; + Configurable preselMinTrackMomentum{"preselMinTrackMomentum", 0.1, {"Requirement on minimum momentum of the track."}}; + Configurable preselSystemPtCut{"preselSystemPtCut", 0.0, {"By default, cut on maximum system pT."}}; + Configurable preselUseOppositeSystemPtCut{"preselUseOppositeSystemPtCut", false, {"Negates the system pT cut (cut on minimum system pT)."}}; + Configurable preselMinInvariantMass{"preselMinInvariantMass", 2.0, {"Requirement on minimum system invariant mass."}}; + Configurable preselMaxInvariantMass{"preselMaxInvariantMass", 5.0, {"Requirement on maximum system invariant mass."}}; + } cutPreselect; + + using FullUDTracks = soa::Join; + using FullSGUDCollisions = soa::Join; + using FullSGUDCollision = FullSGUDCollisions::iterator; + using FullMCUDTracks = soa::Join; + using FullMCSGUDCollisions = soa::Join; + using FullMCSGUDCollision = FullMCSGUDCollisions::iterator; + + // init + void init(InitContext&) + { + if (verboseInfo) + printMediumMessage("INIT METHOD"); + + mySetITShitsRule(cutGlobalTrack.cutITShitsRule); + + histos.add("Reco/hSelections", "Effect of selections;;Number of events (-)", HistType::kTH1D, {{50, 0.5, 50.5}}); + histos.add("Truth/hTroubles", "Counter of unwanted issues;;Number of troubles (-)", HistType::kTH1D, {{15, 0.5, 15.5}}); + + } // end init + + template + bool isGoodFITtime(C const& coll, float maxFITtime) + { + + // FTOA + if ((std::abs(coll.timeFT0A()) > maxFITtime) && coll.timeFT0A() > -998.) + return false; + histos.get(HIST("Reco/hSelections"))->Fill(nSelection); + nSelection++; + + // FTOC + if ((std::abs(coll.timeFT0C()) > maxFITtime) && coll.timeFT0C() > -998.) + return false; + histos.get(HIST("Reco/hSelections"))->Fill(nSelection); + nSelection++; + + return true; + } + + template + bool isGoodROFtime(C const& coll) + { + + // kNoTimeFrameBorder + if (cutSample.cutEvTFb && !coll.tfb()) + return false; + histos.get(HIST("Reco/hSelections"))->Fill(nSelection); + nSelection++; + + // kNoITSROFrameBorder + if (cutSample.cutEvITSROFb && !coll.itsROFb()) + return false; + histos.get(HIST("Reco/hSelections"))->Fill(nSelection); + nSelection++; + + // kNoSameBunchPileup + if (cutSample.cutEvSbp && !coll.sbp()) + return false; + histos.get(HIST("Reco/hSelections"))->Fill(nSelection); + nSelection++; + + // kIsGoodZvtxFT0vsPV + if (cutSample.cutEvZvtxFT0vPV && !coll.zVtxFT0vPV()) + return false; + histos.get(HIST("Reco/hSelections"))->Fill(nSelection); + nSelection++; + + // kIsVertexITSTPC + if (cutSample.cutEvVtxITSTPC && !coll.vtxITSTPC()) + return false; + histos.get(HIST("Reco/hSelections"))->Fill(nSelection); + nSelection++; + + // Occupancy + if (coll.occupancyInTime() > cutSample.cutEvOccupancy) + return false; + histos.get(HIST("Reco/hSelections"))->Fill(nSelection); + nSelection++; + + // kNoCollInTimeRangeStandard + if (cutSample.cutEvTrs && !coll.trs()) + return false; + histos.get(HIST("Reco/hSelections"))->Fill(nSelection); + nSelection++; + + // kNoCollInRofStandard + if (cutSample.cutEvTrofs && !coll.trofs()) + return false; + histos.get(HIST("Reco/hSelections"))->Fill(nSelection); + nSelection++; + + // kNoHighMultCollInPrevRof + if (cutSample.cutEvHmpr && !coll.hmpr()) + return false; + histos.get(HIST("Reco/hSelections"))->Fill(nSelection); + nSelection++; + + return true; + } + + std::vector>> cutMyRequiredITSHits{}; + + void mySetRequireHitsInITSLayers(int8_t minNRequiredHits, std::set requiredLayers) + { + // layer 0 corresponds to the the innermost ITS layer + cutMyRequiredITSHits.push_back(std::make_pair(minNRequiredHits, requiredLayers)); + } + + void mySetITShitsRule(int matching) + { + switch (matching) { + case 0: // Run3ITSibAny + mySetRequireHitsInITSLayers(1, {0, 1, 2}); + break; + case 1: // Run3ITSibTwo + mySetRequireHitsInITSLayers(2, {0, 1, 2}); + break; + case 2: // Run3ITSallAny + mySetRequireHitsInITSLayers(1, {0, 1, 2, 3, 4, 5, 6}); + break; + case 3: // Run3ITSall7Layers + mySetRequireHitsInITSLayers(7, {0, 1, 2, 3, 4, 5, 6}); + break; + default: + LOG(fatal) << "You chose wrong ITS matching"; + break; + } + } + + bool isFulfillsITSHitRequirementsReinstatement(uint8_t itsClusterMap) const + { + constexpr uint8_t kBit = 1; + for (const auto& kITSrequirement : cutMyRequiredITSHits) { + auto hits = std::count_if(kITSrequirement.second.begin(), kITSrequirement.second.end(), [&](auto&& requiredLayer) { return itsClusterMap & (kBit << requiredLayer); }); + if ((kITSrequirement.first == -1) && (hits > 0)) { + return false; // no hits were required in specified layers + } else if (hits < kITSrequirement.first) { + return false; // not enough hits found in specified layers + } + } + return true; + } + + template + bool isGlobalTrackReinstatement(T const& track) + { + // kInAcceptance copy + if (track.pt() < cutGlobalTrack.cutMinPt || track.pt() > cutGlobalTrack.cutMaxPt) + return false; + if (eta(track.px(), track.py(), track.pz()) < cutGlobalTrack.cutMinEta || eta(track.px(), track.py(), track.pz()) > cutGlobalTrack.cutMaxEta) + return false; + // kPrimaryTracks + // GoldenChi2 cut is only for Run 2 + if (std::abs(track.dcaZ()) > cutGlobalTrack.cutMaxDCAz) + return false; + if (cutGlobalTrack.applyPtDependentDCAxy) { + float maxDCA = 0.0182f + 0.0350f / std::pow(track.pt(), 1.01f); + if (std::abs(track.dcaXY()) > maxDCA) + return false; + } else { + if (std::abs(track.dcaXY()) > cutGlobalTrack.cutMaxDCAxy) + return false; + } + // kQualityTrack + // TrackType is always 1 as per definition of processed Run3 AO2Ds + // ITS + if (cutGlobalTrack.cutHasITS && !track.hasITS()) + return false; // ITS refit + if (track.itsNCls() < cutGlobalTrack.cutMinITSnCls) + return false; + if (track.itsChi2NCl() > cutGlobalTrack.cutMaxITSchi2) + return false; + if (!isFulfillsITSHitRequirementsReinstatement(track.itsClusterMap())) + return false; + // TPC + if (cutGlobalTrack.cutHasTPC && !track.hasTPC()) + return false; // TPC refit + if ((track.tpcNClsFindable() - track.tpcNClsFindableMinusFound()) < cutGlobalTrack.cutMinTPCnCls) + return false; // tpcNClsFound() + if (track.tpcNClsCrossedRows() < cutGlobalTrack.cutMinTPCnClsXrows) + return false; + if ((static_cast(track.tpcNClsCrossedRows()) / static_cast(track.tpcNClsFindable())) < cutGlobalTrack.cutMinTPCnClsXrowsOverNcls) + return false; + if (track.tpcChi2NCl() > cutGlobalTrack.cutMaxTPCchi2) + return false; // TPC chi2 + if (cutGlobalTrack.cutGoodITSTPCmatching) { + if (track.itsChi2NCl() < 0.) + return false; // TPC chi2 + } + // TOF + if (track.hasTOF()) { + if (track.tpcChi2NCl() > cutGlobalTrack.cutMaxTOFchi2) + return false; // TOF chi2 + } + + return true; + } + + template + float findRightMass(T const& trk1, T const& trk2) + // choose the right mass for the tracks based on comparing combined sigma + // good for same-type particles decays + { + float nSigmasTPCsqrt[5]; + nSigmasTPCsqrt[P_ELECTRON] = std::sqrt(trk1.tpcNSigmaEl() * trk1.tpcNSigmaEl() + trk2.tpcNSigmaEl() * trk2.tpcNSigmaEl()); + nSigmasTPCsqrt[P_MUON] = std::sqrt(trk1.tpcNSigmaMu() * trk1.tpcNSigmaMu() + trk2.tpcNSigmaMu() * trk2.tpcNSigmaMu()); + nSigmasTPCsqrt[P_PION] = std::sqrt(trk1.tpcNSigmaPi() * trk1.tpcNSigmaPi() + trk2.tpcNSigmaPi() * trk2.tpcNSigmaPi()); + nSigmasTPCsqrt[P_KAON] = std::sqrt(trk1.tpcNSigmaKa() * trk1.tpcNSigmaKa() + trk2.tpcNSigmaKa() * trk2.tpcNSigmaKa()); + nSigmasTPCsqrt[P_PROTON] = std::sqrt(trk1.tpcNSigmaPr() * trk1.tpcNSigmaPr() + trk2.tpcNSigmaPr() * trk2.tpcNSigmaPr()); + + int enumChoiceTPC = std::distance(std::begin(nSigmasTPCsqrt), + std::min_element(std::begin(nSigmasTPCsqrt), std::end(nSigmasTPCsqrt))); + + return pdg->Mass(trackPDGfromEnum(enumChoiceTPC)); + } + + void processDataSG(FullSGUDCollision const& collision, + FullUDTracks const& tracks) + { + + nSelection = 0; + histos.get(HIST("Reco/hSelections"))->Fill(nSelection); + nSelection++; + + if (!isGoodROFtime(collision)) + return; + + int gapSide = collision.gapSide(); + int trueGapSide = sgSelector.trueGap(collision, cutSample.cutTrueGapSideFV0, cutSample.cutTrueGapSideFT0A, cutSample.cutTrueGapSideFT0C, cutSample.cutTrueGapSideZDC); + + if (cutSample.useTrueGap) + gapSide = trueGapSide; + + if (gapSide != cutSample.whichGapSide) + return; + histos.get(HIST("Reco/hSelections"))->Fill(nSelection); + nSelection++; + + if (!isGoodFITtime(collision, cutSample.cutFITtime)) + return; + + if (cutSample.useNumContribs && (collision.numContrib() != cutSample.cutNumContribs)) + return; + histos.get(HIST("Reco/hSelections"))->Fill(nSelection); + nSelection++; + + if (cutSample.useRecoFlag && (collision.flags() != cutSample.cutRecoFlag)) + return; + histos.get(HIST("Reco/hSelections"))->Fill(nSelection); + nSelection++; + + int countTracksPerCollision = 0; + int countGoodNonPVtracks = 0; + int countGoodPVtracks = 0; + std::vector vecTrkIdx; + // Loop over tracks with selections + for (const auto& track : tracks) { + countTracksPerCollision++; + if (!isGlobalTrackReinstatement(track)) + continue; + if (!track.isPVContributor()) { + countGoodNonPVtracks++; + continue; + } + countGoodPVtracks++; + vecTrkIdx.push_back(track.index()); + } // Loop over tracks with selections + + // Critical selection, without it the rest of the process function will fail + if (countGoodPVtracks != 2) + return; + histos.get(HIST("Reco/hSelections"))->Fill(nSelection); + nSelection++; + + const auto& trk1 = tracks.iteratorAt(vecTrkIdx[0]); + const auto& trk2 = tracks.iteratorAt(vecTrkIdx[1]); + + float thisMass = findRightMass(trk1, trk2); + + // prepare lorentz vectors to create system + ROOT::Math::LorentzVector> twoTrackMother, daug[2]; + daug[0].SetPxPyPzE(trk1.px(), trk1.py(), trk1.pz(), energy(thisMass, trk1.px(), trk1.py(), trk1.pz())); + daug[1].SetPxPyPzE(trk2.px(), trk2.py(), trk2.pz(), energy(thisMass, trk2.px(), trk2.py(), trk2.pz())); + twoTrackMother = daug[0] + daug[1]; + float thisPt = pt(twoTrackMother.px(), twoTrackMother.py()); + + // Apply system selections + // invariant mass + if (twoTrackMother.M() < cutPreselect.preselMinInvariantMass || twoTrackMother.M() > cutPreselect.preselMaxInvariantMass) + return; + histos.get(HIST("Reco/hSelections"))->Fill(nSelection); + nSelection++; + + // system pt + if (cutPreselect.preselUseOppositeSystemPtCut ? thisPt < cutPreselect.preselSystemPtCut : thisPt > cutPreselect.preselSystemPtCut) + return; + histos.get(HIST("Reco/hSelections"))->Fill(nSelection); + nSelection++; + + // one track momentum + if (daug[0].P() < cutPreselect.preselMinTrackMomentum && daug[1].P() < cutPreselect.preselMinTrackMomentum) + return; + histos.get(HIST("Reco/hSelections"))->Fill(nSelection); + nSelection++; + + // both tracks momentum + if (cutPreselect.preselUseMinMomentumOnBothTracks && (daug[0].P() < cutPreselect.preselMinTrackMomentum || daug[1].P() < cutPreselect.preselMinTrackMomentum)) + return; + histos.get(HIST("Reco/hSelections"))->Fill(nSelection); + nSelection++; + + // track in TOF + if (cutPreselect.preselAtLeastOneTOFtrack && (!trk1.hasTOF() && !trk2.hasTOF())) + return; + histos.get(HIST("Reco/hSelections"))->Fill(nSelection); + nSelection++; + + // tracks in TOF + if (cutPreselect.preselBothAreTOFtracks && (!trk1.hasTOF() || !trk2.hasTOF())) + return; + histos.get(HIST("Reco/hSelections"))->Fill(nSelection); + nSelection++; + + float px[2] = {trk1.px(), trk2.px()}; + float py[2] = {trk1.py(), trk2.py()}; + float pz[2] = {trk1.pz(), trk2.pz()}; + int sign[2] = {trk1.sign(), trk2.sign()}; + float dcaxy[2] = {trk1.dcaXY(), trk2.dcaXY()}; + float dcaz[2] = {trk1.dcaZ(), trk2.dcaZ()}; + float trkTimeRes[2] = {trk1.trackTimeRes(), trk2.trackTimeRes()}; + uint32_t itsClusterSizesTrk1 = trk1.itsClusterSizes(); + uint32_t itsClusterSizesTrk2 = trk2.itsClusterSizes(); + float tpcSignal[2] = {trk1.tpcSignal(), trk2.tpcSignal()}; + float tpcEl[2] = {trk1.tpcNSigmaEl(), trk2.tpcNSigmaEl()}; + float tpcMu[2] = {trk1.tpcNSigmaMu(), trk2.tpcNSigmaMu()}; + float tpcPi[2] = {trk1.tpcNSigmaPi(), trk2.tpcNSigmaPi()}; + float tpcKa[2] = {trk1.tpcNSigmaKa(), trk2.tpcNSigmaKa()}; + float tpcPr[2] = {trk1.tpcNSigmaPr(), trk2.tpcNSigmaPr()}; + float tpcIP[2] = {trk1.tpcInnerParam(), trk2.tpcInnerParam()}; + float tofSignal[2] = {trk1.tofSignal(), trk2.tofSignal()}; + float tofEl[2] = {trk1.tofNSigmaEl(), trk2.tofNSigmaEl()}; + float tofMu[2] = {trk1.tofNSigmaMu(), trk2.tofNSigmaMu()}; + float tofPi[2] = {trk1.tofNSigmaPi(), trk2.tofNSigmaPi()}; + float tofKa[2] = {trk1.tofNSigmaKa(), trk2.tofNSigmaKa()}; + float tofPr[2] = {trk1.tofNSigmaPr(), trk2.tofNSigmaPr()}; + float tofEP[2] = {trk1.tofExpMom(), trk2.tofExpMom()}; + float infoZDC[4] = {collision.energyCommonZNA(), collision.energyCommonZNC(), collision.timeZNA(), collision.timeZNC()}; + + twoTracks(collision.runNumber(), collision.globalBC(), countTracksPerCollision, collision.numContrib(), countGoodNonPVtracks, collision.posX(), collision.posY(), collision.posZ(), + collision.flags(), collision.occupancyInTime(), collision.hadronicRate(), collision.trs(), collision.trofs(), collision.hmpr(), + collision.tfb(), collision.itsROFb(), collision.sbp(), collision.zVtxFT0vPV(), collision.vtxITSTPC(), + collision.totalFT0AmplitudeA(), collision.totalFT0AmplitudeC(), collision.totalFV0AmplitudeA(), infoZDC[0], infoZDC[1], + collision.timeFT0A(), collision.timeFT0C(), collision.timeFV0A(), infoZDC[2], infoZDC[3], + px, py, pz, sign, dcaxy, dcaz, trkTimeRes, + itsClusterSizesTrk1, itsClusterSizesTrk2, + tpcSignal, tpcEl, tpcMu, tpcPi, tpcKa, tpcPr, tpcIP, + tofSignal, tofEl, tofMu, tofPi, tofKa, tofPr, tofEP); + } + PROCESS_SWITCH(TwoTracksEventTableProducer, processDataSG, "Iterate UD tables with measured data created by SG-Candidate-Producer.", false); + + PresliceUnsorted partPerMcCollision = aod::udmcparticle::udMcCollisionId; + PresliceUnsorted colPerMcCollision = aod::udcollision::udMcCollisionId; + PresliceUnsorted trackPerMcParticle = aod::udmctracklabel::udMcParticleId; + Preslice trackPerCollision = aod::udtrack::udCollisionId; // sorted preslice used because the pair track-collision is already sorted in processDataSG function + + void processMonteCarlo(aod::UDMcCollisions const& mccollisions, + aod::UDMcParticles const& parts, + FullMCSGUDCollisions const& recolls, + FullMCUDTracks const& trks) + { + // start loop over generated collisions + for (const auto& mccoll : mccollisions) { + + // prepare local variables for output table + int32_t runNumber = -999; + int bc = -999; + int nTrks[3] = {-999, -999, -999}; // totalTracks, numContrib, globalNonPVtracks + float vtxPos[3] = {-999., -999., -999.}; + int recoMode = -999; + int occupancy = -999.; + double hadronicRate = -999.; + int bcSels[8] = {-999, -999, -999, -999, -999, -999, -999, -999}; + float amplitudesFIT[3] = {-999., -999., -999.}; // FT0A, FT0C, FV0 + float timesFIT[3] = {-999., -999., -999.}; // FT0A, FT0C, FV0 + + float px[2] = {-999., -999.}; + float py[2] = {-999., -999.}; + float pz[2] = {-999., -999.}; + int sign[2] = {-999, -999}; + float dcaxy[2] = {-999., -999.}; + float dcaz[2] = {-999., -999.}; + float trkTimeRes[2] = {-999., -999.}; + uint32_t itsClusterSizesTrk1 = 4294967295; + uint32_t itsClusterSizesTrk2 = 4294967295; + float tpcSignal[2] = {-999, -999}; + float tpcEl[2] = {-999, -999}; + float tpcMu[2] = {-999, -999}; + float tpcPi[2] = {-999, -999}; + float tpcKa[2] = {-999, -999}; + float tpcPr[2] = {-999, -999}; + float tpcIP[2] = {-999, -999}; + float tofSignal[2] = {-999, -999}; + float tofEl[2] = {-999, -999}; + float tofMu[2] = {-999, -999}; + float tofPi[2] = {-999, -999}; + float tofKa[2] = {-999, -999}; + float tofPr[2] = {-999, -999}; + float tofEP[2] = {-999, -999}; + + int trueChannel = -1; + bool trueHasRecoColl = false; + float trueMotherX[2] = {-999., -999.}; + float trueMotherY[2] = {-999., -999.}; + float trueMotherZ[2] = {-999., -999.}; + float trueDaugX[2] = {-999., -999.}; + float trueDaugY[2] = {-999., -999.}; + float trueDaugZ[2] = {-999., -999.}; + int trueDaugPdgCode[2] = {-999, -999}; + bool problem = false; + + // find reconstructed collisions associated to the generated collision + auto const& collFromMcColls = recolls.sliceBy(colPerMcCollision, mccoll.globalIndex()); + // check the generated collision was reconstructed + if (collFromMcColls.size() > 0) { // get the truth and reco-level info + trueHasRecoColl = true; + // check there is exactly one reco-level collision associated to generated collision + if (collFromMcColls.size() > 1) { + if (verboseInfo) + printLargeMessage("Truth collision has more than 1 reco collision. Skipping this event."); + histos.get(HIST("Truth/hTroubles"))->Fill(1); + problem = true; + continue; + } + // grap reco-level collision + auto const& collFromMcColl = collFromMcColls.iteratorAt(0); + // grab tracks from the reco-level collision to get info to match measured data tables (processDataSG function) + auto const& trksFromColl = trks.sliceBy(trackPerCollision, collFromMcColl.globalIndex()); + int countTracksPerCollision = 0; + int countGoodNonPVtracks = 0; + for (auto const& trkFromColl : trksFromColl) { + countTracksPerCollision++; + if (!trkFromColl.isPVContributor()) { + countGoodNonPVtracks++; + continue; + } + } + + // fill info for reconstructed collision + runNumber = collFromMcColl.runNumber(); + bc = collFromMcColl.globalBC(); + nTrks[0] = countTracksPerCollision; + nTrks[1] = collFromMcColl.numContrib(); + nTrks[2] = countGoodNonPVtracks; + vtxPos[0] = collFromMcColl.posX(); + vtxPos[1] = collFromMcColl.posY(); + vtxPos[2] = collFromMcColl.posZ(); + recoMode = collFromMcColl.flags(); + occupancy = collFromMcColl.occupancyInTime(); + hadronicRate = collFromMcColl.hadronicRate(); + bcSels[0] = collFromMcColl.trs(); + bcSels[1] = collFromMcColl.trofs(); + bcSels[2] = collFromMcColl.hmpr(); + bcSels[3] = collFromMcColl.tfb(); + bcSels[4] = collFromMcColl.itsROFb(); + bcSels[5] = collFromMcColl.sbp(); + bcSels[6] = collFromMcColl.zVtxFT0vPV(); + bcSels[7] = collFromMcColl.vtxITSTPC(); + amplitudesFIT[0] = collFromMcColl.totalFT0AmplitudeA(); + amplitudesFIT[1] = collFromMcColl.totalFT0AmplitudeC(); + amplitudesFIT[2] = collFromMcColl.totalFV0AmplitudeA(); + timesFIT[0] = collFromMcColl.timeFT0A(); + timesFIT[1] = collFromMcColl.timeFT0C(); + timesFIT[2] = collFromMcColl.timeFV0A(); + + // get particles associated to generated collision + auto const& partsFromMcColl = parts.sliceBy(partPerMcCollision, mccoll.globalIndex()); + int countMothers = 0; + for (const auto& particle : partsFromMcColl) { + // select only mothers with checking if particle has no mother + if (particle.has_mothers()) + continue; + countMothers++; + // check the generated collision does not have more than 2 mothers + if (countMothers > 2) { + if (verboseInfo) + printLargeMessage("Truth collision has more than 2 no mother particles. Breaking the particle loop."); + histos.get(HIST("Truth/hTroubles"))->Fill(2); + problem = true; + break; + } + // fill info for each mother + trueMotherX[countMothers - 1] = particle.px(); + trueMotherY[countMothers - 1] = particle.py(); + trueMotherZ[countMothers - 1] = particle.pz(); + + // get daughters of the tau + const auto& daughters = particle.daughters_as(); + int countDaughters = 0; + for (const auto& daughter : daughters) { + // check if it is the charged particle (= no pi0 or neutrino) + if (enumMyParticle(daughter.pdgCode()) == -1) + continue; + countDaughters++; + // check there is only 1 charged daughter related to 1 tau + if (countDaughters > 1) { + if (verboseInfo) + printLargeMessage("Truth collision has more than 1 charged daughters of no mother particles. Breaking the daughter loop."); + histos.get(HIST("Truth/hTroubles"))->Fill(3); + problem = true; + break; + } + // fill info for each daughter + trueDaugX[countMothers - 1] = daughter.px(); + trueDaugY[countMothers - 1] = daughter.py(); + trueDaugZ[countMothers - 1] = daughter.pz(); + trueDaugPdgCode[countMothers - 1] = daughter.pdgCode(); + + // get tracks associated to MC daughter (how well the daughter was reconstructed) + auto const& tracksFromDaughter = trks.sliceBy(trackPerMcParticle, daughter.globalIndex()); + // check there is exactly 1 track per 1 particle + if (tracksFromDaughter.size() > 1) { + if (verboseInfo) + printLargeMessage("Daughter has more than 1 associated track. Skipping this daughter."); + histos.get(HIST("Truth/hTroubles"))->Fill(4); + problem = true; + continue; + } + // grab the track and fill info for reconstructed track (should be done twice) + const auto& trk = tracksFromDaughter.iteratorAt(0); + px[countMothers - 1] = trk.px(); + py[countMothers - 1] = trk.py(); + pz[countMothers - 1] = trk.pz(); + sign[countMothers - 1] = trk.sign(); + dcaxy[countMothers - 1] = trk.dcaXY(); + dcaz[countMothers - 1] = trk.dcaZ(); + trkTimeRes[countMothers - 1] = trk.trackTimeRes(); + if (countMothers == 1) { + itsClusterSizesTrk1 = trk.itsClusterSizes(); + } else { + itsClusterSizesTrk2 = trk.itsClusterSizes(); + } + tpcSignal[countMothers - 1] = trk.tpcSignal(); + tpcEl[countMothers - 1] = trk.tpcNSigmaEl(); + tpcMu[countMothers - 1] = trk.tpcNSigmaMu(); + tpcPi[countMothers - 1] = trk.tpcNSigmaPi(); + tpcKa[countMothers - 1] = trk.tpcNSigmaKa(); + tpcPr[countMothers - 1] = trk.tpcNSigmaPr(); + tpcIP[countMothers - 1] = trk.tpcInnerParam(); + tofSignal[countMothers - 1] = trk.tofSignal(); + tofEl[countMothers - 1] = trk.tofNSigmaEl(); + tofMu[countMothers - 1] = trk.tofNSigmaMu(); + tofPi[countMothers - 1] = trk.tofNSigmaPi(); + tofKa[countMothers - 1] = trk.tofNSigmaKa(); + tofPr[countMothers - 1] = trk.tofNSigmaPr(); + tofEP[countMothers - 1] = trk.tofExpMom(); + } // daughters + } // particles + } else { // get only the truth information. The reco-level info is left on default + // get particles associated to generated collision + auto const& partsFromMcColl = parts.sliceBy(partPerMcCollision, mccoll.globalIndex()); + int countMothers = 0; + for (const auto& particle : partsFromMcColl) { + // select only tauons with checking if particle has no mother + if (particle.has_mothers()) + continue; + countMothers++; + // check the generated collision does not have more than 2 mothers + if (countMothers > 2) { + if (verboseInfo) + printLargeMessage("Truth collision has more than 2 no mother particles. Breaking the particle loop."); + histos.get(HIST("Truth/hTroubles"))->Fill(12); + problem = true; + break; + } + // fill info for each tau + trueMotherX[countMothers - 1] = particle.px(); + trueMotherY[countMothers - 1] = particle.py(); + trueMotherZ[countMothers - 1] = particle.pz(); + + // get daughters of the tau + const auto& daughters = particle.daughters_as(); + int countDaughters = 0; + for (const auto& daughter : daughters) { + // select only the charged particle (= no pi0 or neutrino) + if (enumMyParticle(daughter.pdgCode()) == -1) + continue; + countDaughters++; + // check there is only 1 charged daughter related to 1 tau + if (countDaughters > 1) { + if (verboseInfo) + printLargeMessage("Truth collision has more than 1 charged daughters of no mother particles. Breaking the daughter loop."); + histos.get(HIST("Truth/hTroubles"))->Fill(13); + problem = true; + break; + } + // fill info for each daughter + trueDaugX[countMothers - 1] = daughter.px(); + trueDaugY[countMothers - 1] = daughter.py(); + trueDaugZ[countMothers - 1] = daughter.pz(); + trueDaugPdgCode[countMothers - 1] = daughter.pdgCode(); + } // daughters + } // particles + } // collisions + + // decide the channel and set the variable. Only two cahnnels suported now. + if ((enumMyParticle(trueDaugPdgCode[0]) == P_ELECTRON) && (enumMyParticle(trueDaugPdgCode[1]) == P_ELECTRON)) + trueChannel = CH_EE; + if ((enumMyParticle(trueDaugPdgCode[0]) == P_ELECTRON) && ((enumMyParticle(trueDaugPdgCode[1]) == P_PION) || (enumMyParticle(trueDaugPdgCode[1]) == P_MUON))) + trueChannel = CH_EMUPI; + if ((enumMyParticle(trueDaugPdgCode[1]) == P_ELECTRON) && ((enumMyParticle(trueDaugPdgCode[0]) == P_PION) || (enumMyParticle(trueDaugPdgCode[0]) == P_MUON))) + trueChannel = CH_EMUPI; + + trueTwoTracks(runNumber, bc, nTrks[0], nTrks[1], nTrks[2], vtxPos[0], vtxPos[1], vtxPos[2], + recoMode, occupancy, hadronicRate, bcSels[0], bcSels[1], bcSels[2], + bcSels[3], bcSels[4], bcSels[5], bcSels[6], bcSels[7], + amplitudesFIT[0], amplitudesFIT[1], amplitudesFIT[2], -999., -999., // no ZDC info in MC + timesFIT[0], timesFIT[1], timesFIT[2], -999., -999., // no ZDC info in MC + px, py, pz, sign, dcaxy, dcaz, trkTimeRes, + itsClusterSizesTrk1, itsClusterSizesTrk2, + tpcSignal, tpcEl, tpcMu, tpcPi, tpcKa, tpcPr, tpcIP, + tofSignal, tofEl, tofMu, tofPi, tofKa, tofPr, tofEP, + trueChannel, trueHasRecoColl, mccoll.posX(), mccoll.posY(), mccoll.posZ(), + trueMotherX, trueMotherY, trueMotherZ, trueDaugX, trueDaugY, trueDaugZ, trueDaugPdgCode, problem); + } // mccollisions + } + PROCESS_SWITCH(TwoTracksEventTableProducer, processMonteCarlo, "Iterate UD tables with simulated data created by SG-Candidate-Producer.", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +} diff --git a/PWGUD/Tasks/testMCstdTabsRL.cxx b/PWGUD/Tasks/testMCstdTabsRL.cxx index 6ac26211e03..34bd3085e64 100644 --- a/PWGUD/Tasks/testMCstdTabsRL.cxx +++ b/PWGUD/Tasks/testMCstdTabsRL.cxx @@ -33,7 +33,7 @@ #include "PWGUD/Core/UPCTauCentralBarrelHelperRL.h" // ROOT headers -#include "TLorentzVector.h" +#include "Math/Vector4D.h" using namespace o2; using namespace o2::framework; @@ -74,24 +74,24 @@ struct TestMCstdTabsRL { void processMCgen(aod::McCollision const& collision, aod::McParticles const& particles) { - histos.get(HIST("Events/Truth/hGenIDvsCountCollisions"))->Fill(collision.generatorsID(), 1); - histos.get(HIST("Events/Truth/hGenIDvsNparticles"))->Fill(collision.generatorsID(), particles.size()); + histos.get(HIST("Events/Truth/hGenIDvsCountCollisions"))->Fill(collision.getGeneratorId(), 1); + histos.get(HIST("Events/Truth/hGenIDvsNparticles"))->Fill(collision.getGeneratorId(), particles.size()); - TLorentzVector mother; + ROOT::Math::LorentzVector> mother; for (const auto& particle : particles) { - histos.get(HIST("Events/Truth/hGenIDvsPDGcodesAll"))->Fill(collision.generatorsID(), particle.pdgCode()); + histos.get(HIST("Events/Truth/hGenIDvsPDGcodesAll"))->Fill(collision.getGeneratorId(), particle.pdgCode()); // if (!particle.isPhysicalPrimary()) continue; if (particle.has_mothers()) continue; mother.SetPxPyPzE(particle.px(), particle.py(), particle.pz(), energy(pdg->Mass(particle.pdgCode()), particle.px(), particle.py(), particle.pz())); - histos.get(HIST("Events/Truth/hGenIDvsPDGcodesNoMother"))->Fill(collision.generatorsID(), particle.pdgCode()); - histos.get(HIST("Events/Truth/hGenIDvsMotherMass"))->Fill(collision.generatorsID(), mother.M()); - histos.get(HIST("Events/Truth/hGenIDvsMotherPt"))->Fill(collision.generatorsID(), particle.pt()); - histos.get(HIST("Events/Truth/hGenIDvsMotherRap"))->Fill(collision.generatorsID(), particle.y()); + histos.get(HIST("Events/Truth/hGenIDvsPDGcodesNoMother"))->Fill(collision.getGeneratorId(), particle.pdgCode()); + histos.get(HIST("Events/Truth/hGenIDvsMotherMass"))->Fill(collision.getGeneratorId(), mother.M()); + histos.get(HIST("Events/Truth/hGenIDvsMotherPt"))->Fill(collision.getGeneratorId(), particle.pt()); + histos.get(HIST("Events/Truth/hGenIDvsMotherRap"))->Fill(collision.getGeneratorId(), particle.y()); const auto& daughters = particle.daughters_as(); - histos.get(HIST("Events/Truth/hGenIDvsNdaughters"))->Fill(collision.generatorsID(), daughters.size()); + histos.get(HIST("Events/Truth/hGenIDvsNdaughters"))->Fill(collision.getGeneratorId(), daughters.size()); for (const auto& daughter : daughters) { - histos.get(HIST("Events/Truth/hGenIDvsPDGcodesDaughters"))->Fill(collision.generatorsID(), daughter.pdgCode()); + histos.get(HIST("Events/Truth/hGenIDvsPDGcodesDaughters"))->Fill(collision.getGeneratorId(), daughter.pdgCode()); } } diff --git a/PWGUD/Tasks/upcTauRl.cxx b/PWGUD/Tasks/upcTauRl.cxx index 91b4e87ed29..4f791e2a11e 100644 --- a/PWGUD/Tasks/upcTauRl.cxx +++ b/PWGUD/Tasks/upcTauRl.cxx @@ -43,7 +43,7 @@ #include "PWGUD/Core/SGSelector.h" // ROOT headers -#include "TLorentzVector.h" +#include "Math/Vector4D.h" #include "TPDGCode.h" using namespace o2; @@ -156,6 +156,11 @@ struct UpcTauRl { Configurable cutTrueGapSideFT0C{"cutTrueGapSideFT0C", 50., "FT0C threshold for SG selector"}; Configurable cutTrueGapSideZDC{"cutTrueGapSideZDC", 0., "ZDC threshold for SG selector. 0 is <1n, 4.2 is <2n, 6.7 is <3n, 9.5 is <4n, 12.5 is <5n"}; Configurable cutFITtime{"cutFITtime", 40., "Maximum FIT time allowed. Default is 40ns"}; + Configurable cutEvTFb{"cutEvTFb", true, {"Event selection bit kNoTimeFrameBorder"}}; + Configurable cutEvITSROFb{"cutEvITSROFb", true, {"Event selection bit kNoITSROFrameBorder"}}; + Configurable cutEvSbp{"cutEvSbp", true, {"Event selection bit kNoSameBunchPileup"}}; + Configurable cutEvZvtxFT0vPV{"cutEvZvtxFT0vPV", false, {"Event selection bit kIsGoodZvtxFT0vsPV"}}; + Configurable cutEvVtxITSTPC{"cutEvVtxITSTPC", true, {"Event selection bit kIsVertexITSTPC"}}; Configurable cutEvOccupancy{"cutEvOccupancy", 100000., "Maximum allowed occupancy"}; Configurable cutEvTrs{"cutEvTrs", true, {"Event selection bit kNoCollInTimeRangeStandard"}}; Configurable cutEvTrofs{"cutEvTrofs", true, {"Event selection bit kNoCollInRofStandard"}}; @@ -862,6 +867,26 @@ struct UpcTauRl { bool isGoodROFtime(C const& coll) { + // kNoTimeFrameBorder + if (cutSample.cutEvTFb && !coll.tfb()) + return false; + + // kNoITSROFrameBorder + if (cutSample.cutEvITSROFb && !coll.itsROFb()) + return false; + + // kNoSameBunchPileup + if (cutSample.cutEvSbp && !coll.sbp()) + return false; + + // kIsGoodZvtxFT0vsPV + if (cutSample.cutEvZvtxFT0vPV && !coll.zVtxFT0vPV()) + return false; + + // kIsVertexITSTPC + if (cutSample.cutEvVtxITSTPC && !coll.vtxITSTPC()) + return false; + // Occupancy if (coll.occupancyInTime() > cutSample.cutEvOccupancy) return false; @@ -1012,7 +1037,7 @@ struct UpcTauRl { template bool selectedTauEvent(T const& trkDaug1, T const& trkDaug2) { - TLorentzVector mother, daug[2], motherOfPions, pion[2]; + ROOT::Math::LorentzVector> mother, daug[2], motherOfPions, pion[2]; daug[0].SetPxPyPzE(trkDaug1.px(), trkDaug1.py(), trkDaug1.pz(), energy(pdg->Mass(trackPDG(trkDaug1, cutPID.cutSiTPC, cutPID.cutSiTOF, cutPID.usePIDwTOF, cutPID.useScutTOFinTPC)), trkDaug1.px(), trkDaug1.py(), trkDaug1.pz())); daug[1].SetPxPyPzE(trkDaug2.px(), trkDaug2.py(), trkDaug2.pz(), energy(pdg->Mass(trackPDG(trkDaug2, cutPID.cutSiTPC, cutPID.cutSiTOF, cutPID.usePIDwTOF, cutPID.useScutTOFinTPC)), trkDaug2.px(), trkDaug2.py(), trkDaug2.pz())); if (cutTauEvent.useThresholdsPID) { @@ -1182,7 +1207,7 @@ struct UpcTauRl { histos.get(HIST("Events/hChannels"))->Fill(CH_EMUPI); if (isTwoSelectedTracks && doTwoTracks) { - TLorentzVector mother, daug[2], motherOfPions, pion[2], motherOfMuons, muon[2]; + ROOT::Math::LorentzVector> mother, daug[2], motherOfPions, pion[2], motherOfMuons, muon[2]; const auto& trkDaug1 = reconstructedBarrelTracks.iteratorAt(cutTauEvent.useThresholdsPID ? vecPVnewPIDidx[0] : vecPVidx[0]); const auto& trkDaug2 = reconstructedBarrelTracks.iteratorAt(cutTauEvent.useThresholdsPID ? vecPVnewPIDidx[1] : vecPVidx[1]); daug[0].SetPxPyPzE(trkDaug1.px(), trkDaug1.py(), trkDaug1.pz(), energy(pdg->Mass(trackPDG(trkDaug1, cutPID.cutSiTPC, cutPID.cutSiTOF, cutPID.usePIDwTOF, cutPID.useScutTOFinTPC)), trkDaug1.px(), trkDaug1.py(), trkDaug1.pz())); @@ -1290,7 +1315,7 @@ struct UpcTauRl { const auto& mupionP = (cutTauEvent.useThresholdsPID ? isElectronCandidate(trkDaug1) : enumMyParticle(trackPDG(trkDaug1, cutPID.cutSiTPC, cutPID.cutSiTOF, cutPID.usePIDwTOF, cutPID.useScutTOFinTPC)) == P_ELECTRON) ? daug[1].P() : daug[0].P(); const auto& mupionE = (cutTauEvent.useThresholdsPID ? isElectronCandidate(trkDaug1) : enumMyParticle(trackPDG(trkDaug1, cutPID.cutSiTPC, cutPID.cutSiTOF, cutPID.usePIDwTOF, cutPID.useScutTOFinTPC)) == P_ELECTRON) ? daug[1].E() : daug[0].E(); - TLorentzVector motherOfPiKaon, kaon; + ROOT::Math::LorentzVector> motherOfPiKaon, kaon; if (isElectronCandidate(trkDaug1)) { kaon.SetPxPyPzE(trkDaug1.px(), trkDaug1.py(), trkDaug1.pz(), energy(MassKaonCharged, trkDaug1.px(), trkDaug1.py(), trkDaug1.pz())); motherOfPiKaon = kaon + daug[1]; @@ -1604,7 +1629,7 @@ struct UpcTauRl { } // Loop over tracks with selections if (countPVGT == 2 && doTwoTracks) { - TLorentzVector daug[2], pion[2], muon[2]; + ROOT::Math::LorentzVector> daug[2]; const auto& trkDaug1 = reconstructedBarrelTracks.iteratorAt(vecPVnoPIDidx[0]); const auto& trkDaug2 = reconstructedBarrelTracks.iteratorAt(vecPVnoPIDidx[1]); daug[0].SetPxPyPzE(trkDaug1.px(), trkDaug1.py(), trkDaug1.pz(), energy(pdg->Mass(trackPDG(trkDaug1, cutPID.cutSiTPC, cutPID.cutSiTOF, cutPID.usePIDwTOF, cutPID.useScutTOFinTPC)), trkDaug1.px(), trkDaug1.py(), trkDaug1.pz())); @@ -1645,7 +1670,7 @@ struct UpcTauRl { bool isElEl = (cutTauEvent.useThresholdsPID ? countPVGTelectronsAlt == 2 : countPVGTelectrons == 2); bool isElMuPion = (cutTauEvent.useThresholdsPID ? (countPVGTelectronsAlt == 1 && countPVGTmupionsAlt == 1) : ((countPVGTelectrons == 1 && countPVGTmuons == 1) || (countPVGTelectrons == 1 && countPVGTpions == 1))); if (isTwoSelectedTracks && doTwoTracks) { - TLorentzVector daug[2], pion[2], muon[2]; + ROOT::Math::LorentzVector> daug[2], pion[2], muon[2]; const auto& trkDaug1 = reconstructedBarrelTracks.iteratorAt(cutTauEvent.useThresholdsPID ? vecPVnewPIDidx[0] : vecPVidx[0]); const auto& trkDaug2 = reconstructedBarrelTracks.iteratorAt(cutTauEvent.useThresholdsPID ? vecPVnewPIDidx[1] : vecPVidx[1]); daug[0].SetPxPyPzE(trkDaug1.px(), trkDaug1.py(), trkDaug1.pz(), energy(pdg->Mass(trackPDG(trkDaug1, cutPID.cutSiTPC, cutPID.cutSiTOF, cutPID.usePIDwTOF, cutPID.useScutTOFinTPC)), trkDaug1.px(), trkDaug1.py(), trkDaug1.pz())); @@ -1844,7 +1869,7 @@ struct UpcTauRl { bool isElEl = (cutTauEvent.useThresholdsPID ? countPVGTelectronsAlt == 2 : countPVGTelectrons == 2); bool isElMuPion = (cutTauEvent.useThresholdsPID ? (countPVGTelectronsAlt == 1 && countPVGTmupionsAlt == 1) : ((countPVGTelectrons == 1 && countPVGTmuons == 1) || (countPVGTelectrons == 1 && countPVGTpions == 1))); if (isTwoSelectedTracks && doTwoTracks) { - TLorentzVector daug[2]; + ROOT::Math::LorentzVector> daug[2]; const auto& trkDaug1 = reconstructedBarrelTracks.iteratorAt(cutTauEvent.useThresholdsPID ? vecPVnewPIDidx[0] : vecPVidx[0]); const auto& trkDaug2 = reconstructedBarrelTracks.iteratorAt(cutTauEvent.useThresholdsPID ? vecPVnewPIDidx[1] : vecPVidx[1]); daug[0].SetPxPyPzE(trkDaug1.px(), trkDaug1.py(), trkDaug1.pz(), energy(pdg->Mass(trackPDG(trkDaug1, cutPID.cutSiTPC, cutPID.cutSiTOF, cutPID.usePIDwTOF, cutPID.useScutTOFinTPC)), trkDaug1.px(), trkDaug1.py(), trkDaug1.pz())); From 7f127f5b9c48d9694198557cb6c78bf83bb71ab3 Mon Sep 17 00:00:00 2001 From: abilandz Date: Mon, 23 Jun 2025 16:16:54 +0200 Subject: [PATCH 188/871] =?UTF-8?q?[PWGCF]=20-=20added=206=20differential?= =?UTF-8?q?=20RCT=20flags=20which=20are=20used=20to=20define=20the=20combi?= =?UTF-8?q?ne=E2=80=A6=20(#11727)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Core/MuPa-Configurables.h | 88 +- .../Core/MuPa-DataMembers.h | 91 +- .../Core/MuPa-Enums.h | 65 +- .../Core/MuPa-MemberFunctions.h | 4617 +++++++++++++---- .../Tasks/multiparticle-correlations-ab.cxx | 36 +- 5 files changed, 3730 insertions(+), 1167 deletions(-) diff --git a/PWGCF/MultiparticleCorrelations/Core/MuPa-Configurables.h b/PWGCF/MultiparticleCorrelations/Core/MuPa-Configurables.h index 95d24fa9a47..dcb18ff5dc2 100644 --- a/PWGCF/MultiparticleCorrelations/Core/MuPa-Configurables.h +++ b/PWGCF/MultiparticleCorrelations/Core/MuPa-Configurables.h @@ -46,6 +46,7 @@ struct : ConfigurableGroup { Configurable cfUseSetBinLabel{"cfUseSetBinLabel", false, "until hist->SetBinLabel(...) large memory consumption is resolved, for each histogram dump all that info in the y-axis title. See also local executable PostprocessLabels.C, where I do the final bin labeling offline"}; Configurable cfUseClone{"cfUseClone", false, "until hist->Clone(...) large memory consumption is resolved, do not use cloning. See ROOT Forum thread."}; Configurable cfUseFormula{"cfUseFormula", false, "until TFormula large memory consumption is resolved, do not use this class. See ROOT Forum thread."}; + Configurable cfUseDatabasePDG{"cfUseDatabasePDG", false, "When enabled, there is a standard memory blow-up."}; } cf_tc; // *) QA: @@ -77,7 +78,7 @@ struct : ConfigurableGroup { // *) Event cuts: struct : ConfigurableGroup { - Configurable> cfUseEventCuts{"cfUseEventCuts", {"1-NumberOfEvents", "1-TotalMultiplicity", "1-Multiplicity", "1-ReferenceMultiplicity", "1-Centrality", "1-VertexX", "1-VertexY", "1-VertexZ", "1-NContributors", "1-ImpactParameter", "0-EventPlaneAngle", "1-Occupancy", "1-InteractionRate", "1-CurrentRunDuration", "0-MultMCNParticlesEta08", "0-Trigger", "0-Sel7", "1-Sel8", "1-MultiplicityEstimator", "1-ReferenceMultiplicityEstimator", "1-CentralityEstimator", "1-SelectedEvents", "1-NoSameBunchPileup", "1-IsGoodZvtxFT0vsPV", "1-IsVertexITSTPC", "1-IsVertexTOFmatched", "1-IsVertexTRDmatched", "0-NoCollInTimeRangeStrict", "0-NoCollInTimeRangeStandard", "0-NoCollInRofStrict", "0-NoCollInRofStandard", "0-NoHighMultCollInPrevRof", "0-IsGoodITSLayer3", "0-IsGoodITSLayer0123", "0-IsGoodITSLayersAll", "1-OccupancyEstimator", "1-MinVertexDistanceFromIP", "0-NoPileupTPC", "0-NoPileupFromSPD", "0-NoSPDOnVsOfPileup", "1-RefMultVsNContrUp", "1-RefMultVsNContrLow", "1-CentralityCorrelationsCut", "1-CentralityWeights"}, "use (1) or do not use (0) event cuts"}; + Configurable> cfUseEventCuts{"cfUseEventCuts", {"1-NumberOfEvents", "1-TotalMultiplicity", "1-Multiplicity", "1-ReferenceMultiplicity", "1-Centrality", "1-VertexX", "1-VertexY", "1-VertexZ", "1-NContributors", "1-ImpactParameter", "0-EventPlaneAngle", "1-Occupancy", "1-InteractionRate", "1-CurrentRunDuration", "0-MultMCNParticlesEta08", "0-Trigger", "0-Sel7", "1-Sel8", "1-MultiplicityEstimator", "1-ReferenceMultiplicityEstimator", "1-CentralityEstimator", "1-SelectedEvents", "1-NoSameBunchPileup", "1-IsGoodZvtxFT0vsPV", "1-IsVertexITSTPC", "1-IsVertexTOFmatched", "1-IsVertexTRDmatched", "0-NoCollInTimeRangeStrict", "0-NoCollInTimeRangeStandard", "0-NoCollInRofStrict", "0-NoCollInRofStandard", "0-NoHighMultCollInPrevRof", "0-IsGoodITSLayer3", "0-IsGoodITSLayer0123", "0-IsGoodITSLayersAll", "1-OccupancyEstimator", "1-MinVertexDistanceFromIP", "0-NoPileupTPC", "0-NoPileupFromSPD", "0-NoSPDOnVsOfPileup", "1-RefMultVsNContrUp", "1-RefMultVsNContrLow", "1-CentralityCorrelationsCut", "0-FT0Bad", "0-ITSBad", "0-ITSLimAccMCRepr", "0-TPCBadTracking", "0-TPCLimAccMCRepr", "0-TPCBadPID", "1-CentralityWeights"}, "use (1) or do not use (0) event cuts"}; Configurable cfUseEventCutCounterAbsolute{"cfUseEventCutCounterAbsolute", false, "profile and save how many times each event cut counter triggered (absolute). Use with care, as this is computationally heavy"}; Configurable cfUseEventCutCounterSequential{"cfUseEventCutCounterSequential", false, "profile and save how many times each event cut counter triggered (sequential). Use with care, as this is computationally heavy"}; Configurable cfPrintCutCounterContent{"cfPrintCutCounterContent", false, "if true, prints on the screen after each event the content of fEventCutCounterHist[*][*] (all which were booked)"}; @@ -128,7 +129,12 @@ struct : ConfigurableGroup { Configurable cfCentralityCorrelationsCut{"cfCentralityCorrelationsCut", "CentFT0C_CentFT0M", "Indicate two centrality estimators for the calculation of centrality correlation cut"}; Configurable cfCentralityCorrelationsCutTreshold{"cfCentralityCorrelationsCutTreshold", 10.0, "set the treshold for centrality correlation cut"}; Configurable cfCentralityCorrelationsCutVersion{"cfCentralityCorrelationsCutVersion", "Absolute", "set the version of centrality correlation cut. Supported: \"Relative\" and \"Absolute\""}; - + Configurable cfUseFT0Bad{"cfUseFT0Bad", false, "TBI 20250516 explanation (or see enum)"}; + Configurable cfUseITSBad{"cfUseITSBad", false, "TBI 20250516 explanation (or see enum)"}; + Configurable cfUseITSLimAccMCRepr{"cfUseITSLimAccMCRepr", false, "TBI 20250516 explanation (or see enum)"}; + Configurable cfUseTPCBadTracking{"cfUseTPCBadTracking", false, "TBI 20250516 explanation (or see enum)"}; + Configurable cfUseTPCLimAccMCRepr{"cfUseTPCLimAccMCRepr", false, "TBI 20250516 explanation (or see enum)"}; + Configurable cfUseTPCBadPID{"cfUseTPCBadPID", false, "TBI 20250516 explanation (or see enum)"}; } cf_ec; // *) Particle histograms: @@ -185,29 +191,24 @@ struct : ConfigurableGroup { // *) Multiparticle correlations: struct : ConfigurableGroup { Configurable cfCalculateCorrelations{"cfCalculateCorrelations", false, "calculate or not multiparticle correlations"}; - Configurable cfCalculateCorrelationsAsFunctionOfIntegrated{"cfCalculateCorrelationsAsFunctionOfIntegrated", true, "calculate or not correlations as a function of integrated"}; - Configurable cfCalculateCorrelationsAsFunctionOfMultiplicity{"cfCalculateCorrelationsAsFunctionOfMultiplicity", true, "calculate or not correlations as a function of multiplicity"}; - Configurable cfCalculateCorrelationsAsFunctionOfCentrality{"cfCalculateCorrelationsAsFunctionOfCentrality", true, "calculate or not correlations as a function of centrality"}; - Configurable cfCalculateCorrelationsAsFunctionOfPt{"cfCalculateCorrelationsAsFunctionOfPt", false, "calculate or not correlations as a function of pt"}; - Configurable cfCalculateCorrelationsAsFunctionOfEta{"cfCalculateCorrelationsAsFunctionOfEta", false, "calculate or not correlations as a function of eta"}; - Configurable cfCalculateCorrelationsAsFunctionOfOccupancy{"cfCalculateCorrelationsAsFunctionOfOccupancy", true, "calculate or not correlations as a function of occupancy"}; - Configurable cfCalculateCorrelationsAsFunctionOfInteractionRate{"cfCalculateCorrelationsAsFunctionOfInteractionRate", true, "calculate or not correlations as a function of interaction rate"}; - Configurable cfCalculateCorrelationsAsFunctionOfCurrentRunDuration{"cfCalculateCorrelationsAsFunctionOfCurrentRunDuration", true, "calculate or not correlations as a function of current run duration (i.e. vs. seconds since start of run)"}; - Configurable cfCalculateCorrelationsAsFunctionOfVz{"cfCalculateCorrelationsAsFunctionOfVz", true, "calculate or not correlations as a function of vertex z position"}; + Configurable> cfCalculateCorrelationsAsFunctionOf{"cfCalculateCorrelationsAsFunctionOf", {"1-Integrated", "1-Multiplicity", "1-Centrality", "1-Pt", "1-Eta", "1-Occupancy", "1-InteractionRate", "1-CurrentRunDuration", "1-Vz", "1-Charge"}, "calculate or not correlations as a function of specified variable"}; } cf_mupa; // *) Test0: struct : ConfigurableGroup { + + // 1D: Configurable cfCalculateTest0{"cfCalculateTest0", false, "calculate or not Test0"}; - Configurable cfCalculateTest0AsFunctionOfIntegrated{"cfCalculateTest0AsFunctionOfIntegrated", false, "calculate or not Test0 as a function of integrated"}; - Configurable cfCalculateTest0AsFunctionOfMultiplicity{"cfCalculateTest0AsFunctionOfMultiplicity", false, "calculate or not Test0 as a function of multiplicity"}; - Configurable cfCalculateTest0AsFunctionOfCentrality{"cfCalculateTest0AsFunctionOfCentrality", false, "calculate or not Test0 as a function of centrality"}; - Configurable cfCalculateTest0AsFunctionOfPt{"cfCalculateTest0AsFunctionOfPt", false, "calculate or not Test0 as a function of pt"}; - Configurable cfCalculateTest0AsFunctionOfEta{"cfCalculateTest0AsFunctionOfEta", false, "calculate or not Test0 as a function of eta"}; - Configurable cfCalculateTest0AsFunctionOfOccupancy{"cfCalculateTest0AsFunctionOfOccupancy", false, "calculate or not Test0 as a function of occupancy"}; - Configurable cfCalculateTest0AsFunctionOfInteractionRate{"cfCalculateTest0AsFunctionOfInteractionRate", false, "calculate or not Test0 as a function of interaction rate"}; - Configurable cfCalculateTest0AsFunctionOfCurrentRunDuration{"cfCalculateTest0AsFunctionOfCurrentRunDuration", false, "calculate or not Test0 as a function of current run duration (i.e. vs. seconds since start of run)"}; - Configurable cfCalculateTest0AsFunctionOfVz{"cfCalculateTest0AsFunctionOfVz", false, "calculate or not Test0 as a function of vertex z position"}; + Configurable> cfCalculateTest0AsFunctionOf{"cfCalculateTest0AsFunctionOf", {"1-Integrated", "1-Multiplicity", "1-Centrality", "1-Pt", "1-Eta", "1-Occupancy", "1-InteractionRate", "1-CurrentRunDuration", "1-Vz", "1-Charge"}, "calculate or not correlations as a function of specified variable"}; + + // 2D: + Configurable cfCalculate2DTest0{"cfCalculate2DTest0", false, "calculate or not 2D Test0 using TProfile2D"}; + Configurable> cfCalculate2DTest0AsFunctionOf{"cfCalculate2DTest0AsFunctionOf", {"1-Centrality_Pt", "1-Centrality_Eta", "1-Centrality_Charge", "1-Centrality_Vz", "1-Pt_Eta", "1-Pt_Charge", "1-Eta_Charge"}, "calculate or not correlations in 2D as a function of two specified variables."}; + + // 3D: + Configurable cfCalculate3DTest0{"cfCalculate3DTest0", false, "calculate or not 3D Test0 using TProfile3D"}; + Configurable> cfCalculate3DTest0AsFunctionOf{"cfCalculate3DTest0AsFunctionOf", {"1-Centrality_Pt_Eta", "1-Centrality_Pt_Charge", "1-Centrality_Pt_Vz", "1-Centrality_Eta_Vz", "1-Centrality_Eta_Charge", "1-Centrality_Vz_Charge"}, "calculate or not correlations in 3D as a function of three specified variables."}; + Configurable cfFileWithLabels{"cfFileWithLabels", "/home/abilandz/DatasetsO2/labels.root", "path to external ROOT file which specifies all labels"}; // for AliEn file prepend "/alice/cern.ch/", for CCDB prepend "/alice-ccdb.cern.ch" Configurable cfUseDefaultLabels{"cfUseDefaultLabels", false, "use default internally hardwired labels, only for testing purposes"}; Configurable cfWhichDefaultLabels{"cfWhichDefaultLabels", "standard", "only for testing purposes, select one set of default labels, see GetDefaultObjArrayWithLabels for supported options"}; @@ -216,15 +217,7 @@ struct : ConfigurableGroup { // *) Eta separation: struct : ConfigurableGroup { Configurable cfCalculateEtaSeparations{"cfCalculateEtaSeparations", false, "calculate or not 2p corr. vs. eta separations"}; - Configurable cfCalculateEtaSeparationsAsFunctionOfIntegrated{"cfCalculateEtaSeparationsAsFunctionOfIntegrated", false, "calculate or not 2p corr. vs. eta separations ..."}; - Configurable cfCalculateEtaSeparationsAsFunctionOfMultiplicity{"cfCalculateEtaSeparationsAsFunctionOfMultiplicity", false, "calculate or not 2p corr. vs. eta separations as a function of multiplicity"}; - Configurable cfCalculateEtaSeparationsAsFunctionOfCentrality{"cfCalculateEtaSeparationsAsFunctionOfCentrality", false, "calculate or not 2p corr. vs. eta separations as a function of centrality"}; - Configurable cfCalculateEtaSeparationsAsFunctionOfPt{"cfCalculateEtaSeparationsAsFunctionOfPt", false, "calculate or not 2p corr. vs. eta separations as a function of pt"}; - // Configurable cfCalculateEtaSeparationsAsFunctionOfEta{"cfCalculateEtaSeparationsAsFunctionOfEta", false, "this one doesn't make sense in this context"}; - Configurable cfCalculateEtaSeparationsAsFunctionOfOccupancy{"cfCalculateEtaSeparationsAsFunctionOfOccupancy", false, "calculate or not 2p corr. vs. eta separations as a function of occupancy"}; - Configurable cfCalculateEtaSeparationsAsFunctionOfInteractionRate{"cfCalculateEtaSeparationsAsFunctionOfInteractionRate", false, "calculate or not 2p corr. vs. eta separations as a function of interaction rate"}; - Configurable cfCalculateEtaSeparationsAsFunctionOfCurrentRunDuration{"cfCalculateEtaSeparationsAsFunctionOfCurrentRunDuration", false, "calculate or not 2p corr. vs. eta separations as a function of current run duration (i.e. vs. seconds since start of run)"}; - Configurable cfCalculateEtaSeparationsAsFunctionOfVz{"cfCalculateEtaSeparationsAsFunctionOfVz", false, "calculate or not 2p corr. vs. eta separations as a function of vertex z position"}; + Configurable> cfCalculateEtaSeparationsAsFunctionOf{"cfCalculateEtaSeparationsAsFunctionOf", {"1-Integrated", "1-Multiplicity", "1-Centrality", "1-Pt", "0-Eta", "1-Occupancy", "1-InteractionRate", "1-CurrentRunDuration", "1-Vz", "1-Charge"}, "calculate or not correlations as a function of specified variable"}; Configurable> cfEtaSeparationsValues{"cfEtaSeparationsValues", {0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8}, "Eta separation between interval A (-eta) and B (+eta)"}; Configurable> cfEtaSeparationsSkipHarmonics{"cfEtaSeparationsSkipHarmonics", {"0-v1", "0-v2", "0-v3", "0-v4", "1-v5", "1-v6", "1-v7", "1-v8", "1-v9"}, "For calculation of 2p correlation with eta separation these harmonics will be skipped (if first flag = \"0-v1\", v1 will be NOT be skipped in the calculus of 2p correlations with eta separations, etc.)"}; } cf_es; @@ -237,8 +230,8 @@ struct : ConfigurableGroup { Configurable cfUseDiffPhiPtWeights{"cfUseDiffPhiPtWeights", false, "use or not differential phi(pt) weights"}; Configurable cfUseDiffPhiEtaWeights{"cfUseDiffPhiEtaWeights", false, "use or not differential phi(eta) weights"}; Configurable> cfWhichDiffPhiWeights{"cfWhichDiffPhiWeights", {"1-wPhi", "1-wPt", "1-wEta", "1-wCharge", "1-wCentrality", "1-wVertexZ"}, "use (1) or do not use (0) differential phi weight for particular dimension. If only phi is set to 1, integrated phi weights are used. If phi is set to 0, ALL dimensions are switched off (yes!)"}; - Configurable> cfWhichDiffPtWeights{"cfWhichDiffPtWeights", {"1-wPt"}, "use (1) or do not use (0) differential pt weight for particular dimension. If only pt is set to 1, integrated pt weights are used. If pt is set to 0, ALL dimensions are switched off (yes!)"}; - Configurable> cfWhichDiffEtaWeights{"cfWhichDiffEtaWeights", {"1-wEta"}, "use (1) or do not use (0) differential eta weight for particular dimension. If only eta is set to 1, integrated eta weights are used. If eta is set to 0, ALL dimensions are switched off (yes!)"}; + Configurable> cfWhichDiffPtWeights{"cfWhichDiffPtWeights", {"1-wPt", "1-wCharge", "1-wCentrality"}, "use (1) or do not use (0) differential pt weight for particular dimension. If only pt is set to 1, integrated pt weights are used. If pt is set to 0, ALL dimensions are switched off (yes!)"}; + Configurable> cfWhichDiffEtaWeights{"cfWhichDiffEtaWeights", {"1-wEta", "1-wCharge", "1-wCentrality"}, "use (1) or do not use (0) differential eta weight for particular dimension. If only eta is set to 1, integrated eta weights are used. If eta is set to 0, ALL dimensions are switched off (yes!)"}; Configurable cfFileWithWeights{"cfFileWithWeights", "/home/abilandz/DatasetsO2/weights.root", "path to external ROOT file which holds all particle weights in O2 format"}; // for AliEn file prepend "/alice/cern.ch/", for CCDB prepend "/alice-ccdb.cern.ch" } cf_pw; @@ -271,6 +264,7 @@ struct : ConfigurableGroup { Configurable cfnEventsInternalValidation{"cfnEventsInternalValidation", 0, "number of events simulated on-the-fly for internal validation"}; Configurable cfHarmonicsOptionInternalValidation{"cfHarmonicsOptionInternalValidation", "constant", "for internal validation, supported options are \"constant\", \"correlated\" and \"persistent\""}; Configurable cfRescaleWithTheoreticalInput{"cfRescaleWithTheoreticalInput", false, "if kTRUE, all correlators are rescaled with theoretical input, so that all results in profiles are 1"}; + Configurable cfRandomizeReactionPlane{"cfRandomizeReactionPlane", true, "set to false only when validating against theoretical value the non-isotropic correlators"}; Configurable> cfInternalValidationAmplitudes{"cfInternalValidationAmplitudes", {0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.07, 0.08, 0.09}, "{v1, v2, v3, v4, ...} + has an effect only in combination with cfHarmonicsOptionInternalValidation = \"constant\". Max number of vn's is gMaxHarmonic."}; Configurable> cfInternalValidationPlanes{"cfInternalValidationPlanes", {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, "{Psi1, Psi2, Psi3, Psi4, ...} + has an effect only in combination with cfHarmonicsOptionInternalValidation = \"constant\". Max number of Psin's is gMaxHarmonic."}; Configurable> cfMultRangeInternalValidation{"cfMultRangeInternalValidation", {1000, 1001}, "{min, max}, with convention: min <= M < max"}; @@ -281,32 +275,32 @@ struct : ConfigurableGroup { Configurable cfSaveResultsHistograms{"cfSaveResultsHistograms", false, "save or not results histograms"}; // Fixed-length binning (default): - Configurable> cfFixedLengthMultBins{"cfFixedLengthMultBins", {2000, 0., 20000.}, "nMultBins, multMin, multMax (only for results histograms)"}; - Configurable> cfFixedLengthCentBins{"cfFixedLengthCentBins", {110, 0., 110.}, "nCentBins, centMin, centMax (only for results histograms)"}; - Configurable> cfFixedLengthPtBins{"cfFixedLengthPtBins", {1000, 0., 10.}, "nPtBins, ptMin, ptMax (only for results histograms)"}; - Configurable> cfFixedLengthEtaBins{"cfFixedLengthEtaBins", {80, -2., 2.}, "nEtaBins, etaMin, etaMax (only for results histograms)"}; - Configurable> cfFixedLengthOccuBins{"cfFixedLengthOccuBins", {200, 0., 60000.}, "nOccuBins, occuMin, occuMax (only for results histograms)"}; - Configurable> cfFixedLengthIRBins{"cfFixedLengthIRBins", {1000, 0., 100.}, "nirBins, irMin, irMax (only for results histograms)"}; - Configurable> cfFixedLengthCRDBins{"cfFixedLengthCRDBins", {100000, 0., 100000.}, "ncrdBins, crdMin, crdMax (only for results histograms)"}; - Configurable> cfFixedLengthVzBins{"cfFixedLengthVzBins", {400, -20., 20.}, "nvzBins, vzMin, vzMax (only for results histograms)"}; + Configurable> cfFixedLengthMultBins{"cfFixedLengthMultBins", {2000, 0., 20000.}, "nMultBins, multMin, multMax (only for results histograms)"}; + Configurable> cfFixedLengthCentBins{"cfFixedLengthCentBins", {110, 0., 110.}, "nCentBins, centMin, centMax (only for results histograms)"}; + Configurable> cfFixedLengthPtBins{"cfFixedLengthPtBins", {1000, 0., 10.}, "nPtBins, ptMin, ptMax (only for results histograms)"}; + Configurable> cfFixedLengthEtaBins{"cfFixedLengthEtaBins", {80, -2., 2.}, "nEtaBins, etaMin, etaMax (only for results histograms)"}; + Configurable> cfFixedLengthOccuBins{"cfFixedLengthOccuBins", {200, 0., 60000.}, "nOccuBins, occuMin, occuMax (only for results histograms)"}; + Configurable> cfFixedLengthIRBins{"cfFixedLengthIRBins", {1000, 0., 100.}, "nirBins, irMin, irMax (only for results histograms)"}; + Configurable> cfFixedLengthCRDBins{"cfFixedLengthCRDBins", {100000, 0., 100000.}, "ncrdBins, crdMin, crdMax (only for results histograms)"}; + Configurable> cfFixedLengthVzBins{"cfFixedLengthVzBins", {400, -20., 20.}, "nvzBins, vzMin, vzMax (only for results histograms)"}; // Variable-length binning (per request): Configurable cfUseVariableLengthMultBins{"cfUseVariableLengthMultBins", false, "use or not variable-length multiplicity bins"}; - Configurable> cfVariableLengthMultBins{"cfVariableLengthMultBins", {0., 5., 6., 7., 8., 9., 100., 200., 500., 1000., 10000.}, "variable-length multiplicity bins"}; + Configurable> cfVariableLengthMultBins{"cfVariableLengthMultBins", {0., 5., 6., 7., 8., 9., 100., 200., 500., 1000., 10000.}, "variable-length multiplicity bins"}; Configurable cfUseVariableLengthCentBins{"cfUseVariableLengthCentBins", false, "use or not variable-length centrality bins"}; - Configurable> cfVariableLengthCentBins{"cfVariableLengthCentBins", {0., 10., 50., 100.}, "variable-length centrality bins"}; + Configurable> cfVariableLengthCentBins{"cfVariableLengthCentBins", {0., 10., 50., 100.}, "variable-length centrality bins"}; Configurable cfUseVariableLengthPtBins{"cfUseVariableLengthPtBins", true, "use or not variable-length pt bins"}; - Configurable> cfVariableLengthPtBins{"cfVariableLengthPtBins", {0.20, 0.25, 0.30, 0.35, 0.40, 0.50, 0.60, 0.80, 1.00, 1.25, 1.50, 1.75, 2.00, 2.50, 3.00, 4.00, 5.00}, "variable-length pt bins"}; + Configurable> cfVariableLengthPtBins{"cfVariableLengthPtBins", {0.20, 0.25, 0.30, 0.35, 0.40, 0.50, 0.60, 0.80, 1.00, 1.25, 1.50, 1.75, 2.00, 2.50, 3.00, 4.00, 5.00}, "variable-length pt bins"}; Configurable cfUseVariableLengthEtaBins{"cfUseVariableLengthEtaBins", true, "use or not variable-length eta bins"}; - Configurable> cfVariableLengthEtaBins{"cfVariableLengthEtaBins", {-0.8, -0.6, -0.4, -0.3, -0.2, -0.1, 0.0, 0.1, 0.2, 0.3, 0.4, 0.6, 0.8}, "variable-length eta bins"}; + Configurable> cfVariableLengthEtaBins{"cfVariableLengthEtaBins", {-0.8, -0.6, -0.4, -0.3, -0.2, -0.1, 0.0, 0.1, 0.2, 0.3, 0.4, 0.6, 0.8}, "variable-length eta bins"}; Configurable cfUseVariableLengthOccuBins{"cfUseVariableLengthOccuBins", false, "use or not variable-length occupancy bins"}; - Configurable> cfVariableLengthOccuBins{"cfVariableLengthOccuBins", {0., 5., 6., 7., 8., 9., 100., 200., 500., 1000., 10000.}, "variable-length occupancy bins"}; + Configurable> cfVariableLengthOccuBins{"cfVariableLengthOccuBins", {0., 5., 6., 7., 8., 9., 100., 200., 500., 1000., 10000.}, "variable-length occupancy bins"}; Configurable cfUseVariableLengthIRBins{"cfUseVariableLengthIRBins", false, "use or not variable-length interaction rate bins"}; - Configurable> cfVariableLengthIRBins{"cfVariableLengthIRBins", {0., 5., 10., 50., 100., 200.}, "variable-length ineraction rate bins"}; + Configurable> cfVariableLengthIRBins{"cfVariableLengthIRBins", {0., 5., 10., 50., 100., 200.}, "variable-length ineraction rate bins"}; Configurable cfUseVariableLengthCRDBins{"cfUseVariableLengthCRDBins", false, "use or not variable-length current run duration bins"}; - Configurable> cfVariableLengthCRDBins{"cfVariableLengthCRDBins", {0., 5., 10., 50., 100., 500.}, "variable-length current run duration bins"}; + Configurable> cfVariableLengthCRDBins{"cfVariableLengthCRDBins", {0., 5., 10., 50., 100., 500.}, "variable-length current run duration bins"}; Configurable cfUseVariableLengthVzBins{"cfUseVariableLengthVzBins", false, "use or not variable-length vertex z bins"}; - Configurable> cfVariableLengthVzBins{"cfVariableLengthVzBins", {-10., -8., -6., -4, -2., -1., 0., 1., 2., 4., 6., 8., 10.}, "variable-length vertex z bins"}; + Configurable> cfVariableLengthVzBins{"cfVariableLengthVzBins", {-10., -8., -6., -4, -2., -1., 0., 1., 2., 4., 6., 8., 10.}, "variable-length vertex z bins"}; } cf_res; diff --git a/PWGCF/MultiparticleCorrelations/Core/MuPa-DataMembers.h b/PWGCF/MultiparticleCorrelations/Core/MuPa-DataMembers.h index a603d614a24..87b5e1c9f4b 100644 --- a/PWGCF/MultiparticleCorrelations/Core/MuPa-DataMembers.h +++ b/PWGCF/MultiparticleCorrelations/Core/MuPa-DataMembers.h @@ -16,6 +16,8 @@ #ifndef PWGCF_MULTIPARTICLECORRELATIONS_CORE_MUPA_DATAMEMBERS_H_ #define PWGCF_MULTIPARTICLECORRELATIONS_CORE_MUPA_DATAMEMBERS_H_ +#include + // General remarks: // 0. Starting with C++11, it's possible to initialize data members at declaration, so I do it here // 1. Use //!SetBinLabel(...), see ROOT Forum // See also local executable PostprocessLabels.C bool fUseClone = false; // until Clone(...) large memory consumption is resolved, do not use hist->Clone(...), see ROOT Forum bool fUseFormula = false; // until TFormula large memory consumption is resolved, do not use, see ROOT Forum + bool fUseDatabasePDG = false; // I use it at the moment only to retreive charge for MC particle from its PDG code, because there is no direct getter mcParticle.sign() + // But most likely I will use it to retrieve other particle proprties from PDG table. There is a standard memoty blow-up when used. } tc; // "tc" labels an instance of this group of variables. // *) Event-by-event quantities: @@ -254,20 +259,34 @@ struct ParticleCuts { // *) Q-vectors: struct Qvector { - TList* fQvectorList = NULL; // list to hold all Q-vector objects - TProfile* fQvectorFlagsPro = NULL; // profile to hold all flags for Q-vector - bool fCalculateQvectors = true; // to calculate or not to calculate Q-vectors, that's a Boolean... - // Does NOT apply to Qa, Qb, etc., vectors, needed for eta separ. - TComplex fQ[gMaxHarmonic * gMaxCorrelator + 1][gMaxCorrelator + 1] = {{TComplex(0., 0.)}}; //! generic Q-vector - TComplex fQvector[gMaxHarmonic * gMaxCorrelator + 1][gMaxCorrelator + 1] = {{TComplex(0., 0.)}}; //! "integrated" Q-vector - TComplex fqvector[eqvectorKine_N][gMaxNoBinsKine][gMaxHarmonic * gMaxCorrelator + 1][gMaxCorrelator + 1] = {{{{TComplex(0., 0.)}}}}; //! "differenttial" q-vector [kine var.][binNo][fMaxHarmonic*fMaxCorrelator+1][fMaxCorrelator+1] = [6*12+1][12+1] - int fqVectorEntries[eqvectorKine_N][gMaxNoBinsKine] = {{0}}; // count number of entries in each differential q-vector - TComplex fQabVector[2][gMaxHarmonic][gMaxNumberEtaSeparations] = {{{TComplex(0., 0.)}}}; //! integrated [-eta or +eta][harmonic][eta separation] - float fMab[2][gMaxNumberEtaSeparations] = {{0.}}; //! multiplicities in 2 eta separated intervals - TH1F* fMabDist[2][2][2][gMaxNumberEtaSeparations] = {{{{NULL}}}}; // multiplicity distributions in A and B, for each eta separation [ A or B ] [rec or sim] [ before or after cuts ] [ eta separation value ] - TComplex fqabVector[2][gMaxNoBinsKine][gMaxHarmonic][gMaxNumberEtaSeparations] = {{{{TComplex(0., 0.)}}}}; //! differential in pt [-eta or +eta][binNo][harmonic][eta separation] - float fmab[2][gMaxNoBinsKine][gMaxNumberEtaSeparations] = {{{0.}}}; //! multiplicities vs pt in 2 eta separated intervals -} qv; // "qv" is a common label for objects in this struct + TList* fQvectorList = NULL; // list to hold all Q-vector objects + TProfile* fQvectorFlagsPro = NULL; // profile to hold all flags for Q-vector + bool fCalculateQvectors = true; // to calculate or not to calculate Q-vectors, that's a Boolean... + // Does NOT apply to Qa, Qb, etc., vectors, needed for eta separ. + TComplex fQ[gMaxHarmonic * gMaxCorrelator + 1][gMaxCorrelator + 1] = {{TComplex(0., 0.)}}; //! generic Q-vector + TComplex fQvector[gMaxHarmonic * gMaxCorrelator + 1][gMaxCorrelator + 1] = {{TComplex(0., 0.)}}; //! "integrated" Q-vector + + bool fCalculateqvectorsKineAny = false; // by default, it's off. It's set to true automatically if any of kine correlators is requested, + // either for Correlations, Test0, EtaSeparations, etc. + bool fCalculateqvectorsKine[eqvectorKine_N] = {false}; // same as above, just specifically for each enum eqvectorKine + applies only to Correlations and Test0 + bool fCalculateqvectorsKineEtaSeparations[eqvectorKine_N] = {false}; // same as above, just specifically for each enum eqvectorKine + applies only to EtaSeparations + + std::vector>>>> fqvector; // dynamically allocated differential q-vector => it has to be done this way, to optimize memory usage + // dimensions: [eqvectorKine_N][gMaxNoBinsKine][gMaxHarmonic * gMaxCorrelator + 1][gMaxCorrelator + 1] + std::vector fNumberOfKineBins = {0}; // for each kine vector which was requested in this analysis, here I calculate and store the corresponding number of kine bins + std::vector> fqvectorEntries; // dynamically allocated number of entries for differential q-vector => it has to be done this way, to optimize memory usage + + // q-vectors for eta separations: + TComplex fQabVector[2][gMaxHarmonic][gMaxNumberEtaSeparations] = {{{TComplex(0., 0.)}}}; //! integrated [-eta or +eta][harmonic][eta separation] + float fMab[2][gMaxNumberEtaSeparations] = {{0.}}; //! multiplicities in 2 eta separated intervals + TH1F* fMabDist[2][2][2][gMaxNumberEtaSeparations] = {{{{NULL}}}}; // multiplicity distributions in A and B, for each eta separation [ A or B ] [rec or sim] [ before or after cuts ] [ eta separation value ] + std::vector>>>>> fqabVector; // dynamically allocated differential q-vector. + // dimensions: [-eta or +eta][eqvectorKine_N][global binNo][harmonic][eta separation] + // Remark: Unlike fqvector above, here I support only 2-p correlations, + // therefore no need for "[gMaxHarmonic * gMaxCorrelator + 1][gMaxCorrelator + 1]", etc. + std::vector>>> fmab; //! multiplicities vs kine in 2 eta separated intervals + // [-eta or +eta][eqvectorKine_N][global binNo][eta separation] +} qv; // "qv" is a common label for objects in this struct // *) Multiparticle correlations (standard, isotropic, same harmonic): struct MultiparticleCorrelations { @@ -326,7 +345,7 @@ struct NestedLoops { //! [2p=0,4p=1,6p=2,8p=3][n=1,n=2,...,n=gMaxHarmonic][0=integrated,1=vs. //! multiplicity,2=vs. centrality,3=pT,4=eta] TArrayD* ftaNestedLoops[2] = {NULL}; //! e-b-e container for nested loops [0=angles;1=product of all weights] - TArrayD* ftaNestedLoopsKine[eqvectorKine_N][gMaxNoBinsKine][2] = {{{NULL}}}; //! e-b-e container for nested loops // [0=pT,1=eta][kine bin][0=angles;1=product of all weights] + TArrayD* ftaNestedLoopsKine[eqvectorKine_N][gMaxNoBinsKine][2] = {{{NULL}}}; //! e-b-e container for nested loops // [0=pT,1=eta,2=...][kine bin][0=angles;1=product of all weights] } nl; // "nl" labels an instance of this group of histograms // *) Toy NUA (can be applied both in real data analysis and in analysis 'on-the-fly', e.g. when running internal validation): @@ -354,22 +373,29 @@ struct InternalValidation { unsigned int fnEventsInternalValidation = 0; // how many on-the-fly events will be sampled for each real event, for internal validation TString* fHarmonicsOptionInternalValidation = NULL; // "constant", "correlated" or "persistent", see .cxx for full documentation bool fRescaleWithTheoreticalInput = false; // if true, all measured correlators are rescaled with theoretical input, so that in profiles everything is at 1 + bool fRandomizeReactionPlane = true; // if true, RP is randomized e-by-e. I need false basically only when validating against theoretical input non-isotropic correlators TArrayD* fInternalValidationVnPsin[2] = {NULL}; // 0 = { v1, v2, ... }, 1 = { Psi1, Psi2, ... } int fMultRangeInternalValidation[2] = {0, 0}; // min and max values for uniform multiplicity distribution in on-the-fly analysis (convention: min <= M < max) } iv; // *) Test0: struct Test0 { - TList* fTest0List = NULL; // list to hold all objects for Test0 - TProfile* fTest0FlagsPro = NULL; // store all flags for Test0 - bool fCalculateTest0 = false; // calculate or not Test0 - TProfile* fTest0Pro[gMaxCorrelator][gMaxIndex][eAsFunctionOf_N] = {{{NULL}}}; //! [order][index][0=integrated,1=vs. multiplicity,2=vs. centrality,3=pT,4=eta] - TString* fTest0Labels[gMaxCorrelator][gMaxIndex] = {{NULL}}; // all labels: k-p'th order is stored in k-1'th index. So yes, I also store 1-p - bool fCalculateTest0AsFunctionOf[eAsFunctionOf_N] = {false}; //! [0=integrated,1=vs. multiplicity,2=vs. centrality,3=pT,4=eta,5=vs. occupancy, ...] - TString fFileWithLabels = ""; // path to external ROOT file which specifies all labels of interest - bool fUseDefaultLabels = false; // use default labels hardwired in GetDefaultObjArrayWithLabels(), the choice is made with cfWhichDefaultLabels - TString fWhichDefaultLabels = ""; // only for testing purposes, select one set of default labels, see GetDefaultObjArrayWithLabels for supported options -} t0; // "t0" labels an instance of this group of histograms + TList* fTest0List = NULL; // list to hold all objects for Test0 + TProfile* fTest0FlagsPro = NULL; // store all flags for Test0 + bool fCalculateTest0 = false; // calculate or not Test0 + TProfile* fTest0Pro[gMaxCorrelator][gMaxIndex][eAsFunctionOf_N] = {{{NULL}}}; //! [order][index][0=integrated,1=vs. multiplicity,2=vs. centrality,3=pT,4=eta] + bool fCalculate2DTest0 = false; // calculate or not 2D Test0 + TProfile2D* fTest0Pro2D[gMaxCorrelator][gMaxIndex][eAsFunctionOf2D_N] = {{{NULL}}}; //! [order][index][0=cent vs pt, ..., see enum eAsFunctionOf2D] + bool fCalculate3DTest0 = false; // calculate or not 2D Test0 + TProfile3D* fTest0Pro3D[gMaxCorrelator][gMaxIndex][eAsFunctionOf3D_N] = {{{NULL}}}; //! [order][index][0=cent vs pt vs eta, ..., see enum eAsFunctionOf3D] + TString* fTest0Labels[gMaxCorrelator][gMaxIndex] = {{NULL}}; // all labels: k-p'th order is stored in k-1'th index. So yes, I also store 1-p + bool fCalculateTest0AsFunctionOf[eAsFunctionOf_N] = {false}; //! [0=integrated,1=vs. multiplicity,2=vs. centrality,3=pT,4=eta,5=vs. occupancy, ...] + bool fCalculate2DTest0AsFunctionOf[eAsFunctionOf2D_N] = {false}; //! [0=integrated,1=vs. multiplicity,2=vs. centrality,3=pT,4=eta,5=vs. occupancy, ...] + bool fCalculate3DTest0AsFunctionOf[eAsFunctionOf3D_N] = {false}; //! [0=integrated,1=vs. multiplicity,2=vs. centrality,3=pT,4=eta,5=vs. occupancy, ...] + TString fFileWithLabels = ""; // path to external ROOT file which specifies all labels of interest + bool fUseDefaultLabels = false; // use default labels hardwired in GetDefaultObjArrayWithLabels(), the choice is made with cfWhichDefaultLabels + TString fWhichDefaultLabels = ""; // only for testing purposes, select one set of default labels, see GetDefaultObjArrayWithLabels for supported options +} t0; // "t0" labels an instance of this group of histograms // *) Eta separations: struct EtaSeparations { @@ -394,19 +420,22 @@ struct GlobalCosmetics { } gc; // *) Results: -struct Results { // This is in addition also sort of "abstract" interface, which defines common binning, etc., for other groups of histograms. - TList* fResultsList = NULL; //!Clone() eUseFormula, // Use or not class TFormula + eUseDatabasePDG, // Use or not class TDatabasePDG eConfiguration_N }; @@ -92,11 +93,13 @@ enum eDefaultColors { eColor = kBlack, enum eWeights { wPHI = 0, wPT = 1, wETA = 2, + wCHARGE = 3, eWeights_N }; enum eDiffWeights { // TBI 20250215 this is now obsolete, superseeded with more general implementation, see enums eDiffWeightCategory, eDiffPhiWeights, etc. wPHIPT = 0, wPHIETA, + wPHICHARGE, eDiffWeights_N }; @@ -120,13 +123,15 @@ enum eDiffPhiWeights { enum eDiffPtWeights { wPtPtAxis = 0, - // ... TBI 20250222 add all other axes on which differential pt weight could have non-trivial dependence, in the same spirit I did it above for phi weights in enum eDiffPhiWeights + wPtChargeAxis, + wPtCentralityAxis, eDiffPtWeights_N }; enum eDiffEtaWeights { wEtaEtaAxis = 0, - // ... TBI 20250222 add all other axes on which differential eta weight could have non-trivial dependence, in the same spirit I did it above for phi weights in enum eDiffPhiWeights + wEtaChargeAxis, + wEtaCentralityAxis, eDiffEtaWeights_N }; @@ -195,6 +200,18 @@ enum eEventCuts { eRefMultVsNContrUp, // formula for upper boundary cut in eReferenceMultiplicity_vs_NContributors (remember that I use naming convention "x_vs_y") eRefMultVsNContrLow, // formula for lower boundary cut in eReferenceMultiplicity_vs_NContributors (remember that I use naming convention "x_vs_y") eCentralityCorrelationsCut, // port of void SetCentralityCorrelationsCuts(...) from MuPa class. Example format: "CentFT0C_CentFT0M", so IFS is "_", until proven otherwise + + // RCT flags, see https://indico.cern.ch/event/1545907/ + up-to-date code in Common/CCDB/RCTSelectionFlags.h + // Remark 1: For the time being, I support here differentially 6 flags used to define the combined "CBT" flag, see if (label == "CBT") in Common/CCDB/RCTSelectionFlags.h + // Remark 2: If I want to use directly the combined "CBT" flag, see how it can be done using RCTFlagsChecker in + // https://github.com/AliceO2Group/O2Physics/blob/master/DPG/Tasks/AOTEvent/timeDependentQa.cxx#L115 + // But check before the memory status after RCTFlagsChecker is used. + eFT0Bad, + eITSBad, + eITSLimAccMCRepr, + eTPCBadTracking, + eTPCLimAccMCRepr, + eTPCBadPID, // ... eCentralityWeights, // used for centrality flattening. Remember that this event cut must be implemented very last, // therefore I have it separately implemented for Run 3,2,1 in EventCuts() at the very end in each case. @@ -296,7 +313,8 @@ enum eParticleCuts { eParticleCuts_N }; -enum eAsFunctionOf { +enum eAsFunctionOf { // this is a specific enum only for 1D dependence + // 1D: AFO_INTEGRATED = 0, AFO_MULTIPLICITY, // vs. default multiplicity, which is (at the moment) fSelectedTracks, i.e. number of tracks in Q-vector AFO_CENTRALITY, // vs. default centrality estimator, see how it's calculated in DetermineCentrality(...) @@ -306,9 +324,37 @@ enum eAsFunctionOf { AFO_INTERACTIONRATE, // vs. "interation rate" AFO_CURRENTRUNDURATION, // vs. "current run duration", i.e. vs "seconds since start of run" AFO_VZ, // vs. "vertex z position" + AFO_CHARGE, // vs. "particle charge" + // ... eAsFunctionOf_N }; // prefix is needed, to avoid conflict with enum eKinematics +enum eAsFunctionOf2D { // this is a specific enum only for 2D dependence + // 2D: + AFO_CENTRALITY_PT = 0, + AFO_CENTRALITY_ETA, + AFO_CENTRALITY_CHARGE, + AFO_CENTRALITY_VZ, + AFO_PT_ETA, + AFO_PT_CHARGE, + AFO_ETA_CHARGE, + // ... + eAsFunctionOf2D_N +}; + +enum eAsFunctionOf3D { // this is a specific enum only for 3D dependence + // 3D: + AFO_CENTRALITY_PT_ETA = 0, + AFO_CENTRALITY_PT_CHARGE, + AFO_CENTRALITY_PT_VZ, + AFO_CENTRALITY_ETA_VZ, + AFO_CENTRALITY_ETA_CHARGE, + AFO_CENTRALITY_VZ_CHARGE, + AFO_PT_ETA_CHARGE, + // ... + eAsFunctionOf3D_N +}; + enum eNUAPDF { ePhiNUAPDF = 0, ePtNUAPDF, @@ -317,8 +363,21 @@ enum eNUAPDF { }; enum eqvectorKine { // Here "kine" originally meant "kinematic", i.e. vs. pt or vs. eta, now it's general. + // 1D: PTq = 0, ETAq, + CHARGEq, + // ... + + // 2D: // Yes, I linearize 2D case, in an analogy with "global bin" structure for multidimensional histograms. + PT_ETAq, + PT_CHARGEq, + ETA_CHARGEq, + // ... + + // 3D: // Yes, I linearize 3D case, in an analogy with "global bin" structure for multidimensional histograms. + PT_ETA_CHARGEq, + // ... eqvectorKine_N }; diff --git a/PWGCF/MultiparticleCorrelations/Core/MuPa-MemberFunctions.h b/PWGCF/MultiparticleCorrelations/Core/MuPa-MemberFunctions.h index dc244873b37..2cae5a686f4 100644 --- a/PWGCF/MultiparticleCorrelations/Core/MuPa-MemberFunctions.h +++ b/PWGCF/MultiparticleCorrelations/Core/MuPa-MemberFunctions.h @@ -125,6 +125,9 @@ void BookBaseList() fBasePro->GetXaxis()->SetBinLabel(eUseFormula, "fUseFormula"); fBasePro->Fill(eUseFormula, static_cast(tc.fUseFormula)); + fBasePro->GetXaxis()->SetBinLabel(eUseDatabasePDG, "fUseDatabasePDG"); + fBasePro->Fill(eUseDatabasePDG, static_cast(tc.fUseDatabasePDG)); + } else { // d) Define bin labels indirectly by storing them in y-axis title + local executable PostprocessLabels.C. @@ -199,6 +202,9 @@ void BookBaseList() yAxisTitle += TString::Format("%d:fUseFormula; ", static_cast(eUseFormula)); fBasePro->Fill(eUseFormula, static_cast(tc.fUseFormula)); + yAxisTitle += TString::Format("%d:fUseDatabasePDG; ", static_cast(eUseDatabasePDG)); + fBasePro->Fill(eUseDatabasePDG, static_cast(tc.fUseDatabasePDG)); + // ... // *) Insanity check on the number of fields in this specially crafted y-axis title: @@ -350,6 +356,7 @@ void DefaultConfiguration() tc.fUseSetBinLabel = cf_tc.cfUseSetBinLabel; tc.fUseClone = cf_tc.cfUseClone; tc.fUseFormula = cf_tc.cfUseFormula; + tc.fUseDatabasePDG = cf_tc.cfUseDatabasePDG; // *) Event histograms (for QA see below): eh.fEventHistogramsName[eNumberOfEvents] = "NumberOfEvents"; @@ -423,6 +430,12 @@ void DefaultConfiguration() ec.fEventCutName[eRefMultVsNContrUp] = "RefMultVsNContrUp"; ec.fEventCutName[eRefMultVsNContrLow] = "RefMultVsNContrLow"; ec.fEventCutName[eCentralityCorrelationsCut] = "CentralityCorrelationsCut"; + ec.fEventCutName[eFT0Bad] = "FT0Bad"; + ec.fEventCutName[eITSBad] = "ITSBad"; + ec.fEventCutName[eITSLimAccMCRepr] = "ITSLimAccMCRepr"; + ec.fEventCutName[eTPCBadTracking] = "TPCBadTracking"; + ec.fEventCutName[eTPCLimAccMCRepr] = "TPCLimAccMCRepr"; + ec.fEventCutName[eTPCBadPID] = "TPCBadPID"; ec.fEventCutName[eCentralityWeights] = "CentralityWeights"; for (int t = 0; t < eEventCuts_N; t++) { if (ec.fEventCutName[t].EqualTo("")) { @@ -507,29 +520,106 @@ void DefaultConfiguration() // *) Multiparticle correlations: mupa.fCalculateCorrelations = cf_mupa.cfCalculateCorrelations; - mupa.fCalculateCorrelationsAsFunctionOf[AFO_INTEGRATED] = cf_mupa.cfCalculateCorrelationsAsFunctionOfIntegrated && mupa.fCalculateCorrelations; - mupa.fCalculateCorrelationsAsFunctionOf[AFO_MULTIPLICITY] = cf_mupa.cfCalculateCorrelationsAsFunctionOfMultiplicity && mupa.fCalculateCorrelations; - mupa.fCalculateCorrelationsAsFunctionOf[AFO_CENTRALITY] = cf_mupa.cfCalculateCorrelationsAsFunctionOfCentrality && mupa.fCalculateCorrelations; - mupa.fCalculateCorrelationsAsFunctionOf[AFO_PT] = cf_mupa.cfCalculateCorrelationsAsFunctionOfPt && mupa.fCalculateCorrelations; - mupa.fCalculateCorrelationsAsFunctionOf[AFO_ETA] = cf_mupa.cfCalculateCorrelationsAsFunctionOfEta && mupa.fCalculateCorrelations; - mupa.fCalculateCorrelationsAsFunctionOf[AFO_OCCUPANCY] = cf_mupa.cfCalculateCorrelationsAsFunctionOfOccupancy && mupa.fCalculateCorrelations; - mupa.fCalculateCorrelationsAsFunctionOf[AFO_INTERACTIONRATE] = cf_mupa.cfCalculateCorrelationsAsFunctionOfInteractionRate && mupa.fCalculateCorrelations; - mupa.fCalculateCorrelationsAsFunctionOf[AFO_CURRENTRUNDURATION] = cf_mupa.cfCalculateCorrelationsAsFunctionOfCurrentRunDuration && mupa.fCalculateCorrelations; - mupa.fCalculateCorrelationsAsFunctionOf[AFO_VZ] = cf_mupa.cfCalculateCorrelationsAsFunctionOfVz && mupa.fCalculateCorrelations; + + // *) Use configurable array cfCalculateCorrelationsAsFunctionOf, to specify vs which observable correlations will be calculated (flags 1 or 0). + // Supported format: "0-someName" and "1-someName", where "-" is a field separator. + // Ordering of the flags in that array is interpreted through ordering of enums in enum eAsFunctionOf. + auto lCalculateCorrelationsAsFunctionOf = cf_mupa.cfCalculateCorrelationsAsFunctionOf.value; // this is now the local version of that string array from configurable. + if (lCalculateCorrelationsAsFunctionOf.size() != eAsFunctionOf_N) { + LOGF(info, "\033[1;31m lCalculateCorrelationsAsFunctionOf.size() = %d\033[0m", lCalculateCorrelationsAsFunctionOf.size()); + LOGF(info, "\033[1;31m eAsFunctionOf_N) = %d\033[0m", static_cast(eAsFunctionOf_N)); + LOGF(fatal, "\033[1;31m%s at line %d : Mismatch in the number of flags in configurable cfCalculateCorrelationsAsFunctionOf, and number of entries in enum eAsFunctionOf_N \n \033[0m", __FUNCTION__, __LINE__); + } + + // I append "&& mupa.fCalculateCorrelations" below, to switch off calculation of all correlations with one common flag: + mupa.fCalculateCorrelationsAsFunctionOf[AFO_INTEGRATED] = Alright(lCalculateCorrelationsAsFunctionOf[AFO_INTEGRATED]) && mupa.fCalculateCorrelations; + mupa.fCalculateCorrelationsAsFunctionOf[AFO_MULTIPLICITY] = Alright(lCalculateCorrelationsAsFunctionOf[AFO_MULTIPLICITY]) && mupa.fCalculateCorrelations; + mupa.fCalculateCorrelationsAsFunctionOf[AFO_CENTRALITY] = Alright(lCalculateCorrelationsAsFunctionOf[AFO_CENTRALITY]) && mupa.fCalculateCorrelations; + mupa.fCalculateCorrelationsAsFunctionOf[AFO_PT] = Alright(lCalculateCorrelationsAsFunctionOf[AFO_PT]) && mupa.fCalculateCorrelations; + mupa.fCalculateCorrelationsAsFunctionOf[AFO_ETA] = Alright(lCalculateCorrelationsAsFunctionOf[AFO_ETA]) && mupa.fCalculateCorrelations; + mupa.fCalculateCorrelationsAsFunctionOf[AFO_OCCUPANCY] = Alright(lCalculateCorrelationsAsFunctionOf[AFO_OCCUPANCY]) && mupa.fCalculateCorrelations; + mupa.fCalculateCorrelationsAsFunctionOf[AFO_INTERACTIONRATE] = Alright(lCalculateCorrelationsAsFunctionOf[AFO_INTERACTIONRATE]) && mupa.fCalculateCorrelations; + mupa.fCalculateCorrelationsAsFunctionOf[AFO_CURRENTRUNDURATION] = Alright(lCalculateCorrelationsAsFunctionOf[AFO_CURRENTRUNDURATION]) && mupa.fCalculateCorrelations; + mupa.fCalculateCorrelationsAsFunctionOf[AFO_VZ] = Alright(lCalculateCorrelationsAsFunctionOf[AFO_VZ]) && mupa.fCalculateCorrelations; + mupa.fCalculateCorrelationsAsFunctionOf[AFO_CHARGE] = Alright(lCalculateCorrelationsAsFunctionOf[AFO_CHARGE]) && mupa.fCalculateCorrelations; + // ... // *) Test0: + // 1D: t0.fCalculateTest0 = cf_t0.cfCalculateTest0; - t0.fCalculateTest0AsFunctionOf[AFO_INTEGRATED] = cf_t0.cfCalculateTest0AsFunctionOfIntegrated && t0.fCalculateTest0; - t0.fCalculateTest0AsFunctionOf[AFO_MULTIPLICITY] = cf_t0.cfCalculateTest0AsFunctionOfMultiplicity && t0.fCalculateTest0; - t0.fCalculateTest0AsFunctionOf[AFO_CENTRALITY] = cf_t0.cfCalculateTest0AsFunctionOfCentrality && t0.fCalculateTest0; - t0.fCalculateTest0AsFunctionOf[AFO_PT] = cf_t0.cfCalculateTest0AsFunctionOfPt && t0.fCalculateTest0; - t0.fCalculateTest0AsFunctionOf[AFO_ETA] = cf_t0.cfCalculateTest0AsFunctionOfEta && t0.fCalculateTest0; - t0.fCalculateTest0AsFunctionOf[AFO_OCCUPANCY] = cf_t0.cfCalculateTest0AsFunctionOfOccupancy && t0.fCalculateTest0; - t0.fCalculateTest0AsFunctionOf[AFO_INTERACTIONRATE] = cf_t0.cfCalculateTest0AsFunctionOfInteractionRate && t0.fCalculateTest0; - t0.fCalculateTest0AsFunctionOf[AFO_CURRENTRUNDURATION] = cf_t0.cfCalculateTest0AsFunctionOfCurrentRunDuration && t0.fCalculateTest0; - t0.fCalculateTest0AsFunctionOf[AFO_VZ] = cf_t0.cfCalculateTest0AsFunctionOfVz && t0.fCalculateTest0; - if (t0.fCalculateTest0) { + // *) Use configurable array cfCalculateTest0AsFunctionOf, to specify vs which observable Test0 will be calculated (flags 1 or 0). + // Supported format: "0-someName" and "1-someName", where "-" is a field separator. + // Ordering of the flags in that array is interpreted through ordering of enums in enum eAsFunctionOf. + auto lCalculateTest0AsFunctionOf = cf_t0.cfCalculateTest0AsFunctionOf.value; // this is now the local version of that string array from configurable. + if (lCalculateTest0AsFunctionOf.size() != eAsFunctionOf_N) { + LOGF(info, "\033[1;31m lCalculateTest0AsFunctionOf.size() = %d\033[0m", lCalculateTest0AsFunctionOf.size()); + LOGF(info, "\033[1;31m eAsFunctionOf_N) = %d\033[0m", static_cast(eAsFunctionOf_N)); + LOGF(fatal, "\033[1;31m%s at line %d : Mismatch in the number of flags in configurable cfCalculateTest0AsFunctionOf, and number of entries in enum eAsFunctionOf_N \n \033[0m", __FUNCTION__, __LINE__); + } + + // I append "&& t0.fCalculateTest0" below, to switch off calculation of all Test0 with one common flag: + t0.fCalculateTest0AsFunctionOf[AFO_INTEGRATED] = Alright(lCalculateTest0AsFunctionOf[AFO_INTEGRATED]) && t0.fCalculateTest0; + t0.fCalculateTest0AsFunctionOf[AFO_MULTIPLICITY] = Alright(lCalculateTest0AsFunctionOf[AFO_MULTIPLICITY]) && t0.fCalculateTest0; + t0.fCalculateTest0AsFunctionOf[AFO_CENTRALITY] = Alright(lCalculateTest0AsFunctionOf[AFO_CENTRALITY]) && t0.fCalculateTest0; + t0.fCalculateTest0AsFunctionOf[AFO_PT] = Alright(lCalculateTest0AsFunctionOf[AFO_PT]) && t0.fCalculateTest0; + t0.fCalculateTest0AsFunctionOf[AFO_ETA] = Alright(lCalculateTest0AsFunctionOf[AFO_ETA]) && t0.fCalculateTest0; + t0.fCalculateTest0AsFunctionOf[AFO_OCCUPANCY] = Alright(lCalculateTest0AsFunctionOf[AFO_OCCUPANCY]) && t0.fCalculateTest0; + t0.fCalculateTest0AsFunctionOf[AFO_INTERACTIONRATE] = Alright(lCalculateTest0AsFunctionOf[AFO_INTERACTIONRATE]) && t0.fCalculateTest0; + t0.fCalculateTest0AsFunctionOf[AFO_CURRENTRUNDURATION] = Alright(lCalculateTest0AsFunctionOf[AFO_CURRENTRUNDURATION]) && t0.fCalculateTest0; + t0.fCalculateTest0AsFunctionOf[AFO_VZ] = Alright(lCalculateTest0AsFunctionOf[AFO_VZ]) && t0.fCalculateTest0; + t0.fCalculateTest0AsFunctionOf[AFO_CHARGE] = Alright(lCalculateTest0AsFunctionOf[AFO_CHARGE]) && t0.fCalculateTest0; + // ... + + // 2D: + t0.fCalculate2DTest0 = cf_t0.cfCalculate2DTest0; + + // *) Use configurable array cfCalculate2DTest0AsFunctionOf, to specify vs which two observables Test0 will be calculated (flags 1 or 0). + // Supported format: "0-someName1_someName_2" and "1-someName1_someName_2", where both "-" and "_" are IFS, but with different meaning. + // Ordering of the flags in that array is interpreted through ordering of enums in enum eAsFunctionOf2D_N. + auto lCalculate2DTest0AsFunctionOf = cf_t0.cfCalculate2DTest0AsFunctionOf.value; // this is now the local version of that string array from configurable. + if (lCalculate2DTest0AsFunctionOf.size() != eAsFunctionOf2D_N) { + LOGF(info, "\033[1;31m lCalculate2DTest0AsFunctionOf.size() = %d\033[0m", lCalculate2DTest0AsFunctionOf.size()); + LOGF(info, "\033[1;31m eAsFunctionOf2D_N) = %d\033[0m", static_cast(eAsFunctionOf2D_N)); + LOGF(fatal, "\033[1;31m%s at line %d : Mismatch in the number of flags in configurable cfCalculate2DTest0AsFunctionOf, and number of entries in enum eAsFunctionOf2D_N \n \033[0m", __FUNCTION__, __LINE__); + } + + // I append "&& t0.fCalculate2DTest0" below, to switch off calculation of all Test0 with one common flag: + t0.fCalculate2DTest0AsFunctionOf[AFO_CENTRALITY_PT] = Alright(lCalculate2DTest0AsFunctionOf[AFO_CENTRALITY_PT]) && t0.fCalculate2DTest0; + t0.fCalculate2DTest0AsFunctionOf[AFO_CENTRALITY_ETA] = Alright(lCalculate2DTest0AsFunctionOf[AFO_CENTRALITY_ETA]) && t0.fCalculate2DTest0; + t0.fCalculate2DTest0AsFunctionOf[AFO_CENTRALITY_CHARGE] = Alright(lCalculate2DTest0AsFunctionOf[AFO_CENTRALITY_CHARGE]) && t0.fCalculate2DTest0; + t0.fCalculate2DTest0AsFunctionOf[AFO_CENTRALITY_VZ] = Alright(lCalculate2DTest0AsFunctionOf[AFO_CENTRALITY_VZ]) && t0.fCalculate2DTest0; + t0.fCalculate2DTest0AsFunctionOf[AFO_PT_ETA] = Alright(lCalculate2DTest0AsFunctionOf[AFO_PT_ETA]) && t0.fCalculate2DTest0; + t0.fCalculate2DTest0AsFunctionOf[AFO_PT_CHARGE] = Alright(lCalculate2DTest0AsFunctionOf[AFO_PT_CHARGE]) && t0.fCalculate2DTest0; + t0.fCalculate2DTest0AsFunctionOf[AFO_ETA_CHARGE] = Alright(lCalculate2DTest0AsFunctionOf[AFO_ETA_CHARGE]) && t0.fCalculate2DTest0; + + // ... + + // 3D: + t0.fCalculate3DTest0 = cf_t0.cfCalculate3DTest0; + + // *) Use configurable array cfCalculate3DTest0AsFunctionOf, to specify vs which two observables Test0 will be calculated (flags 1 or 0). + // Supported format: "0-someName1_someName_2" and "1-someName1_someName_2", where both "-" and "_" are IFS, but with different meaning. + // Ordering of the flags in that array is interpreted through ordering of enums in enum eAsFunctionOf3D_N. + auto lCalculate3DTest0AsFunctionOf = cf_t0.cfCalculate3DTest0AsFunctionOf.value; // this is now the local version of that string array from configurable. + if (lCalculate3DTest0AsFunctionOf.size() != eAsFunctionOf3D_N) { + LOGF(info, "\033[1;31m lCalculate3DTest0AsFunctionOf.size() = %d\033[0m", lCalculate3DTest0AsFunctionOf.size()); + LOGF(info, "\033[1;31m eAsFunctionOf3D_N) = %d\033[0m", static_cast(eAsFunctionOf3D_N)); + LOGF(fatal, "\033[1;31m%s at line %d : Mismatch in the number of flags in configurable cfCalculate3DTest0AsFunctionOf, and number of entries in enum eAsFunctionOf3D_N \n \033[0m", __FUNCTION__, __LINE__); + } + + // I append "&& t0.fCalculate3DTest0" below, to switch off calculation of all Test0 with one common flag: + t0.fCalculate3DTest0AsFunctionOf[AFO_CENTRALITY_PT_ETA] = Alright(lCalculate3DTest0AsFunctionOf[AFO_CENTRALITY_PT_ETA]) && t0.fCalculate3DTest0; + t0.fCalculate3DTest0AsFunctionOf[AFO_CENTRALITY_PT_CHARGE] = Alright(lCalculate3DTest0AsFunctionOf[AFO_CENTRALITY_PT_CHARGE]) && t0.fCalculate3DTest0; + t0.fCalculate3DTest0AsFunctionOf[AFO_CENTRALITY_PT_VZ] = Alright(lCalculate3DTest0AsFunctionOf[AFO_CENTRALITY_PT_VZ]) && t0.fCalculate3DTest0; + t0.fCalculate3DTest0AsFunctionOf[AFO_CENTRALITY_ETA_VZ] = Alright(lCalculate3DTest0AsFunctionOf[AFO_CENTRALITY_ETA_VZ]) && t0.fCalculate3DTest0; + t0.fCalculate3DTest0AsFunctionOf[AFO_CENTRALITY_ETA_CHARGE] = Alright(lCalculate3DTest0AsFunctionOf[AFO_CENTRALITY_ETA_CHARGE]) && t0.fCalculate3DTest0; + t0.fCalculate3DTest0AsFunctionOf[AFO_CENTRALITY_VZ_CHARGE] = Alright(lCalculate3DTest0AsFunctionOf[AFO_CENTRALITY_VZ_CHARGE]) && t0.fCalculate3DTest0; + t0.fCalculate3DTest0AsFunctionOf[AFO_PT_ETA_CHARGE] = Alright(lCalculate3DTest0AsFunctionOf[AFO_PT_ETA_CHARGE]) && t0.fCalculate3DTest0; + + // ... + + if (t0.fCalculateTest0 || t0.fCalculate2DTest0 || t0.fCalculate3DTest0) { t0.fFileWithLabels = TString(cf_t0.cfFileWithLabels); t0.fUseDefaultLabels = cf_t0.cfUseDefaultLabels; t0.fWhichDefaultLabels = TString(cf_t0.cfWhichDefaultLabels); @@ -577,7 +667,11 @@ void DefaultConfiguration() for (int dpw = 0; dpw < eDiffPtWeights_N; dpw++) { // "differential pt weight" if (TString(lWhichDiffPtWeights[dpw]).Contains("wPt")) { pw.fUseDiffPtWeights[wPtPtAxis] = Alright(lWhichDiffPtWeights[dpw]); // if I pass "1-Pt" => true, "0-Pt" => false - } else { // ... TBI 20250222 add support for other dimensions of differential pt weights, in the same spirit i did it for differential phi weights + } else if (TString(lWhichDiffPtWeights[dpw]).Contains("wCharge")) { + pw.fUseDiffPtWeights[wPtChargeAxis] = Alright(lWhichDiffPtWeights[dpw]) && pw.fUseDiffPtWeights[wPtPtAxis]; + } else if (TString(lWhichDiffPtWeights[dpw]).Contains("wCentrality")) { + pw.fUseDiffPtWeights[wPtCentralityAxis] = Alright(lWhichDiffPtWeights[dpw]) && pw.fUseDiffPtWeights[wPtPtAxis]; + } else { LOGF(fatal, "\033[1;31m%s at line %d : The setting %s in configurable cfWhichDiffPtWeights is not supported yet. See enum eDiffPtWeights . \n \033[0m", __FUNCTION__, __LINE__, TString(lWhichDiffPtWeights[dpw]).Data()); } } @@ -592,7 +686,11 @@ void DefaultConfiguration() for (int dpw = 0; dpw < eDiffEtaWeights_N; dpw++) { // "differential eta weight" if (TString(lWhichDiffEtaWeights[dpw]).Contains("wEta")) { pw.fUseDiffEtaWeights[wEtaEtaAxis] = Alright(lWhichDiffEtaWeights[dpw]); // if I pass "1-Eta" => true, "0-Eta" => false - } else { // ... TBI 20250222 add support for other dimensions of differential eta weights, in the same spirit i did it for differential phi weights + } else if (TString(lWhichDiffEtaWeights[dpw]).Contains("wCharge")) { + pw.fUseDiffEtaWeights[wEtaChargeAxis] = Alright(lWhichDiffEtaWeights[dpw]) && pw.fUseDiffEtaWeights[wEtaEtaAxis]; + } else if (TString(lWhichDiffEtaWeights[dpw]).Contains("wCentrality")) { + pw.fUseDiffEtaWeights[wEtaCentralityAxis] = Alright(lWhichDiffEtaWeights[dpw]) && pw.fUseDiffEtaWeights[wEtaEtaAxis]; + } else { LOGF(fatal, "\033[1;31m%s at line %d : The setting %s in configurable cfWhichDiffEtaWeights is not supported yet. See enum eDiffEtaWeights . \n \033[0m", __FUNCTION__, __LINE__, TString(lWhichDiffEtaWeights[dpw]).Data()); } } @@ -688,11 +786,23 @@ void DefaultConfiguration() iv.fInternalValidationForceBailout = cf_iv.cfInternalValidationForceBailout; iv.fnEventsInternalValidation = cf_iv.cfnEventsInternalValidation; iv.fRescaleWithTheoreticalInput = cf_iv.cfRescaleWithTheoreticalInput; + iv.fRandomizeReactionPlane = cf_iv.cfRandomizeReactionPlane; iv.fHarmonicsOptionInternalValidation = new TString(cf_iv.cfHarmonicsOptionInternalValidation); // *) Results histograms: - // Define axis titles: - // Remark: keep ordering in sync with enum eAsFunctionOf + // **) Fixed-length or variable-length binning: + // Remark: keep ordering in sync with enum eAsFunctionOf: + cf_res.cfUseVariableLengthMultBins ? res.fUseResultsProVariableLengthBins[AFO_MULTIPLICITY] = true : res.fUseResultsProVariableLengthBins[AFO_MULTIPLICITY] = false; + cf_res.cfUseVariableLengthCentBins ? res.fUseResultsProVariableLengthBins[AFO_CENTRALITY] = true : res.fUseResultsProVariableLengthBins[AFO_CENTRALITY] = false; + cf_res.cfUseVariableLengthPtBins ? res.fUseResultsProVariableLengthBins[AFO_PT] = true : res.fUseResultsProVariableLengthBins[AFO_PT] = false; + cf_res.cfUseVariableLengthEtaBins ? res.fUseResultsProVariableLengthBins[AFO_ETA] = true : res.fUseResultsProVariableLengthBins[AFO_ETA] = false; + cf_res.cfUseVariableLengthOccuBins ? res.fUseResultsProVariableLengthBins[AFO_OCCUPANCY] = true : res.fUseResultsProVariableLengthBins[AFO_OCCUPANCY] = false; + cf_res.cfUseVariableLengthCRDBins ? res.fUseResultsProVariableLengthBins[AFO_CURRENTRUNDURATION] = true : res.fUseResultsProVariableLengthBins[AFO_CURRENTRUNDURATION] = false; + cf_res.cfUseVariableLengthVzBins ? res.fUseResultsProVariableLengthBins[AFO_VZ] = true : res.fUseResultsProVariableLengthBins[AFO_VZ] = false; + + // **) Define axis titles: + // Remark: keep ordering in sync with enum eAsFunctionOf + // 1D: res.fResultsProXaxisTitle[AFO_INTEGRATED] = "integrated"; res.fResultsProRawName[AFO_INTEGRATED] = "int"; // this is how it appears simplified in the hist name when saved to the file res.fResultsProXaxisTitle[AFO_MULTIPLICITY] = "multiplicity"; @@ -711,6 +821,16 @@ void DefaultConfiguration() res.fResultsProRawName[AFO_CURRENTRUNDURATION] = "crd"; res.fResultsProXaxisTitle[AFO_VZ] = "vertex z position"; res.fResultsProRawName[AFO_VZ] = "vz"; + res.fResultsProXaxisTitle[AFO_CHARGE] = "particle charge"; + res.fResultsProRawName[AFO_CHARGE] = "charge"; + // ... + + // 2D: + // Remark: I re-use the above definitions for 1D. + + // 3D: + // Remark: I re-use the above definitions for 1D. + res.fSaveResultsHistograms = cf_res.cfSaveResultsHistograms; // *) QA: @@ -882,15 +1002,29 @@ void DefaultConfiguration() // ** Eta separations: es.fCalculateEtaSeparations = cf_es.cfCalculateEtaSeparations; - es.fCalculateEtaSeparationsAsFunctionOf[AFO_INTEGRATED] = cf_es.cfCalculateEtaSeparationsAsFunctionOfIntegrated && es.fCalculateEtaSeparations; - es.fCalculateEtaSeparationsAsFunctionOf[AFO_MULTIPLICITY] = cf_es.cfCalculateEtaSeparationsAsFunctionOfMultiplicity && es.fCalculateEtaSeparations; - es.fCalculateEtaSeparationsAsFunctionOf[AFO_CENTRALITY] = cf_es.cfCalculateEtaSeparationsAsFunctionOfCentrality && es.fCalculateEtaSeparations; - es.fCalculateEtaSeparationsAsFunctionOf[AFO_PT] = cf_es.cfCalculateEtaSeparationsAsFunctionOfPt && es.fCalculateEtaSeparations; - es.fCalculateEtaSeparationsAsFunctionOf[AFO_ETA] = false; // this one doesn't make sense in this context, obviously - es.fCalculateEtaSeparationsAsFunctionOf[AFO_OCCUPANCY] = cf_es.cfCalculateEtaSeparationsAsFunctionOfOccupancy && es.fCalculateEtaSeparations; - es.fCalculateEtaSeparationsAsFunctionOf[AFO_INTERACTIONRATE] = cf_es.cfCalculateEtaSeparationsAsFunctionOfInteractionRate && es.fCalculateEtaSeparations; - es.fCalculateEtaSeparationsAsFunctionOf[AFO_CURRENTRUNDURATION] = cf_es.cfCalculateEtaSeparationsAsFunctionOfCurrentRunDuration && es.fCalculateEtaSeparations; - es.fCalculateEtaSeparationsAsFunctionOf[AFO_VZ] = cf_es.cfCalculateEtaSeparationsAsFunctionOfVz && es.fCalculateEtaSeparations; + + // *) Use configurable array cfCalculateEtaSeparationsAsFunctionOf, to specify vs which observable EtaSeparations will be calculated (flags 1 or 0). + // Supported format: "0-someName" and "1-someName", where "-" is a field separator. + // Ordering of the flags in that array is interpreted through ordering of enums in enum eAsFunctionOf. + auto lCalculateEtaSeparationsAsFunctionOf = cf_es.cfCalculateEtaSeparationsAsFunctionOf.value; // this is now the local version of that string array from configurable. + if (lCalculateEtaSeparationsAsFunctionOf.size() != eAsFunctionOf_N) { + LOGF(info, "\033[1;31m lCalculateEtaSeparationsAsFunctionOf.size() = %d\033[0m", lCalculateEtaSeparationsAsFunctionOf.size()); + LOGF(info, "\033[1;31m eAsFunctionOf_N) = %d\033[0m", static_cast(eAsFunctionOf_N)); + LOGF(fatal, "\033[1;31m%s at line %d : Mismatch in the number of flags in configurable cfCalculateEtaSeparationsAsFunctionOf, and number of entries in enum eAsFunctionOf_N \n \033[0m", __FUNCTION__, __LINE__); + } + + // I append "&& es.fCalculateEtaSeparations" below, to switch off calculation of all correlations with one common flag: + es.fCalculateEtaSeparationsAsFunctionOf[AFO_INTEGRATED] = Alright(lCalculateEtaSeparationsAsFunctionOf[AFO_INTEGRATED]) && es.fCalculateEtaSeparations; + es.fCalculateEtaSeparationsAsFunctionOf[AFO_MULTIPLICITY] = Alright(lCalculateEtaSeparationsAsFunctionOf[AFO_MULTIPLICITY]) && es.fCalculateEtaSeparations; + es.fCalculateEtaSeparationsAsFunctionOf[AFO_CENTRALITY] = Alright(lCalculateEtaSeparationsAsFunctionOf[AFO_CENTRALITY]) && es.fCalculateEtaSeparations; + es.fCalculateEtaSeparationsAsFunctionOf[AFO_PT] = Alright(lCalculateEtaSeparationsAsFunctionOf[AFO_PT]) && es.fCalculateEtaSeparations; + es.fCalculateEtaSeparationsAsFunctionOf[AFO_ETA] = false; // yes, in this context this one doesn't make sense + es.fCalculateEtaSeparationsAsFunctionOf[AFO_OCCUPANCY] = Alright(lCalculateEtaSeparationsAsFunctionOf[AFO_OCCUPANCY]) && es.fCalculateEtaSeparations; + es.fCalculateEtaSeparationsAsFunctionOf[AFO_INTERACTIONRATE] = Alright(lCalculateEtaSeparationsAsFunctionOf[AFO_INTERACTIONRATE]) && es.fCalculateEtaSeparations; + es.fCalculateEtaSeparationsAsFunctionOf[AFO_CURRENTRUNDURATION] = Alright(lCalculateEtaSeparationsAsFunctionOf[AFO_CURRENTRUNDURATION]) && es.fCalculateEtaSeparations; + es.fCalculateEtaSeparationsAsFunctionOf[AFO_VZ] = Alright(lCalculateEtaSeparationsAsFunctionOf[AFO_VZ]) && es.fCalculateEtaSeparations; + es.fCalculateEtaSeparationsAsFunctionOf[AFO_CHARGE] = Alright(lCalculateEtaSeparationsAsFunctionOf[AFO_CHARGE]) && es.fCalculateEtaSeparations; + // ... if (es.fCalculateEtaSeparations) { auto lEtaSeparationsValues = cf_es.cfEtaSeparationsValues.value; @@ -918,6 +1052,57 @@ void DefaultConfiguration() } // if(es.fCalculateEtaSeparations) { + // Set the flags qv.fCalculateqvectorsKineAny, fCalculateqvectorsKine[eqvectorKine_N] and fCalculateqvectorsKineEtaSeparations[eqvectorKine_N]: + // TBI 20250601 I have to do it without loop, until I provide support for 2D and 3D to Correlations and EtaSeparations + + // Test0 and Correlations: + if (mupa.fCalculateCorrelationsAsFunctionOf[AfoKineMap1D(PTq)] || t0.fCalculateTest0AsFunctionOf[AfoKineMap1D(PTq)]) { + qv.fCalculateqvectorsKine[PTq] = true; + } + if (mupa.fCalculateCorrelationsAsFunctionOf[AfoKineMap1D(ETAq)] || t0.fCalculateTest0AsFunctionOf[AfoKineMap1D(ETAq)]) { + qv.fCalculateqvectorsKine[ETAq] = true; + } + if (mupa.fCalculateCorrelationsAsFunctionOf[AfoKineMap1D(CHARGEq)] || t0.fCalculateTest0AsFunctionOf[AfoKineMap1D(CHARGEq)]) { + qv.fCalculateqvectorsKine[CHARGEq] = true; + } + if (t0.fCalculate2DTest0AsFunctionOf[AfoKineMap2D(PT_ETAq)]) { + qv.fCalculateqvectorsKine[PT_ETAq] = true; + } + if (t0.fCalculate2DTest0AsFunctionOf[AfoKineMap2D(PT_CHARGEq)]) { + qv.fCalculateqvectorsKine[PT_CHARGEq] = true; + } + if (t0.fCalculate2DTest0AsFunctionOf[AfoKineMap2D(ETA_CHARGEq)]) { + qv.fCalculateqvectorsKine[ETA_CHARGEq] = true; + } + if (t0.fCalculate3DTest0AsFunctionOf[AfoKineMap3D(PT_ETA_CHARGEq)]) { + qv.fCalculateqvectorsKine[PT_ETA_CHARGEq] = true; + } + + // Eta separations: + if (es.fCalculateEtaSeparationsAsFunctionOf[AfoKineMap1D(PTq)]) { + qv.fCalculateqvectorsKineEtaSeparations[PTq] = true; + } + qv.fCalculateqvectorsKineEtaSeparations[ETAq] = false; // yes, this one is alwas set explicitly to false + if (es.fCalculateEtaSeparationsAsFunctionOf[AfoKineMap1D(CHARGEq)]) { + qv.fCalculateqvectorsKineEtaSeparations[CHARGEq] = true; + } + qv.fCalculateqvectorsKineEtaSeparations[PT_ETAq] = false; // yes, this one is alwas set explicitly to false + + // TBI 20250617 comment in this branch, when i implement support for 2D eta separations. + // if (es.fCalculate2DEtaSeparationsAsFunctionOf[AfoKineMap2D(PT_CHARGEq)]) { + // qv.fCalculateqvectorsKineEtaSeparations[PT_CHARGEq] = true; + // } + + qv.fCalculateqvectorsKineEtaSeparations[ETA_CHARGEq] = false; // yes, this one is alwas set explicitly to false + qv.fCalculateqvectorsKineEtaSeparations[PT_ETA_CHARGEq] = false; // yes, this one is alwas set explicitly to false + + for (int qKine = 0; qKine < eqvectorKine_N; qKine++) { + if (qv.fCalculateqvectorsKine[qKine] || qv.fCalculateqvectorsKineEtaSeparations[qKine]) { + qv.fCalculateqvectorsKineAny = true; + break; // yes, I need at least one kine calculus, to set this flag to true + } + } + if (tc.fVerbose) { ExitFunction(__FUNCTION__); } @@ -947,7 +1132,7 @@ bool Alright(TString s) } int nEntries = oa->GetEntries(); if (2 != nEntries) { - LOGF(fatal, "\033[1;31m%s at line %d : string expected in this function must be formatted as \"someName-0\" or \"someName-1\" => s = %s\033[0m", __FUNCTION__, __LINE__, s.Data()); + LOGF(fatal, "\033[1;31m%s at line %d : string expected in this function must be formatted as \"0-someName\" or \"1-someName\" => s = %s\033[0m", __FUNCTION__, __LINE__, s.Data()); } // b) Do the thing: @@ -993,7 +1178,7 @@ void DefaultBooking() // *) By default all event histograms are booked. If you do not want particular event histogram to be booked, // use configurable array cfBookEventHistograms, where you can specify name of the histogram accompanied with flags 1 (book) or 0 (do not book). - // Supported format: "someName-0" and "someName-1", where "-" is a field separator. + // Supported format: "0-someName" and "1-someName", where "-" is a field separator. // Ordering of the flags in that array is interpreted through ordering of enums in enum eEventHistograms. auto lBookEventHistograms = cf_eh.cfBookEventHistograms.value; // this is now the local version of that string array from configurable. if (lBookEventHistograms.size() != eEventHistograms_N) { @@ -1524,62 +1709,78 @@ void DefaultBinning() ph.fParticleHistogramsBins2D[ePhiEta][eY][2] = ph.fParticleHistogramsBins[eEta][2]; // d) Default binning for results histograms: - // Remark: These bins apply to following categories fCorrelationsPro, fNestedLoopsPro, fTest0Pro, and fResultsPro. - // *) For integrated resullts, binning is always the same: - res.fResultsProFixedLengthBins[AFO_INTEGRATED][0] = 1; - res.fResultsProFixedLengthBins[AFO_INTEGRATED][1] = 0.; - res.fResultsProFixedLengthBins[AFO_INTEGRATED][2] = 1.; - // *) Fixed-length binning vs. multiplicity: - this->InitializeFixedLengthBins(AFO_MULTIPLICITY); - // *) Fixed-length binning vs. centrality: - this->InitializeFixedLengthBins(AFO_CENTRALITY); - // *) Fixed-length binning vs. pt: - this->InitializeFixedLengthBins(AFO_PT); - // *) Fixed-length binning vs. eta: - this->InitializeFixedLengthBins(AFO_ETA); - // *) Fixed-length binning vs. occupancy: - this->InitializeFixedLengthBins(AFO_OCCUPANCY); - // *) Fixed-length binning vs. interaction rate: - this->InitializeFixedLengthBins(AFO_INTERACTIONRATE); - // *) Fixed-length binning vs. run duration: - this->InitializeFixedLengthBins(AFO_CURRENTRUNDURATION); - // *) Vertex z position: - this->InitializeFixedLengthBins(AFO_VZ); - - // e) Variable-length binning set via MuPa-Configurables.h: - // *) Variable-length binning vs. multiplicity: - if (cf_res.cfUseVariableLengthMultBins) { + // Remark: These bins apply to following categories fCorrelationsPro, fNestedLoopsPro, fTest0Pro, fResultsPro, and all 2D and 3D variants. + // 1D: + // *) For integrated results, binning is always the same nBins = 1 in (0.,1.): + res.fResultsProBinEdges[AFO_INTEGRATED] = new TArrayD(2); + res.fResultsProBinEdges[AFO_INTEGRATED]->AddAt(0., 0); + res.fResultsProBinEdges[AFO_INTEGRATED]->AddAt(1., 1); + + // *) Binning vs. multiplicity: + if (res.fUseResultsProVariableLengthBins[AFO_MULTIPLICITY]) { this->InitializeVariableLengthBins(AFO_MULTIPLICITY); + } else { + this->InitializeFixedLengthBins(AFO_MULTIPLICITY); } - // *) Variable-length binning vs. centrality: - if (cf_res.cfUseVariableLengthCentBins) { + + // *) Binning vs. centrality: + if (res.fUseResultsProVariableLengthBins[AFO_CENTRALITY]) { this->InitializeVariableLengthBins(AFO_CENTRALITY); + } else { + this->InitializeFixedLengthBins(AFO_CENTRALITY); } - // *) Variable-length binning vs. pt: - if (cf_res.cfUseVariableLengthPtBins) { + + // *) Binning vs. pt: + if (res.fUseResultsProVariableLengthBins[AFO_PT]) { this->InitializeVariableLengthBins(AFO_PT); + } else { + this->InitializeFixedLengthBins(AFO_PT); } - // *) Variable-length binning vs. eta: - if (cf_res.cfUseVariableLengthEtaBins) { + + // *) Binning vs. eta: + if (res.fUseResultsProVariableLengthBins[AFO_ETA]) { this->InitializeVariableLengthBins(AFO_ETA); + } else { + this->InitializeFixedLengthBins(AFO_ETA); } - // *) Variable-length binning vs. occupancy: - if (cf_res.cfUseVariableLengthOccuBins) { + + // *) Binning vs. occupancy: + if (res.fUseResultsProVariableLengthBins[AFO_OCCUPANCY]) { this->InitializeVariableLengthBins(AFO_OCCUPANCY); + } else { + this->InitializeFixedLengthBins(AFO_OCCUPANCY); } - // *) Variable-length binning vs. interaction rate: - if (cf_res.cfUseVariableLengthIRBins) { + + // *) Binning vs. interaction rate: + if (res.fUseResultsProVariableLengthBins[AFO_INTERACTIONRATE]) { this->InitializeVariableLengthBins(AFO_INTERACTIONRATE); + } else { + this->InitializeFixedLengthBins(AFO_INTERACTIONRATE); } - // *) Variable-length binning vs. run duration: - if (cf_res.cfUseVariableLengthCRDBins) { + + // *) Binning vs. current run duration: + if (res.fUseResultsProVariableLengthBins[AFO_CURRENTRUNDURATION]) { this->InitializeVariableLengthBins(AFO_CURRENTRUNDURATION); + } else { + this->InitializeFixedLengthBins(AFO_CURRENTRUNDURATION); } - // *) Variable-length binning vs. vertex z position: - if (cf_res.cfUseVariableLengthVzBins) { + + // *) Binning vs. vertex z position: + if (res.fUseResultsProVariableLengthBins[AFO_VZ]) { this->InitializeVariableLengthBins(AFO_VZ); + } else { + this->InitializeFixedLengthBins(AFO_VZ); } + // *) Binning vs. particle charge => binning is always the same nBins = 2 in (-2.,2), so that the center of bins is at +/- 1: + // Therefore, I shall never initialize or set for ill-defined cases the charge to 0., because when filling, that one will go to bin for +1 charge ("lower boundary included"). + res.fResultsProBinEdges[AFO_CHARGE] = new TArrayD(3); + res.fResultsProBinEdges[AFO_CHARGE]->AddAt(-2., 0); + res.fResultsProBinEdges[AFO_CHARGE]->AddAt(0., 1); + res.fResultsProBinEdges[AFO_CHARGE]->AddAt(2., 2); + + // ... + if (tc.fVerbose) { ExitFunction(__FUNCTION__); } @@ -1592,13 +1793,14 @@ void InitializeFixedLengthBins(eAsFunctionOf AFO) { // This is a helper function to suppress code bloat in DefaultBinning(). // It merely initalizes res.fResultsProFixedLengthBins[...] from corresponding configurables + a few other minor thingies. + // I do not have here AFO_INTEGRATED and AFO_CHARGE, because for them binning is always the same, i.e. no need for configurable. if (tc.fVerbose) { StartFunction(__FUNCTION__); } // Common local vector for all fixed-length bins: - std::vector lFixedLength_bins; + std::vector lFixedLength_bins; switch (AFO) { case AFO_MULTIPLICITY: { @@ -1644,15 +1846,10 @@ void InitializeFixedLengthBins(eAsFunctionOf AFO) if (lFixedLength_bins.size() != 3) { LOGF(fatal, "in function \033[1;31m%s at line %d => The array cfFixedLength_bins must have have 3 entries: {nBins, min, max} \n \033[0m", __FUNCTION__, __LINE__); } - res.fResultsProFixedLengthBins[AFO][0] = lFixedLength_bins[0]; - res.fResultsProFixedLengthBins[AFO][1] = lFixedLength_bins[1]; - res.fResultsProFixedLengthBins[AFO][2] = lFixedLength_bins[2]; + + res.fResultsProBinEdges[AFO] = ArrayWithBinEdges(lFixedLength_bins[0], lFixedLength_bins[1], lFixedLength_bins[2]); if (tc.fVerbose) { - LOGF(info, "\033[1;32m %s : fixed-length %s bins \033[0m", __FUNCTION__, res.fResultsProXaxisTitle[AFO].Data()); - LOGF(info, "\033[1;32m [0] : %f \033[0m", res.fResultsProFixedLengthBins[AFO][0]); - LOGF(info, "\033[1;32m [1] : %f \033[0m", res.fResultsProFixedLengthBins[AFO][1]); - LOGF(info, "\033[1;32m [2] : %f \033[0m", res.fResultsProFixedLengthBins[AFO][2]); ExitFunction(__FUNCTION__); } @@ -1670,7 +1867,7 @@ void InitializeVariableLengthBins(eAsFunctionOf AFO) } // Common local vector for all variable-length bins: - std::vector lVariableLength_bins; + std::vector lVariableLength_bins; switch (AFO) { case AFO_MULTIPLICITY: { @@ -1713,15 +1910,14 @@ void InitializeVariableLengthBins(eAsFunctionOf AFO) } // switch(AFO) // From this point onward, the code is the same for any AFO variable: - res.fUseResultsProVariableLengthBins[AFO] = true; if (lVariableLength_bins.size() < 2) { LOGF(fatal, "in function \033[1;31m%s at line %d => The array cfVariableLength_bins must have at least 2 entries \n \033[0m", __FUNCTION__, __LINE__); } - res.fResultsProVariableLengthBins[AFO] = new TArrayF(lVariableLength_bins.size(), lVariableLength_bins.data()); + res.fResultsProBinEdges[AFO] = new TArrayD(lVariableLength_bins.size(), lVariableLength_bins.data()); if (tc.fVerbose) { LOGF(info, "\033[1;32m %s : variable-length %s bins \033[0m", __FUNCTION__, res.fResultsProXaxisTitle[AFO].Data()); - for (int i = 0; i < res.fResultsProVariableLengthBins[AFO]->GetSize(); i++) { - LOGF(info, "\033[1;32m [%d] : %f \033[0m", i, res.fResultsProVariableLengthBins[AFO]->GetAt(i)); + for (int i = 0; i < res.fResultsProBinEdges[AFO]->GetSize(); i++) { + LOGF(info, "\033[1;32m [%d] : %f \033[0m", i, res.fResultsProBinEdges[AFO]->GetAt(i)); } } @@ -1849,6 +2045,12 @@ void DefaultCuts() ec.fUseEventCuts[eRefMultVsNContrUp] = Alright(lUseEventCuts[eRefMultVsNContrUp]); ec.fUseEventCuts[eRefMultVsNContrLow] = Alright(lUseEventCuts[eRefMultVsNContrLow]); ec.fUseEventCuts[eCentralityCorrelationsCut] = Alright(lUseEventCuts[eCentralityCorrelationsCut]); + ec.fUseEventCuts[eFT0Bad] = Alright(lUseEventCuts[eFT0Bad]); + ec.fUseEventCuts[eITSBad] = Alright(lUseEventCuts[eITSBad]); + ec.fUseEventCuts[eITSLimAccMCRepr] = Alright(lUseEventCuts[eITSLimAccMCRepr]); + ec.fUseEventCuts[eTPCBadTracking] = Alright(lUseEventCuts[eTPCBadTracking]); + ec.fUseEventCuts[eTPCLimAccMCRepr] = Alright(lUseEventCuts[eTPCLimAccMCRepr]); + ec.fUseEventCuts[eTPCBadPID] = Alright(lUseEventCuts[eTPCBadPID]); ec.fUseEventCuts[eCentralityWeights] = Alright(lUseEventCuts[eCentralityWeights]); // **) event cuts defined via booleans: @@ -1870,6 +2072,12 @@ void DefaultCuts() ec.fUseEventCuts[eNoPileupTPC] = ec.fUseEventCuts[eNoPileupTPC] && cf_ec.cfUseNoPileupTPC; ec.fUseEventCuts[eNoPileupFromSPD] = ec.fUseEventCuts[eNoPileupFromSPD] && cf_ec.cfUseNoPileupFromSPD; ec.fUseEventCuts[eNoSPDOnVsOfPileup] = ec.fUseEventCuts[eNoSPDOnVsOfPileup] && cf_ec.cfUseNoSPDOnVsOfPileup; + ec.fUseEventCuts[eFT0Bad] = ec.fUseEventCuts[eFT0Bad] && cf_ec.cfUseFT0Bad; + ec.fUseEventCuts[eITSBad] = ec.fUseEventCuts[eITSBad] && cf_ec.cfUseITSBad; + ec.fUseEventCuts[eITSLimAccMCRepr] = ec.fUseEventCuts[eITSLimAccMCRepr] && cf_ec.cfUseITSLimAccMCRepr; + ec.fUseEventCuts[eTPCBadTracking] = ec.fUseEventCuts[eTPCBadTracking] && cf_ec.cfUseTPCBadTracking; + ec.fUseEventCuts[eTPCLimAccMCRepr] = ec.fUseEventCuts[eTPCLimAccMCRepr] && cf_ec.cfUseTPCLimAccMCRepr; + ec.fUseEventCuts[eTPCBadPID] = ec.fUseEventCuts[eTPCBadPID] && cf_ec.cfUseTPCBadPID; ec.fUseEventCuts[eCentralityWeights] = ec.fUseEventCuts[eCentralityWeights] && cf_cw.cfUseCentralityWeights; // **) event cuts defined via [min, max): @@ -2331,7 +2539,12 @@ void SpecificCuts(TString whichSpecificCuts) ec.fUseEventCuts[eIsGoodITSLayer3] = false; ec.fUseEventCuts[eIsGoodITSLayer0123] = false; ec.fUseEventCuts[eIsGoodITSLayersAll] = false; - + ec.fUseEventCuts[eFT0Bad] = false; + ec.fUseEventCuts[eITSBad] = false; + ec.fUseEventCuts[eITSLimAccMCRepr] = false; + ec.fUseEventCuts[eTPCBadTracking] = false; + ec.fUseEventCuts[eTPCLimAccMCRepr] = false; + ec.fUseEventCuts[eTPCBadPID] = false; ec.fUseEventCuts[eTrigger] = true; ec.fsEventCuts[eTrigger] = "kINT7"; // TBI 20250115 remember that it cannot be used when i procees in "Rec" some converted Run 2 MC, see enum @@ -2425,6 +2638,12 @@ void SpecificCuts(TString whichSpecificCuts) ec.fUseEventCuts[eIsGoodITSLayer3] = false; ec.fUseEventCuts[eIsGoodITSLayer0123] = false; ec.fUseEventCuts[eIsGoodITSLayersAll] = false; + ec.fUseEventCuts[eFT0Bad] = false; + ec.fUseEventCuts[eITSBad] = false; + ec.fUseEventCuts[eITSLimAccMCRepr] = false; + ec.fUseEventCuts[eTPCBadTracking] = false; + ec.fUseEventCuts[eTPCLimAccMCRepr] = false; + ec.fUseEventCuts[eTPCBadPID] = false; // ec.fUseEventCuts[eTrigger] = true; // ec.fsEventCuts[eTrigger] = "kINT7"; // TBI 20250115 cannot be used when i procees in "Rec" some converted Run 2 MC, see enum @@ -2680,21 +2899,20 @@ void InsanityChecksBeforeBooking() } // **) Enforce the usage of particular trigger for this dataset: - if (tc.fProcess[eProcessRec_Run2]) { - // TBI 20250115 Not really sure I need this - if I want to run only "Rec" over Monte Carlo, then obviously the condition below is pointless. - // Also here I need to be able automaticaly to determine whether I am processing real data or Monte Carlo, from the dataset itself. - // TBI 20240517 for the time being, here I am enforcing that "kINT7" is mandatory for Run 2 - // TBI 20241209 I still have to validate it for Run 1 converted real data => then expand if(...) statement above - - /* commented out temporariy, see TBI 20250115 above - if (!(ec.fUseEventCuts[eTrigger] && ec.fsEventCuts[eTrigger].EqualTo("kINT7"))) { - LOGF(fatal, "\033[1;31m%s at line %d : trigger \"%s\" is not internally validated/supported yet. Add it to the list of supported triggers, if you really want to use that one.\033[0m", __FUNCTION__, __LINE__, ec.fsEventCuts[eTrigger].Data()); - } else { - LOGF(info, "\033[1;32m%s at line %d : WARNING => trigger \"%s\" can be used only on real converted Run 2 and Run 1 data. For MC converted Run 2 and Run 1 data, this trigger shouldn't be used.\033[0m", __FUNCTION__, __LINE__, ec.fsEventCuts[eTrigger].Data()); - // TBI 20240517 I need here programmatic access to "event-selection-task" flags "isMC and "isRunMC" . Then I can directly bail out. - } - */ - } + // if (tc.fProcess[eProcessRec_Run2]) { + // TBI 20250115 Not really sure I need this - if I want to run only "Rec" over Monte Carlo, then obviously the condition below is pointless. + // Also here I need to be able automaticaly to determine whether I am processing real data or Monte Carlo, from the dataset itself. + // TBI 20240517 for the time being, here I am enforcing that "kINT7" is mandatory for Run 2 + // TBI 20241209 I still have to validate it for Run 1 converted real data => then expand if(...) statement above + + // commented out temporariy, see TBI 20250115 above + // if (!(ec.fUseEventCuts[eTrigger] && ec.fsEventCuts[eTrigger].EqualTo("kINT7"))) { + // LOGF(fatal, "\033[1;31m%s at line %d : trigger \"%s\" is not internally validated/supported yet. Add it to the list of supported triggers, if you really want to use that one.\033[0m", __FUNCTION__, __LINE__, ec.fsEventCuts[eTrigger].Data()); + // } else { + // LOGF(info, "\033[1;32m%s at line %d : WARNING => trigger \"%s\" can be used only on real converted Run 2 and Run 1 data. For MC converted Run 2 and Run 1 data, this trigger shouldn't be used.\033[0m", __FUNCTION__, __LINE__, ec.fsEventCuts[eTrigger].Data()); + // // TBI 20240517 I need here programmatic access to "event-selection-task" flags "isMC and "isRunMC" . Then I can directly bail out. + // } + // } // **) Ensure that fFloatingPointPrecision makes sense: if (!(tc.fFloatingPointPrecision > 0.)) { @@ -2717,6 +2935,11 @@ void InsanityChecksBeforeBooking() LOGF(fatal, "\033[1;31m%s at line %d : set eDiffEtaWeights_N = %d is bigger than gMaxNumberSparseDimensions = %d\033[0m", __FUNCTION__, __LINE__, static_cast(eDiffEtaWeights_N), gMaxNumberSparseDimensions); } + // ** For simulated data when fDatabasePDG is NOT used, I have to disable cut on charge, since that info is not available: + if ((tc.fProcess[eGenericRecSim] || tc.fProcess[eGenericSim]) && pc.fUseParticleCuts[eCharge] && !tc.fUseDatabasePDG) { + LOGF(fatal, "\033[1;31m%s at line %d : For simulated data when fDatabasePDG is NOT used, I have to disable cut on charge, since that info is not available:\033[0m", __FUNCTION__, __LINE__); + } + // b) Ensure that Run 1/2 specific cuts and flags are used only in Run 1/2 (both data and sim): // **) Ensure that eSel7 is used only for converted Run 2 and Run 1 (both data and sim): if (ec.fUseEventCuts[eSel7]) { @@ -2878,6 +3101,12 @@ void InsanityChecksBeforeBooking() } } + if (ec.fUseEventCuts[eFT0Bad] || ec.fUseEventCuts[eITSBad] || ec.fUseEventCuts[eITSLimAccMCRepr] || ec.fUseEventCuts[eTPCBadTracking] || ec.fUseEventCuts[eTPCLimAccMCRepr] || ec.fUseEventCuts[eTPCBadPID]) { + if (!(tc.fProcess[eProcessRec] || tc.fProcess[eProcessRecSim] || tc.fProcess[eProcessSim] || tc.fProcess[eProcessQA])) { + LOGF(fatal, "\033[1;31m%s at line %d : use eFT0Bad, eITSBad, eITSLimAccMCRepr, eTPCBadTracking, eTPCLimAccMCRepr, eTPCBadPID only for Run 3 data and MC\033[0m", __FUNCTION__, __LINE__); + } + } + // **) Supported reference multiplicity estimators for Run 3 are enlisted here: if (tc.fProcess[eProcessRec] || tc.fProcess[eProcessRecSim] || tc.fProcess[eProcessQA]) { if (!(ec.fsEventCuts[eReferenceMultiplicityEstimator].EqualTo("MultTPC", TString::kIgnoreCase) || @@ -3064,6 +3293,42 @@ void InsanityChecksAfterBooking() //============================================================ +void PurgeAfterBooking() +{ + // I can purge a few objects used for common consistent booking across different group of histograms. + + // TBI 20250518 I now automatically purge only 2D and 3D objects, I can refine further an purge also the lighte objects, if necessary + + // a) Purge results histograms and related objects; + // ... + + if (tc.fVerbose) { + StartFunction(__FUNCTION__); + } + + // a) Purge results histograms and related objects: + if (!res.fSaveResultsHistograms) { + for (int v = 0; v < eAsFunctionOf2D_N; v++) { + if (res.fResultsPro2D[v]) { + delete res.fResultsPro2D[v]; + } + } + + for (int v = 0; v < eAsFunctionOf3D_N; v++) { + if (res.fResultsPro3D[v]) { + delete res.fResultsPro3D[v]; + } + } + } // if(!res.fSaveResultsHistograms) + + if (tc.fVerbose) { + ExitFunction(__FUNCTION__); + } + +} // void PurgeAfterBooking() + +//============================================================ + bool Skip(int recOrSim) { // Decide here whether a certain histogram, etc., will be booked and used both for eRec and eSim. @@ -3260,7 +3525,7 @@ void BookAndNestAllLists() } // void BookAndNestAllLists() -//============================================================ +//========================================================== void BookQAHistograms() { @@ -3281,13 +3546,14 @@ void BookQAHistograms() } // *) Print the warning message, because with too many 2D histograms with double precision, the code crashes in terminate, due to: - /* - [1450742:multiparticle-correlations-a-b]: [13:30:27][STATE] Exiting FairMQ state machine - [1450742:multiparticle-correlations-a-b]: [13:30:27][FATAL] error while setting up workflow in o2-analysis-cf-multiparticle-correlations-ab: shmem: could not create a message of size 1282720912, alignment: 64, free memory: 1358639296 - [1450742:multiparticle-correlations-a-b]: terminate called after throwing an instance of 'o2::framework::RuntimeErrorRef' - [1450742:multiparticle-correlations-a-b]: *** Program crashed (Aborted) - [1450742:multiparticle-correlations-a-b]: Backtrace by DPL: - */ + // + // [1450742:multiparticle-correlations-a-b]: [13:30:27][STATE] Exiting FairMQ state machine + // [1450742:multiparticle-correlations-a-b]: [13:30:27][FATAL] error while setting up workflow in o2-analysis-cf-multiparticle-correlations-ab: shmem: could not create a message of size 1282720912, alignment: 64, free memory: 1358639296 + // [1450742:multiparticle-correlations-a-b]: terminate called after throwing an instance of 'o2::framework::RuntimeErrorRef' + // [1450742:multiparticle-correlations-a-b]: *** Program crashed (Aborted) + // [1450742:multiparticle-correlations-a-b]: Backtrace by DPL: + // + if (tc.fVerbose) { LOGF(info, "\033[1;33m%s: !!!! WARNING !!!! With too many 2D histograms with double precision, the code will crash in terminate (\"... shmem: could not create a message of size ...\") . Locally, you can circumvent this while testing by calling Bailout() explicitly. !!!! WARNING !!!! \033[0m", __FUNCTION__); } @@ -4855,7 +5121,10 @@ void BookParticleHistograms() delete lAxis; ph.fParticleSparseHistogramsAxisTitle[eDWPhi][wPhiPhiAxis] = FancyFormatting("Phi"); - // ***) pt-axis for diff phi weights: I re-use binning from results histograms + // ***) pt-axis for diff phi weights - I re-use binning from results histograms: + if (!res.fResultsPro[AFO_PT]) { + LOGF(fatal, "\033[1;31m%s at line %d : res.fResultsPro[AFO_PT] is NULL \033[0m", __FUNCTION__, __LINE__); + } ph.fParticleSparseHistogramsNBins[eDWPhi][wPhiPtAxis] = res.fResultsPro[AFO_PT]->GetNbinsX(); lAxis = res.fResultsPro[AFO_PT]->GetXaxis(); ph.fParticleSparseHistogramsBinEdges[eDWPhi][wPhiPtAxis] = new TArrayD(1 + ph.fParticleSparseHistogramsNBins[eDWPhi][wPhiPtAxis]); @@ -4866,7 +5135,10 @@ void BookParticleHistograms() // delete lAxis; // I do not need to delete here, only when new TAxis(...) ph.fParticleSparseHistogramsAxisTitle[eDWPhi][wPhiPtAxis] = FancyFormatting("Pt"); - // ***) eta-axis for diff phi weights: I re-use binning from results histograms + // ***) eta-axis for diff phi weights - I re-use binning from results histograms: + if (!res.fResultsPro[AFO_ETA]) { + LOGF(fatal, "\033[1;31m%s at line %d : res.fResultsPro[AFO_ETA] is NULL \033[0m", __FUNCTION__, __LINE__); + } ph.fParticleSparseHistogramsNBins[eDWPhi][wPhiEtaAxis] = res.fResultsPro[AFO_ETA]->GetNbinsX(); lAxis = res.fResultsPro[AFO_ETA]->GetXaxis(); ph.fParticleSparseHistogramsBinEdges[eDWPhi][wPhiEtaAxis] = new TArrayD(1 + ph.fParticleSparseHistogramsNBins[eDWPhi][wPhiEtaAxis]); @@ -4877,9 +5149,12 @@ void BookParticleHistograms() // delete lAxis; // I do not need to delete here, only when new TAxis(...) ph.fParticleSparseHistogramsAxisTitle[eDWPhi][wPhiEtaAxis] = FancyFormatting("Eta"); - // ***) charge-axis for diff phi weights: I support only fixed-length binning, nothing really to ever change here: - ph.fParticleSparseHistogramsNBins[eDWPhi][wPhiChargeAxis] = 2; - lAxis = new TAxis(ph.fParticleSparseHistogramsNBins[eDWPhi][wPhiChargeAxis], -1.5, 1.5); + // ***) charge-axis for diff phi weights - I re-use binning from results histograms: + if (!res.fResultsPro[AFO_CHARGE]) { + LOGF(fatal, "\033[1;31m%s at line %d : res.fResultsPro[AFO_CHARGE] is NULL \033[0m", __FUNCTION__, __LINE__); + } + ph.fParticleSparseHistogramsNBins[eDWPhi][wPhiChargeAxis] = res.fResultsPro[AFO_CHARGE]->GetNbinsX(); + lAxis = res.fResultsPro[AFO_CHARGE]->GetXaxis(); ph.fParticleSparseHistogramsBinEdges[eDWPhi][wPhiChargeAxis] = new TArrayD(1 + ph.fParticleSparseHistogramsNBins[eDWPhi][wPhiChargeAxis]); for (int bin = 1; bin <= lAxis->GetNbins(); bin++) { ph.fParticleSparseHistogramsBinEdges[eDWPhi][wPhiChargeAxis]->AddAt(lAxis->GetBinLowEdge(bin), bin - 1); @@ -4888,7 +5163,10 @@ void BookParticleHistograms() // delete lAxis; // I do not need to delete here, only when new TAxis(...) ph.fParticleSparseHistogramsAxisTitle[eDWPhi][wPhiChargeAxis] = FancyFormatting("Charge"); - // ***) centrality-axis for diff phi weights: I re-use binning from results histograms + // ***) centrality-axis for diff phi weights - I re-use binning from results histograms: + if (!res.fResultsPro[AFO_CENTRALITY]) { + LOGF(fatal, "\033[1;31m%s at line %d : res.fResultsPro[AFO_CENTRALITY] is NULL \033[0m", __FUNCTION__, __LINE__); + } ph.fParticleSparseHistogramsNBins[eDWPhi][wPhiCentralityAxis] = res.fResultsPro[AFO_CENTRALITY]->GetNbinsX(); lAxis = res.fResultsPro[AFO_CENTRALITY]->GetXaxis(); ph.fParticleSparseHistogramsBinEdges[eDWPhi][wPhiCentralityAxis] = new TArrayD(1 + ph.fParticleSparseHistogramsNBins[eDWPhi][wPhiCentralityAxis]); @@ -4899,7 +5177,10 @@ void BookParticleHistograms() // delete lAxis; // I do not need to delete here, only when new TAxis(...) ph.fParticleSparseHistogramsAxisTitle[eDWPhi][wPhiCentralityAxis] = "Centrality"; // TBI 20250222 I cannot call here FancyFormatting for "Centrality", because ec.fsEventCuts[eCentralityEstimator] is still not fetched and set from configurable. Re-think how to proceed for this specific case. - // ***) VertexZ-axis for diff phi weights: I re-use binning from results histograms + // ***) VertexZ-axis for diff phi weights - I re-use binning from results histograms: + if (!res.fResultsPro[AFO_VZ]) { + LOGF(fatal, "\033[1;31m%s at line %d : res.fResultsPro[AFO_VZ] is NULL \033[0m", __FUNCTION__, __LINE__); + } ph.fParticleSparseHistogramsNBins[eDWPhi][wPhiVertexZAxis] = res.fResultsPro[AFO_VZ]->GetNbinsX(); lAxis = res.fResultsPro[AFO_VZ]->GetXaxis(); ph.fParticleSparseHistogramsBinEdges[eDWPhi][wPhiVertexZAxis] = new TArrayD(1 + ph.fParticleSparseHistogramsNBins[eDWPhi][wPhiVertexZAxis]); @@ -4914,7 +5195,10 @@ void BookParticleHistograms() // **) eDiffWeightCategory = eDWPt: - // ***) pt-axis for diff pt weights: I re-use binning from results histograms + // ***) pt-axis for diff pt weights - I re-use binning from results histograms: + if (!res.fResultsPro[AFO_PT]) { + LOGF(fatal, "\033[1;31m%s at line %d : res.fResultsPro[AFO_PT] is NULL \033[0m", __FUNCTION__, __LINE__); + } ph.fParticleSparseHistogramsNBins[eDWPt][wPtPtAxis] = res.fResultsPro[AFO_PT]->GetNbinsX(); lAxis = res.fResultsPro[AFO_PT]->GetXaxis(); ph.fParticleSparseHistogramsBinEdges[eDWPt][wPtPtAxis] = new TArrayD(1 + ph.fParticleSparseHistogramsNBins[eDWPt][wPtPtAxis]); @@ -4925,11 +5209,42 @@ void BookParticleHistograms() // delete lAxis; // I do not need to delete here, only when new TAxis(...) ph.fParticleSparseHistogramsAxisTitle[eDWPt][wPtPtAxis] = FancyFormatting("Pt"); + // ***) charge-axis for diff pt weights - I re-use binning from results histograms: + if (!res.fResultsPro[AFO_CHARGE]) { + LOGF(fatal, "\033[1;31m%s at line %d : res.fResultsPro[AFO_CHARGE] is NULL \033[0m", __FUNCTION__, __LINE__); + } + ph.fParticleSparseHistogramsNBins[eDWPt][wPtChargeAxis] = res.fResultsPro[AFO_CHARGE]->GetNbinsX(); + lAxis = res.fResultsPro[AFO_CHARGE]->GetXaxis(); + ph.fParticleSparseHistogramsBinEdges[eDWPt][wPtChargeAxis] = new TArrayD(1 + ph.fParticleSparseHistogramsNBins[eDWPt][wPtChargeAxis]); + for (int bin = 1; bin <= lAxis->GetNbins(); bin++) { + ph.fParticleSparseHistogramsBinEdges[eDWPt][wPtChargeAxis]->AddAt(lAxis->GetBinLowEdge(bin), bin - 1); + } + ph.fParticleSparseHistogramsBinEdges[eDWPt][wPtChargeAxis]->AddAt(lAxis->GetBinLowEdge(1 + lAxis->GetNbins()), lAxis->GetNbins()); // special treatment for last bin + // delete lAxis; // I do not need to delete here, only when new TAxis(...) + ph.fParticleSparseHistogramsAxisTitle[eDWPt][wPtChargeAxis] = FancyFormatting("Charge"); + + // ***) centrality-axis for diff pt weights - I re-use binning from results histograms: + if (!res.fResultsPro[AFO_CENTRALITY]) { + LOGF(fatal, "\033[1;31m%s at line %d : res.fResultsPro[AFO_CENTRALITY] is NULL \033[0m", __FUNCTION__, __LINE__); + } + ph.fParticleSparseHistogramsNBins[eDWPt][wPtCentralityAxis] = res.fResultsPro[AFO_CENTRALITY]->GetNbinsX(); + lAxis = res.fResultsPro[AFO_CENTRALITY]->GetXaxis(); + ph.fParticleSparseHistogramsBinEdges[eDWPt][wPtCentralityAxis] = new TArrayD(1 + ph.fParticleSparseHistogramsNBins[eDWPt][wPtCentralityAxis]); + for (int bin = 1; bin <= lAxis->GetNbins(); bin++) { + ph.fParticleSparseHistogramsBinEdges[eDWPt][wPtCentralityAxis]->AddAt(lAxis->GetBinLowEdge(bin), bin - 1); + } + ph.fParticleSparseHistogramsBinEdges[eDWPt][wPtCentralityAxis]->AddAt(lAxis->GetBinLowEdge(1 + lAxis->GetNbins()), lAxis->GetNbins()); // special treatment for last bin + // delete lAxis; // I do not need to delete here, only when new TAxis(...) + ph.fParticleSparseHistogramsAxisTitle[eDWPt][wPtCentralityAxis] = "Centrality"; // TBI 20250222 I cannot call here FancyFormatting for "Centrality", because ec.fsEventCuts[eCentralityEstimator] is still not fetched and set from configurable. Re-think how to proceed for this specific case. + // ... // **) eDiffWeightCategory = eDWEta: - // ***) eta-axis for diff eta weights: I re-use binning from results histograms + // ***) eta-axis for diff eta weights - I re-use binning from results histograms: + if (!res.fResultsPro[AFO_ETA]) { + LOGF(fatal, "\033[1;31m%s at line %d : res.fResultsPro[AFO_ETA] is NULL \033[0m", __FUNCTION__, __LINE__); + } ph.fParticleSparseHistogramsNBins[eDWEta][wEtaEtaAxis] = res.fResultsPro[AFO_ETA]->GetNbinsX(); lAxis = res.fResultsPro[AFO_ETA]->GetXaxis(); ph.fParticleSparseHistogramsBinEdges[eDWEta][wEtaEtaAxis] = new TArrayD(1 + ph.fParticleSparseHistogramsNBins[eDWEta][wEtaEtaAxis]); @@ -4940,6 +5255,34 @@ void BookParticleHistograms() // delete lAxis; // I do not need to delete here, only when new TAxis(...) ph.fParticleSparseHistogramsAxisTitle[eDWEta][wEtaEtaAxis] = FancyFormatting("Eta"); + // ***) charge-axis for diff eta weights - I re-use binning from results histograms: + if (!res.fResultsPro[AFO_CHARGE]) { + LOGF(fatal, "\033[1;31m%s at line %d : res.fResultsPro[AFO_CHARGE] is NULL \033[0m", __FUNCTION__, __LINE__); + } + ph.fParticleSparseHistogramsNBins[eDWEta][wEtaChargeAxis] = res.fResultsPro[AFO_CHARGE]->GetNbinsX(); + lAxis = res.fResultsPro[AFO_CHARGE]->GetXaxis(); + ph.fParticleSparseHistogramsBinEdges[eDWEta][wEtaChargeAxis] = new TArrayD(1 + ph.fParticleSparseHistogramsNBins[eDWEta][wEtaChargeAxis]); + for (int bin = 1; bin <= lAxis->GetNbins(); bin++) { + ph.fParticleSparseHistogramsBinEdges[eDWEta][wEtaChargeAxis]->AddAt(lAxis->GetBinLowEdge(bin), bin - 1); + } + ph.fParticleSparseHistogramsBinEdges[eDWEta][wEtaChargeAxis]->AddAt(lAxis->GetBinLowEdge(1 + lAxis->GetNbins()), lAxis->GetNbins()); // special treatment for last bin + // delete lAxis; // I do not need to delete here, only when new TAxis(...) + ph.fParticleSparseHistogramsAxisTitle[eDWEta][wEtaChargeAxis] = FancyFormatting("Charge"); + + // ***) centrality-axis for diff eta weights - I re-use binning from results histograms: + if (!res.fResultsPro[AFO_CENTRALITY]) { + LOGF(fatal, "\033[1;31m%s at line %d : res.fResultsPro[AFO_CENTRALITY] is NULL \033[0m", __FUNCTION__, __LINE__); + } + ph.fParticleSparseHistogramsNBins[eDWEta][wEtaCentralityAxis] = res.fResultsPro[AFO_CENTRALITY]->GetNbinsX(); + lAxis = res.fResultsPro[AFO_CENTRALITY]->GetXaxis(); + ph.fParticleSparseHistogramsBinEdges[eDWEta][wEtaCentralityAxis] = new TArrayD(1 + ph.fParticleSparseHistogramsNBins[eDWEta][wEtaCentralityAxis]); + for (int bin = 1; bin <= lAxis->GetNbins(); bin++) { + ph.fParticleSparseHistogramsBinEdges[eDWEta][wEtaCentralityAxis]->AddAt(lAxis->GetBinLowEdge(bin), bin - 1); + } + ph.fParticleSparseHistogramsBinEdges[eDWEta][wEtaCentralityAxis]->AddAt(lAxis->GetBinLowEdge(1 + lAxis->GetNbins()), lAxis->GetNbins()); // special treatment for last bin + // delete lAxis; // I do not need to delete here, only when new TAxis(...) + ph.fParticleSparseHistogramsAxisTitle[eDWEta][wEtaCentralityAxis] = "Centrality"; // TBI 20250222 I cannot call here FancyFormatting for "Centrality", because ec.fsEventCuts[eCentralityEstimator] is still not fetched and set from configurable. Re-think how to proceed for this specific case. + // ... // e) Book specific particle sparse histograms (n-dimensions): @@ -5149,8 +5492,9 @@ void BookQvectorHistograms() // Book all Q-vector histograms. // a) Book the profile holding flags; - // b) Book multiplicity distributions in A and B, for each eta separation; - // c) ... + // b) Differential q-vectors booked dynamically: + // c) Book multiplicity distributions in A and B, for each eta separation; + // d) ... if (tc.fVerbose) { StartFunction(__FUNCTION__); @@ -5206,7 +5550,112 @@ void BookQvectorHistograms() qv.fQvectorList->Add(qv.fQvectorFlagsPro); - // b) Book multiplicity distributions in A and B, for each eta separation: + // b) Differential q-vectors booked dynamically: + // Remark: Here I am slighthly generalizing the great example provided at https://cplusplus.com/forum/articles/7459/ + + // b1) book qv.fqvector and qv.fqvectorEntries : + // dimensions: [eqvectorKine_N][gMaxNoBinsKine][gMaxHarmonic * gMaxCorrelator + 1][gMaxCorrelator + 1] => keep in sync with the documentation in the header + // here I am calculating for each dimensions how many entries I need in a given analysis + if (qv.fCalculateqvectorsKineAny) { + qv.fNumberOfKineBins.resize(eqvectorKine_N); // this is the light object, so I can hardwire here eqvectorKine_N + // then, in NumberOfKineVectors() i will store bins ONLY for qvectorKine which were requested. + // Therefore, final ordering in will correspond to the ordering in enum eqvectorKine ONLY if all kine vectors were requested. + // Otherwise, I fill here bins only for kine vectors which were requested, in consequtive order, starting from 0. + + int dim1 = eqvectorKine_N; + // int dim2 = number of kine bins => I calculate this one dynamically for each qVectorKine, see the loop below + NumberOfKineBins(); // here I calculate and fill qv.fNumberOfKineBins[ ... ] + int dim3 = gMaxHarmonic * gMaxCorrelator + 1; // TBI 20250601 I could dinamically allocate this one as well, but this will trigger another major re-design, and it's not rally a big deal + int dim4 = gMaxCorrelator + 1; // TBI 20250601 I could dinamically allocate this one as well, but this will trigger another major re-design, and it's not really a big deal + + qv.fqvector.resize(dim1); + qv.fqvectorEntries.resize(dim1); + + for (int i = 0; i < dim1; ++i) { // here I am looping over entries in enum eqvectorKine + if (qv.fCalculateqvectorsKine[i]) { + qv.fqvector[i].resize(qv.fNumberOfKineBins[i]); // yes, qv.fNumberOfKineBins[i] => for each qvectorkine I calculate and dynamically allocate only necessary bins + qv.fqvectorEntries[i].resize(qv.fNumberOfKineBins[i]); + } else { + // calculus for this kine variable is not needed, I am ironing out this dimension + qv.fqvector[i].resize(0); + qv.fqvectorEntries[i].resize(0); + } + + for (int j = 0; j < qv.fNumberOfKineBins[i]; ++j) { + if (qv.fCalculateqvectorsKine[i]) { + qv.fqvector[i][j].resize(dim3); + } else { + // calculus for this kine variable is not needed, I am ironing out this dimension + qv.fqvector[i][j].resize(0); + } + + for (int k = 0; k < dim3; ++k) { + if (qv.fCalculateqvectorsKine[i]) { + qv.fqvector[i][j][k].resize(dim4); + } else { + // calculus for this kine variable is not needed, I am ironing out this dimension + qv.fqvector[i][j][k].resize(0); + } + } + } + } // for (int i = 0; i < dim1; ++i) + + // b2) book qv.fqabVector and qv.fmab (differential q-vectors with eta separations): + // dimensions: [-eta or +eta][eqvectorKine_N][global binNo][harmonic][eta separation] => keep in sync with the documentation in the header + // here I am calculating for each dimensions how many entries I need in a given analysis + + if (es.fCalculateEtaSeparations) { + int dim1 = 2; // -eta or eta + int dim2 = eqvectorKine_N; + // int dim3 = number of kine bins => I calculated this one dynamically for each qVectorKine, see the loop below + // NumberOfKineBins(); // here I calculate and fill qv.fNumberOfKineBins[ ... ] => I did it already above for qv.fqvector + int dim4 = gMaxHarmonic; + int dim5 = gMaxNumberEtaSeparations; + qv.fqabVector.resize(dim1); + qv.fmab.resize(dim1); + + for (int i = 0; i < dim1; ++i) { // here I am looping over -eta or eta + qv.fqabVector[i].resize(dim2); + qv.fmab[i].resize(dim2); + + for (int j = 0; j < dim2; ++j) { // here I am looping over entries in enum eqvectorKine + + if (qv.fCalculateqvectorsKineEtaSeparations[j]) { + qv.fqabVector[i][j].resize(qv.fNumberOfKineBins[j]); // yes, qv.fNumberOfKineBins[j] => for each qvectorkine I calculate and dynamically allocate only necessary bins + qv.fmab[i][j].resize(qv.fNumberOfKineBins[j]); + } else { + // calculus for this kine variable is not needed, I am ironing out this dimension + qv.fqabVector[i][j].resize(0); + qv.fmab[i][j].resize(0); + } + + for (int k = 0; k < qv.fNumberOfKineBins[j]; ++k) { + if (qv.fCalculateqvectorsKineEtaSeparations[j]) { + qv.fqabVector[i][j][k].resize(dim4); + qv.fmab[i][j][k].resize(dim5); // yes, directly dim5, because this one doesn't depend on harmonics + } else { + // calculus for this kine variable is not needed, I am ironing out this dimension + // I have already in the previous loop ironed out for qv.fCalculateqvectorsKineEtaSeparations[j] = false, so no need to do it here again + // TBI 20250620 validate what happens here + } + + for (int l = 0; l < dim4; ++l) { // loop over harmonics + if (qv.fCalculateqvectorsKineEtaSeparations[j] && !es.fEtaSeparationsSkipHarmonics[l]) { + qv.fqabVector[i][j][k][l].resize(dim5); + // no need to resize qv.fmab here, because this one doesn't depend on harmonics + } else { + // calculus for this kine variable is not needed, I am ironing out this dimension + // I have already in the previous loop ironed out for qv.fCalculateqvectorsKineEtaSeparations[j] = false, so no need to do it here again + // TBI 20250620 validate what happens here + } + } // for (int l = 0; l < dim4; ++l) + } // for (int k = 0; k < qv.fNumberOfKineBins[j]; ++k) + } // for (int j = 0; j < dim2; ++j) + } // for (int i = 0; i < dim1; ++i) + } // if(es.fCalculateEtaSeparations) + } // if(qv.fCalculateqvectorsKineAny) + + // c) Book multiplicity distributions in A and B, for each eta separation: if (es.fCalculateEtaSeparations) { TString sEtaSep[2] = {"A", "B"}; // A <=> -eta , B <=> + eta TString sEtaSep_long[2] = {TString::Format("%.2f < #eta <", pc.fdParticleCuts[eEta][eMin]), TString::Format("< #eta < %.2f", pc.fdParticleCuts[eEta][eMax])}; @@ -5251,6 +5700,53 @@ void BookQvectorHistograms() //============================================================ +void NumberOfKineBins() +{ + // Helper function called only in void BookQvectorHistograms(), if kine analysis was requested. + // I calculate for each requested kine vector the number of kine bins => this is stored in dynamically allocated array qv.fNumberOfKineBins. + + if (tc.fVerbose) { + StartFunction(__FUNCTION__); + } + + // 1D kine: + if (qv.fCalculateqvectorsKine[PTq]) { + qv.fNumberOfKineBins[PTq] = res.fResultsPro[AFO_PT]->GetNbinsX() + 2; // + 2 means that I take into account overflow and underflow, then skip it in the loop below + } + if (qv.fCalculateqvectorsKine[ETAq]) { + qv.fNumberOfKineBins[ETAq] = res.fResultsPro[AFO_ETA]->GetNbinsX() + 2; // + 2 means that I take into account overflow and underflow, then skip it in the loop below + } + if (qv.fCalculateqvectorsKine[CHARGEq]) { + qv.fNumberOfKineBins[CHARGEq] = res.fResultsPro[AFO_CHARGE]->GetNbinsX() + 2; // + 2 means that I take into account overflow and underflow, then skip it in the loop below + } + // ... + + // 2D kine: + if (qv.fCalculateqvectorsKine[PT_ETAq]) { + qv.fNumberOfKineBins[PT_ETAq] = (res.fResultsPro2D[AfoKineMap2D(PT_ETAq)]->GetNbinsX() + 2) * (res.fResultsPro2D[AfoKineMap2D(PT_ETAq)]->GetNbinsY() + 2); // + 2 means that I take into account overflow and underflow, then skip it in the loop below + } + if (qv.fCalculateqvectorsKine[PT_CHARGEq]) { + qv.fNumberOfKineBins[PT_CHARGEq] = (res.fResultsPro2D[AfoKineMap2D(PT_CHARGEq)]->GetNbinsX() + 2) * (res.fResultsPro2D[AfoKineMap2D(PT_CHARGEq)]->GetNbinsY() + 2); // + 2 means that I take into account overflow and underflow, then skip it in the loop below + } + if (qv.fCalculateqvectorsKine[ETA_CHARGEq]) { + qv.fNumberOfKineBins[ETA_CHARGEq] = (res.fResultsPro2D[AfoKineMap2D(ETA_CHARGEq)]->GetNbinsX() + 2) * (res.fResultsPro2D[AfoKineMap2D(ETA_CHARGEq)]->GetNbinsY() + 2); // + 2 means that I take into account overflow and underflow, then skip it in the loop below + } + // ... + + // 3D kine: + if (qv.fCalculateqvectorsKine[PT_ETA_CHARGEq]) { + qv.fNumberOfKineBins[PT_ETA_CHARGEq] = (res.fResultsPro3D[AfoKineMap3D(PT_ETA_CHARGEq)]->GetNbinsX() + 2) * (res.fResultsPro3D[AfoKineMap3D(PT_ETA_CHARGEq)]->GetNbinsY() + 2) * (res.fResultsPro3D[AfoKineMap3D(PT_ETA_CHARGEq)]->GetNbinsZ() + 2); // + 2 means that I take into account overflow and underflow, then skip it in the loop below + } + // ... + + if (tc.fVerbose) { + ExitFunction(__FUNCTION__); + } + +} // void NumberOfKineBins() + +//============================================================ + void BookCorrelationsHistograms() { // Book all correlations histograms. @@ -5323,50 +5819,19 @@ void BookCorrelationsHistograms() for (int v = 0; v < eAsFunctionOf_N; v++) { // decide what is booked, then later valid pointer to fCorrelationsPro[k][n][v] is used as a boolean, in the standard way: - if (AFO_INTEGRATED == v && !mupa.fCalculateCorrelationsAsFunctionOf[AFO_INTEGRATED]) { - continue; - } - if (AFO_MULTIPLICITY == v && !mupa.fCalculateCorrelationsAsFunctionOf[AFO_MULTIPLICITY]) { - continue; - } - if (AFO_CENTRALITY == v && !mupa.fCalculateCorrelationsAsFunctionOf[AFO_CENTRALITY]) { - continue; - } - if (AFO_PT == v && !mupa.fCalculateCorrelationsAsFunctionOf[AFO_PT]) { - continue; - } - if (AFO_ETA == v && !mupa.fCalculateCorrelationsAsFunctionOf[AFO_ETA]) { - continue; - } - if (AFO_OCCUPANCY == v && !mupa.fCalculateCorrelationsAsFunctionOf[AFO_OCCUPANCY]) { - continue; - } - if (AFO_INTERACTIONRATE == v && !mupa.fCalculateCorrelationsAsFunctionOf[AFO_INTERACTIONRATE]) { - continue; - } - if (AFO_CURRENTRUNDURATION == v && !mupa.fCalculateCorrelationsAsFunctionOf[AFO_CURRENTRUNDURATION]) { - continue; - } - if (AFO_VZ == v && !mupa.fCalculateCorrelationsAsFunctionOf[AFO_VZ]) { + if (!mupa.fCalculateCorrelationsAsFunctionOf[v]) { continue; } if (!res.fResultsPro[v]) { - LOGF(fatal, "\033[1;31m%s at line %d\033[0m", __FUNCTION__, __LINE__); + LOGF(fatal, "\033[1;31m%s at line %d : fResultsPro[%d] is NULL, this shall never happen, but apparently it happened... \033[0m", __FUNCTION__, __LINE__, v); } if (tc.fUseClone) { mupa.fCorrelationsPro[k][n][v] = reinterpret_cast(res.fResultsPro[v]->Clone(Form("fCorrelationsPro[%d][%d][%s]", k, n, res.fResultsProRawName[v].Data()))); // yes } else { - // TBI 20250412 this branch is temporary workaround until hist->Clone(...) large memory consumption is resolved - if (res.fUseResultsProVariableLengthBins[v]) { - // per demand, variable-length binning: - mupa.fCorrelationsPro[k][n][v] = new TProfile(Form("fCorrelationsPro[%d][%d][%s]", k, n, res.fResultsProRawName[v].Data()), "", res.fResultsProVariableLengthBins[v]->GetSize() - 1, res.fResultsProVariableLengthBins[v]->GetArray()); - } else { - // the default fixed-length binning: - mupa.fCorrelationsPro[k][n][v] = new TProfile(Form("fCorrelationsPro[%d][%d][%s]", k, n, res.fResultsProRawName[v].Data()), "", static_cast(res.fResultsProFixedLengthBins[v][0]), res.fResultsProFixedLengthBins[v][1], res.fResultsProFixedLengthBins[v][2]); - } // else - } // else + mupa.fCorrelationsPro[k][n][v] = new TProfile(Form("fCorrelationsPro[%d][%d][%s]", k, n, res.fResultsProRawName[v].Data()), "", res.fResultsPro[v]->GetXaxis()->GetXbins()->GetSize() - 1, res.fResultsPro[v]->GetXaxis()->GetXbins()->GetArray()); + } mupa.fCorrelationsPro[k][n][v]->SetStats(false); mupa.fCorrelationsPro[k][n][v]->Sumw2(); @@ -5515,10 +5980,22 @@ void BookWeightsHistograms() if (pw.fUseDiffPtWeights[wPtPtAxis]) { pw.fWeightsFlagsPro->Fill(11.5, 1.); } + if (pw.fUseDiffPhiWeights[wPtChargeAxis]) { + pw.fWeightsFlagsPro->Fill(12.5, 1.); + } + if (pw.fUseDiffPhiWeights[wPtCentralityAxis]) { + pw.fWeightsFlagsPro->Fill(13.5, 1.); + } // **) differential eta weights using sparse: if (pw.fUseDiffEtaWeights[wEtaEtaAxis]) { - pw.fWeightsFlagsPro->Fill(12.5, 1.); + pw.fWeightsFlagsPro->Fill(14.5, 1.); + } + if (pw.fUseDiffPhiWeights[wEtaChargeAxis]) { + pw.fWeightsFlagsPro->Fill(15.5, 1.); + } + if (pw.fUseDiffPhiWeights[wEtaCentralityAxis]) { + pw.fWeightsFlagsPro->Fill(16.5, 1.); } pw.fWeightsList->Add(pw.fWeightsFlagsPro); @@ -5685,16 +6162,77 @@ void BookNestedLoopsHistograms() // *) Book containers for differential nested loops: if (nl.fCalculateKineCustomNestedLoops) { - const int iMaxSize = 2e4; - for (int b = 0; b < res.fResultsPro[AFO_PT]->GetNbinsX(); b++) { + + const int iMaxSize = 2e4; // this is roughly number of particles per bin, it shouldn't exceed this threshold + int nBins = -1; + + // 1D kine: + // **) vs. pt: + nBins = res.fResultsPro[AFO_PT]->GetNbinsX() + 2; // + 2 means that I take into account overflow and underflow, then skip later + for (int b = 0; b < nBins; b++) { nl.ftaNestedLoopsKine[PTq][b][0] = new TArrayD(iMaxSize); nl.ftaNestedLoopsKine[PTq][b][1] = new TArrayD(iMaxSize); } - for (int b = 0; b < res.fResultsPro[AFO_ETA]->GetNbinsX(); b++) { + + // **) vs. eta: + nBins = res.fResultsPro[AFO_ETA]->GetNbinsX() + 2; // + 2 means that I take into account overflow and underflow, then skip it later + for (int b = 0; b < nBins; b++) { nl.ftaNestedLoopsKine[ETAq][b][0] = new TArrayD(iMaxSize); nl.ftaNestedLoopsKine[ETAq][b][1] = new TArrayD(iMaxSize); } - } + + // **) vs. charge: + nBins = res.fResultsPro[AFO_CHARGE]->GetNbinsX() + 2; // + 2 means that I take into account overflow and underflow, then skip it later + for (int b = 0; b < nBins; b++) { + nl.ftaNestedLoopsKine[CHARGEq][b][0] = new TArrayD(iMaxSize); + nl.ftaNestedLoopsKine[CHARGEq][b][1] = new TArrayD(iMaxSize); + } + + // ... + + // 2D kine: + // **) vs. (pt,eta): + if (res.fResultsPro2D[AfoKineMap2D(PT_ETAq)]) { // this is safe, because this one shall be booked if any of Correlations, Test0, EtaSeparations, etc., was requested + nBins = (res.fResultsPro2D[AfoKineMap2D(PT_ETAq)]->GetNbinsX() + 2) * (res.fResultsPro2D[AfoKineMap2D(PT_ETAq)]->GetNbinsY() + 2); // + 2 means that I take into account overflow and underflow, then skip it in the loop below + for (int b = 0; b < nBins; b++) { // loop over lineralized global bins + nl.ftaNestedLoopsKine[PT_ETAq][b][0] = new TArrayD(iMaxSize); + nl.ftaNestedLoopsKine[PT_ETAq][b][1] = new TArrayD(iMaxSize); + } + } + + // **) vs. (pt,charge): + if (res.fResultsPro2D[AfoKineMap2D(PT_CHARGEq)]) { // this is safe, because this one shall be booked if any of Correlations, Test0, EtaSeparations, etc., was requested + nBins = (res.fResultsPro2D[AfoKineMap2D(PT_CHARGEq)]->GetNbinsX() + 2) * (res.fResultsPro2D[AfoKineMap2D(PT_CHARGEq)]->GetNbinsY() + 2); // + 2 means that I take into account overflow and underflow, then skip it in the loop below + for (int b = 0; b < nBins; b++) { // loop over lineralized global bins + nl.ftaNestedLoopsKine[PT_CHARGEq][b][0] = new TArrayD(iMaxSize); + nl.ftaNestedLoopsKine[PT_CHARGEq][b][1] = new TArrayD(iMaxSize); + } + } + + // **) vs. (eta,charge): + if (res.fResultsPro2D[AfoKineMap2D(ETA_CHARGEq)]) { // this is safe, because this one shall be booked if any of Correlations, Test0, EtaSeparations, etc., was requested + nBins = (res.fResultsPro2D[AfoKineMap2D(ETA_CHARGEq)]->GetNbinsX() + 2) * (res.fResultsPro2D[AfoKineMap2D(ETA_CHARGEq)]->GetNbinsY() + 2); // + 2 means that I take into account overflow and underflow, then skip it in the loop below + for (int b = 0; b < nBins; b++) { // loop over lineralized global bins + nl.ftaNestedLoopsKine[ETA_CHARGEq][b][0] = new TArrayD(iMaxSize); + nl.ftaNestedLoopsKine[ETA_CHARGEq][b][1] = new TArrayD(iMaxSize); + } + } + + // ... + + // 3D kine: + // **) vs. (pt,eta,charge): + if (res.fResultsPro3D[AfoKineMap3D(PT_ETA_CHARGEq)]) { // this is safe, because this one shall be booked if any of Correlations, Test0, EtaSeparations, etc., was requested + nBins = (res.fResultsPro3D[AfoKineMap3D(PT_ETA_CHARGEq)]->GetNbinsX() + 2) * (res.fResultsPro3D[AfoKineMap3D(PT_ETA_CHARGEq)]->GetNbinsY() + 2) * (res.fResultsPro3D[AfoKineMap3D(PT_ETA_CHARGEq)]->GetNbinsZ() + 2); // + 2 means that I take into account overflow and underflow, then skip it in the loop below + for (int b = 0; b < nBins; b++) { // loop over lineralized global bins + nl.ftaNestedLoopsKine[PT_ETA_CHARGEq][b][0] = new TArrayD(iMaxSize); + nl.ftaNestedLoopsKine[PT_ETA_CHARGEq][b][1] = new TArrayD(iMaxSize); + } + } + + // ... + + } // if (nl.fCalculateKineCustomNestedLoops) // b) Common local labels (keep 'em in sync with BookCorrelationsHistograms()) TString oVariable[4] = { @@ -5723,30 +6261,21 @@ void BookNestedLoopsHistograms() if (tc.fUseClone) { nl.fNestedLoopsPro[k][n][v] = reinterpret_cast(res.fResultsPro[v]->Clone(Form("fNestedLoopsPro[%d][%d][%d]", k, n, v))); // yes } else { - // TBI 20250412 this branch is temporary workaround until hist->Clone(...) large memory consumption is resolved - if (res.fUseResultsProVariableLengthBins[v]) { - // per demand, variable-length binning: - nl.fNestedLoopsPro[k][n][v] = new TProfile(Form("fNestedLoopsPro[%d][%d][%s]", k, n, res.fResultsProRawName[v].Data()), "", res.fResultsProVariableLengthBins[v]->GetSize() - 1, res.fResultsProVariableLengthBins[v]->GetArray()); - } else { - // the default fixed-length binning: - nl.fNestedLoopsPro[k][n][v] = new TProfile(Form("fNestedLoopsPro[%d][%d][%s]", k, n, res.fResultsProRawName[v].Data()), "", static_cast(res.fResultsProFixedLengthBins[v][0]), res.fResultsProFixedLengthBins[v][1], res.fResultsProFixedLengthBins[v][2]); - } // else - } // else + nl.fNestedLoopsPro[k][n][v] = new TProfile(Form("fNestedLoopsPro[%d][%d][%s]", k, n, res.fResultsProRawName[v].Data()), "", res.fResultsPro[v]->GetXaxis()->GetXbins()->GetSize() - 1, res.fResultsPro[v]->GetXaxis()->GetXbins()->GetArray()); + } nl.fNestedLoopsPro[k][n][v]->SetTitle(Form("#LT#LTcos[%s(%s)]#GT#GT", 1 == n + 1 ? "" : Form("%d", n + 1), oVariable[k].Data())); nl.fNestedLoopsPro[k][n][v]->SetStats(false); nl.fNestedLoopsPro[k][n][v]->Sumw2(); nl.fNestedLoopsPro[k][n][v]->GetXaxis()->SetTitle(res.fResultsProXaxisTitle[v].Data()); - /* - if(fUseFixedNumberOfRandomlySelectedTracks && 1==v) // just a warning - for the meaning of multiplicity in this special case - { - nl.fNestedLoopsPro[k][n][1]->GetXaxis()->SetTitle("WARNING: for each - multiplicity, fFixedNumberOfRandomlySelectedTracks is selected randomly - in Q-vector"); - } - */ + // if(fUseFixedNumberOfRandomlySelectedTracks && 1==v) // just a warning + // for the meaning of multiplicity in this special case + // { + // nl.fNestedLoopsPro[k][n][1]->GetXaxis()->SetTitle("WARNING: for each + // multiplicity, fFixedNumberOfRandomlySelectedTracks is selected randomly + // in Q-vector"); + // } nl.fNestedLoopsList->Add(nl.fNestedLoopsPro[k][n][v]); } // for(int v=0;v<5;v++) // variable [0=integrated,1=vs. @@ -5961,7 +6490,7 @@ void BookInternalValidationHistograms() } // a) Book the profile holding flags: - iv.fInternalValidationFlagsPro = new TProfile("fInternalValidationFlagsPro", "flags for internal validation", 4, 0., 4.); + iv.fInternalValidationFlagsPro = new TProfile("fInternalValidationFlagsPro", "flags for internal validation", 5, 0., 5.); iv.fInternalValidationFlagsPro->SetStats(false); iv.fInternalValidationFlagsPro->SetLineColor(eColor); iv.fInternalValidationFlagsPro->SetFillColor(eFillColor); @@ -5975,7 +6504,9 @@ void BookInternalValidationHistograms() iv.fInternalValidationFlagsPro->Fill(1.5, iv.fnEventsInternalValidation); iv.fInternalValidationFlagsPro->GetXaxis()->SetBinLabel(3, "fRescaleWithTheoreticalInput"); iv.fInternalValidationFlagsPro->Fill(2.5, iv.fRescaleWithTheoreticalInput); - iv.fInternalValidationFlagsPro->GetXaxis()->SetBinLabel(4, TString::Format("option = %s", iv.fHarmonicsOptionInternalValidation->Data())); + iv.fInternalValidationFlagsPro->GetXaxis()->SetBinLabel(4, "fRandomizeReactionPlane"); + iv.fInternalValidationFlagsPro->Fill(3.5, iv.fRandomizeReactionPlane); + iv.fInternalValidationFlagsPro->GetXaxis()->SetBinLabel(5, TString::Format("option = %s", iv.fHarmonicsOptionInternalValidation->Data())); } else { // Workaround for SetBinLabel() large memory consumption: @@ -5990,7 +6521,10 @@ void BookInternalValidationHistograms() yAxisTitle += TString::Format("%d:fRescaleWithTheoreticalInput; ", 3); iv.fInternalValidationFlagsPro->Fill(2.5, static_cast(iv.fRescaleWithTheoreticalInput)); - yAxisTitle += TString::Format("%d:option = %s; ", 4, iv.fHarmonicsOptionInternalValidation->Data()); + yAxisTitle += TString::Format("%d:fRandomizeReactionPlane; ", 4); + iv.fInternalValidationFlagsPro->Fill(3.5, static_cast(iv.fRandomizeReactionPlane)); + + yAxisTitle += TString::Format("%d:option = %s; ", 5, iv.fHarmonicsOptionInternalValidation->Data()); // ... @@ -6139,6 +6673,7 @@ void InternalValidation() GetParticleWeights(); pw.fParticleWeightsAreFetched = true; } + // differential phi weights: if (pw.fUseDiffPhiWeights[wPhiPhiAxis]) { // Yes, I check only the first flag. This way, I can switch off all differential phi weights by setting 0-wPhi in config. // On the other hand, it doesn't make sense to calculate differential phi weights without having phi axis. @@ -6146,6 +6681,23 @@ void InternalValidation() GetParticleWeights(); pw.fParticleWeightsAreFetched = true; } + + // differential pt weights: + if (pw.fUseDiffPhiWeights[wPtPtAxis]) { // Yes, I check only the first flag. This way, I can switch off all differential pt weights by setting 0-wPt in config. + // On the other hand, it doesn't make sense to calculate differential pt weights without having pt axis. + // At any point I shall be able to fall back to integrated pt weights, that corresponds to the case wheh "1-wPt" and all others are "0-w..." + GetParticleWeights(); + pw.fParticleWeightsAreFetched = true; + } + + // differential eta weights: + if (pw.fUseDiffPhiWeights[wEtaEtaAxis]) { // Yes, I check only the first flag. This way, I can switch off all differential eta weights by setting 0-wEta in config. + // On the other hand, it doesn't make sense to calculate differential eta weights without having eta axis. + // At any point I shall be able to fall back to integrated eta weights, that corresponds to the case wheh "1-wEta" and all others are "0-w..." + GetParticleWeights(); + pw.fParticleWeightsAreFetched = true; + } + } // if (!pw.fParticleWeightsAreFetched) { // a) Fourier like p.d.f. for azimuthal angles and flow amplitudes: @@ -6245,7 +6797,12 @@ void InternalValidation() // b1) Determine multiplicity, centrality, reaction plane and configure p.d.f. for azimuthal angles if harmonics are not constant e-by-e: int nMult = static_cast(gRandom->Uniform(iv.fMultRangeInternalValidation[eMin], iv.fMultRangeInternalValidation[eMax])); - double fReactionPlane = gRandom->Uniform(0., o2::constants::math::TwoPI); // no cast is needed, since Uniform(...) returns double + double fReactionPlane = 0.; + if (iv.fRandomizeReactionPlane) { + fReactionPlane = gRandom->Uniform(0., o2::constants::math::TwoPI); // no cast is needed, since Uniform(...) returns double + } else { + LOGF(info, "\033[1;33m%s at line %d : Reaction plane was not randomized for this collision.\033[0m", __FUNCTION__, __LINE__); + } if (iv.fHarmonicsOptionInternalValidation->EqualTo("constant")) { fPhiPDF->SetParameter(18, fReactionPlane); } else if (iv.fHarmonicsOptionInternalValidation->EqualTo("correlated")) { @@ -6254,13 +6811,13 @@ void InternalValidation() ebye.fCentrality = static_cast(gRandom->Uniform(0., 100.)); // this is perfectly fine for this exercise ebye.fOccupancy = static_cast(gRandom->Uniform(0., 10000.)); // this is perfectly fine for this exercise - ebye.fInteractionRate = static_cast(gRandom->Uniform(0., 10000.)); // this is perfectly fine for this exercise + ebye.fInteractionRate = static_cast(gRandom->Uniform(0., 1000.)); // this is perfectly fine for this exercise ebye.fCurrentRunDuration = static_cast(gRandom->Uniform(0., 86400.)); // this is perfectly fine for this exercise ebye.fVz = static_cast(gRandom->Uniform(-20., 20.)); // this is perfectly fine for this exercise ebye.fFT0CAmplitudeOnFoundBC = static_cast(gRandom->Uniform(0., 100000.)); // this is perfectly fine for this exercise ebye.fImpactParameter = static_cast(gRandom->Uniform(0., 20.)); // this is perfectly fine for this exercise - // b2) Fill event histograms before cuts: + // b2) Fill event histograms before cuts: if (eh.fFillEventHistograms) { !eh.fEventHistograms[eNumberOfEvents][eSim][eBefore] ? true : eh.fEventHistograms[eNumberOfEvents][eSim][eBefore]->Fill(0.5); !eh.fEventHistograms[eTotalMultiplicity][eSim][eBefore] ? true : eh.fEventHistograms[eTotalMultiplicity][eSim][eBefore]->Fill(nMult); @@ -6310,6 +6867,7 @@ void InternalValidation() double dPhi = 0.; double dPt = 0.; double dEta = 0.; + double dCharge = -44.; // it has to be double, because below I use e.g. double kineArr[2] = {dPt, dCharge}; // *) Define min and max ranges for sampling: double dPt_min = res.fResultsPro[AFO_PT]->GetXaxis()->GetBinLowEdge(1); // yes, low edge of first bin is pt min @@ -6321,16 +6879,32 @@ void InternalValidation() // Particle angle: dPhi = fPhiPDF->GetRandom(); - // *) To increase performance, sample pt or eta only if requested: - if (mupa.fCalculateCorrelationsAsFunctionOf[AFO_PT] || t0.fCalculateTest0AsFunctionOf[AFO_PT] || es.fCalculateEtaSeparationsAsFunctionOf[AFO_PT]) { + // *) To increase performance, sample pt, eta or charge only if requested: + if (mupa.fCalculateCorrelationsAsFunctionOf[AFO_PT] || t0.fCalculateTest0AsFunctionOf[AFO_PT] || es.fCalculateEtaSeparationsAsFunctionOf[AFO_PT] || + t0.fCalculate2DTest0AsFunctionOf[AFO_CENTRALITY_PT] || t0.fCalculate2DTest0AsFunctionOf[AFO_PT_ETA] || t0.fCalculate2DTest0AsFunctionOf[AFO_PT_CHARGE] || + t0.fCalculate3DTest0AsFunctionOf[AFO_CENTRALITY_PT_ETA] || t0.fCalculate3DTest0AsFunctionOf[AFO_CENTRALITY_PT_CHARGE] || t0.fCalculate3DTest0AsFunctionOf[AFO_CENTRALITY_PT_VZ] || + t0.fCalculate3DTest0AsFunctionOf[AFO_PT_ETA_CHARGE]) { dPt = gRandom->Uniform(dPt_min, dPt_max); } - if (mupa.fCalculateCorrelationsAsFunctionOf[AFO_ETA] || t0.fCalculateTest0AsFunctionOf[AFO_ETA] || es.fCalculateEtaSeparations) { + if (mupa.fCalculateCorrelationsAsFunctionOf[AFO_ETA] || t0.fCalculateTest0AsFunctionOf[AFO_ETA] || es.fCalculateEtaSeparations || + t0.fCalculate2DTest0AsFunctionOf[AFO_CENTRALITY_ETA] || t0.fCalculate2DTest0AsFunctionOf[AFO_PT_ETA] || t0.fCalculate2DTest0AsFunctionOf[AFO_ETA_CHARGE] || + t0.fCalculate3DTest0AsFunctionOf[AFO_CENTRALITY_PT_ETA] || t0.fCalculate3DTest0AsFunctionOf[AFO_CENTRALITY_ETA_CHARGE] || t0.fCalculate3DTest0AsFunctionOf[AFO_CENTRALITY_ETA_VZ] || + t0.fCalculate3DTest0AsFunctionOf[AFO_PT_ETA_CHARGE]) { // Yes, I have to use here es.fCalculateEtaSeparations , and not some differential flag, like for pt case above dEta = gRandom->Uniform(dEta_min, dEta_max); } + if (mupa.fCalculateCorrelationsAsFunctionOf[AFO_CHARGE] || t0.fCalculateTest0AsFunctionOf[AFO_CHARGE] || es.fCalculateEtaSeparationsAsFunctionOf[AFO_CHARGE] || + t0.fCalculate2DTest0AsFunctionOf[AFO_CENTRALITY_CHARGE] || t0.fCalculate2DTest0AsFunctionOf[AFO_PT_CHARGE] || t0.fCalculate2DTest0AsFunctionOf[AFO_ETA_CHARGE] || + t0.fCalculate3DTest0AsFunctionOf[AFO_CENTRALITY_PT_CHARGE] || t0.fCalculate3DTest0AsFunctionOf[AFO_CENTRALITY_ETA_CHARGE] || t0.fCalculate3DTest0AsFunctionOf[AFO_CENTRALITY_VZ_CHARGE] || + t0.fCalculate3DTest0AsFunctionOf[AFO_PT_ETA_CHARGE]) { + dCharge = (1 == gRandom->Integer(2) ? 1 : -1); // gRandom->Integer(2) samples either 0 or 1, then I cast 0 into -1 + if (tc.fInsanityCheckForEachParticle && std::abs(dCharge) != 1) { + LOGF(fatal, "\033[1;31m%s at line %d : dCharge = %d\033[0m", __FUNCTION__, __LINE__, dCharge); + } + } + // *) Fill few selected particle histograms before cuts here directly: // Remark: I do not call FillParticleHistograms(track, eBefore), as I do not want to bother to make here full 'track' object, etc., just to fill simple kine info: if (ph.fFillParticleHistograms || ph.fFillParticleHistograms2D) { @@ -6338,6 +6912,7 @@ void InternalValidation() !ph.fParticleHistograms[ePhi][eSim][eBefore] ? true : ph.fParticleHistograms[ePhi][eSim][eBefore]->Fill(dPhi); !ph.fParticleHistograms[ePt][eSim][eBefore] ? true : ph.fParticleHistograms[ePt][eSim][eBefore]->Fill(dPt); !ph.fParticleHistograms[eEta][eSim][eBefore] ? true : ph.fParticleHistograms[eEta][eSim][eBefore]->Fill(dEta); + !ph.fParticleHistograms[eCharge][eSim][eBefore] ? true : ph.fParticleHistograms[eCharge][eSim][eBefore]->Fill(dCharge); // 2D: !ph.fParticleHistograms2D[ePhiPt][eSim][eBefore] ? true : ph.fParticleHistograms2D[ePhiPt][eSim][eBefore]->Fill(dPhi, dPt); !ph.fParticleHistograms2D[ePhiEta][eSim][eBefore] ? true : ph.fParticleHistograms2D[ePhiEta][eSim][eBefore]->Fill(dPhi, dEta); @@ -6362,6 +6937,7 @@ void InternalValidation() !ph.fParticleHistograms[ePhi][eSim][eAfter] ? true : ph.fParticleHistograms[ePhi][eSim][eAfter]->Fill(dPhi); !ph.fParticleHistograms[ePt][eSim][eAfter] ? true : ph.fParticleHistograms[ePt][eSim][eAfter]->Fill(dPt); !ph.fParticleHistograms[eEta][eSim][eAfter] ? true : ph.fParticleHistograms[eEta][eSim][eAfter]->Fill(dEta); + !ph.fParticleHistograms[eCharge][eSim][eAfter] ? true : ph.fParticleHistograms[eCharge][eSim][eAfter]->Fill(dCharge); // 2D: !ph.fParticleHistograms2D[ePhiPt][eSim][eAfter] ? true : ph.fParticleHistograms2D[ePhiPt][eSim][eAfter]->Fill(dPhi, dPt); !ph.fParticleHistograms2D[ePhiEta][eSim][eAfter] ? true : ph.fParticleHistograms2D[ePhiEta][eSim][eAfter]->Fill(dPhi, dEta); @@ -6373,20 +6949,74 @@ void InternalValidation() this->FillQvector(dPhi, dPt, dEta); // all 3 arguments are passed by reference } - // *) Differential q-vectors: - // **) pt-dependence: + // *) Differential q-vectors (keep in sync with the code in MainLoopOverParticles(...)): + + // ** 1D: + // ***) pt dependence: if (qv.fCalculateQvectors && (mupa.fCalculateCorrelationsAsFunctionOf[AFO_PT] || t0.fCalculateTest0AsFunctionOf[AFO_PT]) && !es.fCalculateEtaSeparations) { // In this branch I do not need eta separation, so the lighter call can be executed: - this->Fillqvector(dPhi, dPt, PTq); // first 2 arguments are passed by reference, 3rd argument is enum + double kineArr[1] = {dPt}; + this->FillqvectorNdim(dPhi, kineArr, 1, PTq); } else if (es.fCalculateEtaSeparations && es.fCalculateEtaSeparationsAsFunctionOf[AFO_PT]) { // In this branch I do need eta separation, so the heavier call must be executed: - // Remark: Within Fillqvector() I check again all the relevant flags. - this->Fillqvector(dPhi, dPt, PTq, dEta); // first 2 arguments and the last one are passed by reference, 3rd argument is enum. "kine" variable is the 2nd argument + double kineArr[1] = {dPt}; + this->FillqvectorNdim(dPhi, kineArr, 1, PTq, dEta); } - // **) eta-dependence: + + // ***) eta dependence: if (qv.fCalculateQvectors && (mupa.fCalculateCorrelationsAsFunctionOf[AFO_ETA] || t0.fCalculateTest0AsFunctionOf[AFO_ETA])) { // Remark: For eta dependence I do not consider es.fCalculateEtaSeparations, because in this context that calculation is meaningless. - this->Fillqvector(dPhi, dEta, ETAq); // first 2 arguments are passed by reference, 3rd argument is enum + double kineArr[1] = {dEta}; + this->FillqvectorNdim(dPhi, kineArr, 1, ETAq); + } + + // ***) charge dependence: + if (qv.fCalculateQvectors && (mupa.fCalculateCorrelationsAsFunctionOf[AFO_CHARGE] || t0.fCalculateTest0AsFunctionOf[AFO_CHARGE]) && !es.fCalculateEtaSeparations) { + // In this branch I do not need eta separation, so the lighter call can be executed: + double kineArr[1] = {dCharge}; + this->FillqvectorNdim(dPhi, kineArr, 1, CHARGEq); + } else if (es.fCalculateEtaSeparations && es.fCalculateEtaSeparationsAsFunctionOf[AFO_CHARGE]) { + // In this branch I do need eta separation, so the heavier call must be executed: + double kineArr[1] = {dCharge}; + this->FillqvectorNdim(dPhi, kineArr, 1, CHARGEq, dEta); + } + + // ... + + // ** 2D: + // ***) pt-eta dependence: + if (qv.fCalculateQvectors && (t0.fCalculate2DTest0AsFunctionOf[AFO_PT_ETA] || t0.fCalculate3DTest0AsFunctionOf[AFO_CENTRALITY_PT_ETA])) { + // Remark: For eta dependence I do not consider es.fCalculateEtaSeparations, because in this context that calculation is meaningless. + double kineArr[2] = {dPt, dEta}; + this->FillqvectorNdim(dPhi, kineArr, 2, PT_ETAq); + } + + // ***) pt-charge dependence: + if (qv.fCalculateQvectors && (t0.fCalculate2DTest0AsFunctionOf[AFO_PT_CHARGE] || t0.fCalculate3DTest0AsFunctionOf[AFO_CENTRALITY_PT_CHARGE]) && !es.fCalculateEtaSeparations) { + // In this branch I do not need eta separation, so the lighter call can be executed: + double kineArr[2] = {dPt, dCharge}; + this->FillqvectorNdim(dPhi, kineArr, 2, PT_CHARGEq); + } else if (es.fCalculateEtaSeparations && false) { // && TBI 20250623 finalize, replace "false" with 2D flag for (pt,charge) with eta separation case + // In this branch I do need eta separation, so the heavier call must be executed: + double kineArr[2] = {dPt, dCharge}; + this->FillqvectorNdim(dPhi, kineArr, 2, PT_CHARGEq, dEta); + } + + // ***) eta-charge dependence: + if (qv.fCalculateQvectors && (t0.fCalculate2DTest0AsFunctionOf[AFO_ETA_CHARGE] || t0.fCalculate3DTest0AsFunctionOf[AFO_CENTRALITY_ETA_CHARGE])) { + // Remark: For eta dependence I do not consider es.fCalculateEtaSeparations, because in this context that calculation is meaningless. + double kineArr[2] = {dEta, dCharge}; + this->FillqvectorNdim(dPhi, kineArr, 2, ETA_CHARGEq); + } + + // ... + + // ** 3D: + // ***) pt-eta-charge dependence: + if (qv.fCalculateQvectors && (t0.fCalculate3DTest0AsFunctionOf[AFO_PT_ETA_CHARGE])) { + // Remark: For eta dependence I do not consider es.fCalculateEtaSeparations, because in this context that calculation is meaningless. + double kineArr[3] = {dPt, dEta, dCharge}; + this->FillqvectorNdim(dPhi, kineArr, 3, PT_ETA_CHARGEq); } // *) Fill nested loops containers: @@ -6432,7 +7062,7 @@ void InternalValidation() ResetEventByEventQuantities(); // *) Print info on the current event number (within current real event): - LOGF(info, " Event # %d/%d (within current real event) ....", e + 1, static_cast(iv.fnEventsInternalValidation)); + LOGF(info, " Event # %d/%d (within current real event, running internal validation) ....", e + 1, static_cast(iv.fnEventsInternalValidation)); // *) Determine all event counters: DetermineEventCounters(); @@ -6521,20 +7151,24 @@ void BookTest0Histograms() // a) Book the profile holding flags; // b) Book placeholder and make sure all labels are stored in the placeholder; - // c) Book what needs to be booked; - // d) Few quick insanity checks on booking. + // c) Book what needs to be booked for 1D; + // d) Book what needs to be booked for 2D; + // e) Book what needs to be booked for 3D; + // f) Few quick insanity checks on booking (cherry-picking). if (tc.fVerbose) { StartFunction(__FUNCTION__); } // a) Book the profile holding flags: - t0.fTest0FlagsPro = new TProfile("fTest0FlagsPro", "flags for Test0", 1, 0., 1.); + t0.fTest0FlagsPro = new TProfile("fTest0FlagsPro", "flags for Test0", 3, 0., 3.); t0.fTest0FlagsPro->SetStats(false); t0.fTest0FlagsPro->GetXaxis()->SetLabelSize(0.04); if (tc.fUseSetBinLabel) { t0.fTest0FlagsPro->GetXaxis()->SetBinLabel(1, "fCalculateTest0"); + t0.fTest0FlagsPro->GetXaxis()->SetBinLabel(2, "fCalculate2DTest0"); + t0.fTest0FlagsPro->GetXaxis()->SetBinLabel(3, "fCalculate3DTest0"); // ... @@ -6543,7 +7177,8 @@ void BookTest0Histograms() TString yAxisTitle = ""; yAxisTitle += TString::Format("%d:fCalculateTest0; ", 1); - t0.fTest0FlagsPro->Fill(0.5, static_cast(t0.fCalculateTest0)); + yAxisTitle += TString::Format("%d:fCalculate2DTest0; ", 2); + yAxisTitle += TString::Format("%d:fCalculate3DTest0; ", 3); // ... @@ -6563,87 +7198,171 @@ void BookTest0Histograms() } // else - t0.fTest0FlagsPro->Fill(0.5, t0.fCalculateTest0); + t0.fTest0FlagsPro->Fill(0.5, static_cast(t0.fCalculateTest0)); + t0.fTest0FlagsPro->Fill(1.5, static_cast(t0.fCalculate2DTest0)); + t0.fTest0FlagsPro->Fill(2.5, static_cast(t0.fCalculate3DTest0)); + // ... t0.fTest0List->Add(t0.fTest0FlagsPro); - if (!t0.fCalculateTest0) { + if (!(t0.fCalculateTest0 || t0.fCalculate2DTest0 || t0.fCalculate3DTest0)) { return; } // b) Book placeholder and make sure all labels are stored in the placeholder: this->StoreLabelsInPlaceholder(); - // c) Book what needs to be booked: - for (int mo = 0; mo < gMaxCorrelator; mo++) { - for (int mi = 0; mi < gMaxIndex; mi++) { - if (!t0.fTest0Labels[mo][mi]) { - continue; - } - { + // c) Book what needs to be booked for 1D: + if (t0.fCalculateTest0) { + for (int mo = 0; mo < gMaxCorrelator; mo++) { + for (int mi = 0; mi < gMaxIndex; mi++) { + if (!t0.fTest0Labels[mo][mi]) { + continue; + } for (int v = 0; v < eAsFunctionOf_N; v++) { - // decide what is booked, then later valid pointer to fCorrelationsPro[k][n][v] is used as a boolean, in the standard way: - if (AFO_INTEGRATED == v && !t0.fCalculateTest0AsFunctionOf[AFO_INTEGRATED]) { - continue; - } - if (AFO_MULTIPLICITY == v && !t0.fCalculateTest0AsFunctionOf[AFO_MULTIPLICITY]) { - continue; - } - if (AFO_CENTRALITY == v && !t0.fCalculateTest0AsFunctionOf[AFO_CENTRALITY]) { + + // decide what is booked, then later valid pointer to fTest0Pro[k][n][v] is used as a boolean, in the standard way: + if (!t0.fCalculateTest0AsFunctionOf[v]) { continue; } - if (AFO_PT == v && !t0.fCalculateTest0AsFunctionOf[AFO_PT]) { - continue; + + if (!res.fResultsPro[v]) { + LOGF(fatal, "\033[1;31m%s at line %d : fResultsPro[%d] is NULL, this shall never happen, but apparently it happened... \033[0m", __FUNCTION__, __LINE__, v); } - if (AFO_ETA == v && !t0.fCalculateTest0AsFunctionOf[AFO_ETA]) { - continue; + + if (tc.fUseClone) { + t0.fTest0Pro[mo][mi][v] = reinterpret_cast(res.fResultsPro[v]->Clone(Form("fTest0Pro[%d][%d][%s]", mo, mi, res.fResultsProRawName[v].Data()))); // yes + } else { + t0.fTest0Pro[mo][mi][v] = new TProfile(Form("fTest0Pro[%d][%d][%s]", mo, mi, res.fResultsProRawName[v].Data()), "", res.fResultsPro[v]->GetXaxis()->GetXbins()->GetSize() - 1, res.fResultsPro[v]->GetXaxis()->GetXbins()->GetArray()); } - if (AFO_OCCUPANCY == v && !t0.fCalculateTest0AsFunctionOf[AFO_OCCUPANCY]) { - continue; + + t0.fTest0Pro[mo][mi][v]->SetStats(false); + t0.fTest0Pro[mo][mi][v]->Sumw2(); + t0.fTest0Pro[mo][mi][v]->SetTitle(t0.fTest0Labels[mo][mi]->Data()); + t0.fTest0Pro[mo][mi][v]->GetXaxis()->SetTitle(FancyFormatting(res.fResultsProXaxisTitle[v].Data())); + t0.fTest0List->Add(t0.fTest0Pro[mo][mi][v]); // yes, this has to be here + + } // for(int v=0;vGetName(); + TObjArray* oa = rawName.Tokenize("[]"); + if (oa->GetEntries() != 2) { + LOGF(fatal, "\033[1;31m%s at line %d : oa->GetEntries() = %d \033[0m", __FUNCTION__, __LINE__, oa->GetEntries()); } - if (AFO_CURRENTRUNDURATION == v && !t0.fCalculateTest0AsFunctionOf[AFO_CURRENTRUNDURATION]) { - continue; + rawName = oa->At(1)->GetName(); // basically: fResultsPro2D[cent_pt] => cent_pt + delete oa; + if (rawName.EqualTo("")) { + LOGF(fatal, "\033[1;31m%s at line %d : rawName is empty string \033[0m", __FUNCTION__, __LINE__); } - if (AFO_VZ == v && !t0.fCalculateTest0AsFunctionOf[AFO_VZ]) { - continue; + + if (tc.fUseClone) { + t0.fTest0Pro2D[mo][mi][v] = reinterpret_cast(res.fResultsPro2D[v]->Clone(Form("fTest0Pro2D[%d][%d][%s]", mo, mi, rawName.Data()))); + } else { + // TBI 20250412 this branch is temporary workaround until hist->Clone(...) large memory consumption is resolved + t0.fTest0Pro2D[mo][mi][v] = new TProfile2D(Form("fTest0Pro2D[%d][%d][%s]", mo, mi, rawName.Data()), "", + res.fResultsPro2D[v]->GetXaxis()->GetXbins()->GetSize() - 1, res.fResultsPro2D[v]->GetXaxis()->GetXbins()->GetArray(), + res.fResultsPro2D[v]->GetYaxis()->GetXbins()->GetSize() - 1, res.fResultsPro2D[v]->GetYaxis()->GetXbins()->GetArray()); // yes, GetYaxis()->GetXbins() + } // else + + t0.fTest0Pro2D[mo][mi][v]->SetStats(false); + t0.fTest0Pro2D[mo][mi][v]->Sumw2(); + t0.fTest0Pro2D[mo][mi][v]->SetTitle(t0.fTest0Labels[mo][mi]->Data()); + t0.fTest0Pro2D[mo][mi][v]->GetXaxis()->SetTitle(FancyFormatting(res.fResultsPro2D[v]->GetXaxis()->GetTitle())); + t0.fTest0Pro2D[mo][mi][v]->GetYaxis()->SetTitle(FancyFormatting(res.fResultsPro2D[v]->GetYaxis()->GetTitle())); + t0.fTest0List->Add(t0.fTest0Pro2D[mo][mi][v]); // yes, this has to be here + + } // for(int v=0;vGetName(); + TObjArray* oa = rawName.Tokenize("[]"); + if (oa->GetEntries() != 2) { + LOGF(fatal, "\033[1;31m%s at line %d : oa->GetEntries() = %d \033[0m", __FUNCTION__, __LINE__, oa->GetEntries()); + } + rawName = oa->At(1)->GetName(); // basically: fResultsPro2D[cent_pt_eta] => cent_pt_eta + delete oa; + if (rawName.EqualTo("")) { + LOGF(fatal, "\033[1;31m%s at line %d : rawName is empty string \033[0m", __FUNCTION__, __LINE__); } if (tc.fUseClone) { - t0.fTest0Pro[mo][mi][v] = reinterpret_cast(res.fResultsPro[v]->Clone(Form("fTest0Pro[%d][%d][%s]", mo, mi, res.fResultsProRawName[v].Data()))); // yes + t0.fTest0Pro3D[mo][mi][v] = reinterpret_cast(res.fResultsPro3D[v]->Clone(Form("fTest0Pro3D[%d][%d][%s]", mo, mi, rawName.Data()))); } else { // TBI 20250412 this branch is temporary workaround until hist->Clone(...) large memory consumption is resolved - if (res.fUseResultsProVariableLengthBins[v]) { - // per demand, variable-length binning: - t0.fTest0Pro[mo][mi][v] = new TProfile(Form("fTest0Pro[%d][%d][%s]", mo, mi, res.fResultsProRawName[v].Data()), "", res.fResultsProVariableLengthBins[v]->GetSize() - 1, res.fResultsProVariableLengthBins[v]->GetArray()); - } else { - // the default fixed-length binning: - t0.fTest0Pro[mo][mi][v] = new TProfile(Form("fTest0Pro[%d][%d][%s]", mo, mi, res.fResultsProRawName[v].Data()), "", static_cast(res.fResultsProFixedLengthBins[v][0]), res.fResultsProFixedLengthBins[v][1], res.fResultsProFixedLengthBins[v][2]); - } // else + t0.fTest0Pro3D[mo][mi][v] = new TProfile3D(Form("fTest0Pro3D[%d][%d][%s]", mo, mi, rawName.Data()), "", + res.fResultsPro3D[v]->GetXaxis()->GetXbins()->GetSize() - 1, res.fResultsPro3D[v]->GetXaxis()->GetXbins()->GetArray(), + res.fResultsPro3D[v]->GetYaxis()->GetXbins()->GetSize() - 1, res.fResultsPro3D[v]->GetYaxis()->GetXbins()->GetArray(), // yes, GetYaxis()->GetXbins() + res.fResultsPro3D[v]->GetZaxis()->GetXbins()->GetSize() - 1, res.fResultsPro3D[v]->GetZaxis()->GetXbins()->GetArray()); // yes, GetZaxis()->GetXbins() } // else - t0.fTest0Pro[mo][mi][v]->SetStats(false); - t0.fTest0Pro[mo][mi][v]->Sumw2(); - t0.fTest0Pro[mo][mi][v]->SetTitle(t0.fTest0Labels[mo][mi]->Data()); - t0.fTest0Pro[mo][mi][v]->GetXaxis()->SetTitle(FancyFormatting(res.fResultsProXaxisTitle[v].Data())); - t0.fTest0List->Add(t0.fTest0Pro[mo][mi][v]); // yes, this has to be here + t0.fTest0Pro3D[mo][mi][v]->SetStats(false); + t0.fTest0Pro3D[mo][mi][v]->Sumw2(); + t0.fTest0Pro3D[mo][mi][v]->SetTitle(t0.fTest0Labels[mo][mi]->Data()); + t0.fTest0Pro3D[mo][mi][v]->GetXaxis()->SetTitle(FancyFormatting(res.fResultsPro3D[v]->GetXaxis()->GetTitle())); + t0.fTest0Pro3D[mo][mi][v]->GetYaxis()->SetTitle(FancyFormatting(res.fResultsPro3D[v]->GetYaxis()->GetTitle())); + t0.fTest0Pro3D[mo][mi][v]->GetZaxis()->SetTitle(FancyFormatting(res.fResultsPro3D[v]->GetZaxis()->GetTitle())); + t0.fTest0List->Add(t0.fTest0Pro3D[mo][mi][v]); // yes, this has to be here } // for(int v=0;vGetXaxis()->GetTitle()).EqualTo("integrated")) { LOGF(fatal, "\033[1;31m%s at line %d\033[0m", __FUNCTION__, __LINE__); // ordering in enum eAsFunctionOf is not the same as in TString fResultsProXaxisTitle[eAsFunctionOf_N] } if (t0.fTest0Pro[0][0][AFO_PT] && !TString(t0.fTest0Pro[0][0][AFO_PT]->GetXaxis()->GetTitle()).EqualTo("p_{T}")) { - LOGF(fatal, "\033[1;31m%s at line %d\033[0m", __FUNCTION__, __LINE__); // ordering in enum eAsFunctionOf is not the same as in TString fResultsProXaxisTitle[eAsFunctionOf_N] + LOGF(fatal, "\033[1;31m%s at line %d : x-axis title = %s\033[0m", __FUNCTION__, __LINE__, t0.fTest0Pro[0][0][AFO_PT]->GetXaxis()->GetTitle()); // ordering in enum eAsFunctionOf is not the same as in TString fResultsProXaxisTitle[eAsFunctionOf_N] + } + + // 2D: + if (t0.fTest0Pro2D[0][0][AFO_CENTRALITY_PT] && !(TString(t0.fTest0Pro2D[0][0][AFO_CENTRALITY_PT]->GetXaxis()->GetTitle()).Contains("centrality", TString::kIgnoreCase) && TString(t0.fTest0Pro2D[0][0][AFO_CENTRALITY_PT]->GetYaxis()->GetTitle()).EqualTo("p_{T}"))) { + LOGF(fatal, "\033[1;31m%s at line %d : x-axis title = %s, y-axis title = %s\033[0m", __FUNCTION__, __LINE__, t0.fTest0Pro2D[0][0][AFO_CENTRALITY_PT]->GetXaxis()->GetTitle(), t0.fTest0Pro2D[0][0][AFO_CENTRALITY_PT]->GetYaxis()->GetTitle()); // ordering in enum eAsFunctionOf is not the same as in TString fResultsProXaxisTitle[eAsFunctionOf_N] + } + + // 3D: + if (t0.fTest0Pro3D[0][0][AFO_CENTRALITY_PT_ETA] && !(TString(t0.fTest0Pro3D[0][0][AFO_CENTRALITY_PT_ETA]->GetXaxis()->GetTitle()).Contains("centrality", TString::kIgnoreCase) && TString(t0.fTest0Pro3D[0][0][AFO_CENTRALITY_PT_ETA]->GetYaxis()->GetTitle()).EqualTo("p_{T}") && TString(t0.fTest0Pro3D[0][0][AFO_CENTRALITY_PT_ETA]->GetZaxis()->GetTitle()).EqualTo("#eta"))) { + LOGF(fatal, "\033[1;31m%s at line %d : x-axis title = %s, y-axis title = %s, z-axis title = %s\033[0m", __FUNCTION__, __LINE__, t0.fTest0Pro3D[0][0][AFO_CENTRALITY_PT_ETA]->GetXaxis()->GetTitle(), t0.fTest0Pro3D[0][0][AFO_CENTRALITY_PT_ETA]->GetYaxis()->GetTitle(), t0.fTest0Pro3D[0][0][AFO_CENTRALITY_PT_ETA]->GetZaxis()->GetTitle()); // ordering in enum eAsFunctionOf is not the same as in TString fResultsProXaxisTitle[eAsFunctionOf_N] } if (tc.fVerbose) { @@ -6716,51 +7435,21 @@ void BookEtaSeparationsHistograms() } for (int e = 0; e < gMaxNumberEtaSeparations; e++) { for (int v = 0; v < eAsFunctionOf_N; v++) { + // decide what is booked, then later valid pointer to es.fEtaSeparationsPro[h][e][v] is used as a boolean, in the standard way: - if (AFO_INTEGRATED == v && !es.fCalculateEtaSeparationsAsFunctionOf[AFO_INTEGRATED]) { - continue; - } - if (AFO_MULTIPLICITY == v && !es.fCalculateEtaSeparationsAsFunctionOf[AFO_MULTIPLICITY]) { - continue; - } - if (AFO_CENTRALITY == v && !es.fCalculateEtaSeparationsAsFunctionOf[AFO_CENTRALITY]) { - continue; - } - if (AFO_PT == v && !es.fCalculateEtaSeparationsAsFunctionOf[AFO_PT]) { - continue; - } - if (AFO_ETA == v && !es.fCalculateEtaSeparationsAsFunctionOf[AFO_ETA]) { - continue; - } - if (AFO_OCCUPANCY == v && !es.fCalculateEtaSeparationsAsFunctionOf[AFO_OCCUPANCY]) { - continue; - } - if (AFO_INTERACTIONRATE == v && !es.fCalculateEtaSeparationsAsFunctionOf[AFO_INTERACTIONRATE]) { - continue; - } - if (AFO_CURRENTRUNDURATION == v && !es.fCalculateEtaSeparationsAsFunctionOf[AFO_CURRENTRUNDURATION]) { - continue; - } - if (AFO_VZ == v && !es.fCalculateEtaSeparationsAsFunctionOf[AFO_VZ]) { + if (!es.fCalculateEtaSeparationsAsFunctionOf[v]) { continue; } if (!res.fResultsPro[v]) { - LOGF(fatal, "\033[1;31m%s at line %d\033[0m", __FUNCTION__, __LINE__); + LOGF(fatal, "\033[1;31m%s at line %d : fResultsPro[%d] is NULL, this shall never happen, but apparently it happened... \033[0m", __FUNCTION__, __LINE__, v); } if (tc.fUseClone) { es.fEtaSeparationsPro[h][e][v] = reinterpret_cast(res.fResultsPro[v]->Clone(Form("fEtaSeparationsPro[%d][%d][%s]", h, e, res.fResultsProRawName[v].Data()))); // yes } else { - // TBI 20250412 this branch is temporary workaround until hist->Clone(...) large memory consumption is resolved - if (res.fUseResultsProVariableLengthBins[v]) { - // per demand, variable-length binning: - es.fEtaSeparationsPro[h][e][v] = new TProfile(Form("fEtaSeparationsPro[%d][%d][%s]", h, e, res.fResultsProRawName[v].Data()), "", res.fResultsProVariableLengthBins[v]->GetSize() - 1, res.fResultsProVariableLengthBins[v]->GetArray()); - } else { - // the default fixed-length binning: - es.fEtaSeparationsPro[h][e][v] = new TProfile(Form("fEtaSeparationsPro[%d][%d][%s]", h, e, res.fResultsProRawName[v].Data()), "", static_cast(res.fResultsProFixedLengthBins[v][0]), res.fResultsProFixedLengthBins[v][1], res.fResultsProFixedLengthBins[v][2]); - } // else - } // else + es.fEtaSeparationsPro[h][e][v] = new TProfile(Form("fEtaSeparationsPro[%d][%d][%s]", h, e, res.fResultsProRawName[v].Data()), "", res.fResultsPro[v]->GetXaxis()->GetXbins()->GetSize() - 1, res.fResultsPro[v]->GetXaxis()->GetXbins()->GetArray()); + } es.fEtaSeparationsPro[h][e][v]->SetStats(false); es.fEtaSeparationsPro[h][e][v]->Sumw2(); @@ -6790,9 +7479,12 @@ void BookEtaSeparationsHistograms() void BookResultsHistograms() { // Book all results histograms. + // These results histograms in addition act as a sort of "abstract" interface, which defines common binning, etc., for other groups of histograms. // a) Book the profile holding flags; - // b) Book results histograms, which in addition act as a sort of "abstract" interface, which defines common binning, etc., for other groups of histograms. + // b) Book (and optionaly save) results histograms 1D; + // c) Book (and optionaly save) results histograms 2D; + // d) Book (and optionaly save) results histograms 3D. if (tc.fVerbose) { StartFunction(__FUNCTION__); @@ -6834,21 +7526,206 @@ void BookResultsHistograms() } res.fResultsList->Add(res.fResultsFlagsPro); - // b) Book results histograms, which in addition act as a sort of "abstract" interface, which defines common binning, etc., for other groups of histograms: + // b) Book (and optionaly save) results histograms 1D: for (int v = 0; v < eAsFunctionOf_N; v++) { - if (res.fUseResultsProVariableLengthBins[v]) { - // per demand, variable-length binning: - res.fResultsPro[v] = new TProfile(Form("fResultsPro[%s]", res.fResultsProRawName[v].Data()), "...", res.fResultsProVariableLengthBins[v]->GetSize() - 1, res.fResultsProVariableLengthBins[v]->GetArray()); - } else { - // the default fixed-length binning: - res.fResultsPro[v] = new TProfile(Form("fResultsPro[%s]", res.fResultsProRawName[v].Data()), "...", static_cast(res.fResultsProFixedLengthBins[v][0]), res.fResultsProFixedLengthBins[v][1], res.fResultsProFixedLengthBins[v][2]); - } - // Optionally, save these histograms. Or just use them as an "abstract" interface for the booking of other group of histograms: + // TBI 20250518 I book 1D case always for the time being, because I also use their binning to book particle sparse histograms. + // There should not be any big memory penalty for 1D case + // if (!(t0.fCalculateTest0AsFunctionOf[v] || mupa.fCalculateCorrelationsAsFunctionOf[v] || es.fCalculateEtaSeparationsAsFunctionOf[v])) { + // // TBI 20250518 do I need here also some check for the nested loops? + // continue; + // } + + res.fResultsPro[v] = new TProfile(Form("fResultsPro[%s]", res.fResultsProRawName[v].Data()), "...", res.fResultsProBinEdges[v]->GetSize() - 1, res.fResultsProBinEdges[v]->GetArray()); + res.fResultsPro[v]->GetXaxis()->SetTitle(res.fResultsProXaxisTitle[v].Data()); + res.fResultsPro[v]->SetStats(false); + + delete res.fResultsProBinEdges[v]; // yes, it served the purpose. Now this info is carried permanently with res.fResultsPro[v], and I can always retrieve it later with e.g. + // res.fResultsPro[AFO_PT]->GetXaxis()->GetXbins() (which gives pointer to TArrayD, yes I need double, because TProfile ctor takes double) + + // Optionally, save these histograms - I need this mostly to check/validate the binning. if (res.fSaveResultsHistograms) { res.fResultsList->Add(res.fResultsPro[v]); } - } // for (int v = 0; v < eAsFunctionOf_N; v++) { + } // for (int v = 0; v < eAsFunctionOf_N; v++) + + // c) Book (and optionaly save) results histograms 2D: + // Remark 1: Here I cannot loop, because for each axis I re-use binning from 1D cases. + // Remark 2: I have deleted above res.fResultsProBinEdges[...], that info is now only in the axis of res.fResultsPro[...] + if (t0.fCalculate2DTest0AsFunctionOf[AFO_CENTRALITY_PT]) { + TString rawName = TString::Format("%s_%s", res.fResultsProRawName[AFO_CENTRALITY].Data(), res.fResultsProRawName[AFO_PT].Data()); // raw name is e.g. "[cent_pt]" in the file + res.fResultsPro2D[AFO_CENTRALITY_PT] = new TProfile2D(Form("fResultsPro2D[%s]", rawName.Data()), "...", + res.fResultsPro[AFO_CENTRALITY]->GetXaxis()->GetXbins()->GetSize() - 1, res.fResultsPro[AFO_CENTRALITY]->GetXaxis()->GetXbins()->GetArray(), + res.fResultsPro[AFO_PT]->GetXaxis()->GetXbins()->GetSize() - 1, res.fResultsPro[AFO_PT]->GetXaxis()->GetXbins()->GetArray()); + res.fResultsPro2D[AFO_CENTRALITY_PT]->GetXaxis()->SetTitle(res.fResultsPro[AFO_CENTRALITY]->GetXaxis()->GetTitle()); + res.fResultsPro2D[AFO_CENTRALITY_PT]->GetYaxis()->SetTitle(res.fResultsPro[AFO_PT]->GetXaxis()->GetTitle()); + res.fResultsPro2D[AFO_CENTRALITY_PT]->SetStats(false); + } + + if (t0.fCalculate2DTest0AsFunctionOf[AFO_CENTRALITY_ETA]) { + TString rawName = TString::Format("%s_%s", res.fResultsProRawName[AFO_CENTRALITY].Data(), res.fResultsProRawName[AFO_ETA].Data()); + res.fResultsPro2D[AFO_CENTRALITY_ETA] = new TProfile2D(Form("fResultsPro2D[%s]", rawName.Data()), "...", + res.fResultsPro[AFO_CENTRALITY]->GetXaxis()->GetXbins()->GetSize() - 1, res.fResultsPro[AFO_CENTRALITY]->GetXaxis()->GetXbins()->GetArray(), + res.fResultsPro[AFO_ETA]->GetXaxis()->GetXbins()->GetSize() - 1, res.fResultsPro[AFO_ETA]->GetXaxis()->GetXbins()->GetArray()); + res.fResultsPro2D[AFO_CENTRALITY_ETA]->GetXaxis()->SetTitle(res.fResultsPro[AFO_CENTRALITY]->GetXaxis()->GetTitle()); + res.fResultsPro2D[AFO_CENTRALITY_ETA]->GetYaxis()->SetTitle(res.fResultsPro[AFO_ETA]->GetXaxis()->GetTitle()); + res.fResultsPro2D[AFO_CENTRALITY_ETA]->SetStats(false); + } + + if (t0.fCalculate2DTest0AsFunctionOf[AFO_CENTRALITY_CHARGE]) { + TString rawName = TString::Format("%s_%s", res.fResultsProRawName[AFO_CENTRALITY].Data(), res.fResultsProRawName[AFO_CHARGE].Data()); + res.fResultsPro2D[AFO_CENTRALITY_CHARGE] = new TProfile2D(Form("fResultsPro2D[%s]", rawName.Data()), "...", + res.fResultsPro[AFO_CENTRALITY]->GetXaxis()->GetXbins()->GetSize() - 1, res.fResultsPro[AFO_CENTRALITY]->GetXaxis()->GetXbins()->GetArray(), + res.fResultsPro[AFO_CHARGE]->GetXaxis()->GetXbins()->GetSize() - 1, res.fResultsPro[AFO_CHARGE]->GetXaxis()->GetXbins()->GetArray()); + + res.fResultsPro2D[AFO_CENTRALITY_CHARGE]->GetXaxis()->SetTitle(res.fResultsPro[AFO_CENTRALITY]->GetXaxis()->GetTitle()); + res.fResultsPro2D[AFO_CENTRALITY_CHARGE]->GetYaxis()->SetTitle(res.fResultsPro[AFO_CHARGE]->GetXaxis()->GetTitle()); + res.fResultsPro2D[AFO_CENTRALITY_CHARGE]->SetStats(false); + } + + if (t0.fCalculate2DTest0AsFunctionOf[AFO_CENTRALITY_VZ]) { + TString rawName = TString::Format("%s_%s", res.fResultsProRawName[AFO_CENTRALITY].Data(), res.fResultsProRawName[AFO_VZ].Data()); + res.fResultsPro2D[AFO_CENTRALITY_VZ] = new TProfile2D(Form("fResultsPro2D[%s]", rawName.Data()), "...", + res.fResultsPro[AFO_CENTRALITY]->GetXaxis()->GetXbins()->GetSize() - 1, res.fResultsPro[AFO_CENTRALITY]->GetXaxis()->GetXbins()->GetArray(), + res.fResultsPro[AFO_VZ]->GetXaxis()->GetXbins()->GetSize() - 1, res.fResultsPro[AFO_VZ]->GetXaxis()->GetXbins()->GetArray()); + res.fResultsPro2D[AFO_CENTRALITY_VZ]->GetXaxis()->SetTitle(res.fResultsPro[AFO_CENTRALITY]->GetXaxis()->GetTitle()); + res.fResultsPro2D[AFO_CENTRALITY_VZ]->GetYaxis()->SetTitle(res.fResultsPro[AFO_VZ]->GetXaxis()->GetTitle()); + res.fResultsPro2D[AFO_CENTRALITY_VZ]->SetStats(false); + } + + if (t0.fCalculate2DTest0AsFunctionOf[AFO_PT_ETA]) { + TString rawName = TString::Format("%s_%s", res.fResultsProRawName[AFO_PT].Data(), res.fResultsProRawName[AFO_ETA].Data()); + res.fResultsPro2D[AFO_PT_ETA] = new TProfile2D(Form("fResultsPro2D[%s]", rawName.Data()), "...", + res.fResultsPro[AFO_PT]->GetXaxis()->GetXbins()->GetSize() - 1, res.fResultsPro[AFO_PT]->GetXaxis()->GetXbins()->GetArray(), + res.fResultsPro[AFO_ETA]->GetXaxis()->GetXbins()->GetSize() - 1, res.fResultsPro[AFO_ETA]->GetXaxis()->GetXbins()->GetArray()); + res.fResultsPro2D[AFO_PT_ETA]->GetXaxis()->SetTitle(res.fResultsPro[AFO_PT]->GetXaxis()->GetTitle()); + res.fResultsPro2D[AFO_PT_ETA]->GetYaxis()->SetTitle(res.fResultsPro[AFO_ETA]->GetXaxis()->GetTitle()); + res.fResultsPro2D[AFO_PT_ETA]->SetStats(false); + } + + if (t0.fCalculate2DTest0AsFunctionOf[AFO_PT_CHARGE]) { + TString rawName = TString::Format("%s_%s", res.fResultsProRawName[AFO_PT].Data(), res.fResultsProRawName[AFO_CHARGE].Data()); + res.fResultsPro2D[AFO_PT_CHARGE] = new TProfile2D(Form("fResultsPro2D[%s]", rawName.Data()), "...", + res.fResultsPro[AFO_PT]->GetXaxis()->GetXbins()->GetSize() - 1, res.fResultsPro[AFO_PT]->GetXaxis()->GetXbins()->GetArray(), + res.fResultsPro[AFO_CHARGE]->GetXaxis()->GetXbins()->GetSize() - 1, res.fResultsPro[AFO_CHARGE]->GetXaxis()->GetXbins()->GetArray()); + res.fResultsPro2D[AFO_PT_CHARGE]->GetXaxis()->SetTitle(res.fResultsPro[AFO_PT]->GetXaxis()->GetTitle()); + res.fResultsPro2D[AFO_PT_CHARGE]->GetYaxis()->SetTitle(res.fResultsPro[AFO_CHARGE]->GetXaxis()->GetTitle()); + res.fResultsPro2D[AFO_PT_CHARGE]->SetStats(false); + } + + if (t0.fCalculate2DTest0AsFunctionOf[AFO_ETA_CHARGE]) { + TString rawName = TString::Format("%s_%s", res.fResultsProRawName[AFO_ETA].Data(), res.fResultsProRawName[AFO_CHARGE].Data()); + res.fResultsPro2D[AFO_ETA_CHARGE] = new TProfile2D(Form("fResultsPro2D[%s]", rawName.Data()), "...", + res.fResultsPro[AFO_ETA]->GetXaxis()->GetXbins()->GetSize() - 1, res.fResultsPro[AFO_ETA]->GetXaxis()->GetXbins()->GetArray(), + res.fResultsPro[AFO_CHARGE]->GetXaxis()->GetXbins()->GetSize() - 1, res.fResultsPro[AFO_CHARGE]->GetXaxis()->GetXbins()->GetArray()); + res.fResultsPro2D[AFO_ETA_CHARGE]->GetXaxis()->SetTitle(res.fResultsPro[AFO_ETA]->GetXaxis()->GetTitle()); + res.fResultsPro2D[AFO_ETA_CHARGE]->GetYaxis()->SetTitle(res.fResultsPro[AFO_CHARGE]->GetXaxis()->GetTitle()); + res.fResultsPro2D[AFO_ETA_CHARGE]->SetStats(false); + } + + // ... + + // Optionally, save 2D results histograms - I need this mostly to check/validate the binning: + for (int v = 0; v < eAsFunctionOf2D_N; v++) { + if (res.fSaveResultsHistograms && res.fResultsPro2D[v]) { + res.fResultsList->Add(res.fResultsPro2D[v]); + } + } + + // d) Book (and optionaly save) results histograms 3D: + // Remark 1: Here I cannot loop, because for each axis I re-use binning from 1D cases. + // Remark 2: I have deleted above res.fResultsProBinEdges[...], that info is now only in the axis of res.fResultsPro[...] + if (t0.fCalculate3DTest0AsFunctionOf[AFO_CENTRALITY_PT_ETA]) { + TString rawName = TString::Format("%s_%s_%s", res.fResultsProRawName[AFO_CENTRALITY].Data(), res.fResultsProRawName[AFO_PT].Data(), res.fResultsProRawName[AFO_ETA].Data()); + res.fResultsPro3D[AFO_CENTRALITY_PT_ETA] = new TProfile3D(Form("fResultsPro3D[%s]", rawName.Data()), "...", + res.fResultsPro[AFO_CENTRALITY]->GetXaxis()->GetXbins()->GetSize() - 1, res.fResultsPro[AFO_CENTRALITY]->GetXaxis()->GetXbins()->GetArray(), + res.fResultsPro[AFO_PT]->GetXaxis()->GetXbins()->GetSize() - 1, res.fResultsPro[AFO_PT]->GetXaxis()->GetXbins()->GetArray(), + res.fResultsPro[AFO_ETA]->GetXaxis()->GetXbins()->GetSize() - 1, res.fResultsPro[AFO_ETA]->GetXaxis()->GetXbins()->GetArray()); + res.fResultsPro3D[AFO_CENTRALITY_PT_ETA]->GetXaxis()->SetTitle(res.fResultsPro[AFO_CENTRALITY]->GetXaxis()->GetTitle()); + res.fResultsPro3D[AFO_CENTRALITY_PT_ETA]->GetYaxis()->SetTitle(res.fResultsPro[AFO_PT]->GetXaxis()->GetTitle()); + res.fResultsPro3D[AFO_CENTRALITY_PT_ETA]->GetZaxis()->SetTitle(res.fResultsPro[AFO_ETA]->GetXaxis()->GetTitle()); + res.fResultsPro3D[AFO_CENTRALITY_PT_ETA]->SetStats(false); + } + + if (t0.fCalculate3DTest0AsFunctionOf[AFO_CENTRALITY_PT_CHARGE]) { + TString rawName = TString::Format("%s_%s_%s", res.fResultsProRawName[AFO_CENTRALITY].Data(), res.fResultsProRawName[AFO_PT].Data(), res.fResultsProRawName[AFO_CHARGE].Data()); + res.fResultsPro3D[AFO_CENTRALITY_PT_CHARGE] = new TProfile3D(Form("fResultsPro3D[%s]", rawName.Data()), "...", + res.fResultsPro[AFO_CENTRALITY]->GetXaxis()->GetXbins()->GetSize() - 1, res.fResultsPro[AFO_CENTRALITY]->GetXaxis()->GetXbins()->GetArray(), + res.fResultsPro[AFO_PT]->GetXaxis()->GetXbins()->GetSize() - 1, res.fResultsPro[AFO_PT]->GetXaxis()->GetXbins()->GetArray(), + res.fResultsPro[AFO_CHARGE]->GetXaxis()->GetXbins()->GetSize() - 1, res.fResultsPro[AFO_CHARGE]->GetXaxis()->GetXbins()->GetArray()); + res.fResultsPro3D[AFO_CENTRALITY_PT_CHARGE]->GetXaxis()->SetTitle(res.fResultsPro[AFO_CENTRALITY]->GetXaxis()->GetTitle()); + res.fResultsPro3D[AFO_CENTRALITY_PT_CHARGE]->GetYaxis()->SetTitle(res.fResultsPro[AFO_PT]->GetXaxis()->GetTitle()); + res.fResultsPro3D[AFO_CENTRALITY_PT_CHARGE]->GetZaxis()->SetTitle(res.fResultsPro[AFO_CHARGE]->GetXaxis()->GetTitle()); + res.fResultsPro3D[AFO_CENTRALITY_PT_CHARGE]->SetStats(false); + } + + if (t0.fCalculate3DTest0AsFunctionOf[AFO_CENTRALITY_PT_VZ]) { + TString rawName = TString::Format("%s_%s_%s", res.fResultsProRawName[AFO_CENTRALITY].Data(), res.fResultsProRawName[AFO_PT].Data(), res.fResultsProRawName[AFO_VZ].Data()); + res.fResultsPro3D[AFO_CENTRALITY_PT_VZ] = new TProfile3D(Form("fResultsPro3D[%s]", rawName.Data()), "...", + res.fResultsPro[AFO_CENTRALITY]->GetXaxis()->GetXbins()->GetSize() - 1, res.fResultsPro[AFO_CENTRALITY]->GetXaxis()->GetXbins()->GetArray(), + res.fResultsPro[AFO_PT]->GetXaxis()->GetXbins()->GetSize() - 1, res.fResultsPro[AFO_PT]->GetXaxis()->GetXbins()->GetArray(), + res.fResultsPro[AFO_VZ]->GetXaxis()->GetXbins()->GetSize() - 1, res.fResultsPro[AFO_VZ]->GetXaxis()->GetXbins()->GetArray()); + res.fResultsPro3D[AFO_CENTRALITY_PT_VZ]->GetXaxis()->SetTitle(res.fResultsPro[AFO_CENTRALITY]->GetXaxis()->GetTitle()); + res.fResultsPro3D[AFO_CENTRALITY_PT_VZ]->GetYaxis()->SetTitle(res.fResultsPro[AFO_PT]->GetXaxis()->GetTitle()); + res.fResultsPro3D[AFO_CENTRALITY_PT_VZ]->GetZaxis()->SetTitle(res.fResultsPro[AFO_VZ]->GetXaxis()->GetTitle()); + res.fResultsPro3D[AFO_CENTRALITY_PT_VZ]->SetStats(false); + } + + if (t0.fCalculate3DTest0AsFunctionOf[AFO_CENTRALITY_ETA_VZ]) { + TString rawName = TString::Format("%s_%s_%s", res.fResultsProRawName[AFO_CENTRALITY].Data(), res.fResultsProRawName[AFO_ETA].Data(), res.fResultsProRawName[AFO_VZ].Data()); + res.fResultsPro3D[AFO_CENTRALITY_ETA_VZ] = new TProfile3D(Form("fResultsPro3D[%s]", rawName.Data()), "...", + res.fResultsPro[AFO_CENTRALITY]->GetXaxis()->GetXbins()->GetSize() - 1, res.fResultsPro[AFO_CENTRALITY]->GetXaxis()->GetXbins()->GetArray(), + res.fResultsPro[AFO_ETA]->GetXaxis()->GetXbins()->GetSize() - 1, res.fResultsPro[AFO_ETA]->GetXaxis()->GetXbins()->GetArray(), + res.fResultsPro[AFO_VZ]->GetXaxis()->GetXbins()->GetSize() - 1, res.fResultsPro[AFO_VZ]->GetXaxis()->GetXbins()->GetArray()); + res.fResultsPro3D[AFO_CENTRALITY_ETA_VZ]->GetXaxis()->SetTitle(res.fResultsPro[AFO_CENTRALITY]->GetXaxis()->GetTitle()); + res.fResultsPro3D[AFO_CENTRALITY_ETA_VZ]->GetYaxis()->SetTitle(res.fResultsPro[AFO_ETA]->GetXaxis()->GetTitle()); + res.fResultsPro3D[AFO_CENTRALITY_ETA_VZ]->GetZaxis()->SetTitle(res.fResultsPro[AFO_VZ]->GetXaxis()->GetTitle()); + res.fResultsPro3D[AFO_CENTRALITY_ETA_VZ]->SetStats(false); + } + + if (t0.fCalculate3DTest0AsFunctionOf[AFO_CENTRALITY_ETA_CHARGE]) { + TString rawName = TString::Format("%s_%s_%s", res.fResultsProRawName[AFO_CENTRALITY].Data(), res.fResultsProRawName[AFO_ETA].Data(), res.fResultsProRawName[AFO_CHARGE].Data()); + res.fResultsPro3D[AFO_CENTRALITY_ETA_CHARGE] = new TProfile3D(Form("fResultsPro3D[%s]", rawName.Data()), "...", + res.fResultsPro[AFO_CENTRALITY]->GetXaxis()->GetXbins()->GetSize() - 1, res.fResultsPro[AFO_CENTRALITY]->GetXaxis()->GetXbins()->GetArray(), + res.fResultsPro[AFO_ETA]->GetXaxis()->GetXbins()->GetSize() - 1, res.fResultsPro[AFO_ETA]->GetXaxis()->GetXbins()->GetArray(), + res.fResultsPro[AFO_CHARGE]->GetXaxis()->GetXbins()->GetSize() - 1, res.fResultsPro[AFO_CHARGE]->GetXaxis()->GetXbins()->GetArray()); + res.fResultsPro3D[AFO_CENTRALITY_ETA_CHARGE]->GetXaxis()->SetTitle(res.fResultsPro[AFO_CENTRALITY]->GetXaxis()->GetTitle()); + res.fResultsPro3D[AFO_CENTRALITY_ETA_CHARGE]->GetYaxis()->SetTitle(res.fResultsPro[AFO_ETA]->GetXaxis()->GetTitle()); + res.fResultsPro3D[AFO_CENTRALITY_ETA_CHARGE]->GetZaxis()->SetTitle(res.fResultsPro[AFO_CHARGE]->GetXaxis()->GetTitle()); + res.fResultsPro3D[AFO_CENTRALITY_ETA_CHARGE]->SetStats(false); + } + + if (t0.fCalculate3DTest0AsFunctionOf[AFO_CENTRALITY_VZ_CHARGE]) { + TString rawName = TString::Format("%s_%s_%s", res.fResultsProRawName[AFO_CENTRALITY].Data(), res.fResultsProRawName[AFO_VZ].Data(), res.fResultsProRawName[AFO_CHARGE].Data()); + res.fResultsPro3D[AFO_CENTRALITY_VZ_CHARGE] = new TProfile3D(Form("fResultsPro3D[%s]", rawName.Data()), "...", + res.fResultsPro[AFO_CENTRALITY]->GetXaxis()->GetXbins()->GetSize() - 1, res.fResultsPro[AFO_CENTRALITY]->GetXaxis()->GetXbins()->GetArray(), + res.fResultsPro[AFO_VZ]->GetXaxis()->GetXbins()->GetSize() - 1, res.fResultsPro[AFO_VZ]->GetXaxis()->GetXbins()->GetArray(), + res.fResultsPro[AFO_CHARGE]->GetXaxis()->GetXbins()->GetSize() - 1, res.fResultsPro[AFO_CHARGE]->GetXaxis()->GetXbins()->GetArray()); + res.fResultsPro3D[AFO_CENTRALITY_VZ_CHARGE]->GetXaxis()->SetTitle(res.fResultsPro[AFO_CENTRALITY]->GetXaxis()->GetTitle()); + res.fResultsPro3D[AFO_CENTRALITY_VZ_CHARGE]->GetYaxis()->SetTitle(res.fResultsPro[AFO_VZ]->GetXaxis()->GetTitle()); + res.fResultsPro3D[AFO_CENTRALITY_VZ_CHARGE]->GetZaxis()->SetTitle(res.fResultsPro[AFO_CHARGE]->GetXaxis()->GetTitle()); + res.fResultsPro3D[AFO_CENTRALITY_VZ_CHARGE]->SetStats(false); + } + + if (t0.fCalculate3DTest0AsFunctionOf[AFO_PT_ETA_CHARGE]) { + TString rawName = TString::Format("%s_%s_%s", res.fResultsProRawName[AFO_PT].Data(), res.fResultsProRawName[AFO_ETA].Data(), res.fResultsProRawName[AFO_CHARGE].Data()); + res.fResultsPro3D[AFO_PT_ETA_CHARGE] = new TProfile3D(Form("fResultsPro3D[%s]", rawName.Data()), "...", + res.fResultsPro[AFO_PT]->GetXaxis()->GetXbins()->GetSize() - 1, res.fResultsPro[AFO_PT]->GetXaxis()->GetXbins()->GetArray(), + res.fResultsPro[AFO_ETA]->GetXaxis()->GetXbins()->GetSize() - 1, res.fResultsPro[AFO_ETA]->GetXaxis()->GetXbins()->GetArray(), + res.fResultsPro[AFO_CHARGE]->GetXaxis()->GetXbins()->GetSize() - 1, res.fResultsPro[AFO_CHARGE]->GetXaxis()->GetXbins()->GetArray()); + res.fResultsPro3D[AFO_PT_ETA_CHARGE]->GetXaxis()->SetTitle(res.fResultsPro[AFO_PT]->GetXaxis()->GetTitle()); + res.fResultsPro3D[AFO_PT_ETA_CHARGE]->GetYaxis()->SetTitle(res.fResultsPro[AFO_ETA]->GetXaxis()->GetTitle()); + res.fResultsPro3D[AFO_PT_ETA_CHARGE]->GetZaxis()->SetTitle(res.fResultsPro[AFO_CHARGE]->GetXaxis()->GetTitle()); + res.fResultsPro3D[AFO_PT_ETA_CHARGE]->SetStats(false); + } + + // Optionally, save 3D results histograms - I need this mostly to check/validate the binning: + for (int v = 0; v < eAsFunctionOf3D_N; v++) { + + if (res.fSaveResultsHistograms && res.fResultsPro3D[v]) { + res.fResultsList->Add(res.fResultsPro3D[v]); + } + } if (tc.fVerbose) { ExitFunction(__FUNCTION__); @@ -6858,11 +7735,46 @@ void BookResultsHistograms() //============================================================ +TArrayD* ArrayWithBinEdges(int nBins, float min, float max) +{ + // Helper function to determine concrete bin edges, when the fixed-size binning was specified with nBins in (min, max). + + // a) Insanity checks on arguments; + // b) Okay, do the thing. + + if (tc.fVerbose) { + StartFunction(__FUNCTION__); + } + + // a) Insanity check on arguments: + if (nBins <= 0 || max < min || std::abs(max - min) < tc.fFloatingPointPrecision) { + LOGF(fatal, "\033[1;31m%s at line %d : Insane arguments for fixed-length binning: nBins = %d , min = %f, max = %f \033[0m", __FUNCTION__, __LINE__, nBins, min, max); + } + + // b) Okay, do the thing: + float binWidth = (max - min) / (1. * nBins); + + TArrayD* binEdges = new TArrayD(nBins + 1); + for (int b = 1; b <= nBins + 1; b++) { + binEdges->AddAt(min + (b - 1) * binWidth, b - 1); + } + + if (tc.fVerbose) { + ExitFunction(__FUNCTION__); + } + + return binEdges; + +} // TArrayD *ArrayWithBinEdges(int nBins, float min, float max) + +//============================================================ + void BookTheRest() { // Here I book everything not sorted (yes) in specific functions above. // a) Book the timer; + // b) Book TDatabasePDG; // *) ... if (tc.fVerbose) { @@ -6876,6 +7788,11 @@ void BookTheRest() tc.fTimer[eLocal] = new TStopwatch(); } + // b) Book TDatabasePDG: + if (tc.fUseDatabasePDG && (tc.fProcess[eGenericRecSim] || tc.fProcess[eGenericSim])) { + tc.fDatabasePDG = new TDatabasePDG(); // there is a standard memory blow-up here + } + if (tc.fVerbose) { ExitFunction(__FUNCTION__); } @@ -7389,19 +8306,23 @@ void ResetEventByEventQuantities() qv.fQvector[h][wp] = TComplex(0., 0.); } } + } // if (qv.fCalculateQvectors) + + if (qv.fCalculateqvectorsKineAny) { + ResetQ(); // TBI 20250601 do I really need this one here. It doesn't hurt, though... + // Remark: It's important to validate this reset with nested loops e-by-e and for all events. + for (int i = 0; i < static_cast(qv.fqvector.size()); ++i) { + for (int j = 0; j < static_cast(qv.fqvector[i].size()); ++j) { + qv.fqvectorEntries[i][j] = 0; + for (int k = 0; k < static_cast(qv.fqvector[i][j].size()); ++k) { + for (int l = 0; l < static_cast(qv.fqvector[i][j][k].size()); ++l) { + qv.fqvector[i][j][k][l] = {0., 0.}; // yes, this is the right notation for complex numbers + } + } + } + } - // b2) diff. Q-vector: - for (int bin = 1; bin <= gMaxNoBinsKine; bin++) { - qv.fqVectorEntries[PTq][bin - 1] = 0; // TBI 20240214 shall I loop also over enum's PTq and ETAq? If yes, fix it also below for qv.fqvector[PTq][bin - 1][... - qv.fqVectorEntries[ETAq][bin - 1] = 0; - for (int h = 0; h < gMaxHarmonic * gMaxCorrelator + 1; h++) { - for (int wp = 0; wp < gMaxCorrelator + 1; wp++) { // weight power - qv.fqvector[PTq][bin - 1][h][wp] = TComplex(0., 0.); - qv.fqvector[ETAq][bin - 1][h][wp] = TComplex(0., 0.); - } // for (int wp = 0; wp < gMaxCorrelator + 1; wp++) { // weight power - } // for (int h = 0; h < gMaxHarmonic * gMaxCorrelator + 1; h++) { - } // for (int b = 0; b < gMaxNoBinsKine; b++ ) { - } // if(qv.fCalculateQvectors) + } // if (qv.fCalculateqvectorsKineAny) // b3) integrated Q-vector needed for calculations with eta separations: if (es.fCalculateEtaSeparations) { @@ -7422,29 +8343,36 @@ void ResetEventByEventQuantities() } } - // b4) diff. q-vector in pt needed for calculations with eta separations: - if (es.fCalculateEtaSeparationsAsFunctionOf[AFO_PT]) { // yes, for the time being, only as a function of pt makes sense if eta separation is used - for (int ab = 0; ab < 2; ab++) { // ab = 0 <=> -eta , ab = 1 <=> + eta - for (int bin = 1; bin <= gMaxNoBinsKine; bin++) { - for (int h = 0; h < gMaxHarmonic; h++) { - if (es.fEtaSeparationsSkipHarmonics[h]) { - continue; - } - for (int e = 0; e < gMaxNumberEtaSeparations; e++) { - qv.fqabVector[ab][bin - 1][h][e] = TComplex(0., 0.); // yes, bin - 1 here + // b4) diff. q-vector needed for calculations with eta separations: + if (es.fCalculateEtaSeparationsAsFunctionOf[AFO_PT]) { // _444 check this conditions + // [-eta or +eta][eqvectorKine_N][global binNo][harmonic][eta separation] + for (int i = 0; i < static_cast(qv.fqabVector.size()); ++i) { + for (int j = 0; j < static_cast(qv.fqabVector[i].size()); ++j) { + for (int k = 0; k < static_cast(qv.fqabVector[i][j].size()); ++k) { + for (int l = 0; l < static_cast(qv.fqabVector[i][j][k].size()); ++l) { // yes, this dimension is for harmonics at the moment + if (es.fEtaSeparationsSkipHarmonics[l]) { + continue; + } + for (int m = 0; m < static_cast(qv.fqabVector[i][j][k][l].size()); ++m) { + qv.fqabVector[i][j][k][l][m] = {0., 0.}; // yes, this is the right notation for complex numbers + } } } } } - for (int ab = 0; ab < 2; ab++) { // ab = 0 <=> -eta , ab = 1 <=> + eta - for (int bin = 1; bin <= gMaxNoBinsKine; bin++) { - for (int e = 0; e < gMaxNumberEtaSeparations; e++) { - qv.fmab[ab][bin - 1][e] = 0.; // yes, bin - 1 here + // [-eta or +eta][eqvectorKine_N][global binNo][eta separation] + for (int i = 0; i < static_cast(qv.fmab.size()); ++i) { + for (int j = 0; j < static_cast(qv.fmab[i].size()); ++j) { + for (int k = 0; k < static_cast(qv.fmab[i][j].size()); ++k) { + for (int l = 0; l < static_cast(qv.fmab[i][j][k].size()); ++l) { + qv.fmab[i][j][k][l] = 0.; + } } } } - } + + } // if (es.fCalculateEtaSeparationsAsFunctionOf[AFO_PT]) // c) Reset ebe containers for nested loops: if (nl.fCalculateNestedLoops || nl.fCalculateCustomNestedLoops) { @@ -7458,14 +8386,74 @@ void ResetEventByEventQuantities() } // if(nl.fCalculateNestedLoops || nl.fCalculateCustomNestedLoops) if (nl.fCalculateKineCustomNestedLoops) { - for (int b = 0; b < res.fResultsPro[AFO_PT]->GetNbinsX(); b++) { + int nBins = -1; + + // 1D kine: + // **) vs. pt: + nBins = res.fResultsPro[AFO_PT]->GetNbinsX() + 2; // + 2 means that I take into account overflow and underflow, then skip it in the loop below + for (int b = 0; b < nBins; b++) { nl.ftaNestedLoopsKine[PTq][b][0]->Reset(); nl.ftaNestedLoopsKine[PTq][b][1]->Reset(); } - for (int b = 0; b < res.fResultsPro[AFO_ETA]->GetNbinsX(); b++) { + + // **) vs. eta: + nBins = res.fResultsPro[AFO_ETA]->GetNbinsX() + 2; // + 2 means that I take into account overflow and underflow, then skip it in the loop below + for (int b = 0; b < nBins; b++) { nl.ftaNestedLoopsKine[ETAq][b][0]->Reset(); nl.ftaNestedLoopsKine[ETAq][b][1]->Reset(); } + + // **) vs. charge: + nBins = res.fResultsPro[AFO_CHARGE]->GetNbinsX() + 2; // + 2 means that I take into account overflow and underflow, then skip it in the loop below + for (int b = 0; b < nBins; b++) { + nl.ftaNestedLoopsKine[CHARGEq][b][0]->Reset(); + nl.ftaNestedLoopsKine[CHARGEq][b][1]->Reset(); + } + + // ... + + // 2D kine: + // **) vs. (pt,eta): + if (res.fResultsPro2D[AfoKineMap2D(PT_ETAq)]) { // this is safe, because this one shall be booked if any of Correlations, Test0, EtaSeparations, etc., was requested + nBins = (res.fResultsPro2D[AfoKineMap2D(PT_ETAq)]->GetNbinsX() + 2) * (res.fResultsPro2D[AfoKineMap2D(PT_ETAq)]->GetNbinsY() + 2); // + 2 means that I take into account overflow and underflow, then skip it in the loop below + for (int b = 0; b < nBins; b++) { // loop over lineralized global bins + nl.ftaNestedLoopsKine[PT_ETAq][b][0]->Reset(); + nl.ftaNestedLoopsKine[PT_ETAq][b][1]->Reset(); + } + } + + // **) vs. (pt,charge): + if (res.fResultsPro2D[AfoKineMap2D(PT_CHARGEq)]) { // this is safe, because this one shall be booked if any of Correlations, Test0, EtaSeparations, etc., was requested + nBins = (res.fResultsPro2D[AfoKineMap2D(PT_CHARGEq)]->GetNbinsX() + 2) * (res.fResultsPro2D[AfoKineMap2D(PT_CHARGEq)]->GetNbinsY() + 2); // + 2 means that I take into account overflow and underflow, then skip it in the loop below + for (int b = 0; b < nBins; b++) { // loop over lineralized global bins + nl.ftaNestedLoopsKine[PT_CHARGEq][b][0]->Reset(); + nl.ftaNestedLoopsKine[PT_CHARGEq][b][1]->Reset(); + } + } + + // **) vs. (eta,charge): + if (res.fResultsPro2D[AfoKineMap2D(ETA_CHARGEq)]) { // this is safe, because this one shall be booked if any of Correlations, Test0, EtaSeparations, etc., was requested + nBins = (res.fResultsPro2D[AfoKineMap2D(ETA_CHARGEq)]->GetNbinsX() + 2) * (res.fResultsPro2D[AfoKineMap2D(ETA_CHARGEq)]->GetNbinsY() + 2); // + 2 means that I take into account overflow and underflow, then skip it in the loop below + for (int b = 0; b < nBins; b++) { // loop over lineralized global bins + nl.ftaNestedLoopsKine[ETA_CHARGEq][b][0]->Reset(); + nl.ftaNestedLoopsKine[ETA_CHARGEq][b][1]->Reset(); + } + } + + // ... + + // 3D kine: + // **) vs. (pt,eta,charge): + if (res.fResultsPro3D[AfoKineMap3D(PT_ETA_CHARGEq)]) { // this is safe, because this one shall be booked if any of Correlations, Test0, EtaSeparations, etc., was requested + nBins = (res.fResultsPro3D[AfoKineMap3D(PT_ETA_CHARGEq)]->GetNbinsX() + 2) * (res.fResultsPro3D[AfoKineMap3D(PT_ETA_CHARGEq)]->GetNbinsY() + 2) * (res.fResultsPro3D[AfoKineMap3D(PT_ETA_CHARGEq)]->GetNbinsZ() + 2); // + 2 means that I take into account overflow and underflow, then skip it in the loop below + for (int b = 0; b < nBins; b++) { // loop over lineralized global bins + nl.ftaNestedLoopsKine[PT_ETA_CHARGEq][b][0]->Reset(); + nl.ftaNestedLoopsKine[PT_ETA_CHARGEq][b][1]->Reset(); + } + } + + // ... + } // if(nl.fCalculateKineCustomNestedLoops) { // d) Fisher-Yates algorithm: @@ -8114,6 +9102,72 @@ bool EventCuts(T1 const& collision, T2 const& tracks, eCutModus cutModus) } } + // *) FT0Bad: // see O2Physics/Common/CCDB/RCTSelectionFlags.h + if (ec.fUseEventCuts[eFT0Bad]) { + if (cutModus == eCutCounterBinning) { + EventCut(eRec, eFT0Bad, eCutCounterBinning); + } else if (collision.rct_bit(o2::aod::rctsel::kFT0Bad)) { + if (!EventCut(eRec, eFT0Bad, cutModus)) { + return false; + } + } + } + + // *) ITSBad: // see O2Physics/Common/CCDB/RCTSelectionFlags.h + if (ec.fUseEventCuts[eITSBad]) { + if (cutModus == eCutCounterBinning) { + EventCut(eRec, eITSBad, eCutCounterBinning); + } else if (collision.rct_bit(o2::aod::rctsel::kITSBad)) { + if (!EventCut(eRec, eITSBad, cutModus)) { + return false; + } + } + } + + // *) ITSLimAccMCRepr: // see O2Physics/Common/CCDB/RCTSelectionFlags.h + if (ec.fUseEventCuts[eITSLimAccMCRepr]) { + if (cutModus == eCutCounterBinning) { + EventCut(eRec, eITSLimAccMCRepr, eCutCounterBinning); + } else if (collision.rct_bit(o2::aod::rctsel::kITSLimAccMCRepr)) { + if (!EventCut(eRec, eITSLimAccMCRepr, cutModus)) { + return false; + } + } + } + + // *) TPCBadTracking: // see O2Physics/Common/CCDB/RCTSelectionFlags.h + if (ec.fUseEventCuts[eTPCBadTracking]) { + if (cutModus == eCutCounterBinning) { + EventCut(eRec, eTPCBadTracking, eCutCounterBinning); + } else if (collision.rct_bit(o2::aod::rctsel::kTPCBadTracking)) { + if (!EventCut(eRec, eTPCBadTracking, cutModus)) { + return false; + } + } + } + + // *) TPCLimAccMCRepr: // see O2Physics/Common/CCDB/RCTSelectionFlags.h + if (ec.fUseEventCuts[eTPCLimAccMCRepr]) { + if (cutModus == eCutCounterBinning) { + EventCut(eRec, eTPCLimAccMCRepr, eCutCounterBinning); + } else if (collision.rct_bit(o2::aod::rctsel::kTPCLimAccMCRepr)) { + if (!EventCut(eRec, eTPCLimAccMCRepr, cutModus)) { + return false; + } + } + } + + // *) TPCBadPID: // see O2Physics/Common/CCDB/RCTSelectionFlags.h + if (ec.fUseEventCuts[eTPCBadPID]) { + if (cutModus == eCutCounterBinning) { + EventCut(eRec, eTPCBadPID, eCutCounterBinning); + } else if (collision.rct_bit(o2::aod::rctsel::kTPCBadPID)) { + if (!EventCut(eRec, eTPCBadPID, cutModus)) { + return false; + } + } + } + // ... // *) Centrality weights (flattening): @@ -8588,7 +9642,7 @@ void FillEventHistograms(T1 const& collision, T2 const& tracks, eBeforeAfter ba) !eh.fEventHistograms[eImpactParameter][eSim][ba] ? true : eh.fEventHistograms[eImpactParameter][eSim][ba]->Fill(collision.impactParameter()); // yes, because in this branch 'collision' is always aod::McCollision !eh.fEventHistograms[eEventPlaneAngle][eSim][ba] ? true : eh.fEventHistograms[eEventPlaneAngle][eSim][ba]->Fill(collision.eventPlaneAngle()); // yes, because in this branch 'collision' is always aod::McCollision !eh.fEventHistograms[eMultiplicity][eSim][ba] ? true : eh.fEventHistograms[eMultiplicity][eSim][ba]->Fill(ebye.fMultiplicity); - !eh.fEventHistograms[eCentrality][eSim][ba] ? true : eh.fEventHistograms[eCentrality][eSim][ba]->Fill(ebye.fCentrality); // ebye.fCentrality = ebye.fCentralitySim in any case in this branh + !eh.fEventHistograms[eCentrality][eSim][ba] ? true : eh.fEventHistograms[eCentrality][eSim][ba]->Fill(ebye.fCentrality); // ebye.fCentrality = ebye.fCentralitySim in any case in this branch // eh.fEventHistograms[eReferenceMultiplicity][eSim][ba]->Fill(ebye.fReferenceMultiplicity); // TBI 20241123 this case is still not supported in DetermineReferenceMultiplicity() // eh.fEventHistograms[eTotalMultiplicity][eSim][ba]->Fill(tracks.size()); // TBI 20231030 check further how to use the same thing for 'sim' } @@ -8788,6 +9842,10 @@ void CheckUnderflowAndOverflow() { // Check and bail out if in event and particle histograms there are entries which went to underflow or overflow bins. + // TBI 20250527 I have reinvented the wheel here, there are already member functions TH1::IsBinUnderflow() and TH1::IsBinOverflow(), + // which I have use also for 2D and 3D cases with "global bin". + // Reimplemented this function using those member functions eventually. + // a) Event histograms 1D; // b) Event histograms 2D; // c) Particle histograms 1D; @@ -9597,31 +10655,30 @@ bool ParticleCuts(T const& track, eCutModus cutModus) // In this branch I can cut additionally and directly on corresponding MC truth simulated, e.g. on mcparticle.pt() // In case I implement something here, remember to switch from eRec to eSim when calling e.g. ParticleCut(...) - /* - // *) Phi: TBI 2024-511 re-think if i really cut directly on MC truth kine and other info and keep it in sync with what I did in AliPhysics - if (pc.fUseParticleCuts[ePhi]) { - if (cutModus == eCutCounterBinning) { - ParticleCut(eSim, ePhi, eCutCounterBinning); - } else if (mcparticle.phi() < pc.fdParticleCuts[ePhi][eMin] || mcparticle.phi() > pc.fdParticleCuts[ePhi][eMax]) { - if (!ParticleCut(eSim, ePhi, cutModus)) { - return false; - } - } - } - */ - // *) Charge: TBI 20240511 mcparticle.sign() doesn't exist, here most likely i need to cut on the signature of mcparticle.pdg() but check further, because e is negative charge, but PDG is 11, etc. - /* - if (pc.fUseParticleCuts[eCharge]) { - if (cutModus == eCutCounterBinning) { - ParticleCut(eSim, eCharge, eCutCounterBinning); - } else if (0 == mcparticle.sign() || mcparticle.sign() < pc.fdParticleCuts[eCharge][eMin] || mcparticle.sign() > pc.fdParticleCuts[eCharge][eMax]) { - // TBI 20240511 with first condition, I always throw away neutral particles, so for the time being that is hardcoded - if (!ParticleCut(eSim, eCharge, cutModus)) { - return false; - } - } - } - */ + // // *) Phi: TBI 2024-511 re-think if i really cut directly on MC truth kine and other info and keep it in sync with what I did in AliPhysics + // if (pc.fUseParticleCuts[ePhi]) { + // if (cutModus == eCutCounterBinning) { + // ParticleCut(eSim, ePhi, eCutCounterBinning); + // } else if (mcparticle.phi() < pc.fdParticleCuts[ePhi][eMin] || mcparticle.phi() > pc.fdParticleCuts[ePhi][eMax]) { + // if (!ParticleCut(eSim, ePhi, cutModus)) { + // return false; + // } + // } + // } + + // *) Charge: TBI 20240511 mcparticle.sign() doesn't exist, get charge from tc.fDatabasePDG instead using PDG code , as I did it below + + // if (pc.fUseParticleCuts[eCharge]) { + // if (cutModus == eCutCounterBinning) { + // ParticleCut(eSim, eCharge, eCutCounterBinning); + // } else if (0 == mcparticle.sign() || mcparticle.sign() < pc.fdParticleCuts[eCharge][eMin] || mcparticle.sign() > pc.fdParticleCuts[eCharge][eMax]) { + // // TBI 20240511 with first condition, I always throw away neutral particles, so for the time being that is hardcoded + // if (!ParticleCut(eSim, eCharge, cutModus)) { + // return false; + // } + // } + // } + // TBI 20240511 add cut on PDG // ... @@ -9670,23 +10727,42 @@ bool ParticleCuts(T const& track, eCutModus cutModus) } } - /* - // *) Charge: - if (pc.fUseParticleCuts[eCharge]) { - if (cutModus == eCutCounterBinning) { - ParticleCut(eSim, eCharge, eCutCounterBinning); - } else if (0 == track.sign() || track.sign() < pc.fdParticleCuts[eCharge][eMin] || track.sign() > pc.fdParticleCuts[eCharge][eMax]) { - // TBI 20240511 with first condition, I always throw away neutral particles, so for the time being that is hardcoded - if (!ParticleCut(eSim, eCharge, cutModus)) { - return false; - } - } + // *) Charge: + if (pc.fUseParticleCuts[eCharge]) { + double charge = -44.; // yes, never initialize charge to 0. + if (tc.fDatabasePDG && tc.fDatabasePDG->GetParticle(track.pdgCode())) { + // Yes, I have to check the 2nd condition, because e.g. for PDG code 1000010020 (deuteron), GetParticle(...) returns NULL + charge = tc.fDatabasePDG->GetParticle(track.pdgCode())->Charge() / 3.; // yes, divided by 3. Fundamental unit of charge is associated with quarks + if (tc.fVerboseForEachParticle) { + LOGF(info, "\033[1;33m%s at line %d: !!!! WARNING !!!! There is a large memory blow-up when using TDatabasePDG !!!! WARNING !!!! \033[0m", __FUNCTION__, __LINE__); } - */ - // TBI 20240511 add cut on PDG - - // ... - + } + if (cutModus == eCutCounterBinning) { + ParticleCut(eSim, eCharge, eCutCounterBinning); + } else if (0 == static_cast(charge) || charge < pc.fdParticleCuts[eCharge][eMin] || charge > pc.fdParticleCuts[eCharge][eMax]) { + // TBI 20250611 with first condition, I always throw away neutral particles when fDatabasePDG is used. + // However due to initialization charge = 0. that way I true all particles when fDatabasePDG is NOT used. + // Therefore, when fDatabasePDG is NOT used, I have to disable cut on charge, since that info is not available. + if (!ParticleCut(eSim, eCharge, cutModus)) { + return false; + } + } + } + + // *) PDG code: + if (pc.fUseParticleCuts[ePDG]) { + if (cutModus == eCutCounterBinning) { + ParticleCut(eSim, ePDG, eCutCounterBinning); + } else if (track.pdgCode() < pc.fdParticleCuts[ePDG][eMin] || track.pdgCode() > pc.fdParticleCuts[ePDG][eMax]) { + // TBI 20250611 I need to generalize this, e.g. add support to process more that one PDG code (e.g. 2212 and -2212, etc.) + if (!ParticleCut(eSim, ePDG, cutModus)) { + return false; + } + } + } + + // ... + } // if constexpr (rs == eSim || rs == eSim_Run2 || rs == eSim_Run1) { // ------------------------------------------------------------------------- @@ -9969,36 +11045,17 @@ void FillParticleHistograms(T const& track, eBeforeAfter ba, int weight = 1) // 1D: if (ph.fFillParticleHistograms) { - // From o2::aod::Tracks - - // memStatus ~120 + // From o2::aod::Tracks !ph.fParticleHistograms[ePhi][eRec][ba] ? true : ph.fParticleHistograms[ePhi][eRec][ba]->Fill(track.phi(), weight); - - // memStatus ~125 - !ph.fParticleHistograms[ePt][eRec][ba] ? true : ph.fParticleHistograms[ePt][eRec][ba]->Fill(track.pt(), weight); - - // memStatus ~127 - !ph.fParticleHistograms[eEta][eRec][ba] ? true : ph.fParticleHistograms[eEta][eRec][ba]->Fill(track.eta(), weight); - - // memStatus ~133 - !ph.fParticleHistograms[eCharge][eRec][ba] ? true : ph.fParticleHistograms[eCharge][eRec][ba]->Fill(track.sign(), weight); - // memStatus ~139 - // From o2::aod::TracksExtra_001 !ph.fParticleHistograms[etpcNClsFindable][eRec][ba] ? true : ph.fParticleHistograms[etpcNClsFindable][eRec][ba]->Fill(track.tpcNClsFindable(), weight); !ph.fParticleHistograms[etpcNClsShared][eRec][ba] ? true : ph.fParticleHistograms[etpcNClsShared][eRec][ba]->Fill(track.tpcNClsShared(), weight); - - // memStatus ~140 - !ph.fParticleHistograms[eitsChi2NCl][eRec][ba] ? true : ph.fParticleHistograms[eitsChi2NCl][eRec][ba]->Fill(track.itsChi2NCl(), weight); - - // memStatus ~146 - !ph.fParticleHistograms[etpcNClsFound][eRec][ba] ? true : ph.fParticleHistograms[etpcNClsFound][eRec][ba]->Fill(track.tpcNClsFound(), weight); !ph.fParticleHistograms[etpcNClsCrossedRows][eRec][ba] ? true : ph.fParticleHistograms[etpcNClsCrossedRows][eRec][ba]->Fill(track.tpcNClsCrossedRows(), weight); !ph.fParticleHistograms[eitsNCls][eRec][ba] ? true : ph.fParticleHistograms[eitsNCls][eRec][ba]->Fill(track.itsNCls(), weight); @@ -10031,13 +11088,13 @@ void FillParticleHistograms(T const& track, eBeforeAfter ba, int weight = 1) // **) eDWPt : here the fundamental 0-th axis never to be projected out is "pt" if (ph.fBookParticleSparseHistograms[eDWPt]) { // Remark: It is mandatory that ordering in initialization here resembles the ordering in enum eDiffPtWeights - double vector[eDiffPtWeights_N] = {track.pt()}; + double vector[eDiffPtWeights_N] = {track.pt(), static_cast(track.sign()), ebye.fCentrality}; ph.fParticleSparseHistograms[eDWPt][eRec]->Fill(vector, weight); } // **) eDWEta : here the fundamental 0-th axis never to be projected out is "eta" if (ph.fBookParticleSparseHistograms[eDWEta]) { // Remark: It is mandatory that ordering in initialization here resembles the ordering in enum eDiffEtaWeights - double vector[eDiffEtaWeights_N] = {track.eta()}; + double vector[eDiffEtaWeights_N] = {track.eta(), static_cast(track.sign()), ebye.fCentrality}; ph.fParticleSparseHistograms[eDWEta][eRec]->Fill(vector, weight); } } // if (ba == eAfter) { @@ -10145,8 +11202,16 @@ void FillParticleHistograms(T const& track, eBeforeAfter ba, int weight = 1) !ph.fParticleHistograms[ePhi][eSim][ba] ? true : ph.fParticleHistograms[ePhi][eSim][ba]->Fill(mcparticle.phi(), weight); !ph.fParticleHistograms[ePt][eSim][ba] ? true : ph.fParticleHistograms[ePt][eSim][ba]->Fill(mcparticle.pt(), weight); !ph.fParticleHistograms[eEta][eSim][ba] ? true : ph.fParticleHistograms[eEta][eSim][ba]->Fill(mcparticle.eta(), weight); - // !ph.fParticleHistograms[eCharge][eSim][ba] ? true : ph.fParticleHistograms[eCharge][eSim][ba]->Fill( ... ); // TBI 20240511 there is no mcparticle.sign()) - !ph.fParticleHistograms[ePDG][eSim][ba] ? true : ph.fParticleHistograms[ePDG][eSim][ba]->Fill(mcparticle.pdgCode(), weight); // TBI 20240512 this one gets filles correctly, deduce from it charge signature + + // special treatment for charge, because there is no getter mcparticle.sign() + double charge = -44.; // yes, never initialize charge to 0. + if (tc.fDatabasePDG && tc.fDatabasePDG->GetParticle(mcparticle.pdgCode())) { + // Yes, I have to check the 2nd condition, because e.g. for PDG code 1000010020 (deuteron), GetParticle(...) returns NULL + charge = tc.fDatabasePDG->GetParticle(mcparticle.pdgCode())->Charge() / 3.; // yes, divided by 3. Fundamental unit of charge is associated with quarks + } + + !ph.fParticleHistograms[eCharge][eSim][ba] ? true : ph.fParticleHistograms[eCharge][eSim][ba]->Fill(charge); + !ph.fParticleHistograms[ePDG][eSim][ba] ? true : ph.fParticleHistograms[ePDG][eSim][ba]->Fill(mcparticle.pdgCode(), weight); } // 2D: @@ -10160,22 +11225,44 @@ void FillParticleHistograms(T const& track, eBeforeAfter ba, int weight = 1) // **) eDWPhi : here the fundamental 0-th axis never to be projected out is "phi" if (ph.fBookParticleSparseHistograms[eDWPhi]) { // Remark: It is mandatory that ordering in initialization here resembles the ordering in enum eDiffPhiWeights - double vector[eDiffPhiWeights_N] = {mcparticle.phi(), mcparticle.pt(), mcparticle.eta(), 0., 0., 0.}; - // TBI 20250223 I do not have access to particle charge signature here => I set it to 0 temporarily. - // Then, I did not calculate and store centrality for "sim" => I set it to 0 temporarily. - // Same for vertex z, I could trivially extend ebye.fVz also for "sim" dimension => I set it to 0 temporarily here, until that's done. + + // special treatment for charge, because there is no getter mcparticle.sign() + double charge = -44.; // yes, never initialize charge to 0. + if (tc.fDatabasePDG && tc.fDatabasePDG->GetParticle(mcparticle.pdgCode())) { + // Yes, I have to check the 2nd condition, because e.g. for PDG code 1000010020 (deuteron), GetParticle(...) returns NULL + charge = tc.fDatabasePDG->GetParticle(mcparticle.pdgCode())->Charge() / 3.; // yes, divided by 3. Fundamental unit of charge is associated with quarks + } + + double vector[eDiffPhiWeights_N] = {mcparticle.phi(), mcparticle.pt(), mcparticle.eta(), charge, ebye.fCentralitySim, 0.}; + // TBI 20250611 I do nothing for vertex z, I could trivially extend ebye.fVz also for "sim" dimension => I set it to 0 temporarily here, until that's done. ph.fParticleSparseHistograms[eDWPhi][eSim]->Fill(vector, weight); } // **) eDWPt : here the fundamental 0-th axis never to be projected out is "pt" if (ph.fBookParticleSparseHistograms[eDWPt]) { // Remark: It is mandatory that ordering in initialization here resembles the ordering in enum eDiffPtWeights - double vector[eDiffPtWeights_N] = {mcparticle.pt()}; + + // special treatment for charge, because there is no getter mcparticle.sign() + double charge = -44.; // yes, never initialize charge to 0. + if (tc.fDatabasePDG && tc.fDatabasePDG->GetParticle(mcparticle.pdgCode())) { + // Yes, I have to check the 2nd condition, because e.g. for PDG code 1000010020 (deuteron), GetParticle(...) returns NULL + charge = tc.fDatabasePDG->GetParticle(mcparticle.pdgCode())->Charge() / 3.; // yes, divided by 3. Fundamental unit of charge is associated with quarks + } + + double vector[eDiffPtWeights_N] = {mcparticle.pt(), charge, ebye.fCentralitySim}; ph.fParticleSparseHistograms[eDWPt][eSim]->Fill(vector, weight); } // **) eDWEta : here the fundamental 0-th axis never to be projected out is "eta" if (ph.fBookParticleSparseHistograms[eDWEta]) { // Remark: It is mandatory that ordering in initialization here resembles the ordering in enum eDiffEtaWeights - double vector[eDiffEtaWeights_N] = {mcparticle.eta()}; + + // special treatment for charge, because there is no getter mcparticle.sign() + double charge = -44.; // yes, never initialize charge to 0. + if (tc.fDatabasePDG && tc.fDatabasePDG->GetParticle(mcparticle.pdgCode())) { + // Yes, I have to check the 2nd condition, because e.g. for PDG code 1000010020 (deuteron), GetParticle(...) returns NULL + charge = tc.fDatabasePDG->GetParticle(mcparticle.pdgCode())->Charge() / 3.; // yes, divided by 3. Fundamental unit of charge is associated with quarks + } + + double vector[eDiffEtaWeights_N] = {mcparticle.eta(), charge, ebye.fCentralitySim}; ph.fParticleSparseHistograms[eDWEta][eSim]->Fill(vector, weight); } } // if (ba == eAfter) { @@ -10194,7 +11281,15 @@ void FillParticleHistograms(T const& track, eBeforeAfter ba, int weight = 1) !ph.fParticleHistograms[ePhi][eSim][ba] ? true : ph.fParticleHistograms[ePhi][eSim][ba]->Fill(track.phi(), weight); !ph.fParticleHistograms[ePt][eSim][ba] ? true : ph.fParticleHistograms[ePt][eSim][ba]->Fill(track.pt(), weight); !ph.fParticleHistograms[eEta][eSim][ba] ? true : ph.fParticleHistograms[eEta][eSim][ba]->Fill(track.eta(), weight); - // !ph.fParticleHistograms[eCharge][eSim][ba] ? true : ph.fParticleHistograms[eCharge][eSim][ba]->Fill( ... ); // TBI 20240511 there is no mcparticle.sign()) + + // special treatment for charge, because there is no getter mcparticle.sign() + double charge = -44.; // yes, never initialize charge to 0. + if (tc.fDatabasePDG && tc.fDatabasePDG->GetParticle(track.pdgCode())) { + // Yes, I have to check the 2nd condition, because e.g. for PDG code 1000010020 (deuteron), GetParticle(...) returns NULL + charge = tc.fDatabasePDG->GetParticle(track.pdgCode())->Charge() / 3.; // yes, divided by 3. Fundamental unit of charge is associated with quarks + } + + !ph.fParticleHistograms[eCharge][eSim][ba] ? true : ph.fParticleHistograms[eCharge][eSim][ba]->Fill(charge); !ph.fParticleHistograms[ePDG][eSim][ba] ? true : ph.fParticleHistograms[ePDG][eSim][ba]->Fill(track.pdgCode(), weight); } // if(ph.fFillParticleHistograms) { @@ -10302,8 +11397,7 @@ void FillParticleHistograms(T const& track, eBeforeAfter ba, int weight = 1) void CalculateCorrelations() { // Calculate analytically multiparticle correlations from Q-vectors. - // In this method, only isotropic correlations for which all harmonics are the - // same are evaluated. + // In this method, only isotropic correlations for which all harmonics are the same are evaluated. // a) Flush 'n' fill the generic Q-vectors; // b) Calculate correlations; @@ -10352,7 +11446,7 @@ void CalculateCorrelations() if (std::abs(nestedLoopValue) > 0. && std::abs(twoC - nestedLoopValue) > tc.fFloatingPointPrecision) { LOGF(fatal, "\033[1;31m%s at line %d : nestedLoopValue = %f is not the same as twoC = %f\033[0m", __FUNCTION__, __LINE__, nestedLoopValue, twoC); } else { - LOGF(info, "\033[1;32m ebye check (integrated) with CustomNestedLoops is OK for isotropic 2-p, harmonic %d\033[0m", h); + LOGF(info, "\033[1;32m ebye check (integrated) with CustomNestedLoops is OK for isotropic 2-p, harmonic %d\033[0m", h); } delete harmonics; harmonics = NULL; @@ -10421,7 +11515,7 @@ void CalculateCorrelations() if (std::abs(nestedLoopValue) > 0. && std::abs(fourC - nestedLoopValue) > tc.fFloatingPointPrecision) { LOGF(fatal, "\033[1;31m%s at line %d : nestedLoopValue = %f is not the same as fourC = %f\033[0m", __FUNCTION__, __LINE__, nestedLoopValue, fourC); } else { - LOGF(info, "\033[1;32m ebye check (integrated) with CustomNestedLoops is OK for isotropic 4-p, harmonic %d\033[0m", h); + LOGF(info, "\033[1;32m ebye check (integrated) with CustomNestedLoops is OK for isotropic 4-p, harmonic %d\033[0m", h); } delete harmonics; harmonics = NULL; @@ -10492,7 +11586,7 @@ void CalculateCorrelations() if (std::abs(nestedLoopValue) > 0. && std::abs(sixC - nestedLoopValue) > tc.fFloatingPointPrecision) { LOGF(fatal, "\033[1;31m%s at line %d : nestedLoopValue = %f is not the same as sixC = %f\033[0m", __FUNCTION__, __LINE__, nestedLoopValue, sixC); } else { - LOGF(info, "\033[1;32m ebye check (integrated) with CustomNestedLoops is OK for isotropic 6-p, harmonic %d\033[0m", h); + LOGF(info, "\033[1;32m ebye check (integrated) with CustomNestedLoops is OK for isotropic 6-p, harmonic %d\033[0m", h); } delete harmonics; harmonics = NULL; @@ -10565,7 +11659,7 @@ void CalculateCorrelations() if (std::abs(nestedLoopValue) > 0. && std::abs(eightC - nestedLoopValue) > tc.fFloatingPointPrecision) { LOGF(fatal, "\033[1;31m%s at line %d : nestedLoopValue = %f is not the same as eightC = %f\033[0m", __FUNCTION__, __LINE__, nestedLoopValue, eightC); } else { - LOGF(info, "\033[1;32m ebye check (integrated) with CustomNestedLoops is OK for isotropic 8-p, harmonic %d\033[0m", h); + LOGF(info, "\033[1;32m ebye check (integrated) with CustomNestedLoops is OK for isotropic 8-p, harmonic %d\033[0m", h); } delete harmonics; harmonics = NULL; @@ -10640,6 +11734,11 @@ void CalculateKineCorrelations(eAsFunctionOf AFO_variable) // nBins = res.fResultsPro[AFO_ETA]->GetNbinsX(); // TBI 20241111 temporarily commented out just to suppress warnings break; } + case AFO_CHARGE: { + qvKine = CHARGEq; + // nBins = res.fResultsPro[AFO_ETA]->GetNbinsX(); // TBI 20241111 temporarily commented out just to suppress warnings + break; + } default: { LOGF(fatal, "\033[1;31m%s at line %d : This AFO_variable = %d is not supported yet. \033[0m", __FUNCTION__, __LINE__, static_cast(AFO_variable)); break; @@ -10836,7 +11935,7 @@ void CalculateTest0() } else if (std::abs(nestedLoopValue) > 0. && std::abs(correlation / weight - nestedLoopValue) > tc.fFloatingPointPrecision) { LOGF(fatal, "\033[1;31m%s at line %d : nestedLoopValue = %f is not the same as correlation/weight = %f, for correlator %s\033[0m", __FUNCTION__, __LINE__, nestedLoopValue, correlation / weight, t0.fTest0Labels[mo][mi]->Data()); } else { - LOGF(info, "\033[1;32m ebye check (integrated) with CustomNestedLoops is OK for %d-p Test0 corr. %s\033[0m", mo + 1, t0.fTest0Labels[mo][mi]->Data()); + LOGF(info, "\033[1;32m ebye check (integrated) with CustomNestedLoops is OK for %d-p Test0 corr. %s\033[0m", mo + 1, t0.fTest0Labels[mo][mi]->Data()); } delete harmonics; harmonics = NULL; @@ -10858,6 +11957,8 @@ void CalculateTest0() } // if(fUseInternalValidation && fRescaleWithTheoreticalInput) // Finally, fill: + + // 1D: // integrated: if (t0.fTest0Pro[mo][mi][AFO_INTEGRATED]) { t0.fTest0Pro[mo][mi][AFO_INTEGRATED]->Fill(0.5, correlation / weight, weight); @@ -10886,6 +11987,21 @@ void CalculateTest0() if (t0.fTest0Pro[mo][mi][AFO_VZ]) { t0.fTest0Pro[mo][mi][AFO_VZ]->Fill(ebye.fVz, correlation / weight, weight); } + + // ... + + // 2D: + // vs. centrality vs. vertex z position: + if (t0.fTest0Pro2D[mo][mi][AFO_CENTRALITY_VZ]) { + t0.fTest0Pro2D[mo][mi][AFO_CENTRALITY_VZ]->Fill(ebye.fCentrality, ebye.fVz, correlation / weight, weight); + } + + // ... + + // 3D: + + // ... + } // if(t0.fTest0Labels[mo][mi]) } // for(int mi=0;miGetNbinsX(); break; } + case AFO_CHARGE: { + qvKine = CHARGEq; + nBins = res.fResultsPro[AFO_CHARGE]->GetNbinsX(); + break; + } default: { LOGF(fatal, "\033[1;31m%s at line %d : This AFO_variable = %d is not supported yet. \033[0m", __FUNCTION__, __LINE__, static_cast(AFO_variable)); break; @@ -10935,11 +12060,11 @@ void CalculateKineTest0(eAsFunctionOf AFO_variable) LOGF(fatal, "\033[1;31m%s at line %d : qvKine == eqvectorKine_N => add some more entries to the case statement \033[0m", __FUNCTION__, __LINE__); } - // *) Uniform loop over bin for all kine variables: + // *) Uniform loop over bins for all kine variables: for (int b = 0; b < nBins; b++) { // *) Ensures that in each bin of interest, I have the same cut on number of particles, like in integrated analysis: - if ((qv.fqVectorEntries[qvKine][b] < ec.fdEventCuts[eMultiplicity][eMin]) || (qv.fqVectorEntries[qvKine][b] > ec.fdEventCuts[eMultiplicity][eMax] || std::abs(qv.fqVectorEntries[qvKine][b] - ec.fdEventCuts[eMultiplicity][eMax]) < tc.fFloatingPointPrecision)) { + if ((qv.fqvectorEntries[qvKine][b] < ec.fdEventCuts[eMultiplicity][eMin]) || (qv.fqvectorEntries[qvKine][b] > ec.fdEventCuts[eMultiplicity][eMax] || std::abs(qv.fqvectorEntries[qvKine][b] - ec.fdEventCuts[eMultiplicity][eMax]) < tc.fFloatingPointPrecision)) { if (tc.fVerbose) { LOGF(info, "\033[1;31m%s eMultiplicity cut in bin = %d, for qvKine = %d\033[0m", __FUNCTION__, b, static_cast(qvKine)); } @@ -10949,7 +12074,7 @@ void CalculateKineTest0(eAsFunctionOf AFO_variable) // After that, I can call all standard Q-vector functions again: for (int h = 0; h < gMaxHarmonic * gMaxCorrelator + 1; h++) { for (int wp = 0; wp < gMaxCorrelator + 1; wp++) { // weight power - qv.fQ[h][wp] = qv.fqvector[qvKine][b][h][wp]; + // qv.fQ[h][wp] = qv.fqvector[qvKine][b][h][wp]; TBI 20250616 I cannot use this any longer, after I added one more dimension to qv.fqvector } } @@ -10973,7 +12098,7 @@ void CalculateKineTest0(eAsFunctionOf AFO_variable) delete oa; // yes, otherwise it's a memory leak } - if (qv.fqVectorEntries[qvKine][b] < mo + 1) { + if (qv.fqvectorEntries[qvKine][b] < mo + 1) { continue; } @@ -11091,15 +12216,39 @@ void CalculateKineTest0(eAsFunctionOf AFO_variable) LOGF(info, "\n\033[1;33m t0.fTest0Pro[mo][mi][AFO_variable]->GetTitle() = %s \033[0m\n", t0.fTest0Pro[mo][mi][AFO_variable]->GetTitle()); LOGF(info, "\n\033[1;33m [mo][mi][AFO_variable] = [%d][%d][%d] \033[0m\n", mo, mi, static_cast(AFO_variable)); LOGF(info, "\n\033[1;33m ebye.fSelectedTracks = %d \033[0m\n", ebye.fSelectedTracks); - LOGF(info, "\n\033[1;33m qv.fqVectorEntries[qvKine][b] = %d \033[0m\n", qv.fqVectorEntries[qvKine][b]); + LOGF(info, "\n\033[1;33m qv.fqvectorEntries[qvKine][b] = %d \033[0m\n", qv.fqvectorEntries[qvKine][b]); LOGF(fatal, "\033[1;31m%s at line %d\033[0m", __FUNCTION__, __LINE__); } // Finally, fill: + + // 1D: if (t0.fTest0Pro[mo][mi][AFO_variable]) { t0.fTest0Pro[mo][mi][AFO_variable]->Fill(t0.fTest0Pro[mo][mi][AFO_variable]->GetXaxis()->GetBinCenter(b + 1), correlation / weight, weight); } // fill in the bin center + // 2D: + if (t0.fCalculate2DTest0) { + + // vs. centrality vs. pt: + if (t0.fTest0Pro2D[mo][mi][AFO_CENTRALITY_PT] && AFO_variable == AFO_PT) { + t0.fTest0Pro2D[mo][mi][AFO_CENTRALITY_PT]->Fill(ebye.fCentrality, t0.fTest0Pro2D[mo][mi][AFO_CENTRALITY_PT]->GetYaxis()->GetBinCenter(b + 1), correlation / weight, weight); + } + + // vs. centrality vs. eta: + if (t0.fTest0Pro2D[mo][mi][AFO_CENTRALITY_ETA] && AFO_variable == AFO_ETA) { + t0.fTest0Pro2D[mo][mi][AFO_CENTRALITY_ETA]->Fill(ebye.fCentrality, t0.fTest0Pro2D[mo][mi][AFO_CENTRALITY_ETA]->GetYaxis()->GetBinCenter(b + 1), correlation / weight, weight); + } + + // vs. centrality vs. charge: + if (t0.fTest0Pro2D[mo][mi][AFO_CENTRALITY_CHARGE] && AFO_variable == AFO_CHARGE) { + t0.fTest0Pro2D[mo][mi][AFO_CENTRALITY_CHARGE]->Fill(ebye.fCentrality, t0.fTest0Pro2D[mo][mi][AFO_CENTRALITY_CHARGE]->GetYaxis()->GetBinCenter(b + 1), correlation / weight, weight); + } + + // ... + + } // if(t0.fCalculate2DTest0) + } // if(fTest0Labels[mo][mi]) } // for(int mi=0;mi 0. && qv.fQabVector[1][h][e].Rho() > 0.)) { - continue; - } - if (!(qv.fMab[0][e] > 0. && qv.fMab[1][e] > 0.)) { - continue; - } - - // calculate correlation and weights with particular eta separation: - correlation = TComplex(qv.fQabVector[0][h][e] * TComplex::Conjugate(qv.fQabVector[1][h][e])).Re(); - weight = qv.fMab[0][e] * qv.fMab[1][e]; - - // for on-the-fly and internal validation, rescale results with theoretical value: - if (iv.fUseInternalValidation && iv.fRescaleWithTheoreticalInput && iv.fInternalValidationVnPsin[eVn] && std::abs(iv.fInternalValidationVnPsin[eVn]->GetAt(h)) > 0.) { - correlation /= std::pow(iv.fInternalValidationVnPsin[eVn]->GetAt(h), 2.); - } - - // integrated: - if (es.fEtaSeparationsPro[h][e][AFO_INTEGRATED]) { - es.fEtaSeparationsPro[h][e][AFO_INTEGRATED]->Fill(0.5, correlation / weight, weight); - } + int nBins = -1; - // vs. multiplicity: - if (es.fEtaSeparationsPro[h][e][AFO_MULTIPLICITY]) { - es.fEtaSeparationsPro[h][e][AFO_MULTIPLICITY]->Fill(ebye.fMultiplicity + 0.5, correlation / weight, weight); - } + switch (Ndim) { - // vs. centrality: - if (es.fEtaSeparationsPro[h][e][AFO_CENTRALITY]) { - es.fEtaSeparationsPro[h][e][AFO_CENTRALITY]->Fill(ebye.fCentrality, correlation / weight, weight); + case 1: { + eAsFunctionOf AFO_var = AfoKineMap1D(kineVarChoice); + if (res.fResultsPro[AFO_var]) { + nBins = res.fResultsPro[AFO_var]->GetNbinsX() + 2; // + 2 means that I take into account overflow and underflow, then skip it in the loop below. } - // vs. occupancy: - if (es.fEtaSeparationsPro[h][e][AFO_OCCUPANCY]) { - es.fEtaSeparationsPro[h][e][AFO_OCCUPANCY]->Fill(ebye.fOccupancy, correlation / weight, weight); - } + break; + } - // vs. interaction rate: - if (es.fEtaSeparationsPro[h][e][AFO_INTERACTIONRATE]) { - es.fEtaSeparationsPro[h][e][AFO_INTERACTIONRATE]->Fill(ebye.fInteractionRate, correlation / weight, weight); + case 2: { + eAsFunctionOf2D AFO_var = AfoKineMap2D(kineVarChoice); + if (res.fResultsPro2D[AFO_var]) { + nBins = (res.fResultsPro2D[AFO_var]->GetNbinsX() + 2) * (res.fResultsPro2D[AFO_var]->GetNbinsY() + 2); // + 2 means that I take into account overflow and underflow, then skip it in the loop below } - // vs. current run duration: - if (es.fEtaSeparationsPro[h][e][AFO_CURRENTRUNDURATION]) { - es.fEtaSeparationsPro[h][e][AFO_CURRENTRUNDURATION]->Fill(ebye.fCurrentRunDuration, correlation / weight, weight); - } + break; + } - // vs. vertex z position: - if (es.fEtaSeparationsPro[h][e][AFO_VZ]) { - es.fEtaSeparationsPro[h][e][AFO_VZ]->Fill(ebye.fVz, correlation / weight, weight); + case 3: { + eAsFunctionOf3D AFO_var = AfoKineMap3D(kineVarChoice); + if (res.fResultsPro3D[AFO_var]) { + nBins = (res.fResultsPro3D[AFO_var]->GetNbinsX() + 2) * (res.fResultsPro3D[AFO_var]->GetNbinsY() + 2) * (res.fResultsPro3D[AFO_var]->GetNbinsZ() + 2); // + 2 means that I take into account overflow and underflow, then skip it in the loop below } - - } // for (int e = 0; e < gMaxNumberEtaSeparations; e++) { - } // for (int h = 0; h < gMaxHarmonic; h++) { - - if (tc.fVerbose) { - ExitFunction(__FUNCTION__); - } - -} // void CalculateEtaSeparations() - -//============================================================ - -void CalculateKineEtaSeparations(eAsFunctionOf AFO_variable) -{ - // Calculate differential correlations with pseudorapidity separations. - - if (tc.fVerbose) { - StartFunction(__FUNCTION__); - } - - // *) ... - eqvectorKine qvKine = eqvectorKine_N; // which eqvectorKine enum - int nBins = -1; - - switch (AFO_variable) { - case AFO_PT: { - qvKine = PTq; - nBins = res.fResultsPro[AFO_PT]->GetNbinsX(); break; } - case AFO_ETA: { - LOGF(fatal, "\033[1;31m%s at line %d : It doesn't make sense (i.e. AFO_ETA cannot be used here). \033[0m", __FUNCTION__, __LINE__, static_cast(AFO_variable)); - break; // obsolete, but it supresses the warning - } + + // ... + default: { - LOGF(fatal, "\033[1;31m%s at line %d : This AFO_variable = %d is not supported yet. \033[0m", __FUNCTION__, __LINE__, static_cast(AFO_variable)); + LOGF(fatal, "\033[1;31m%s at line %d : Ndim = %d is not supported yet. \033[0m", __FUNCTION__, __LINE__, Ndim); break; } - } // switch(AFO_variable) - // *) Insanity checks on above settings: - if (qvKine == eqvectorKine_N) { - LOGF(fatal, "\033[1;31m%s at line %d : qvKine == eqvectorKine_N => add some more entries to the case statement \033[0m", __FUNCTION__, __LINE__); - } + } // switch (Ndim) - // *) Uniform loop over bin for all kine variables: - for (int b = 0; b < nBins; b++) { + // *) Uniform loop over linearized global bins for all kine variables: + for (int b = 0; b < nBins; b++) { // yes, "< nBins", not "<= nBins", because b runs over all regular bins + 2 (therefore, including underflow and overflow already) - /* TBI 20241206 Do I need to adapt and apply this cut, also for Qa and Qb? If so, most likely I would need to apply it on sum, i.e. on entries in Qa + Qb + // *) Check if this bin is overflow or underflow: + // Well, I already checked that when filling fqvector, if this global bin is overflow or underflow, qvector and number of entries shall be empty for that bin, so I am checking for that: + if (0 == qv.fqvectorEntries[kineVarChoice][b]) { + if (tc.fVerbose) { + LOGF(info, "\033[1;31m%s no entries in bin = %d, for kineVarChoice = %d (%s). Just skipping this bin (this is most likely underflow or overflow global bin)\033[0m", __FUNCTION__, b, static_cast(kineVarChoice), StringKineMap(kineVarChoice).Data()); + } + continue; + } - // *) Ensures that in each bin of interest, I have the same cut on number of particles, like in integrated analysis: - if ((qv.fqVectorEntries[qvKine][b] < ec.fdEventCuts[eMultiplicity][eMin]) || (qv.fqVectorEntries[qvKine][b] > ec.fdEventCuts[eMultiplicity][eMax] || std::abs(qv.fqVectorEntries[qvKine][b] - ec.fdEventCuts[eMultiplicity][eMax]) < tc.fFloatingPointPrecision)) { - if (tc.fVerbose) { - LOGF(info, "\033[1;31m%s eMultiplicity cut in bin = %d, for qvKine = %d\033[0m", __FUNCTION__, b, static_cast(qvKine)); - } - } + // *) Ensures that in each bin of interest, I have the same cut on number of particles, like in integrated analysis: + /* TBI 20250603 not sure any longer if I can use this code: + // 1. if i do not use it, I allow possibility that correlations are calculated even when that makes no sense (two few particles for that correlators) + // 2. if I use it, I will not be able to get exactly the same result after rebinning (or ironing out some dimensions) as in integrated analysis + // => re-think + if ((qv.fqvectorEntries[kineVarChoice][b] < ec.fdEventCuts[eMultiplicity][eMin]) || (qv.fqvectorEntries[kineVarChoice][b] > ec.fdEventCuts[eMultiplicity][eMax] || std::abs(qv.fqvectorEntries[kineVarChoice][b] - ec.fdEventCuts[eMultiplicity][eMax]) < tc.fFloatingPointPrecision)) { + if (tc.fVerbose) { + LOGF(info, "\033[1;31m%s eMultiplicity cut in global bin = %d, for kineVarChoice = %d (%s), there are only %d selected particles in this bin\033[0m", __FUNCTION__, b, static_cast(kineVarChoice), StringKineMap(kineVarChoice).Data(), qv.fqvectorEntries[kineVarChoice][b]); + } + } */ - // Calculate differential 2-p correlations with eta separations from Qa (-eta, index [0]) and Qb (+eta, index [1]) vectors: + // *) Re-initialize Q-vector to be q-vector in this bin: + // After that, I can call all standard Q-vector functions again: + for (int h = 0; h < gMaxHarmonic * gMaxCorrelator + 1; h++) { + for (int wp = 0; wp < gMaxCorrelator + 1; wp++) { + qv.fQ[h][wp] = TComplex(qv.fqvector[kineVarChoice][b][h][wp].real(), qv.fqvector[kineVarChoice][b][h][wp].imag()); // TBI 20250601 check if there is a simpler way to initialize ROOT TComplex with C++ type 'complex' + } + } + + // *) Okay, let's do transparently the differential calculus, whether it's 1D, 2D, 3D, ...: double correlation = 0.; double weight = 0.; - for (int h = 0; h < gMaxHarmonic; h++) { - if (es.fEtaSeparationsSkipHarmonics[h]) { - continue; - } + int n[gMaxCorrelator] = {0}; // array holding harmonics - for (int e = 0; e < gMaxNumberEtaSeparations; e++) { - if (!(qv.fqabVector[0][b][h][e].Rho() > 0. && qv.fqabVector[1][b][h][e].Rho() > 0.)) { - continue; - } - if (!(qv.fmab[0][b][e] > 0. && qv.fmab[1][b][e] > 0.)) { - continue; - } + for (int mo = 0; mo < gMaxCorrelator; mo++) { + for (int mi = 0; mi < gMaxIndex; mi++) { + // TBI 20240221 I do not have to loop each time all the way up to gMaxCorrelator and gMaxIndex, but nevermind now, it's not a big efficiency loss. + if (t0.fTest0Labels[mo][mi]) { + // Extract harmonics from TString, FS is " ": + for (int h = 0; h <= mo; h++) { + // cout<At(h)->GetName()).Atoi(); + delete oa; // yes, otherwise it's a memory leak + } - // calculate correlation and weights with particular eta separation: - correlation = TComplex(qv.fqabVector[0][b][h][e] * TComplex::Conjugate(qv.fqabVector[1][b][h][e])).Re(); - weight = qv.fmab[0][b][e] * qv.fmab[1][b][e]; + if (qv.fqvectorEntries[kineVarChoice][b] < mo + 1) { + continue; + } - // for on-the-fly and internal validation, rescale results with theoretical value: - if (iv.fUseInternalValidation && iv.fRescaleWithTheoreticalInput && iv.fInternalValidationVnPsin[eVn] && std::abs(iv.fInternalValidationVnPsin[eVn]->GetAt(h)) > 0.) { - correlation /= std::pow(iv.fInternalValidationVnPsin[eVn]->GetAt(h), 2.); - } + switch (mo + 1) // which order? yes, mo+1 + { + case 1: + correlation = One(n[0]).Re(); + weight = One(0).Re(); + break; - // finally, fill: - if (es.fEtaSeparationsPro[h][e][AFO_variable]) { - es.fEtaSeparationsPro[h][e][AFO_variable]->Fill(es.fEtaSeparationsPro[h][e][AFO_variable]->GetXaxis()->GetBinCenter(b + 1), correlation / weight, weight); - } - } - } - } // for (int b = 0; b < nBins; b++) { + case 2: + correlation = Two(n[0], n[1]).Re(); + weight = Two(0, 0).Re(); + break; - if (tc.fVerbose) { - ExitFunction(__FUNCTION__); - } + case 3: + correlation = Three(n[0], n[1], n[2]).Re(); + weight = Three(0, 0, 0).Re(); + break; -} // void CalculateKineEtaSeparations() + case 4: + correlation = Four(n[0], n[1], n[2], n[3]).Re(); + weight = Four(0, 0, 0, 0).Re(); + break; -//============================================================ + case 5: + correlation = Five(n[0], n[1], n[2], n[3], n[4]).Re(); + weight = Five(0, 0, 0, 0, 0).Re(); + break; -void FillNestedLoopsContainers(const int& particleIndex, const double& dPhi, const double& dPt, const double& dEta) -{ - // Fill into the nested loop containers the current particle. + case 6: + correlation = Six(n[0], n[1], n[2], n[3], n[4], n[5]).Re(); + weight = Six(0, 0, 0, 0, 0, 0).Re(); + break; - if (tc.fVerbose) { - StartFunction(__FUNCTION__); - } + case 7: + correlation = Seven(n[0], n[1], n[2], n[3], n[4], n[5], n[6]).Re(); + weight = Seven(0, 0, 0, 0, 0, 0, 0).Re(); + break; + + case 8: + correlation = Eight(n[0], n[1], n[2], n[3], n[4], n[5], n[6], n[7]).Re(); + weight = Eight(0, 0, 0, 0, 0, 0, 0, 0).Re(); + break; + + case 9: + correlation = Nine(n[0], n[1], n[2], n[3], n[4], n[5], n[6], n[7], n[8]).Re(); + weight = Nine(0, 0, 0, 0, 0, 0, 0, 0, 0).Re(); + break; + + case 10: + correlation = Ten(n[0], n[1], n[2], n[3], n[4], n[5], n[6], n[7], n[8], n[9]).Re(); + weight = Ten(0, 0, 0, 0, 0, 0, 0, 0, 0, 0).Re(); + break; + + case 11: + correlation = Eleven(n[0], n[1], n[2], n[3], n[4], n[5], n[6], n[7], n[8], n[9], n[10]).Re(); + weight = Eleven(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0).Re(); + break; + + case 12: + correlation = Twelve(n[0], n[1], n[2], n[3], n[4], n[5], n[6], n[7], n[8], n[9], n[10], n[11]).Re(); + weight = Twelve(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0).Re(); + break; + + default: + LOGF(fatal, "\033[1;31m%s at line %d : not supported yet: %s \n\n\033[0m", __FUNCTION__, __LINE__, t0.fTest0Labels[mo][mi]->Data()); + } // switch(mo+1) + + // *) e-b-e sanity check: + if (nl.fCalculateKineCustomNestedLoops) { + TArrayI* harmonics = new TArrayI(mo + 1); + for (int i = 0; i < mo + 1; i++) { + harmonics->SetAt(n[i], i); + } + if (!(weight > 0.)) { + LOGF(fatal, "\033[1;31m%s at line %d : is perhaps order of some requested correlator bigger than the number of particles? Correlator = %s \033[0m", __FUNCTION__, __LINE__, t0.fTest0Labels[mo][mi]->Data()); + } + double nestedLoopValue = this->CalculateKineCustomNestedLoops(harmonics, kineVarChoice, b); + PrintBinEdgesKine(kineVarChoice, b); + if (!(std::abs(nestedLoopValue) > 0.)) { + LOGF(info, " e-b-e check with CalculateKineCustomNestedLoops was NOT calculated for %d-p Test0 corr. %s, kineVarChoice (eqvectorKine) = %d (%s), bin = %d", mo + 1, t0.fTest0Labels[mo][mi]->Data(), static_cast(kineVarChoice), StringKineMap(kineVarChoice).Data(), b); + } else if (std::abs(nestedLoopValue) > 0. && std::abs(correlation / weight - nestedLoopValue) > tc.fFloatingPointPrecision) { + LOGF(fatal, "\033[1;31m%s at line %d : correlator: %s \n correlation: %f \n custom loop: %f \033[0m", __FUNCTION__, __LINE__, t0.fTest0Labels[mo][mi]->Data(), correlation / weight, nestedLoopValue); + } else { + LOGF(info, "\033[1;32m ebye check (differential) with CalculateKineCustomNestedLoops is OK for %d-p Test0 corr. %s, kineVarChoice (eqvectorKine) = %d (%s), bin = %d, nParticles in this bin = %d\033[0m", mo + 1, t0.fTest0Labels[mo][mi]->Data(), static_cast(kineVarChoice), StringKineMap(kineVarChoice).Data(), b, qv.fqvectorEntries[kineVarChoice][b]); + } + delete harmonics; + harmonics = NULL; + } // if(nl.fCalculateKineCustomNestedLoops) + + // To ease comparison, rescale with theoretical value. Now all Test0 results shall be at 1: + if (iv.fUseInternalValidation && iv.fRescaleWithTheoreticalInput && iv.fInternalValidationVnPsin[eVn] && iv.fInternalValidationVnPsin[ePsin]) { + TArrayI* harmonics = new TArrayI(mo + 1); + for (int i = 0; i < mo + 1; i++) { + harmonics->SetAt(n[i], i); + } + TComplex theoreticalValue = TheoreticalValue(harmonics, iv.fInternalValidationVnPsin[eVn], iv.fInternalValidationVnPsin[ePsin]); + if (std::abs(theoreticalValue.Re()) > 0.) { + correlation /= theoreticalValue.Re(); + } + // TBI 20240424 for the time being, I do not do anything with imaginary part, but I could eventually... + delete harmonics; + harmonics = NULL; + } // if(fUseInternalValidation && fRescaleWithTheoreticalInput) + + // Insanity check for the event weight: + if (!(weight > 0.)) { + // If it's negative, that means that sum of particle weights is smaller than "number of particles - 1" + // In that case, you can simply rescale all particle weights, so that each of them is > 1, basically recalculate weights.root files with such a rescaling. + LOGF(info, "\n\033[1;33m b = %d \033[0m\n", b); + LOGF(info, "\n\033[1;33m kineVarChoice = %d \033[0m\n", static_cast(kineVarChoice)); + LOGF(info, "\n\033[1;33m event weight = %e \033[0m\n", weight); + LOGF(info, "\n\033[1;33m sum of particle weights = %e \033[0m\n", One(0).Re()); + LOGF(info, "\n\033[1;33m correlation = %f \033[0m\n", correlation); + + switch (Ndim) { + + case 1: { + eAsFunctionOf AFO_var = AfoKineMap1D(kineVarChoice); + LOGF(info, "\n\033[1;33m t0.fTest0Pro[mo][mi][AFO_variable]->GetTitle() = %s \033[0m\n", t0.fTest0Pro[mo][mi][AFO_var]->GetTitle()); + LOGF(info, "\n\033[1;33m [mo][mi][AFO_variable] = [%d][%d][%d] \033[0m\n", mo, mi, static_cast(AFO_var)); + break; + } + + case 2: { + eAsFunctionOf2D AFO_var = AfoKineMap2D(kineVarChoice); + LOGF(info, "\n\033[1;33m t0.fTest0Pro2D[mo][mi][AFO_variable]->GetTitle() = %s \033[0m\n", t0.fTest0Pro2D[mo][mi][AFO_var]->GetTitle()); + LOGF(info, "\n\033[1;33m [mo][mi][AFO_variable] = [%d][%d][%d] \033[0m\n", mo, mi, static_cast(AFO_var)); + break; + } + + case 3: { + eAsFunctionOf3D AFO_var = AfoKineMap3D(kineVarChoice); + LOGF(info, "\n\033[1;33m t0.fTest0Pro3D[mo][mi][AFO_variable]->GetTitle() = %s \033[0m\n", t0.fTest0Pro3D[mo][mi][AFO_var]->GetTitle()); + LOGF(info, "\n\033[1;33m [mo][mi][AFO_variable] = [%d][%d][%d] \033[0m\n", mo, mi, static_cast(AFO_var)); + break; + } + + // ... + + default: { + LOGF(fatal, "\033[1;31m%s at line %d : Ndim = %d is not supported yet. \033[0m", __FUNCTION__, __LINE__, Ndim); + break; + } + + } // switch (Ndim) + + LOGF(info, "\n\033[1;33m ebye.fSelectedTracks = %d \033[0m\n", ebye.fSelectedTracks); + LOGF(info, "\n\033[1;33m qv.fqvectorEntries[kineVarChoice][b] = %d \033[0m\n", qv.fqvectorEntries[kineVarChoice][b]); + LOGF(fatal, "\033[1;31m%s at line %d\033[0m", __FUNCTION__, __LINE__); + } + + // Finally, fill: + switch (Ndim) { + + case 1: { + + // *) cases for which 1D vs. pt calculus is needed: + if (kineVarChoice == PTq) { + // **) vs. pt: + if (t0.fTest0Pro[mo][mi][AFO_PT]) { + t0.fTest0Pro[mo][mi][AFO_PT]->Fill(t0.fTest0Pro[mo][mi][AFO_PT]->GetXaxis()->GetBinCenter(b), correlation / weight, weight); // only for 1D kine case, I can use direcly b, because "linearized global bin" is the same as ordinary bin + } + // **) vs. centrality vs. pt: + if (t0.fTest0Pro2D[mo][mi][AFO_CENTRALITY_PT]) { + t0.fTest0Pro2D[mo][mi][AFO_CENTRALITY_PT]->Fill(ebye.fCentrality, t0.fTest0Pro2D[mo][mi][AFO_CENTRALITY_PT]->GetYaxis()->GetBinCenter(b), correlation / weight, weight); // only for 1D kine case, I can use direcly b, because "linearized global bin" is the same as ordinary bin + } + // **) vs. centrality vs. pt vs. vz: + if (t0.fTest0Pro3D[mo][mi][AFO_CENTRALITY_PT_VZ]) { + t0.fTest0Pro3D[mo][mi][AFO_CENTRALITY_PT_VZ]->Fill(ebye.fCentrality, t0.fTest0Pro3D[mo][mi][AFO_CENTRALITY_PT_VZ]->GetYaxis()->GetBinCenter(b), ebye.fVz, correlation / weight, weight); // only for 1D kine case, I can use direcly b, because "linearized global bin" is the same as ordinary bin + } + + // ... + + } // if (kineVarChoice == PTq) { + + // *) cases for which 1D vs. eta calculus is needed: + if (kineVarChoice == ETAq) { + // **) vs. eta: + if (t0.fTest0Pro[mo][mi][AFO_ETA]) { + t0.fTest0Pro[mo][mi][AFO_ETA]->Fill(t0.fTest0Pro[mo][mi][AFO_ETA]->GetXaxis()->GetBinCenter(b), correlation / weight, weight); // only for 1D kine case, I can use direcly b, because "linearized global bin" is the same as ordinary bin + } + // **) vs. centrality vs. eta: + if (t0.fTest0Pro2D[mo][mi][AFO_CENTRALITY_ETA]) { + t0.fTest0Pro2D[mo][mi][AFO_CENTRALITY_ETA]->Fill(ebye.fCentrality, t0.fTest0Pro2D[mo][mi][AFO_CENTRALITY_ETA]->GetYaxis()->GetBinCenter(b), correlation / weight, weight); // only for 1D kine case, I can use direcly b, because "linearized global bin" is the same as ordinary bin + } + // **) vs. centrality vs. eta vs. vz: + if (t0.fTest0Pro3D[mo][mi][AFO_CENTRALITY_ETA_VZ]) { + t0.fTest0Pro3D[mo][mi][AFO_CENTRALITY_ETA_VZ]->Fill(ebye.fCentrality, t0.fTest0Pro3D[mo][mi][AFO_CENTRALITY_ETA_VZ]->GetYaxis()->GetBinCenter(b), ebye.fVz, correlation / weight, weight); // only for 1D kine case, I can use direcly b, because "linearized global bin" is the same as ordinary bin + } + + // ... + + } // if (kineVarChoice == ETAq) { + + // *) cases for which 1D vs. charge calculus is needed: + if (kineVarChoice == CHARGEq) { + // **) vs. charge: + if (t0.fTest0Pro[mo][mi][AFO_CHARGE]) { + t0.fTest0Pro[mo][mi][AFO_CHARGE]->Fill(t0.fTest0Pro[mo][mi][AFO_CHARGE]->GetXaxis()->GetBinCenter(b), correlation / weight, weight); // only for 1D kine case, I can use direcly b, because "linearized global bin" is the same as ordinary bin + } + // **) vs. centrality vs. charge: + if (t0.fTest0Pro2D[mo][mi][AFO_CENTRALITY_CHARGE]) { + t0.fTest0Pro2D[mo][mi][AFO_CENTRALITY_CHARGE]->Fill(ebye.fCentrality, t0.fTest0Pro2D[mo][mi][AFO_CENTRALITY_CHARGE]->GetYaxis()->GetBinCenter(b), correlation / weight, weight); // only for 1D kine case, I can use direcly b, because "linearized global bin" is the same as ordinary bin + } + + // **) vs. centrality vs. vz vs. charge: + if (t0.fTest0Pro3D[mo][mi][AFO_CENTRALITY_VZ_CHARGE]) { + t0.fTest0Pro3D[mo][mi][AFO_CENTRALITY_VZ_CHARGE]->Fill(ebye.fCentrality, ebye.fVz, t0.fTest0Pro3D[mo][mi][AFO_CENTRALITY_VZ_CHARGE]->GetZaxis()->GetBinCenter(b), correlation / weight, weight); // only for 1D kine case, I can use direcly b, because "linearized global bin" is the same as ordinary bin + } + + // ... + + } // if (kineVarChoice == CHARGEq) { + + // ... + + break; + } + + case 2: { + + // *) cases for which 2D vs. (pt,eta) calculus is needed: + if (kineVarChoice == PT_ETAq) { + + // transfer global bin b into (binX, binY, binZ): + int binX = -1; + int binY = -1; + int binZ = -1; // dummy for 2D case + t0.fTest0Pro2D[mo][mi][AFO_PT_ETA]->GetBinXYZ(b, binX, binY, binZ); + + // **) vs. pt vs. eta: + if (t0.fTest0Pro2D[mo][mi][AFO_PT_ETA]) { + t0.fTest0Pro2D[mo][mi][AFO_PT_ETA]->Fill(t0.fTest0Pro2D[mo][mi][AFO_PT_ETA]->GetXaxis()->GetBinCenter(binX), t0.fTest0Pro2D[mo][mi][AFO_PT_ETA]->GetYaxis()->GetBinCenter(binY), correlation / weight, weight); + } + + // **) vs. centrality vs. pt vs. eta: + if (t0.fTest0Pro3D[mo][mi][AFO_CENTRALITY_PT_ETA]) { + // Remark: I have to re-use binX, binY, binZ obtained from t0.fTest0Pro2D[mo][mi][AFO_PT_ETA] above, because I am looping for "case 2:" here over global bin number of + // t0.fTest0Pro2D[mo][mi][AFO_PT_ETA], not of t0.fTest0Pro3D[mo][mi][AFO_CENTRALITY_PT_ETA] + t0.fTest0Pro3D[mo][mi][AFO_CENTRALITY_PT_ETA]->Fill(ebye.fCentrality, t0.fTest0Pro3D[mo][mi][AFO_CENTRALITY_PT_ETA]->GetYaxis()->GetBinCenter(binX), t0.fTest0Pro3D[mo][mi][AFO_CENTRALITY_PT_ETA]->GetZaxis()->GetBinCenter(binY), correlation / weight, weight); // yes, y-axis of this histogram is x-axis of t0.fTest0Pro2D[mo][mi][AFO_PT_ETA], and similarly z-axis here is y-axis of t0.fTest0Pro2D[mo][mi][AFO_PT_ETA] + } + + // ... + + } // if (kineVarChoice == PT_ETAq) + + // *) cases for which 2D vs. (pt,charge) calculus is needed: + if (kineVarChoice == PT_CHARGEq) { + + // transfer global bin b into (binX, binY, binZ): + int binX = -1; + int binY = -1; + int binZ = -1; // dummy for 2D case + t0.fTest0Pro2D[mo][mi][AFO_PT_CHARGE]->GetBinXYZ(b, binX, binY, binZ); + + // **) vs. pt vs. charge: + if (t0.fTest0Pro2D[mo][mi][AFO_PT_CHARGE]) { + t0.fTest0Pro2D[mo][mi][AFO_PT_CHARGE]->Fill(t0.fTest0Pro2D[mo][mi][AFO_PT_CHARGE]->GetXaxis()->GetBinCenter(binX), t0.fTest0Pro2D[mo][mi][AFO_PT_CHARGE]->GetYaxis()->GetBinCenter(binY), correlation / weight, weight); + } + // **) vs. centrality vs. pt vs. charge: + if (t0.fTest0Pro3D[mo][mi][AFO_CENTRALITY_PT_CHARGE]) { + // Remark: I have to re-use binX, binY, binZ obtained from t0.fTest0Pro2D[mo][mi][AFO_PT_CHARGE] above, because I am looping for "case 2:" here over global bin number of + // t0.fTest0Pro2D[mo][mi][AFO_PT_CHARGE], not of t0.fTest0Pro3D[mo][mi][AFO_CENTRALITY_PT_CHARGE] + t0.fTest0Pro3D[mo][mi][AFO_CENTRALITY_PT_CHARGE]->Fill(ebye.fCentrality, t0.fTest0Pro3D[mo][mi][AFO_CENTRALITY_PT_CHARGE]->GetYaxis()->GetBinCenter(binX), t0.fTest0Pro3D[mo][mi][AFO_CENTRALITY_PT_CHARGE]->GetZaxis()->GetBinCenter(binY), correlation / weight, weight); // yes, y-axis of this histogram is x-axis of t0.fTest0Pro2D[mo][mi][AFO_PT_CHARGE], and similarly z-axis here is y-axis of t0.fTest0Pro2D[mo][mi][AFO_PT_CHARGE] + } + + // ... + + } // if (kineVarChoice == PT_CHARGEq) + + // *) cases for which 2D vs. (eta,charge) calculus is needed: + if (kineVarChoice == ETA_CHARGEq) { + + // transfer global bin b into (binX, binY, binZ): + int binX = -1; + int binY = -1; + int binZ = -1; // dummy for 2D case + t0.fTest0Pro2D[mo][mi][AFO_ETA_CHARGE]->GetBinXYZ(b, binX, binY, binZ); + + // **) vs. eta vs. charge: + if (t0.fTest0Pro2D[mo][mi][AFO_ETA_CHARGE]) { + t0.fTest0Pro2D[mo][mi][AFO_ETA_CHARGE]->Fill(t0.fTest0Pro2D[mo][mi][AFO_ETA_CHARGE]->GetXaxis()->GetBinCenter(binX), t0.fTest0Pro2D[mo][mi][AFO_ETA_CHARGE]->GetYaxis()->GetBinCenter(binY), correlation / weight, weight); + } + // **) vs. centrality vs. eta vs. charge: + if (t0.fTest0Pro3D[mo][mi][AFO_CENTRALITY_ETA_CHARGE]) { + // Remark: I have to re-use binX, binY, binZ obtained from t0.fTest0Pro2D[mo][mi][AFO_ETA_CHARGE] above, because I am looping for "case 2:" here over global bin number of + // t0.fTest0Pro2D[mo][mi][AFO_ETA_CHARGE], not of t0.fTest0Pro3D[mo][mi][AFO_CENTRALITY_ETA_CHARGE] + t0.fTest0Pro3D[mo][mi][AFO_CENTRALITY_ETA_CHARGE]->Fill(ebye.fCentrality, t0.fTest0Pro3D[mo][mi][AFO_CENTRALITY_ETA_CHARGE]->GetYaxis()->GetBinCenter(binX), t0.fTest0Pro3D[mo][mi][AFO_CENTRALITY_ETA_CHARGE]->GetZaxis()->GetBinCenter(binY), correlation / weight, weight); // yes, y-axis of this histogram is x-axis of t0.fTest0Pro2D[mo][mi][AFO_ETA_CHARGE], and similarly z-axis here is y-axis of t0.fTest0Pro2D[mo][mi][AFO_ETA_CHARGE] + } + + // ... + + } // if (kineVarChoice == ETA_CHARGEq) + + // ... + + break; + } + + case 3: { + + // *) cases for which 3D vs. (pt,eta,charge) calculus is needed: + if (kineVarChoice == PT_ETA_CHARGEq) { + + // transfer global bin b into (binX, binY, binZ): + int binX = -1; + int binY = -1; + int binZ = -1; + t0.fTest0Pro3D[mo][mi][AFO_PT_ETA_CHARGE]->GetBinXYZ(b, binX, binY, binZ); + + // **) vs. pt vs. eta vs. charge: + if (t0.fTest0Pro3D[mo][mi][AFO_PT_ETA_CHARGE]) { + t0.fTest0Pro3D[mo][mi][AFO_PT_ETA_CHARGE]->Fill(t0.fTest0Pro3D[mo][mi][AFO_PT_ETA_CHARGE]->GetXaxis()->GetBinCenter(binX), + t0.fTest0Pro3D[mo][mi][AFO_PT_ETA_CHARGE]->GetYaxis()->GetBinCenter(binY), + t0.fTest0Pro3D[mo][mi][AFO_PT_ETA_CHARGE]->GetZaxis()->GetBinCenter(binZ), + correlation / weight, weight); + } + } + + // ... + + break; + } + + // ... + + default: { + LOGF(fatal, "\033[1;31m%s at line %d : Ndim = %d is not supported yet. \033[0m", __FUNCTION__, __LINE__, Ndim); + break; + } + + } // switch (Ndim) + + } // if(fTest0Labels[mo][mi]) + } // for(int mi=0;mi kineVarChoice (eqvectorKine) = %d, global (ordinary) bin %d <=> (%f, %f)", static_cast(kineVarChoice), bin, res.fResultsPro[AfoKineMap1D(kineVarChoice)]->GetBinLowEdge(bin), res.fResultsPro[AfoKineMap1D(kineVarChoice)]->GetBinLowEdge(bin + 1)); + + break; + } + + // 2D: + case PT_ETAq: + case PT_CHARGEq: + case ETA_CHARGEq: { + + // transfer global bin b into (binX, binY, binZ): + int binX = -1; + int binY = -1; + int binZ = -1; // dummy for 2D case + res.fResultsPro2D[AfoKineMap2D(kineVarChoice)]->GetBinXYZ(bin, binX, binY, binZ); + + LOGF(info, " => kineVarChoice (eqvectorKine) = %d, global bin %d = (%d, %d) <=> (%f, %f) x (%f, %f)", static_cast(kineVarChoice), bin, binX, binY, res.fResultsPro2D[AfoKineMap2D(kineVarChoice)]->GetXaxis()->GetBinLowEdge(binX), res.fResultsPro2D[AfoKineMap2D(kineVarChoice)]->GetXaxis()->GetBinLowEdge(binX + 1), res.fResultsPro2D[AfoKineMap2D(kineVarChoice)]->GetYaxis()->GetBinLowEdge(binY), res.fResultsPro2D[AfoKineMap2D(kineVarChoice)]->GetYaxis()->GetBinLowEdge(binY + 1)); + + break; + } + + // 3D: + case PT_ETA_CHARGEq: { + + // transfer global bin b into (binX, binY, binZ): + int binX = -1; + int binY = -1; + int binZ = -1; + res.fResultsPro3D[AfoKineMap3D(kineVarChoice)]->GetBinXYZ(bin, binX, binY, binZ); + + LOGF(info, " => kineVarChoice (eqvectorKine) = %d, global bin %d = (%d, %d, %d) <=> (%f, %f) x (%f, %f) x (%f, %f)", static_cast(kineVarChoice), bin, binX, binY, binZ, res.fResultsPro3D[AfoKineMap3D(kineVarChoice)]->GetXaxis()->GetBinLowEdge(binX), res.fResultsPro3D[AfoKineMap3D(kineVarChoice)]->GetXaxis()->GetBinLowEdge(binX + 1), res.fResultsPro3D[AfoKineMap3D(kineVarChoice)]->GetYaxis()->GetBinLowEdge(binY), res.fResultsPro3D[AfoKineMap3D(kineVarChoice)]->GetYaxis()->GetBinLowEdge(binY + 1), res.fResultsPro3D[AfoKineMap3D(kineVarChoice)]->GetZaxis()->GetBinLowEdge(binZ), res.fResultsPro3D[AfoKineMap3D(kineVarChoice)]->GetZaxis()->GetBinLowEdge(binZ + 1)); + + break; + } + + default: { + LOGF(fatal, "\033[1;31m%s at line %d : This kineVarChoice = %d is not supported yet. \033[0m", __FUNCTION__, __LINE__, static_cast(kineVarChoice)); + break; + } + + } // switch(AFO_variable) + + if (tc.fVerbose) { + ExitFunction(__FUNCTION__); + } + +} // void PrintBinEdgesKine() + +//============================================================ + +void CalculateEtaSeparations() +{ + // Calculate correlations with pseudorapidity separations. + + // Remark: this is a port and generalization of void AliFlowAnalysisWithMultiparticleCorrelations::CalculateEtaGaps(AliFlowEventSimple *anEvent) + + if (tc.fVerbose) { + StartFunction(__FUNCTION__); + } + + // Calculate 2-p correlations with eta separations from Qa (-eta, index [0]) and Qb (+eta, index [1]) vectors: + double correlation = 0.; + double weight = 0.; + for (int h = 0; h < gMaxHarmonic; h++) { + if (es.fEtaSeparationsSkipHarmonics[h]) { + continue; + } + for (int e = 0; e < gMaxNumberEtaSeparations; e++) { + if (!(qv.fQabVector[0][h][e].Rho() > 0. && qv.fQabVector[1][h][e].Rho() > 0.)) { + continue; + } + if (!(qv.fMab[0][e] > 0. && qv.fMab[1][e] > 0.)) { + continue; + } + + // calculate correlation and weights with particular eta separation: + correlation = TComplex(qv.fQabVector[0][h][e] * TComplex::Conjugate(qv.fQabVector[1][h][e])).Re(); + weight = qv.fMab[0][e] * qv.fMab[1][e]; + + // for on-the-fly and internal validation, rescale results with theoretical value: + if (iv.fUseInternalValidation && iv.fRescaleWithTheoreticalInput && iv.fInternalValidationVnPsin[eVn] && std::abs(iv.fInternalValidationVnPsin[eVn]->GetAt(h)) > 0.) { + correlation /= std::pow(iv.fInternalValidationVnPsin[eVn]->GetAt(h), 2.); + } + + // integrated: + if (es.fEtaSeparationsPro[h][e][AFO_INTEGRATED]) { + es.fEtaSeparationsPro[h][e][AFO_INTEGRATED]->Fill(0.5, correlation / weight, weight); + } + + // vs. multiplicity: + if (es.fEtaSeparationsPro[h][e][AFO_MULTIPLICITY]) { + es.fEtaSeparationsPro[h][e][AFO_MULTIPLICITY]->Fill(ebye.fMultiplicity + 0.5, correlation / weight, weight); + } + + // vs. centrality: + if (es.fEtaSeparationsPro[h][e][AFO_CENTRALITY]) { + es.fEtaSeparationsPro[h][e][AFO_CENTRALITY]->Fill(ebye.fCentrality, correlation / weight, weight); + } + + // vs. occupancy: + if (es.fEtaSeparationsPro[h][e][AFO_OCCUPANCY]) { + es.fEtaSeparationsPro[h][e][AFO_OCCUPANCY]->Fill(ebye.fOccupancy, correlation / weight, weight); + } + + // vs. interaction rate: + if (es.fEtaSeparationsPro[h][e][AFO_INTERACTIONRATE]) { + es.fEtaSeparationsPro[h][e][AFO_INTERACTIONRATE]->Fill(ebye.fInteractionRate, correlation / weight, weight); + } + + // vs. current run duration: + if (es.fEtaSeparationsPro[h][e][AFO_CURRENTRUNDURATION]) { + es.fEtaSeparationsPro[h][e][AFO_CURRENTRUNDURATION]->Fill(ebye.fCurrentRunDuration, correlation / weight, weight); + } + + // vs. vertex z position: + if (es.fEtaSeparationsPro[h][e][AFO_VZ]) { + es.fEtaSeparationsPro[h][e][AFO_VZ]->Fill(ebye.fVz, correlation / weight, weight); + } + + } // for (int e = 0; e < gMaxNumberEtaSeparations; e++) { + } // for (int h = 0; h < gMaxHarmonic; h++) { + + if (tc.fVerbose) { + ExitFunction(__FUNCTION__); + } + +} // void CalculateEtaSeparations() + +//============================================================ + +void CalculateKineEtaSeparationsNdim(eqvectorKine kineVarChoice, int Ndim) +{ + // Calculate analytically N-dimensional kine eta separations from differential q-vectors. + + if (tc.fVerbose) { + StartFunction(__FUNCTION__); + } + + // This is a replacement for the legacy function CalculateKineEtaSeparations(...), which is as of 20250620 deemed obsolete. + // Remember that here I changed design, and pass enum eqvectorKine as an argument, not any longer enum eAsFunctionOf. + + if (tc.fVerbose) { + StartFunction(__FUNCTION__); + } + + int nBins = -1; + + switch (Ndim) { + + case 1: { + eAsFunctionOf AFO_var = AfoKineMap1D(kineVarChoice); + if (res.fResultsPro[AFO_var]) { + nBins = res.fResultsPro[AFO_var]->GetNbinsX() + 2; // + 2 means that I take into account overflow and underflow, then skip it in the loop below. + } + + break; + } + + case 2: { + eAsFunctionOf2D AFO_var = AfoKineMap2D(kineVarChoice); + if (res.fResultsPro2D[AFO_var]) { + nBins = (res.fResultsPro2D[AFO_var]->GetNbinsX() + 2) * (res.fResultsPro2D[AFO_var]->GetNbinsY() + 2); // + 2 means that I take into account overflow and underflow, then skip it in the loop below + } + + break; + } + + case 3: { + eAsFunctionOf3D AFO_var = AfoKineMap3D(kineVarChoice); + if (res.fResultsPro3D[AFO_var]) { + nBins = (res.fResultsPro3D[AFO_var]->GetNbinsX() + 2) * (res.fResultsPro3D[AFO_var]->GetNbinsY() + 2) * (res.fResultsPro3D[AFO_var]->GetNbinsZ() + 2); // + 2 means that I take into account overflow and underflow, then skip it in the loop below + } + break; + } + + // ... + + default: { + LOGF(fatal, "\033[1;31m%s at line %d : Ndim = %d is not supported yet. \033[0m", __FUNCTION__, __LINE__, Ndim); + break; + } + + } // switch (Ndim) + + // *) Uniform loop over linearized global bins for all kine variables: + for (int b = 0; b < nBins; b++) { // yes, "< nBins", not "<= nBins", because b runs over all regular bins + 2 (therefore, including underflow and overflow already) + + // TBI 20241206 Do I need to adapt and apply this cut, also for Qa and Qb? If so, most likely I would need to apply it on sum, i.e. on entries in Qa + Qb + // + // // *) Ensures that in each bin of interest, I have the same cut on number of particles, like in integrated analysis: + // if ((qv.fqvectorEntries[qvKine][b] < ec.fdEventCuts[eMultiplicity][eMin]) || (qv.fqvectorEntries[qvKine][b] > ec.fdEventCuts[eMultiplicity][eMax] || std::abs(qv.fqvectorEntries[qvKine][b] - ec.fdEventCuts[eMultiplicity][eMax]) < tc.fFloatingPointPrecision)) { + // if (tc.fVerbose) { + // LOGF(info, "\033[1;31m%s eMultiplicity cut in bin = %d, for qvKine = %d\033[0m", __FUNCTION__, b, static_cast(qvKine)); + // } + // } + + // Calculate differential 2-p correlations with eta separations from Qa (-eta, index [0]) and Qb (+eta, index [1]) vectors: + double correlation = 0.; + double weight = 0.; + for (int h = 0; h < gMaxHarmonic; h++) { + if (es.fEtaSeparationsSkipHarmonics[h]) { + continue; + } + + for (int e = 0; e < gMaxNumberEtaSeparations; e++) { + if (!(std::abs(qv.fqabVector[0][kineVarChoice][b][h][e]) > 0. && std::abs(qv.fqabVector[1][kineVarChoice][b][h][e]) > 0.)) { + continue; + } + if (!(qv.fmab[0][kineVarChoice][b][e] > 0. && qv.fmab[1][kineVarChoice][b][e] > 0.)) { + continue; + } + + // calculate correlation and weights with particular eta separation: + correlation = (qv.fqabVector[0][kineVarChoice][b][h][e] * std::conj(qv.fqabVector[1][kineVarChoice][b][h][e])).real(); + // Remark: this was the legacy code, just in case I would still need it: + // correlation = TComplex(qv.fqabVector[0][kineVarChoice][b][h][e] * TComplex::Conjugate(qv.fqabVector[1][kineVarChoice][b][h][e])).Re(); + weight = qv.fmab[0][kineVarChoice][b][e] * qv.fmab[1][kineVarChoice][b][e]; + + // for on-the-fly and internal validation, rescale results with theoretical value: + if (iv.fUseInternalValidation && iv.fRescaleWithTheoreticalInput && iv.fInternalValidationVnPsin[eVn] && std::abs(iv.fInternalValidationVnPsin[eVn]->GetAt(h)) > 0.) { + correlation /= std::pow(iv.fInternalValidationVnPsin[eVn]->GetAt(h), 2.); + } + + // finally, fill 1D case: + if (es.fEtaSeparationsPro[h][e][AfoKineMap1D(kineVarChoice)]) { + es.fEtaSeparationsPro[h][e][AfoKineMap1D(kineVarChoice)]->Fill(es.fEtaSeparationsPro[h][e][AfoKineMap1D(kineVarChoice)]->GetXaxis()->GetBinCenter(b), correlation / weight, weight); + } + + // TBI 20250620 I need to add support eventually also for 2D and 3D cases. + } + } + } // for (int b = 0; b < nBins; b++) + + // *) Quick insanity check: I shall never have any entry in underflow (bin = 0) or overflow (bin = nBins -1) in es.fEtaSeparationsPro, otherwise some cuts were bypassed: + if (tc.fDoAdditionalInsanityChecks) { + for (int h = 0; h < gMaxHarmonic; h++) { + for (int e = 0; e < gMaxNumberEtaSeparations; e++) { + if (es.fEtaSeparationsPro[h][e][AfoKineMap1D(kineVarChoice)] && std::abs(es.fEtaSeparationsPro[h][e][AfoKineMap1D(kineVarChoice)]->GetBinContent(0)) > 0.) { + LOGF(fatal, "\033[1;31m%s at line %d : underflow is not empty \033[0m", __FUNCTION__, __LINE__); + } + if (es.fEtaSeparationsPro[h][e][AfoKineMap1D(kineVarChoice)] && std::abs(es.fEtaSeparationsPro[h][e][AfoKineMap1D(kineVarChoice)]->GetBinContent(nBins - 1)) > 0.) { + LOGF(fatal, "\033[1;31m%s at line %d : overflow is not empty \033[0m", __FUNCTION__, __LINE__); + } + } + } + } // if (tc.fDoAdditionalInsanityChecks) + + if (tc.fVerbose) { + ExitFunction(__FUNCTION__); + } + +} // void CalculateKineEtaSeparationsNdim(eqvectorKine kineVarChoice, int Ndim) + +//============================================================ + +void FillNestedLoopsContainers(const int& particleIndex, const double& dPhi, const double& dPt, const double& dEta) +{ + // Fill into the nested loop containers the current particle. + + if (tc.fVerbose) { + StartFunction(__FUNCTION__); + } if (tc.fInsanityCheckForEachParticle) { if (particleIndex < 0) { @@ -11349,18 +13057,17 @@ void CalculateNestedLoops() LOGF(info, " ebye.fSelectedTracks = %d", ebye.fSelectedTracks); int nParticles = ebye.fSelectedTracks; - /* TBI 20220823 enable the lines below eventually - if(fUseFixedNumberOfRandomlySelectedTracks) - { - nParticles = 0; - for(int i=0;iGetSize();i++) - { - if(std::abs(ftaNestedLoops[0]->GetAt(i)) > 0. && - std::abs(ftaNestedLoops[1]->GetAt(i)) > 0.){nParticles++;} - } - } - cout<<"nParticles = "<GetSize();i++) + // { + // if(std::abs(ftaNestedLoops[0]->GetAt(i)) > 0. && + // std::abs(ftaNestedLoops[1]->GetAt(i)) > 0.){nParticles++;} + // } + // } + // cout<<"nParticles = "<Add(pw.fDiffWeightsSparse[dwc]); - /* - -TBI-today - - // Cosmetics: TBI 20240216 do I really want to overwrite initial cosmetics, perhaps this shall go better into MakeWeights.C ? - // Or I could move all this to GetHistogramWithWeights, where in any case I am setting e.g. histogram title, etc. - TString sVariable[eDiffWeights_N] = {"#varphi", "#varphi"}; // yes, for the time being, x-axis is always phi - TString sWeights[eDiffWeights_N] = {"(w_{#varphi})_{| p_{T}}", "(w_{#varphi})_{| #eta}"}; - pw.fDiffWeightsSparse[whichDiffWeight][bin]->SetStats(false); - pw.fDiffWeightsSparse[whichDiffWeight][bin]->GetXaxis()->SetTitle(sVariable[whichDiffWeight].Data()); - pw.fDiffWeightsSparse[whichDiffWeight][bin]->GetYaxis()->SetTitle(sWeights[whichDiffWeight].Data()); - pw.fDiffWeightsSparse[whichDiffWeight][bin]->SetFillColor(eFillColor); - pw.fDiffWeightsSparse[whichDiffWeight][bin]->SetLineColor(eColor); - pw.fWeightsList->Add(pw.fDiffWeightsSparse[whichDiffWeight][bin]); // This is working at the moment, because I am fetching all weights in Preprocess(), which is called after init() - // But if eventually it will be possible to fetch run number programatically in init(), I will have to re-think this line. - - // Flag: - if (!pw.fUseDiffWeights[whichDiffWeight]) // yes, set it only once to true, for all bins - { - pw.fUseDiffWeights[whichDiffWeight] = true; - } - - if (tc.fVerbose) { - ExitFunction(__FUNCTION__); - } - - */ + // TBI 20250530 check this code snippet - do I need it? + // // Cosmetics: TBI 20240216 do I really want to overwrite initial cosmetics, perhaps this shall go better into MakeWeights.C ? + // // Or I could move all this to GetHistogramWithWeights, where in any case I am setting e.g. histogram title, etc. + // TString sVariable[eDiffWeights_N] = {"#varphi", "#varphi"}; // yes, for the time being, x-axis is always phi + // TString sWeights[eDiffWeights_N] = {"(w_{#varphi})_{| p_{T}}", "(w_{#varphi})_{| #eta}"}; + // pw.fDiffWeightsSparse[whichDiffWeight][bin]->SetStats(false); + // pw.fDiffWeightsSparse[whichDiffWeight][bin]->GetXaxis()->SetTitle(sVariable[whichDiffWeight].Data()); + // pw.fDiffWeightsSparse[whichDiffWeight][bin]->GetYaxis()->SetTitle(sWeights[whichDiffWeight].Data()); + // pw.fDiffWeightsSparse[whichDiffWeight][bin]->SetFillColor(eFillColor); + // pw.fDiffWeightsSparse[whichDiffWeight][bin]->SetLineColor(eColor); + // pw.fWeightsList->Add(pw.fDiffWeightsSparse[whichDiffWeight][bin]); // This is working at the moment, because I am fetching all weights in Preprocess(), which is called after init() + // // But if eventually it will be possible to fetch run number programatically in init(), I will have to re-think this line. + + // // Flag: + // if (!pw.fUseDiffWeights[whichDiffWeight]) // yes, set it only once to true, for all bins + // { + // pw.fUseDiffWeights[whichDiffWeight] = true; + // } + + // if (tc.fVerbose) { + // ExitFunction(__FUNCTION__); + // } } // void SetDiffWeightsSparse(THnSparseF* const sparse) @@ -12678,52 +14380,50 @@ THnSparseF* GetSparseHistogramWithWeights(const char* filePath, const char* runN // hist->SetTitle(Form("%s, %.2f < %s < %.2f", filePath, min, lVariableName, max)); - /* - // *) insanity check for differential weights => check if boundaries of current bin are the same as bin boundaries for which these weights were calculated. - // This way I ensure that weights correspond to same kinematic cuts and binning as in current analysis. - // Current example format which was set in MakeWeights.C: someString(s), min < kinematic-variable-name < max - // Algorithm: IFS is " " and I take (N-1)th and (N-5)th entry: - TObjArray* oa = TString(hist->GetTitle()).Tokenize(" "); - if (!oa) { - LOGF(fatal, "in function \033[1;31m%s at line %d \n hist->GetTitle() = %s\033[0m", __FUNCTION__, __LINE__, hist->GetTitle()); - } - int nEntries = oa->GetEntries(); - - // I need to figure out corresponding variable from results histograms and its formatting: - eAsFunctionOf AFO = eAsFunctionOf_N; - const char* lVariableName = ""; - if (TString(variable).EqualTo("phipt")) { - AFO = AFO_PT; - lVariableName = FancyFormatting("Pt"); - } else if (TString(variable).EqualTo("phieta")) { - AFO = AFO_ETA; - lVariableName = FancyFormatting("Eta"); - } else { - LOGF(fatal, "\033[1;31m%s at line %d : name = %s is not supported yet. \033[0m", __FUNCTION__, __LINE__, static_cast(variable)); - } - - // Get min and max value for bin, stored locally: - float min = res.fResultsPro[AFO]->GetBinLowEdge(bin + 1); - float max = res.fResultsPro[AFO]->GetBinLowEdge(bin + 2); - if (min > max) { - LOGF(fatal, "\033[1;33m min = %f, max = %f, res.fResultsPro[AFO]->GetName() = %s\033[0m", min, max, res.fResultsPro[AFO]->GetName()); - } - - // Compare with min and max value stored in external weights.root file using MakeWeights.C: - if (!(std::abs(TString(oa->At(nEntries - 1)->GetName()).Atof() - max) < tc.fFloatingPointPrecision)) { - LOGF(info, "\033[1;33m hist->GetTitle() = %s, res.fResultsPro[AFO]->GetName() = %s\033[0m", hist->GetTitle(), res.fResultsPro[AFO]->GetName()); - LOGF(fatal, "in function \033[1;31m%s at line %d : mismatch in upper bin boundaries \n from title = %f , local = %f\033[0m", __FUNCTION__, __LINE__, TString(oa->At(nEntries - 1)->GetName()).Atof(), max); - } - if (!(std::abs(TString(oa->At(nEntries - 5)->GetName()).Atof() - min) < tc.fFloatingPointPrecision)) { - LOGF(info, "\033[1;33m hist->GetTitle() = %s, res.fResultsPro[AFO]->GetName() = %s\033[0m", hist->GetTitle(), res.fResultsPro[AFO]->GetName()); - LOGF(fatal, "in function \033[1;31m%s at line %d : mismatch in lower bin boundaries \n from title = %f , local = %f\033[0m", __FUNCTION__, __LINE__, TString(oa->At(nEntries - 5)->GetName()).Atof(), min); - } - delete oa; // yes, otherwise it's a memory leak - - // *) final settings and cosmetics: - hist->SetDirectory(0); - - */ + // TBI 20250530 check this code snippet - do I need it? + // // *) insanity check for differential weights => check if boundaries of current bin are the same as bin boundaries for which these weights were calculated. + // // This way I ensure that weights correspond to same kinematic cuts and binning as in current analysis. + // // Current example format which was set in MakeWeights.C: someString(s), min < kinematic-variable-name < max + // // Algorithm: IFS is " " and I take (N-1)th and (N-5)th entry: + // TObjArray* oa = TString(hist->GetTitle()).Tokenize(" "); + // if (!oa) { + // LOGF(fatal, "in function \033[1;31m%s at line %d \n hist->GetTitle() = %s\033[0m", __FUNCTION__, __LINE__, hist->GetTitle()); + // } + // int nEntries = oa->GetEntries(); + // + // // I need to figure out corresponding variable from results histograms and its formatting: + // eAsFunctionOf AFO = eAsFunctionOf_N; + // const char* lVariableName = ""; + // if (TString(variable).EqualTo("phipt")) { + // AFO = AFO_PT; + // lVariableName = FancyFormatting("Pt"); + // } else if (TString(variable).EqualTo("phieta")) { + // AFO = AFO_ETA; + // lVariableName = FancyFormatting("Eta"); + // } else { + // LOGF(fatal, "\033[1;31m%s at line %d : name = %s is not supported yet. \033[0m", __FUNCTION__, __LINE__, static_cast(variable)); + // } + // + // // Get min and max value for bin, stored locally: + // float min = res.fResultsPro[AFO]->GetBinLowEdge(bin + 1); + // float max = res.fResultsPro[AFO]->GetBinLowEdge(bin + 2); + // if (min > max) { + // LOGF(fatal, "\033[1;33m min = %f, max = %f, res.fResultsPro[AFO]->GetName() = %s\033[0m", min, max, res.fResultsPro[AFO]->GetName()); + // } + // + // // Compare with min and max value stored in external weights.root file using MakeWeights.C: + // if (!(std::abs(TString(oa->At(nEntries - 1)->GetName()).Atof() - max) < tc.fFloatingPointPrecision)) { + // LOGF(info, "\033[1;33m hist->GetTitle() = %s, res.fResultsPro[AFO]->GetName() = %s\033[0m", hist->GetTitle(), res.fResultsPro[AFO]->GetName()); + // LOGF(fatal, "in function \033[1;31m%s at line %d : mismatch in upper bin boundaries \n from title = %f , local = %f\033[0m", __FUNCTION__, __LINE__, TString(oa->At(nEntries - 1)->GetName()).Atof(), max); + // } + // if (!(std::abs(TString(oa->At(nEntries - 5)->GetName()).Atof() - min) < tc.fFloatingPointPrecision)) { + // LOGF(info, "\033[1;33m hist->GetTitle() = %s, res.fResultsPro[AFO]->GetName() = %s\033[0m", hist->GetTitle(), res.fResultsPro[AFO]->GetName()); + // LOGF(fatal, "in function \033[1;31m%s at line %d : mismatch in lower bin boundaries \n from title = %f , local = %f\033[0m", __FUNCTION__, __LINE__, TString(oa->At(nEntries - 5)->GetName()).Atof(), min); + // } + // delete oa; // yes, otherwise it's a memory leak + // + // // *) final settings and cosmetics: + // hist->SetDirectory(0); // TBI 20241021 if I need to split hist title across two lines, use this technique: // hist->SetTitle(Form("#splitline{#scale[0.6]{%s}}{#scale[0.4]{%s}}",hist->GetTitle(),filePath)); @@ -12873,20 +14573,6 @@ TH1D* GetHistogramWithCentralityWeights(const char* filePath, const char* runNum LOGF(fatal, "\033[1;31m%s at line %d\033[0m", __FUNCTION__, __LINE__); } - /* - // xxxxxxxxxxxx TBI 20241124 remove this code - - hist = reinterpret_cast(centralityWeightsFile->Get("FT0C_Default list name")); // TBI 20241122 temporary workaround - if (!hist) { - Exit(); - } - hist->SetDirectory(0); - hist->SetTitle(Form("%s, %s", filePath, runNumber)); // I have to do it here, because only here I have "filePath" available - return hist; - - // xxxxxxxxxxxx - */ - centralityWeightsFile->GetObject("ccdb_object", baseList); // TBI 20231008 for simplicity, hardwired name // of base TList is "ccdb_object" also for // local case, see if I need to change this @@ -12992,6 +14678,13 @@ TObjArray* GetDefaultObjArrayWithLabels(const char* whichDefaultLabels) TObjString* objstr = new TObjString(labels[l].Data()); arr->Add(objstr); } + } else if (TString(whichDefaultLabels).EqualTo("projections")) { // use this set to test projections when calculating multi-dimensional weights + const int nLabels = 10; + TString labels[nLabels] = {"1", "2", "3", "1 -1", "2 -2", "3 -3", "3 -1 -2", "1 1 -1 -1", "2 2 -2 -2", "3 3 -3 -3"}; + for (int l = 0; l < nLabels; l++) { + TObjString* objstr = new TObjString(labels[l].Data()); + arr->Add(objstr); + } } else if (TString(whichDefaultLabels).EqualTo("standard")) { const int nLabels = 7; TString labels[nLabels] = {"1 -1", "2 -2", "3 -3", "2 1 -1 -2", "3 1 -1 -3", "3 2 -2 -3", "3 2 1 -1 -2 -3"}; @@ -13798,6 +15491,19 @@ double WeightFromSparse(const double& dPhi, const double& dPt, const double& dEt // Each of these cases, however, have different global bin! // Total number of linearized global bins for N-dimensional sparse = (N_1 + 2) * (N_2 + 2) * ... (N_N + 2), // where N_1 is number of bins in first dimension, etc. The offset + 2 in each case counts underflow and overflow. + // Mapping between 2D bins and linearized global bins goes as follows (for an example 2 x 3 histogram): + // 0,0 => 0 + // 1,0 => 1 + // 2,0 => 2 + // 3,0 => 3 + // 0,1 => 4 + // 1,1 => 5 + // ... + // 2,4 => 18 + // 3,4 => 19 + // So, for 2 x 3 histogram, there are (2+2) * (3+2) = 20 linearized global bins. + // Remember that I need to loop first over y dimensions, then nest inside the loop over x dimension, to achieve loop over global bins in consequtive order. + double weight = pw.fDiffWeightsSparse[dwc]->GetBinContent(bin); if (tc.fVerbose) { @@ -13814,6 +15520,8 @@ double DiffWeight(const double& valueY, const double& valueX, eqvectorKine varia { // Determine differential particle weight y(x). For the time being, "y = phi" always, but this can be generalized. + // TBI 20250520 This function is now obsolete, use WeightFromSparse(...) instead. + if (tc.fVerbose) { StartFunction(__FUNCTION__); } @@ -14392,16 +16100,16 @@ double CalculateCustomNestedLoops(TArrayI* harmonics) } int nParticles = ebye.fSelectedTracks; - /* TBI 20231108 enable eventually - if(fUseFixedNumberOfRandomlySelectedParticles) - { - nParticles = 0; - for(int i=0;iGetSize();i++) - { - if(std::abs(nl.ftaNestedLoops[0]->GetAt(i)) > 0. && std::abs(nl.ftaNestedLoops[1]->GetAt(i)) > 0.){nParticles++;} - } - } - */ + // TBI 20250530 check this code snippet + // TBI 20231108 enable eventually + // if(fUseFixedNumberOfRandomlySelectedParticles) + // { + // nParticles = 0; + // for(int i=0;iGetSize();i++) + // { + // if(std::abs(nl.ftaNestedLoops[0]->GetAt(i)) > 0. && std::abs(nl.ftaNestedLoops[1]->GetAt(i)) > 0.){nParticles++;} + // } + // } // a) Determine the order of correlator; int order = harmonics->GetSize(); @@ -14590,6 +16298,10 @@ double CalculateCustomNestedLoops(TArrayI* harmonics) double CalculateKineCustomNestedLoops(TArrayI* harmonics, eAsFunctionOf AFO_variable, int bin) { + // !!! OBSOLETE FUNCTION !!! + + LOGF(info, "\033[1;33m%s at line %d: !!!! WARNING !!!! As of 20250529, this is an obsolete function, use double CalculateKineCustomNestedLoops(TArrayI* harmonics, eqvectorKine kineVarChoice, int bin) instead !!!! WARNING !!!! \033[0m", __FUNCTION__, __LINE__); + // For the specified harmonics, kine variable, and bin, get the correlation from nested loops. // Order of correlator is the number of harmonics, i.e. the number of elements in an array. @@ -14619,37 +16331,265 @@ double CalculateKineCustomNestedLoops(TArrayI* harmonics, eAsFunctionOf AFO_vari kineVarName = "eta"; break; } + case AFO_CHARGE: { + qvKine = CHARGEq; + kineVarName = "charge"; + break; + } default: { LOGF(fatal, "\033[1;31m%s at line %d : This AFO_variable = %d is not supported yet. \033[0m", __FUNCTION__, __LINE__, static_cast(AFO_variable)); break; } } // switch(AFO_variable) - // *) Insanity checks on above settings: - if (qvKine == eqvectorKine_N) { - LOGF(fatal, "\033[1;31m%s at line %d : qvKine == eqvectorKine_N => add some more entries to the case statement \033[0m", __FUNCTION__, __LINE__); + // *) Insanity checks on above settings: + if (qvKine == eqvectorKine_N) { + LOGF(fatal, "\033[1;31m%s at line %d : qvKine == eqvectorKine_N => add some more entries to the case statement \033[0m", __FUNCTION__, __LINE__); + } + + if (0 > bin || res.fResultsPro[AFO_variable]->GetNbinsX() < bin) { // this 'bin' starts from 0, i.e. this is an array bin + // either underflow or overflow is hit, meaning that histogram is booked in narrower range than cuts + LOGF(fatal, "\033[1;31m%s at line %d => AFO_variable = %d, bin = %d\033[0m", __FUNCTION__, __LINE__, static_cast(AFO_variable), bin); + } + + // Get the number of particles in this kine bin: + int nParticles = 0; + for (int i = 0; i < nl.ftaNestedLoopsKine[qvKine][bin][0]->GetSize(); i++) { + if (std::abs(nl.ftaNestedLoopsKine[qvKine][bin][0]->GetAt(i)) > 0.) { + nParticles++; + } + } + + // 'qvKine' is enum eqvectorKine: + if (!res.fResultsPro[AFO_variable]) { + LOGF(fatal, "\033[1;31m%s at line %d : AFO_variable = %d, bin = %d \033[0m", __FUNCTION__, __LINE__, static_cast(AFO_variable), bin); + } + + LOGF(info, " Processing qvKine = %d (vs. %s), nParticles in this kine bin = %d, bin range = [%f,%f) ....", static_cast(qvKine), kineVarName.Data(), nParticles, res.fResultsPro[AFO_variable]->GetBinLowEdge(bin + 1), res.fResultsPro[AFO_variable]->GetBinLowEdge(bin + 2)); + + // a) Determine the order of correlator; + int order = harmonics->GetSize(); + if (0 == order || order > gMaxCorrelator) { + LOGF(fatal, "\033[1;31m%s at line %d\033[0m", __FUNCTION__, __LINE__); + } + if (order > nParticles) { + LOGF(info, " There is no enough particles in this bin to calculate the requested correlator"); + return 0.; // TBI 20240405 Is this really safe here? Re-think... + } + if (nl.fMaxNestedLoop > 0 && nl.fMaxNestedLoop < order) { + LOGF(info, " nl.fMaxNestedLoop > 0 && nl.fMaxNestedLoop < order, where nl.fMaxNestedLoop = %d, order = %d", nl.fMaxNestedLoop, order); + return 0.; // TBI 20240405 Is this really safe here? Re-think... + } + + // b) Custom nested loop: + TProfile* profile = new TProfile("profile", "", 1, 0., 1.); // helper profile to get all averages automatically + // profile->Sumw2(); + double value = 0.; // cos of current multiplet + double weight = 1.; // weight of current multiplet + for (int i1 = 0; i1 < nParticles; i1++) { + double dPhi1 = nl.ftaNestedLoopsKine[qvKine][bin][0]->GetAt(i1); + double dW1 = nl.ftaNestedLoopsKine[qvKine][bin][1]->GetAt(i1); + if (1 == order) { + value = std::cos(harmonics->GetAt(0) * dPhi1); + weight = dW1; + profile->Fill(0.5, value, weight); + continue; + } + for (int i2 = 0; i2 < nParticles; i2++) { + if (i2 == i1) { + continue; + } + double dPhi2 = nl.ftaNestedLoopsKine[qvKine][bin][0]->GetAt(i2); + double dW2 = nl.ftaNestedLoopsKine[qvKine][bin][1]->GetAt(i2); + if (2 == order) { + value = std::cos(harmonics->GetAt(0) * dPhi1 + harmonics->GetAt(1) * dPhi2); + weight = dW1 * dW2; + profile->Fill(0.5, value, weight); + continue; + } + for (int i3 = 0; i3 < nParticles; i3++) { + if (i3 == i1 || i3 == i2) { + continue; + } + double dPhi3 = nl.ftaNestedLoopsKine[qvKine][bin][0]->GetAt(i3); + double dW3 = nl.ftaNestedLoopsKine[qvKine][bin][1]->GetAt(i3); + if (3 == order) { + value = std::cos(harmonics->GetAt(0) * dPhi1 + harmonics->GetAt(1) * dPhi2 + harmonics->GetAt(2) * dPhi3); + weight = dW1 * dW2 * dW3; + profile->Fill(0.5, value, weight); + continue; + } + for (int i4 = 0; i4 < nParticles; i4++) { + if (i4 == i1 || i4 == i2 || i4 == i3) { + continue; + } + double dPhi4 = nl.ftaNestedLoopsKine[qvKine][bin][0]->GetAt(i4); + double dW4 = nl.ftaNestedLoopsKine[qvKine][bin][1]->GetAt(i4); + if (4 == order) { + value = std::cos(harmonics->GetAt(0) * dPhi1 + harmonics->GetAt(1) * dPhi2 + harmonics->GetAt(2) * dPhi3 + harmonics->GetAt(3) * dPhi4); + weight = dW1 * dW2 * dW3 * dW4; + profile->Fill(0.5, value, weight); + continue; + } + for (int i5 = 0; i5 < nParticles; i5++) { + if (i5 == i1 || i5 == i2 || i5 == i3 || i5 == i4) { + continue; + } + double dPhi5 = nl.ftaNestedLoopsKine[qvKine][bin][0]->GetAt(i5); + double dW5 = nl.ftaNestedLoopsKine[qvKine][bin][1]->GetAt(i5); + if (5 == order) { + value = std::cos(harmonics->GetAt(0) * dPhi1 + harmonics->GetAt(1) * dPhi2 + harmonics->GetAt(2) * dPhi3 + harmonics->GetAt(3) * dPhi4 + harmonics->GetAt(4) * dPhi5); + weight = dW1 * dW2 * dW3 * dW4 * dW5; + profile->Fill(0.5, value, weight); + continue; + } + for (int i6 = 0; i6 < nParticles; i6++) { + if (i6 == i1 || i6 == i2 || i6 == i3 || i6 == i4 || i6 == i5) { + continue; + } + double dPhi6 = nl.ftaNestedLoopsKine[qvKine][bin][0]->GetAt(i6); + double dW6 = nl.ftaNestedLoopsKine[qvKine][bin][1]->GetAt(i6); + if (6 == order) { + value = std::cos(harmonics->GetAt(0) * dPhi1 + harmonics->GetAt(1) * dPhi2 + harmonics->GetAt(2) * dPhi3 + harmonics->GetAt(3) * dPhi4 + harmonics->GetAt(4) * dPhi5 + harmonics->GetAt(5) * dPhi6); + weight = dW1 * dW2 * dW3 * dW4 * dW5 * dW6; + profile->Fill(0.5, value, weight); + continue; + } + for (int i7 = 0; i7 < nParticles; i7++) { + if (i7 == i1 || i7 == i2 || i7 == i3 || i7 == i4 || i7 == i5 || i7 == i6) { + continue; + } + double dPhi7 = nl.ftaNestedLoopsKine[qvKine][bin][0]->GetAt(i7); + double dW7 = nl.ftaNestedLoopsKine[qvKine][bin][1]->GetAt(i7); + if (7 == order) { + value = std::cos(harmonics->GetAt(0) * dPhi1 + harmonics->GetAt(1) * dPhi2 + harmonics->GetAt(2) * dPhi3 + harmonics->GetAt(3) * dPhi4 + harmonics->GetAt(4) * dPhi5 + harmonics->GetAt(5) * dPhi6 + harmonics->GetAt(6) * dPhi7); + weight = dW1 * dW2 * dW3 * dW4 * dW5 * dW6 * dW7; + profile->Fill(0.5, value, weight); + continue; + } + for (int i8 = 0; i8 < nParticles; i8++) { + if (i8 == i1 || i8 == i2 || i8 == i3 || i8 == i4 || i8 == i5 || i8 == i6 || i8 == i7) { + continue; + } + double dPhi8 = nl.ftaNestedLoopsKine[qvKine][bin][0]->GetAt(i8); + double dW8 = nl.ftaNestedLoopsKine[qvKine][bin][1]->GetAt(i8); + if (8 == order) { + value = std::cos(harmonics->GetAt(0) * dPhi1 + harmonics->GetAt(1) * dPhi2 + harmonics->GetAt(2) * dPhi3 + harmonics->GetAt(3) * dPhi4 + harmonics->GetAt(4) * dPhi5 + harmonics->GetAt(5) * dPhi6 + harmonics->GetAt(6) * dPhi7 + harmonics->GetAt(7) * dPhi8); + weight = dW1 * dW2 * dW3 * dW4 * dW5 * dW6 * dW7 * dW8; + profile->Fill(0.5, value, weight); + continue; + } + for (int i9 = 0; i9 < nParticles; i9++) { + if (i9 == i1 || i9 == i2 || i9 == i3 || i9 == i4 || i9 == i5 || i9 == i6 || i9 == i7 || i9 == i8) { + continue; + } + double dPhi9 = nl.ftaNestedLoopsKine[qvKine][bin][0]->GetAt(i9); + double dW9 = nl.ftaNestedLoopsKine[qvKine][bin][1]->GetAt(i9); + if (9 == order) { + value = std::cos(harmonics->GetAt(0) * dPhi1 + harmonics->GetAt(1) * dPhi2 + harmonics->GetAt(2) * dPhi3 + harmonics->GetAt(3) * dPhi4 + harmonics->GetAt(4) * dPhi5 + harmonics->GetAt(5) * dPhi6 + harmonics->GetAt(6) * dPhi7 + harmonics->GetAt(7) * dPhi8 + harmonics->GetAt(8) * dPhi9); + weight = dW1 * dW2 * dW3 * dW4 * dW5 * dW6 * dW7 * dW8 * dW9; + profile->Fill(0.5, value, weight); + continue; + } + for (int i10 = 0; i10 < nParticles; i10++) { + if (i10 == i1 || i10 == i2 || i10 == i3 || i10 == i4 || i10 == i5 || i10 == i6 || i10 == i7 || i10 == i8 || i10 == i9) { + continue; + } + double dPhi10 = nl.ftaNestedLoopsKine[qvKine][bin][0]->GetAt(i10); + double dW10 = nl.ftaNestedLoopsKine[qvKine][bin][1]->GetAt(i10); + if (10 == order) { + value = std::cos(harmonics->GetAt(0) * dPhi1 + harmonics->GetAt(1) * dPhi2 + harmonics->GetAt(2) * dPhi3 + harmonics->GetAt(3) * dPhi4 + harmonics->GetAt(4) * dPhi5 + harmonics->GetAt(5) * dPhi6 + harmonics->GetAt(6) * dPhi7 + harmonics->GetAt(7) * dPhi8 + harmonics->GetAt(8) * dPhi9 + harmonics->GetAt(9) * dPhi10); + weight = dW1 * dW2 * dW3 * dW4 * dW5 * dW6 * dW7 * dW8 * dW9 * dW10; + profile->Fill(0.5, value, weight); + continue; + } + for (int i11 = 0; i11 < nParticles; i11++) { + if (i11 == i1 || i11 == i2 || i11 == i3 || i11 == i4 || i11 == i5 || i11 == i6 || i11 == i7 || i11 == i8 || i11 == i9 || i11 == i10) { + continue; + } + double dPhi11 = nl.ftaNestedLoopsKine[qvKine][bin][0]->GetAt(i11); + double dW11 = nl.ftaNestedLoopsKine[qvKine][bin][1]->GetAt(i11); + if (11 == order) { + value = std::cos(harmonics->GetAt(0) * dPhi1 + harmonics->GetAt(1) * dPhi2 + harmonics->GetAt(2) * dPhi3 + harmonics->GetAt(3) * dPhi4 + harmonics->GetAt(4) * dPhi5 + harmonics->GetAt(5) * dPhi6 + harmonics->GetAt(6) * dPhi7 + harmonics->GetAt(7) * dPhi8 + harmonics->GetAt(8) * dPhi9 + harmonics->GetAt(9) * dPhi10 + harmonics->GetAt(10) * dPhi11); + weight = dW1 * dW2 * dW3 * dW4 * dW5 * dW6 * dW7 * dW8 * dW9 * dW10 * dW11; + profile->Fill(0.5, value, weight); + continue; + } + for (int i12 = 0; i12 < nParticles; i12++) { + if (i12 == i1 || i12 == i2 || i12 == i3 || i12 == i4 || i12 == i5 || i12 == i6 || i12 == i7 || i12 == i8 || i12 == i9 || i12 == i10 || i12 == i11) { + continue; + } + double dPhi12 = nl.ftaNestedLoopsKine[qvKine][bin][0]->GetAt(i12); + double dW12 = nl.ftaNestedLoopsKine[qvKine][bin][1]->GetAt(i12); + if (12 == order) { + value = std::cos(harmonics->GetAt(0) * dPhi1 + harmonics->GetAt(1) * dPhi2 + harmonics->GetAt(2) * dPhi3 + harmonics->GetAt(3) * dPhi4 + harmonics->GetAt(4) * dPhi5 + harmonics->GetAt(5) * dPhi6 + harmonics->GetAt(6) * dPhi7 + harmonics->GetAt(7) * dPhi8 + harmonics->GetAt(8) * dPhi9 + harmonics->GetAt(9) * dPhi10 + harmonics->GetAt(10) * dPhi11 + harmonics->GetAt(11) * dPhi12); + weight = dW1 * dW2 * dW3 * dW4 * dW5 * dW6 * dW7 * dW8 * dW9 * dW10 * dW11 * dW12; + profile->Fill(0.5, value, weight); + continue; + } + + // ... it's easy to continue the above pattern here + + } // for(int i12=0; i12GetBinContent(1); + delete profile; + profile = NULL; + if (tc.fVerbose) { + ExitFunction(__FUNCTION__); + } + return finalValue; + +} // double CalculateKineCustomNestedLoops(TArrayI *harmonics, eAsFunctionOf AFO_variable, int bin) + +//============================================================ + +double CalculateKineCustomNestedLoops(TArrayI* harmonics, eqvectorKine kineVarChoice, int bin) +{ + // For the specified harmonics, kine variable, and bin, get the correlation from nested loops. + // Order of correlator is the number of harmonics, i.e. the number of elements in an array. + + // a) Determine the order of correlator; + // b) Custom nested loop; + // c) Return value. + + if (tc.fVerbose) { + StartFunction(__FUNCTION__); } - if (0 > bin || res.fResultsPro[AFO_variable]->GetNbinsX() < bin) { // this 'bin' starts from 0, i.e. this is an array bin - // either underflow or overflow is hit, meaning that histogram is booked in narrower range than cuts - LOGF(fatal, "\033[1;31m%s at line %d => AFO_variable = %d, bin = %d\033[0m", __FUNCTION__, __LINE__, static_cast(AFO_variable), bin); + if (!harmonics) { + LOGF(fatal, "\033[1;31m%s at line %d\033[0m", __FUNCTION__, __LINE__); } + // TBI 20250529 add protection for b in underflow or overflow + // Get the number of particles in this kine bin: int nParticles = 0; - for (int i = 0; i < nl.ftaNestedLoopsKine[qvKine][bin][0]->GetSize(); i++) { - if (std::abs(nl.ftaNestedLoopsKine[qvKine][bin][0]->GetAt(i)) > 0.) { + for (int i = 0; i < nl.ftaNestedLoopsKine[kineVarChoice][bin][0]->GetSize(); i++) { + if (std::abs(nl.ftaNestedLoopsKine[kineVarChoice][bin][0]->GetAt(i)) > 0.) { nParticles++; } } - // 'qvKine' is enum eqvectorKine: - if (!res.fResultsPro[AFO_variable]) { - LOGF(fatal, "\033[1;31m%s at line %d : AFO_variable = %d, bin = %d \033[0m", __FUNCTION__, __LINE__, static_cast(AFO_variable), bin); + // It doesn't hurt to do here insanity check on the number of particles, in case I have already calculated it independently when calculating diff. q-vectors: + if (qv.fCalculateqvectorsKineAny && qv.fqvectorEntries[kineVarChoice][bin] > 0) { // TBI 20250602 I think this chained condition is ok, but re-think nevertheless + if (!(nParticles == qv.fqvectorEntries[kineVarChoice][bin])) { + LOGF(fatal, "\033[1;31m%s at line %d : nParticles = %d, qv.fqvectorEntries[kineVarChoice][bin] = %d, kineVarChoices = %d (%s), bin = %d\033[0m", __FUNCTION__, __LINE__, nParticles, qv.fqvectorEntries[kineVarChoice][bin], static_cast(kineVarChoice), StringKineMap(kineVarChoice).Data(), bin); + } } - LOGF(info, " Processing qvKine = %d (vs. %s), nParticles in this kine bin = %d, bin range = [%f,%f) ....", static_cast(qvKine), kineVarName.Data(), nParticles, res.fResultsPro[AFO_variable]->GetBinLowEdge(bin + 1), res.fResultsPro[AFO_variable]->GetBinLowEdge(bin + 2)); - // a) Determine the order of correlator; int order = harmonics->GetSize(); if (0 == order || order > gMaxCorrelator) { @@ -14670,8 +16610,8 @@ double CalculateKineCustomNestedLoops(TArrayI* harmonics, eAsFunctionOf AFO_vari double value = 0.; // cos of current multiplet double weight = 1.; // weight of current multiplet for (int i1 = 0; i1 < nParticles; i1++) { - double dPhi1 = nl.ftaNestedLoopsKine[qvKine][bin][0]->GetAt(i1); - double dW1 = nl.ftaNestedLoopsKine[qvKine][bin][1]->GetAt(i1); + double dPhi1 = nl.ftaNestedLoopsKine[kineVarChoice][bin][0]->GetAt(i1); + double dW1 = nl.ftaNestedLoopsKine[kineVarChoice][bin][1]->GetAt(i1); if (1 == order) { value = std::cos(harmonics->GetAt(0) * dPhi1); weight = dW1; @@ -14682,8 +16622,8 @@ double CalculateKineCustomNestedLoops(TArrayI* harmonics, eAsFunctionOf AFO_vari if (i2 == i1) { continue; } - double dPhi2 = nl.ftaNestedLoopsKine[qvKine][bin][0]->GetAt(i2); - double dW2 = nl.ftaNestedLoopsKine[qvKine][bin][1]->GetAt(i2); + double dPhi2 = nl.ftaNestedLoopsKine[kineVarChoice][bin][0]->GetAt(i2); + double dW2 = nl.ftaNestedLoopsKine[kineVarChoice][bin][1]->GetAt(i2); if (2 == order) { value = std::cos(harmonics->GetAt(0) * dPhi1 + harmonics->GetAt(1) * dPhi2); weight = dW1 * dW2; @@ -14694,8 +16634,8 @@ double CalculateKineCustomNestedLoops(TArrayI* harmonics, eAsFunctionOf AFO_vari if (i3 == i1 || i3 == i2) { continue; } - double dPhi3 = nl.ftaNestedLoopsKine[qvKine][bin][0]->GetAt(i3); - double dW3 = nl.ftaNestedLoopsKine[qvKine][bin][1]->GetAt(i3); + double dPhi3 = nl.ftaNestedLoopsKine[kineVarChoice][bin][0]->GetAt(i3); + double dW3 = nl.ftaNestedLoopsKine[kineVarChoice][bin][1]->GetAt(i3); if (3 == order) { value = std::cos(harmonics->GetAt(0) * dPhi1 + harmonics->GetAt(1) * dPhi2 + harmonics->GetAt(2) * dPhi3); weight = dW1 * dW2 * dW3; @@ -14706,8 +16646,8 @@ double CalculateKineCustomNestedLoops(TArrayI* harmonics, eAsFunctionOf AFO_vari if (i4 == i1 || i4 == i2 || i4 == i3) { continue; } - double dPhi4 = nl.ftaNestedLoopsKine[qvKine][bin][0]->GetAt(i4); - double dW4 = nl.ftaNestedLoopsKine[qvKine][bin][1]->GetAt(i4); + double dPhi4 = nl.ftaNestedLoopsKine[kineVarChoice][bin][0]->GetAt(i4); + double dW4 = nl.ftaNestedLoopsKine[kineVarChoice][bin][1]->GetAt(i4); if (4 == order) { value = std::cos(harmonics->GetAt(0) * dPhi1 + harmonics->GetAt(1) * dPhi2 + harmonics->GetAt(2) * dPhi3 + harmonics->GetAt(3) * dPhi4); weight = dW1 * dW2 * dW3 * dW4; @@ -14718,8 +16658,8 @@ double CalculateKineCustomNestedLoops(TArrayI* harmonics, eAsFunctionOf AFO_vari if (i5 == i1 || i5 == i2 || i5 == i3 || i5 == i4) { continue; } - double dPhi5 = nl.ftaNestedLoopsKine[qvKine][bin][0]->GetAt(i5); - double dW5 = nl.ftaNestedLoopsKine[qvKine][bin][1]->GetAt(i5); + double dPhi5 = nl.ftaNestedLoopsKine[kineVarChoice][bin][0]->GetAt(i5); + double dW5 = nl.ftaNestedLoopsKine[kineVarChoice][bin][1]->GetAt(i5); if (5 == order) { value = std::cos(harmonics->GetAt(0) * dPhi1 + harmonics->GetAt(1) * dPhi2 + harmonics->GetAt(2) * dPhi3 + harmonics->GetAt(3) * dPhi4 + harmonics->GetAt(4) * dPhi5); weight = dW1 * dW2 * dW3 * dW4 * dW5; @@ -14730,8 +16670,8 @@ double CalculateKineCustomNestedLoops(TArrayI* harmonics, eAsFunctionOf AFO_vari if (i6 == i1 || i6 == i2 || i6 == i3 || i6 == i4 || i6 == i5) { continue; } - double dPhi6 = nl.ftaNestedLoopsKine[qvKine][bin][0]->GetAt(i6); - double dW6 = nl.ftaNestedLoopsKine[qvKine][bin][1]->GetAt(i6); + double dPhi6 = nl.ftaNestedLoopsKine[kineVarChoice][bin][0]->GetAt(i6); + double dW6 = nl.ftaNestedLoopsKine[kineVarChoice][bin][1]->GetAt(i6); if (6 == order) { value = std::cos(harmonics->GetAt(0) * dPhi1 + harmonics->GetAt(1) * dPhi2 + harmonics->GetAt(2) * dPhi3 + harmonics->GetAt(3) * dPhi4 + harmonics->GetAt(4) * dPhi5 + harmonics->GetAt(5) * dPhi6); weight = dW1 * dW2 * dW3 * dW4 * dW5 * dW6; @@ -14742,8 +16682,8 @@ double CalculateKineCustomNestedLoops(TArrayI* harmonics, eAsFunctionOf AFO_vari if (i7 == i1 || i7 == i2 || i7 == i3 || i7 == i4 || i7 == i5 || i7 == i6) { continue; } - double dPhi7 = nl.ftaNestedLoopsKine[qvKine][bin][0]->GetAt(i7); - double dW7 = nl.ftaNestedLoopsKine[qvKine][bin][1]->GetAt(i7); + double dPhi7 = nl.ftaNestedLoopsKine[kineVarChoice][bin][0]->GetAt(i7); + double dW7 = nl.ftaNestedLoopsKine[kineVarChoice][bin][1]->GetAt(i7); if (7 == order) { value = std::cos(harmonics->GetAt(0) * dPhi1 + harmonics->GetAt(1) * dPhi2 + harmonics->GetAt(2) * dPhi3 + harmonics->GetAt(3) * dPhi4 + harmonics->GetAt(4) * dPhi5 + harmonics->GetAt(5) * dPhi6 + harmonics->GetAt(6) * dPhi7); weight = dW1 * dW2 * dW3 * dW4 * dW5 * dW6 * dW7; @@ -14754,8 +16694,8 @@ double CalculateKineCustomNestedLoops(TArrayI* harmonics, eAsFunctionOf AFO_vari if (i8 == i1 || i8 == i2 || i8 == i3 || i8 == i4 || i8 == i5 || i8 == i6 || i8 == i7) { continue; } - double dPhi8 = nl.ftaNestedLoopsKine[qvKine][bin][0]->GetAt(i8); - double dW8 = nl.ftaNestedLoopsKine[qvKine][bin][1]->GetAt(i8); + double dPhi8 = nl.ftaNestedLoopsKine[kineVarChoice][bin][0]->GetAt(i8); + double dW8 = nl.ftaNestedLoopsKine[kineVarChoice][bin][1]->GetAt(i8); if (8 == order) { value = std::cos(harmonics->GetAt(0) * dPhi1 + harmonics->GetAt(1) * dPhi2 + harmonics->GetAt(2) * dPhi3 + harmonics->GetAt(3) * dPhi4 + harmonics->GetAt(4) * dPhi5 + harmonics->GetAt(5) * dPhi6 + harmonics->GetAt(6) * dPhi7 + harmonics->GetAt(7) * dPhi8); weight = dW1 * dW2 * dW3 * dW4 * dW5 * dW6 * dW7 * dW8; @@ -14766,8 +16706,8 @@ double CalculateKineCustomNestedLoops(TArrayI* harmonics, eAsFunctionOf AFO_vari if (i9 == i1 || i9 == i2 || i9 == i3 || i9 == i4 || i9 == i5 || i9 == i6 || i9 == i7 || i9 == i8) { continue; } - double dPhi9 = nl.ftaNestedLoopsKine[qvKine][bin][0]->GetAt(i9); - double dW9 = nl.ftaNestedLoopsKine[qvKine][bin][1]->GetAt(i9); + double dPhi9 = nl.ftaNestedLoopsKine[kineVarChoice][bin][0]->GetAt(i9); + double dW9 = nl.ftaNestedLoopsKine[kineVarChoice][bin][1]->GetAt(i9); if (9 == order) { value = std::cos(harmonics->GetAt(0) * dPhi1 + harmonics->GetAt(1) * dPhi2 + harmonics->GetAt(2) * dPhi3 + harmonics->GetAt(3) * dPhi4 + harmonics->GetAt(4) * dPhi5 + harmonics->GetAt(5) * dPhi6 + harmonics->GetAt(6) * dPhi7 + harmonics->GetAt(7) * dPhi8 + harmonics->GetAt(8) * dPhi9); weight = dW1 * dW2 * dW3 * dW4 * dW5 * dW6 * dW7 * dW8 * dW9; @@ -14778,8 +16718,8 @@ double CalculateKineCustomNestedLoops(TArrayI* harmonics, eAsFunctionOf AFO_vari if (i10 == i1 || i10 == i2 || i10 == i3 || i10 == i4 || i10 == i5 || i10 == i6 || i10 == i7 || i10 == i8 || i10 == i9) { continue; } - double dPhi10 = nl.ftaNestedLoopsKine[qvKine][bin][0]->GetAt(i10); - double dW10 = nl.ftaNestedLoopsKine[qvKine][bin][1]->GetAt(i10); + double dPhi10 = nl.ftaNestedLoopsKine[kineVarChoice][bin][0]->GetAt(i10); + double dW10 = nl.ftaNestedLoopsKine[kineVarChoice][bin][1]->GetAt(i10); if (10 == order) { value = std::cos(harmonics->GetAt(0) * dPhi1 + harmonics->GetAt(1) * dPhi2 + harmonics->GetAt(2) * dPhi3 + harmonics->GetAt(3) * dPhi4 + harmonics->GetAt(4) * dPhi5 + harmonics->GetAt(5) * dPhi6 + harmonics->GetAt(6) * dPhi7 + harmonics->GetAt(7) * dPhi8 + harmonics->GetAt(8) * dPhi9 + harmonics->GetAt(9) * dPhi10); weight = dW1 * dW2 * dW3 * dW4 * dW5 * dW6 * dW7 * dW8 * dW9 * dW10; @@ -14790,8 +16730,8 @@ double CalculateKineCustomNestedLoops(TArrayI* harmonics, eAsFunctionOf AFO_vari if (i11 == i1 || i11 == i2 || i11 == i3 || i11 == i4 || i11 == i5 || i11 == i6 || i11 == i7 || i11 == i8 || i11 == i9 || i11 == i10) { continue; } - double dPhi11 = nl.ftaNestedLoopsKine[qvKine][bin][0]->GetAt(i11); - double dW11 = nl.ftaNestedLoopsKine[qvKine][bin][1]->GetAt(i11); + double dPhi11 = nl.ftaNestedLoopsKine[kineVarChoice][bin][0]->GetAt(i11); + double dW11 = nl.ftaNestedLoopsKine[kineVarChoice][bin][1]->GetAt(i11); if (11 == order) { value = std::cos(harmonics->GetAt(0) * dPhi1 + harmonics->GetAt(1) * dPhi2 + harmonics->GetAt(2) * dPhi3 + harmonics->GetAt(3) * dPhi4 + harmonics->GetAt(4) * dPhi5 + harmonics->GetAt(5) * dPhi6 + harmonics->GetAt(6) * dPhi7 + harmonics->GetAt(7) * dPhi8 + harmonics->GetAt(8) * dPhi9 + harmonics->GetAt(9) * dPhi10 + harmonics->GetAt(10) * dPhi11); weight = dW1 * dW2 * dW3 * dW4 * dW5 * dW6 * dW7 * dW8 * dW9 * dW10 * dW11; @@ -14802,8 +16742,8 @@ double CalculateKineCustomNestedLoops(TArrayI* harmonics, eAsFunctionOf AFO_vari if (i12 == i1 || i12 == i2 || i12 == i3 || i12 == i4 || i12 == i5 || i12 == i6 || i12 == i7 || i12 == i8 || i12 == i9 || i12 == i10 || i12 == i11) { continue; } - double dPhi12 = nl.ftaNestedLoopsKine[qvKine][bin][0]->GetAt(i12); - double dW12 = nl.ftaNestedLoopsKine[qvKine][bin][1]->GetAt(i12); + double dPhi12 = nl.ftaNestedLoopsKine[kineVarChoice][bin][0]->GetAt(i12); + double dW12 = nl.ftaNestedLoopsKine[kineVarChoice][bin][1]->GetAt(i12); if (12 == order) { value = std::cos(harmonics->GetAt(0) * dPhi1 + harmonics->GetAt(1) * dPhi2 + harmonics->GetAt(2) * dPhi3 + harmonics->GetAt(3) * dPhi4 + harmonics->GetAt(4) * dPhi5 + harmonics->GetAt(5) * dPhi6 + harmonics->GetAt(6) * dPhi7 + harmonics->GetAt(7) * dPhi8 + harmonics->GetAt(8) * dPhi9 + harmonics->GetAt(9) * dPhi10 + harmonics->GetAt(10) * dPhi11 + harmonics->GetAt(11) * dPhi12); weight = dW1 * dW2 * dW3 * dW4 * dW5 * dW6 * dW7 * dW8 * dW9 * dW10 * dW11 * dW12; @@ -15556,226 +17496,520 @@ void PrintCutCounterContent() } LOGF(info, "bin = %d => %s : %d", bin, ec.fEventCutCounterHist[rs][cc]->GetXaxis()->GetBinLabel(bin), static_cast(ec.fEventCutCounterHist[rs][cc]->GetBinContent(bin))); } - } // for (int cc = 0; cc < eCutCounter_N; cc++) // enum eCutCounter - } // for (int rs = 0; rs < 2; rs++) // reco/sim + } // for (int cc = 0; cc < eCutCounter_N; cc++) // enum eCutCounter + } // for (int rs = 0; rs < 2; rs++) // reco/sim + + if (tc.fVerbose) { + ExitFunction(__FUNCTION__); + } + +} // void PrintCutCounterContent() + +//============================================================ + +void Trace(const char* functionName, int lineNumber) +{ + // A simple utility wrapper. Use only during debugging, sprinkle calls to this function here and there, as follows + // Trace(__FUNCTION__, __LINE__); + + LOGF(info, "\033[1;32m%s .... line %d\033[0m", functionName, lineNumber); + +} // void Trace(const char* functionName, int lineNumber) + +//============================================================ + +void Exit() +{ + // A simple utility wrapper. Used only during debugging. + // Use directly as: Exit(); + // Line number, function name, formatting, etc, are determinad automatically. + + LOGF(info, "\n\n\n\n\n\n\n\n\n\n"); + exit(1); + +} // void Exit() + +//============================================================ + +void StartFunction(const char* functionName) +{ + // A simple utility wrapper, used when tc.fVerbose = true. It merely ensures uniform formatting of notification when the function starts. + + LOGF(info, "\033[1;32mStart %s\033[0m", functionName); // prints in green + +} // void StartFunction(const char* functionName) + +//============================================================ + +void ExitFunction(const char* functionName) +{ + // A simple utility wrapper, used when tc.fVerbose = true. It merely ensures uniform formatting of notification when the function exits. + + LOGF(info, "\033[1;32mExit %s\033[0m", functionName); // prints in green + +} // void ExitFunction(const char* functionName) + +//============================================================ + +void BailOut(bool finalBailout = false) +{ + // Use only locally - bail out if maximum number of events was reached, and dump all results by that point in a local ROOT file. + // If fSequentialBailout > 0, bail out is performed each fSequentialBailout events, each time in a new local ROOT file. + // For sequential bailout, the naming scheme of ROOT files is AnalysisResultsBailOut_eh.fEventCounter[eProcessed].root . + // If ROOT file with the same name already exists, BailOut is not performed, since the argument is that + // it's pointless to perform Bailout for same eh.fEventCounter[eProcessed], even if eh.fEventCounter[eTotal] changed. + // Only if finalBailout = true, I will overwrite the existing file with the same name. + + if (tc.fVerbose) { + StartFunction(__FUNCTION__); + } + + // *) Local variables: TBI 20240130 shall I promote 'em to data members + add support for configurables? + TString sBailOutFile = "AnalysisResultsBailOut.root"; + TString sDirectoryFile = "multiparticle-correlations-a-b"; + + // *) For sequential bailout, I need to adapt the ROOT file name each time this function is called: + if (tc.fSequentialBailout > 0) { + sBailOutFile.ReplaceAll(".root", Form("_%d.root", eh.fEventCounter[eProcessed])); // replaces in-place + // basically, at 1st call "AnalysisResultsBailOut.root" => "AnalysisResultsBailOut_1*eh.fEventCounter[eProcessed].root", + // at 2nd call "AnalysisResultsBailOut.root" => "AnalysisResultsBailOut_2*eh.fEventCounter[eProcessed].root", etc. + if (!finalBailout && !gSystem->AccessPathName(sBailOutFile.Data(), kFileExists)) { // only for finalBailout = true, I will overwrite the existing file with the same name. + LOGF(info, "\033[1;33m\nsBailOutFile = %s already exits, that means that eh.fEventCounter[eProcessed] is the same as in the previous call of BailOut.\nJust skipping and waiting more events to pass selection criteria... \033[0m", sBailOutFile.Data()); + return; + } + } + + // *) Info message: + if (eh.fEventHistograms[eNumberOfEvents][eRec][eAfter]) { + LOGF(info, "\033[1;32m=> Per request, bailing out after %d selected events in the local file %s .\n\033[0m", static_cast(eh.fEventHistograms[eNumberOfEvents][eRec][eAfter]->GetBinContent(1)), sBailOutFile.Data()); + } + + // *) Okay, let's bail out intentionally: + TFile* f = new TFile(sBailOutFile.Data(), "recreate"); + TDirectoryFile* dirFile = new TDirectoryFile(sDirectoryFile.Data(), sDirectoryFile.Data()); + // TBI 20240130 I cannot add here fBaseList directly, since that one is declared as OutputObj + // Therefore, adding one-by-one nested TList's I want to bail out. + // Keep in sync with BookAndNestAllLists(). + TList* bailOutList = new TList(); // this is sort of 'fake' fBaseList + bailOutList->SetOwner(false); // yes, beacause for sequential bailout, with SetOwner(true) the code is crashing after 1st sequential bailout is done + bailOutList->SetName(sBaseListName.Data()); + bailOutList->Add(fBasePro); // yes, this one needs a special treatment + bailOutList->Add(qa.fQAList); + bailOutList->Add(ec.fEventCutsList); + bailOutList->Add(eh.fEventHistogramsList); + bailOutList->Add(pc.fParticleCutsList); + bailOutList->Add(ph.fParticleHistogramsList); + bailOutList->Add(qv.fQvectorList); + bailOutList->Add(mupa.fCorrelationsList); + bailOutList->Add(pw.fWeightsList); + bailOutList->Add(cw.fCentralityWeightsList); + bailOutList->Add(nl.fNestedLoopsList); + bailOutList->Add(nua.fNUAList); + bailOutList->Add(iv.fInternalValidationList); + bailOutList->Add(t0.fTest0List); + bailOutList->Add(es.fEtaSeparationsList); + bailOutList->Add(res.fResultsList); + + // *) Add list with nested list to TDirectoryFile: + dirFile->Add(bailOutList, true); + dirFile->Write(dirFile->GetName(), TObject::kSingleKey + TObject::kOverwrite); + + delete dirFile; + dirFile = NULL; + f->Close(); + + if (tc.fVerbose && !(tc.fSequentialBailout > 0)) { // then it will be called only once, for the only and permanent bailout + ExitFunction(__FUNCTION__); + } + + // *) Hasta la vista: + if (finalBailout) { + LOGF(fatal, "\033[1;31mHasta la vista - bailed out permanently in function %s at line %d\n The output file is: %s\n\n\033[0m", __FUNCTION__, __LINE__, sBailOutFile.Data()); + } else { + LOGF(info, "\033[1;32mBailed out sequentially in function %s at line %d\n The output file is: %s\n\n\033[0m", __FUNCTION__, __LINE__, sBailOutFile.Data()); + if (tc.fVerbose) { + ExitFunction(__FUNCTION__); + } + } + +} // void BailOut(bool finalBailout = false) + +//============================================================ + +void FillQvector(const double& dPhi, const double& dPt, const double& dEta) +{ + // Fill integrated Q-vector. + // Example usage: this->FillQvector(dPhi, dPt, dEta); + + // TBI 20240430 I could optimize further, and have a bare version of this function when weights are NOT used. + // But since usage of weights amounts to checking a few simple booleans here, I do not anticipate any big gain in efficiency... + + if (tc.fVerboseForEachParticle) { + StartFunction(__FUNCTION__); + LOGF(info, "\033[1;32m dPhi = %f\033[0m", dPhi); + LOGF(info, "\033[1;32m dPt = %f\033[0m", dPt); + LOGF(info, "\033[1;32m dEta = %f\033[0m", dEta); + } + + // Particle weights: + double wPhi = 1.; // integrated phi weight + double wPt = 1.; // integrated pt weight + double wEta = 1.; // integrated eta weight + double wToPowerP = 1.; // weight raised to power p + + if (pw.fUseWeights[wPHI]) { + wPhi = Weight(dPhi, wPHI); + if (!(wPhi > 0.)) { + LOGF(error, "\033[1;33m%s wPhi is not positive\033[0m", __FUNCTION__); + LOGF(fatal, "dPhi = %f\nwPhi = %f", dPhi, wPhi); + } + } // if(pw.fUseWeights[wPHI]) + + if (pw.fUseWeights[wPT]) { + wPt = Weight(dPt, wPT); // corresponding pt weight + if (!(wPt > 0.)) { + LOGF(error, "\033[1;33m%s wPt is not positive\033[0m", __FUNCTION__); + LOGF(fatal, "dPt = %f\nwPt = %f", dPt, wPt); + } + } // if(pw.fUseWeights[wPT]) + + if (pw.fUseWeights[wETA]) { + wEta = Weight(dEta, wETA); // corresponding eta weight + if (!(wEta > 0.)) { + LOGF(error, "\033[1;33m%s wEta is not positive\033[0m", __FUNCTION__); + LOGF(fatal, "dEta = %f\nwEta = %f", dEta, wEta); + } + } // if(pw.fUseWeights[wETA]) + + if (qv.fCalculateQvectors) { + for (int h = 0; h < gMaxHarmonic * gMaxCorrelator + 1; h++) { + for (int wp = 0; wp < gMaxCorrelator + 1; wp++) { // weight power + if (pw.fUseWeights[wPHI] || pw.fUseWeights[wPT] || pw.fUseWeights[wETA]) { + wToPowerP = std::pow(wPhi * wPt * wEta, wp); + qv.fQvector[h][wp] += TComplex(wToPowerP * std::cos(h * dPhi), wToPowerP * std::sin(h * dPhi)); // Q-vector with weights + } else { + qv.fQvector[h][wp] += TComplex(std::cos(h * dPhi), std::sin(h * dPhi)); // bare Q-vector without weights + } + } // for(int wp=0;wp 0.) { + for (int e = 0; e < gMaxNumberEtaSeparations; e++) { + if (dEta > es.fEtaSeparationsValues[e] / 2.) { // yes, if eta separation is 0.2, then separation interval runs from -0.1 to 0.1 + qv.fMab[1][e] += wPhi * wPt * wEta; + for (int h = 0; h < gMaxHarmonic; h++) { + { + if (es.fEtaSeparationsSkipHarmonics[h]) { + continue; + } + qv.fQabVector[1][h][e] += TComplex(wPhi * wPt * wEta * std::cos((h + 1) * dPhi), wPhi * wPt * wEta * std::sin((h + 1) * dPhi)); + } + } // for (int h = 0; h < gMaxHarmonic; h++) { + } // for (int e = 0; e < gMaxNumberEtaSeparations; e++) { // eta separation + } + } + } // if(es.fCalculateEtaSeparations) { - if (tc.fVerbose) { + if (tc.fVerboseForEachParticle) { ExitFunction(__FUNCTION__); } -} // void PrintCutCounterContent() +} // void FillQvector(const double& dPhi, const double& dPt, const double& dEta) //============================================================ -void Trace(const char* functionName, int lineNumber) +void FillQvectorFromSparse(const double& dPhi, const double& dPt, const double& dEta, const double& dCharge) { - // A simple utility wrapper. Use only during debugging, sprinkle calls to this function here and there, as follows - // Trace(__FUNCTION__, __LINE__); + // Fill integrated Q-vector using sparse histograms. - LOGF(info, "\033[1;32m%s .... line %d\033[0m", functionName, lineNumber); + // Remark: I pass by reference particle quantities, while event quantities (centrality, vertex z, ...) I fetch from data members (or from global variables in a macro). -} // void Trace(const char* functionName, int lineNumber) + // To do: + // 20250224 do I need to switch to this function also in InternalValidation()? I still use simple FillQvector() there. + // That would really make sense only after I add support for usage of particle weights in InternalValidation() -//============================================================ + if (tc.fVerboseForEachParticle) { + StartFunction(__FUNCTION__); + LOGF(info, "\033[1;32m dPhi = %f\033[0m", dPhi); + LOGF(info, "\033[1;32m dPt = %f\033[0m", dPt); + LOGF(info, "\033[1;32m dEta = %f\033[0m", dEta); + LOGF(info, "\033[1;32m dCharge = %f\033[0m", dCharge); + } -void Exit() -{ - // A simple utility wrapper. Used only during debugging. - // Use directly as: Exit(); - // Line number, function name, formatting, etc, are determinad automatically. + // Particle weights from sparse histograms: + double wPhi = 1.; // differential multidimensional phi weight, its dimensions are defined via enum eDiffPhiWeights + double wPt = 1.; // differential multidimensional pt weight, its dimensions are defined via enum eDiffPtWeights + double wEta = 1.; // differential multidimensional eta weight, its dimensions are defined via enum eDiffEtaWeights + double wToPowerP = 1.; // weight raised to power p - LOGF(info, "\n\n\n\n\n\n\n\n\n\n"); - exit(1); + // *) Multidimensional phi weights: + if (pw.fUseDiffPhiWeights[wPhiPhiAxis]) { // yes, 0th axis serves as a comon boolean for this category + wPhi = WeightFromSparse(dPhi, dPt, dEta, dCharge, eDWPhi); + // last argument is enum eDiffWeightCategory. Event quantities, e.g. centraliy and vz, I do not need to pass, because + // for them I have ebye data members + if (!(wPhi > 0.)) { + LOGF(error, "\033[1;33m%s wPhi is not positive\033[0m", __FUNCTION__); + LOGF(error, "dPhi = %f", dPhi); + if (pw.fUseDiffPhiWeights[wPhiPtAxis]) { + LOGF(fatal, "dPt = %f", dPt); + } + if (pw.fUseDiffPhiWeights[wPhiEtaAxis]) { + LOGF(fatal, "dEta = %f", dEta); + } + if (pw.fUseDiffPhiWeights[wPhiChargeAxis]) { + LOGF(fatal, "dCharge = %f", dCharge); + } + if (pw.fUseDiffPhiWeights[wPhiCentralityAxis]) { + LOGF(fatal, "ebye.Centrality = %f", ebye.fCentrality); + } + if (pw.fUseDiffPhiWeights[wPhiVertexZAxis]) { + LOGF(fatal, "ebye.Vz = %f", ebye.fVz); + } + LOGF(fatal, "Multidimensional weight for enabled dimensions is wPhi = %f", wPhi); + } + } // if(pw.fUseDiffPhiWeights[wPhiPhiAxis]) -} // void Exit() + // *) Multidimensional pt weights: + if (pw.fUseDiffPtWeights[wPtPtAxis]) { // yes, 0th axis serves as a comon boolean for this category + wPt = WeightFromSparse(dPhi, dPt, dEta, dCharge, eDWPt); // TBI 20250224 not sure if this is the right/best approach + // last argument is enum eDiffWeightCategory. Event quantities, e.g. centraliy and vz, I do not need to pass, because + // for them I have ebye data members + if (!(wPt > 0.)) { + LOGF(error, "\033[1;33m%s wPt is not positive\033[0m", __FUNCTION__); + LOGF(error, "dPt = %f", dPt); + if (pw.fUseDiffPtWeights[wPtPtAxis]) { + LOGF(fatal, "dPt = %f", dPt); + } + LOGF(fatal, "Multidimensional weight for enabled dimensions is wPt = %f", wPt); + } + } // if(pw.fUseDiffPtWeights[wPtPtAxis]) -//============================================================ + // *) Multidimensional eta weights: + if (pw.fUseDiffEtaWeights[wEtaEtaAxis]) { // yes, 0th axis serves as a comon boolean for this category + wEta = WeightFromSparse(dPhi, dPt, dEta, dCharge, eDWEta); // TBI 20250224 not sure if this is the right/best approach + // last argument is enum eDiffWeightCategory. Event quantities, e.g. centraliy and vz, I do not need to pass, because + // for them I have ebye data members + if (!(wEta > 0.)) { + LOGF(error, "\033[1;33m%s wEta is not positive\033[0m", __FUNCTION__); + LOGF(error, "dEta = %f", dEta); + if (pw.fUseDiffEtaWeights[wEtaEtaAxis]) { + LOGF(fatal, "dEta = %f", dEta); + } + LOGF(fatal, "Multidimensional weight for enabled dimensions is wEta = %f", wEta); + } + } // if(pw.fUseDiffEtaWeights[wEtaEtaAxis]) -void StartFunction(const char* functionName) -{ - // A simple utility wrapper, used when tc.fVerbose = true. It merely ensures uniform formatting of notification when the function starts. + if (qv.fCalculateQvectors) { + for (int h = 0; h < gMaxHarmonic * gMaxCorrelator + 1; h++) { + for (int wp = 0; wp < gMaxCorrelator + 1; wp++) { // weight power + if (pw.fUseDiffPhiWeights[wPhiPhiAxis] || pw.fUseDiffPtWeights[wPtPtAxis] || pw.fUseDiffEtaWeights[wEtaEtaAxis]) { + wToPowerP = std::pow(wPhi * wPt * wEta, wp); + qv.fQvector[h][wp] += TComplex(wToPowerP * std::cos(h * dPhi), wToPowerP * std::sin(h * dPhi)); // Q-vector with weights + } else { + qv.fQvector[h][wp] += TComplex(std::cos(h * dPhi), std::sin(h * dPhi)); // bare Q-vector without weights + } + } // for(int wp=0;wp 0.) { + for (int e = 0; e < gMaxNumberEtaSeparations; e++) { + if (dEta > es.fEtaSeparationsValues[e] / 2.) { // yes, if eta separation is 0.2, then separation interval runs from -0.1 to 0.1 + qv.fMab[1][e] += wPhi * wPt * wEta; + for (int h = 0; h < gMaxHarmonic; h++) { + { + if (es.fEtaSeparationsSkipHarmonics[h]) { + continue; + } + qv.fQabVector[1][h][e] += TComplex(wPhi * wPt * wEta * std::cos((h + 1) * dPhi), wPhi * wPt * wEta * std::sin((h + 1) * dPhi)); + } + } // for (int h = 0; h < gMaxHarmonic; h++) { + } // for (int e = 0; e < gMaxNumberEtaSeparations; e++) { // eta separation + } + } + } // if(es.fCalculateEtaSeparations) { -} // void StartFunction(const char* functionName) + if (tc.fVerboseForEachParticle) { + ExitFunction(__FUNCTION__); + } + +} // void FillQvectorFromSparse(const double& dPhi, const double& dPt, const double& dEta, const double& dCharge) //============================================================ -void ExitFunction(const char* functionName) +void Fillqvector(const double& dPhi, const double& kineVarValue, eqvectorKine kineVarChoice, const double& dEta = 0.) { - // A simple utility wrapper, used when tc.fVerbose = true. It merely ensures uniform formatting of notification when the function exits. - - LOGF(info, "\033[1;32mExit %s\033[0m", functionName); // prints in green + // !!! OBSOLETE FUNCTION (as of 20250527) !!! -} // void ExitFunction(const char* functionName) + LOGF(info, "\033[1;33m%s at line %d: !!!! WARNING !!!! As of 20250527, this is an obsolete function, use FillqvectorNdim(...) and FillqvectorNdimFromSparse(...) instead !!!! WARNING !!!! \033[0m", __FUNCTION__, __LINE__); -//============================================================ + // Fill differential q-vector, in generic kinematic variable. Here "kine" originally meant vs. pt or vs. eta, now it's general. + // Example usage #1: this->Fillqvector(dPhi, dPt, PTq); // differential q-vectors without using eta separations + // Example usage #2: this->Fillqvector(dPhi, dPt, PTq, dEta); // differential q-vectors with using eta separations (I need dEta of particle to decide whether particle is added to qa or qb) -void BailOut(bool finalBailout = false) -{ - // Use only locally - bail out if maximum number of events was reached, and dump all results by that point in a local ROOT file. - // If fSequentialBailout > 0, bail out is performed each fSequentialBailout events, each time in a new local ROOT file. - // For sequential bailout, the naming scheme of ROOT files is AnalysisResultsBailOut_eh.fEventCounter[eProcessed].root . - // If ROOT file with the same name already exists, BailOut is not performed, since the argument is that - // it's pointless to perform Bailout for same eh.fEventCounter[eProcessed], even if eh.fEventCounter[eTotal] changed. - // Only if finalBailout = true, I will overwrite the existing file with the same name. + // Remark: As of 20250527, this function is obsolete, and it's superseeded by more general functions: + // a) void FillqvectorNdim(...) (without particle weights) + // b) void FillqvectorNdimFromSparse(...) (with particle weights) - if (tc.fVerbose) { + if (tc.fVerboseForEachParticle) { StartFunction(__FUNCTION__); } - // *) Local variables: TBI 20240130 shall I promote 'em to data members + add support for configurables? - TString sBailOutFile = "AnalysisResultsBailOut.root"; - TString sDirectoryFile = "multiparticle-correlations-a-b"; - - // *) For sequential bailout, I need to adapt the ROOT file name each time this function is called: - if (tc.fSequentialBailout > 0) { - sBailOutFile.ReplaceAll(".root", Form("_%d.root", eh.fEventCounter[eProcessed])); // replaces in-place - // basically, at 1st call "AnalysisResultsBailOut.root" => "AnalysisResultsBailOut_1*eh.fEventCounter[eProcessed].root", - // at 2nd call "AnalysisResultsBailOut.root" => "AnalysisResultsBailOut_2*eh.fEventCounter[eProcessed].root", etc. - if (!finalBailout && !gSystem->AccessPathName(sBailOutFile.Data(), kFileExists)) { // only for finalBailout = true, I will overwrite the existing file with the same name. - LOGF(info, "\033[1;33m\nsBailOutFile = %s already exits, that means that eh.fEventCounter[eProcessed] is the same as in the previous call of BailOut.\nJust skipping and waiting more events to pass selection criteria... \033[0m", sBailOutFile.Data()); - return; + // *) Mapping between enum's "eqvectorKine" on one side, and "eAsFunctionOf", "eWeights" and "eDiffWeights" on the other: + // TBI 20240212 I could promote this also to a member function, if I need it elsewhere. Or I could use TExMap? + eAsFunctionOf AFO_var = eAsFunctionOf_N; // this local variable determines the enum "eAsFunctionOf" which corresponds to enum "eqvectorKine" + eWeights AFO_weight = eWeights_N; // this local variable determines the enum "eWeights" which corresponds to enum "eqvectorKine" + eDiffWeights AFO_diffWeight = eDiffWeights_N; // this local variable determines the enum "eDiffWeights" which corresponds to enum "eqvectorKine" + switch (kineVarChoice) { + case PTq: { + AFO_var = AFO_PT; + AFO_weight = wPT; + AFO_diffWeight = wPHIPT; // TBI 20250215 this is now obsolete, see the comment in enum + break; } - } - - // *) Info message: - if (eh.fEventHistograms[eNumberOfEvents][eRec][eAfter]) { - LOGF(info, "\033[1;32m=> Per request, bailing out after %d selected events in the local file %s .\n\033[0m", static_cast(eh.fEventHistograms[eNumberOfEvents][eRec][eAfter]->GetBinContent(1)), sBailOutFile.Data()); - } - - // *) Okay, let's bail out intentionally: - TFile* f = new TFile(sBailOutFile.Data(), "recreate"); - TDirectoryFile* dirFile = new TDirectoryFile(sDirectoryFile.Data(), sDirectoryFile.Data()); - // TBI 20240130 I cannot add here fBaseList directly, since that one is declared as OutputObj - // Therefore, adding one-by-one nested TList's I want to bail out. - // Keep in sync with BookAndNestAllLists(). - TList* bailOutList = new TList(); // this is sort of 'fake' fBaseList - bailOutList->SetOwner(false); // yes, beacause for sequential bailout, with SetOwner(true) the code is crashing after 1st sequential bailout is done - bailOutList->SetName(sBaseListName.Data()); - bailOutList->Add(fBasePro); // yes, this one needs a special treatment - bailOutList->Add(qa.fQAList); - bailOutList->Add(ec.fEventCutsList); - bailOutList->Add(eh.fEventHistogramsList); - bailOutList->Add(pc.fParticleCutsList); - bailOutList->Add(ph.fParticleHistogramsList); - bailOutList->Add(qv.fQvectorList); - bailOutList->Add(mupa.fCorrelationsList); - bailOutList->Add(pw.fWeightsList); - bailOutList->Add(cw.fCentralityWeightsList); - bailOutList->Add(nl.fNestedLoopsList); - bailOutList->Add(nua.fNUAList); - bailOutList->Add(iv.fInternalValidationList); - bailOutList->Add(t0.fTest0List); - bailOutList->Add(es.fEtaSeparationsList); - bailOutList->Add(res.fResultsList); - - // *) Add list with nested list to TDirectoryFile: - dirFile->Add(bailOutList, true); - dirFile->Write(dirFile->GetName(), TObject::kSingleKey + TObject::kOverwrite); - delete dirFile; - dirFile = NULL; - f->Close(); + case ETAq: { + AFO_var = AFO_ETA; + AFO_weight = wETA; + AFO_diffWeight = wPHIETA; // TBI 20250215 this is now obsolete, see the comment in enum + break; + } + case CHARGEq: { + AFO_var = AFO_CHARGE; + AFO_weight = wCHARGE; + AFO_diffWeight = wPHICHARGE; // TBI 20250215 this is now obsolete, see the comment in enum + break; + } + default: { + LOGF(fatal, "\033[1;31m%s at line %d : this kineVarChoice = %d is not supported yet. \033[0m", __FUNCTION__, __LINE__, static_cast(kineVarChoice)); + break; + } + } // switch(kineVarChoice) - if (tc.fVerbose && !(tc.fSequentialBailout > 0)) { // then it will be called only once, for the only and permanent bailout - ExitFunction(__FUNCTION__); + // *) Insanity checks on above settings: + if (AFO_var == eAsFunctionOf_N) { + LOGF(fatal, "\033[1;31m%s at line %d : AFO_var == eAsFunctionOf_N => add some more entries to the case statement \033[0m", __FUNCTION__, __LINE__); + } + if (AFO_weight == eWeights_N) { + LOGF(fatal, "\033[1;31m%s at line %d : AFO_weight == eWeights_N => add some more entries to the case statement \033[0m", __FUNCTION__, __LINE__); + } + if (AFO_diffWeight == eDiffWeights_N) { + LOGF(fatal, "\033[1;31m%s at line %d : AFO_diffWeight == eDiffWeights_N => add some more entries to the case statement \033[0m", __FUNCTION__, __LINE__); } - // *) Hasta la vista: - if (finalBailout) { - LOGF(fatal, "\033[1;31mHasta la vista - bailed out permanently in function %s at line %d\n The output file is: %s\n\n\033[0m", __FUNCTION__, __LINE__, sBailOutFile.Data()); - } else { - LOGF(info, "\033[1;32mBailed out sequentially in function %s at line %d\n The output file is: %s\n\n\033[0m", __FUNCTION__, __LINE__, sBailOutFile.Data()); - if (tc.fVerbose) { - ExitFunction(__FUNCTION__); + // *) Get the desired bin number: + int bin = -1; + if (res.fResultsPro[AFO_var]) { + bin = res.fResultsPro[AFO_var]->FindBin(kineVarValue); // this 'bin' starts from 1, i.e. this is genuine histogram bin + if (0 >= bin || res.fResultsPro[AFO_var]->GetNbinsX() < bin) { // either underflow or overflow is hit, meaning that histogram is booked in narrower range than cuts + LOGF(fatal, "\033[1;31m%s at line %d : kineVarChoice = %d, bin = %d, kineVarValue = %f \033[0m", __FUNCTION__, __LINE__, static_cast(kineVarChoice), bin, kineVarValue); } } -} // void BailOut(bool finalBailout = false) - -//============================================================ + // *) Get all integrated kinematic weights: + double wToPowerP = 1.; // weight raised to power p + double kineVarWeight = 1.; // e.g. this can be integrated pT or eta weight + if (pw.fUseWeights[AFO_weight]) { + kineVarWeight = Weight(kineVarValue, AFO_weight); // corresponding e.g. pt or eta weight + if (!(kineVarWeight > 0.)) { + LOGF(fatal, "\033[1;31m%s at line %d : kineVarWeight is not positive \033[0m", __FUNCTION__, __LINE__); + // TBI 20240212 or could I just skip this particle? + } + } // if(fUseWeights[AFO_weight]) { -void FillQvector(const double& dPhi, const double& dPt, const double& dEta) -{ - // Fill integrated Q-vector. - // Example usage: this->FillQvector(dPhi, dPt, dEta); + // *) Get all differential phi-weights for this kinematic variable: + // Remark: special treatment is justified for phi-weights, because q-vector is defined in terms of phi-weights. + double diffPhiWeightsForThisKineVar = 1.; + if (pw.fUseDiffWeights[AFO_diffWeight]) { + diffPhiWeightsForThisKineVar = DiffWeight(dPhi, kineVarValue, kineVarChoice); // corresponding differential phi weight as a function of e.g. pt or eta + if (!(diffPhiWeightsForThisKineVar > 0.)) { + LOGF(fatal, "\033[1;31m%s at line %d : diffPhiWeightsForThisKineVar is not positive \033[0m", __FUNCTION__, __LINE__); + // TBI 20240212 or could I just skip this particle? + } + } // if(pw.fUseDiffWeights[AFO_diffWeight]) { - // TBI 20240430 I could optimize further, and have a bare version of this function when weights are NOT used. - // But since usage of weights amounts to checking a few simple booleans here, I do not anticipate any big gain in efficiency... + // *) Finally, fill differential q-vector in that bin: + for (int h = 0; h < gMaxHarmonic * gMaxCorrelator + 1; h++) { + for (int wp = 0; wp < gMaxCorrelator + 1; wp++) { // weight power + if (pw.fUseWeights[AFO_weight] || pw.fUseDiffWeights[AFO_diffWeight]) { + // TBI 20240212 supported at the moment: e.g. q-vector vs pt can be weighted only with diff. phi(pt) and integrated pt weights. + // It cannot be weighted in addition with eta weights, since in any case I anticipate I will do always 1-D analysis, by integrating out all other dependencies + wToPowerP = std::pow(diffPhiWeightsForThisKineVar * kineVarWeight, wp); + qv.fqvector[kineVarChoice][bin - 1][h][wp] += TComplex(wToPowerP * std::cos(h * dPhi), wToPowerP * std::sin(h * dPhi)); // q-vector with weights + } else { + qv.fqvector[kineVarChoice][bin - 1][h][wp] += TComplex(std::cos(h * dPhi), std::sin(h * dPhi)); // bare q-vector without weights + } + } // for(int wp=0;wpAddAt(dPhi, qv.fqvectorEntries[kineVarChoice][bin - 1]); + nl.ftaNestedLoopsKine[kineVarChoice][bin - 1][1]->AddAt(diffPhiWeightsForThisKineVar * kineVarWeight, qv.fqvectorEntries[kineVarChoice][bin - 1]); } - // Particle weights: - double wPhi = 1.; // integrated phi weight - double wPt = 1.; // integrated pt weight - double wEta = 1.; // integrated eta weight - double wToPowerP = 1.; // weight raised to power p - - if (pw.fUseWeights[wPHI]) { - wPhi = Weight(dPhi, wPHI); - if (!(wPhi > 0.)) { - LOGF(error, "\033[1;33m%s wPhi is not positive\033[0m", __FUNCTION__); - LOGF(fatal, "dPhi = %f\nwPhi = %f", dPhi, wPhi); - } - } // if(pw.fUseWeights[wPHI]) + // *) Multiplicity counter in this bin: + qv.fqvectorEntries[kineVarChoice][bin - 1]++; // count number of particles in this pt bin in this event - if (pw.fUseWeights[wPT]) { - wPt = Weight(dPt, wPT); // corresponding pt weight - if (!(wPt > 0.)) { - LOGF(error, "\033[1;33m%s wPt is not positive\033[0m", __FUNCTION__); - LOGF(fatal, "dPt = %f\nwPt = %f", dPt, wPt); - } - } // if(pw.fUseWeights[wPT]) + // *) Usage of eta separations in differential correlations: + if (es.fCalculateEtaSeparations && es.fCalculateEtaSeparationsAsFunctionOf[AFO_var]) { // yes, I can decouple this one from if (qv.fCalculateQvectors) - if (pw.fUseWeights[wETA]) { - wEta = Weight(dEta, wETA); // corresponding eta weight - if (!(wEta > 0.)) { - LOGF(error, "\033[1;33m%s wEta is not positive\033[0m", __FUNCTION__); - LOGF(fatal, "dEta = %f\nwEta = %f", dEta, wEta); + if (AFO_var == AFO_ETA) { + LOGF(fatal, "\033[1;31m%s at line %d : AFO_var == AFO_ETA . This doesn't make any sense in this context. \033[0m", __FUNCTION__, __LINE__); } - } // if(pw.fUseWeights[wETA]) - - if (qv.fCalculateQvectors) { - for (int h = 0; h < gMaxHarmonic * gMaxCorrelator + 1; h++) { - for (int wp = 0; wp < gMaxCorrelator + 1; wp++) { // weight power - if (pw.fUseWeights[wPHI] || pw.fUseWeights[wPT] || pw.fUseWeights[wETA]) { - wToPowerP = std::pow(wPhi * wPt * wEta, wp); - qv.fQvector[h][wp] += TComplex(wToPowerP * std::cos(h * dPhi), wToPowerP * std::sin(h * dPhi)); // Q-vector with weights - } else { - qv.fQvector[h][wp] += TComplex(std::cos(h * dPhi), std::sin(h * dPhi)); // bare Q-vector without weights - } - } // for(int wp=0;wp 0.) { for (int e = 0; e < gMaxNumberEtaSeparations; e++) { if (dEta > es.fEtaSeparationsValues[e] / 2.) { // yes, if eta separation is 0.2, then separation interval runs from -0.1 to 0.1 - qv.fMab[1][e] += wPhi * wPt * wEta; + // qv.fmab[1][bin - 1][e] += diffPhiWeightsForThisKineVar * kineVarWeight; // Remark: I can hardwire linear weight like this only for 2-p correlation + // TBI 20250616 I cannot use this any longer, after i added one more dimension for (int h = 0; h < gMaxHarmonic; h++) { { if (es.fEtaSeparationsSkipHarmonics[h]) { continue; } - qv.fQabVector[1][h][e] += TComplex(wPhi * wPt * wEta * std::cos((h + 1) * dPhi), wPhi * wPt * wEta * std::sin((h + 1) * dPhi)); + // qv.fqabVector[1][bin - 1][h][e] += TComplex(diffPhiWeightsForThisKineVar * kineVarWeight * std::cos((h + 1) * dPhi), diffPhiWeightsForThisKineVar * kineVarWeight * std::sin((h + 1) * dPhi)); // Remark: I can hardwire linear weight like this only for 2-p correlation // TBI 20250616 I cannot use this any longer, after I added one more dimension to qv.fqabVector } } // for (int h = 0; h < gMaxHarmonic; h++) { } // for (int e = 0; e < gMaxNumberEtaSeparations; e++) { // eta separation @@ -15787,289 +18021,436 @@ void FillQvector(const double& dPhi, const double& dPt, const double& dEta) ExitFunction(__FUNCTION__); } -} // void FillQvector(const double& dPhi, const double& dPt, const double& dEta) +} // void Fillqvector(const double& dPhi, const double& kineVarValue, eqvectorKine kineVarChoice) //============================================================ -void FillQvectorFromSparse(const double& dPhi, const double& dPt, const double& dEta, const double& dCharge) +eAsFunctionOf AfoKineMap1D(eqvectorKine kineVarChoice) { - // Fill integrated Q-vector using sparse histograms. + // Simple utility function to map for the 1-dimensional case eqvectorKine into eAsFunctionOf. - // Remark: I pass by reference particle quantities, while event quantities (centrality, vertex z, ...) I fetch from data members (or from global variables in a macro). + if (tc.fVerboseForEachParticle) { + StartFunction(__FUNCTION__); + } - // To do: - // 20250224 do I need to switch to this function also in InternalValidation()? I still use simple FillQvector() there. - // That would really make sense only after I add support for usage of particle weights in InternalValidation() + eAsFunctionOf AFO_var = eAsFunctionOf_N; + + switch (kineVarChoice) { + + case PTq: { + AFO_var = AFO_PT; + break; + } + + case ETAq: { + AFO_var = AFO_ETA; + break; + } + + case CHARGEq: { + AFO_var = AFO_CHARGE; + break; + } + + // ... + + default: { + LOGF(fatal, "\033[1;31m%s at line %d : this kineVarChoice = %d is not supported yet for 1D case. \033[0m", __FUNCTION__, __LINE__, static_cast(kineVarChoice)); + break; + } + + } // switch(kineVarChoice) + + if (tc.fVerboseForEachParticle) { + ExitFunction(__FUNCTION__); + } + + return AFO_var; + +} // eAsFunctionOf AfoKineMap1D(eqvectorKine kineVarChoice) + +//============================================================ + +eAsFunctionOf2D AfoKineMap2D(eqvectorKine kineVarChoice) +{ + // Simple utility function to map for the 2-dimensional case eqvectorKine into eAsFunctionOf2D. if (tc.fVerboseForEachParticle) { StartFunction(__FUNCTION__); - LOGF(info, "\033[1;32m dPhi = %f\033[0m", dPhi); - LOGF(info, "\033[1;32m dPt = %f\033[0m", dPt); - LOGF(info, "\033[1;32m dEta = %f\033[0m", dEta); - LOGF(info, "\033[1;32m dCharge = %f\033[0m", dCharge); } - // Particle weights from sparse histograms: - double wPhi = 1.; // differential multidimensional phi weight, its dimensions are defined via enum eDiffPhiWeights - double wPt = 1.; // differential multidimensional pt weight, its dimensions are defined via enum eDiffPtWeights - double wEta = 1.; // differential multidimensional eta weight, its dimensions are defined via enum eDiffEtaWeights - double wToPowerP = 1.; // weight raised to power p + eAsFunctionOf2D AFO_var = eAsFunctionOf2D_N; - // *) Multidimensional phi weights: - if (pw.fUseDiffPhiWeights[wPhiPhiAxis]) { // yes, 0th axis serves as a comon boolean for this category - wPhi = WeightFromSparse(dPhi, dPt, dEta, dCharge, eDWPhi); - // last argument is enum eDiffWeightCategory. Event quantities, e.g. centraliy and vz, I do not need to pass, because - // for them I have ebye data members - if (!(wPhi > 0.)) { - LOGF(error, "\033[1;33m%s wPhi is not positive\033[0m", __FUNCTION__); - LOGF(error, "dPhi = %f", dPhi); - if (pw.fUseDiffPhiWeights[wPhiPtAxis]) { - LOGF(fatal, "dPt = %f", dPt); - } - if (pw.fUseDiffPhiWeights[wPhiEtaAxis]) { - LOGF(fatal, "dEta = %f", dEta); - } - if (pw.fUseDiffPhiWeights[wPhiChargeAxis]) { - LOGF(fatal, "dCharge = %f", dCharge); - } - if (pw.fUseDiffPhiWeights[wPhiCentralityAxis]) { - LOGF(fatal, "ebye.Centrality = %f", ebye.fCentrality); - } - if (pw.fUseDiffPhiWeights[wPhiVertexZAxis]) { - LOGF(fatal, "ebye.Vz = %f", ebye.fVz); - } - LOGF(fatal, "Multidimensional weight for enabled dimensions is wPhi = %f", wPhi); + switch (kineVarChoice) { + + case PT_ETAq: { + AFO_var = AFO_PT_ETA; + break; } - } // if(pw.fUseDiffPhiWeights[wPhiPhiAxis]) - // *) Multidimensional pt weights: - if (pw.fUseDiffPtWeights[wPtPtAxis]) { // yes, 0th axis serves as a comon boolean for this category - wPt = WeightFromSparse(dPhi, dPt, dEta, dCharge, eDWPt); // TBI 20250224 not sure if this is the right/best approach - // last argument is enum eDiffWeightCategory. Event quantities, e.g. centraliy and vz, I do not need to pass, because - // for them I have ebye data members - if (!(wPt > 0.)) { - LOGF(error, "\033[1;33m%s wPt is not positive\033[0m", __FUNCTION__); - LOGF(error, "dPt = %f", dPt); - if (pw.fUseDiffPtWeights[wPtPtAxis]) { - LOGF(fatal, "dPt = %f", dPt); - } - LOGF(fatal, "Multidimensional weight for enabled dimensions is wPt = %f", wPt); + case PT_CHARGEq: { + AFO_var = AFO_PT_CHARGE; + break; } - } // if(pw.fUseDiffPtWeights[wPtPtAxis]) - // *) Multidimensional eta weights: - if (pw.fUseDiffEtaWeights[wEtaEtaAxis]) { // yes, 0th axis serves as a comon boolean for this category - wEta = WeightFromSparse(dPhi, dPt, dEta, dCharge, eDWEta); // TBI 20250224 not sure if this is the right/best approach - // last argument is enum eDiffWeightCategory. Event quantities, e.g. centraliy and vz, I do not need to pass, because - // for them I have ebye data members - if (!(wEta > 0.)) { - LOGF(error, "\033[1;33m%s wEta is not positive\033[0m", __FUNCTION__); - LOGF(error, "dEta = %f", dEta); - if (pw.fUseDiffEtaWeights[wEtaEtaAxis]) { - LOGF(fatal, "dEta = %f", dEta); - } - LOGF(fatal, "Multidimensional weight for enabled dimensions is wEta = %f", wEta); + case ETA_CHARGEq: { + AFO_var = AFO_ETA_CHARGE; + break; + } + + // ... + + default: { + LOGF(fatal, "\033[1;31m%s at line %d : this kineVarChoice = %d is not supported yet for 2D case. \033[0m", __FUNCTION__, __LINE__, static_cast(kineVarChoice)); + break; + } + + } // switch(kineVarChoice) + + if (tc.fVerboseForEachParticle) { + ExitFunction(__FUNCTION__); + } + + return AFO_var; + +} // eAsFunctionOf2D AfoKineMap2D(eqvectorKine kineVarChoice) + +//============================================================ + +eAsFunctionOf3D AfoKineMap3D(eqvectorKine kineVarChoice) +{ + // Simple utility function to map for the 3-dimensional case eqvectorKine into eAsFunctionOf3D. + + if (tc.fVerboseForEachParticle) { + StartFunction(__FUNCTION__); + } + + eAsFunctionOf3D AFO_var = eAsFunctionOf3D_N; + + switch (kineVarChoice) { + + case PT_ETA_CHARGEq: { + AFO_var = AFO_PT_ETA_CHARGE; + break; } - } // if(pw.fUseDiffEtaWeights[wEtaEtaAxis]) - if (qv.fCalculateQvectors) { - for (int h = 0; h < gMaxHarmonic * gMaxCorrelator + 1; h++) { - for (int wp = 0; wp < gMaxCorrelator + 1; wp++) { // weight power - if (pw.fUseDiffPhiWeights[wPhiPhiAxis] || pw.fUseDiffPtWeights[wPtPtAxis] || pw.fUseDiffEtaWeights[wEtaEtaAxis]) { - wToPowerP = std::pow(wPhi * wPt * wEta, wp); - qv.fQvector[h][wp] += TComplex(wToPowerP * std::cos(h * dPhi), wToPowerP * std::sin(h * dPhi)); // Q-vector with weights - } else { - qv.fQvector[h][wp] += TComplex(std::cos(h * dPhi), std::sin(h * dPhi)); // bare Q-vector without weights - } - } // for(int wp=0;wp 0.) { - for (int e = 0; e < gMaxNumberEtaSeparations; e++) { - if (dEta > es.fEtaSeparationsValues[e] / 2.) { // yes, if eta separation is 0.2, then separation interval runs from -0.1 to 0.1 - qv.fMab[1][e] += wPhi * wPt * wEta; - for (int h = 0; h < gMaxHarmonic; h++) { - { - if (es.fEtaSeparationsSkipHarmonics[h]) { - continue; - } - qv.fQabVector[1][h][e] += TComplex(wPhi * wPt * wEta * std::cos((h + 1) * dPhi), wPhi * wPt * wEta * std::sin((h + 1) * dPhi)); - } - } // for (int h = 0; h < gMaxHarmonic; h++) { - } // for (int e = 0; e < gMaxNumberEtaSeparations; e++) { // eta separation - } + default: { + LOGF(fatal, "\033[1;31m%s at line %d : this kineVarChoice = %d is not supported yet for 3D case. \033[0m", __FUNCTION__, __LINE__, static_cast(kineVarChoice)); + break; } - } // if(es.fCalculateEtaSeparations) { + + } // switch(kineVarChoice) if (tc.fVerboseForEachParticle) { ExitFunction(__FUNCTION__); } -} // void FillQvectorFromSparse(const double& dPhi, const double& dPt, const double& dEta, const double& dCharge) + return AFO_var; + +} // eAsFunctionOf3D AfoKineMap3D(eqvectorKine kineVarChoice) //============================================================ -void Fillqvector(const double& dPhi, const double& kineVarValue, eqvectorKine kineVarChoice, const double& dEta = 0.) +TString StringKineMap(eqvectorKine kineVarChoice) { - // Fill differential q-vector, in generic kinematic variable. Here "kine" originally meant vs. pt or vs. eta, now it's general. - // Example usage #1: this->Fillqvector(dPhi, dPt, PTq); // differential q-vectors without using eta separations - // Example usage #2: this->Fillqvector(dPhi, dPt, PTq, dEta); // differential q-vectors with using eta separations (I need dEta of particle to decide whether particle is added to qa or qb) + // Simple utility function to map eqvectorKine into string. + + // Example: StringKineMap(PTq).Data() => prints "vs. pt" if (tc.fVerboseForEachParticle) { StartFunction(__FUNCTION__); } - // *) Mapping between enum's "eqvectorKine" on one side, and "eAsFunctionOf", "eWeights" and "eDiffWeights" on the other: - // TBI 20240212 I could promote this also to a member function, if I need it elsewhere. Or I could use TExMap? - eAsFunctionOf AFO_var = eAsFunctionOf_N; // this local variable determines the enum "eAsFunctionOf" which corresponds to enum "eqvectorKine" - eWeights AFO_weight = eWeights_N; // this local variable determines the enum "eWeights" which corresponds to enum "eqvectorKine" - eDiffWeights AFO_diffWeight = eDiffWeights_N; // this local variable determines the enum "eDiffWeights" which corresponds to enum "eqvectorKine" + TString s = ""; + switch (kineVarChoice) { + case PTq: { - AFO_var = AFO_PT; - AFO_weight = wPT; - AFO_diffWeight = wPHIPT; + s = "vs. pt"; break; } + case ETAq: { - AFO_var = AFO_ETA; - AFO_weight = wETA; - AFO_diffWeight = wPHIETA; + s = "vs. eta"; + break; + } + + case CHARGEq: { + s = "vs. charge"; + break; + } + + case PT_ETAq: { + s = "vs. pt vs. eta"; + break; + } + + case PT_CHARGEq: { + s = "vs. pt vs. charge"; + break; + } + + case ETA_CHARGEq: { + s = "vs. eta vs. charge"; break; } + + case PT_ETA_CHARGEq: { + s = "vs. pt vs. eta vs. charge"; + break; + } + + // ... + default: { LOGF(fatal, "\033[1;31m%s at line %d : this kineVarChoice = %d is not supported yet. \033[0m", __FUNCTION__, __LINE__, static_cast(kineVarChoice)); break; } + } // switch(kineVarChoice) - // *) Insanity checks on above settings: - if (AFO_var == eAsFunctionOf_N) { - LOGF(fatal, "\033[1;31m%s at line %d : AFO_var == eAsFunctionOf_N => add some more entries to the case statement \033[0m", __FUNCTION__, __LINE__); - } - if (AFO_weight == eWeights_N) { - LOGF(fatal, "\033[1;31m%s at line %d : AFO_weight == eWeights_N => add some more entries to the case statement \033[0m", __FUNCTION__, __LINE__); + if (tc.fVerboseForEachParticle) { + ExitFunction(__FUNCTION__); } - if (AFO_diffWeight == eDiffWeights_N) { - LOGF(fatal, "\033[1;31m%s at line %d : AFO_diffWeight == eDiffWeights_N => add some more entries to the case statement \033[0m", __FUNCTION__, __LINE__); + + return s; + +} // TString StringKineMap(eqvectorKine kineVarChoice) + +//============================================================ + +void FillqvectorNdim(const double& dPhi, double* kineVarValues, int Ndim, eqvectorKine kineVarChoice, const double& dEta = 0.) +{ + // Fill differential q-vector in N dimensions, calculated vs. N generic kinematic variables, + // and using only the unit particle weights (for non-unit weights, there is FillqvectorNdimFromSparse(...)). + // Here "kine" originally meant vs. pt or vs. eta, now it's general. + // For more than 1 dimension, e.g. vs. (pt, eta), "kineVarChoice" corresponds to linearized 2D case, in an analogy with "global bin" structure for multidimensional histograms. + + // Remark 0: "kineVarValues" is now an array, e.g. for qvector vs. (pt, eta), it holds pt and eta of a particle. Ndim is dimensionality of that array. + // Remark 1: The last argument "dEta" is meant to be used only for fqabVector (I need dEta of particle to decide whether particle is added to qa or qb) + // Remark 2: "bin" is always mean to be "linearized global bin", therefore I changed indexing here from "bin-1" to "bin" + + // Example - the standard 1D case: + // double kineArr[1] = {dPt}; + // this->FillqvectorNdim(dPhi, kineArr, 1, PTq); // differential q-vector vs. pt + + // Example - the 2D case: + // double kineArr[2] = {dPt, dEta}; + // this->FillqvectorNdim(dPhi, kineArr, 2, PT_ETAq); // differential q-vector vs. (pt, eta) + + // Example - the 3D case: + // double kineArr[3] = {dPt, dEta, dCharge}; + // this->FillqvectorNdim(dPhi, kineArr, 3, PT_ETA_CHARGEq); // differential q-vector vs. (pt, eta, charge) + + // Example - the 1D case, pt dependence with eta separations: + // double kineArr[1] = {dPt}; + // this->FillqvectorNdim(dPhi, kineArr, 1, PTq, dEta); // differential q-vectors with using eta separations (I need dEta of particle to decide whether particle is added to qa or qb) + + if (tc.fVerboseForEachParticle) { + StartFunction(__FUNCTION__); } - // *) Get the desired bin number: + // This is the linearized global bin, the 2nd index of fqvector[...][gMaxNoBinsKine][...][...], it shall work transparently for 1D, 2D, 3D, etc... + // Yes, it is also the 3rd index of fqabVector[...][...][gMaxNoBinsKine][...][...] int bin = -1; - if (res.fResultsPro[AFO_var]) { - bin = res.fResultsPro[AFO_var]->FindBin(kineVarValue); // this 'bin' starts from 1, i.e. this is genuine histogram bin - if (0 >= bin || res.fResultsPro[AFO_var]->GetNbinsX() < bin) { // either underflow or overflow is hit, meaning that histogram is booked in narrower range than cuts - LOGF(fatal, "\033[1;31m%s at line %d : kineVarChoice = %d, bin = %d, kineVarValue = %f \033[0m", __FUNCTION__, __LINE__, static_cast(kineVarChoice), bin, kineVarValue); + + switch (Ndim) { + + case 1: { + eAsFunctionOf AFO_var = AfoKineMap1D(kineVarChoice); + if (res.fResultsPro[AFO_var]) { + bin = res.fResultsPro[AFO_var]->FindBin(kineVarValues[0]); // this is linearized 'global bin', for 1D it's the same as ordinary bin + + // TBI 20250528 check if the check below is computationally heavy. If so, add the flag tc.fInsanityCheckForEachParticle here. + if (res.fResultsPro[AFO_var]->IsBinUnderflow(bin) || res.fResultsPro[AFO_var]->IsBinOverflow(bin)) { + LOGF(fatal, "\033[1;31m%s at line %d : kineVarChoice = %d (%s), kineVarValues[0] = %f is in bin = %d, which is either underflow or overflow.\033[0m", __FUNCTION__, __LINE__, static_cast(kineVarChoice), StringKineMap(kineVarChoice).Data(), kineVarValues[0], bin); + } + } + break; } - } - // *) Get all integrated kinematic weights: - double wToPowerP = 1.; // weight raised to power p - double kineVarWeight = 1.; // e.g. this can be integrated pT or eta weight - if (pw.fUseWeights[AFO_weight]) { - kineVarWeight = Weight(kineVarValue, AFO_weight); // corresponding e.g. pt or eta weight - if (!(kineVarWeight > 0.)) { - LOGF(fatal, "\033[1;31m%s at line %d : kineVarWeight is not positive \033[0m", __FUNCTION__, __LINE__); - // TBI 20240212 or could I just skip this particle? + case 2: { + eAsFunctionOf2D AFO_var = AfoKineMap2D(kineVarChoice); + if (res.fResultsPro2D[AFO_var]) { + bin = res.fResultsPro2D[AFO_var]->FindBin(kineVarValues[0], kineVarValues[1]); // this is linearized 'global bin' + + // TBI 20250528 check if the check below is computationally heavy. If so, add the flag tc.fInsanityCheckForEachParticle here. + if (res.fResultsPro2D[AFO_var]->IsBinUnderflow(bin) || res.fResultsPro2D[AFO_var]->IsBinOverflow(bin)) { + LOGF(fatal, "\033[1;31m%s at line %d : kineVarChoice = %d (%s), kineVarValues[0] = %f, kineVarValues[1] = %f is in global bin = %d, which is either underflow or overflow.\033[0m", __FUNCTION__, __LINE__, static_cast(kineVarChoice), StringKineMap(kineVarChoice).Data(), kineVarValues[0], kineVarValues[1], bin); + } + } + break; } - } // if(fUseWeights[AFO_weight]) { - // *) Get all differential phi-weights for this kinematic variable: - // Remark: special treatment is justified for phi-weights, because q-vector is defined in terms of phi-weights. - double diffPhiWeightsForThisKineVar = 1.; - if (pw.fUseDiffWeights[AFO_diffWeight]) { - diffPhiWeightsForThisKineVar = DiffWeight(dPhi, kineVarValue, kineVarChoice); // corresponding differential phi weight as a function of e.g. pt or eta - if (!(diffPhiWeightsForThisKineVar > 0.)) { - LOGF(fatal, "\033[1;31m%s at line %d : diffPhiWeightsForThisKineVar is not positive \033[0m", __FUNCTION__, __LINE__); - // TBI 20240212 or could I just skip this particle? + case 3: { + eAsFunctionOf3D AFO_var = AfoKineMap3D(kineVarChoice); + if (res.fResultsPro3D[AFO_var]) { + bin = res.fResultsPro3D[AFO_var]->FindBin(kineVarValues[0], kineVarValues[1], kineVarValues[2]); // this is linearized 'global bin' + + // TBI 20250528 check if the check below is computationally heavy. If so, add the flag tc.fInsanityCheckForEachParticle here. + if (res.fResultsPro3D[AFO_var]->IsBinUnderflow(bin) || res.fResultsPro3D[AFO_var]->IsBinOverflow(bin)) { + LOGF(fatal, "\033[1;31m%s at line %d : kineVarChoice = %d (%s), kineVarValues[0] = %f, kineVarValues[1] = %f, kineVarValues[2] = %f is in global bin = %d, which is either underflow or overflow.\033[0m", __FUNCTION__, __LINE__, static_cast(kineVarChoice), StringKineMap(kineVarChoice).Data(), kineVarValues[0], kineVarValues[1], kineVarValues[2], bin); + } + } + break; } - } // if(pw.fUseDiffWeights[AFO_diffWeight]) { - // *) Finally, fill differential q-vector in that bin: - for (int h = 0; h < gMaxHarmonic * gMaxCorrelator + 1; h++) { - for (int wp = 0; wp < gMaxCorrelator + 1; wp++) { // weight power - if (pw.fUseWeights[AFO_weight] || pw.fUseDiffWeights[AFO_diffWeight]) { - // TBI 20240212 supported at the moment: e.g. q-vector vs pt can be weighted only with diff. phi(pt) and integrated pt weights. - // It cannot be weighted in addition with eta weights, since in any case I anticipate I will do always 1-D analysis, by integrating out all other dependencies - wToPowerP = std::pow(diffPhiWeightsForThisKineVar * kineVarWeight, wp); - qv.fqvector[kineVarChoice][bin - 1][h][wp] += TComplex(wToPowerP * std::cos(h * dPhi), wToPowerP * std::sin(h * dPhi)); // q-vector with weights - } else { - qv.fqvector[kineVarChoice][bin - 1][h][wp] += TComplex(std::cos(h * dPhi), std::sin(h * dPhi)); // bare q-vector without weights + // ... + + default: { + LOGF(fatal, "\033[1;31m%s at line %d : Ndim = %d is not supported yet. \033[0m", __FUNCTION__, __LINE__, Ndim); + break; + } + + } // switch (Ndim) + + // zzzzzzzzzzzzzzzzzzzzzz + + /* + + // *) Mapping between enum's "eqvectorKine" on one side, and "eAsFunctionOf", "eWeights" and "eDiffWeights" on the other: + // TBI 20240212 I could promote this also to a member function, if I need it elsewhere. Or I could use TExMap? + eAsFunctionOf AFO_var = eAsFunctionOf_N; // this local variable determines the enum "eAsFunctionOf" which corresponds to enum "eqvectorKine" + eWeights AFO_weight = eWeights_N; // this local variable determines the enum "eWeights" which corresponds to enum "eqvectorKine" + eDiffWeights AFO_diffWeight = eDiffWeights_N; // this local variable determines the enum "eDiffWeights" which corresponds to enum "eqvectorKine" + switch (kineVarChoice) { + case PTq: { + AFO_var = AFO_PT; + AFO_weight = wPT; + AFO_diffWeight = wPHIPT; // TBI 20250215 this is now obsolete, see the comment in enum + break; + } + case ETAq: { + AFO_var = AFO_ETA; + AFO_weight = wETA; + AFO_diffWeight = wPHIETA; // TBI 20250215 this is now obsolete, see the comment in enum + break; + } + case CHARGEq: { + AFO_var = AFO_CHARGE; + AFO_weight = wCHARGE; + AFO_diffWeight = wPHICHARGE; // TBI 20250215 this is now obsolete, see the comment in enum + break; + } + default: { + LOGF(fatal, "\033[1;31m%s at line %d : this kineVarChoice = %d is not supported yet. \033[0m", __FUNCTION__, __LINE__, static_cast(kineVarChoice)); + break; + } + } // switch(kineVarChoice) + + // *) Insanity checks on above settings: + if (AFO_var == eAsFunctionOf_N) { + LOGF(fatal, "\033[1;31m%s at line %d : AFO_var == eAsFunctionOf_N => add some more entries to the case statement \033[0m", __FUNCTION__, __LINE__); + } + if (AFO_weight == eWeights_N) { + LOGF(fatal, "\033[1;31m%s at line %d : AFO_weight == eWeights_N => add some more entries to the case statement \033[0m", __FUNCTION__, __LINE__); + } + if (AFO_diffWeight == eDiffWeights_N) { + LOGF(fatal, "\033[1;31m%s at line %d : AFO_diffWeight == eDiffWeights_N => add some more entries to the case statement \033[0m", __FUNCTION__, __LINE__); + } + + // *) Get the desired bin number: + int bin = -1; + if (res.fResultsPro[AFO_var]) { + bin = res.fResultsPro[AFO_var]->FindBin(kineVarValue); // this 'bin' starts from 1, i.e. this is genuine histogram bin + if (0 >= bin || res.fResultsPro[AFO_var]->GetNbinsX() < bin) { // either underflow or overflow is hit, meaning that histogram is booked in narrower range than cuts + LOGF(fatal, "\033[1;31m%s at line %d : kineVarChoice = %d, bin = %d, kineVarValue = %f \033[0m", __FUNCTION__, __LINE__, static_cast(kineVarChoice), bin, kineVarValue); + } + } + */ + + /* + // *) Get all integrated kinematic weights: + double wToPowerP = 1.; // weight raised to power p + double kineVarWeight = 1.; // e.g. this can be integrated pT or eta weight + if (pw.fUseWeights[AFO_weight]) { + kineVarWeight = Weight(kineVarValue, AFO_weight); // corresponding e.g. pt or eta weight + if (!(kineVarWeight > 0.)) { + LOGF(fatal, "\033[1;31m%s at line %d : kineVarWeight is not positive \033[0m", __FUNCTION__, __LINE__); + // TBI 20240212 or could I just skip this particle? + } + } // if(fUseWeights[AFO_weight]) { + + // *) Get all differential phi-weights for this kinematic variable: + // Remark: special treatment is justified for phi-weights, because q-vector is defined in terms of phi-weights. + double diffPhiWeightsForThisKineVar = 1.; + if (pw.fUseDiffWeights[AFO_diffWeight]) { + diffPhiWeightsForThisKineVar = DiffWeight(dPhi, kineVarValue, kineVarChoice); // corresponding differential phi weight as a function of e.g. pt or eta + if (!(diffPhiWeightsForThisKineVar > 0.)) { + LOGF(fatal, "\033[1;31m%s at line %d : diffPhiWeightsForThisKineVar is not positive \033[0m", __FUNCTION__, __LINE__); + // TBI 20240212 or could I just skip this particle? } + } // if(pw.fUseDiffWeights[AFO_diffWeight]) { + + */ + + // *) Finally, fill differential q-vector in that linearized "global bin": + for (int h = 0; h < gMaxHarmonic * gMaxCorrelator + 1; h++) { + for (int wp = 0; wp < gMaxCorrelator + 1; wp++) { // weight power + qv.fqvector[kineVarChoice][bin][h][wp] += std::complex(std::cos(h * dPhi), std::sin(h * dPhi)); // bare q-vector without weights } // for(int wp=0;wpAddAt(dPhi, qv.fqVectorEntries[kineVarChoice][bin - 1]); - nl.ftaNestedLoopsKine[kineVarChoice][bin - 1][1]->AddAt(diffPhiWeightsForThisKineVar * kineVarWeight, qv.fqVectorEntries[kineVarChoice][bin - 1]); + nl.ftaNestedLoopsKine[kineVarChoice][bin][0]->AddAt(dPhi, qv.fqvectorEntries[kineVarChoice][bin]); + nl.ftaNestedLoopsKine[kineVarChoice][bin][1]->AddAt(1, qv.fqvectorEntries[kineVarChoice][bin]); // TBI 20250529 bare, without weights. Otherwise, adapt and use the line below + // nl.ftaNestedLoopsKine[kineVarChoice][bin][1]->AddAt(diffPhiWeightsForThisKineVar * kineVarWeight, qv.fqvectorEntries[kineVarChoice][bin]); // TBI 20250527 temporarily commented out } // *) Multiplicity counter in this bin: - qv.fqVectorEntries[kineVarChoice][bin - 1]++; // count number of particles in this pt bin in this event + qv.fqvectorEntries[kineVarChoice][bin]++; // count number of particles in this differential bin in this event // *) Usage of eta separations in differential correlations: - if (es.fCalculateEtaSeparations && es.fCalculateEtaSeparationsAsFunctionOf[AFO_var]) { // yes, I can decouple this one from if (qv.fCalculateQvectors) + if (es.fCalculateEtaSeparations && qv.fCalculateqvectorsKineEtaSeparations[kineVarChoice]) { // yes, I have decoupled this one from if (qv.fCalculateQvectors) - if (AFO_var == AFO_ETA) { - LOGF(fatal, "\033[1;31m%s at line %d : AFO_var == AFO_ETA . This doesn't make any sense in this context. \033[0m", __FUNCTION__, __LINE__); + if (kineVarChoice == ETAq || kineVarChoice == PT_ETAq || kineVarChoice == ETA_CHARGEq || kineVarChoice == PT_ETA_CHARGEq) { + LOGF(fatal, "\033[1;31m%s at line %d : kineVarChoice == %s . This doesn't make any sense in this context => eta separations cannot be used for differential vectors vs. eta (either 1D or 2D or 3D case). \033[0m", __FUNCTION__, __LINE__, StringKineMap(kineVarChoice).Data()); // _22 } if (dEta < 0.) { for (int e = 0; e < gMaxNumberEtaSeparations; e++) { - if (dEta < -1. * es.fEtaSeparationsValues[e] / 2.) { // yes, if eta separation is 0.2, then separation interval runs from -0.1 to 0.1 - qv.fmab[0][bin - 1][e] += diffPhiWeightsForThisKineVar * kineVarWeight; // Remark: I can hardwire linear weight like this only for 2-p correlation + if (dEta < -1. * es.fEtaSeparationsValues[e] / 2.) { // yes, if eta separation is 0.2, then separation interval runs from -0.1 to 0.1 + qv.fmab[0][kineVarChoice][bin][e] += 1.; // diffPhiWeightsForThisKineVar * kineVarWeight; // Remark: I can hardwire linear weight like this only for 2-p correlation for (int h = 0; h < gMaxHarmonic; h++) { if (es.fEtaSeparationsSkipHarmonics[h]) { continue; } - qv.fqabVector[0][bin - 1][h][e] += TComplex(diffPhiWeightsForThisKineVar * kineVarWeight * std::cos((h + 1) * dPhi), diffPhiWeightsForThisKineVar * kineVarWeight * std::sin((h + 1) * dPhi)); // Remark: I can hardwire linear weight like this only for 2-p correlation + qv.fqabVector[0][kineVarChoice][bin][h][e] += std::complex(std::cos((h + 1) * dPhi), std::sin((h + 1) * dPhi)); // bare q_ab-vector without weights } } // for (int h = 0; h < gMaxHarmonic; h++) { } // for (int e = 0; e < gMaxNumberEtaSeparations; e++) { // eta separation } else if (dEta > 0.) { for (int e = 0; e < gMaxNumberEtaSeparations; e++) { - if (dEta > es.fEtaSeparationsValues[e] / 2.) { // yes, if eta separation is 0.2, then separation interval runs from -0.1 to 0.1 - qv.fmab[1][bin - 1][e] += diffPhiWeightsForThisKineVar * kineVarWeight; // Remark: I can hardwire linear weight like this only for 2-p correlation + if (dEta > es.fEtaSeparationsValues[e] / 2.) { // yes, if eta separation is 0.2, then separation interval runs from -0.1 to 0.1 + qv.fmab[1][kineVarChoice][bin][e] += 1.; // diffPhiWeightsForThisKineVar * kineVarWeight; // Remark: I can hardwire linear weight like this only for 2-p correlation for (int h = 0; h < gMaxHarmonic; h++) { { if (es.fEtaSeparationsSkipHarmonics[h]) { continue; } - qv.fqabVector[1][bin - 1][h][e] += TComplex(diffPhiWeightsForThisKineVar * kineVarWeight * std::cos((h + 1) * dPhi), diffPhiWeightsForThisKineVar * kineVarWeight * std::sin((h + 1) * dPhi)); // Remark: I can hardwire linear weight like this only for 2-p correlation + qv.fqabVector[1][kineVarChoice][bin][h][e] += std::complex(std::cos((h + 1) * dPhi), std::sin((h + 1) * dPhi)); // bare q_ab-vector without weights } } // for (int h = 0; h < gMaxHarmonic; h++) { } // for (int e = 0; e < gMaxNumberEtaSeparations; e++) { // eta separation } } - } // if(es.fCalculateEtaSeparations) { + } // if(es.fCalculateEtaSeparations) if (tc.fVerboseForEachParticle) { ExitFunction(__FUNCTION__); } -} // void Fillqvector(const double& dPhi, const double& kineVarValue, eqvectorKine kineVarChoice) +} // void FillqvectorNdim(const double& dPhi, double* kineVarValues, int Ndim, eqvectorKine kineVarChoice, const double& dEta = 0.) //============================================================ void CalculateEverything() { // Calculate everything for selected events and particles. - // Remark: Data members for Q-vectors, containers for nested loops, etc., must all be filled when this function is called. + // Remark: Data members for Q-vectors (both integrated and differential), containers for nested loops, etc., must all be filled when this function is called. if (tc.fVerbose) { StartFunction(__FUNCTION__); @@ -16095,14 +18476,45 @@ void CalculateEverything() this->CalculateTest0(); } - // *) Calculate kine Test0: TBI 20240110 name convention - // Remark: vs. pt, vs. eta, etc., are all calculated here - if (qv.fCalculateQvectors && t0.fCalculateTest0AsFunctionOf[AFO_PT]) { - this->CalculateKineTest0(AFO_PT); + // *) Calculate kine Test0: + + // **) 1D kine: + // ***) cases for which 1D vs. pt calculus is needed: + if (qv.fCalculateQvectors && qv.fCalculateqvectorsKine[PTq]) { // TBI 20250601 do I really need here qv.fCalculateQvectors + this->CalculateKineTest0Ndim(PTq, 1); + } + + // ***) cases for which 1D vs. eta calculus is needed: + if (qv.fCalculateQvectors && qv.fCalculateqvectorsKine[ETAq]) { // TBI 20250601 do I really need here qv.fCalculateQvectors + this->CalculateKineTest0Ndim(ETAq, 1); } - if (qv.fCalculateQvectors && t0.fCalculateTest0AsFunctionOf[AFO_ETA]) { - this->CalculateKineTest0(AFO_ETA); + // ***) cases for which 1D vs. charge calculus is needed: + if (qv.fCalculateQvectors && qv.fCalculateqvectorsKine[CHARGEq]) { // TBI 20250601 do I really need here qv.fCalculateQvectors + this->CalculateKineTest0Ndim(CHARGEq, 1); } + // ... + + // **) 2D kine: + // ***) cases for which 2D vs. (pt,eta) calculus is needed: + if (qv.fCalculateQvectors && qv.fCalculateqvectorsKine[PT_ETAq]) { // TBI 20250601 do I really need here qv.fCalculateQvectors + this->CalculateKineTest0Ndim(PT_ETAq, 2); + } + // ***) cases for which 2D vs. (pt,charge) calculus is needed: + if (qv.fCalculateQvectors && qv.fCalculateqvectorsKine[PT_CHARGEq]) { // TBI 20250601 do I really need here qv.fCalculateQvectors + this->CalculateKineTest0Ndim(PT_CHARGEq, 2); + } + // ***) cases for which 2D vs. (eta,charge) calculus is needed: + if (qv.fCalculateQvectors && qv.fCalculateqvectorsKine[ETA_CHARGEq]) { // TBI 20250601 do I really need here qv.fCalculateQvectors + this->CalculateKineTest0Ndim(ETA_CHARGEq, 2); + } + // ... + + // **) 3D kine: + // ***) cases for which 3D vs. (pt,eta,charge) calculus is needed: + if (qv.fCalculateQvectors && qv.fCalculateqvectorsKine[PT_ETA_CHARGEq]) { // TBI 20250601 do I really need here qv.fCalculateQvectors + this->CalculateKineTest0Ndim(PT_ETA_CHARGEq, 3); + } + // ... // *) Calculate nested loops: if (nl.fCalculateNestedLoops) { @@ -16118,7 +18530,10 @@ void CalculateEverything() if (es.fCalculateEtaSeparations) { this->CalculateEtaSeparations(); if (es.fCalculateEtaSeparationsAsFunctionOf[AFO_PT]) { - this->CalculateKineEtaSeparations(AFO_PT); // The implementation of CalculateKineEtaSeparations( ... ) is generic and can be used for any other "kine" variable, for which it makes sense + this->CalculateKineEtaSeparationsNdim(PTq, 1); + } + if (es.fCalculateEtaSeparationsAsFunctionOf[AFO_CHARGE]) { + this->CalculateKineEtaSeparationsNdim(CHARGEq, 1); } } @@ -16191,9 +18606,10 @@ void MainLoopOverParticles(T const& tracks) } // *) Declare local kinematic variables: - double dPhi = 0.; // azimuthal angle - double dPt = 0.; // transverse momentum - double dEta = 0.; // pseudorapidity + double dPhi = 0.; // azimuthal angle + double dPt = 0.; // transverse momentum + double dEta = 0.; // pseudorapidity + double dCharge = -44.; // particle charge. Yes, never initialize charge to 0. // *) If random access of tracks from collection is requested, use Fisher-Yates algorithm to generate random indices: if (tc.fUseFisherYates) { @@ -16230,41 +18646,31 @@ void MainLoopOverParticles(T const& tracks) continue; } - // memStatus ~120 (with 'continue') - // *) Fill particle histograms before particle cuts: if (ph.fFillParticleHistograms || ph.fFillParticleHistograms2D || qa.fFillQAParticleHistograms2D) { FillParticleHistograms(track, eBefore); } - - // memStatus ~163 (with 'continue') - // *) Particle cuts counters (use only during QA, as this is computationally heavy): if (pc.fUseParticleCutCounterAbsolute || pc.fUseParticleCutCounterSequential) { ParticleCutsCounters(track); } - // memStatus ~164 (with 'continue') - // *) Particle cuts: if (!ParticleCuts(track, eCut)) { // Main call for event cuts. continue; // not return!! } - // memStatus ~162 (with 'continue') - // *) Fill particle histograms after particle cuts: if (ph.fFillParticleHistograms || ph.fFillParticleHistograms2D || qa.fFillQAParticleHistograms2D) { FillParticleHistograms(track, eAfter); } - // memStatus ~164 (with 'continue') - // *) Intitialize local kinematic variables: // Remark: for "eRecSim" processing, kinematics is taken from "reconstructed". dPhi = track.phi(); dPt = track.pt(); dEta = track.eta(); + dCharge = track.sign(); // Remark: Keep in sync all calls and flags below with the ones in InternalValidation(). // *) Integrated Q-vectors: @@ -16274,29 +18680,84 @@ void MainLoopOverParticles(T const& tracks) this->FillQvector(dPhi, dPt, dEta); // all 3 arguments are passed by reference } else { // this is now the new approach, with sparse histograms: - this->FillQvectorFromSparse(dPhi, dPt, dEta, track.sign()); // particle arguments are passed by reference. - // Event observables (centrality, vertex z, ...), I do not need to pass as arguments, - // as I have data members for them (ebye.fCentrality, ebye.Vz, ...) + this->FillQvectorFromSparse(dPhi, dPt, dEta, dCharge); // particle arguments are passed by reference. + // Event observables (centrality, vertex z, ...), I do not need to pass as arguments, + // as I have data members for them (ebye.fCentrality, ebye.Vz, ...) } } - // *) Differential q-vectors: - // **) pt-dependence: + // *) Differential q-vectors (keep in sync with the code in InternalValidation()): + + // ** 1D: + // ***) pt dependence: if (qv.fCalculateQvectors && (mupa.fCalculateCorrelationsAsFunctionOf[AFO_PT] || t0.fCalculateTest0AsFunctionOf[AFO_PT]) && !es.fCalculateEtaSeparations) { // In this branch I do not need eta separation, so the lighter call can be executed: - this->Fillqvector(dPhi, dPt, PTq); // first 2 arguments are passed by reference, 3rd argument is enum + double kineArr[1] = {dPt}; + this->FillqvectorNdim(dPhi, kineArr, 1, PTq); } else if (es.fCalculateEtaSeparations && es.fCalculateEtaSeparationsAsFunctionOf[AFO_PT]) { // In this branch I do need eta separation, so the heavier call must be executed: - // Remark: Within Fillqvector() I check again all the relevant flags. - this->Fillqvector(dPhi, dPt, PTq, dEta); // first 2 arguments and the last one are passed by reference, 3rd argument is enum. "kine" variable is the 2nd argument + double kineArr[1] = {dPt}; + this->FillqvectorNdim(dPhi, kineArr, 1, PTq, dEta); } - // **) eta-dependence: + + // ***) eta dependence: if (qv.fCalculateQvectors && (mupa.fCalculateCorrelationsAsFunctionOf[AFO_ETA] || t0.fCalculateTest0AsFunctionOf[AFO_ETA])) { // Remark: For eta dependence I do not consider es.fCalculateEtaSeparations, because in this context that calculation is meaningless. - this->Fillqvector(dPhi, dEta, ETAq); // first 2 arguments are passed by reference, 3rd argument is enum + double kineArr[1] = {dEta}; + this->FillqvectorNdim(dPhi, kineArr, 1, ETAq); + } + + // ***) charge dependence: + if (qv.fCalculateQvectors && (mupa.fCalculateCorrelationsAsFunctionOf[AFO_CHARGE] || t0.fCalculateTest0AsFunctionOf[AFO_CHARGE]) && !es.fCalculateEtaSeparations) { + // In this branch I do not need eta separation, so the lighter call can be executed: + double kineArr[1] = {dCharge}; + this->FillqvectorNdim(dPhi, kineArr, 1, CHARGEq); + } else if (es.fCalculateEtaSeparations && es.fCalculateEtaSeparationsAsFunctionOf[AFO_CHARGE]) { + // In this branch I do need eta separation, so the heavier call must be executed: + double kineArr[1] = {dCharge}; + this->FillqvectorNdim(dPhi, kineArr, 1, CHARGEq, dEta); + } + + // ... + + // ** 2D: + // ***) pt-eta dependence: + if (qv.fCalculateQvectors && (t0.fCalculate2DTest0AsFunctionOf[AFO_PT_ETA] || t0.fCalculate3DTest0AsFunctionOf[AFO_CENTRALITY_PT_ETA])) { + // Remark: For eta dependence I do not consider es.fCalculateEtaSeparations, because in this context that calculation is meaningless. + double kineArr[2] = {dPt, dEta}; + this->FillqvectorNdim(dPhi, kineArr, 2, PT_ETAq); + } + + // ***) pt-charge dependence: + if (qv.fCalculateQvectors && (t0.fCalculate2DTest0AsFunctionOf[AFO_PT_CHARGE] || t0.fCalculate3DTest0AsFunctionOf[AFO_CENTRALITY_PT_CHARGE]) && !es.fCalculateEtaSeparations) { + // In this branch I do not need eta separation, so the lighter call can be executed: + double kineArr[2] = {dPt, dCharge}; + this->FillqvectorNdim(dPhi, kineArr, 2, PT_CHARGEq); + } else if (es.fCalculateEtaSeparations) { // && TBI 20250527 finalize by checking if 2D pt_charge with eta separations was requested + // In this branch I do need eta separation, so the heavier call must be executed: + LOGF(info, "\033[1;33m%s at line %d: !!!! WARNING !!!! This branch is not finalized yet, i need to implement 2D objects also for eta separations, but it's unlikely I will ever need that in pracice. If I ever add it, just finalize the if statement, and comment in two lines below !!!! WARNING !!!! \033[0m", __FUNCTION__, __LINE__); + // double kineArr[2] = {dPt, dCharge}; + // this->FillqvectorNdim(dPhi, kineArr, 2, PT_CHARGEq, dEta); // TBI 20250620 enable when I finalize else if above + } + + // ***) eta-charge dependence: + if (qv.fCalculateQvectors && (t0.fCalculate2DTest0AsFunctionOf[AFO_ETA_CHARGE] || t0.fCalculate3DTest0AsFunctionOf[AFO_CENTRALITY_ETA_CHARGE])) { + // Remark: For eta dependence I do not consider es.fCalculateEtaSeparations, because in this context that calculation is meaningless. + double kineArr[2] = {dEta, dCharge}; + this->FillqvectorNdim(dPhi, kineArr, 2, ETA_CHARGEq); + } + + // ... + + // ** 3D: + // ***) pt-eta-charge dependence: + if (qv.fCalculateQvectors && (t0.fCalculate3DTest0AsFunctionOf[AFO_PT_ETA_CHARGE])) { + // Remark: For eta dependence I do not consider es.fCalculateEtaSeparations, because in this context that calculation is meaningless. + double kineArr[3] = {dPt, dEta, dCharge}; + this->FillqvectorNdim(dPhi, kineArr, 3, PT_ETA_CHARGEq); } - // *) Fill nested loops containers: + // *) Fill nested loops containers (integrated => I fill kine containers for nested loops in FillqvectorNdim(...)): if (nl.fCalculateNestedLoops || nl.fCalculateCustomNestedLoops) { this->FillNestedLoopsContainers(ebye.fSelectedTracks, dPhi, dPt, dEta); // all 4 arguments are passed by reference } @@ -16344,6 +18805,8 @@ void Steer(T1 const& collision, T2 const& bcs, T3 const& tracks) StartFunction(__FUNCTION__); } + // memStatus: ~50K (without differential q-vectors and eta separations) + // *) Dry run: if (tc.fDryRun) { EventCounterForDryRun(eFill); @@ -16352,6 +18815,8 @@ void Steer(T1 const& collision, T2 const& bcs, T3 const& tracks) return; } + // memStatus: ~50K (without differential q-vectors and eta separations) + // *) Reset event-by-event quantities: TBI 20240430 I do not need this call also here really, but it doesn't hurt either... ResetEventByEventQuantities(); @@ -16392,22 +18857,20 @@ void Steer(T1 const& collision, T2 const& bcs, T3 const& tracks) // *) Determine vertex z position: DetermineVertexZ(collision); + // memStatus: ~50K (without differential q-vectors and eta separations) + // *) Determine additional QA thingies: if (qa.fFillQAEventHistograms2D || qa.fFillQAParticleHistograms2D || qa.fFillQAParticleEventHistograms2D || qa.fFillQACorrelationsVsHistograms2D || qa.fFillQACorrelationsVsInteractionRateVsProfiles2D) { // Remark: I implement ideally here only the getters for which the subscription to additional non-standard tables was needed for QA purposes. DetermineQAThingies(collision, bcs); } - // memStatus: ~116 - // *) Fill event histograms before event cuts: if (eh.fFillEventHistograms || qa.fFillQAEventHistograms2D || qa.fFillQAParticleEventHistograms2D) { // Remark: I do not above the flag fFillQACorrelationsVsHistograms2D, because as a part of QA I calculate <2> only after cuts in any case FillEventHistograms(collision, tracks, eBefore); } - // memStatus: ~117 - // *) Print info on the current event number (total, before cuts): if (tc.fVerboseEventCounter) { PrintEventCounter(eBefore); @@ -16418,19 +18881,17 @@ void Steer(T1 const& collision, T2 const& bcs, T3 const& tracks) EventCutsCounters(collision, tracks); } - // memStatus: ~117 - // *) Event cuts: if (!EventCuts(collision, tracks, eCut)) { // Main call for event cuts return; } - // memStatus: ~117 + // memStatus: ~50K (without differential q-vectors and eta separations) // *) Main loop over particles: - MainLoopOverParticles(tracks); + MainLoopOverParticles(tracks); // memStatus: so here I invest ~20K, as of 20250530 - // memStatus: ~162 (all particle histograms), ~133 (only phi, pt, eta) + // memStatus: ~70K (without differential q-vectors and eta separations) // *) Determine multiplicity of this event, for all "vs. mult" results: DetermineMultiplicity(); @@ -16457,6 +18918,8 @@ void Steer(T1 const& collision, T2 const& bcs, T3 const& tracks) // *) Calculate everything for selected events and particles: CalculateEverything(); + // memStatus: ~72K (without differential q-vectors and eta separations) + // *) Reset event-by-event quantities: ResetEventByEventQuantities(); @@ -16481,12 +18944,20 @@ void Steer(T1 const& collision, T2 const& bcs, T3 const& tracks) tc.fTimer[eGlobal]->Continue(); // yes } - // memStatus: ~160 +- 5 - if (tc.fVerbose) { ExitFunction(__FUNCTION__); } + // memStatus (summary): Last update: 20250602 + // Remark: disable sequential bailout before doing this test (yes!) + all of UseSetBinLabel, ... UseDatabasetPDG + // ~46K (skeleton - literally) + // ~50K (dry run with 1D objects booked) + // ~70K (all object declaration besides kine objects (diff. q-vectors and eta separations) + all calculus and 1D histograms filled, trivial labels) + // ~70K (all object declaration + 1D kine objects (diff. q-vectors in coarse kine bins) + all calculus and 1D histograms filled, standard labels) + // ~80K (all object declaration + 1D + 2D kine objects (diff. q-vectors in fine kine bins) + all calculus and 1D histograms filled, standard labels) + // ~110K (all object declaration + 1D + 2D + 3D kine objects (diff. q-vectors in fine kine bins) + all calculus and 1D histograms filled, standard labels) + // ~125K (all object declaration + 1D + 2D + 3D kine objects (diff. q-vectors in fine kine bins) + all calculus and 1D histograms filled, Set_0 labels) + } // template void Steer(T1 const* collision, T2 const* tracks) #endif // PWGCF_MULTIPARTICLECORRELATIONS_CORE_MUPA_MEMBERFUNCTIONS_H_ diff --git a/PWGCF/MultiparticleCorrelations/Tasks/multiparticle-correlations-ab.cxx b/PWGCF/MultiparticleCorrelations/Tasks/multiparticle-correlations-ab.cxx index 344c45a7330..5b218fa1e5e 100644 --- a/PWGCF/MultiparticleCorrelations/Tasks/multiparticle-correlations-ab.cxx +++ b/PWGCF/MultiparticleCorrelations/Tasks/multiparticle-correlations-ab.cxx @@ -73,21 +73,27 @@ using Collision_QA = CollisionRec; // if I would need additional tables for QA, using TracksRec_QA = TracksRec; // if I would need additional tables for QA, just join 'em here with TracksRec // *) ROOT: -#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 std; // *) Enums: @@ -157,13 +163,13 @@ struct MultiparticleCorrelationsAB // this name is used in lower-case format to // *) Book all remaining objects; BookAndNestAllLists(); - BookResultsHistograms(); // yes, this one has to be booked first, because it defines the common binning for other groups of histograms TBI 20250412 this is true only if I can use Clone() + BookResultsHistograms(); // yes, this one has to be booked first, because it defines the common binning for other groups of histograms, w/ or w/o clonning BookQAHistograms(); BookEventHistograms(); BookEventCutsHistograms(); BookParticleHistograms(); - BookParticleCutsHistograms(); - BookQvectorHistograms(); + BookParticleCutsHistograms(); // memStatus: 50913 + BookQvectorHistograms(); // memStatus: 50913 (without differential q-vectors and eta separations) BookCorrelationsHistograms(); BookWeightsHistograms(); BookCentralityWeightsHistograms(); @@ -173,6 +179,10 @@ struct MultiparticleCorrelationsAB // this name is used in lower-case format to BookTest0Histograms(); BookEtaSeparationsHistograms(); BookTheRest(); // I book everything that was not sorted (yet) in the specific functions above + // memStatus: 50913 (without differential q-vectors and eta separations) + + // *) I can purge a few objects used for common consistent booking across different group of histograms: + PurgeAfterBooking(); // *) Insanity checks after booking: InsanityChecksAfterBooking(); // pointers of all local histograms, etc., are available, so I can do insanity checks directly on all booked objects From 37bbce6707c65bf8aa8cb8c4be7f3b518d4b7dcd Mon Sep 17 00:00:00 2001 From: Mario Ciacco Date: Mon, 23 Jun 2025 16:51:54 +0200 Subject: [PATCH 189/871] [PWGLF] fix histogram filling using eta (#11732) --- PWGLF/TableProducer/Strangeness/strangeTreeCreator.cxx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/PWGLF/TableProducer/Strangeness/strangeTreeCreator.cxx b/PWGLF/TableProducer/Strangeness/strangeTreeCreator.cxx index a18397f214e..455da9e0719 100644 --- a/PWGLF/TableProducer/Strangeness/strangeTreeCreator.cxx +++ b/PWGLF/TableProducer/Strangeness/strangeTreeCreator.cxx @@ -457,14 +457,16 @@ struct StrangeTreeCreator { } float ptPos = std::hypot(momPos[0], momPos[1]); + float pPos = std::hypot(momPos[0], momPos[1], momPos[2]); + float etaPos = 0.5 * std::log((pPos + momPos[2]) / (pPos - momPos[2])); float deltaMass = mK0Short - o2::constants::physics::MassK0; float massKineBias = deltaMass / kineFactor(momV0, momPos, momNeg, o2::constants::physics::MassPiMinus, o2::constants::physics::MassPiMinus, false); float massKineReso = deltaMass / kineFactor(momV0, momPos, momNeg, o2::constants::physics::MassPiMinus, o2::constants::physics::MassPiMinus, true); histos.fill(HIST("QA/massLambda"), centrality, ptV0, mLambda); histos.fill(HIST("QA/massK0s"), ptV0, mK0Short); - histos.fill(HIST("massKineBias"), ptPos, massKineBias); - histos.fill(HIST("massKineReso"), ptPos, massKineReso); + histos.fill(HIST("massKineBias"), etaPos, ptPos, massKineBias); + histos.fill(HIST("massKineReso"), etaPos, ptPos, massKineReso); CandidateV0 candV0; candV0.pt = matter > 0. ? ptV0 : -ptV0; From 3d4e672f24986a6b4a7fbf44f888eca82fa6f429 Mon Sep 17 00:00:00 2001 From: Phil Stahlhut <138057549+pstahlhu@users.noreply.github.com> Date: Mon, 23 Jun 2025 17:24:17 +0200 Subject: [PATCH 190/871] [PWGHF] XicToXiPiPi: Update KF variables and move residual/pull calulation to candidate creator (#11562) --- PWGHF/Core/HfMlResponseXicToXiPiPi.h | 28 +- PWGHF/D2H/Tasks/taskXicToXiPiPi.cxx | 70 ++- .../DataModel/CandidateReconstructionTables.h | 94 ++-- .../candidateCreatorXicToXiPiPi.cxx | 166 ++++--- .../candidateSelectorXicToXiPiPi.cxx | 16 +- .../TableProducer/treeCreatorXicToXiPiPi.cxx | 411 ++++++------------ PWGHF/Utils/utilsEvSelHf.h | 2 +- 7 files changed, 360 insertions(+), 427 deletions(-) diff --git a/PWGHF/Core/HfMlResponseXicToXiPiPi.h b/PWGHF/Core/HfMlResponseXicToXiPiPi.h index d8c040b28ce..64a3241485b 100644 --- a/PWGHF/Core/HfMlResponseXicToXiPiPi.h +++ b/PWGHF/Core/HfMlResponseXicToXiPiPi.h @@ -16,12 +16,12 @@ #ifndef PWGHF_CORE_HFMLRESPONSEXICTOXIPIPI_H_ #define PWGHF_CORE_HFMLRESPONSEXICTOXIPIPI_H_ +#include "PWGHF/Core/HfMlResponse.h" + #include #include #include -#include "PWGHF/Core/HfMlResponse.h" - // Fill the map of available input features // the key is the feature's name (std::string) // the value is the corresponding value in EnumInputFeatures @@ -62,10 +62,10 @@ enum class InputFeaturesXicToXiPiPi : uint8_t { decayLengthXYNormalised, cpa, cpaXY, - cosPaXi, - cosPaXYXi, - cosPaLambda, - cosPaXYLambda, + cpaXi, + cpaXYXi, + cpaLambda, + cpaXYLambda, impactParameterXi, impactParameterPi0, impactParameterPi1, @@ -119,10 +119,10 @@ class HfMlResponseXicToXiPiPi : public HfMlResponse CHECK_AND_FILL_VEC_XICTOXIPIPI(decayLengthXYNormalised); CHECK_AND_FILL_VEC_XICTOXIPIPI(cpa); CHECK_AND_FILL_VEC_XICTOXIPIPI(cpaXY); - CHECK_AND_FILL_VEC_XICTOXIPIPI(cosPaXi); - CHECK_AND_FILL_VEC_XICTOXIPIPI(cosPaXYXi); - CHECK_AND_FILL_VEC_XICTOXIPIPI(cosPaLambda); - CHECK_AND_FILL_VEC_XICTOXIPIPI(cosPaXYLambda); + CHECK_AND_FILL_VEC_XICTOXIPIPI(cpaXi); + CHECK_AND_FILL_VEC_XICTOXIPIPI(cpaXYXi); + CHECK_AND_FILL_VEC_XICTOXIPIPI(cpaLambda); + CHECK_AND_FILL_VEC_XICTOXIPIPI(cpaXYLambda); CHECK_AND_FILL_VEC_XICTOXIPIPI_FULL(candidate, impactParameterXi, impactParameter0); CHECK_AND_FILL_VEC_XICTOXIPIPI_FULL(candidate, impactParameterPi0, impactParameter1); CHECK_AND_FILL_VEC_XICTOXIPIPI_FULL(candidate, impactParameterPi1, impactParameter2); @@ -166,10 +166,10 @@ class HfMlResponseXicToXiPiPi : public HfMlResponse FILL_MAP_XICTOXIPIPI(decayLengthXYNormalised), FILL_MAP_XICTOXIPIPI(cpa), FILL_MAP_XICTOXIPIPI(cpaXY), - FILL_MAP_XICTOXIPIPI(cosPaXi), - FILL_MAP_XICTOXIPIPI(cosPaXYXi), - FILL_MAP_XICTOXIPIPI(cosPaLambda), - FILL_MAP_XICTOXIPIPI(cosPaXYLambda), + FILL_MAP_XICTOXIPIPI(cpaXi), + FILL_MAP_XICTOXIPIPI(cpaXYXi), + FILL_MAP_XICTOXIPIPI(cpaLambda), + FILL_MAP_XICTOXIPIPI(cpaXYLambda), FILL_MAP_XICTOXIPIPI(impactParameterXi), FILL_MAP_XICTOXIPIPI(impactParameterPi0), FILL_MAP_XICTOXIPIPI(impactParameterPi1), diff --git a/PWGHF/D2H/Tasks/taskXicToXiPiPi.cxx b/PWGHF/D2H/Tasks/taskXicToXiPiPi.cxx index d9958ba459f..9c42b24c133 100644 --- a/PWGHF/D2H/Tasks/taskXicToXiPiPi.cxx +++ b/PWGHF/D2H/Tasks/taskXicToXiPiPi.cxx @@ -17,7 +17,9 @@ /// \author Carolina Reetz , Heidelberg University /// \author Jaeyoon Cho , Inha University -#include +#include "PWGHF/Core/SelectorCuts.h" +#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "PWGHF/DataModel/CandidateSelectionTables.h" #include "CommonConstants/PhysicsConstants.h" #include "Framework/AnalysisTask.h" @@ -25,9 +27,7 @@ #include "Framework/O2DatabasePDGPlugin.h" #include "Framework/runDataProcessing.h" -#include "PWGHF/Core/SelectorCuts.h" -#include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" +#include using namespace o2; using namespace o2::aod; @@ -48,6 +48,8 @@ struct HfTaskXicToXiPiPi { // THnSparese for ML selection check Configurable enableTHn{"enableTHn", false, "Fill THnSparse for Xic"}; + const int nVarsMultiClass = 3; + Service pdg; Filter filterSelectCandidates = (aod::hf_sel_candidate_xic::isSelXicToXiPiPi >= selectionFlagXic); @@ -130,10 +132,9 @@ struct HfTaskXicToXiPiPi { registry.add("hMassXiPi2", "#Xi^{#plus}_{c} candidates;inv. mass #Xi^{#mp} #pi^{#pm} (prong 2) (GeV/#it{c}^{2});#it{p}_{T} (GeV/#it{c})", {HistType::kTH2F, {axisMassXiRes, axisPt}}); // KFParticle if (doprocessWithKFParticle || doprocessWithKFParticleAndML) { - registry.add("hChi2geoXi", "#Xi^{#plus}_{c} candidates;#Xi^{#mp} #chi^{2}_{geo};entries", {HistType::kTH2F, {axisChi2, axisPt}}); - registry.add("hChi2geoLam", "#Xi^{#plus}_{c} candidates;#Lambda #chi^{2}_{geo};entries", {HistType::kTH2F, {axisChi2, axisPt}}); - registry.add("hChi2topoToPV", "#Xi^{#plus}_{c} candidates;#Xi^{#plus}_{c} candidate #chi^{2}_{topo} to PV;entries", {HistType::kTH2F, {axisChi2, axisPt}}); - registry.add("hChi2topoXiToXicPlus", "#Xi^{#plus}_{c} candidates;#Xi^{#mp} candidate #chi^{2}_{topo} to #Xi^{#plus}_{c};entries", {HistType::kTH2F, {axisChi2, axisPt}}); + registry.add("hChi2GeoXi", "#Xi^{#plus}_{c} candidates;#chi^{2}_{geo} (#Xi^{#mp});entries", {HistType::kTH2F, {axisChi2, axisPt}}); + registry.add("hChi2GeoLam", "#Xi^{#plus}_{c} candidates;#chi^{2}_{geo} (#Lambda);entries", {HistType::kTH2F, {axisChi2, axisPt}}); + registry.add("hChi2TopoXicPlusToPV", "#Xi^{#plus}_{c} candidates;#chi^{2}_{topo} (#Xi^{#plus}_{c} #rightarrow PV);entries", {HistType::kTH2F, {axisChi2, axisPt}}); } } @@ -202,14 +203,12 @@ struct HfTaskXicToXiPiPi { registry.add("hMassXiPi2RecBg", "#Xi^{#plus}_{c} candidates (unmatched);inv. mass #Xi^{#mp} #pi^{#pm} (prong 2) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {{300, 1.0, 2.0}, axisPt}}); // MC reconstructed with KFParticle if (doprocessMcWithKFParticle || doprocessMcWithKFParticleAndML) { - registry.add("hChi2topoToPVRecSig", "#Xi^{#plus}_{c} candidates (matched);#Xi^{#plus}_{c} candidate #chi^{2}_{topo} to PV;entries", {HistType::kTH2F, {axisChi2, axisPt}}); - registry.add("hChi2topoToPVRecBg", "#Xi^{#plus}_{c} candidates (unmatched);#Xi^{#plus}_{c} candidate #chi^{2}_{topo} to PV;entries", {HistType::kTH2F, {axisChi2, axisPt}}); - registry.add("hChi2geoXiRecSig", "#Xi^{#plus}_{c} candidates (matched);#Xi^{#mp} #chi^{2}_{geo};entries", {HistType::kTH2F, {axisChi2, axisPt}}); - registry.add("hChi2geoXiRecBg", "#Xi^{#plus}_{c} candidates (unmatched);#Xi^{#mp} #chi^{2}_{geo};entries", {HistType::kTH2F, {axisChi2, axisPt}}); - registry.add("hChi2geoLamRecSig", "#Xi^{#plus}_{c} candidates (matched);#Lambda #chi^{2}_{geo};entries", {HistType::kTH2F, {axisChi2, axisPt}}); - registry.add("hChi2geoLamRecBg", "#Xi^{#plus}_{c} candidates (unmatched);#Lambda #chi^{2}_{geo};entries", {HistType::kTH2F, {axisChi2, axisPt}}); - registry.add("hChi2topoXiToXicPlusRecSig", "#Xi^{#plus}_{c} candidates (matched);#Xi^{#mp} candidate #chi^{2}_{topo} to #Xi^{#plus}_{c};entries", {HistType::kTH2F, {axisChi2, axisPt}}); - registry.add("hChi2topoXiToXicPlusRecBg", "#Xi^{#plus}_{c} candidates (unmatched);#Xi^{#mp} candidate #chi^{2}_{topo} to #Xi^{#plus}_{c};entries", {HistType::kTH2F, {axisChi2, axisPt}}); + registry.add("hChi2GeoXiRecSig", "#Xi^{#plus}_{c} candidates (matched);#chi^{2}_{geo} (#Xi^{#mp});entries", {HistType::kTH2F, {axisChi2, axisPt}}); + registry.add("hChi2GeoXiRecBg", "#Xi^{#plus}_{c} candidates (unmatched);#chi^{2}_{geo} (#Xi^{#mp});entries", {HistType::kTH2F, {axisChi2, axisPt}}); + registry.add("hChi2GeoLamRecSig", "#Xi^{#plus}_{c} candidates (matched);#chi^{2}_{geo} (#Lambda);entries", {HistType::kTH2F, {axisChi2, axisPt}}); + registry.add("hChi2GeoLamRecBg", "#Xi^{#plus}_{c} candidates (unmatched);#chi^{2}_{geo} (#Lambda);entries", {HistType::kTH2F, {axisChi2, axisPt}}); + registry.add("hChi2TopoXicPlusToPVRecSig", "#Xi^{#plus}_{c} candidates (matched);#chi^{2}_{topo} (#Xi^{#plus}_{c} #rightarrow PV);entries", {HistType::kTH2F, {axisChi2, axisPt}}); + registry.add("hChi2TopoXicPlusToPVRecBg", "#Xi^{#plus}_{c} candidates (unmatched);#chi^{2}_{topo} (#Xi^{#plus}_{c} #rightarrow PV);entries", {HistType::kTH2F, {axisChi2, axisPt}}); } // MC generated registry.add("hPtProng0Gen", "MC particles (generated);prong 0 (#Xi^{#mp}) #it{p}_{T}^{gen} (GeV/#it{c});entries", {HistType::kTH2F, {{300, 0., 30.}, axisPt}}); @@ -284,7 +283,7 @@ struct HfTaskXicToXiPiPi { if (scoreSize > 0) { outputBkg = candidate.mlProbXicToXiPiPi()[0]; outputPrompt = candidate.mlProbXicToXiPiPi()[1]; - if (scoreSize == 3) { + if (scoreSize == nVarsMultiClass) { outputFD = candidate.mlProbXicToXiPiPi()[2]; } } @@ -343,19 +342,18 @@ struct HfTaskXicToXiPiPi { registry.fill(HIST("hImpParErr"), candidate.errorImpactParameter1(), ptCandXic); registry.fill(HIST("hImpParErr"), candidate.errorImpactParameter2(), ptCandXic); registry.fill(HIST("hChi2PCA"), candidate.chi2PCA(), ptCandXic); - registry.fill(HIST("hCPAXi"), candidate.cosPaXi(), ptCandXic); - registry.fill(HIST("hCPAxyXi"), candidate.cosPaXYXi(), ptCandXic); - registry.fill(HIST("hCPALambda"), candidate.cosPaLambda(), ptCandXic); - registry.fill(HIST("hCPAxyLambda"), candidate.cosPaLambda(), ptCandXic); + registry.fill(HIST("hCPAXi"), candidate.cpaXi(), ptCandXic); + registry.fill(HIST("hCPAxyXi"), candidate.cpaXYXi(), ptCandXic); + registry.fill(HIST("hCPALambda"), candidate.cpaLambda(), ptCandXic); + registry.fill(HIST("hCPAxyLambda"), candidate.cpaLambda(), ptCandXic); registry.fill(HIST("hMassXiPi1"), candidate.invMassXiPi0(), ptCandXic); registry.fill(HIST("hMassXiPi2"), candidate.invMassXiPi1(), ptCandXic); // fill KFParticle specific histograms if constexpr (useKfParticle) { - registry.fill(HIST("hChi2topoToPV"), candidate.chi2TopoXicPlusToPV(), ptCandXic); - registry.fill(HIST("hChi2topoXiToXicPlus"), candidate.chi2TopoXiToXicPlus(), ptCandXic); - registry.fill(HIST("hChi2geoXi"), candidate.kfCascadeChi2(), ptCandXic); - registry.fill(HIST("hChi2geoLam"), candidate.kfV0Chi2(), ptCandXic); + registry.fill(HIST("hChi2GeoXi"), candidate.kfCascadeChi2(), ptCandXic); + registry.fill(HIST("hChi2GeoLam"), candidate.kfV0Chi2(), ptCandXic); + registry.fill(HIST("hChi2TopoXicPlusToPV"), candidate.chi2TopoXicPlusToPV(), ptCandXic); } // fill THnSparse @@ -418,17 +416,16 @@ struct HfTaskXicToXiPiPi { registry.fill(HIST("hImpParErrRecSig"), candidate.errorImpactParameter1(), ptCandXic); registry.fill(HIST("hImpParErrRecSig"), candidate.errorImpactParameter2(), ptCandXic); registry.fill(HIST("hChi2PCARecSig"), candidate.chi2PCA(), ptCandXic); - registry.fill(HIST("hCPAXiRecSig"), candidate.cosPaXi(), ptCandXic); - registry.fill(HIST("hCPAxyXiRecSig"), candidate.cosPaXYXi(), ptCandXic); - registry.fill(HIST("hCPALambdaRecSig"), candidate.cosPaLambda(), ptCandXic); - registry.fill(HIST("hCPAxyLambdaRecSig"), candidate.cosPaLambda(), ptCandXic); + registry.fill(HIST("hCPAXiRecSig"), candidate.cpaXi(), ptCandXic); + registry.fill(HIST("hCPAxyXiRecSig"), candidate.cpaXYXi(), ptCandXic); + registry.fill(HIST("hCPALambdaRecSig"), candidate.cpaLambda(), ptCandXic); + registry.fill(HIST("hCPAxyLambdaRecSig"), candidate.cpaLambda(), ptCandXic); // fill KFParticle specific histograms if constexpr (useKfParticle) { - registry.fill(HIST("hChi2topoToPVRecSig"), candidate.chi2TopoXicPlusToPV(), ptCandXic); - registry.fill(HIST("hChi2topoXiToXicPlusRecSig"), candidate.chi2TopoXiToXicPlus(), ptCandXic); registry.fill(HIST("hChi2geoXiRecSig"), candidate.kfCascadeChi2(), ptCandXic); registry.fill(HIST("hChi2geoLamRecSig"), candidate.kfV0Chi2(), ptCandXic); + registry.fill(HIST("hChi2TopoXicPlusToPVRecSig"), candidate.chi2TopoXicPlusToPV(), ptCandXic); } } else { registry.fill(HIST("hPtRecBg"), ptCandXic); @@ -457,17 +454,16 @@ struct HfTaskXicToXiPiPi { registry.fill(HIST("hImpParErrRecBg"), candidate.errorImpactParameter1(), ptCandXic); registry.fill(HIST("hImpParErrRecBg"), candidate.errorImpactParameter2(), ptCandXic); registry.fill(HIST("hChi2PCARecBg"), candidate.chi2PCA(), ptCandXic); - registry.fill(HIST("hCPAXiRecBg"), candidate.cosPaXi(), ptCandXic); - registry.fill(HIST("hCPAxyXiRecBg"), candidate.cosPaXYXi(), ptCandXic); - registry.fill(HIST("hCPALambdaRecBg"), candidate.cosPaLambda(), ptCandXic); - registry.fill(HIST("hCPAxyLambdaRecBg"), candidate.cosPaLambda(), ptCandXic); + registry.fill(HIST("hCPAXiRecBg"), candidate.cpaXi(), ptCandXic); + registry.fill(HIST("hCPAxyXiRecBg"), candidate.cpaXYXi(), ptCandXic); + registry.fill(HIST("hCPALambdaRecBg"), candidate.cpaLambda(), ptCandXic); + registry.fill(HIST("hCPAxyLambdaRecBg"), candidate.cpaLambda(), ptCandXic); // fill KFParticle specific histograms if constexpr (useKfParticle) { - registry.fill(HIST("hChi2topoToPVRecBg"), candidate.chi2TopoXicPlusToPV(), ptCandXic); - registry.fill(HIST("hChi2topoXiToXicPlusRecBg"), candidate.chi2TopoXiToXicPlus(), ptCandXic); registry.fill(HIST("hChi2geoXiRecBg"), candidate.kfCascadeChi2(), ptCandXic); registry.fill(HIST("hChi2geoLamRecBg"), candidate.kfV0Chi2(), ptCandXic); + registry.fill(HIST("hChi2TopoXicPlusToPVRecBg"), candidate.chi2TopoXicPlusToPV(), ptCandXic); } } diff --git a/PWGHF/DataModel/CandidateReconstructionTables.h b/PWGHF/DataModel/CandidateReconstructionTables.h index 83b9a594912..fd296e328f6 100644 --- a/PWGHF/DataModel/CandidateReconstructionTables.h +++ b/PWGHF/DataModel/CandidateReconstructionTables.h @@ -1767,24 +1767,24 @@ namespace hf_cand_xic_to_xi_pi_pi { DECLARE_SOA_INDEX_COLUMN_FULL(Pi0, pi0, int, Tracks, "_pi0"); DECLARE_SOA_INDEX_COLUMN_FULL(Pi1, pi1, int, Tracks, "_pi1"); +DECLARE_SOA_COLUMN(Sign, sign, float); +DECLARE_SOA_COLUMN(InvMassXicPlus, invMassXicPlus, float); +DECLARE_SOA_COLUMN(InvMassXi, invMassXi, float); +DECLARE_SOA_COLUMN(InvMassLambda, invMassLambda, float); +DECLARE_SOA_COLUMN(InvMassXiPi0, invMassXiPi0, float); +DECLARE_SOA_COLUMN(InvMassXiPi1, invMassXiPi1, float); DECLARE_SOA_COLUMN(XPvErr, xPvErr, float); DECLARE_SOA_COLUMN(YPvErr, yPvErr, float); DECLARE_SOA_COLUMN(ZPvErr, zPvErr, float); DECLARE_SOA_COLUMN(XSvErr, xSvErr, float); DECLARE_SOA_COLUMN(YSvErr, ySvErr, float); DECLARE_SOA_COLUMN(ZSvErr, zSvErr, float); -DECLARE_SOA_COLUMN(CosPaXi, cosPaXi, float); -DECLARE_SOA_COLUMN(CosPaXYXi, cosPaXYXi, float); -DECLARE_SOA_COLUMN(CosPaLambda, cosPaLambda, float); -DECLARE_SOA_COLUMN(CosPaXYLambda, cosPaXYLambda, float); -DECLARE_SOA_COLUMN(CosPaLambdaToXi, cosPaLambdaToXi, float); -DECLARE_SOA_COLUMN(CosPaXYLambdaToXi, cosPaXYLambdaToXi, float); -DECLARE_SOA_COLUMN(InvMassXicPlus, invMassXicPlus, float); -DECLARE_SOA_COLUMN(InvMassXi, invMassXi, float); -DECLARE_SOA_COLUMN(InvMassLambda, invMassLambda, float); -DECLARE_SOA_COLUMN(Sign, sign, float); -DECLARE_SOA_COLUMN(InvMassXiPi0, invMassXiPi0, float); -DECLARE_SOA_COLUMN(InvMassXiPi1, invMassXiPi1, float); +DECLARE_SOA_COLUMN(CpaXi, cpaXi, float); +DECLARE_SOA_COLUMN(CpaXYXi, cpaXYXi, float); +DECLARE_SOA_COLUMN(CpaLambda, cpaLambda, float); +DECLARE_SOA_COLUMN(CpaXYLambda, cpaXYLambda, float); +DECLARE_SOA_COLUMN(CpaLambdaToXi, cpaLambdaToXi, float); +DECLARE_SOA_COLUMN(CpaXYLambdaToXi, cpaXYLambdaToXi, float); DECLARE_SOA_COLUMN(PBachelorPi, pBachelorPi, float); DECLARE_SOA_COLUMN(PPiFromLambda, pPiFromLambda, float); DECLARE_SOA_COLUMN(PPrFromLambda, pPrFromLambda, float); @@ -1796,16 +1796,20 @@ DECLARE_SOA_COLUMN(DcaBachelorToPV, dcaBachelorToPV, float); DECLARE_SOA_COLUMN(DcaXYCascToPV, dcaXYCascToPV, float); DECLARE_SOA_COLUMN(DcaZCascToPV, dcaZCascToPV, float); // KF specific columns -DECLARE_SOA_COLUMN(DcaXYPi0Pi1, dcaXYPi0Pi1, float); -DECLARE_SOA_COLUMN(DcaXYPi0Xi, dcaXYPi0Xi, float); -DECLARE_SOA_COLUMN(DcaXYPi1Xi, dcaXYPi1Xi, float); +DECLARE_SOA_COLUMN(Chi2TopoXicPlusToPV, chi2TopoXicPlusToPV, float); +DECLARE_SOA_COLUMN(Chi2TopoXicPlusToPVBefConst, chi2TopoXicPlusToPVBefConst, float); +DECLARE_SOA_COLUMN(Chi2PrimXi, chi2PrimXi, float); +DECLARE_SOA_COLUMN(Chi2PrimPi0, chi2PrimPi0, float); +DECLARE_SOA_COLUMN(Chi2PrimPi1, chi2PrimPi1, float); +DECLARE_SOA_COLUMN(Chi2DevPi0Pi1, chi2DevPi0Pi1, float); +DECLARE_SOA_COLUMN(Chi2DevPi0Xi, chi2DevPi0Xi, float); +DECLARE_SOA_COLUMN(Chi2DevPi1Xi, chi2DevPi1Xi, float); DECLARE_SOA_COLUMN(DcaPi0Pi1, dcaPi0Pi1, float); DECLARE_SOA_COLUMN(DcaPi0Xi, dcaPi0Xi, float); DECLARE_SOA_COLUMN(DcaPi1Xi, dcaPi1Xi, float); -DECLARE_SOA_COLUMN(Chi2TopoXicPlusToPV, chi2TopoXicPlusToPV, float); -DECLARE_SOA_COLUMN(Chi2TopoXicPlusToPVBeforeConstraint, chi2TopoXicPlusToPVBeforeConstraint, float); -DECLARE_SOA_COLUMN(Chi2TopoXiToXicPlus, chi2TopoXiToXicPlus, float); -DECLARE_SOA_COLUMN(Chi2TopoXiToXicPlusBeforeConstraint, chi2TopoXiToXicPlusBeforeConstraint, float); +DECLARE_SOA_COLUMN(DcaXYPi0Pi1, dcaXYPi0Pi1, float); +DECLARE_SOA_COLUMN(DcaXYPi0Xi, dcaXYPi0Xi, float); +DECLARE_SOA_COLUMN(DcaXYPi1Xi, dcaXYPi1Xi, float); DECLARE_SOA_COLUMN(KfDecayLength, kfDecayLength, float); DECLARE_SOA_COLUMN(KfDecayLengthNormalised, kfDecayLengthNormalised, float); DECLARE_SOA_COLUMN(KfDecayLengthXY, kfDecayLengthXY, float); @@ -1826,6 +1830,21 @@ DECLARE_SOA_COLUMN(FlagMcMatchRec, flagMcMatchRec, int8_t); // reconstruction le DECLARE_SOA_COLUMN(FlagMcMatchGen, flagMcMatchGen, int8_t); // generator level DECLARE_SOA_COLUMN(OriginRec, originRec, int8_t); DECLARE_SOA_COLUMN(OriginGen, originGen, int8_t); +// Residuals and pulls +DECLARE_SOA_COLUMN(PtResidual, ptResidual, float); +DECLARE_SOA_COLUMN(PResidual, pResidual, float); +DECLARE_SOA_COLUMN(XPvResidual, xPvResidual, float); +DECLARE_SOA_COLUMN(YPvResidual, yPvResidual, float); +DECLARE_SOA_COLUMN(ZPvResidual, zPvResidual, float); +DECLARE_SOA_COLUMN(XPvPull, xPvPull, float); +DECLARE_SOA_COLUMN(YPvPull, yPvPull, float); +DECLARE_SOA_COLUMN(ZPvPull, zPvPull, float); +DECLARE_SOA_COLUMN(XSvResidual, xSvResidual, float); +DECLARE_SOA_COLUMN(YSvResidual, ySvResidual, float); +DECLARE_SOA_COLUMN(ZSvResidual, zSvResidual, float); +DECLARE_SOA_COLUMN(XSvPull, xSvPull, float); +DECLARE_SOA_COLUMN(YSvPull, ySvPull, float); +DECLARE_SOA_COLUMN(ZSvPull, zSvPull, float); // Dynamic columns DECLARE_SOA_DYNAMIC_COLUMN(PProng0, pProng0, //! [](float px, float py, float pz) -> float { return RecoDecay::p(px, py, pz); }); @@ -1859,7 +1878,7 @@ DECLARE_SOA_TABLE(HfCandXicBase, "AOD", "HFCANDXICBASE", hf_cand::ErrorImpactParameter0, hf_cand::ErrorImpactParameter1, hf_cand::ErrorImpactParameter2, // cascade specific columns hf_cand_xic_to_xi_pi_pi::PBachelorPi, hf_cand_xic_to_xi_pi_pi::PPiFromLambda, hf_cand_xic_to_xi_pi_pi::PPrFromLambda, - hf_cand_xic_to_xi_pi_pi::CosPaXi, hf_cand_xic_to_xi_pi_pi::CosPaXYXi, hf_cand_xic_to_xi_pi_pi::CosPaLambda, hf_cand_xic_to_xi_pi_pi::CosPaXYLambda, hf_cand_xic_to_xi_pi_pi::CosPaLambdaToXi, hf_cand_xic_to_xi_pi_pi::CosPaXYLambdaToXi, + hf_cand_xic_to_xi_pi_pi::CpaXi, hf_cand_xic_to_xi_pi_pi::CpaXYXi, hf_cand_xic_to_xi_pi_pi::CpaLambda, hf_cand_xic_to_xi_pi_pi::CpaXYLambda, hf_cand_xic_to_xi_pi_pi::CpaLambdaToXi, hf_cand_xic_to_xi_pi_pi::CpaXYLambdaToXi, hf_cand_xic_to_xi_pi_pi::InvMassXi, hf_cand_xic_to_xi_pi_pi::InvMassLambda, hf_cand_xic_to_xi_pi_pi::InvMassXiPi0, hf_cand_xic_to_xi_pi_pi::InvMassXiPi1, // DCA hf_cand_xic_to_xi_pi_pi::DcaXiDaughters, hf_cand_xic_to_xi_pi_pi::DcaV0Daughters, hf_cand_xic_to_xi_pi_pi::DcaPosToPV, hf_cand_xic_to_xi_pi_pi::DcaNegToPV, hf_cand_xic_to_xi_pi_pi::DcaBachelorToPV, hf_cand_xic_to_xi_pi_pi::DcaXYCascToPV, hf_cand_xic_to_xi_pi_pi::DcaZCascToPV, @@ -1897,26 +1916,47 @@ DECLARE_SOA_TABLE(HfCandXicBase, "AOD", "HFCANDXICBASE", // extended table with expression columns that can be used as arguments of dynamic columns DECLARE_SOA_EXTENDED_TABLE_USER(HfCandXicExt, HfCandXicBase, "HFCANDXICEXT", hf_cand_3prong::Px, hf_cand_3prong::Py, hf_cand_3prong::Pz); - using HfCandXic = HfCandXicExt; +// table with KF-specific variables DECLARE_SOA_TABLE(HfCandXicKF, "AOD", "HFCANDXICKF", - cascdata::KFCascadeChi2, cascdata::KFV0Chi2, hf_cand_xic_to_xi_pi_pi::KfDecayLength, hf_cand_xic_to_xi_pi_pi::KfDecayLengthNormalised, hf_cand_xic_to_xi_pi_pi::KfDecayLengthXY, hf_cand_xic_to_xi_pi_pi::KfDecayLengthXYNormalised, - hf_cand_xic_to_xi_pi_pi::Chi2TopoXicPlusToPVBeforeConstraint, hf_cand_xic_to_xi_pi_pi::Chi2TopoXicPlusToPV, hf_cand_xic_to_xi_pi_pi::Chi2TopoXiToXicPlusBeforeConstraint, hf_cand_xic_to_xi_pi_pi::Chi2TopoXiToXicPlus, - hf_cand_xic_to_xi_pi_pi::DcaXYPi0Pi1, hf_cand_xic_to_xi_pi_pi::DcaXYPi0Xi, hf_cand_xic_to_xi_pi_pi::DcaXYPi1Xi, - hf_cand_xic_to_xi_pi_pi::DcaPi0Pi1, hf_cand_xic_to_xi_pi_pi::DcaPi0Xi, hf_cand_xic_to_xi_pi_pi::DcaPi1Xi); + cascdata::KFCascadeChi2, cascdata::KFV0Chi2, + hf_cand_xic_to_xi_pi_pi::Chi2TopoXicPlusToPVBefConst, hf_cand_xic_to_xi_pi_pi::Chi2TopoXicPlusToPV, + hf_cand_xic_to_xi_pi_pi::Chi2PrimXi, hf_cand_xic_to_xi_pi_pi::Chi2PrimPi0, hf_cand_xic_to_xi_pi_pi::Chi2PrimPi1, + hf_cand_xic_to_xi_pi_pi::Chi2DevPi0Pi1, hf_cand_xic_to_xi_pi_pi::Chi2DevPi0Xi, hf_cand_xic_to_xi_pi_pi::Chi2DevPi1Xi, + hf_cand_xic_to_xi_pi_pi::DcaPi0Pi1, hf_cand_xic_to_xi_pi_pi::DcaPi0Xi, hf_cand_xic_to_xi_pi_pi::DcaPi1Xi, + hf_cand_xic_to_xi_pi_pi::DcaXYPi0Pi1, hf_cand_xic_to_xi_pi_pi::DcaXYPi0Xi, hf_cand_xic_to_xi_pi_pi::DcaXYPi1Xi); // table with results of reconstruction level MC matching -DECLARE_SOA_TABLE(HfCandXicMcRec, "AOD", "HFCANDXICMCREC", //! +DECLARE_SOA_TABLE(HfCandXicMcRec, "AOD", "HFCANDXICMCREC", hf_cand_xic_to_xi_pi_pi::FlagMcMatchRec, hf_cand_xic_to_xi_pi_pi::OriginRec); + // table with results of generator level MC matching -DECLARE_SOA_TABLE(HfCandXicMcGen, "AOD", "HFCANDXICMCGEN", //! +DECLARE_SOA_TABLE(HfCandXicMcGen, "AOD", "HFCANDXICMCGEN", hf_cand_xic_to_xi_pi_pi::FlagMcMatchGen, hf_cand_xic_to_xi_pi_pi::OriginGen, hf_cand::PdgBhadMotherPart); +// table with residuals and pulls of PV +DECLARE_SOA_TABLE(HfCandXicResid, "AOD", "HFCANDXICRESID", + hf_cand_xic_to_xi_pi_pi::OriginGen, + hf_cand_xic_to_xi_pi_pi::PResidual, + hf_cand_xic_to_xi_pi_pi::PtResidual, + hf_cand_xic_to_xi_pi_pi::XPvResidual, + hf_cand_xic_to_xi_pi_pi::YPvResidual, + hf_cand_xic_to_xi_pi_pi::ZPvResidual, + hf_cand_xic_to_xi_pi_pi::XPvPull, + hf_cand_xic_to_xi_pi_pi::YPvPull, + hf_cand_xic_to_xi_pi_pi::ZPvPull, + hf_cand_xic_to_xi_pi_pi::XSvResidual, + hf_cand_xic_to_xi_pi_pi::YSvResidual, + hf_cand_xic_to_xi_pi_pi::ZSvResidual, + hf_cand_xic_to_xi_pi_pi::XSvPull, + hf_cand_xic_to_xi_pi_pi::YSvPull, + hf_cand_xic_to_xi_pi_pi::ZSvPull); + // specific chic candidate properties namespace hf_cand_chic { diff --git a/PWGHF/TableProducer/candidateCreatorXicToXiPiPi.cxx b/PWGHF/TableProducer/candidateCreatorXicToXiPiPi.cxx index 69fea11d5c9..3f710601315 100644 --- a/PWGHF/TableProducer/candidateCreatorXicToXiPiPi.cxx +++ b/PWGHF/TableProducer/candidateCreatorXicToXiPiPi.cxx @@ -21,37 +21,37 @@ #define HomogeneousField // o2-linter: disable=name/macro (required by KFParticle) #endif -#include -#include -#include -#include - -#include -#include -#include -#include -#include +#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "PWGHF/Utils/utilsBfieldCCDB.h" +#include "PWGHF/Utils/utilsEvSelHf.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" +#include "PWGLF/DataModel/mcCentrality.h" -#include +#include "Common/Core/trackUtilities.h" +#include "Common/DataModel/CollisionAssociationTables.h" +#include "Tools/KFparticle/KFUtilities.h" #include "CommonConstants/PhysicsConstants.h" #include "DCAFitter/DCAFitterN.h" #include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" +#include "Framework/RunningWorkflowInfo.h" #include "Framework/runDataProcessing.h" #include "ReconstructionDataFormats/DCA.h" -#include "Framework/RunningWorkflowInfo.h" -#include "Common/Core/trackUtilities.h" -#include "Common/DataModel/CollisionAssociationTables.h" -#include "Tools/KFparticle/KFUtilities.h" +#include -#include "PWGLF/DataModel/LFStrangenessTables.h" -#include "PWGLF/DataModel/mcCentrality.h" +#include +#include +#include +#include +#include -#include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/Utils/utilsBfieldCCDB.h" -#include "PWGHF/Utils/utilsEvSelHf.h" +#include +#include +#include +#include +#include using namespace o2; using namespace o2::constants::physics; @@ -88,7 +88,6 @@ struct HfCandidateCreatorXicToXiPiPi { // KFParticle Configurable useXiMassConstraint{"useXiMassConstraint", true, "Use mass constraint for Xi"}; Configurable constrainXicPlusToPv{"constrainXicPlusToPv", false, "Constrain XicPlus to PV"}; - Configurable constrainXiToXicPlus{"constrainXiToXicPlus", false, "Constrain Xi to XicPlus"}; Configurable kfConstructMethod{"kfConstructMethod", 2, "Construct method of XicPlus: 0 fast mathematics without constraint of fixed daughter particle masses, 2 daughter particle masses stay fixed in construction process"}; Configurable rejDiffCollTrack{"rejDiffCollTrack", true, "Reject tracks coming from different collisions (effective only for KFParticle w/o derived data)"}; @@ -128,7 +127,9 @@ struct HfCandidateCreatorXicToXiPiPi { // add histograms to registry if (fillHistograms) { // counter - registry.add("hVertexerType", "Use KF or DCAFitterN;Vertexer type;entries", {HistType::kTH1F, {{2, -0.5, 1.5}}}); // See o2::aod::hf_cand::VertexerType + registry.add("hVertexerType", "Use DCAFitter or KFParticle;;entries", {HistType::kTH1F, {{2, -0.5, 1.5}}}); + registry.get(HIST("hVertexerType"))->GetXaxis()->SetBinLabel(1 + aod::hf_cand::VertexerType::DCAFitter, "DCAFitter"); + registry.get(HIST("hVertexerType"))->GetXaxis()->SetBinLabel(1 + aod::hf_cand::VertexerType::KfParticle, "KFParticle"); registry.add("hCandCounter", "hCandCounter", {HistType::kTH1F, {{4, -0.5, 3.5}}}); registry.get(HIST("hCandCounter"))->GetXaxis()->SetBinLabel(1 + TotalSkimmedTriplets, "total"); registry.get(HIST("hCandCounter"))->GetXaxis()->SetBinLabel(1 + SelEvent, "Event selected"); @@ -524,41 +525,22 @@ struct HfCandidateCreatorXicToXiPiPi { registry.fill(HIST("hCandCounter"), VertexFit); } - // get geometrical chi2 of XicPlus + // get chi2 values float chi2GeoXicPlus = kfXicPlus.GetChi2() / kfXicPlus.GetNDF(); + float chi2PrimXi = kfXi.GetDeviationFromVertex(kfPv); + float chi2PrimPi0 = kfCharmBachelor0.GetDeviationFromVertex(kfPv); + float chi2PrimPi1 = kfCharmBachelor1.GetDeviationFromVertex(kfPv); // topological constraint of Xic to PV - float chi2topoXicPlusToPVBeforeConstraint = kfXicPlus.GetDeviationFromVertex(kfPv); + float chi2TopoXicPlusToPVBefConst = kfXicPlus.GetDeviationFromVertex(kfPv); KFParticle kfXicPlusToPV = kfXicPlus; kfXicPlusToPV.SetProductionVertex(kfPv); - float chi2topoXicPlusToPV = kfXicPlusToPV.GetChi2() / kfXicPlusToPV.GetNDF(); + float chi2TopoXicPlusToPV = kfXicPlusToPV.GetChi2() / kfXicPlusToPV.GetNDF(); if (constrainXicPlusToPv) { kfXicPlus = kfXicPlusToPV; kfXicPlus.TransportToDecayVertex(); } - // topological constraint of Xi to XicPlus - float chi2topoXiToXicPlusBeforeConstraint = kfXi.GetDeviationFromVertex(kfXicPlus); - KFParticle kfXiToXicPlus = kfXi; - kfXiToXicPlus.SetProductionVertex(kfXicPlus); - float chi2topoXiToXicPlus = kfXiToXicPlus.GetChi2() / kfXiToXicPlus.GetNDF(); - kfXiToXicPlus.TransportToDecayVertex(); - if (constrainXiToXicPlus) { - KFParticle kfXicPlusWithXiToXicPlus; - const KFParticle* kfDaughtersXicPlusWithXiToXicPlus[3] = {&kfCharmBachelor0, &kfCharmBachelor1, &kfXiToXicPlus}; - kfXicPlusWithXiToXicPlus.SetConstructMethod(kfConstructMethod); - try { - kfXicPlusWithXiToXicPlus.Construct(kfDaughtersXicPlusWithXiToXicPlus, 3); - } catch (std::runtime_error& e) { - LOG(debug) << "Failed to construct XicPlus with Xi connstrained to XicPlus: " << e.what(); - continue; - } - kfXicPlus = kfXicPlusWithXiToXicPlus; - } - - // get covariance matrix of XicPlus - auto covMatrixXicPlus = kfXicPlus.CovarianceMatrix(); - //---------------------calculate physical parameters of XicPlus candidate---------------------- // sign of charm baryon int signXic = casc.sign() < 0 ? +1 : -1; @@ -589,13 +571,18 @@ struct HfCandidateCreatorXicToXiPiPi { float cpaLambdaToXi = RecoDecay::cpa(vertexCasc, vertexV0, pVecV0); float cpaXYLambdaToXi = RecoDecay::cpaXY(vertexCasc, vertexV0, pVecV0); + // get chi2 deviation of Pi0-Pi1, Pi0-Xi, Pi1-Xi + float chi2DevPi0Pi1 = kfCharmBachelor0.GetDeviationFromParticle(kfCharmBachelor1); + float chi2DevPi0Xi = kfCharmBachelor0.GetDeviationFromParticle(kfXi); + float chi2DevPi1Xi = kfCharmBachelor1.GetDeviationFromParticle(kfXi); + // get DCAs of Pi0-Pi1, Pi0-Xi, Pi1-Xi - float dcaXYPi0Pi1 = kfCharmBachelor0.GetDistanceFromParticleXY(kfCharmBachelor1); - float dcaXYPi0Xi = kfCharmBachelor0.GetDistanceFromParticleXY(kfXi); - float dcaXYPi1Xi = kfCharmBachelor1.GetDistanceFromParticleXY(kfXi); float dcaPi0Pi1 = kfCharmBachelor0.GetDistanceFromParticle(kfCharmBachelor1); float dcaPi0Xi = kfCharmBachelor0.GetDistanceFromParticle(kfXi); float dcaPi1Xi = kfCharmBachelor1.GetDistanceFromParticle(kfXi); + float dcaXYPi0Pi1 = kfCharmBachelor0.GetDistanceFromParticleXY(kfCharmBachelor1); + float dcaXYPi0Xi = kfCharmBachelor0.GetDistanceFromParticleXY(kfXi); + float dcaXYPi1Xi = kfCharmBachelor1.GetDistanceFromParticleXY(kfXi); // mass of Xi-Pi0 pair KFParticle kfXiPi0; @@ -672,6 +659,7 @@ struct HfCandidateCreatorXicToXiPiPi { registry.fill(HIST("hCovPVXZ"), covMatrixPV[3]); registry.fill(HIST("hCovPVZZ"), covMatrixPV[5]); // covariance matrix elements of SV + auto covMatrixXicPlus = kfXicPlus.CovarianceMatrix(); registry.fill(HIST("hCovSVXX"), covMatrixXicPlus[0]); registry.fill(HIST("hCovSVYY"), covMatrixXicPlus[2]); registry.fill(HIST("hCovSVXZ"), covMatrixXicPlus[3]); @@ -708,11 +696,13 @@ struct HfCandidateCreatorXicToXiPiPi { /*PID information*/ nSigTpcPiFromXicPlus0, nSigTpcPiFromXicPlus1, nSigTpcBachelorPi, nSigTpcPiFromLambda, nSigTpcPrFromLambda, nSigTofPiFromXicPlus0, nSigTofPiFromXicPlus1, nSigTofBachelorPi, nSigTofPiFromLambda, nSigTofPrFromLambda); - rowCandidateKF(casc.kfCascadeChi2(), casc.kfV0Chi2(), - kfDecayLength, kfDecayLengthNormalised, kfDecayLengthXY, kfDecayLengthXYNormalised, - chi2topoXicPlusToPVBeforeConstraint, chi2topoXicPlusToPV, chi2topoXiToXicPlusBeforeConstraint, chi2topoXiToXicPlus, - dcaXYPi0Pi1, dcaXYPi0Xi, dcaXYPi1Xi, - dcaPi0Pi1, dcaPi0Xi, dcaPi1Xi); + rowCandidateKF(kfDecayLength, kfDecayLengthNormalised, kfDecayLengthXY, kfDecayLengthXYNormalised, + casc.kfCascadeChi2(), casc.kfV0Chi2(), + chi2TopoXicPlusToPVBefConst, chi2TopoXicPlusToPV, + chi2PrimXi, chi2PrimPi0, chi2PrimPi1, + chi2DevPi0Pi1, chi2DevPi0Xi, chi2DevPi1Xi, + dcaPi0Pi1, dcaPi0Xi, dcaPi1Xi, + dcaXYPi0Pi1, dcaXYPi0Xi, dcaXYPi1Xi); } // loop over track triplets } @@ -857,10 +847,12 @@ struct HfCandidateCreatorXicToXiPiPiExpressions { Spawns rowCandidateXic; Produces rowMcMatchRec; Produces rowMcMatchGen; + Produces rowResiduals; Configurable fillMcHistograms{"fillMcHistograms", true, "Fill validation plots"}; Configurable matchDecayedPions{"matchDecayedPions", true, "Match also candidates with daughter pion tracks that decay with kinked topology"}; Configurable matchInteractionsWithMaterial{"matchInteractionsWithMaterial", true, "Match also candidates with daughter tracks that interact with material"}; + Configurable fillResidualTable{"fillResidualTable", false, "Fill table containing residuals and pulls of PV and SV"}; HfEventSelectionMc hfEvSelMc; @@ -887,10 +879,10 @@ struct HfCandidateCreatorXicToXiPiPiExpressions { // add histograms to registry if (fillMcHistograms) { registry.add("hDecayedPions", "hDecayedPions", {HistType::kTH1F, {{5, -0.5, 4.5}}}); - registry.add("hInteractionsWithMaterial", "hInteractionsWithMaterial", {HistType::kTH1F, {{21, -0.5, 20.5}}}); + registry.add("hInteractionsWithMaterial", "hInteractionsWithMaterial", {HistType::kTH1F, {{6, -0.5, 5.5}}}); registry.add("hDebugRec", "hDebugRec", {HistType::kTH1F, {{4, -0.5, 3.5}}}); registry.get(HIST("hDebugRec"))->GetXaxis()->SetBinLabel(1 + TotalRec, "total"); - registry.get(HIST("hDebugRec"))->GetXaxis()->SetBinLabel(1 + XicToFinalState, "#Xi^{+}_{c} #rightarrow #pi^{#plus}) #pi^{#plus} #pi^{#minus} p #pi^{#minus}"); + registry.get(HIST("hDebugRec"))->GetXaxis()->SetBinLabel(1 + XicToFinalState, "#Xi^{+}_{c} #rightarrow #pi^{#plus} #pi^{#plus} #pi^{#minus} p #pi^{#minus}"); registry.get(HIST("hDebugRec"))->GetXaxis()->SetBinLabel(1 + XiToPiPPi, "#Xi^{#minus} #rightarrow #pi^{#minus} p #pi^{#minus}"); registry.get(HIST("hDebugRec"))->GetXaxis()->SetBinLabel(1 + LambdaToPPi, "#Lambda #rightarrow p #pi^{#minus}"); } @@ -928,6 +920,12 @@ struct HfCandidateCreatorXicToXiPiPiExpressions { std::array arrXiResonance = {3324, kPiPlus}; // 3324: Ξ(1530) // for non-prompt std::vector idxBhadMothers; + // residuals and pulls + std::array momentumResiduals{-9999.f}; + std::array pvResiduals{-9999.f}; + std::array pvPulls{-9999.f}; + std::array svResiduals{-9999.f}; + std::array svPulls{-9999.f}; // Match reconstructed candidates. for (const auto& candidate : *rowCandidateXic) { @@ -937,6 +935,13 @@ struct HfCandidateCreatorXicToXiPiPiExpressions { nPionsDecayed = 0; nInteractionsWithMaterial = 0; arrDaughIndex.clear(); + if (fillResidualTable) { + momentumResiduals.fill(-9999.f); + pvResiduals.fill(-9999.f); + pvPulls.fill(-9999.f); + svResiduals.fill(-9999.f); + svPulls.fill(-9999.f); + } auto arrayDaughters = std::array{candidate.pi0_as(), // pi <- Xic candidate.pi1_as(), // pi <- Xic @@ -996,7 +1001,9 @@ struct HfCandidateCreatorXicToXiPiPiExpressions { if (fillMcHistograms) { registry.fill(HIST("hDebugRec"), LambdaToPPi); } - RecoDecay::getDaughters(mcParticles.rawIteratorAt(indexRecXicPlus), &arrDaughIndex, std::array{0}, 1); + auto particleXicPlus = mcParticles.rawIteratorAt(indexRecXicPlus); + // Check whether XicPlus decays via resonant decay + RecoDecay::getDaughters(particleXicPlus, &arrDaughIndex, std::array{0}, 1); if (arrDaughIndex.size() == NDaughtersResonant) { for (auto iProng = 0u; iProng < NDaughtersResonant; ++iProng) { auto daughI = mcParticles.rawIteratorAt(arrDaughIndex[iProng]); @@ -1008,22 +1015,53 @@ struct HfCandidateCreatorXicToXiPiPiExpressions { } else { flag = sign * (1 << aod::hf_cand_xic_to_xi_pi_pi::DecayType::XicToXiPiPi); } + // Check whether the charm baryon is non-prompt (from a b quark). + if (flag != 0) { + origin = RecoDecay::getCharmHadronOrigin(mcParticles, particleXicPlus, false); + } + // Calculate residuals and pulls + if (flag != 0 && fillResidualTable) { + auto mcCollision = particleXicPlus.template mcCollision_as(); + auto particleDaughter0 = mcParticles.rawIteratorAt(arrDaughIndex[0]); + + momentumResiduals[0] = candidate.p() - particleXicPlus.p(); + momentumResiduals[1] = candidate.pt() - particleXicPlus.pt(); + pvResiduals[0] = candidate.posX() - mcCollision.posX(); + pvResiduals[1] = candidate.posY() - mcCollision.posY(); + pvResiduals[2] = candidate.posZ() - mcCollision.posZ(); + svResiduals[0] = candidate.xSecondaryVertex() - particleDaughter0.vx(); + svResiduals[1] = candidate.ySecondaryVertex() - particleDaughter0.vy(); + svResiduals[2] = candidate.zSecondaryVertex() - particleDaughter0.vz(); + try { + pvPulls[0] = pvResiduals[0] / candidate.xPvErr(); + pvPulls[1] = pvResiduals[1] / candidate.yPvErr(); + pvPulls[2] = pvResiduals[2] / candidate.zPvErr(); + svPulls[0] = svResiduals[0] / candidate.xSvErr(); + svPulls[1] = svResiduals[1] / candidate.ySvErr(); + svPulls[2] = svResiduals[2] / candidate.zSvErr(); + } catch (const std::runtime_error& error) { + LOG(info) << "Run time error found: " << error.what() << ". Set values of vertex pulls to -9999.9."; + } + } } } } - // Check whether the charm baryon is non-prompt (from a b quark). - if (flag != 0) { - auto particle = mcParticles.rawIteratorAt(indexRecXicPlus); - origin = RecoDecay::getCharmHadronOrigin(mcParticles, particle, false); - } // Fill histograms if (flag != 0 && fillMcHistograms) { registry.fill(HIST("hDecayedPions"), nPionsDecayed); registry.fill(HIST("hInteractionsWithMaterial"), nInteractionsWithMaterial); } - // Fill table + + // Fill tables rowMcMatchRec(flag, origin); + if (fillResidualTable) { + rowResiduals(origin, momentumResiduals[0], momentumResiduals[1], + pvResiduals[0], pvResiduals[1], pvResiduals[2], + pvPulls[0], pvPulls[1], pvPulls[2], + svResiduals[0], svResiduals[1], svResiduals[2], + svPulls[0], svPulls[1], svPulls[2]); + } } // close loop over candidates // Match generated particles. diff --git a/PWGHF/TableProducer/candidateSelectorXicToXiPiPi.cxx b/PWGHF/TableProducer/candidateSelectorXicToXiPiPi.cxx index 745a881d7ad..ae3256fcd48 100644 --- a/PWGHF/TableProducer/candidateSelectorXicToXiPiPi.cxx +++ b/PWGHF/TableProducer/candidateSelectorXicToXiPiPi.cxx @@ -15,20 +15,20 @@ /// \author Phil Lennart Stahlhut , Heidelberg University /// \author Jaeyoon Cho , Inha University -#include -#include - -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - -#include "Common/Core/TrackSelectorPID.h" - #include "PWGHF/Core/HfMlResponseXicToXiPiPi.h" #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" #include "PWGHF/Utils/utilsAnalysis.h" // findBin function +#include "Common/Core/TrackSelectorPID.h" + +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" + +#include +#include + using namespace o2; using namespace o2::aod; using namespace o2::framework; diff --git a/PWGHF/TableProducer/treeCreatorXicToXiPiPi.cxx b/PWGHF/TableProducer/treeCreatorXicToXiPiPi.cxx index 5e32ff5c1bf..be12fd5cbeb 100644 --- a/PWGHF/TableProducer/treeCreatorXicToXiPiPi.cxx +++ b/PWGHF/TableProducer/treeCreatorXicToXiPiPi.cxx @@ -16,19 +16,18 @@ /// \author Carolina Reetz , Heidelberg University /// \author Jaeyoon Cho , Inha University -#include +#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "PWGHF/DataModel/CandidateSelectionTables.h" #include "CommonConstants/PhysicsConstants.h" #include "Framework/AnalysisTask.h" #include "Framework/runDataProcessing.h" -#include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" +#include using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; -using namespace o2::constants::physics; namespace o2::aod { @@ -36,11 +35,10 @@ namespace full { DECLARE_SOA_COLUMN(CandidateSelFlag, candidateSelFlag, int); //! Selection flag of candidate (output of candidateSelector) // vertices -DECLARE_SOA_COLUMN(Chi2Sv, chi2Sv, float); -DECLARE_SOA_COLUMN(Chi2XiVtx, chi2XiVtx, float); -DECLARE_SOA_COLUMN(Chi2LamVtx, chi2LamVtx, float); +DECLARE_SOA_COLUMN(Chi2SV, chi2SV, float); //! Chi2 of candidate vertex +DECLARE_SOA_COLUMN(Chi2GeoXi, chi2GeoXi, float); //! Chi2 of Xi vertex +DECLARE_SOA_COLUMN(Chi2GeoLambda, chi2GeoLambda, float); //! Chi2 of Lambda vertex // properties of XicPlus -DECLARE_SOA_COLUMN(Sign, sign, float); DECLARE_SOA_COLUMN(E, e, float); //! Energy of candidate (GeV) DECLARE_SOA_COLUMN(M, m, float); //! Invariant mass of candidate (GeV/c2) DECLARE_SOA_COLUMN(P, p, float); //! Momentum of candidate (GeV/c) @@ -55,64 +53,26 @@ DECLARE_SOA_COLUMN(DecayLengthNormalised, decayLengthNormalised, float); //! DECLARE_SOA_COLUMN(DecayLengthXYNormalised, decayLengthXYNormalised, float); //! Normalised transverse decay length of candidate DECLARE_SOA_COLUMN(Cpa, cpa, float); //! Cosine pointing angle of candidate DECLARE_SOA_COLUMN(CpaXY, cpaXY, float); //! Cosine pointing angle of candidate in transverse plane -DECLARE_SOA_COLUMN(Chi2TopoXicPlusToPVBeforeConstraint, chi2TopoXicPlusToPVBeforeConstraint, float); -DECLARE_SOA_COLUMN(Chi2TopoXicPlusToPV, chi2TopoXicPlusToPV, float); -DECLARE_SOA_COLUMN(Chi2TopoXiToXicPlusBeforeConstraint, chi2TopoXiToXicPlusBeforeConstraint, float); -DECLARE_SOA_COLUMN(Chi2TopoXiToXicPlus, chi2TopoXiToXicPlus, float); // properties of daughter tracks -DECLARE_SOA_COLUMN(PtXi, ptXi, float); //! Transverse momentum of Xi (prong0) (GeV/c) -DECLARE_SOA_COLUMN(ImpactParameterXi, impactParameterXi, float); //! Impact parameter of Xi (prong0) -DECLARE_SOA_COLUMN(ImpactParameterNormalisedXi, impactParameterNormalisedXi, float); //! Normalised impact parameter of Xi (prong0) -DECLARE_SOA_COLUMN(PPi0, pPi0, float); +DECLARE_SOA_COLUMN(PtXi, ptXi, float); //! Transverse momentum of Xi (prong0) (GeV/c) +DECLARE_SOA_COLUMN(ImpactParameterXi, impactParameterXi, float); //! Impact parameter of Xi (prong0) +DECLARE_SOA_COLUMN(ImpactParameterNormalisedXi, impactParameterNormalisedXi, float); //! Normalised impact parameter of Xi (prong0) +DECLARE_SOA_COLUMN(PPi0, pPi0, float); //! Momentum of Pi0 (prong1) (GeV/c) DECLARE_SOA_COLUMN(PtPi0, ptPi0, float); //! Transverse momentum of Pi0 (prong1) (GeV/c) DECLARE_SOA_COLUMN(ImpactParameterPi0, impactParameterPi0, float); //! Impact parameter of Pi0 (prong1) DECLARE_SOA_COLUMN(ImpactParameterNormalisedPi0, impactParameterNormalisedPi0, float); //! Normalised impact parameter of Pi0 (prong1) -DECLARE_SOA_COLUMN(PPi1, pPi1, float); +DECLARE_SOA_COLUMN(PPi1, pPi1, float); //! Momentum of Pi1 (prong2) (GeV/c) DECLARE_SOA_COLUMN(PtPi1, ptPi1, float); //! Transverse momentum of Pi1 (prong2) (GeV/c) DECLARE_SOA_COLUMN(ImpactParameterPi1, impactParameterPi1, float); //! Normalised impact parameter of Pi1 (prong2) DECLARE_SOA_COLUMN(ImpactParameterNormalisedPi1, impactParameterNormalisedPi1, float); //! Normalised impact parameter of Pi1 (prong2) DECLARE_SOA_COLUMN(MaxNormalisedDeltaIP, maxNormalisedDeltaIP, float); //! Maximum normalized difference between measured and expected impact parameter of candidate prongs -DECLARE_SOA_COLUMN(CpaXi, cpaXi, float); -DECLARE_SOA_COLUMN(CpaXYXi, cpaXYXi, float); -DECLARE_SOA_COLUMN(CpaLam, cpaLam, float); -DECLARE_SOA_COLUMN(CpaXYLam, cpaXYLam, float); -DECLARE_SOA_COLUMN(CpaLamToXi, cpaLamToXi, float); -DECLARE_SOA_COLUMN(CpaXYLamToXi, cpaXYLamToXi, float); -DECLARE_SOA_COLUMN(DcaXYPi0Pi1, dcaXYPi0Pi1, float); -DECLARE_SOA_COLUMN(DcaXYPi0Xi, dcaXYPi0Xi, float); -DECLARE_SOA_COLUMN(DcaXYPi1Xi, dcaXYPi1Xi, float); -DECLARE_SOA_COLUMN(DcaPi0Pi1, dcaPi0Pi1, float); -DECLARE_SOA_COLUMN(DcaPi0Xi, dcaPi0Xi, float); -DECLARE_SOA_COLUMN(DcaPi1Xi, dcaPi1Xi, float); -DECLARE_SOA_COLUMN(InvMassXi, invMassXi, float); -DECLARE_SOA_COLUMN(InvMassLambda, invMassLambda, float); -DECLARE_SOA_COLUMN(InvMassXiPi0, invMassXiPi0, float); -DECLARE_SOA_COLUMN(InvMassXiPi1, invMassXiPi1, float); -DECLARE_SOA_COLUMN(PBachelorPi, pBachelorPi, float); -DECLARE_SOA_COLUMN(PPiFromLambda, pPiFromLambda, float); -DECLARE_SOA_COLUMN(PPrFromLambda, pPrFromLambda, float); -// residuals and pulls -DECLARE_SOA_COLUMN(PtResidual, ptResidual, float); -DECLARE_SOA_COLUMN(PResidual, pResidual, float); -DECLARE_SOA_COLUMN(XPvResidual, xPvResidual, float); -DECLARE_SOA_COLUMN(YPvResidual, yPvResidual, float); -DECLARE_SOA_COLUMN(ZPvResidual, zPvResidual, float); -DECLARE_SOA_COLUMN(XPvPull, xPvPull, float); -DECLARE_SOA_COLUMN(YPvPull, yPvPull, float); -DECLARE_SOA_COLUMN(ZPvPull, zPvPull, float); -DECLARE_SOA_COLUMN(XSvResidual, xSvResidual, float); -DECLARE_SOA_COLUMN(YSvResidual, ySvResidual, float); -DECLARE_SOA_COLUMN(ZSvResidual, zSvResidual, float); -DECLARE_SOA_COLUMN(XSvPull, xSvPull, float); -DECLARE_SOA_COLUMN(YSvPull, ySvPull, float); -DECLARE_SOA_COLUMN(ZSvPull, zSvPull, float); } // namespace full DECLARE_SOA_TABLE(HfCandXicToXiPiPiLites, "AOD", "HFXICXI2PILITE", hf_cand_xic_to_xi_pi_pi::FlagMcMatchRec, hf_cand_xic_to_xi_pi_pi::OriginRec, full::CandidateSelFlag, - full::Sign, + hf_cand_xic_to_xi_pi_pi::Sign, full::Y, full::Eta, full::Phi, @@ -122,11 +82,11 @@ DECLARE_SOA_TABLE(HfCandXicToXiPiPiLites, "AOD", "HFXICXI2PILITE", full::PtPi0, full::PtPi1, full::M, - full::InvMassXi, - full::InvMassLambda, - full::InvMassXiPi0, - full::InvMassXiPi1, - full::Chi2Sv, + hf_cand_xic_to_xi_pi_pi::InvMassXi, + hf_cand_xic_to_xi_pi_pi::InvMassLambda, + hf_cand_xic_to_xi_pi_pi::InvMassXiPi0, + hf_cand_xic_to_xi_pi_pi::InvMassXiPi1, + full::Chi2SV, full::Ct, full::DecayLength, full::DecayLengthNormalised, @@ -134,10 +94,10 @@ DECLARE_SOA_TABLE(HfCandXicToXiPiPiLites, "AOD", "HFXICXI2PILITE", full::DecayLengthXYNormalised, full::Cpa, full::CpaXY, - full::CpaXi, - full::CpaXYXi, - full::CpaLam, - full::CpaXYLam, + hf_cand_xic_to_xi_pi_pi::CpaXi, + hf_cand_xic_to_xi_pi_pi::CpaXYXi, + hf_cand_xic_to_xi_pi_pi::CpaLambda, + hf_cand_xic_to_xi_pi_pi::CpaXYLambda, full::ImpactParameterXi, full::ImpactParameterNormalisedXi, full::ImpactParameterPi0, @@ -150,7 +110,7 @@ DECLARE_SOA_TABLE(HfCandXicToXiPiPiLiteKfs, "AOD", "HFXICXI2PILITKF", hf_cand_xic_to_xi_pi_pi::FlagMcMatchRec, hf_cand_xic_to_xi_pi_pi::OriginRec, full::CandidateSelFlag, - full::Sign, + hf_cand_xic_to_xi_pi_pi::Sign, full::Y, full::Eta, full::Phi, @@ -160,11 +120,11 @@ DECLARE_SOA_TABLE(HfCandXicToXiPiPiLiteKfs, "AOD", "HFXICXI2PILITKF", full::PtPi0, full::PtPi1, full::M, - full::InvMassXi, - full::InvMassLambda, - full::InvMassXiPi0, - full::InvMassXiPi1, - full::Chi2Sv, + hf_cand_xic_to_xi_pi_pi::InvMassXi, + hf_cand_xic_to_xi_pi_pi::InvMassLambda, + hf_cand_xic_to_xi_pi_pi::InvMassXiPi0, + hf_cand_xic_to_xi_pi_pi::InvMassXiPi1, + full::Chi2SV, full::Ct, full::DecayLength, full::DecayLengthNormalised, @@ -172,10 +132,10 @@ DECLARE_SOA_TABLE(HfCandXicToXiPiPiLiteKfs, "AOD", "HFXICXI2PILITKF", full::DecayLengthXYNormalised, full::Cpa, full::CpaXY, - full::CpaXi, - full::CpaXYXi, - full::CpaLam, - full::CpaXYLam, + hf_cand_xic_to_xi_pi_pi::CpaXi, + hf_cand_xic_to_xi_pi_pi::CpaXYXi, + hf_cand_xic_to_xi_pi_pi::CpaLambda, + hf_cand_xic_to_xi_pi_pi::CpaXYLambda, full::ImpactParameterXi, full::ImpactParameterNormalisedXi, full::ImpactParameterPi0, @@ -184,24 +144,28 @@ DECLARE_SOA_TABLE(HfCandXicToXiPiPiLiteKfs, "AOD", "HFXICXI2PILITKF", full::ImpactParameterNormalisedPi1, full::MaxNormalisedDeltaIP, // KF specific columns - full::Chi2XiVtx, - full::Chi2LamVtx, - full::Chi2TopoXicPlusToPVBeforeConstraint, - full::Chi2TopoXicPlusToPV, - full::Chi2TopoXiToXicPlusBeforeConstraint, - full::Chi2TopoXiToXicPlus, - full::DcaXYPi0Pi1, - full::DcaXYPi0Xi, - full::DcaXYPi1Xi, - full::DcaPi0Pi1, - full::DcaPi0Xi, - full::DcaPi1Xi); + full::Chi2GeoXi, + full::Chi2GeoLambda, + hf_cand_xic_to_xi_pi_pi::Chi2TopoXicPlusToPVBefConst, + hf_cand_xic_to_xi_pi_pi::Chi2TopoXicPlusToPV, + hf_cand_xic_to_xi_pi_pi::Chi2PrimXi, + hf_cand_xic_to_xi_pi_pi::Chi2PrimPi0, + hf_cand_xic_to_xi_pi_pi::Chi2PrimPi1, + hf_cand_xic_to_xi_pi_pi::Chi2DevPi0Pi1, + hf_cand_xic_to_xi_pi_pi::Chi2DevPi0Xi, + hf_cand_xic_to_xi_pi_pi::Chi2DevPi1Xi, + hf_cand_xic_to_xi_pi_pi::DcaPi0Pi1, + hf_cand_xic_to_xi_pi_pi::DcaPi0Xi, + hf_cand_xic_to_xi_pi_pi::DcaPi1Xi, + hf_cand_xic_to_xi_pi_pi::DcaXYPi0Pi1, + hf_cand_xic_to_xi_pi_pi::DcaXYPi0Xi, + hf_cand_xic_to_xi_pi_pi::DcaXYPi1Xi); DECLARE_SOA_TABLE(HfCandXicToXiPiPiFulls, "AOD", "HFXICXI2PIFULL", hf_cand_xic_to_xi_pi_pi::FlagMcMatchRec, hf_cand_xic_to_xi_pi_pi::OriginRec, full::CandidateSelFlag, - full::Sign, + hf_cand_xic_to_xi_pi_pi::Sign, full::Y, full::Eta, full::Phi, @@ -211,11 +175,11 @@ DECLARE_SOA_TABLE(HfCandXicToXiPiPiFulls, "AOD", "HFXICXI2PIFULL", full::PtPi0, full::PtPi1, full::M, - full::InvMassXi, - full::InvMassLambda, - full::InvMassXiPi0, - full::InvMassXiPi1, - full::Chi2Sv, + hf_cand_xic_to_xi_pi_pi::InvMassXi, + hf_cand_xic_to_xi_pi_pi::InvMassLambda, + hf_cand_xic_to_xi_pi_pi::InvMassXiPi0, + hf_cand_xic_to_xi_pi_pi::InvMassXiPi1, + full::Chi2SV, full::Ct, full::DecayLength, full::DecayLengthNormalised, @@ -223,10 +187,10 @@ DECLARE_SOA_TABLE(HfCandXicToXiPiPiFulls, "AOD", "HFXICXI2PIFULL", full::DecayLengthXYNormalised, full::Cpa, full::CpaXY, - full::CpaXi, - full::CpaXYXi, - full::CpaLam, - full::CpaXYLam, + hf_cand_xic_to_xi_pi_pi::CpaXi, + hf_cand_xic_to_xi_pi_pi::CpaXYXi, + hf_cand_xic_to_xi_pi_pi::CpaLambda, + hf_cand_xic_to_xi_pi_pi::CpaXYLambda, full::ImpactParameterXi, full::ImpactParameterNormalisedXi, full::ImpactParameterPi0, @@ -235,13 +199,13 @@ DECLARE_SOA_TABLE(HfCandXicToXiPiPiFulls, "AOD", "HFXICXI2PIFULL", full::ImpactParameterNormalisedPi1, full::MaxNormalisedDeltaIP, // additional columns only stored in the full candidate table - full::CpaLamToXi, - full::CpaXYLamToXi, + hf_cand_xic_to_xi_pi_pi::CpaLambdaToXi, + hf_cand_xic_to_xi_pi_pi::CpaXYLambdaToXi, full::PPi0, full::PPi1, - full::PBachelorPi, - full::PPiFromLambda, - full::PPrFromLambda, + hf_cand_xic_to_xi_pi_pi::PBachelorPi, + hf_cand_xic_to_xi_pi_pi::PPiFromLambda, + hf_cand_xic_to_xi_pi_pi::PPrFromLambda, hf_cand_xic_to_xi_pi_pi::DcaXiDaughters, hf_cand_xic_to_xi_pi_pi::DcaV0Daughters, hf_cand_xic_to_xi_pi_pi::DcaPosToPV, @@ -264,7 +228,7 @@ DECLARE_SOA_TABLE(HfCandXicToXiPiPiFullKfs, "AOD", "HFXICXI2PIFULKF", hf_cand_xic_to_xi_pi_pi::FlagMcMatchRec, hf_cand_xic_to_xi_pi_pi::OriginRec, full::CandidateSelFlag, - full::Sign, + hf_cand_xic_to_xi_pi_pi::Sign, full::Y, full::Eta, full::Phi, @@ -274,11 +238,11 @@ DECLARE_SOA_TABLE(HfCandXicToXiPiPiFullKfs, "AOD", "HFXICXI2PIFULKF", full::PtPi0, full::PtPi1, full::M, - full::InvMassXi, - full::InvMassLambda, - full::InvMassXiPi0, - full::InvMassXiPi1, - full::Chi2Sv, + hf_cand_xic_to_xi_pi_pi::InvMassXi, + hf_cand_xic_to_xi_pi_pi::InvMassLambda, + hf_cand_xic_to_xi_pi_pi::InvMassXiPi0, + hf_cand_xic_to_xi_pi_pi::InvMassXiPi1, + full::Chi2SV, full::Ct, full::DecayLength, full::DecayLengthNormalised, @@ -286,10 +250,10 @@ DECLARE_SOA_TABLE(HfCandXicToXiPiPiFullKfs, "AOD", "HFXICXI2PIFULKF", full::DecayLengthXYNormalised, full::Cpa, full::CpaXY, - full::CpaXi, - full::CpaXYXi, - full::CpaLam, - full::CpaXYLam, + hf_cand_xic_to_xi_pi_pi::CpaXi, + hf_cand_xic_to_xi_pi_pi::CpaXYXi, + hf_cand_xic_to_xi_pi_pi::CpaLambda, + hf_cand_xic_to_xi_pi_pi::CpaXYLambda, full::ImpactParameterXi, full::ImpactParameterNormalisedXi, full::ImpactParameterPi0, @@ -298,13 +262,13 @@ DECLARE_SOA_TABLE(HfCandXicToXiPiPiFullKfs, "AOD", "HFXICXI2PIFULKF", full::ImpactParameterNormalisedPi1, full::MaxNormalisedDeltaIP, // additional columns only stored in the full candidate table - full::CpaLamToXi, - full::CpaXYLamToXi, + hf_cand_xic_to_xi_pi_pi::CpaLambdaToXi, + hf_cand_xic_to_xi_pi_pi::CpaXYLambdaToXi, full::PPi0, full::PPi1, - full::PBachelorPi, - full::PPiFromLambda, - full::PPrFromLambda, + hf_cand_xic_to_xi_pi_pi::PBachelorPi, + hf_cand_xic_to_xi_pi_pi::PPiFromLambda, + hf_cand_xic_to_xi_pi_pi::PPrFromLambda, hf_cand_xic_to_xi_pi_pi::DcaXiDaughters, hf_cand_xic_to_xi_pi_pi::DcaV0Daughters, hf_cand_xic_to_xi_pi_pi::DcaPosToPV, @@ -323,18 +287,22 @@ DECLARE_SOA_TABLE(HfCandXicToXiPiPiFullKfs, "AOD", "HFXICXI2PIFULKF", hf_cand_xic_to_xi_pi_pi::NSigTofPiFromLambda, hf_cand_xic_to_xi_pi_pi::NSigTofPrFromLambda, // KF-specific columns - full::Chi2XiVtx, - full::Chi2LamVtx, - full::Chi2TopoXicPlusToPVBeforeConstraint, - full::Chi2TopoXicPlusToPV, - full::Chi2TopoXiToXicPlusBeforeConstraint, - full::Chi2TopoXiToXicPlus, - full::DcaXYPi0Pi1, - full::DcaXYPi0Xi, - full::DcaXYPi1Xi, - full::DcaPi0Pi1, - full::DcaPi0Xi, - full::DcaPi1Xi); + full::Chi2GeoXi, + full::Chi2GeoLambda, + hf_cand_xic_to_xi_pi_pi::Chi2TopoXicPlusToPVBefConst, + hf_cand_xic_to_xi_pi_pi::Chi2TopoXicPlusToPV, + hf_cand_xic_to_xi_pi_pi::Chi2PrimXi, + hf_cand_xic_to_xi_pi_pi::Chi2PrimPi0, + hf_cand_xic_to_xi_pi_pi::Chi2PrimPi1, + hf_cand_xic_to_xi_pi_pi::Chi2DevPi0Pi1, + hf_cand_xic_to_xi_pi_pi::Chi2DevPi0Xi, + hf_cand_xic_to_xi_pi_pi::Chi2DevPi1Xi, + hf_cand_xic_to_xi_pi_pi::DcaPi0Pi1, + hf_cand_xic_to_xi_pi_pi::DcaPi0Xi, + hf_cand_xic_to_xi_pi_pi::DcaPi1Xi, + hf_cand_xic_to_xi_pi_pi::DcaXYPi0Pi1, + hf_cand_xic_to_xi_pi_pi::DcaXYPi0Xi, + hf_cand_xic_to_xi_pi_pi::DcaXYPi1Xi); DECLARE_SOA_TABLE(HfCandXicToXiPiPiFullPs, "AOD", "HFXICXI2PIFULLP", hf_cand_xic_to_xi_pi_pi::FlagMcMatchGen, @@ -344,23 +312,6 @@ DECLARE_SOA_TABLE(HfCandXicToXiPiPiFullPs, "AOD", "HFXICXI2PIFULLP", full::Eta, full::Phi, full::Y); - -DECLARE_SOA_TABLE(HfCandXicToXiPiPiResiduals, "AOD", "HFXICXI2PIRESID", - hf_cand_xic_to_xi_pi_pi::OriginGen, - full::PResidual, - full::PtResidual, - full::XPvResidual, - full::YPvResidual, - full::ZPvResidual, - full::XPvPull, - full::YPvPull, - full::ZPvPull, - full::XSvResidual, - full::YSvResidual, - full::ZSvResidual, - full::XSvPull, - full::YSvPull, - full::ZSvPull); } // namespace o2::aod /// Writes the full information in an output TTree @@ -370,7 +321,6 @@ struct HfTreeCreatorXicToXiPiPi { Produces rowCandidateFull; Produces rowCandidateFullKf; Produces rowCandidateFullParticles; - Produces rowCandidateResiduals; Configurable selectionFlagXic{"selectionFlagXic", 1, "Selection Flag for Xic"}; Configurable fillCandidateLiteTable{"fillCandidateLiteTable", false, "Switch to fill lite table with candidate properties"}; @@ -380,9 +330,6 @@ struct HfTreeCreatorXicToXiPiPi { Configurable fillOnlyBackground{"fillOnlyBackground", false, "Flag to fill derived tables with background for ML trainings"}; 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"}; - // parameters for MC matching in residual process function - Configurable matchDecayedPions{"matchDecayedPions", true, "Match also candidates with daughter pion tracks that decay with kinked topology"}; - Configurable matchInteractionsWithMaterial{"matchInteractionsWithMaterial", true, "Match also candidates with daughter tracks that interact with material"}; using SelectedCandidates = soa::Filtered>; using SelectedCandidatesKf = soa::Filtered>; @@ -439,10 +386,10 @@ struct HfTreeCreatorXicToXiPiPi { candidate.decayLengthXYNormalised(), candidate.cpa(), candidate.cpaXY(), - candidate.cosPaXi(), - candidate.cosPaXYXi(), - candidate.cosPaLambda(), - candidate.cosPaXYLambda(), + candidate.cpaXi(), + candidate.cpaXYXi(), + candidate.cpaLambda(), + candidate.cpaXYLambda(), candidate.impactParameter0(), candidate.impactParameterNormalised0(), candidate.impactParameter1(), @@ -477,10 +424,10 @@ struct HfTreeCreatorXicToXiPiPi { candidate.decayLengthXYNormalised(), candidate.cpa(), candidate.cpaXY(), - candidate.cosPaXi(), - candidate.cosPaXYXi(), - candidate.cosPaLambda(), - candidate.cosPaXYLambda(), + candidate.cpaXi(), + candidate.cpaXYXi(), + candidate.cpaLambda(), + candidate.cpaXYLambda(), candidate.impactParameter0(), candidate.impactParameterNormalised0(), candidate.impactParameter1(), @@ -489,8 +436,8 @@ struct HfTreeCreatorXicToXiPiPi { candidate.impactParameterNormalised2(), candidate.maxNormalisedDeltaIP(), // additional columns only stored in the full candidate table - candidate.cosPaLambdaToXi(), - candidate.cosPaXYLambdaToXi(), + candidate.cpaLambdaToXi(), + candidate.cpaXYLambdaToXi(), candidate.pProng1(), candidate.pProng2(), candidate.pBachelorPi(), @@ -542,10 +489,10 @@ struct HfTreeCreatorXicToXiPiPi { candidate.kfDecayLengthXYNormalised(), candidate.cpa(), candidate.cpaXY(), - candidate.cosPaXi(), - candidate.cosPaXYXi(), - candidate.cosPaLambda(), - candidate.cosPaXYLambda(), + candidate.cpaXi(), + candidate.cpaXYXi(), + candidate.cpaLambda(), + candidate.cpaXYLambda(), candidate.impactParameter0(), candidate.impactParameterNormalised0(), candidate.impactParameter1(), @@ -556,16 +503,20 @@ struct HfTreeCreatorXicToXiPiPi { // KF-specific columns candidate.kfCascadeChi2(), candidate.kfV0Chi2(), - candidate.chi2TopoXicPlusToPVBeforeConstraint(), + candidate.chi2TopoXicPlusToPVBefConst(), candidate.chi2TopoXicPlusToPV(), - candidate.chi2TopoXiToXicPlusBeforeConstraint(), - candidate.chi2TopoXiToXicPlus(), - candidate.dcaXYPi0Pi1(), - candidate.dcaXYPi0Xi(), - candidate.dcaXYPi1Xi(), + candidate.chi2PrimXi(), + candidate.chi2PrimPi0(), + candidate.chi2PrimPi1(), + candidate.chi2DevPi0Pi1(), + candidate.chi2DevPi0Xi(), + candidate.chi2DevPi1Xi(), candidate.dcaPi0Pi1(), candidate.dcaPi0Xi(), - candidate.dcaPi1Xi()); + candidate.dcaPi1Xi(), + candidate.dcaXYPi0Pi1(), + candidate.dcaXYPi0Xi(), + candidate.dcaXYPi1Xi()); } else { rowCandidateFullKf( flagMc, @@ -593,10 +544,10 @@ struct HfTreeCreatorXicToXiPiPi { candidate.kfDecayLengthXYNormalised(), candidate.cpa(), candidate.cpaXY(), - candidate.cosPaXi(), - candidate.cosPaXYXi(), - candidate.cosPaLambda(), - candidate.cosPaXYLambda(), + candidate.cpaXi(), + candidate.cpaXYXi(), + candidate.cpaLambda(), + candidate.cpaXYLambda(), candidate.impactParameter0(), candidate.impactParameterNormalised0(), candidate.impactParameter1(), @@ -605,8 +556,8 @@ struct HfTreeCreatorXicToXiPiPi { candidate.impactParameterNormalised2(), candidate.maxNormalisedDeltaIP(), // additional columns only stored in the full candidate table - candidate.cosPaLambdaToXi(), - candidate.cosPaXYLambdaToXi(), + candidate.cpaLambdaToXi(), + candidate.cpaXYLambdaToXi(), candidate.pProng1(), candidate.pProng2(), candidate.pBachelorPi(), @@ -632,16 +583,20 @@ struct HfTreeCreatorXicToXiPiPi { // KF-specific columns candidate.kfCascadeChi2(), candidate.kfV0Chi2(), - candidate.chi2TopoXicPlusToPVBeforeConstraint(), + candidate.chi2TopoXicPlusToPVBefConst(), candidate.chi2TopoXicPlusToPV(), - candidate.chi2TopoXiToXicPlusBeforeConstraint(), - candidate.chi2TopoXiToXicPlus(), - candidate.dcaXYPi0Pi1(), - candidate.dcaXYPi0Xi(), - candidate.dcaXYPi1Xi(), + candidate.chi2PrimXi(), + candidate.chi2PrimPi0(), + candidate.chi2PrimPi1(), + candidate.chi2DevPi0Pi1(), + candidate.chi2DevPi0Xi(), + candidate.chi2DevPi1Xi(), candidate.dcaPi0Pi1(), candidate.dcaPi0Xi(), - candidate.dcaPi1Xi()); + candidate.dcaPi1Xi(), + candidate.dcaXYPi0Pi1(), + candidate.dcaXYPi0Xi(), + candidate.dcaXYPi1Xi()); } } } @@ -791,102 +746,6 @@ struct HfTreeCreatorXicToXiPiPi { } } PROCESS_SWITCH(HfTreeCreatorXicToXiPiPi, processMcKf, "Process MC with KF Particle reconstruction", false); - - void processResiduals(SelectedCandidatesMc const&, - aod::TracksWMc const& tracks, - aod::McParticles const& particles, - aod::McCollisions const&) - { - rowCandidateResiduals.reserve(recSig.size()); - - recSig->bindExternalIndices(&tracks); - - std::vector arrDaughIndex; - int indexRecXicPlus; - int origin; - std::array pvResiduals; - std::array svResiduals; - std::array pvPulls; - std::array svPulls; - - for (const auto& candidate : recSig) { - arrDaughIndex.clear(); - indexRecXicPlus = -1; - origin = RecoDecay::OriginType::None; - pvResiduals = {-9999.9}; - svResiduals = {-9999.9}; - pvPulls = {-9999.9}; - svPulls = {-9999.9}; - - auto arrayDaughters = std::array{candidate.pi0_as(), // pi <- Xic - candidate.pi1_as(), // pi <- Xic - candidate.bachelor_as(), // pi <- cascade - candidate.posTrack_as(), // p <- lambda - candidate.negTrack_as()}; // pi <- lambda - - // get XicPlus as MC particle - if (matchDecayedPions && matchInteractionsWithMaterial) { - indexRecXicPlus = RecoDecay::getMatchedMCRec(particles, arrayDaughters, Pdg::kXiCPlus, std::array{+kPiPlus, +kPiPlus, +kPiMinus, +kProton, +kPiMinus}, true, nullptr, 4); - } else if (matchDecayedPions && !matchInteractionsWithMaterial) { - indexRecXicPlus = RecoDecay::getMatchedMCRec(particles, arrayDaughters, Pdg::kXiCPlus, std::array{+kPiPlus, +kPiPlus, +kPiMinus, +kProton, +kPiMinus}, true, nullptr, 4); - } else if (!matchDecayedPions && matchInteractionsWithMaterial) { - indexRecXicPlus = RecoDecay::getMatchedMCRec(particles, arrayDaughters, Pdg::kXiCPlus, std::array{+kPiPlus, +kPiPlus, +kPiMinus, +kProton, +kPiMinus}, true, nullptr, 4); - } else { - indexRecXicPlus = RecoDecay::getMatchedMCRec(particles, arrayDaughters, Pdg::kXiCPlus, std::array{+kPiPlus, +kPiPlus, +kPiMinus, +kProton, +kPiMinus}, true, nullptr, 4); - } - if (indexRecXicPlus == -1) { - continue; - } - auto particleXicPlusGen = particles.rawIteratorAt(indexRecXicPlus); - origin = RecoDecay::getCharmHadronOrigin(particles, particleXicPlusGen, false); - - // get MC collision - auto mcCollision = particleXicPlusGen.mcCollision_as(); - - // get XicPlus daughters as MC particle - RecoDecay::getDaughters(particleXicPlusGen, &arrDaughIndex, std::array{+kXiMinus, +kPiPlus, +kPiPlus}, 2); - auto daugh0XicPlus = particles.rawIteratorAt(arrDaughIndex[0]); - - // calculate residuals and pulls - float pResidual = candidate.p() - particleXicPlusGen.p(); - float ptResidual = candidate.pt() - particleXicPlusGen.pt(); - pvResiduals[0] = candidate.posX() - mcCollision.posX(); - pvResiduals[1] = candidate.posY() - mcCollision.posY(); - pvResiduals[2] = candidate.posZ() - mcCollision.posZ(); - svResiduals[0] = candidate.xSecondaryVertex() - daugh0XicPlus.vx(); - svResiduals[1] = candidate.ySecondaryVertex() - daugh0XicPlus.vy(); - svResiduals[2] = candidate.zSecondaryVertex() - daugh0XicPlus.vz(); - try { - pvPulls[0] = pvResiduals[0] / candidate.xPvErr(); - pvPulls[1] = pvResiduals[1] / candidate.yPvErr(); - pvPulls[2] = pvResiduals[2] / candidate.zPvErr(); - svPulls[0] = svResiduals[0] / candidate.xSvErr(); - svPulls[1] = svResiduals[1] / candidate.ySvErr(); - svPulls[2] = svResiduals[2] / candidate.zSvErr(); - } catch (const std::runtime_error& error) { - LOG(info) << "Run time error found: " << error.what() << ". Set values of vertex pulls to -9999.9."; - } - - // fill table - rowCandidateResiduals( - origin, - pResidual, - ptResidual, - pvResiduals[0], - pvResiduals[1], - pvResiduals[2], - pvPulls[0], - pvPulls[1], - pvPulls[2], - svResiduals[0], - svResiduals[1], - svResiduals[2], - svPulls[0], - svPulls[1], - svPulls[2]); - } // loop over reconstructed signal - } - PROCESS_SWITCH(HfTreeCreatorXicToXiPiPi, processResiduals, "Process Residuals and pulls for both DCAFitter and KFParticle reconstruction", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGHF/Utils/utilsEvSelHf.h b/PWGHF/Utils/utilsEvSelHf.h index 5d57ffb5eff..63e3e72d7e4 100644 --- a/PWGHF/Utils/utilsEvSelHf.h +++ b/PWGHF/Utils/utilsEvSelHf.h @@ -203,7 +203,7 @@ struct HfEventSelection : o2::framework::ConfigurableGroup { hPosZAfterEvSel = registry.add(NameHistPosZAfterEvSel, "selected events;#it{z}_{prim. vtx.} (cm);entries", {o2::framework::HistType::kTH1D, {{400, -20., 20.}}}); hPosXAfterEvSel = registry.add(NameHistPosXAfterEvSel, "selected events;#it{x}_{prim. vtx.} (cm);entries", {o2::framework::HistType::kTH1D, {{200, -0.5, 0.5}}}); hPosYAfterEvSel = registry.add(NameHistPosYAfterEvSel, "selected events;#it{y}_{prim. vtx.} (cm);entries", {o2::framework::HistType::kTH1D, {{200, -0.5, 0.5}}}); - hNumPvContributorsAfterSel = registry.add(NameHistNumPvContributorsAfterSel, "selected events;#it{y}_{prim. vtx.} (cm);entries", {o2::framework::HistType::kTH1D, {{500, -0.5, 499.5}}}); + hNumPvContributorsAfterSel = registry.add(NameHistNumPvContributorsAfterSel, "selected events;number of prim. vtx. contributors;entries", {o2::framework::HistType::kTH1D, {{500, -0.5, 499.5}}}); setEventRejectionLabels(hCollisions, softwareTrigger); const o2::framework::AxisSpec th2AxisCent{th2ConfigAxisCent, "Centrality"}; From e501845932879c7295e35ac2114b90df03626b40 Mon Sep 17 00:00:00 2001 From: Rohaan Deb <67634136+RD0407@users.noreply.github.com> Date: Mon, 23 Jun 2025 17:33:17 +0200 Subject: [PATCH 191/871] [PWGLF] PWGLF/Tasks/Nuspex/spectraTOF.cxx : Bug Fixes (#11734) --- PWGLF/Tasks/Nuspex/spectraTOF.cxx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/PWGLF/Tasks/Nuspex/spectraTOF.cxx b/PWGLF/Tasks/Nuspex/spectraTOF.cxx index bff2593257a..f80b2870959 100644 --- a/PWGLF/Tasks/Nuspex/spectraTOF.cxx +++ b/PWGLF/Tasks/Nuspex/spectraTOF.cxx @@ -1206,7 +1206,7 @@ struct tofSpectra { return false; } } - return (std::abs(track.dcaXY()) <= (maxDcaXYFactor.value * (0.0105f + 0.0350f / pow(track.pt(), 1.1f)))); + return (std::abs(track.dcaXY()) <= (maxDcaXYFactor.value * (0.0105f + 0.0350f / std::pow(track.pt(), 1.1f)))); } return track.isGlobalTrack(); } @@ -1887,7 +1887,9 @@ struct tofSpectra { if (!isParticleEnabled()) { // Check if the particle is enabled return; } - + if (!collision.has_mcCollision()) { + return; // Skips processing if no corresponding MC collision is found (rare case!) + } const auto& mcCollision = collision.mcCollision_as(); const float multiplicity = getMultiplicity(collision); const int occupancy = collision.trackOccupancyInTimeRange(); From ed25c14ad7e8d9fbda74b500bdfc3e5eea10f2d0 Mon Sep 17 00:00:00 2001 From: Tanu Gahlaut <154991749+TGahlaut1@users.noreply.github.com> Date: Tue, 24 Jun 2025 01:03:28 +0530 Subject: [PATCH 192/871] [PWGCF] Update meanPtFlucId.cxx (#11738) --- PWGCF/EbyEFluctuations/Tasks/meanPtFlucId.cxx | 124 ++++++++++-------- 1 file changed, 68 insertions(+), 56 deletions(-) diff --git a/PWGCF/EbyEFluctuations/Tasks/meanPtFlucId.cxx b/PWGCF/EbyEFluctuations/Tasks/meanPtFlucId.cxx index 9f1187560f2..d6eca57ad0e 100644 --- a/PWGCF/EbyEFluctuations/Tasks/meanPtFlucId.cxx +++ b/PWGCF/EbyEFluctuations/Tasks/meanPtFlucId.cxx @@ -54,22 +54,19 @@ struct MeanPtFlucId { Configurable cfgCutDcaZ{"cfgCutDcaZ", 0.15, "DCAz cut"}; Configurable cfgCutPosZ{"cfgCutPosZ", 7.0, "cut for vertex Z"}; Configurable cfgPosZ{"cfgPosZ", true, "Position Z"}; - Configurable cfgCutNSig2{"cfgCutNSig2", 2.0, "nSigma cut (2)"}; - Configurable cfgCutNSig3{"cfgCutNSig3", 3.0, "nSigma cut (3)"}; - Configurable cfgCutNSig5{"cfgCutNSig5", 5.0, "nSigma cut (3)"}; + Configurable cfgCutNSig2{"cfgCutNSig2", 2.0, "nSigma cut: 2"}; + Configurable cfgCutNSig3{"cfgCutNSig3", 3.0, "nSigma cut: 3"}; + Configurable cfgCutNSig5{"cfgCutNSig5", 5.0, "nSigma cut: 5"}; + Configurable cfgSelCutNSigPi{"cfgSelCutNSigPi", 2.0, "nSigma cut for pion selection"}; + Configurable cfgSelCutNSigKa{"cfgSelCutNSigKa", 3.0, "nSigma cut for kaon selection"}; + Configurable cfgSelCutNSigPr{"cfgSelCutNSigPr", 2.0, "nSigma cut for proton selection"}; + Configurable cfgRejCutNSigPi{"cfgRejCutNSigPi", 3.0, "nSigma cut for rejection of other particles while selecting pion"}; Configurable cfgCutPiPtMin{"cfgCutPiPtMin", 0.2, "Minimum pion p_{T} cut"}; Configurable cfgCutKaPtMin{"cfgCutKaPtMin", 0.3, "Minimum kaon p_{T} cut"}; Configurable cfgCutPrPtMin{"cfgCutPrPtMin", 0.5, "Minimum proton p_{T} cut"}; Configurable cfgCutPiThrsldP{"cfgCutPiThrsldP", 0.6, "Threshold p cut pion"}; Configurable cfgCutKaThrsldP{"cfgCutKaThrsldP", 0.6, "Threshold p cut kaon"}; Configurable cfgCutPrThrsldP{"cfgCutPrThrsldP", 1.0, "Threshold p cut proton "}; - Configurable cfgCutPiP1{"cfgCutPiP1", 0.5, "pion p cut-1"}; - Configurable cfgCutPiP2{"cfgCutPiP2", 0.6, "pion p cut-2"}; - Configurable cfgCutKaP1{"cfgCutKaP1", 0.4, "kaon p cut-1"}; - Configurable cfgCutKaP2{"cfgCutKaP2", 0.6, "kaon p cut-2"}; - Configurable cfgCutKaP3{"cfgCutKaP3", 1.2, "kaon p cut-3"}; - Configurable cfgCutPrP1{"cfgCutPrP1", 0.9, "proton p cut-1"}; - Configurable cfgCutPrP2{"cfgCutPrP2", 1.0, "proton p cut-2"}; Configurable cfgSel8{"cfgSel8", true, "Sel8 trigger"}; Configurable cfgMinWeight{"cfgMinWeight", 1e-6, "Minimum weight for efficiency correction"}; Configurable cfgNoSameBunchPileup{"cfgNoSameBunchPileup", true, "kNoSameBunchPileup"}; @@ -455,50 +452,63 @@ struct MeanPtFlucId { return false; } - template - PIDType identifyParticle(const T& track) + template + bool identifyParticle(T const& track, float momThreshold) { - const float pt = track.pt(); - const float p = track.p(); - - // Check pion - const bool tpcPi = std::fabs(track.tpcNSigmaPi()) < cfgCutNSig3 && std::fabs(track.tpcNSigmaPi()) < std::fabs(track.tpcNSigmaKa()) && std::fabs(track.tpcNSigmaPi()) < std::fabs(track.tpcNSigmaPr()); - const bool tofPi = track.hasTOF() && std::fabs(track.tofNSigmaPi()) < cfgCutNSig3 && std::fabs(track.tofNSigmaPi()) < std::fabs(track.tofNSigmaKa()) && std::fabs(track.tofNSigmaPi()) < std::fabs(track.tofNSigmaPr()); - const bool isPi = (pt >= cfgCutPiPtMin && - ((p <= cfgCutPiThrsldP && ((tpcPi && !track.hasTOF()) || (tpcPi && tofPi))) || - (p > cfgCutPiThrsldP && tpcPi && tofPi))); - - // Check kaon - const bool tpcKa = std::fabs(track.tpcNSigmaKa()) < cfgCutNSig3 && std::fabs(track.tpcNSigmaKa()) < std::fabs(track.tpcNSigmaPi()) && std::fabs(track.tpcNSigmaKa()) < std::fabs(track.tpcNSigmaPr()); - const bool tofKa = track.hasTOF() && std::fabs(track.tofNSigmaKa()) < cfgCutNSig3 && std::fabs(track.tofNSigmaKa()) < std::fabs(track.tofNSigmaPi()) && std::fabs(track.tofNSigmaKa()) < std::fabs(track.tofNSigmaPr()); - const bool tofKaTight = track.hasTOF() && std::fabs(track.tofNSigmaKa()) < cfgCutNSig2; - const bool isKa = (pt >= cfgCutKaPtMin && - ((p <= cfgCutKaThrsldP && ((tpcKa && !track.hasTOF()) || (tpcKa && tofKa))) || - (p > cfgCutKaThrsldP && tpcKa && - ((tofKa && p <= cfgCutKaP3) || (tofKaTight && p > cfgCutKaP3))))); - - // Check proton - const bool tpcPr = std::fabs(track.tpcNSigmaPr()) < cfgCutNSig3 && std::fabs(track.tpcNSigmaPr()) < std::fabs(track.tpcNSigmaPi()) && std::fabs(track.tpcNSigmaPr()) < std::fabs(track.tpcNSigmaKa()); - const bool tofPr = track.hasTOF() && std::fabs(track.tofNSigmaPr()) < cfgCutNSig3 && std::fabs(track.tofNSigmaPr()) < std::fabs(track.tofNSigmaPi()) && std::fabs(track.tofNSigmaPr()) < std::fabs(track.tofNSigmaKa()); - const bool isPr = (pt >= cfgCutPrPtMin && - ((p <= cfgCutPrThrsldP && ((tpcPr && !track.hasTOF()) || (tpcPr && tofPr))) || - (p > cfgCutPrThrsldP && tpcPr && tofPr))); - - if (!isPi && !isKa && !isPr) { // Reject tracks that are not identified as any particle - return PIDType::kNone; + + const int sp = static_cast(s1); + const int sq = static_cast(s2); + const int sr = static_cast(s3); + std::vector vTpcNSigma = {-999., track.tpcNSigmaPi(), track.tpcNSigmaKa(), track.tpcNSigmaPr()}; + std::vector vTofNSigma = {-999., track.tofNSigmaPi(), track.tofNSigmaKa(), track.tofNSigmaPr()}; + bool isTofPidFlag = false, isTpcPidFlag = false; + + float nSigmaSelCut = 0.; + float nSigmaTofRejCut = 0.; + float nSigmaTpcRejCut = 0.; + if constexpr (s1 == PIDType::kProtons) { + nSigmaSelCut = cfgSelCutNSigPr; + nSigmaTofRejCut = std::fabs(vTofNSigma[sp]); + nSigmaTpcRejCut = std::fabs(vTpcNSigma[sp]); + } else if constexpr (s1 == PIDType::kKaons) { + nSigmaSelCut = cfgSelCutNSigKa; + nSigmaTofRejCut = std::fabs(vTofNSigma[sp]); + nSigmaTpcRejCut = std::fabs(vTpcNSigma[sp]); + } else if constexpr (s1 == PIDType::kPions) { + nSigmaSelCut = cfgSelCutNSigPi; + nSigmaTofRejCut = cfgRejCutNSigPi; + nSigmaTpcRejCut = cfgRejCutNSigPi; + } + + if (track.hasTOF()) { + if (std::fabs(vTofNSigma[sp]) < nSigmaSelCut && + std::fabs(vTofNSigma[sq]) > nSigmaTofRejCut && + std::fabs(vTofNSigma[sr]) > nSigmaTofRejCut) { + isTofPidFlag = true; + } + if (std::fabs(vTpcNSigma[sp]) < cfgCutNSig2) { + isTpcPidFlag = true; + } + } else { // select from TPC Only + if (track.p() >= momThreshold) { + return false; + } + if (std::fabs(vTpcNSigma[sp]) < nSigmaSelCut && + std::fabs(vTpcNSigma[sq]) > nSigmaTpcRejCut && + std::fabs(vTpcNSigma[sr]) > nSigmaTpcRejCut) { + isTofPidFlag = true; + isTpcPidFlag = true; + } } - if (isPi) { - return PIDType::kPions; - } else if (isKa) { - return PIDType::kKaons; - } else if (isPr) { - return PIDType::kProtons; + if (isTofPidFlag && isTpcPidFlag) { + return true; // Track is identified as one of the particles } - return PIDType::kNone; + return false; // Track is not identified as any of the particles } + // Get corrected weight for the track: template float getCorrectedWeight(T1 hWeightPt, T1 hPurePt, float pt, bool cfgWeightPt, bool cfgPurity) { @@ -647,12 +657,12 @@ struct MeanPtFlucId { hist.fill(HIST(Dire[Mode]) + HIST("h2_TOFNsigma"), track.p(), nSigmaTOF); hist.fill(HIST(Dire[Mode]) + HIST("h2_TpcTofNsigma"), nSigmaTPC, nSigmaTOF); hist.fill(HIST(Dire[Mode]) + HIST("h2_TPCSignal"), track.p(), track.tpcSignal()); - hist.fill(HIST(Dire[Mode]) + HIST("innerParam/h2_TPCSignal"), track.p(), track.tpcSignal()); + hist.fill(HIST(Dire[Mode]) + HIST("innerParam/h2_TPCSignal"), track.tpcInnerParam(), track.tpcSignal()); hist.fill(HIST(Dire[Mode]) + HIST("h2_TOFSignal"), track.p(), track.beta()); hist.fill(HIST(Dire[Mode]) + HIST("h2_pvsm2"), track.mass() * track.mass(), track.p()); hist.fill(HIST("QA/after/h2_TPCSignal"), track.p(), track.tpcSignal()); - hist.fill(HIST("QA/after/innerParam/h2_TPCSignal"), track.p(), track.tpcSignal()); + hist.fill(HIST("QA/after/innerParam/h2_TPCSignal"), track.tpcInnerParam(), track.tpcSignal()); hist.fill(HIST("QA/after/h2_TOFSignal"), track.p(), track.beta()); hist.fill(HIST("QA/after/h2_pvsm2"), track.mass() * track.mass(), track.p()); } @@ -797,16 +807,18 @@ struct MeanPtFlucId { if (cfgRejTrk && rejectTracks(track)) { continue; } - auto selID = identifyParticle(track); - if (selID == PIDType::kPions && pt >= cfgCutPiPtMin) { + auto selIDPion = identifyParticle(track, cfgCutPiThrsldP); + auto selIDKaon = identifyParticle(track, cfgCutKaThrsldP); + auto selIDProton = identifyParticle(track, cfgCutPrThrsldP); + if (selIDPion && pt >= cfgCutPiPtMin) { hist.fill(HIST("QA/Pion/h_Pt"), track.pt()); fillIdParticleQAHistos(track, rapPi, nSigmaTPCPi, nSigmaTOFPi, centFT0M, hWeightPtPi, hPurePtPi, cfgWeightPtId, cfgPurityId, nPiW, nPiW2, q1Pi, q2Pi); } - if (selID == PIDType::kKaons && pt >= cfgCutKaPtMin) { + if (selIDKaon && pt >= cfgCutKaPtMin) { hist.fill(HIST("QA/Kaon/h_Pt"), track.pt()); fillIdParticleQAHistos(track, rapKa, nSigmaTPCKa, nSigmaTOFKa, centFT0M, hWeightPtKa, hPurePtKa, cfgWeightPtId, cfgPurityId, nKaW, nKaW2, q1Ka, q2Ka); } - if (selID == PIDType::kProtons && pt >= cfgCutPrPtMin) { + if (selIDProton && pt >= cfgCutPrPtMin) { hist.fill(HIST("QA/Proton/h_Pt"), track.pt()); fillIdParticleQAHistos(track, rapPr, nSigmaTPCPr, nSigmaTOFPr, centFT0M, hWeightPtPr, hPurePtPr, cfgWeightPtId, cfgPurityId, nPrW, nPrW2, q1Pr, q2Pr); } @@ -814,7 +826,7 @@ struct MeanPtFlucId { if constexpr (RecoFlag) { auto mc = track.template mcParticle_as(); int pid = mc.pdgCode(); - if (selID == PIDType::kPions && pt >= cfgCutPiPtMin) { + if (selIDPion && pt >= cfgCutPiPtMin) { if (std::abs(pid) == kPiPlus) { hist.fill(HIST("QA/Pion/h_PtTruth"), pt); fillPtMCHist(false, pt, eta, rapPi, phi, centFT0M, pid, kPiPlus, kPiMinus); @@ -825,7 +837,7 @@ struct MeanPtFlucId { } } } - if (selID == PIDType::kKaons && pt >= cfgCutKaPtMin) { + if (selIDKaon && pt >= cfgCutKaPtMin) { if (std::abs(pid) == kKPlus) { hist.fill(HIST("QA/Kaon/h_PtTruth"), pt); fillPtMCHist(false, pt, eta, rapKa, phi, centFT0M, pid, kKPlus, kKMinus); @@ -836,7 +848,7 @@ struct MeanPtFlucId { } } } - if (selID == PIDType::kProtons && pt >= cfgCutPrPtMin) { + if (selIDProton && pt >= cfgCutPrPtMin) { if (std::abs(pid) == kProton) { hist.fill(HIST("QA/Proton/h_PtTruth"), pt); fillPtMCHist(false, pt, eta, rapPr, phi, centFT0M, pid, kProton, kProtonBar); From 6ace6af4e26a7815d255ec0bcd630c8f8a912ce6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADt=20Ku=C4=8Dera?= Date: Mon, 23 Jun 2025 22:18:04 +0200 Subject: [PATCH 193/871] [PWGHF] Fix argument copies and uninitialised members (#11686) --- PWGHF/Core/HfHelper.h | 2 +- PWGHF/TableProducer/mcPidTof.cxx | 54 +++++++++++++++----------------- 2 files changed, 27 insertions(+), 29 deletions(-) diff --git a/PWGHF/Core/HfHelper.h b/PWGHF/Core/HfHelper.h index 5c613a4b69a..933557eaa29 100644 --- a/PWGHF/Core/HfHelper.h +++ b/PWGHF/Core/HfHelper.h @@ -1263,7 +1263,7 @@ class HfHelper /// \param mlScores vector with ml scores of charm hadron (position 0:bkg 1:prompt 2:nonprompt) /// \return true if b-hadron candidate passes all selections template - bool applySelectionDmesMlScoresForB(const T1& cuts, const T2& binsPtC, float ptC, std::vector mlScores) + bool applySelectionDmesMlScoresForB(const T1& cuts, const T2& binsPtC, float ptC, const std::vector& mlScores) { int pTBin = o2::analysis::findBin(binsPtC, ptC); if (pTBin == -1) { diff --git a/PWGHF/TableProducer/mcPidTof.cxx b/PWGHF/TableProducer/mcPidTof.cxx index 6738cab46b9..6a547938d51 100644 --- a/PWGHF/TableProducer/mcPidTof.cxx +++ b/PWGHF/TableProducer/mcPidTof.cxx @@ -16,32 +16,30 @@ /// It works only for MC and adds the possibility to apply postcalibrations for MC. /// -#include -#include -#include -#include -#include - -#include - -// O2 includes -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "ReconstructionDataFormats/Track.h" -#include "CCDB/BasicCCDBManager.h" -#include "TOFBase/EventTimeMaker.h" - -// O2Physics includes -#include "TableHelper.h" -#include "MetadataHelper.h" -#include "CollisionTypeHelper.h" -#include "Common/DataModel/TrackSelectionTables.h" +#include "Common/Core/CollisionTypeHelper.h" +#include "Common/Core/MetadataHelper.h" +#include "Common/Core/TableHelper.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/FT0Corrected.h" #include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/TrackSelectionTables.h" #include "Common/TableProducer/PID/pidTOFBase.h" +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + using namespace o2; using namespace o2::framework; using namespace o2::pid; @@ -82,14 +80,14 @@ struct TOFCalibConfig { } template - void getCfg(o2::framework::InitContext& initContext, const std::string name, VType& v, const std::string task) + void getCfg(o2::framework::InitContext& initContext, const std::string& name, VType& v, const std::string& task) { if (!getTaskOptionValue(initContext, task, name, v, false)) { LOG(fatal) << "Could not get " << name << " from " << task << " task"; } } - void inheritFromBaseTask(o2::framework::InitContext& initContext, const std::string task = "tof-signal") + void inheritFromBaseTask(o2::framework::InitContext& initContext, const std::string& task = "tof-signal") { mInitMode = 2; getCfg(initContext, "ccdb-url", mUrl, task); @@ -297,7 +295,7 @@ struct TOFCalibConfig { // Configurable options std::string mUrl; std::string mPathGrpLhcIf; - int64_t mTimestamp; + int64_t mTimestamp{0}; std::string mTimeShiftCCDBPathPos; std::string mTimeShiftCCDBPathNeg; std::string mTimeShiftCCDBPathPosMC; @@ -306,10 +304,10 @@ struct TOFCalibConfig { std::string mParametrizationPath; std::string mReconstructionPass; std::string mReconstructionPassDefault; - bool mFatalOnPassNotAvailable; - bool mEnableTimeDependentResponse; - int mCollisionSystem; - bool mAutoSetProcessFunctions; + bool mFatalOnPassNotAvailable{false}; + bool mEnableTimeDependentResponse{false}; + int mCollisionSystem{-1}; + bool mAutoSetProcessFunctions{false}; }; // Part 1 TOF signal definition From 143520363e946fe8b52e053a26cd9723e8d10ed0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aust=C4=97ja=20=20Jurgaityt=C4=97?= <119352645+ZeptoStarling@users.noreply.github.com> Date: Mon, 23 Jun 2025 23:39:38 +0200 Subject: [PATCH 194/871] [PWGCF] Add producer task for Pb-Pb collisions with centrality filter (#11737) --- PWGCF/FemtoDream/Tasks/CMakeLists.txt | 5 + ...mtoDreamTripletTaskTrackTrackTrackPbPb.cxx | 528 ++++++++++++++++++ 2 files changed, 533 insertions(+) create mode 100644 PWGCF/FemtoDream/Tasks/femtoDreamTripletTaskTrackTrackTrackPbPb.cxx diff --git a/PWGCF/FemtoDream/Tasks/CMakeLists.txt b/PWGCF/FemtoDream/Tasks/CMakeLists.txt index ecc4f689ae0..4c8613e3d40 100644 --- a/PWGCF/FemtoDream/Tasks/CMakeLists.txt +++ b/PWGCF/FemtoDream/Tasks/CMakeLists.txt @@ -19,6 +19,11 @@ o2physics_add_dpl_workflow(femtodream-triplet-track-track-track PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(femtodream-triplet-track-track-track-pbpb + SOURCES femtoDreamTripletTaskTrackTrackTrackPbPb.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(femtodream-pair-track-v0 SOURCES femtoDreamPairTaskTrackV0.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore diff --git a/PWGCF/FemtoDream/Tasks/femtoDreamTripletTaskTrackTrackTrackPbPb.cxx b/PWGCF/FemtoDream/Tasks/femtoDreamTripletTaskTrackTrackTrackPbPb.cxx new file mode 100644 index 00000000000..ddb9737d7d5 --- /dev/null +++ b/PWGCF/FemtoDream/Tasks/femtoDreamTripletTaskTrackTrackTrackPbPb.cxx @@ -0,0 +1,528 @@ +// Copyright 2019-2022 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 femtoDreamTripletTaskTrackTrackTrack.cxx +/// \brief Tasks that reads the track tables and creates track triplets; only three identical particles can be used +/// \author Laura Serksnyte, TU München, laura.serksnyte@tum.de + +#include "PWGCF/DataModel/FemtoDerived.h" +#include "PWGCF/FemtoDream/Core/femtoDreamContainerThreeBody.h" +#include "PWGCF/FemtoDream/Core/femtoDreamDetaDphiStar.h" +#include "PWGCF/FemtoDream/Core/femtoDreamEventHisto.h" +#include "PWGCF/FemtoDream/Core/femtoDreamPairCleaner.h" +#include "PWGCF/FemtoDream/Core/femtoDreamParticleHisto.h" +#include "PWGCF/FemtoDream/Core/femtoDreamUtils.h" + +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/O2DatabasePDGPlugin.h" +#include "Framework/RunningWorkflowInfo.h" +#include "Framework/StepTHn.h" +#include "Framework/runDataProcessing.h" + +#include "TDatabasePDG.h" + +#include +#include + +using namespace o2; +using namespace o2::analysis::femtoDream; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::soa; + +struct femtoDreamTripletTaskTrackTrackTrack { + SliceCache cache; + Preslice perCol = aod::femtodreamparticle::fdCollisionId; + + Configurable ConfCentralityMin{"ConfCentralityMin", 0, "Minimum Centrality Percentile"}; + Configurable ConfCentralityMax{"ConfCentralityMax", 10, "Maximum Centrality Percentile"}; + + Filter EventCentrality = aod::femtodreamcollision::multV0M >= ConfCentralityMin && aod::femtodreamcollision::multV0M <= ConfCentralityMax; + using FilteredFDCollisions = soa::Filtered; + using FilteredFDCollision = FilteredFDCollisions::iterator; + + using MaskedCollisions = soa::Join; + using MaskedCollision = MaskedCollisions::iterator; + aod::femtodreamcollision::BitMaskType MaskBit = -1; + float mMassOne = -999, mMassTwo = -999, mMassThree = -999; + + /// Particle selection part + + // which CPR to use, old is with a possible bug and new is fixed + Configurable ConfUseOLD_possiblyWrong_CPR{"ConfUseOLD_possiblyWrong_CPR", true, "Use for old CPR, which possibly has a bug. This is implemented only for debugging reasons to compare old and new code on hyperloop datasets."}; + + /// Table for both particles + Configurable ConfTracksInMixedEvent{"ConfTracksInMixedEvent", 1, "Number of tracks of interest, contained in the mixed event sample: 1 - only events with at least one track of interest are used in mixing; ...; 3 - only events with at least three track of interest are used in mixing. Max value is 3"}; + Configurable ConfMaxpT{"ConfMaxpT", 4.05f, "Maximum transverse momentum of the particles"}; + Configurable ConfMinpT{"ConfMinpT", 0.3f, "Minimum transverse momentum of the particles"}; + Configurable ConfMaxDCAxy{"ConfMaxDCAxy", -0.1f, "Maximum DCAxy of the particles"}; + Configurable ConfMinDCAxy{"ConfMinDCAxy", 0.1f, "Minimum DCAxy of the particles"}; + Configurable ConfPIDthrMom{"ConfPIDthrMom", 1.f, "Momentum threshold from which TPC and TOF are required for PID"}; + Configurable ConfAtWhichRadiiToCut{"ConfAtWhichRadiiToCut", 1, "At which radii perform deta dphi selection: 0 - at PV, 1 - averaged phi, 2 - at given radii"}; + Configurable ConfAtWhichTPCRadii{"ConfAtWhichTPCRadii", 85., "If ConfAtWhichRadiiToCut = 2; this allows to select at which TPC radii to cut"}; + Configurable ConfTPCPIDBit{"ConfTPCPIDBit", 16, "PID TPC bit from cutCulator "}; + Configurable ConfTPCTOFPIDBit{"ConfTPCTOFPIDBit", 8, "PID TPCTOF bit from cutCulator"}; + Configurable ConfIsMC{"ConfIsMC", false, "Enable additional Histogramms in the case of a MonteCarlo Run"}; + Configurable ConfUse3D{"ConfUse3D", false, "Enable three dimensional histogramms (to be used only for analysis with high statistics): k* vs mT vs multiplicity"}; + Configurable ConfDCACutPtDep{"ConfDCACutPtDep", false, "Use pt dependent dca cut for tracks"}; + + // Which particles to analyse; currently support only for same species and cuts triplets + Configurable ConfPDGCodePart{"ConfPDGCodePart", 2212, "Particle PDG code"}; + Configurable ConfCutPart{"ConfCutPart", 5542474, "Track - Selection bit from cutCulator"}; + + /// Partition for selected particles + Partition SelectedParts = (aod::femtodreamparticle::partType == uint8_t(aod::femtodreamparticle::ParticleType::kTrack)) && + ifnode(aod::femtodreamparticle::pt * (nexp(aod::femtodreamparticle::eta) + nexp(-1.f * aod::femtodreamparticle::eta)) / 2.f <= ConfPIDthrMom, ncheckbit(aod::femtodreamparticle::pidcut, ConfTPCPIDBit), ncheckbit(aod::femtodreamparticle::pidcut, ConfTPCTOFPIDBit)) && + (ncheckbit(aod::femtodreamparticle::cut, ConfCutPart)) && + (aod::femtodreamparticle::pt < ConfMaxpT) && + (aod::femtodreamparticle::pt > ConfMinpT) && + ifnode(ConfDCACutPtDep, (nabs(aod::femtodreamparticle::tempFitVar) <= 0.0105f + (0.035f / npow(aod::femtodreamparticle::pt, 1.1f))), + ((aod::femtodreamparticle::tempFitVar >= ConfMinDCAxy) && + (aod::femtodreamparticle::tempFitVar <= ConfMaxDCAxy))); + ; + + Partition> SelectedPartsMC = (aod::femtodreamparticle::partType == uint8_t(aod::femtodreamparticle::ParticleType::kTrack)) && + ifnode(aod::femtodreamparticle::pt * (nexp(aod::femtodreamparticle::eta) + nexp(-1.f * aod::femtodreamparticle::eta)) / 2.f <= ConfPIDthrMom, ncheckbit(aod::femtodreamparticle::pidcut, ConfTPCPIDBit), ncheckbit(aod::femtodreamparticle::pidcut, ConfTPCTOFPIDBit)) && + (ncheckbit(aod::femtodreamparticle::cut, ConfCutPart)) && + (aod::femtodreamparticle::pt < ConfMaxpT) && + (aod::femtodreamparticle::pt > ConfMinpT) && + ifnode(ConfDCACutPtDep, (nabs(aod::femtodreamparticle::tempFitVar) <= 0.0105f + (0.035f / npow(aod::femtodreamparticle::pt, 1.1f))), + ((aod::femtodreamparticle::tempFitVar >= ConfMinDCAxy) && + (aod::femtodreamparticle::tempFitVar <= ConfMaxDCAxy))); + ; + + /// Histogramming of Selected Particles + FemtoDreamParticleHisto trackHistoSelectedParts; + FemtoDreamParticleHisto trackHistoALLSelectedParts; + + /// Histogramming for Event + FemtoDreamEventHisto eventHisto; + + /// particle part + ConfigurableAxis ConfTempFitVarBins{"ConfTempFitVarBins", {300, -0.15, 0.15}, "binning of the TempFitVar in the pT vs. TempFitVar plot"}; + ConfigurableAxis ConfTempFitVarpTBins{"ConfTempFitVarpTBins", {20, 0.5, 4.05}, "pT binning of the pT vs. TempFitVar plot"}; + ConfigurableAxis ConfBinmultTempFit{"ConfBinmultTempFit", {1, 0, 1}, "multiplicity Binning for the TempFitVar plot"}; + + /// Correlation part + 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 ConfVtxBins{"ConfVtxBins", {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"}; + + ColumnBinningPolicy colBinning{{ConfVtxBins, ConfMultBins}, true}; + + ConfigurableAxis ConfQ3Bins{"ConfQ3Bins", {2000, 0., 8.}, "binning Q3"}; + ConfigurableAxis ConfQ3BinsFor4D{"ConfQ3BinsFor4D", {500, 0., 2.}, "binning Q3 for 4D hist"}; + Configurable ConfNEventsMix{"ConfNEventsMix", 5, "Number of events for mixing"}; + Configurable ConfIsCPR{"ConfIsCPR", true, "Close Pair Rejection"}; + Configurable ConfFillCPRQA{"ConfFillCPRQA", false, "Fill Close Pair Rejection plots as a function of eta and phi"}; + Configurable ConfCPRPlotPerRadii{"ConfCPRPlotPerRadii", false, "Plot CPR per radii"}; + Configurable ConfCPRdeltaPhiMax{"ConfCPRdeltaPhiMax", 0.01, "Max. Delta Phi for Close Pair Rejection"}; + Configurable ConfCPRdeltaEtaMax{"ConfCPRdeltaEtaMax", 0.01, "Max. Delta Eta for Close Pair Rejection"}; + Configurable ConfMaxQ3IncludedInCPRPlots{"ConfMaxQ3IncludedInCPRPlots", 8., "Maximum Q3, for which the pair CPR is included in plots"}; + ConfigurableAxis ConfDummy{"ConfDummy", {1, 0, 1}, "Dummy axis"}; + + FemtoDreamContainerThreeBody sameEventCont; + FemtoDreamContainerThreeBody mixedEventCont; + FemtoDreamPairCleaner pairCleaner; + FemtoDreamDetaDphiStar pairCloseRejectionSE; + FemtoDreamDetaDphiStar pairCloseRejectionME; + /// Histogram output + HistogramRegistry qaRegistry{"TrackQA", {}, OutputObjHandlingPolicy::AnalysisObject}; + HistogramRegistry resultRegistry{"Correlations", {}, OutputObjHandlingPolicy::AnalysisObject}; + HistogramRegistry ThreeBodyQARegistry{"ThreeBodyQARegistry", {}, OutputObjHandlingPolicy::AnalysisObject}; + + void init(InitContext& context) + { + + eventHisto.init(&qaRegistry, false); + + colBinning = {{ConfVtxBins, ConfMultBins}, true}; + + trackHistoSelectedParts.init(&qaRegistry, ConfBinmultTempFit, ConfDummy, ConfTempFitVarpTBins, ConfDummy, ConfDummy, ConfTempFitVarBins, ConfDummy, ConfDummy, ConfDummy, ConfDummy, ConfDummy, ConfDummy, ConfIsMC, ConfPDGCodePart); + trackHistoALLSelectedParts.init(&qaRegistry, ConfBinmultTempFit, ConfDummy, ConfTempFitVarpTBins, ConfDummy, ConfDummy, ConfTempFitVarBins, ConfDummy, ConfDummy, ConfDummy, ConfDummy, ConfDummy, ConfDummy, ConfIsMC, ConfPDGCodePart); + + ThreeBodyQARegistry.add("TripletTaskQA/hSECollisionBins", ";bin;Entries", kTH1F, {{120, -0.5, 119.5}}); + ThreeBodyQARegistry.add("TripletTaskQA/hMECollisionBins", ";bin;Entries", kTH1F, {{120, -0.5, 119.5}}); + ThreeBodyQARegistry.add("TripletTaskQA/particle_pT_in_Triplet_SE", "; p_{T1} ; p_{T2} ; p_{T3} ; Q_{3}", kTHnSparseF, {ConfTempFitVarpTBins, ConfTempFitVarpTBins, ConfTempFitVarpTBins, ConfQ3BinsFor4D}); + ThreeBodyQARegistry.add("TripletTaskQA/particle_pT_in_Triplet_ME", "; p_{T1} ; p_{T2} ; p_{T3} ; Q_{3}", kTHnSparseF, {ConfTempFitVarpTBins, ConfTempFitVarpTBins, ConfTempFitVarpTBins, ConfQ3BinsFor4D}); + std::vector tmpVecMult = ConfMultBins; + framework::AxisSpec multAxis = {tmpVecMult, "Multiplicity"}; + ThreeBodyQARegistry.add("TripletTaskQA/hSEMultVSGoodTracks", ";Mult;GoodT", kTH2F, {multAxis, {100, 0, 100}}); + ThreeBodyQARegistry.add("TripletTaskQA/hTripletsPerEventBelow14", ";Triplets;Entries", kTH1F, {{10, 0, 10}}); + ThreeBodyQARegistry.add("TripletTaskQA/NumberOfTacksPassingSelection", ";Triplets;Entries", kTH1F, {{30, 0, 30}}); + if (ConfIsMC) { + ThreeBodyQARegistry.add("TrackMC_QA/hMazzachi", ";gen;(reco-gen)/gen", kTH2F, {{100, ConfMinpT, ConfMaxpT}, {300, -1, 1}}); + } + ThreeBodyQARegistry.add("TripletTaskQA/hCentrality", ";Centrality; Q3", kTH2F, {{100, 0, 100}, ConfQ3Bins}); + ThreeBodyQARegistry.add("TripletTaskQA/hCentralityME", ";Centrality;", kTH1F, {{100, 0.0, 100.0}}); + + sameEventCont.init(&resultRegistry, ConfQ3Bins, ConfMultBins, ConfIsMC); + mixedEventCont.init(&resultRegistry, ConfQ3Bins, ConfMultBins, ConfIsMC); + sameEventCont.setPDGCodes(ConfPDGCodePart, ConfPDGCodePart, ConfPDGCodePart); + mixedEventCont.setPDGCodes(ConfPDGCodePart, ConfPDGCodePart, ConfPDGCodePart); + pairCleaner.init(&qaRegistry); // SERKSNYTE : later check if init should be updated to have 3 separate histos + if (ConfIsCPR.value) { + pairCloseRejectionSE.init(&resultRegistry, &qaRegistry, ConfCPRdeltaPhiMax.value, ConfCPRdeltaEtaMax.value, ConfCPRPlotPerRadii.value, 1, ConfUseOLD_possiblyWrong_CPR, ConfMaxQ3IncludedInCPRPlots, false, ConfAtWhichRadiiToCut, ConfAtWhichTPCRadii, ConfFillCPRQA); + pairCloseRejectionME.init(&resultRegistry, &qaRegistry, ConfCPRdeltaPhiMax.value, ConfCPRdeltaEtaMax.value, ConfCPRPlotPerRadii.value, 2, ConfUseOLD_possiblyWrong_CPR, ConfMaxQ3IncludedInCPRPlots, false, ConfAtWhichRadiiToCut, ConfAtWhichTPCRadii, ConfFillCPRQA); + } + + // get masses + mMassOne = TDatabasePDG::Instance()->GetParticle(ConfPDGCodePart)->Mass(); + mMassTwo = TDatabasePDG::Instance()->GetParticle(ConfPDGCodePart)->Mass(); + mMassThree = TDatabasePDG::Instance()->GetParticle(ConfPDGCodePart)->Mass(); + + // get bit for the collision mask + std::bitset<8 * sizeof(aod::femtodreamcollision::BitMaskType)> mask; + int index = 0; + auto& workflows = context.services().get(); + for (DeviceSpec const& device : workflows.devices) { + if (device.name.find("femto-dream-triplet-task-track-track-track") != std::string::npos) { + if (containsNameValuePair(device.options, "ConfCutPart", ConfCutPart.value) && + containsNameValuePair(device.options, "ConfTPCPIDBit", ConfTPCPIDBit.value) && + containsNameValuePair(device.options, "ConfTPCTOFPIDBit", ConfTPCTOFPIDBit.value) && + containsNameValuePair(device.options, "ConfPIDthrMom", ConfPIDthrMom.value) && + containsNameValuePair(device.options, "ConfMaxpT", ConfMaxpT.value) && + containsNameValuePair(device.options, "ConfMinpT", ConfMinpT.value) && + containsNameValuePair(device.options, "ConfMaxDCAxy", ConfMaxDCAxy.value) && + containsNameValuePair(device.options, "ConfMinDCAxy", ConfMinDCAxy.value)) { + mask.set(index); + MaskBit = static_cast(mask.to_ulong()); + LOG(info) << "Device name matched: " << device.name; + LOG(info) << "Bitmask for collisions: " << mask.to_string(); + break; + } else { + index++; + } + } + } + + if ((doprocessSameEvent && doprocessSameEventMasked) || + (doprocessMixedEvent && doprocessMixedEventMasked) || + (doprocessSameEventMC && doprocessSameEventMCMasked) || + (doprocessMixedEventMC && doprocessMixedEventMCMasked)) { + LOG(fatal) << "Normal and masked processing cannot be activated simultaneously!"; + } + } + + template + void fillCollision(CollisionType col) + { + ThreeBodyQARegistry.fill(HIST("TripletTaskQA/hSECollisionBins"), colBinning.getBin({col.posZ(), col.multNtr()})); + eventHisto.fillQA(col); + } + + /// This function processes the same event and takes care of all the histogramming + /// @tparam PartitionType + /// @tparam PartType + /// @tparam isMC: enables Monte Carlo truth specific histograms + /// @param groupSelectedParts partition for the first particle passed by the process function + /// @param parts femtoDreamParticles table (in case of Monte Carlo joined with FemtoDreamMCLabels) + /// @param magFieldTesla magnetic field of the collision + /// @param multCol multiplicity of the collision + template + void doSameEvent(PartitionType groupSelectedParts, PartType parts, float magFieldTesla, int multCol, float centCol) + { + /// Histogramming same event + int numberOfTracksPassingSelection = 0; + for (auto& part : groupSelectedParts) { + numberOfTracksPassingSelection = numberOfTracksPassingSelection + 1; + trackHistoSelectedParts.fillQA(part, aod::femtodreamparticle::kPt, multCol, centCol); + } + ThreeBodyQARegistry.fill(HIST("TripletTaskQA/NumberOfTacksPassingSelection"), numberOfTracksPassingSelection); + + /// Now build the combinations + int numberOfTriplets = 0; + for (auto& [p1, p2, p3] : combinations(CombinationsStrictlyUpperIndexPolicy(groupSelectedParts, groupSelectedParts, groupSelectedParts))) { + auto Q3 = FemtoDreamMath::getQ3(p1, mMassOne, p2, mMassTwo, p3, mMassThree); + + if (ConfIsCPR.value) { + if (pairCloseRejectionSE.isClosePair(p1, p2, parts, magFieldTesla, Q3)) { + continue; + } + if (pairCloseRejectionSE.isClosePair(p2, p3, parts, magFieldTesla, Q3)) { + continue; + } + if (pairCloseRejectionSE.isClosePair(p1, p3, parts, magFieldTesla, Q3)) { + continue; + } + } + + // track cleaning + if (!pairCleaner.isCleanPair(p1, p2, parts)) { + continue; + } + if (!pairCleaner.isCleanPair(p2, p3, parts)) { + continue; + } + if (!pairCleaner.isCleanPair(p1, p3, parts)) { + continue; + } + + // fill pT of all three particles as a function of Q3 for lambda calculations + if (Q3 < 1.4) { + numberOfTriplets = numberOfTriplets + 1; + } + ThreeBodyQARegistry.fill(HIST("TripletTaskQA/particle_pT_in_Triplet_SE"), p1.pt(), p2.pt(), p3.pt(), Q3); + sameEventCont.setTriplet(p1, p2, p3, multCol, Q3); + ThreeBodyQARegistry.fill(HIST("TripletTaskQA/hCentrality"), centCol, Q3); + } + ThreeBodyQARegistry.fill(HIST("TripletTaskQA/hTripletsPerEventBelow14"), numberOfTriplets); + } + + /// process function to call doSameEvent with Data + /// \param col subscribe to the collision table (Data) + /// \param parts subscribe to the femtoDreamParticleTable + void processSameEvent(FilteredFDCollision& col, + o2::aod::FDParticles& parts) + { + fillCollision(col); + auto thegroupSelectedParts = SelectedParts->sliceByCached(aod::femtodreamparticle::fdCollisionId, col.globalIndex(), cache); + for (auto& part : thegroupSelectedParts) { + trackHistoALLSelectedParts.fillQA(part, aod::femtodreamparticle::kPt, col.multNtr(), col.multV0M()); + } + + if (thegroupSelectedParts.size() < 3) { + return; + } + doSameEvent(thegroupSelectedParts, parts, col.magField(), col.multNtr(), col.multV0M()); + } + PROCESS_SWITCH(femtoDreamTripletTaskTrackTrackTrack, processSameEvent, "Enable processing same event", true); + + /// process function to call doSameEvent with Data which has a mask for containing particles or not + /// \param col subscribe to the collision table (Data) + /// \param parts subscribe to the femtoDreamParticleTable + void processSameEventMasked(MaskedCollision& col, o2::aod::FDParticles& parts) + { + fillCollision(col); + auto thegroupSelectedParts = SelectedParts->sliceByCached(aod::femtodreamparticle::fdCollisionId, col.globalIndex(), cache); + for (auto& part : thegroupSelectedParts) { + trackHistoALLSelectedParts.fillQA(part, aod::femtodreamparticle::kPt, col.multNtr(), col.multV0M()); + } + if (thegroupSelectedParts.size() < 3) { + return; + } + doSameEvent(thegroupSelectedParts, parts, col.magField(), col.multNtr(), col.multV0M()); + } + PROCESS_SWITCH(femtoDreamTripletTaskTrackTrackTrack, processSameEventMasked, "Enable processing same event with masks", false); + + /// process function for to call doSameEvent with Monte Carlo + /// \param col subscribe to the collision table (Monte Carlo Reconstructed reconstructed) + /// \param parts subscribe to joined table FemtoDreamParticles and FemtoDreamMCLables to access Monte Carlo truth + /// \param FemtoDreamMCParticles subscribe to the Monte Carlo truth table + void processSameEventMC(o2::aod::FDCollision& col, + soa::Join& parts, + o2::aod::FDMCParticles&) + { + fillCollision(col); + auto thegroupSelectedParts = SelectedPartsMC->sliceByCached(aod::femtodreamparticle::fdCollisionId, col.globalIndex(), cache); + for (auto& part : thegroupSelectedParts) { + trackHistoALLSelectedParts.fillQA(part, aod::femtodreamparticle::kPt, col.multNtr(), col.multV0M()); + ThreeBodyQARegistry.fill(HIST("TrackMC_QA/hMazzachi"), part.fdMCParticle().pt(), (part.pt() - part.fdMCParticle().pt()) / part.fdMCParticle().pt()); + } + if (thegroupSelectedParts.size() < 3) { + return; + } + doSameEvent(thegroupSelectedParts, parts, col.magField(), col.multNtr(), col.multV0M()); + } + PROCESS_SWITCH(femtoDreamTripletTaskTrackTrackTrack, processSameEventMC, "Enable processing same event for Monte Carlo", false); + + /// process function for to call doSameEvent with Monte Carlo which has a mask for containing particles or not + /// \param col subscribe to the collision table (Monte Carlo Reconstructed reconstructed) + /// \param parts subscribe to joined table FemtoDreamParticles and FemtoDreamMCLables to access Monte Carlo truth + /// \param FemtoDreamMCParticles subscribe to the Monte Carlo truth table + void processSameEventMCMasked(MaskedCollision& col, + soa::Join& parts, + o2::aod::FDMCParticles&) + { + fillCollision(col); + auto thegroupSelectedParts = SelectedPartsMC->sliceByCached(aod::femtodreamparticle::fdCollisionId, col.globalIndex(), cache); + for (auto& part : thegroupSelectedParts) { + trackHistoALLSelectedParts.fillQA(part, aod::femtodreamparticle::kPt, col.multNtr(), col.multV0M()); + ThreeBodyQARegistry.fill(HIST("TrackMC_QA/hMazzachi"), part.fdMCParticle().pt(), (part.pt() - part.fdMCParticle().pt()) / part.fdMCParticle().pt()); + } + if (thegroupSelectedParts.size() < 3) { + return; + } + doSameEvent(thegroupSelectedParts, parts, col.magField(), col.multNtr(), col.multV0M()); + } + PROCESS_SWITCH(femtoDreamTripletTaskTrackTrackTrack, processSameEventMCMasked, "Enable processing same event for Monte Carlo", false); + + /// This function processes the mixed event + /// \tparam PartitionType + /// \tparam PartType + /// \tparam isMC: enables Monte Carlo truth specific histograms + /// \param groupPartsOne partition for the first particle passed by the process function + /// \param groupPartsTwo partition for the second particle passed by the process function + /// \param groupPartsThree partition for the third particle passed by the process function + /// \param parts femtoDreamParticles table (in case of Monte Carlo joined with FemtoDreamMCLabels) + /// \param magFieldTesla magnetic field of the collision + /// \param multCol multiplicity of the collision + template + void doMixedEvent(PartitionType groupPartsOne, PartitionType groupPartsTwo, PartitionType groupPartsThree, PartType parts, float magFieldTesla, int multCol) + { + for (auto& [p1, p2, p3] : combinations(CombinationsFullIndexPolicy(groupPartsOne, groupPartsTwo, groupPartsThree))) { + + auto Q3 = FemtoDreamMath::getQ3(p1, mMassOne, p2, mMassTwo, p3, mMassThree); + if (ConfIsCPR.value) { + if (pairCloseRejectionME.isClosePair(p1, p2, parts, magFieldTesla, Q3)) { + continue; + } + if (pairCloseRejectionME.isClosePair(p2, p3, parts, magFieldTesla, Q3)) { + continue; + } + + if (pairCloseRejectionME.isClosePair(p1, p3, parts, magFieldTesla, Q3)) { + continue; + } + } + // fill pT of all three particles as a function of Q3 for lambda calculations + ThreeBodyQARegistry.fill(HIST("TripletTaskQA/particle_pT_in_Triplet_ME"), p1.pt(), p2.pt(), p3.pt(), Q3); + mixedEventCont.setTriplet(p1, p2, p3, multCol, Q3); + } + } + + /// process function for to call doMixedEvent with Data + /// @param cols subscribe to the collisions table (Data) + /// @param parts subscribe to the femtoDreamParticleTable + void processMixedEvent(FilteredFDCollisions& cols, + o2::aod::FDParticles& parts) + { + for (auto& [collision1, collision2, collision3] : soa::selfCombinations(colBinning, ConfNEventsMix, -1, cols, cols, cols)) { + const int multiplicityCol = collision1.multNtr(); + ThreeBodyQARegistry.fill(HIST("TripletTaskQA/hMECollisionBins"), colBinning.getBin({collision1.posZ(), multiplicityCol})); + ThreeBodyQARegistry.fill(HIST("TripletTaskQA/hCentralityME"), collision1.multV0M()); + ThreeBodyQARegistry.fill(HIST("TripletTaskQA/hCentralityME"), collision2.multV0M()); + ThreeBodyQARegistry.fill(HIST("TripletTaskQA/hCentralityME"), collision3.multV0M()); + + auto groupPartsOne = SelectedParts->sliceByCached(aod::femtodreamparticle::fdCollisionId, collision1.globalIndex(), cache); + auto groupPartsTwo = SelectedParts->sliceByCached(aod::femtodreamparticle::fdCollisionId, collision2.globalIndex(), cache); + auto groupPartsThree = SelectedParts->sliceByCached(aod::femtodreamparticle::fdCollisionId, collision3.globalIndex(), cache); + + const auto& magFieldTesla1 = collision1.magField(); + const auto& magFieldTesla2 = collision2.magField(); + const auto& magFieldTesla3 = collision3.magField(); + if ((magFieldTesla1 != magFieldTesla2) || (magFieldTesla2 != magFieldTesla3) || (magFieldTesla1 != magFieldTesla3)) { + continue; + } + + doMixedEvent(groupPartsOne, groupPartsTwo, groupPartsThree, parts, magFieldTesla1, multiplicityCol); + } + } + PROCESS_SWITCH(femtoDreamTripletTaskTrackTrackTrack, processMixedEvent, "Enable processing mixed events", true); + + /// process function for to call doMixedEvent with Data which has a mask for containing particles or not + /// @param cols subscribe to the collisions table (Data) + /// @param parts subscribe to the femtoDreamParticleTable + void processMixedEventMasked(MaskedCollisions& cols, o2::aod::FDParticles& parts) + { + Partition PartitionMaskedCol1 = (ConfTracksInMixedEvent == 1 && (aod::femtodreamcollision::bitmaskTrackOne & MaskBit) == MaskBit) || + (ConfTracksInMixedEvent == 2 && (aod::femtodreamcollision::bitmaskTrackTwo & MaskBit) == MaskBit) || + (ConfTracksInMixedEvent == 3 && (aod::femtodreamcollision::bitmaskTrackThree & MaskBit) == MaskBit); + + PartitionMaskedCol1.bindTable(cols); + + for (auto& [collision1, collision2, collision3] : soa::selfCombinations(colBinning, ConfNEventsMix, -1, *PartitionMaskedCol1.mFiltered, *PartitionMaskedCol1.mFiltered, *PartitionMaskedCol1.mFiltered)) { + const int multiplicityCol = collision1.multNtr(); + ThreeBodyQARegistry.fill(HIST("TripletTaskQA/hMECollisionBins"), colBinning.getBin({collision1.posZ(), multiplicityCol})); + + auto groupPartsOne = SelectedParts->sliceByCached(aod::femtodreamparticle::fdCollisionId, collision1.globalIndex(), cache); + auto groupPartsTwo = SelectedParts->sliceByCached(aod::femtodreamparticle::fdCollisionId, collision2.globalIndex(), cache); + auto groupPartsThree = SelectedParts->sliceByCached(aod::femtodreamparticle::fdCollisionId, collision3.globalIndex(), cache); + + const auto& magFieldTesla1 = collision1.magField(); + const auto& magFieldTesla2 = collision2.magField(); + const auto& magFieldTesla3 = collision3.magField(); + + if ((magFieldTesla1 != magFieldTesla2) || (magFieldTesla2 != magFieldTesla3) || (magFieldTesla1 != magFieldTesla3)) { + continue; + } + + doMixedEvent(groupPartsOne, groupPartsTwo, groupPartsThree, parts, magFieldTesla1, multiplicityCol); + } + } + PROCESS_SWITCH(femtoDreamTripletTaskTrackTrackTrack, processMixedEventMasked, "Enable processing mixed events", false); + + /// brief process function for to call doMixedEvent with Monte Carlo + /// @param cols subscribe to the collisions table (Monte Carlo Reconstructed reconstructed) + /// @param parts subscribe to joined table FemtoDreamParticles and FemtoDreamMCLables to access Monte Carlo truth + /// @param FemtoDreamMCParticles subscribe to the Monte Carlo truth table + void processMixedEventMC(o2::aod::FDCollisions& cols, + soa::Join& parts, + o2::aod::FDMCParticles&) + { + for (auto& [collision1, collision2, collision3] : soa::selfCombinations(colBinning, ConfNEventsMix, -1, cols, cols, cols)) { + + const int multiplicityCol = collision1.multNtr(); + ThreeBodyQARegistry.fill(HIST("TripletTaskQA/hMECollisionBins"), colBinning.getBin({collision1.posZ(), multiplicityCol})); + + auto groupPartsOne = SelectedPartsMC->sliceByCached(aod::femtodreamparticle::fdCollisionId, collision1.globalIndex(), cache); + auto groupPartsTwo = SelectedPartsMC->sliceByCached(aod::femtodreamparticle::fdCollisionId, collision2.globalIndex(), cache); + auto groupPartsThree = SelectedPartsMC->sliceByCached(aod::femtodreamparticle::fdCollisionId, collision3.globalIndex(), cache); + + const auto& magFieldTesla1 = collision1.magField(); + const auto& magFieldTesla2 = collision2.magField(); + const auto& magFieldTesla3 = collision3.magField(); + + if ((magFieldTesla1 != magFieldTesla2) || (magFieldTesla2 != magFieldTesla3) || (magFieldTesla1 != magFieldTesla3)) { + continue; + } + // CONSIDER testing different strategies to which events to use + + doMixedEvent(groupPartsOne, groupPartsTwo, groupPartsThree, parts, magFieldTesla1, multiplicityCol); + } + } + PROCESS_SWITCH(femtoDreamTripletTaskTrackTrackTrack, processMixedEventMC, "Enable processing mixed events MC", false); + + /// brief process function for to call doMixedEvent with Monte Carlo which has a mask for containing particles or not + /// @param cols subscribe to the collisions table (Monte Carlo Reconstructed reconstructed) + /// @param parts subscribe to joined table FemtoDreamParticles and FemtoDreamMCLables to access Monte Carlo truth + /// @param FemtoDreamMCParticles subscribe to the Monte Carlo truth table + void processMixedEventMCMasked(MaskedCollisions& cols, + soa::Join& parts, + o2::aod::FDMCParticles&) + { + Partition PartitionMaskedCol1 = (ConfTracksInMixedEvent == 1 && (aod::femtodreamcollision::bitmaskTrackOne & MaskBit) == MaskBit) || + (ConfTracksInMixedEvent == 2 && (aod::femtodreamcollision::bitmaskTrackTwo & MaskBit) == MaskBit) || + (ConfTracksInMixedEvent == 3 && (aod::femtodreamcollision::bitmaskTrackThree & MaskBit) == MaskBit); + PartitionMaskedCol1.bindTable(cols); + + for (auto& [collision1, collision2, collision3] : soa::selfCombinations(colBinning, ConfNEventsMix, -1, *PartitionMaskedCol1.mFiltered, *PartitionMaskedCol1.mFiltered, *PartitionMaskedCol1.mFiltered)) { + + const int multiplicityCol = collision1.multNtr(); + ThreeBodyQARegistry.fill(HIST("TripletTaskQA/hMECollisionBins"), colBinning.getBin({collision1.posZ(), multiplicityCol})); + + auto groupPartsOne = SelectedPartsMC->sliceByCached(aod::femtodreamparticle::fdCollisionId, collision1.globalIndex(), cache); + auto groupPartsTwo = SelectedPartsMC->sliceByCached(aod::femtodreamparticle::fdCollisionId, collision2.globalIndex(), cache); + auto groupPartsThree = SelectedPartsMC->sliceByCached(aod::femtodreamparticle::fdCollisionId, collision3.globalIndex(), cache); + + const auto& magFieldTesla1 = collision1.magField(); + const auto& magFieldTesla2 = collision2.magField(); + const auto& magFieldTesla3 = collision3.magField(); + + if ((magFieldTesla1 != magFieldTesla2) || (magFieldTesla2 != magFieldTesla3) || (magFieldTesla1 != magFieldTesla3)) { + continue; + } + // CONSIDER testing different strategies to which events to use + + doMixedEvent(groupPartsOne, groupPartsTwo, groupPartsThree, parts, magFieldTesla1, multiplicityCol); + } + } + PROCESS_SWITCH(femtoDreamTripletTaskTrackTrackTrack, processMixedEventMCMasked, "Enable processing mixed events MC", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + WorkflowSpec workflow{ + adaptAnalysisTask(cfgc), + }; + return workflow; +} From f06a697f5434126c8cf3885e3d1253a31c4e958a Mon Sep 17 00:00:00 2001 From: Oleksii Lubynets Date: Tue, 24 Jun 2025 10:23:58 +0200 Subject: [PATCH 195/871] [PWGHF] Cut variation - enhance plotting features, minor code cleaning and chore (#11726) --- PWGHF/D2H/Macros/compute_fraction_cutvar.py | 84 ++++++++++++--------- PWGHF/D2H/Macros/config_cutvar_example.json | 2 +- PWGHF/D2H/Macros/cut_variation.py | 43 +++++++---- 3 files changed, 79 insertions(+), 50 deletions(-) diff --git a/PWGHF/D2H/Macros/compute_fraction_cutvar.py b/PWGHF/D2H/Macros/compute_fraction_cutvar.py index 04b3e9f6fe2..e275b74b45a 100644 --- a/PWGHF/D2H/Macros/compute_fraction_cutvar.py +++ b/PWGHF/D2H/Macros/compute_fraction_cutvar.py @@ -16,7 +16,7 @@ import ROOT # pylint: disable=import-error sys.path.insert(0, '..') from cut_variation import CutVarMinimiser -from utils.style_formatter import set_object_style +from style_formatter import set_object_style # pylint: disable=no-member,too-many-locals,too-many-statements @@ -27,6 +27,7 @@ def main(config): """ ROOT.gROOT.SetBatch(True) + ROOT.TH1.AddDirectory(False) with open(config, encoding="utf8") as fil: cfg = json.load(fil) @@ -34,13 +35,22 @@ def main(config): hist_rawy, hist_effp, hist_effnp = ([] for _ in range(3)) for filename_rawy, filename_eff in zip(cfg["rawyields"]["inputfiles"], cfg["efficiencies"]["inputfiles"]): infile_rawy = ROOT.TFile.Open(os.path.join(cfg["rawyields"]["inputdir"], filename_rawy)) - hist_rawy.append(infile_rawy.Get(cfg["rawyields"]["histoname"])) + hist_rawy_name = cfg["rawyields"]["histoname"] + hist_rawy.append(infile_rawy.Get(hist_rawy_name)) + if(hist_rawy[-1] is None): + sys.exit(f"Fatal error: Histogram with raw yield \"{hist_rawy_name}\" is absent. Exit.") hist_rawy[-1].SetDirectory(0) infile_rawy.Close() infile_eff = ROOT.TFile.Open(os.path.join(cfg["efficiencies"]["inputdir"], filename_eff)) - hist_effp.append(infile_eff.Get(cfg["efficiencies"]["histonames"]["prompt"])) - hist_effnp.append(infile_eff.Get(cfg["efficiencies"]["histonames"]["nonprompt"])) + hist_effp_name = cfg["efficiencies"]["histonames"]["prompt"] + hist_effnp_name = cfg["efficiencies"]["histonames"]["nonprompt"] + hist_effp.append(infile_eff.Get(hist_effp_name)) + hist_effnp.append(infile_eff.Get(hist_effnp_name)) + if(hist_effp[-1] is None): + sys.exit(f"Fatal error: Histogram with efficiency for prompt \"{hist_effp_name}\" is absent. Exit.") + if(hist_effnp[-1] is None): + sys.exit(f"Fatal error: Histogram with efficiency for nonprompt \"{hist_effnp}\" is absent. Exit.") hist_effp[-1].SetDirectory(0) hist_effnp[-1].SetDirectory(0) infile_eff.Close() @@ -48,8 +58,14 @@ def main(config): if cfg["central_efficiency"]["computerawfrac"]: infile_name = os.path.join(cfg["central_efficiency"]["inputdir"], cfg["central_efficiency"]["inputfile"]) infile_central_eff = ROOT.TFile.Open(infile_name) - hist_central_effp = infile_central_eff.Get(cfg["central_efficiency"]["histonames"]["prompt"]) - hist_central_effnp = infile_central_eff.Get(cfg["central_efficiency"]["histonames"]["nonprompt"]) + hist_central_effp_name = cfg["central_efficiency"]["histonames"]["prompt"] + hist_central_effp = infile_central_eff.Get(hist_central_effp_name) + if(hist_central_effp is None): + sys.exit(f"Fatal error: Histogram with central efficiency for prompt \"{hist_central_effp_name}\" is absent. Exit.") + hist_central_effnp_name = cfg["central_efficiency"]["histonames"]["nonprompt"] + hist_central_effnp = infile_central_eff.Get(hist_central_effnp_name) + if(hist_central_effnp is None): + sys.exit(f"Fatal error: Histogram with central efficiency for nonprompt \"{hist_central_effnp_name}\" is absent. Exit.") hist_central_effp.SetDirectory(0) hist_central_effnp.SetDirectory(0) infile_central_eff.Close() @@ -115,18 +131,19 @@ def main(config): output = ROOT.TFile(os.path.join(cfg["output"]["directory"], cfg["output"]["file"]), "recreate") n_sets = len(hist_rawy) + pt_axis_title = hist_rawy[0].GetXaxis().GetTitle() for ipt in range(hist_rawy[0].GetNbinsX()): pt_min = hist_rawy[0].GetXaxis().GetBinLowEdge(ipt + 1) pt_max = hist_rawy[0].GetXaxis().GetBinUpEdge(ipt + 1) rawy, effp, effnp, unc_rawy, unc_effp, unc_effnp = (np.zeros(n_sets) for _ in range(6)) for iset, (hrawy, heffp, heffnp) in enumerate(zip(hist_rawy, hist_effp, hist_effnp)): - rawy.itemset(iset, hrawy.GetBinContent(ipt + 1)) - effp.itemset(iset, heffp.GetBinContent(ipt + 1)) - effnp.itemset(iset, heffnp.GetBinContent(ipt + 1)) - unc_rawy.itemset(iset, hrawy.GetBinError(ipt + 1)) - unc_effp.itemset(iset, heffp.GetBinError(ipt + 1)) - unc_effnp.itemset(iset, heffnp.GetBinError(ipt + 1)) + rawy[iset] = hrawy.GetBinContent(ipt + 1) + effp[iset] = heffp.GetBinContent(ipt + 1) + effnp[iset] = heffnp.GetBinContent(ipt + 1) + unc_rawy[iset] = hrawy.GetBinError(ipt + 1) + unc_effp[iset] = heffp.GetBinError(ipt + 1) + unc_effnp[iset] = heffnp.GetBinError(ipt + 1) minimiser = CutVarMinimiser(rawy, effp, effnp, unc_rawy, unc_effp, unc_effnp) minimiser.minimise_system(cfg["minimisation"]["correlated"]) @@ -155,30 +172,32 @@ def main(config): hist_frac_raw_nonprompt.SetBinContent(ipt + 1, raw_frac_nonprompt[0]) hist_frac_raw_nonprompt.SetBinError(ipt + 1, raw_frac_nonprompt[1]) - canv_rawy, histos_rawy, leg_r = minimiser.plot_result(f"_pt{pt_min:.0f}_{pt_max:.0f}") + hist_bin_title = f"bin # {ipt+1}; {pt_axis_title}#in ({pt_min}; {pt_max})" + + canv_rawy, histos_rawy, leg_r = minimiser.plot_result(f"_pt{pt_min}_{pt_max}", hist_bin_title) output.cd() canv_rawy.Write() for _, hist in histos_rawy.items(): hist.Write() - canv_eff, histos_eff, leg_e = minimiser.plot_efficiencies(f"_pt{pt_min:.0f}_{pt_max:.0f}") + canv_eff, histos_eff, leg_e = minimiser.plot_efficiencies(f"_pt{pt_min}_{pt_max}", hist_bin_title) output.cd() canv_eff.Write() for _, hist in histos_eff.items(): hist.Write() - canv_frac, histos_frac, leg_f = minimiser.plot_fractions(f"_pt{pt_min:.0f}_{pt_max:.0f}") + canv_frac, histos_frac, leg_f = minimiser.plot_fractions(f"_pt{pt_min}_{pt_max}", hist_bin_title) output.cd() canv_frac.Write() for _, hist in histos_frac.items(): hist.Write() - canv_cov, histo_cov = minimiser.plot_cov_matrix(True, f"_pt{pt_min:.0f}_{pt_max:.0f}") + canv_cov, histo_cov = minimiser.plot_cov_matrix(True, f"_pt{pt_min}_{pt_max}", hist_bin_title) output.cd() canv_cov.Write() histo_cov.Write() - canv_combined = ROOT.TCanvas("canv_combined", "", 1000, 1000) + canv_combined = ROOT.TCanvas(f"canv_combined_{ipt}", "", 1000, 1000) canv_combined.Divide(2, 2) canv_combined.cd(1) canv_rawy.DrawClonePad() @@ -194,23 +213,20 @@ def main(config): output_name_frac_pdf = f"Frac_{cfg['output']['file'].replace('.root', '.pdf')}" output_name_covmat_pdf = f"CovMatrix_{cfg['output']['file'].replace('.root', '.pdf')}" output_name_pdf = f"{cfg['output']['file'].replace('.root', '.pdf')}" - if ipt == 0: - canv_rawy.SaveAs(f"{os.path.join(cfg['output']['directory'], output_name_rawy_pdf)}[") - canv_eff.SaveAs(f"{os.path.join(cfg['output']['directory'], output_name_eff_pdf)}[") - canv_frac.SaveAs(f"{os.path.join(cfg['output']['directory'], output_name_frac_pdf)}[") - canv_cov.SaveAs(f"{os.path.join(cfg['output']['directory'], output_name_covmat_pdf)}[") - canv_combined.SaveAs(f"{os.path.join(cfg['output']['directory'], output_name_pdf)}[") - canv_rawy.SaveAs(f"{os.path.join(cfg['output']['directory'], output_name_rawy_pdf)}") - canv_eff.SaveAs(f"{os.path.join(cfg['output']['directory'], output_name_eff_pdf)}") - canv_frac.SaveAs(f"{os.path.join(cfg['output']['directory'], output_name_frac_pdf)}") - canv_cov.SaveAs(f"{os.path.join(cfg['output']['directory'], output_name_covmat_pdf)}") - canv_combined.SaveAs(f"{os.path.join(cfg['output']['directory'], output_name_pdf)}") - if ipt == hist_rawy[0].GetNbinsX() - 1: - canv_rawy.SaveAs(f"{os.path.join(cfg['output']['directory'], output_name_rawy_pdf)}]") - canv_eff.SaveAs(f"{os.path.join(cfg['output']['directory'], output_name_eff_pdf)}]") - canv_frac.SaveAs(f"{os.path.join(cfg['output']['directory'], output_name_frac_pdf)}]") - canv_cov.SaveAs(f"{os.path.join(cfg['output']['directory'], output_name_covmat_pdf)}]") - canv_combined.SaveAs(f"{os.path.join(cfg['output']['directory'], output_name_pdf)}]") + + if hist_rawy[0].GetNbinsX() == 1: + print_bracket = "" + elif ipt == 0: + print_bracket = "(" + elif ipt == hist_rawy[0].GetNbinsX() - 1: + print_bracket = ")" + else: + print_bracket = "" + canv_rawy.Print(f"{os.path.join(cfg['output']['directory'], output_name_rawy_pdf)}{print_bracket}") + canv_eff.Print(f"{os.path.join(cfg['output']['directory'], output_name_eff_pdf)}{print_bracket}") + canv_frac.Print(f"{os.path.join(cfg['output']['directory'], output_name_frac_pdf)}{print_bracket}") + canv_cov.Print(f"{os.path.join(cfg['output']['directory'], output_name_covmat_pdf)}{print_bracket}") + canv_combined.Print(f"{os.path.join(cfg['output']['directory'], output_name_pdf)}{print_bracket}") output.cd() hist_corry_prompt.Write() diff --git a/PWGHF/D2H/Macros/config_cutvar_example.json b/PWGHF/D2H/Macros/config_cutvar_example.json index 6ac80c747ad..20466b37044 100644 --- a/PWGHF/D2H/Macros/config_cutvar_example.json +++ b/PWGHF/D2H/Macros/config_cutvar_example.json @@ -70,4 +70,4 @@ "directory": ".", "file": "CutVarDplus_pp13TeV_MB.root" } -} \ No newline at end of file +} diff --git a/PWGHF/D2H/Macros/cut_variation.py b/PWGHF/D2H/Macros/cut_variation.py index ba827a6309c..8c93783d205 100644 --- a/PWGHF/D2H/Macros/cut_variation.py +++ b/PWGHF/D2H/Macros/cut_variation.py @@ -12,7 +12,7 @@ import numpy as np # pylint: disable=import-error import ROOT # pylint: disable=import-error sys.path.insert(0, '..') -from utils.style_formatter import set_global_style, set_object_style +from style_formatter import set_global_style, set_object_style # pylint: disable=too-many-instance-attributes @@ -110,9 +110,9 @@ def __initialise_objects(self): self.unc_frac_nonprompt = np.zeros(shape=self.n_sets) for i_set, (rawy, effp, effnp) in enumerate(zip(self.raw_yields, self.eff_prompt, self.eff_nonprompt)): - self.m_rawy.itemset(i_set, rawy) - self.m_eff.itemset((i_set, 0), effp) - self.m_eff.itemset((i_set, 1), effnp) + self.m_rawy[i_set] = rawy + self.m_eff[(i_set, 0)] = effp + self.m_eff[(i_set, 1)] = effnp # pylint: disable=too-many-locals def minimise_system(self, correlated=True, precision=1.0e-8, max_iterations=100): @@ -165,7 +165,7 @@ def minimise_system(self, correlated=True, precision=1.0e-8, max_iterations=100) else: rho = 0.0 cov_row_col = rho * unc_row * unc_col - self.m_cov_sets.itemset((i_row, i_col), cov_row_col) + self.m_cov_sets[i_row, i_col] = cov_row_col self.m_cov_sets = np.matrix(self.m_cov_sets) self.m_weights = np.linalg.inv(np.linalg.cholesky(self.m_cov_sets)) @@ -211,10 +211,10 @@ def minimise_system(self, correlated=True, precision=1.0e-8, max_iterations=100) + der_fnp_np**2 * self.m_covariance.item(1, 1) + 2 * der_fnp_p * der_fnp_np * self.m_covariance.item(1, 0) ) - self.frac_prompt.itemset(i_set, rawyp / (rawyp + rawynp)) - self.frac_nonprompt.itemset(i_set, rawynp / (rawyp + rawynp)) - self.unc_frac_prompt.itemset(i_set, unc_fp) - self.unc_frac_nonprompt.itemset(i_set, unc_fnp) + self.frac_prompt[i_set] = rawyp / (rawyp + rawynp) + self.frac_nonprompt[i_set] = rawynp / (rawyp + rawynp) + self.unc_frac_prompt[i_set] = unc_fp + self.unc_frac_nonprompt[i_set] = unc_fnp def get_red_chi2(self): """ @@ -424,7 +424,7 @@ def get_corr_nonprompt_fraction(self): return self.get_raw_nonprompt_fraction(1.0, 1.0) # pylint: disable=no-member - def plot_result(self, suffix=""): + def plot_result(self, suffix="", title=""): """ Helper function to plot minimisation result as a function of cut set @@ -528,6 +528,9 @@ def plot_result(self, suffix=""): hist_raw_yield_prompt.Draw("histsame") hist_raw_yield_nonprompt.Draw("histsame") hist_raw_yield_sum.Draw("histsame") + tex = ROOT.TLatex() + tex.SetTextSize(0.04) + tex.DrawLatexNDC(0.05, 0.95, title) canvas.Modified() canvas.Update() @@ -540,7 +543,7 @@ def plot_result(self, suffix=""): return canvas, histos, leg - def plot_cov_matrix(self, correlated=True, suffix=""): + def plot_cov_matrix(self, correlated=True, suffix="", title=""): """ Helper function to plot covariance matrix @@ -563,6 +566,7 @@ def plot_cov_matrix(self, correlated=True, suffix=""): padleftmargin=0.14, padbottommargin=0.12, padrightmargin=0.12, + padtopmargin = 0.075, palette=ROOT.kRainBow, ) @@ -592,12 +596,15 @@ def plot_cov_matrix(self, correlated=True, suffix=""): canvas = ROOT.TCanvas(f"cCorrMatrixCutSets{suffix}", "", 500, 500) hist_corr_matrix.Draw("colz") + tex = ROOT.TLatex() + tex.SetTextSize(0.04) + tex.DrawLatexNDC(0.05, 0.95, title) canvas.Modified() canvas.Update() return canvas, hist_corr_matrix - def plot_efficiencies(self, suffix=""): + def plot_efficiencies(self, suffix="", title=""): """ Helper function to plot efficiencies as a function of cut set @@ -616,7 +623,7 @@ def plot_efficiencies(self, suffix=""): needed otherwise it is destroyed """ - set_global_style(padleftmargin=0.14, padbottommargin=0.12, titleoffset=1.2) + set_global_style(padleftmargin=0.14, padbottommargin=0.12, titleoffset=1.2, padtopmargin = 0.075) hist_eff_prompt = ROOT.TH1F( f"hEffPromptVsCut{suffix}", @@ -678,12 +685,15 @@ def plot_efficiencies(self, suffix=""): leg.AddEntry(hist_eff_prompt, "prompt", "pl") leg.AddEntry(hist_eff_nonprompt, "non-prompt", "pl") leg.Draw() + tex = ROOT.TLatex() + tex.SetTextSize(0.04) + tex.DrawLatexNDC(0.05, 0.95, title) canvas.Modified() canvas.Update() return canvas, histos, leg - def plot_fractions(self, suffix=""): + def plot_fractions(self, suffix="", title=""): """ Helper function to plot fractions as a function of cut set @@ -702,7 +712,7 @@ def plot_fractions(self, suffix=""): needed otherwise it is destroyed """ - set_global_style(padleftmargin=0.14, padbottommargin=0.12, titleoffset=1.2) + set_global_style(padleftmargin=0.14, padbottommargin=0.12, titleoffset=1.2, padtopmargin = 0.075) hist_f_prompt = ROOT.TH1F( f"hFracPromptVsCut{suffix}", @@ -757,6 +767,9 @@ def plot_fractions(self, suffix=""): leg.AddEntry(hist_f_prompt, "prompt", "pl") leg.AddEntry(hist_f_nonprompt, "non-prompt", "pl") leg.Draw() + tex = ROOT.TLatex() + tex.SetTextSize(0.04) + tex.DrawLatexNDC(0.05, 0.95, title) canvas.Modified() canvas.Update() From 774e2ce55fb0b8f3859bd6df1fff8e6e79ccd403 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADt=20Ku=C4=8Dera?= Date: Tue, 24 Jun 2025 11:25:44 +0200 Subject: [PATCH 196/871] [Tools] Include What You Use (#11552) --- Tools/KFparticle/KFUtilities.h | 23 ++++++++++++++++------- Tools/ML/MlResponse.h | 13 +++++++------ Tools/ML/model.cxx | 15 ++++++++++++++- Tools/ML/model.h | 21 ++++++++++----------- 4 files changed, 47 insertions(+), 25 deletions(-) diff --git a/Tools/KFparticle/KFUtilities.h b/Tools/KFparticle/KFUtilities.h index d1545e11651..bec24fd7adc 100644 --- a/Tools/KFparticle/KFUtilities.h +++ b/Tools/KFparticle/KFUtilities.h @@ -22,17 +22,26 @@ #define HomogeneousField #endif -#include +#include "Common/Core/RecoDecay.h" +#include "Common/Core/trackUtilities.h" + +#include +#include +#include +#include #include // FIXME -#include "KFParticle.h" -#include "KFPTrack.h" -#include "KFPVertex.h" -#include "KFParticleBase.h" -#include "KFVertex.h" +#include +#include +#include +#include -#include "Common/Core/RecoDecay.h" +#include +#include +#include +#include +#include /// @brief Function to create a KFPVertex from the collision table in the AO2Ds. /// The Multiplicity table is required to set the number of real PV Contributors diff --git a/Tools/ML/MlResponse.h b/Tools/ML/MlResponse.h index b8c192fd386..c60946bcb03 100644 --- a/Tools/ML/MlResponse.h +++ b/Tools/ML/MlResponse.h @@ -17,17 +17,18 @@ #ifndef TOOLS_ML_MLRESPONSE_H_ #define TOOLS_ML_MLRESPONSE_H_ -#include +#include "Tools/ML/model.h" + +#include +#include +#include +#include +#include #include #include #include -#include "CCDB/CcdbApi.h" -#include "Framework/Array2D.h" - -#include "Tools/ML/model.h" - namespace o2 { namespace cuts_ml diff --git a/Tools/ML/model.cxx b/Tools/ML/model.cxx index 7e2e099aa3b..62ccd9f9839 100644 --- a/Tools/ML/model.cxx +++ b/Tools/ML/model.cxx @@ -17,9 +17,22 @@ /// \brief A general-purpose class with functions for ONNX model applications /// -// ONNX includes #include "Tools/ML/model.h" +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + namespace o2 { diff --git a/Tools/ML/model.h b/Tools/ML/model.h index 1fef9154c9b..e08b84f129f 100644 --- a/Tools/ML/model.h +++ b/Tools/ML/model.h @@ -20,19 +20,18 @@ #ifndef TOOLS_ML_MODEL_H_ #define TOOLS_ML_MODEL_H_ -// C++ and system includes -#include -#include -#include -#include -#include -#include +#include -// ROOT includes -#include "TSystem.h" +#include -// O2 includes -#include "Framework/Logger.h" +#include +#include +#include +#include +#include +#include +#include +#include namespace o2 { From d766d05c68afb5316747d19a2fc16bc4f72dd8a5 Mon Sep 17 00:00:00 2001 From: Rahul Verma <110929992+rahulverma012@users.noreply.github.com> Date: Tue, 24 Jun 2025 14:55:53 +0530 Subject: [PATCH 197/871] [DPG] Added TrackMeanOccupancy variable in the D0 daughter candidates (#11743) --- DPG/Tasks/AOTTrack/D0CalibTables.h | 26 ++++++++- .../derivedDataCreatorD0Calibration.cxx | 56 ++++++++++++++----- 2 files changed, 66 insertions(+), 16 deletions(-) diff --git a/DPG/Tasks/AOTTrack/D0CalibTables.h b/DPG/Tasks/AOTTrack/D0CalibTables.h index 5825377c736..ce8683d716d 100644 --- a/DPG/Tasks/AOTTrack/D0CalibTables.h +++ b/DPG/Tasks/AOTTrack/D0CalibTables.h @@ -160,9 +160,9 @@ uint8_t getCompressedBdtScoreSgn(T bdtScore) return getCompressedUint8(bdtScore, 1. / 255); } -/// It compresses the number of sigma (0.1 sigma precision) +/// It compresses the occupancy value ///\param occupancy is the occupancy value -///\return The number of sigma compressed to a int8_t with 0.1 precision +///\return The number of occupancy compressed to a uint8_t template uint8_t getCompressedOccupancy(T occupancy) { @@ -327,6 +327,16 @@ DECLARE_SOA_COLUMN(ITSChi2NCl, itsChi2NCl, uint8_t); //! c DECLARE_SOA_COLUMN(TPCChi2NCl, tpcChi2NCl, uint8_t); //! compressed NsigmaTOF for kaons // o2-linter: disable=name/o2-column DECLARE_SOA_COLUMN(TRDChi2, trdChi2, uint8_t); //! compressed NsigmaTOF for kaons // o2-linter: disable=name/o2-column DECLARE_SOA_COLUMN(TOFChi2, tofChi2, uint8_t); //! compressed NsigmaTOF for kaons // o2-linter: disable=name/o2-column +DECLARE_SOA_COLUMN(CmoPrimUnfm80, cmoPrimUnfm80, uint8_t); +DECLARE_SOA_COLUMN(CmoFV0AUnfm80, cmoFV0AUnfm80, uint8_t); +DECLARE_SOA_COLUMN(CmoFT0AUnfm80, cmoFT0AUnfm80, uint8_t); +DECLARE_SOA_COLUMN(CmoFT0CUnfm80, cmoFT0CUnfm80, uint8_t); +DECLARE_SOA_COLUMN(CwmoPrimUnfm80, cwmoPrimUnfm80, uint8_t); +DECLARE_SOA_COLUMN(CwmoFV0AUnfm80, cwmoFV0AUnfm80, uint8_t); +DECLARE_SOA_COLUMN(CwmoFT0AUnfm80, cwmoFT0AUnfm80, uint8_t); +DECLARE_SOA_COLUMN(CwmoFT0CUnfm80, cwmoFT0CUnfm80, uint8_t); +DECLARE_SOA_COLUMN(CmoRobustT0V0PrimUnfm80, cmoRobustT0V0PrimUnfm80, uint8_t); +DECLARE_SOA_COLUMN(CwmoRobustT0V0PrimUnfm80, cwmoRobustT0V0PrimUnfm80, uint8_t); } // namespace hf_calib DECLARE_SOA_TABLE(D0CalibTrack, "AOD", "D0CALIBTRACKS", @@ -383,7 +393,17 @@ DECLARE_SOA_TABLE(D0CalibTrack, "AOD", "D0CALIBTRACKS", hf_calib::TpcNumSigmaPi, hf_calib::TpcNumSigmaKa, hf_calib::TofNumSigmaPi, - hf_calib::TofNumSigmaKa); + hf_calib::TofNumSigmaKa, + hf_calib::CmoPrimUnfm80, + hf_calib::CmoFV0AUnfm80, + hf_calib::CmoFT0AUnfm80, + hf_calib::CmoFT0CUnfm80, + hf_calib::CwmoPrimUnfm80, + hf_calib::CwmoFV0AUnfm80, + hf_calib::CwmoFT0AUnfm80, + hf_calib::CwmoFT0CUnfm80, + hf_calib::CmoRobustT0V0PrimUnfm80, + hf_calib::CwmoRobustT0V0PrimUnfm80); namespace hf_calib { diff --git a/DPG/Tasks/AOTTrack/derivedDataCreatorD0Calibration.cxx b/DPG/Tasks/AOTTrack/derivedDataCreatorD0Calibration.cxx index 1136eaff683..7e28f0b01fb 100644 --- a/DPG/Tasks/AOTTrack/derivedDataCreatorD0Calibration.cxx +++ b/DPG/Tasks/AOTTrack/derivedDataCreatorD0Calibration.cxx @@ -26,17 +26,18 @@ #include "Common/DataModel/Centrality.h" #include "Common/DataModel/CollisionAssociationTables.h" #include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/OccupancyTables.h" #include "Common/DataModel/PIDResponseTOF.h" #include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "CommonDataFormat/InteractionRecord.h" #include "Tools/ML/MlResponse.h" +#include "CommonDataFormat/InteractionRecord.h" #include #include #include -#include #include +#include #include #include @@ -101,8 +102,9 @@ struct DerivedDataCreatorD0Calibration { std::string prefix = "ml"; } cfgMl; - using TracksWCovExtraPid = soa::Join; + using TracksWCovExtraPid = soa::Join; using CollisionsWEvSel = soa::Join; + using TrackMeanOccs = soa::Join; Preslice trackIndicesPerCollision = aod::track_association::collisionId; @@ -448,20 +450,48 @@ struct DerivedDataCreatorD0Calibration { // tracks if (!selectedTracks.count(trackPos.globalIndex())) { // fill track table with positive track if not yet present - trackTable(selectedCollisions[collision.globalIndex()], - trackPos.x(), trackPos.alpha(), trackPos.y(), trackPos.z(), trackPos.snp(), trackPos.tgl(), trackPos.signed1Pt(), // stored at PV - trackPos.cYY(), trackPos.cZY(), trackPos.cZZ(), trackPos.cSnpY(), trackPos.cSnpZ(), trackPos.cSnpSnp(), trackPos.cTglY(), trackPos.cTglZ(), trackPos.cTglSnp(), trackPos.cTglTgl(), trackPos.c1PtY(), trackPos.c1PtZ(), trackPos.c1PtSnp(), trackPos.c1PtTgl(), trackPos.c1Pt21Pt2(), - trackPos.tpcInnerParam(), trackPos.flags(), trackPos.itsClusterSizes(), trackPos.tpcNClsFindable(), trackPos.tpcNClsFindableMinusFound(), trackPos.tpcNClsFindableMinusCrossedRows(), trackPos.tpcNClsShared(), trackPos.trdPattern(), getCompressedChi2(trackPos.itsChi2NCl()), getCompressedChi2(trackPos.tpcChi2NCl()), getCompressedChi2(trackPos.trdChi2()), getCompressedChi2(trackPos.tofChi2()), trackPos.tpcSignal(), trackPos.trdSignal(), trackPos.length(), trackPos.tofExpMom(), trackPos.trackTime(), trackPos.trackTimeRes(), - dcaPos.getY(), dcaPos.getZ(), getCompressedNumSigmaPid(trackPos.tpcNSigmaPi()), getCompressedNumSigmaPid(trackPos.tpcNSigmaKa()), getCompressedNumSigmaPid(trackPos.tofNSigmaPi()), getCompressedNumSigmaPid(trackPos.tofNSigmaKa())); + if (trackPos.tmoId() != -1) { + auto tmoFromTrack = trackPos.tmo_as(); // obtain track mean occupancies + trackTable(selectedCollisions[collision.globalIndex()], + trackPos.x(), trackPos.alpha(), trackPos.y(), trackPos.z(), trackPos.snp(), trackPos.tgl(), trackPos.signed1Pt(), // stored at PV + trackPos.cYY(), trackPos.cZY(), trackPos.cZZ(), trackPos.cSnpY(), trackPos.cSnpZ(), trackPos.cSnpSnp(), trackPos.cTglY(), trackPos.cTglZ(), trackPos.cTglSnp(), trackPos.cTglTgl(), trackPos.c1PtY(), trackPos.c1PtZ(), trackPos.c1PtSnp(), trackPos.c1PtTgl(), trackPos.c1Pt21Pt2(), + trackPos.tpcInnerParam(), trackPos.flags(), trackPos.itsClusterSizes(), trackPos.tpcNClsFindable(), trackPos.tpcNClsFindableMinusFound(), trackPos.tpcNClsFindableMinusCrossedRows(), trackPos.tpcNClsShared(), trackPos.trdPattern(), getCompressedChi2(trackPos.itsChi2NCl()), getCompressedChi2(trackPos.tpcChi2NCl()), getCompressedChi2(trackPos.trdChi2()), getCompressedChi2(trackPos.tofChi2()), trackPos.tpcSignal(), trackPos.trdSignal(), trackPos.length(), trackPos.tofExpMom(), trackPos.trackTime(), trackPos.trackTimeRes(), + dcaPos.getY(), dcaPos.getZ(), getCompressedNumSigmaPid(trackPos.tpcNSigmaPi()), getCompressedNumSigmaPid(trackPos.tpcNSigmaKa()), getCompressedNumSigmaPid(trackPos.tofNSigmaPi()), getCompressedNumSigmaPid(trackPos.tofNSigmaKa()), + getCompressedOccupancy(tmoFromTrack.tmoPrimUnfm80()), getCompressedOccupancy(tmoFromTrack.tmoFV0AUnfm80()), getCompressedOccupancy(tmoFromTrack.tmoFT0AUnfm80()), getCompressedOccupancy(tmoFromTrack.tmoFT0CUnfm80()), + getCompressedOccupancy(tmoFromTrack.twmoPrimUnfm80()), getCompressedOccupancy(tmoFromTrack.twmoFV0AUnfm80()), getCompressedOccupancy(tmoFromTrack.twmoFT0AUnfm80()), getCompressedOccupancy(tmoFromTrack.twmoFT0CUnfm80()), + getCompressedOccupancy(tmoFromTrack.tmoRobustT0V0PrimUnfm80()), getCompressedOccupancy(tmoFromTrack.twmoRobustT0V0PrimUnfm80())); + } else { + // if track doesn't have occupancies stored for it + trackTable(selectedCollisions[collision.globalIndex()], + trackPos.x(), trackPos.alpha(), trackPos.y(), trackPos.z(), trackPos.snp(), trackPos.tgl(), trackPos.signed1Pt(), // stored at PV + trackPos.cYY(), trackPos.cZY(), trackPos.cZZ(), trackPos.cSnpY(), trackPos.cSnpZ(), trackPos.cSnpSnp(), trackPos.cTglY(), trackPos.cTglZ(), trackPos.cTglSnp(), trackPos.cTglTgl(), trackPos.c1PtY(), trackPos.c1PtZ(), trackPos.c1PtSnp(), trackPos.c1PtTgl(), trackPos.c1Pt21Pt2(), + trackPos.tpcInnerParam(), trackPos.flags(), trackPos.itsClusterSizes(), trackPos.tpcNClsFindable(), trackPos.tpcNClsFindableMinusFound(), trackPos.tpcNClsFindableMinusCrossedRows(), trackPos.tpcNClsShared(), trackPos.trdPattern(), getCompressedChi2(trackPos.itsChi2NCl()), getCompressedChi2(trackPos.tpcChi2NCl()), getCompressedChi2(trackPos.trdChi2()), getCompressedChi2(trackPos.tofChi2()), trackPos.tpcSignal(), trackPos.trdSignal(), trackPos.length(), trackPos.tofExpMom(), trackPos.trackTime(), trackPos.trackTimeRes(), + dcaPos.getY(), dcaPos.getZ(), getCompressedNumSigmaPid(trackPos.tpcNSigmaPi()), getCompressedNumSigmaPid(trackPos.tpcNSigmaKa()), getCompressedNumSigmaPid(trackPos.tofNSigmaPi()), getCompressedNumSigmaPid(trackPos.tofNSigmaKa()), + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + } selectedTracks[trackPos.globalIndex()] = trackTable.lastIndex(); } if (!selectedTracks.count(trackNeg.globalIndex())) { // fill track table with negative track if not yet present - trackTable(selectedCollisions[collision.globalIndex()], - trackNeg.x(), trackNeg.alpha(), trackNeg.y(), trackNeg.z(), trackNeg.snp(), trackNeg.tgl(), trackNeg.signed1Pt(), // stored at PV - trackNeg.cYY(), trackNeg.cZY(), trackNeg.cZZ(), trackNeg.cSnpY(), trackNeg.cSnpZ(), trackNeg.cSnpSnp(), trackNeg.cTglY(), trackNeg.cTglZ(), trackNeg.cTglSnp(), trackNeg.cTglTgl(), trackNeg.c1PtY(), trackNeg.c1PtZ(), trackNeg.c1PtSnp(), trackNeg.c1PtTgl(), trackNeg.c1Pt21Pt2(), - trackNeg.tpcInnerParam(), trackNeg.flags(), trackNeg.itsClusterSizes(), trackNeg.tpcNClsFindable(), trackNeg.tpcNClsFindableMinusFound(), trackNeg.tpcNClsFindableMinusCrossedRows(), trackNeg.tpcNClsShared(), trackNeg.trdPattern(), getCompressedChi2(trackNeg.itsChi2NCl()), getCompressedChi2(trackNeg.tpcChi2NCl()), getCompressedChi2(trackNeg.trdChi2()), getCompressedChi2(trackNeg.tofChi2()), trackNeg.tpcSignal(), trackNeg.trdSignal(), trackNeg.length(), trackNeg.tofExpMom(), trackNeg.trackTime(), trackNeg.trackTimeRes(), - dcaNeg.getY(), dcaNeg.getZ(), getCompressedNumSigmaPid(trackNeg.tpcNSigmaPi()), getCompressedNumSigmaPid(trackNeg.tpcNSigmaKa()), getCompressedNumSigmaPid(trackNeg.tofNSigmaPi()), getCompressedNumSigmaPid(trackNeg.tofNSigmaKa())); + if (trackNeg.tmoId() != -1) { + auto tmoFromTrack = trackNeg.tmo_as(); + trackTable(selectedCollisions[collision.globalIndex()], + trackNeg.x(), trackNeg.alpha(), trackNeg.y(), trackNeg.z(), trackNeg.snp(), trackNeg.tgl(), trackNeg.signed1Pt(), // stored at PV + trackNeg.cYY(), trackNeg.cZY(), trackNeg.cZZ(), trackNeg.cSnpY(), trackNeg.cSnpZ(), trackNeg.cSnpSnp(), trackNeg.cTglY(), trackNeg.cTglZ(), trackNeg.cTglSnp(), trackNeg.cTglTgl(), trackNeg.c1PtY(), trackNeg.c1PtZ(), trackNeg.c1PtSnp(), trackNeg.c1PtTgl(), trackNeg.c1Pt21Pt2(), + trackNeg.tpcInnerParam(), trackNeg.flags(), trackNeg.itsClusterSizes(), trackNeg.tpcNClsFindable(), trackNeg.tpcNClsFindableMinusFound(), trackNeg.tpcNClsFindableMinusCrossedRows(), trackNeg.tpcNClsShared(), trackNeg.trdPattern(), getCompressedChi2(trackNeg.itsChi2NCl()), getCompressedChi2(trackNeg.tpcChi2NCl()), getCompressedChi2(trackNeg.trdChi2()), getCompressedChi2(trackNeg.tofChi2()), trackNeg.tpcSignal(), trackNeg.trdSignal(), trackNeg.length(), trackNeg.tofExpMom(), trackNeg.trackTime(), trackNeg.trackTimeRes(), + dcaNeg.getY(), dcaNeg.getZ(), getCompressedNumSigmaPid(trackNeg.tpcNSigmaPi()), getCompressedNumSigmaPid(trackNeg.tpcNSigmaKa()), getCompressedNumSigmaPid(trackNeg.tofNSigmaPi()), getCompressedNumSigmaPid(trackNeg.tofNSigmaKa()), + getCompressedOccupancy(tmoFromTrack.tmoPrimUnfm80()), getCompressedOccupancy(tmoFromTrack.tmoFV0AUnfm80()), getCompressedOccupancy(tmoFromTrack.tmoFT0AUnfm80()), getCompressedOccupancy(tmoFromTrack.tmoFT0CUnfm80()), + getCompressedOccupancy(tmoFromTrack.twmoPrimUnfm80()), getCompressedOccupancy(tmoFromTrack.twmoFV0AUnfm80()), getCompressedOccupancy(tmoFromTrack.twmoFT0AUnfm80()), getCompressedOccupancy(tmoFromTrack.twmoFT0CUnfm80()), + getCompressedOccupancy(tmoFromTrack.tmoRobustT0V0PrimUnfm80()), getCompressedOccupancy(tmoFromTrack.twmoRobustT0V0PrimUnfm80())); + } else { + // if track doesn't have occupancies stored for it + trackTable(selectedCollisions[collision.globalIndex()], + trackNeg.x(), trackNeg.alpha(), trackNeg.y(), trackNeg.z(), trackNeg.snp(), trackNeg.tgl(), trackNeg.signed1Pt(), // stored at PV + trackNeg.cYY(), trackNeg.cZY(), trackNeg.cZZ(), trackNeg.cSnpY(), trackNeg.cSnpZ(), trackNeg.cSnpSnp(), trackNeg.cTglY(), trackNeg.cTglZ(), trackNeg.cTglSnp(), trackNeg.cTglTgl(), trackNeg.c1PtY(), trackNeg.c1PtZ(), trackNeg.c1PtSnp(), trackNeg.c1PtTgl(), trackNeg.c1Pt21Pt2(), + trackNeg.tpcInnerParam(), trackNeg.flags(), trackNeg.itsClusterSizes(), trackNeg.tpcNClsFindable(), trackNeg.tpcNClsFindableMinusFound(), trackNeg.tpcNClsFindableMinusCrossedRows(), trackNeg.tpcNClsShared(), trackNeg.trdPattern(), getCompressedChi2(trackNeg.itsChi2NCl()), getCompressedChi2(trackNeg.tpcChi2NCl()), getCompressedChi2(trackNeg.trdChi2()), getCompressedChi2(trackNeg.tofChi2()), trackNeg.tpcSignal(), trackNeg.trdSignal(), trackNeg.length(), trackNeg.tofExpMom(), trackNeg.trackTime(), trackNeg.trackTimeRes(), + dcaNeg.getY(), dcaNeg.getZ(), getCompressedNumSigmaPid(trackNeg.tpcNSigmaPi()), getCompressedNumSigmaPid(trackNeg.tpcNSigmaKa()), getCompressedNumSigmaPid(trackNeg.tofNSigmaPi()), getCompressedNumSigmaPid(trackNeg.tofNSigmaKa()), + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + } selectedTracks[trackNeg.globalIndex()] = trackTable.lastIndex(); } From 8ac448f2ad1225f5d24aa94e1d65703637780747 Mon Sep 17 00:00:00 2001 From: yuanzhe <90246048+wang-yuanzhe@users.noreply.github.com> Date: Tue, 24 Jun 2025 11:55:23 +0200 Subject: [PATCH 198/871] [PWGLF] Store cosPA and ct in datamodel for h3l_3body (#11735) --- PWGLF/DataModel/Vtx3BodyTables.h | 24 ++++++---- .../Nuspex/decay3bodybuilder.cxx | 3 ++ PWGLF/Utils/decay3bodyBuilderHelper.h | 46 +++++++++++-------- 3 files changed, 45 insertions(+), 28 deletions(-) diff --git a/PWGLF/DataModel/Vtx3BodyTables.h b/PWGLF/DataModel/Vtx3BodyTables.h index f03dfa8254c..df07fbc0c97 100644 --- a/PWGLF/DataModel/Vtx3BodyTables.h +++ b/PWGLF/DataModel/Vtx3BodyTables.h @@ -17,10 +17,12 @@ #ifndef PWGLF_DATAMODEL_VTX3BODYTABLES_H_ #define PWGLF_DATAMODEL_VTX3BODYTABLES_H_ -#include -#include "Framework/AnalysisDataModel.h" #include "Common/Core/RecoDecay.h" + #include "CommonConstants/PhysicsConstants.h" +#include "Framework/AnalysisDataModel.h" + +#include namespace o2::aod { @@ -30,8 +32,8 @@ namespace vtx3body DECLARE_SOA_INDEX_COLUMN_FULL(TrackPr, trackPr, int, Tracks, "_pr"); //! DECLARE_SOA_INDEX_COLUMN_FULL(TrackPi, trackPi, int, Tracks, "_pi"); //! DECLARE_SOA_INDEX_COLUMN_FULL(TrackDe, trackDe, int, Tracks, "_de"); //! -DECLARE_SOA_INDEX_COLUMN(Collision, collision); //! -DECLARE_SOA_INDEX_COLUMN(Decay3Body, decay3body); //! +DECLARE_SOA_INDEX_COLUMN(Collision, collision); //! +DECLARE_SOA_INDEX_COLUMN(Decay3Body, decay3body); //! // General 3 body Vtx properties DECLARE_SOA_COLUMN(Mass, mass, float); //! candidate mass (with H3L or Anti-H3L mass hypothesis depending on deuteron charge) @@ -70,6 +72,12 @@ DECLARE_SOA_COLUMN(DCATrackPiToSV, dcaTrackPiToSv, float); //! DCA of pion to DECLARE_SOA_COLUMN(DCATrackDeToSV, dcaTrackDeToSv, float); //! DCA of deuteron to SV DECLARE_SOA_COLUMN(DCAVtxDaughters, dcaVtxdaughters, float); //! Quadratic sum of DCA between daughters at SV +// CosPA +DECLARE_SOA_COLUMN(CosPA, cosPA, float); //! Cosine of pointing angle of the 3body candidate + +// Ct +DECLARE_SOA_COLUMN(Ct, ct, float); //! Reconstruction Ct of 3body candidate + // Strangeness tracking DECLARE_SOA_COLUMN(TrackedClSize, trackedClSize, float); //! Average ITS cluster size of strangeness tracked 3body @@ -145,10 +153,6 @@ DECLARE_SOA_DYNAMIC_COLUMN(DistOverTotMom, distovertotmom, //! PV to 3 body deca return std::sqrt(std::pow(X - pvX, 2) + std::pow(Y - pvY, 2) + std::pow(Z - pvZ, 2)) / (P + 1E-10); }); -// CosPA -DECLARE_SOA_DYNAMIC_COLUMN(VtxCosPA, vtxcosPA, //! 3 body vtx CosPA - [](float X, float Y, float Z, float Px, float Py, float Pz, float pvX, float pvY, float pvZ) -> float { return RecoDecay::cpa(std::array{pvX, pvY, pvZ}, std::array{X, Y, Z}, std::array{Px, Py, Pz}); }); - // Dca to PV DECLARE_SOA_DYNAMIC_COLUMN(DCAVtxToPV, dcavtxtopv, //! DCA of 3 body vtx to PV [](float X, float Y, float Z, float Px, float Py, float Pz, float pvX, float pvY, float pvZ) -> float { return std::sqrt((std::pow((pvY - Y) * Pz - (pvZ - Z) * Py, 2) + std::pow((pvX - X) * Pz - (pvZ - Z) * Px, 2) + std::pow((pvX - X) * Py - (pvY - Y) * Px, 2)) / (Px * Px + Py * Py + Pz * Pz)); }); @@ -207,6 +211,7 @@ DECLARE_SOA_TABLE(Vtx3BodyDatas, "AOD", "VTX3BODYDATA", //! vtx3body::DCAZTrackPrToPV, vtx3body::DCAZTrackPiToPV, vtx3body::DCAZTrackDeToPV, vtx3body::DCATrackPrToSV, vtx3body::DCATrackPiToSV, vtx3body::DCATrackDeToSV, vtx3body::DCAVtxDaughters, + vtx3body::CosPA, vtx3body::Ct, vtx3body::TPCNSigmaPr, vtx3body::TPCNSigmaPi, vtx3body::TPCNSigmaDe, vtx3body::TPCNSigmaPiBach, vtx3body::TOFNSigmaDe, vtx3body::ITSClSizePr, vtx3body::ITSClSizePi, vtx3body::ITSClSizeDe, @@ -218,7 +223,6 @@ DECLARE_SOA_TABLE(Vtx3BodyDatas, "AOD", "VTX3BODYDATA", //! vtx3body::Pt, vtx3body::VtxRadius, vtx3body::DistOverTotMom, - vtx3body::VtxCosPA, vtx3body::DCAVtxToPV, // Longitudinal @@ -256,6 +260,7 @@ DECLARE_SOA_TABLE(McVtx3BodyDatas, "AOD", "MC3BODYDATA", //! vtx3body::DCAZTrackPrToPV, vtx3body::DCAZTrackPiToPV, vtx3body::DCAZTrackDeToPV, vtx3body::DCATrackPrToSV, vtx3body::DCATrackPiToSV, vtx3body::DCATrackDeToSV, vtx3body::DCAVtxDaughters, + vtx3body::CosPA, vtx3body::Ct, vtx3body::TPCNSigmaPr, vtx3body::TPCNSigmaPi, vtx3body::TPCNSigmaDe, vtx3body::TPCNSigmaPiBach, vtx3body::TOFNSigmaDe, vtx3body::ITSClSizePr, vtx3body::ITSClSizePi, vtx3body::ITSClSizeDe, @@ -283,7 +288,6 @@ DECLARE_SOA_TABLE(McVtx3BodyDatas, "AOD", "MC3BODYDATA", //! vtx3body::VtxRadius, vtx3body::GenRadius, vtx3body::DistOverTotMom, - vtx3body::VtxCosPA, vtx3body::DCAVtxToPV, // Longitudinal diff --git a/PWGLF/TableProducer/Nuspex/decay3bodybuilder.cxx b/PWGLF/TableProducer/Nuspex/decay3bodybuilder.cxx index e7ddcd7b471..318e2874068 100644 --- a/PWGLF/TableProducer/Nuspex/decay3bodybuilder.cxx +++ b/PWGLF/TableProducer/Nuspex/decay3bodybuilder.cxx @@ -958,6 +958,7 @@ struct decay3bodyBuilder { -1., -1., -1., // trackDCAzToPV: 0 - proton, 1 - pion, 2 - deuteron -1., -1., -1., // daughterDCAtoSV: 0 - proton, 1 - pion, 2 - deuteron -1., // daughterDCAatSV + -1., -1., // cosPA, ctau -1., -1., -1., -1., // tpcNsigma: 0 - proton, 1 - pion, 2 - deuteron, 3 - bach with pion hyp -1., // tofNsigmaDeuteron -1., -1., -1., // average ITS cluster sizes: proton, pion, deuteron @@ -1115,6 +1116,7 @@ struct decay3bodyBuilder { helper.decay3body.trackDCAzToPV[0], helper.decay3body.trackDCAzToPV[1], helper.decay3body.trackDCAzToPV[2], // 0 - proton, 1 - pion, 2 - deuteron helper.decay3body.daughterDCAtoSV[0], helper.decay3body.daughterDCAtoSV[1], helper.decay3body.daughterDCAtoSV[2], // 0 - proton, 1 - pion, 2 - deuteron helper.decay3body.daughterDCAatSV, + helper.decay3body.cosPA, helper.decay3body.ctau, helper.decay3body.tpcNsigma[0], helper.decay3body.tpcNsigma[1], helper.decay3body.tpcNsigma[2], helper.decay3body.tpcNsigma[2], // 0 - proton, 1 - pion, 2 - deuteron, 3 - bach with pion hyp helper.decay3body.tofNsigmaDeuteron, helper.decay3body.averageITSClSize[0], helper.decay3body.averageITSClSize[1], helper.decay3body.averageITSClSize[2], // 0 - proton, 1 - pion, 2 - deuteron @@ -1143,6 +1145,7 @@ struct decay3bodyBuilder { helper.decay3body.trackDCAzToPV[0], helper.decay3body.trackDCAzToPV[1], helper.decay3body.trackDCAzToPV[2], // 0 - proton, 1 - pion, 2 - deuteron helper.decay3body.daughterDCAtoSV[0], helper.decay3body.daughterDCAtoSV[1], helper.decay3body.daughterDCAtoSV[2], // 0 - proton, 1 - pion, 2 - deuteron helper.decay3body.daughterDCAatSV, + helper.decay3body.cosPA, helper.decay3body.ctau, helper.decay3body.tpcNsigma[0], helper.decay3body.tpcNsigma[1], helper.decay3body.tpcNsigma[2], helper.decay3body.tpcNsigma[2], // 0 - proton, 1 - pion, 2 - deuteron, 3 - bach with pion hyp helper.decay3body.tofNsigmaDeuteron, helper.decay3body.averageITSClSize[0], helper.decay3body.averageITSClSize[1], helper.decay3body.averageITSClSize[2], // 0 - proton, 1 - pion, 2 - deuteron diff --git a/PWGLF/Utils/decay3bodyBuilderHelper.h b/PWGLF/Utils/decay3bodyBuilderHelper.h index 03a5b98aa08..1343bd61552 100644 --- a/PWGLF/Utils/decay3bodyBuilderHelper.h +++ b/PWGLF/Utils/decay3bodyBuilderHelper.h @@ -12,27 +12,29 @@ #ifndef PWGLF_UTILS_DECAY3BODYBUILDERHELPER_H_ #define PWGLF_UTILS_DECAY3BODYBUILDERHELPER_H_ -#include -#include -#include +#include "Common/Core/RecoDecay.h" +#include "Common/Core/trackUtilities.h" +#include "Tools/KFparticle/KFUtilities.h" + +#include "CommonConstants/PhysicsConstants.h" #include "DCAFitter/DCAFitterN.h" -#include "Framework/AnalysisDataModel.h" -#include "ReconstructionDataFormats/Track.h" #include "DetectorsBase/GeometryManager.h" #include "DetectorsVertexing/SVertexHypothesis.h" -#include "CommonConstants/PhysicsConstants.h" -#include "Common/Core/trackUtilities.h" -#include "Common/Core/RecoDecay.h" -#include "Tools/KFparticle/KFUtilities.h" +#include "Framework/AnalysisDataModel.h" +#include "ReconstructionDataFormats/Track.h" + +#include +#include +#include #ifndef HomogeneousField #define HomogeneousField #endif /// includes KFParticle -#include "KFParticle.h" #include "KFPTrack.h" #include "KFPVertex.h" +#include "KFParticle.h" #include "KFParticleBase.h" #include "KFVertex.h" @@ -78,6 +80,8 @@ struct decay3bodyCandidate { // float dcaxyToPV = 0.0f; float chi2 = 0.0f; float trackedClSize = 0.0f; + float cosPA = 0.0f; // cosine of pointing angle + float ctau = 0.0f; // ctau of the candidate float daughterDCAatSV = 0.0f; // quadratic sum of DCA between daughters at SV std::array daughterDCAtoSV = {0.0f, 0.0f, 0.0f}; // 0 - pos, 1 - neg, 2 - bach @@ -413,27 +417,33 @@ class decay3bodyBuilderHelper return false; } - // pointing angle - float cpa = RecoDecay::cpa(std::array{pvX, pvY, pvZ}, std::array{decay3body.position[0], decay3body.position[1], decay3body.position[2]}, std::array{decay3body.momentum[0], decay3body.momentum[1], decay3body.momentum[2]}); - if (cpa < decay3bodyselections.minCosPA) { + // vertex chi2 + if (decay3body.chi2 > decay3bodyselections.maxChi2) { decay3body = {}; return false; } + } - // vertex chi2 - if (decay3body.chi2 > decay3bodyselections.maxChi2) { + // pointing angle + float cpa = RecoDecay::cpa(std::array{pvX, pvY, pvZ}, std::array{decay3body.position[0], decay3body.position[1], decay3body.position[2]}, std::array{decay3body.momentum[0], decay3body.momentum[1], decay3body.momentum[2]}); + if (useSelections) { + if (cpa < decay3bodyselections.minCosPA) { decay3body = {}; return false; } + } + decay3body.cosPA = cpa; - // ctau - float P = RecoDecay::sqrtSumOfSquares(decay3body.momentum[0], decay3body.momentum[1], decay3body.momentum[2]); - float ctau = std::sqrt(std::pow(decay3body.position[0] - pvX, 2) + std::pow(decay3body.position[1] - pvY, 2) + std::pow(decay3body.position[2] - pvZ, 2)) / (P + 1E-10) * o2::constants::physics::MassHyperTriton; + // ctau + float P = RecoDecay::sqrtSumOfSquares(decay3body.momentum[0], decay3body.momentum[1], decay3body.momentum[2]); + float ctau = std::sqrt(std::pow(decay3body.position[0] - pvX, 2) + std::pow(decay3body.position[1] - pvY, 2) + std::pow(decay3body.position[2] - pvZ, 2)) / (P + 1E-10) * o2::constants::physics::MassHyperTriton; + if (useSelections) { if (ctau < decay3bodyselections.minCtau || ctau > decay3bodyselections.maxCtau) { decay3body = {}; return false; } } + decay3body.ctau = ctau; //_______________________________________________________________________ // SVertexer selections in case of event mixing From 82c740851f4c21e469f616ba59fb0e1f4ab7b1b3 Mon Sep 17 00:00:00 2001 From: Roman Lietava Date: Tue, 24 Jun 2025 18:37:39 +0200 Subject: [PATCH 199/871] [PWGLF] dev: adding track multiplicity (#11745) --- PWGLF/DataModel/LFNonPromptCascadeTables.h | 5 +++ PWGLF/Tasks/Strangeness/nonPromptCascade.cxx | 34 +++++++++++++++----- 2 files changed, 31 insertions(+), 8 deletions(-) diff --git a/PWGLF/DataModel/LFNonPromptCascadeTables.h b/PWGLF/DataModel/LFNonPromptCascadeTables.h index a4e15df33ef..b698164abd4 100644 --- a/PWGLF/DataModel/LFNonPromptCascadeTables.h +++ b/PWGLF/DataModel/LFNonPromptCascadeTables.h @@ -119,6 +119,7 @@ DECLARE_SOA_COLUMN(MultFT0M, multFT0M, float); DECLARE_SOA_COLUMN(CentFT0C, centFT0C, float); DECLARE_SOA_COLUMN(CentFT0A, centFT0A, float); DECLARE_SOA_COLUMN(CentFT0M, centFT0M, float); +DECLARE_SOA_COLUMN(MultNTracksGlobal, multNTracksGlobal, int); DECLARE_SOA_COLUMN(ToiMask, toiMask, uint32_t); } // namespace NPCascadeTable @@ -185,6 +186,7 @@ DECLARE_SOA_TABLE(NPCascTable, "AOD", "NPCASCTABLE", NPCascadeTable::CentFT0C, NPCascadeTable::CentFT0A, NPCascadeTable::CentFT0M, + NPCascadeTable::MultNTracksGlobal, NPCascadeTable::ToiMask) DECLARE_SOA_TABLE(NPCascTableNT, "AOD", "NPCASCTABLENT", @@ -250,6 +252,7 @@ DECLARE_SOA_TABLE(NPCascTableNT, "AOD", "NPCASCTABLENT", NPCascadeTable::CentFT0C, NPCascadeTable::CentFT0A, NPCascadeTable::CentFT0M, + NPCascadeTable::MultNTracksGlobal, NPCascadeTable::ToiMask) DECLARE_SOA_TABLE(NPCascTableMC, "AOD", "NPCASCTABLEMC", @@ -334,6 +337,7 @@ DECLARE_SOA_TABLE(NPCascTableMC, "AOD", "NPCASCTABLEMC", NPCascadeTable::MCcollisionMatch, NPCascadeTable::HasFakeReassociation, NPCascadeTable::MotherDecayDaughters, + NPCascadeTable::MultNTracksGlobal, NPCascadeTable::ToiMask) DECLARE_SOA_TABLE(NPCascTableMCNT, "AOD", "NPCASCTABLEMCNT", @@ -418,6 +422,7 @@ DECLARE_SOA_TABLE(NPCascTableMCNT, "AOD", "NPCASCTABLEMCNT", NPCascadeTable::MCcollisionMatch, NPCascadeTable::HasFakeReassociation, NPCascadeTable::MotherDecayDaughters, + NPCascadeTable::MultNTracksGlobal, NPCascadeTable::ToiMask) DECLARE_SOA_TABLE(NPCascTableGen, "AOD", "NPCASCTABLEGen", diff --git a/PWGLF/Tasks/Strangeness/nonPromptCascade.cxx b/PWGLF/Tasks/Strangeness/nonPromptCascade.cxx index bb2960e745b..79e8ad6f4e0 100644 --- a/PWGLF/Tasks/Strangeness/nonPromptCascade.cxx +++ b/PWGLF/Tasks/Strangeness/nonPromptCascade.cxx @@ -125,6 +125,7 @@ struct NPCascCandidate { float centFT0C; float centFT0A; float centFT0M; + int multNTracksGlobal; uint32_t toiMask; }; std::array isFromHF(auto& particle) @@ -174,12 +175,14 @@ struct NonPromptCascadeTask { using TracksExtData = soa::Join; using TracksExtMC = soa::Join; - using CollisionCandidatesRun3 = soa::Join; - using CollisionCandidatesRun3MC = soa::Join; + using CollisionCandidatesRun3 = soa::Join; + using CollisionCandidatesRun3MC = soa::Join; Preslice perCollision = aod::track::collisionId; Preslice perCollisionMC = aod::track::collisionId; + HistogramRegistry mRegistry; + Configurable ccdbUrl{"ccdbUrl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; Configurable cfgPropToPCA{"cfgPropToPCA", true, "create tracks version propagated to PCA"}; Configurable cfgRedoPV{"cfgRedoPV", true, "redo PV"}; @@ -207,8 +210,6 @@ struct NonPromptCascadeTask { float mBz = 0.f; o2::vertexing::DCAFitterN<2> mDCAFitter; - HistogramRegistry mRegistry; - void initCCDB(aod::BCsWithTimestamps::iterator const& bc) { if (mRunNumber == bc.runNumber()) { @@ -244,11 +245,17 @@ struct NonPromptCascadeTask { mDCAFitter.setUseAbsDCA(cfgUseAbsDCA); std::vector ptBinning = {0.4, 0.8, 1.2, 1.6, 2.0, 2.4, 2.8, 3.2, 3.6, 4.0, 4.4, 4.8, 5.2, 5.6, 6.0}; - AxisSpec ptAxis = {ptBinning, "#it{p}_{T} (GeV/#it{c})"}; + // AxisSpec ptAxis = {ptBinning, "#it{p}_{T} (GeV/#it{c})"}; + AxisSpec centAxis = {101, 0., 101., "Centrality"}; + AxisSpec centAxisZoom = {100, 0., 1., "Centrality"}; + AxisSpec multAxis = {10000, 0, 10000, "Multiplicity"}; + AxisSpec multAxisZoom = {1000, 0, 1000, "Multiplicity"}; std::array cutsNames{"# candidates", "hasTOF", "nClusTPC", "nSigmaTPCbach", "nSigmaTPCprotontrack", "nSigmaTPCpiontrack", "cosPA"}; auto cutsOmega{std::get>(mRegistry.add("h_PIDcutsOmega", ";;Invariant mass (GeV/#it{c}^{2})", HistType::kTH2D, {{cutsNames.size(), -0.5, -0.5 + cutsNames.size()}, {125, 1.650, 1.700}}))}; auto cutsXi{std::get>(mRegistry.add("h_PIDcutsXi", ";;Invariant mass (GeV/#it{c}^{2})", HistType::kTH2D, {{6, -0.5, 5.5}, {125, 1.296, 1.346}}))}; + mRegistry.add("hMultVsCent", "hMultVsCent", HistType::kTH2F, {centAxis, multAxis}); + mRegistry.add("hMultVsCentZoom", "hMultVsCentZoom", HistType::kTH2F, {centAxisZoom, multAxisZoom}); for (size_t iBin{0}; iBin < cutsNames.size(); ++iBin) { cutsOmega->GetYaxis()->SetBinLabel(iBin + 1, cutsNames[iBin].c_str()); @@ -314,6 +321,16 @@ struct NonPromptCascadeTask { } } } + void fillMultHistos(const auto& collisions) + { + std::cout << "Filling mult histos" << std::endl; + for (const auto& coll : collisions) { + // std::cout << coll.centFT0M() << " mult, cent " << coll.multFT0M() << std::endl; + mRegistry.fill(HIST("hMultVsCent"), coll.centFT0M(), coll.multFT0M()); + mRegistry.fill(HIST("hMultVsCentZoom"), coll.centFT0M(), coll.multFT0M()); + } + }; + template void fillCandidatesVector(CollisionType const&, TrackType const& tracks, auto const& cascades, auto& candidates, std::map toiMap = {}) { @@ -533,7 +550,7 @@ struct NonPromptCascadeTask { cascITSclusters, protonTrack.itsNCls(), pionTrack.itsNCls(), bachelor.itsNCls(), protonTrack.tpcNClsFound(), pionTrack.tpcNClsFound(), bachelor.tpcNClsFound(), protonTrack.tpcNSigmaPr(), pionTrack.tpcNSigmaPi(), bachelor.tpcNSigmaKa(), bachelor.tpcNSigmaPi(), protonTrack.hasTOF(), pionTrack.hasTOF(), bachelor.hasTOF(), - protonTrack.tofNSigmaPr(), pionTrack.tofNSigmaPi(), bachelor.tofNSigmaKa(), bachelor.tofNSigmaPi(), collision.sel8(), collision.multFT0C(), collision.multFT0A(), collision.multFT0M(), collision.centFT0C(), collision.centFT0A(), collision.centFT0M(), toiMask}); + protonTrack.tofNSigmaPr(), pionTrack.tofNSigmaPi(), bachelor.tofNSigmaKa(), bachelor.tofNSigmaPi(), collision.sel8(), collision.multFT0C(), collision.multFT0A(), collision.multFT0M(), collision.centFT0C(), collision.centFT0A(), collision.centFT0M(), collision.multNTracksGlobal(), toiMask}); } } @@ -553,7 +570,7 @@ struct NonPromptCascadeTask { c.protonTPCNSigma, c.pionTPCNSigma, c.bachKaonTPCNSigma, c.bachPionTPCNSigma, c.protonHasTOF, c.pionHasTOF, c.bachHasTOF, c.protonTOFNSigma, c.pionTOFNSigma, c.bachKaonTOFNSigma, c.bachPionTOFNSigma, - c.sel8, c.multFT0C, c.multFT0A, c.multFT0M, c.centFT0C, c.centFT0A, c.centFT0M, c.toiMask); + c.sel8, c.multFT0C, c.multFT0A, c.multFT0M, c.centFT0C, c.centFT0A, c.centFT0M, c.multNTracksGlobal, c.toiMask); } } @@ -592,7 +609,7 @@ struct NonPromptCascadeTask { c.sel8, c.multFT0C, c.multFT0A, c.multFT0M, c.centFT0C, c.centFT0A, c.centFT0M, particle.pt(), particle.eta(), particle.phi(), mcCollision.posX(), mcCollision.posY(), mcCollision.posZ(), particle.pdgCode(), mcCollision.posX() - particle.vx(), mcCollision.posY() - particle.vy(), - mcCollision.posZ() - particle.vz(), mcCollision.globalIndex() == recCollision.mcCollisionId(), c.hasFakeReassociation, motherDecayDaughters, c.toiMask); + mcCollision.posZ() - particle.vz(), mcCollision.globalIndex() == recCollision.mcCollisionId(), c.hasFakeReassociation, motherDecayDaughters, c.multNTracksGlobal, c.toiMask); } } @@ -669,6 +686,7 @@ struct NonPromptCascadeTask { aod::V0s const& /*v0s*/, TracksExtData const& tracks, aod::BCsWithTimestamps const&) { + fillMultHistos(collisions); std::map toiMap; zorroAccounting(collisions, toiMap); fillCandidatesVector(collisions, tracks, trackedCascades, gCandidates, toiMap); From f4f22523e4f43ed0ca8303fffe034624a8c4adae Mon Sep 17 00:00:00 2001 From: sgaretti <129837066+sgaretti@users.noreply.github.com> Date: Tue, 24 Jun 2025 18:45:46 +0200 Subject: [PATCH 200/871] [PWGDQ] Removing centrality info to MC gen + 2D histo impact param vs centFT0C (#11752) --- PWGDQ/Core/HistogramsLibrary.cxx | 1 + PWGDQ/DataModel/ReducedInfoTables.h | 2 +- PWGDQ/Tasks/dqEfficiency_withAssoc.cxx | 4 ++-- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/PWGDQ/Core/HistogramsLibrary.cxx b/PWGDQ/Core/HistogramsLibrary.cxx index bfd83ec9a53..7ac7e6d2e66 100644 --- a/PWGDQ/Core/HistogramsLibrary.cxx +++ b/PWGDQ/Core/HistogramsLibrary.cxx @@ -935,6 +935,7 @@ void o2::aod::dqhistograms::DefineHistograms(HistogramManager* hm, const char* h 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); + hm->AddHistogram(histClass, "MCImpPar_CentFT0CMC", "MC impact param vs MC Cent. FT0C", false, 20, 0.0, 20.0, VarManager::kMCEventImpParam, 100, 0.0, 100.0, VarManager::kCentFT0C); } if (!groupStr.CompareTo("pair")) { diff --git a/PWGDQ/DataModel/ReducedInfoTables.h b/PWGDQ/DataModel/ReducedInfoTables.h index 2b087c2b3f1..68673e81de2 100644 --- a/PWGDQ/DataModel/ReducedInfoTables.h +++ b/PWGDQ/DataModel/ReducedInfoTables.h @@ -864,7 +864,7 @@ DECLARE_SOA_TABLE(DileptonsMiniTree, "AOD", "RTDILEPTMTREE", //! dilepton_track_index::Pt2, dilepton_track_index::Eta2, dilepton_track_index::Phi2); DECLARE_SOA_TABLE(DileptonsMiniTreeGen, "AOD", "RTDILMTREEGEN", //! - reducedpair::McDecision, mccollision::ImpactParameter, reducedpair::CentFT0C, + reducedpair::McDecision, mccollision::ImpactParameter, dilepton_track_index::PtMC1, dilepton_track_index::EtaMC1, dilepton_track_index::PhiMC1, dilepton_track_index::PtMC2, dilepton_track_index::EtaMC2, dilepton_track_index::PhiMC2); diff --git a/PWGDQ/Tasks/dqEfficiency_withAssoc.cxx b/PWGDQ/Tasks/dqEfficiency_withAssoc.cxx index d5531f18dc1..a033e9a2032 100644 --- a/PWGDQ/Tasks/dqEfficiency_withAssoc.cxx +++ b/PWGDQ/Tasks/dqEfficiency_withAssoc.cxx @@ -2055,7 +2055,7 @@ struct AnalysisSameEventPairing { fHistMan->FillHistClass(Form("MCTruthGen_%s", sig->GetName()), VarManager::fgValues); if (useMiniTree.fConfigMiniTree) { auto mcEvent = mcEvents.rawIteratorAt(mctrack.reducedMCeventId()); - dileptonMiniTreeGen(mcDecision, mcEvent.impactParameter(), VarManager::fgValues[VarManager::kCentFT0C], mctrack.pt(), mctrack.eta(), mctrack.phi(), -999, -999, -999); + dileptonMiniTreeGen(mcDecision, mcEvent.impactParameter(), mctrack.pt(), mctrack.eta(), mctrack.phi(), -999, -999, -999); } } } @@ -2077,7 +2077,7 @@ struct AnalysisSameEventPairing { fHistMan->FillHistClass(Form("MCTruthGenPair_%s", sig->GetName()), VarManager::fgValues); if (useMiniTree.fConfigMiniTree) { // WARNING! To be checked - dileptonMiniTreeGen(mcDecision, -999, VarManager::fgValues[VarManager::kCentFT0C], t1.pt(), t1.eta(), t1.phi(), t2.pt(), t2.eta(), t2.phi()); + dileptonMiniTreeGen(mcDecision, -999, t1.pt(), t1.eta(), t1.phi(), t2.pt(), t2.eta(), t2.phi()); } } isig++; From ac654b4107176562eda2e3ea704237f3c37a929b Mon Sep 17 00:00:00 2001 From: Fabrizio Date: Tue, 24 Jun 2025 19:31:24 +0200 Subject: [PATCH 201/871] [DPG] Improve D0 calibration data producer (#11754) Co-authored-by: ALICE Action Bot --- DPG/Tasks/AOTTrack/D0CalibTables.h | 119 +++-- .../derivedDataCreatorD0Calibration.cxx | 412 ++++++++++++++++-- 2 files changed, 439 insertions(+), 92 deletions(-) diff --git a/DPG/Tasks/AOTTrack/D0CalibTables.h b/DPG/Tasks/AOTTrack/D0CalibTables.h index ce8683d716d..1564b6cebdf 100644 --- a/DPG/Tasks/AOTTrack/D0CalibTables.h +++ b/DPG/Tasks/AOTTrack/D0CalibTables.h @@ -13,18 +13,21 @@ /// \brief Definitions of derived tables produced by data creator for D0 calibration studies /// \author Fabrizio Grosa , CERN -#ifndef D0CALIBTABLES_H_ -#define D0CALIBTABLES_H_ +#ifndef DPG_TASKS_AOTTRACK_D0CALIBTABLES_H_ +#define DPG_TASKS_AOTTRACK_D0CALIBTABLES_H_ -#include -#include -#include +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/TrackSelectionTables.h" -#include #include +#include -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" +#include + +#include +#include +#include +#include namespace o2 { @@ -298,7 +301,7 @@ DECLARE_SOA_COLUMN(OccupancyTracks, occupancyTracks, uint8_t); //! FT0 occupancy DECLARE_SOA_COLUMN(OccupancyFT0C, occupancyFT0C, uint8_t); //! FT0 occupancy } // namespace hf_calib -DECLARE_SOA_TABLE(D0CalibColl, "AOD", "D0CALIBCOLLS", +DECLARE_SOA_TABLE(D0CalibColls, "AOD", "D0CALIBCOLL", o2::soa::Index<>, collision::PosX, collision::PosY, @@ -318,15 +321,15 @@ DECLARE_SOA_TABLE(D0CalibColl, "AOD", "D0CALIBCOLLS", namespace hf_calib { -DECLARE_SOA_INDEX_COLUMN_FULL(Collision, collision, int, D0CalibColl, ""); //! Index of collision -DECLARE_SOA_COLUMN(TpcNumSigmaPi, tpcNumSigmaPi, int8_t); //! compressed NsigmaTPC for pions -DECLARE_SOA_COLUMN(TpcNumSigmaKa, tpcNumSigmaKa, int8_t); //! compressed NsigmaTPC for kaons -DECLARE_SOA_COLUMN(TofNumSigmaPi, tofNumSigmaPi, int8_t); //! compressed NsigmaTOF for pions -DECLARE_SOA_COLUMN(TofNumSigmaKa, tofNumSigmaKa, int8_t); //! compressed NsigmaTOF for kaons -DECLARE_SOA_COLUMN(ITSChi2NCl, itsChi2NCl, uint8_t); //! compressed NsigmaTOF for kaons // o2-linter: disable=name/o2-column -DECLARE_SOA_COLUMN(TPCChi2NCl, tpcChi2NCl, uint8_t); //! compressed NsigmaTOF for kaons // o2-linter: disable=name/o2-column -DECLARE_SOA_COLUMN(TRDChi2, trdChi2, uint8_t); //! compressed NsigmaTOF for kaons // o2-linter: disable=name/o2-column -DECLARE_SOA_COLUMN(TOFChi2, tofChi2, uint8_t); //! compressed NsigmaTOF for kaons // o2-linter: disable=name/o2-column +DECLARE_SOA_INDEX_COLUMN_FULL(Collision, collision, int, D0CalibColls, ""); //! Index of collision +DECLARE_SOA_COLUMN(TpcNumSigmaPi, tpcNumSigmaPi, int8_t); //! compressed NsigmaTPC for pions +DECLARE_SOA_COLUMN(TpcNumSigmaKa, tpcNumSigmaKa, int8_t); //! compressed NsigmaTPC for kaons +DECLARE_SOA_COLUMN(TofNumSigmaPi, tofNumSigmaPi, int8_t); //! compressed NsigmaTOF for pions +DECLARE_SOA_COLUMN(TofNumSigmaKa, tofNumSigmaKa, int8_t); //! compressed NsigmaTOF for kaons +DECLARE_SOA_COLUMN(ITSChi2NCl, itsChi2NCl, uint8_t); //! compressed NsigmaTOF for kaons // o2-linter: disable=name/o2-column +DECLARE_SOA_COLUMN(TPCChi2NCl, tpcChi2NCl, uint8_t); //! compressed NsigmaTOF for kaons // o2-linter: disable=name/o2-column +DECLARE_SOA_COLUMN(TRDChi2, trdChi2, uint8_t); //! compressed NsigmaTOF for kaons // o2-linter: disable=name/o2-column +DECLARE_SOA_COLUMN(TOFChi2, tofChi2, uint8_t); //! compressed NsigmaTOF for kaons // o2-linter: disable=name/o2-column DECLARE_SOA_COLUMN(CmoPrimUnfm80, cmoPrimUnfm80, uint8_t); DECLARE_SOA_COLUMN(CmoFV0AUnfm80, cmoFV0AUnfm80, uint8_t); DECLARE_SOA_COLUMN(CmoFT0AUnfm80, cmoFT0AUnfm80, uint8_t); @@ -339,7 +342,7 @@ DECLARE_SOA_COLUMN(CmoRobustT0V0PrimUnfm80, cmoRobustT0V0PrimUnfm80, uint8_t); DECLARE_SOA_COLUMN(CwmoRobustT0V0PrimUnfm80, cwmoRobustT0V0PrimUnfm80, uint8_t); } // namespace hf_calib -DECLARE_SOA_TABLE(D0CalibTrack, "AOD", "D0CALIBTRACKS", +DECLARE_SOA_TABLE(D0CalibTracks, "AOD", "D0CALIBTRACK", o2::soa::Index<>, /// *** collision index hf_calib::CollisionId, @@ -386,7 +389,32 @@ DECLARE_SOA_TABLE(D0CalibTrack, "AOD", "D0CALIBTRACKS", track::TOFExpMom, track::TrackTime, track::TrackTimeRes, - /// *** track QA --> FIXME: info not present for each track in normal AO2Ds, check how to do + /// *** track QA + trackqa::TPCTime0, + trackqa::TPCdEdxNorm, + trackqa::TPCDCAR, + trackqa::TPCDCAZ, + trackqa::TPCClusterByteMask, + trackqa::TPCdEdxMax0R, + trackqa::TPCdEdxMax1R, + trackqa::TPCdEdxMax2R, + trackqa::TPCdEdxMax3R, + trackqa::TPCdEdxTot0R, + trackqa::TPCdEdxTot1R, + trackqa::TPCdEdxTot2R, + trackqa::TPCdEdxTot3R, + trackqa::DeltaRefContParamY, + trackqa::DeltaRefContParamZ, + trackqa::DeltaRefContParamSnp, + trackqa::DeltaRefContParamTgl, + trackqa::DeltaRefContParamQ2Pt, + trackqa::DeltaRefGloParamY, + trackqa::DeltaRefGloParamZ, + trackqa::DeltaRefGloParamSnp, + trackqa::DeltaRefGloParamTgl, + trackqa::DeltaRefGloParamQ2Pt, + trackqa::DeltaTOFdX, + trackqa::DeltaTOFdZ, /// *** DCA, Nsigma track::DcaXY, track::DcaZ, @@ -394,6 +422,7 @@ DECLARE_SOA_TABLE(D0CalibTrack, "AOD", "D0CALIBTRACKS", hf_calib::TpcNumSigmaKa, hf_calib::TofNumSigmaPi, hf_calib::TofNumSigmaKa, + /// *** Occupancy variables hf_calib::CmoPrimUnfm80, hf_calib::CmoFV0AUnfm80, hf_calib::CmoFT0AUnfm80, @@ -407,32 +436,32 @@ DECLARE_SOA_TABLE(D0CalibTrack, "AOD", "D0CALIBTRACKS", namespace hf_calib { -DECLARE_SOA_INDEX_COLUMN_FULL(TrackPos, trackPos, int, D0CalibTrack, ""); //! Index of positive track -DECLARE_SOA_INDEX_COLUMN_FULL(TrackNeg, trackNeg, int, D0CalibTrack, ""); //! Index of negative track -DECLARE_SOA_COLUMN(MassHypo, massHypo, uint8_t); //! mass hypothesis for D0 (D0, D0bar, or both) -DECLARE_SOA_COLUMN(Pt, pt, float); //! D0-candidate pT -DECLARE_SOA_COLUMN(Eta, eta, float); //! D0-candidate eta -DECLARE_SOA_COLUMN(Phi, phi, float); //! D0-candidate phi -DECLARE_SOA_COLUMN(InvMassD0, invMassD0, float); //! invariant mass (D0 hypothesis) -DECLARE_SOA_COLUMN(InvMassD0bar, invMassD0bar, float); //! invariant mass (D0bar hypothesis) -DECLARE_SOA_COLUMN(DecLength, decLength, uint8_t); //! compressed decay length -DECLARE_SOA_COLUMN(DecLengthXY, decLengthXY, uint8_t); //! compressed decay length XY -DECLARE_SOA_COLUMN(NormDecLength, normDecLength, uint8_t); //! compressed normalised decay length -DECLARE_SOA_COLUMN(NormDecLengthXY, normDecLengthXY, uint8_t); //! compressed normalised decay length XY -DECLARE_SOA_COLUMN(CosPa, cosPa, uint8_t); //! compressed cosine of pointing angle -DECLARE_SOA_COLUMN(CosPaXY, cosPaXY, uint8_t); //! compressed cosine of pointing angle XY -DECLARE_SOA_COLUMN(PointingAngle, pointingAngle, uint8_t); //! compressed pointing angle -DECLARE_SOA_COLUMN(PointingAngleXY, pointingAngleXY, uint8_t); //! compressed pointing angle XY -DECLARE_SOA_COLUMN(DecVtxChi2, decVtxChi2, uint8_t); //! compressed decay vertex chi2 -DECLARE_SOA_COLUMN(BdtScoreBkgD0, bdtScoreBkgD0, uint16_t); //! compressed BDT score (bkg, D0 mass hypo) -DECLARE_SOA_COLUMN(BdtScorePromptD0, bdtScorePromptD0, uint8_t); //! compressed BDT score (prompt, D0 mass hypo) -DECLARE_SOA_COLUMN(BdtScoreNonpromptD0, bdtScoreNonpromptD0, uint8_t); //! compressed BDT score (non-prompt, D0 mass hypo) -DECLARE_SOA_COLUMN(BdtScoreBkgD0bar, bdtScoreBkgD0bar, uint16_t); //! compressed BDT score (bkg, D0bar mass hypo) -DECLARE_SOA_COLUMN(BdtScorePromptD0bar, bdtScorePromptD0bar, uint8_t); //! compressed BDT score (prompt, D0bar mass hypo) -DECLARE_SOA_COLUMN(BdtScoreNonpromptD0bar, bdtScoreNonpromptD0bar, uint8_t); //! compressed BDT score (non-prompt, D0bar mass hypo) +DECLARE_SOA_INDEX_COLUMN_FULL(TrackPos, trackPos, int, D0CalibTracks, "_Pos"); //! Index of positive track +DECLARE_SOA_INDEX_COLUMN_FULL(TrackNeg, trackNeg, int, D0CalibTracks, "_Neg"); //! Index of negative track +DECLARE_SOA_COLUMN(MassHypo, massHypo, uint8_t); //! mass hypothesis for D0 (D0, D0bar, or both) +DECLARE_SOA_COLUMN(Pt, pt, float); //! D0-candidate pT +DECLARE_SOA_COLUMN(Eta, eta, float); //! D0-candidate eta +DECLARE_SOA_COLUMN(Phi, phi, float); //! D0-candidate phi +DECLARE_SOA_COLUMN(InvMassD0, invMassD0, float); //! invariant mass (D0 hypothesis) +DECLARE_SOA_COLUMN(InvMassD0bar, invMassD0bar, float); //! invariant mass (D0bar hypothesis) +DECLARE_SOA_COLUMN(DecLength, decLength, uint8_t); //! compressed decay length +DECLARE_SOA_COLUMN(DecLengthXY, decLengthXY, uint8_t); //! compressed decay length XY +DECLARE_SOA_COLUMN(NormDecLength, normDecLength, uint8_t); //! compressed normalised decay length +DECLARE_SOA_COLUMN(NormDecLengthXY, normDecLengthXY, uint8_t); //! compressed normalised decay length XY +DECLARE_SOA_COLUMN(CosPa, cosPa, uint8_t); //! compressed cosine of pointing angle +DECLARE_SOA_COLUMN(CosPaXY, cosPaXY, uint8_t); //! compressed cosine of pointing angle XY +DECLARE_SOA_COLUMN(PointingAngle, pointingAngle, uint8_t); //! compressed pointing angle +DECLARE_SOA_COLUMN(PointingAngleXY, pointingAngleXY, uint8_t); //! compressed pointing angle XY +DECLARE_SOA_COLUMN(DecVtxChi2, decVtxChi2, uint8_t); //! compressed decay vertex chi2 +DECLARE_SOA_COLUMN(BdtScoreBkgD0, bdtScoreBkgD0, uint16_t); //! compressed BDT score (bkg, D0 mass hypo) +DECLARE_SOA_COLUMN(BdtScorePromptD0, bdtScorePromptD0, uint8_t); //! compressed BDT score (prompt, D0 mass hypo) +DECLARE_SOA_COLUMN(BdtScoreNonpromptD0, bdtScoreNonpromptD0, uint8_t); //! compressed BDT score (non-prompt, D0 mass hypo) +DECLARE_SOA_COLUMN(BdtScoreBkgD0bar, bdtScoreBkgD0bar, uint16_t); //! compressed BDT score (bkg, D0bar mass hypo) +DECLARE_SOA_COLUMN(BdtScorePromptD0bar, bdtScorePromptD0bar, uint8_t); //! compressed BDT score (prompt, D0bar mass hypo) +DECLARE_SOA_COLUMN(BdtScoreNonpromptD0bar, bdtScoreNonpromptD0bar, uint8_t); //! compressed BDT score (non-prompt, D0bar mass hypo) } // namespace hf_calib -DECLARE_SOA_TABLE(D0CalibCand, "AOD", "D0CALIBCANDS", +DECLARE_SOA_TABLE(D0CalibCands, "AOD", "D0CALIBCAND", o2::soa::Index<>, hf_calib::CollisionId, hf_calib::TrackPosId, @@ -460,4 +489,4 @@ DECLARE_SOA_TABLE(D0CalibCand, "AOD", "D0CALIBCANDS", hf_calib::BdtScoreNonpromptD0bar); } // namespace aod } // namespace o2 -#endif // D0CALIBTABLES_H_ +#endif // DPG_TASKS_AOTTRACK_D0CALIBTABLES_H_ diff --git a/DPG/Tasks/AOTTrack/derivedDataCreatorD0Calibration.cxx b/DPG/Tasks/AOTTrack/derivedDataCreatorD0Calibration.cxx index 7e28f0b01fb..20b50370644 100644 --- a/DPG/Tasks/AOTTrack/derivedDataCreatorD0Calibration.cxx +++ b/DPG/Tasks/AOTTrack/derivedDataCreatorD0Calibration.cxx @@ -38,6 +38,7 @@ #include #include #include +#include #include #include @@ -48,6 +49,7 @@ #include #include #include +#include using namespace o2; using namespace o2::analysis; @@ -58,9 +60,9 @@ using namespace o2::hf_calib; struct DerivedDataCreatorD0Calibration { - Produces collTable; - Produces trackTable; - Produces candTable; + Produces collTable; + Produces trackTable; + Produces candTable; struct : ConfigurableGroup { Configurable ptMin{"ptMin", 0.4, "min. track pT"}; @@ -102,7 +104,7 @@ struct DerivedDataCreatorD0Calibration { std::string prefix = "ml"; } cfgMl; - using TracksWCovExtraPid = soa::Join; + using TracksWCovExtraPid = soa::Join; using CollisionsWEvSel = soa::Join; using TrackMeanOccs = soa::Join; @@ -122,6 +124,8 @@ struct DerivedDataCreatorD0Calibration { // tolerances for preselections before vertex reconstruction const float ptTolerance{0.1f}; const float invMassTolerance{0.05f}; + uint32_t precisionCovMask{0xFFFFE000}; // 10 bits + uint32_t precisionDcaMask{0xFFFFFC00}; // 13 bits OutputObj histDownSampl{"histDownSampl"}; @@ -167,7 +171,9 @@ struct DerivedDataCreatorD0Calibration { void process(CollisionsWEvSel const& collisions, aod::TrackAssoc const& trackIndices, TracksWCovExtraPid const&, - aod::BCsWithTimestamps const&) + aod::BCsWithTimestamps const&, + TrackMeanOccs const&, + aod::TracksQAVersion const&) { std::map selectedCollisions; // map with indices of selected collisions (key: original AOD Collision table index, value: D0 collision index) std::map selectedTracks; // map with indices of selected tracks (key: original AOD Track table index, value: D0 daughter track index) @@ -441,64 +447,376 @@ struct DerivedDataCreatorD0Calibration { // collision if (!selectedCollisions.count(collision.globalIndex())) { // fill collision table if not yet present - collTable(collision.posX(), collision.posY(), collision.posZ(), - collision.covXX(), collision.covXY(), collision.covXZ(), collision.covYY(), collision.covYZ(), collision.covZZ(), - collision.numContrib(), uint8_t(std::round(collision.centFT0C())), getCompressedOccupancy(collision.trackOccupancyInTimeRange()), getCompressedOccupancy(collision.ft0cOccupancyInTimeRange()), - eventIR.orbit, runNumber); + collTable(collision.posX(), + collision.posY(), + collision.posZ(), + collision.covXX(), + collision.covXY(), + collision.covXZ(), + collision.covYY(), + collision.covYZ(), + collision.covZZ(), + collision.numContrib(), + uint8_t(std::round(collision.centFT0C())), + getCompressedOccupancy(collision.trackOccupancyInTimeRange()), + getCompressedOccupancy(collision.ft0cOccupancyInTimeRange()), + eventIR.orbit, + runNumber); selectedCollisions[collision.globalIndex()] = collTable.lastIndex(); } // tracks if (!selectedTracks.count(trackPos.globalIndex())) { // fill track table with positive track if not yet present - if (trackPos.tmoId() != -1) { + uint8_t tmoPrimUnfm80{0u}; + uint8_t tmoFV0AUnfm80{0u}; + uint8_t tmoFT0AUnfm80{0u}; + uint8_t tmoFT0CUnfm80{0u}; + uint8_t twmoPrimUnfm80{0u}; + uint8_t twmoFV0AUnfm80{0u}; + uint8_t twmoFT0AUnfm80{0u}; + uint8_t twmoFT0CUnfm80{0u}; + uint8_t tmoRobustT0V0PrimUnfm80{0u}; + uint8_t twmoRobustT0V0PrimUnfm80{0u}; + if (trackPos.has_tmo()) { auto tmoFromTrack = trackPos.tmo_as(); // obtain track mean occupancies - trackTable(selectedCollisions[collision.globalIndex()], - trackPos.x(), trackPos.alpha(), trackPos.y(), trackPos.z(), trackPos.snp(), trackPos.tgl(), trackPos.signed1Pt(), // stored at PV - trackPos.cYY(), trackPos.cZY(), trackPos.cZZ(), trackPos.cSnpY(), trackPos.cSnpZ(), trackPos.cSnpSnp(), trackPos.cTglY(), trackPos.cTglZ(), trackPos.cTglSnp(), trackPos.cTglTgl(), trackPos.c1PtY(), trackPos.c1PtZ(), trackPos.c1PtSnp(), trackPos.c1PtTgl(), trackPos.c1Pt21Pt2(), - trackPos.tpcInnerParam(), trackPos.flags(), trackPos.itsClusterSizes(), trackPos.tpcNClsFindable(), trackPos.tpcNClsFindableMinusFound(), trackPos.tpcNClsFindableMinusCrossedRows(), trackPos.tpcNClsShared(), trackPos.trdPattern(), getCompressedChi2(trackPos.itsChi2NCl()), getCompressedChi2(trackPos.tpcChi2NCl()), getCompressedChi2(trackPos.trdChi2()), getCompressedChi2(trackPos.tofChi2()), trackPos.tpcSignal(), trackPos.trdSignal(), trackPos.length(), trackPos.tofExpMom(), trackPos.trackTime(), trackPos.trackTimeRes(), - dcaPos.getY(), dcaPos.getZ(), getCompressedNumSigmaPid(trackPos.tpcNSigmaPi()), getCompressedNumSigmaPid(trackPos.tpcNSigmaKa()), getCompressedNumSigmaPid(trackPos.tofNSigmaPi()), getCompressedNumSigmaPid(trackPos.tofNSigmaKa()), - getCompressedOccupancy(tmoFromTrack.tmoPrimUnfm80()), getCompressedOccupancy(tmoFromTrack.tmoFV0AUnfm80()), getCompressedOccupancy(tmoFromTrack.tmoFT0AUnfm80()), getCompressedOccupancy(tmoFromTrack.tmoFT0CUnfm80()), - getCompressedOccupancy(tmoFromTrack.twmoPrimUnfm80()), getCompressedOccupancy(tmoFromTrack.twmoFV0AUnfm80()), getCompressedOccupancy(tmoFromTrack.twmoFT0AUnfm80()), getCompressedOccupancy(tmoFromTrack.twmoFT0CUnfm80()), - getCompressedOccupancy(tmoFromTrack.tmoRobustT0V0PrimUnfm80()), getCompressedOccupancy(tmoFromTrack.twmoRobustT0V0PrimUnfm80())); - } else { - // if track doesn't have occupancies stored for it - trackTable(selectedCollisions[collision.globalIndex()], - trackPos.x(), trackPos.alpha(), trackPos.y(), trackPos.z(), trackPos.snp(), trackPos.tgl(), trackPos.signed1Pt(), // stored at PV - trackPos.cYY(), trackPos.cZY(), trackPos.cZZ(), trackPos.cSnpY(), trackPos.cSnpZ(), trackPos.cSnpSnp(), trackPos.cTglY(), trackPos.cTglZ(), trackPos.cTglSnp(), trackPos.cTglTgl(), trackPos.c1PtY(), trackPos.c1PtZ(), trackPos.c1PtSnp(), trackPos.c1PtTgl(), trackPos.c1Pt21Pt2(), - trackPos.tpcInnerParam(), trackPos.flags(), trackPos.itsClusterSizes(), trackPos.tpcNClsFindable(), trackPos.tpcNClsFindableMinusFound(), trackPos.tpcNClsFindableMinusCrossedRows(), trackPos.tpcNClsShared(), trackPos.trdPattern(), getCompressedChi2(trackPos.itsChi2NCl()), getCompressedChi2(trackPos.tpcChi2NCl()), getCompressedChi2(trackPos.trdChi2()), getCompressedChi2(trackPos.tofChi2()), trackPos.tpcSignal(), trackPos.trdSignal(), trackPos.length(), trackPos.tofExpMom(), trackPos.trackTime(), trackPos.trackTimeRes(), - dcaPos.getY(), dcaPos.getZ(), getCompressedNumSigmaPid(trackPos.tpcNSigmaPi()), getCompressedNumSigmaPid(trackPos.tpcNSigmaKa()), getCompressedNumSigmaPid(trackPos.tofNSigmaPi()), getCompressedNumSigmaPid(trackPos.tofNSigmaKa()), - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + tmoPrimUnfm80 = getCompressedOccupancy(tmoFromTrack.tmoPrimUnfm80()); + tmoFV0AUnfm80 = getCompressedOccupancy(tmoFromTrack.tmoFV0AUnfm80()); + tmoFT0AUnfm80 = getCompressedOccupancy(tmoFromTrack.tmoFT0AUnfm80()); + tmoFT0CUnfm80 = getCompressedOccupancy(tmoFromTrack.tmoFT0CUnfm80()); + twmoPrimUnfm80 = getCompressedOccupancy(tmoFromTrack.twmoPrimUnfm80()); + twmoFV0AUnfm80 = getCompressedOccupancy(tmoFromTrack.twmoFV0AUnfm80()); + twmoFT0AUnfm80 = getCompressedOccupancy(tmoFromTrack.twmoFT0AUnfm80()); + twmoFT0CUnfm80 = getCompressedOccupancy(tmoFromTrack.twmoFT0CUnfm80()); + tmoRobustT0V0PrimUnfm80 = getCompressedOccupancy(tmoFromTrack.tmoRobustT0V0PrimUnfm80()); + twmoRobustT0V0PrimUnfm80 = getCompressedOccupancy(tmoFromTrack.twmoRobustT0V0PrimUnfm80()); + } + float tpcTime0{0.f}; + float tpcdEdxNorm{0.f}; + int16_t tpcDcaR{0}; + int16_t tpcDcaZ{0}; + uint8_t tpcClusterByteMask{0u}; + uint8_t tpcdEdxMax0R{0u}; + uint8_t tpcdEdxMax1R{0u}; + uint8_t tpcdEdxMax2R{0u}; + uint8_t tpcdEdxMax3R{0u}; + uint8_t tpcdEdxTot0R{0u}; + uint8_t tpcdEdxTot1R{0u}; + uint8_t tpcdEdxTot2R{0u}; + uint8_t tpcdEdxTot3R{0u}; + int8_t deltaRefContParamY{0}; + int8_t deltaRefITSParamZ{0}; + int8_t deltaRefContParamSnp{0}; + int8_t deltaRefContParamTgl{0}; + int8_t deltaRefContParamQ2Pt{0}; + int8_t deltaRefGloParamY{0}; + int8_t deltaRefGloParamZ{0}; + int8_t deltaRefGloParamSnp{0}; + int8_t deltaRefGloParamTgl{0}; + int8_t deltaRefGloParamQ2Pt{0}; + int8_t deltaTOFdX{0}; + int8_t deltaTOFdZ{0}; + if (trackPos.has_trackQA()) { + auto trackQA = trackPos.trackQA_as(); // obtain track QA + tpcTime0 = trackQA.tpcTime0(); + tpcdEdxNorm = trackQA.tpcdEdxNorm(); + tpcDcaR = trackQA.tpcdcaR(); + tpcDcaZ = trackQA.tpcdcaZ(); + tpcClusterByteMask = trackQA.tpcClusterByteMask(); + tpcdEdxMax0R = trackQA.tpcdEdxMax0R(); + tpcdEdxMax1R = trackQA.tpcdEdxMax1R(); + tpcdEdxMax2R = trackQA.tpcdEdxMax2R(); + tpcdEdxMax3R = trackQA.tpcdEdxMax3R(); + tpcdEdxTot0R = trackQA.tpcdEdxTot0R(); + tpcdEdxTot1R = trackQA.tpcdEdxTot1R(); + tpcdEdxTot2R = trackQA.tpcdEdxTot2R(); + tpcdEdxTot3R = trackQA.tpcdEdxTot3R(); + deltaRefContParamY = trackQA.deltaRefContParamY(); + deltaRefITSParamZ = trackQA.deltaRefITSParamZ(); + deltaRefContParamSnp = trackQA.deltaRefContParamSnp(); + deltaRefContParamTgl = trackQA.deltaRefContParamTgl(); + deltaRefContParamQ2Pt = trackQA.deltaRefContParamQ2Pt(); + deltaRefGloParamY = trackQA.deltaRefGloParamY(); + deltaRefGloParamZ = trackQA.deltaRefGloParamZ(); + deltaRefGloParamSnp = trackQA.deltaRefGloParamSnp(); + deltaRefGloParamTgl = trackQA.deltaRefGloParamTgl(); + deltaRefGloParamQ2Pt = trackQA.deltaRefGloParamQ2Pt(); + deltaTOFdX = trackQA.deltaTOFdX(); + deltaTOFdZ = trackQA.deltaTOFdZ(); } + + trackTable(selectedCollisions[collision.globalIndex()], // stored at PV + trackPos.x(), + trackPos.alpha(), + trackPos.y(), + trackPos.z(), + trackPos.snp(), + trackPos.tgl(), + trackPos.signed1Pt(), + o2::math_utils::detail::truncateFloatFraction(trackPos.cYY(), precisionCovMask), + o2::math_utils::detail::truncateFloatFraction(trackPos.cZY(), precisionCovMask), + o2::math_utils::detail::truncateFloatFraction(trackPos.cZZ(), precisionCovMask), + o2::math_utils::detail::truncateFloatFraction(trackPos.cSnpY(), precisionCovMask), + o2::math_utils::detail::truncateFloatFraction(trackPos.cSnpZ(), precisionCovMask), + o2::math_utils::detail::truncateFloatFraction(trackPos.cSnpSnp(), precisionCovMask), + o2::math_utils::detail::truncateFloatFraction(trackPos.cTglY(), precisionCovMask), + o2::math_utils::detail::truncateFloatFraction(trackPos.cTglZ(), precisionCovMask), + o2::math_utils::detail::truncateFloatFraction(trackPos.cTglSnp(), precisionCovMask), + o2::math_utils::detail::truncateFloatFraction(trackPos.cTglTgl(), precisionCovMask), + o2::math_utils::detail::truncateFloatFraction(trackPos.c1PtY(), precisionCovMask), + o2::math_utils::detail::truncateFloatFraction(trackPos.c1PtZ(), precisionCovMask), + o2::math_utils::detail::truncateFloatFraction(trackPos.c1PtSnp(), precisionCovMask), + o2::math_utils::detail::truncateFloatFraction(trackPos.c1PtTgl(), precisionCovMask), + o2::math_utils::detail::truncateFloatFraction(trackPos.c1Pt21Pt2(), precisionCovMask), + trackPos.tpcInnerParam(), + trackPos.flags(), + trackPos.itsClusterSizes(), + trackPos.tpcNClsFindable(), + trackPos.tpcNClsFindableMinusFound(), + trackPos.tpcNClsFindableMinusCrossedRows(), + trackPos.tpcNClsShared(), + trackPos.trdPattern(), + getCompressedChi2(trackPos.itsChi2NCl()), + getCompressedChi2(trackPos.tpcChi2NCl()), + getCompressedChi2(trackPos.trdChi2()), + getCompressedChi2(trackPos.tofChi2()), + trackPos.tpcSignal(), + trackPos.trdSignal(), + trackPos.length(), + trackPos.tofExpMom(), + trackPos.trackTime(), + trackPos.trackTimeRes(), + tpcTime0, + tpcdEdxNorm, + tpcDcaR, + tpcDcaZ, + tpcClusterByteMask, + tpcdEdxMax0R, + tpcdEdxMax1R, + tpcdEdxMax2R, + tpcdEdxMax3R, + tpcdEdxTot0R, + tpcdEdxTot1R, + tpcdEdxTot2R, + tpcdEdxTot3R, + deltaRefContParamY, + deltaRefITSParamZ, + deltaRefContParamSnp, + deltaRefContParamTgl, + deltaRefContParamQ2Pt, + deltaRefGloParamY, + deltaRefGloParamZ, + deltaRefGloParamSnp, + deltaRefGloParamTgl, + deltaRefGloParamQ2Pt, + deltaTOFdX, + deltaTOFdZ, + o2::math_utils::detail::truncateFloatFraction(dcaPos.getY(), precisionDcaMask), + o2::math_utils::detail::truncateFloatFraction(dcaPos.getZ(), precisionDcaMask), + getCompressedNumSigmaPid(trackPos.tpcNSigmaPi()), + getCompressedNumSigmaPid(trackPos.tpcNSigmaKa()), + getCompressedNumSigmaPid(trackPos.tofNSigmaPi()), + getCompressedNumSigmaPid(trackPos.tofNSigmaKa()), + tmoPrimUnfm80, + tmoFV0AUnfm80, + tmoFT0AUnfm80, + tmoFT0CUnfm80, + twmoPrimUnfm80, + twmoFV0AUnfm80, + twmoFT0AUnfm80, + twmoFT0CUnfm80, + tmoRobustT0V0PrimUnfm80, + twmoRobustT0V0PrimUnfm80); selectedTracks[trackPos.globalIndex()] = trackTable.lastIndex(); } if (!selectedTracks.count(trackNeg.globalIndex())) { // fill track table with negative track if not yet present - if (trackNeg.tmoId() != -1) { - auto tmoFromTrack = trackNeg.tmo_as(); - trackTable(selectedCollisions[collision.globalIndex()], - trackNeg.x(), trackNeg.alpha(), trackNeg.y(), trackNeg.z(), trackNeg.snp(), trackNeg.tgl(), trackNeg.signed1Pt(), // stored at PV - trackNeg.cYY(), trackNeg.cZY(), trackNeg.cZZ(), trackNeg.cSnpY(), trackNeg.cSnpZ(), trackNeg.cSnpSnp(), trackNeg.cTglY(), trackNeg.cTglZ(), trackNeg.cTglSnp(), trackNeg.cTglTgl(), trackNeg.c1PtY(), trackNeg.c1PtZ(), trackNeg.c1PtSnp(), trackNeg.c1PtTgl(), trackNeg.c1Pt21Pt2(), - trackNeg.tpcInnerParam(), trackNeg.flags(), trackNeg.itsClusterSizes(), trackNeg.tpcNClsFindable(), trackNeg.tpcNClsFindableMinusFound(), trackNeg.tpcNClsFindableMinusCrossedRows(), trackNeg.tpcNClsShared(), trackNeg.trdPattern(), getCompressedChi2(trackNeg.itsChi2NCl()), getCompressedChi2(trackNeg.tpcChi2NCl()), getCompressedChi2(trackNeg.trdChi2()), getCompressedChi2(trackNeg.tofChi2()), trackNeg.tpcSignal(), trackNeg.trdSignal(), trackNeg.length(), trackNeg.tofExpMom(), trackNeg.trackTime(), trackNeg.trackTimeRes(), - dcaNeg.getY(), dcaNeg.getZ(), getCompressedNumSigmaPid(trackNeg.tpcNSigmaPi()), getCompressedNumSigmaPid(trackNeg.tpcNSigmaKa()), getCompressedNumSigmaPid(trackNeg.tofNSigmaPi()), getCompressedNumSigmaPid(trackNeg.tofNSigmaKa()), - getCompressedOccupancy(tmoFromTrack.tmoPrimUnfm80()), getCompressedOccupancy(tmoFromTrack.tmoFV0AUnfm80()), getCompressedOccupancy(tmoFromTrack.tmoFT0AUnfm80()), getCompressedOccupancy(tmoFromTrack.tmoFT0CUnfm80()), - getCompressedOccupancy(tmoFromTrack.twmoPrimUnfm80()), getCompressedOccupancy(tmoFromTrack.twmoFV0AUnfm80()), getCompressedOccupancy(tmoFromTrack.twmoFT0AUnfm80()), getCompressedOccupancy(tmoFromTrack.twmoFT0CUnfm80()), - getCompressedOccupancy(tmoFromTrack.tmoRobustT0V0PrimUnfm80()), getCompressedOccupancy(tmoFromTrack.twmoRobustT0V0PrimUnfm80())); - } else { - // if track doesn't have occupancies stored for it - trackTable(selectedCollisions[collision.globalIndex()], - trackNeg.x(), trackNeg.alpha(), trackNeg.y(), trackNeg.z(), trackNeg.snp(), trackNeg.tgl(), trackNeg.signed1Pt(), // stored at PV - trackNeg.cYY(), trackNeg.cZY(), trackNeg.cZZ(), trackNeg.cSnpY(), trackNeg.cSnpZ(), trackNeg.cSnpSnp(), trackNeg.cTglY(), trackNeg.cTglZ(), trackNeg.cTglSnp(), trackNeg.cTglTgl(), trackNeg.c1PtY(), trackNeg.c1PtZ(), trackNeg.c1PtSnp(), trackNeg.c1PtTgl(), trackNeg.c1Pt21Pt2(), - trackNeg.tpcInnerParam(), trackNeg.flags(), trackNeg.itsClusterSizes(), trackNeg.tpcNClsFindable(), trackNeg.tpcNClsFindableMinusFound(), trackNeg.tpcNClsFindableMinusCrossedRows(), trackNeg.tpcNClsShared(), trackNeg.trdPattern(), getCompressedChi2(trackNeg.itsChi2NCl()), getCompressedChi2(trackNeg.tpcChi2NCl()), getCompressedChi2(trackNeg.trdChi2()), getCompressedChi2(trackNeg.tofChi2()), trackNeg.tpcSignal(), trackNeg.trdSignal(), trackNeg.length(), trackNeg.tofExpMom(), trackNeg.trackTime(), trackNeg.trackTimeRes(), - dcaNeg.getY(), dcaNeg.getZ(), getCompressedNumSigmaPid(trackNeg.tpcNSigmaPi()), getCompressedNumSigmaPid(trackNeg.tpcNSigmaKa()), getCompressedNumSigmaPid(trackNeg.tofNSigmaPi()), getCompressedNumSigmaPid(trackNeg.tofNSigmaKa()), - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + uint8_t tmoPrimUnfm80{0u}; + uint8_t tmoFV0AUnfm80{0u}; + uint8_t tmoFT0AUnfm80{0u}; + uint8_t tmoFT0CUnfm80{0u}; + uint8_t twmoPrimUnfm80{0u}; + uint8_t twmoFV0AUnfm80{0u}; + uint8_t twmoFT0AUnfm80{0u}; + uint8_t twmoFT0CUnfm80{0u}; + uint8_t tmoRobustT0V0PrimUnfm80{0u}; + uint8_t twmoRobustT0V0PrimUnfm80{0u}; + if (trackNeg.has_tmo()) { + auto tmoFromTrack = trackNeg.tmo_as(); // obtain track mean occupancies + tmoPrimUnfm80 = getCompressedOccupancy(tmoFromTrack.tmoPrimUnfm80()); + tmoFV0AUnfm80 = getCompressedOccupancy(tmoFromTrack.tmoFV0AUnfm80()); + tmoFT0AUnfm80 = getCompressedOccupancy(tmoFromTrack.tmoFT0AUnfm80()); + tmoFT0CUnfm80 = getCompressedOccupancy(tmoFromTrack.tmoFT0CUnfm80()); + twmoPrimUnfm80 = getCompressedOccupancy(tmoFromTrack.twmoPrimUnfm80()); + twmoFV0AUnfm80 = getCompressedOccupancy(tmoFromTrack.twmoFV0AUnfm80()); + twmoFT0AUnfm80 = getCompressedOccupancy(tmoFromTrack.twmoFT0AUnfm80()); + twmoFT0CUnfm80 = getCompressedOccupancy(tmoFromTrack.twmoFT0CUnfm80()); + tmoRobustT0V0PrimUnfm80 = getCompressedOccupancy(tmoFromTrack.tmoRobustT0V0PrimUnfm80()); + twmoRobustT0V0PrimUnfm80 = getCompressedOccupancy(tmoFromTrack.twmoRobustT0V0PrimUnfm80()); + } + float tpcTime0{0.f}; + float tpcdEdxNorm{0.f}; + int16_t tpcDcaR{0}; + int16_t tpcDcaZ{0}; + uint8_t tpcClusterByteMask{0u}; + uint8_t tpcdEdxMax0R{0u}; + uint8_t tpcdEdxMax1R{0u}; + uint8_t tpcdEdxMax2R{0u}; + uint8_t tpcdEdxMax3R{0u}; + uint8_t tpcdEdxTot0R{0u}; + uint8_t tpcdEdxTot1R{0u}; + uint8_t tpcdEdxTot2R{0u}; + uint8_t tpcdEdxTot3R{0u}; + int8_t deltaRefContParamY{0}; + int8_t deltaRefITSParamZ{0}; + int8_t deltaRefContParamSnp{0}; + int8_t deltaRefContParamTgl{0}; + int8_t deltaRefContParamQ2Pt{0}; + int8_t deltaRefGloParamY{0}; + int8_t deltaRefGloParamZ{0}; + int8_t deltaRefGloParamSnp{0}; + int8_t deltaRefGloParamTgl{0}; + int8_t deltaRefGloParamQ2Pt{0}; + int8_t deltaTOFdX{0}; + int8_t deltaTOFdZ{0}; + if (trackNeg.has_trackQA()) { + auto trackQA = trackNeg.trackQA_as(); // obtain track QA + tpcTime0 = trackQA.tpcTime0(); + tpcdEdxNorm = trackQA.tpcdEdxNorm(); + tpcDcaR = trackQA.tpcdcaR(); + tpcDcaZ = trackQA.tpcdcaZ(); + tpcClusterByteMask = trackQA.tpcClusterByteMask(); + tpcdEdxMax0R = trackQA.tpcdEdxMax0R(); + tpcdEdxMax1R = trackQA.tpcdEdxMax1R(); + tpcdEdxMax2R = trackQA.tpcdEdxMax2R(); + tpcdEdxMax3R = trackQA.tpcdEdxMax3R(); + tpcdEdxTot0R = trackQA.tpcdEdxTot0R(); + tpcdEdxTot1R = trackQA.tpcdEdxTot1R(); + tpcdEdxTot2R = trackQA.tpcdEdxTot2R(); + tpcdEdxTot3R = trackQA.tpcdEdxTot3R(); + deltaRefContParamY = trackQA.deltaRefContParamY(); + deltaRefITSParamZ = trackQA.deltaRefITSParamZ(); + deltaRefContParamSnp = trackQA.deltaRefContParamSnp(); + deltaRefContParamTgl = trackQA.deltaRefContParamTgl(); + deltaRefContParamQ2Pt = trackQA.deltaRefContParamQ2Pt(); + deltaRefGloParamY = trackQA.deltaRefGloParamY(); + deltaRefGloParamZ = trackQA.deltaRefGloParamZ(); + deltaRefGloParamSnp = trackQA.deltaRefGloParamSnp(); + deltaRefGloParamTgl = trackQA.deltaRefGloParamTgl(); + deltaRefGloParamQ2Pt = trackQA.deltaRefGloParamQ2Pt(); + deltaTOFdX = trackQA.deltaTOFdX(); + deltaTOFdZ = trackQA.deltaTOFdZ(); } + + trackTable(selectedCollisions[collision.globalIndex()], // stored at PV + trackNeg.x(), + trackNeg.alpha(), + trackNeg.y(), + trackNeg.z(), + trackNeg.snp(), + trackNeg.tgl(), + trackNeg.signed1Pt(), + o2::math_utils::detail::truncateFloatFraction(trackNeg.cYY(), precisionCovMask), + o2::math_utils::detail::truncateFloatFraction(trackNeg.cZY(), precisionCovMask), + o2::math_utils::detail::truncateFloatFraction(trackNeg.cZZ(), precisionCovMask), + o2::math_utils::detail::truncateFloatFraction(trackNeg.cSnpY(), precisionCovMask), + o2::math_utils::detail::truncateFloatFraction(trackNeg.cSnpZ(), precisionCovMask), + o2::math_utils::detail::truncateFloatFraction(trackNeg.cSnpSnp(), precisionCovMask), + o2::math_utils::detail::truncateFloatFraction(trackNeg.cTglY(), precisionCovMask), + o2::math_utils::detail::truncateFloatFraction(trackNeg.cTglZ(), precisionCovMask), + o2::math_utils::detail::truncateFloatFraction(trackNeg.cTglSnp(), precisionCovMask), + o2::math_utils::detail::truncateFloatFraction(trackNeg.cTglTgl(), precisionCovMask), + o2::math_utils::detail::truncateFloatFraction(trackNeg.c1PtY(), precisionCovMask), + o2::math_utils::detail::truncateFloatFraction(trackNeg.c1PtZ(), precisionCovMask), + o2::math_utils::detail::truncateFloatFraction(trackNeg.c1PtSnp(), precisionCovMask), + o2::math_utils::detail::truncateFloatFraction(trackNeg.c1PtTgl(), precisionCovMask), + o2::math_utils::detail::truncateFloatFraction(trackNeg.c1Pt21Pt2(), precisionCovMask), + trackNeg.tpcInnerParam(), + trackNeg.flags(), + trackNeg.itsClusterSizes(), + trackNeg.tpcNClsFindable(), + trackNeg.tpcNClsFindableMinusFound(), + trackNeg.tpcNClsFindableMinusCrossedRows(), + trackNeg.tpcNClsShared(), + trackNeg.trdPattern(), + getCompressedChi2(trackNeg.itsChi2NCl()), + getCompressedChi2(trackNeg.tpcChi2NCl()), + getCompressedChi2(trackNeg.trdChi2()), + getCompressedChi2(trackNeg.tofChi2()), + trackNeg.tpcSignal(), + trackNeg.trdSignal(), + trackNeg.length(), + trackNeg.tofExpMom(), + trackNeg.trackTime(), + trackNeg.trackTimeRes(), + tpcTime0, + tpcdEdxNorm, + tpcDcaR, + tpcDcaZ, + tpcClusterByteMask, + tpcdEdxMax0R, + tpcdEdxMax1R, + tpcdEdxMax2R, + tpcdEdxMax3R, + tpcdEdxTot0R, + tpcdEdxTot1R, + tpcdEdxTot2R, + tpcdEdxTot3R, + deltaRefContParamY, + deltaRefITSParamZ, + deltaRefContParamSnp, + deltaRefContParamTgl, + deltaRefContParamQ2Pt, + deltaRefGloParamY, + deltaRefGloParamZ, + deltaRefGloParamSnp, + deltaRefGloParamTgl, + deltaRefGloParamQ2Pt, + deltaTOFdX, + deltaTOFdZ, + o2::math_utils::detail::truncateFloatFraction(dcaNeg.getY(), precisionDcaMask), + o2::math_utils::detail::truncateFloatFraction(dcaNeg.getZ(), precisionDcaMask), + getCompressedNumSigmaPid(trackNeg.tpcNSigmaPi()), + getCompressedNumSigmaPid(trackNeg.tpcNSigmaKa()), + getCompressedNumSigmaPid(trackNeg.tofNSigmaPi()), + getCompressedNumSigmaPid(trackNeg.tofNSigmaKa()), + tmoPrimUnfm80, + tmoFV0AUnfm80, + tmoFT0AUnfm80, + tmoFT0CUnfm80, + twmoPrimUnfm80, + twmoFV0AUnfm80, + twmoFT0AUnfm80, + twmoFT0CUnfm80, + tmoRobustT0V0PrimUnfm80, + twmoRobustT0V0PrimUnfm80); selectedTracks[trackNeg.globalIndex()] = trackTable.lastIndex(); } // candidate - candTable(selectedCollisions[collision.globalIndex()], selectedTracks[trackPos.globalIndex()], selectedTracks[trackNeg.globalIndex()], massHypo, ptD0, etaD0, phiD0, invMassD0, invMassD0bar, - getCompressedDecayLength(decLenD0), getCompressedDecayLength(decLenXYD0), getCompressedNormDecayLength(decLenD0 / errorDecayLengthD0), getCompressedNormDecayLength(decLenXYD0 / errorDecayLengthXYD0), - getCompressedCosPa(cosPaD0), getCompressedCosPa(cosPaXYD0), getCompressedPointingAngle(paD0), getCompressedPointingAngle(paXYD0), getCompressedChi2(chi2PCA), getCompressedBdtScoreBkg(bdtScoresD0[0]), getCompressedBdtScoreSgn(bdtScoresD0[1]), getCompressedBdtScoreSgn(bdtScoresD0[2]), getCompressedBdtScoreBkg(bdtScoresD0bar[0]), getCompressedBdtScoreSgn(bdtScoresD0bar[1]), getCompressedBdtScoreSgn(bdtScoresD0bar[2])); + candTable(selectedCollisions[collision.globalIndex()], + selectedTracks[trackPos.globalIndex()], + selectedTracks[trackNeg.globalIndex()], + massHypo, + ptD0, + etaD0, + phiD0, + invMassD0, + invMassD0bar, + getCompressedDecayLength(decLenD0), + getCompressedDecayLength(decLenXYD0), + getCompressedNormDecayLength(decLenD0 / errorDecayLengthD0), + getCompressedNormDecayLength(decLenXYD0 / errorDecayLengthXYD0), + getCompressedCosPa(cosPaD0), + getCompressedCosPa(cosPaXYD0), + getCompressedPointingAngle(paD0), + getCompressedPointingAngle(paXYD0), + getCompressedChi2(chi2PCA), + getCompressedBdtScoreBkg(bdtScoresD0[0]), + getCompressedBdtScoreSgn(bdtScoresD0[1]), + getCompressedBdtScoreSgn(bdtScoresD0[2]), + getCompressedBdtScoreBkg(bdtScoresD0bar[0]), + getCompressedBdtScoreSgn(bdtScoresD0bar[1]), + getCompressedBdtScoreSgn(bdtScoresD0bar[2])); } // end loop over negative tracks } // end loop over positive tracks } // end loop over collisions tracks From 16da8131b9b03a02cc4875713bef8be1107bbffd Mon Sep 17 00:00:00 2001 From: NNicassio99 <140729099+NNicassio99@users.noreply.github.com> Date: Tue, 24 Jun 2025 20:09:24 +0200 Subject: [PATCH 202/871] =?UTF-8?q?[ALICE3]=20Adding=20dummy=20nSigma=20va?= =?UTF-8?q?lues=20in=20RICH=20tables=20to=20avoid=20mismatch=20with=20trac?= =?UTF-8?q?=E2=80=A6=20(#11746)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Nicola Nicassio Co-authored-by: Nicolò Jacazio --- ALICE3/TableProducer/OTF/onTheFlyRichPid.cxx | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/ALICE3/TableProducer/OTF/onTheFlyRichPid.cxx b/ALICE3/TableProducer/OTF/onTheFlyRichPid.cxx index 82816062390..e3c740966d1 100644 --- a/ALICE3/TableProducer/OTF/onTheFlyRichPid.cxx +++ b/ALICE3/TableProducer/OTF/onTheFlyRichPid.cxx @@ -745,10 +745,15 @@ struct OnTheFlyRichPid { } for (const auto& track : tracks) { + + float nSigmaBarrelRich[5] = {error_value, error_value, error_value, error_value, error_value}; + // first step: find precise arrival time (if any) // --- convert track into perfect track - if (!track.has_mcParticle()) // should always be OK but check please + if (!track.has_mcParticle()) { // should always be OK but check please + upgradeRich(nSigmaBarrelRich[0], nSigmaBarrelRich[1], nSigmaBarrelRich[2], nSigmaBarrelRich[3], nSigmaBarrelRich[4]); continue; + } auto mcParticle = track.mcParticle(); o2::track::TrackParCov o2track = o2::upgrade::convertMCParticleToO2Track(mcParticle, pdg); @@ -761,12 +766,14 @@ struct OnTheFlyRichPid { // get particle to calculate Cherenkov angle and resolution auto pdgInfo = pdg->GetParticle(mcParticle.pdgCode()); if (pdgInfo == nullptr) { + upgradeRich(nSigmaBarrelRich[0], nSigmaBarrelRich[1], nSigmaBarrelRich[2], nSigmaBarrelRich[3], nSigmaBarrelRich[4]); continue; } // find track bRICH sector int i_sector = findSector(o2track.getEta()); if (i_sector < 0) { + upgradeRich(nSigmaBarrelRich[0], nSigmaBarrelRich[1], nSigmaBarrelRich[2], nSigmaBarrelRich[3], nSigmaBarrelRich[4]); continue; } @@ -794,12 +801,12 @@ struct OnTheFlyRichPid { } // Straight to Nsigma - float deltaThetaBarrelRich[5], nSigmaBarrelRich[5]; + float deltaThetaBarrelRich[5]; //, nSigmaBarrelRich[5]; int lpdg_array[5] = {kElectron, kMuonMinus, kPiPlus, kKPlus, kProton}; float masses[5]; for (int ii = 0; ii < 5; ii++) { - nSigmaBarrelRich[ii] = error_value; + // nSigmaBarrelRich[ii] = error_value; auto pdgInfoThis = pdg->GetParticle(lpdg_array[ii]); masses[ii] = pdgInfoThis->Mass(); From 267749a1bf705d0cac210f893c8014c8c56d9f88 Mon Sep 17 00:00:00 2001 From: shahor02 Date: Tue, 24 Jun 2025 21:03:31 +0200 Subject: [PATCH 203/871] [Common,PWGCF,DPG] TimeDeadMap needs explicit dependence on O2::DataFormatsITSMFT (#11742) --- Common/TableProducer/CMakeLists.txt | 2 ++ DPG/Tasks/AOTEvent/CMakeLists.txt | 2 +- PWGCF/TwoParticleCorrelations/Tasks/CMakeLists.txt | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Common/TableProducer/CMakeLists.txt b/Common/TableProducer/CMakeLists.txt index 40cb408511e..867fbffe856 100644 --- a/Common/TableProducer/CMakeLists.txt +++ b/Common/TableProducer/CMakeLists.txt @@ -25,11 +25,13 @@ o2physics_add_dpl_workflow(trackselection o2physics_add_dpl_workflow(event-selection SOURCES eventSelection.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCCDB + O2::DataFormatsITSMFT COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(event-selection-service SOURCES eventSelectionService.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCCDB + O2::DataFormatsITSMFT COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(multiplicity-table diff --git a/DPG/Tasks/AOTEvent/CMakeLists.txt b/DPG/Tasks/AOTEvent/CMakeLists.txt index 4cf8873a59f..83503f45254 100644 --- a/DPG/Tasks/AOTEvent/CMakeLists.txt +++ b/DPG/Tasks/AOTEvent/CMakeLists.txt @@ -11,7 +11,7 @@ o2physics_add_dpl_workflow(event-selection-qa SOURCES eventSelectionQa.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::AnalysisCCDB O2::DetectorsBase + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::AnalysisCCDB O2::DetectorsBase O2::DataFormatsITSMFT COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(lumi-qa diff --git a/PWGCF/TwoParticleCorrelations/Tasks/CMakeLists.txt b/PWGCF/TwoParticleCorrelations/Tasks/CMakeLists.txt index 83526365550..3ff80210ce2 100644 --- a/PWGCF/TwoParticleCorrelations/Tasks/CMakeLists.txt +++ b/PWGCF/TwoParticleCorrelations/Tasks/CMakeLists.txt @@ -40,7 +40,7 @@ o2physics_add_dpl_workflow(dpt-dpt-efficiency-and-qc o2physics_add_dpl_workflow(dpt-dpt-per-run-qc SOURCES dptDptPerRunQc.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGCFCore O2Physics::AnalysisCCDB + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGCFCore O2Physics::AnalysisCCDB O2::DataFormatsITSMFT COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(dpt-dpt-per-run-extra-qc From e2ff8e784eb982b75b86f44a3d5c58fda32619e8 Mon Sep 17 00:00:00 2001 From: amatyja Date: Tue, 24 Jun 2025 22:36:42 +0200 Subject: [PATCH 204/871] [PWGUD] Added RCT flags to UD tables (#11714) --- PWGUD/Core/SGSelector.h | 97 +++++++++++--- PWGUD/DataModel/UDTables.h | 43 +++++- PWGUD/TableProducer/Converters/CMakeLists.txt | 5 + .../UDCollisionSelExtrasV003Converter.cxx | 126 ++++++++++++++++++ PWGUD/TableProducer/DGCandProducer.cxx | 27 ++-- PWGUD/TableProducer/SGCandProducer.cxx | 65 ++++++--- PWGUD/TableProducer/UPCCandidateProducer.cxx | 33 ++--- 7 files changed, 326 insertions(+), 70 deletions(-) create mode 100644 PWGUD/TableProducer/Converters/UDCollisionSelExtrasV003Converter.cxx diff --git a/PWGUD/Core/SGSelector.h b/PWGUD/Core/SGSelector.h index 4845818f244..b9fc3ecf2e7 100644 --- a/PWGUD/Core/SGSelector.h +++ b/PWGUD/Core/SGSelector.h @@ -8,17 +8,26 @@ // 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 SGSelector.h +/// \author Alexander Bylinkin +/// \author Adam Matyja +/// \since 2023-11-21 +/// \brief Support class holding tools to work with Single Gap selection in central barrel UPCs +/// #ifndef PWGUD_CORE_SGSELECTOR_H_ #define PWGUD_CORE_SGSELECTOR_H_ -#include -#include "TDatabasePDG.h" -#include "TLorentzVector.h" -#include "Framework/Logger.h" -#include "Framework/AnalysisTask.h" -#include "PWGUD/Core/UDHelpers.h" #include "PWGUD/Core/SGCutParHolder.h" +#include "PWGUD/Core/UDHelpers.h" + +#include "Common/CCDB/RCTSelectionFlags.h" + +#include "Framework/AnalysisTask.h" +#include "Framework/Logger.h" + +#include template struct SelectionResult { @@ -26,10 +35,20 @@ struct SelectionResult { BC* bc; // Pointer to the BC object }; +namespace o2::aod::sgselector +{ +enum TrueGap : int { + NoGap = -1, + SingleGapA = 0, + SingleGapC = 1, + DoubleGap = 2 +}; +} + class SGSelector { public: - SGSelector() : fPDG(TDatabasePDG::Instance()) {} + SGSelector() : myRCTChecker{"CBT"}, myRCTCheckerHadron{"CBT_hadronPID"}, myRCTCheckerZDC{"CBT", true}, myRCTCheckerHadronZDC{"CBT_hadronPID", true} {} template int Print(SGCutParHolder /*diffCuts*/, CC& collision, BCs& /*bcRange*/, TCs& /*tracks*/, FWs& /*fwdtracks*/) @@ -107,7 +126,8 @@ class SGSelector template int FwdTrkSelector(TFwdTrack const& fwdtrack) { - if (fwdtrack.trackType() == 0 || fwdtrack.trackType() == 3) + // if (fwdtrack.trackType() == 0 || fwdtrack.trackType() == 3) + if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack || fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack) return 1; else return 0; @@ -125,29 +145,68 @@ class SGSelector FT0C = collision.totalFT0AmplitudeC(); ZNA = collision.energyCommonZNA(); ZNC = collision.energyCommonZNC(); - if (gap == 0) { + if (gap == o2::aod::sgselector::SingleGapA) { // gap == 0 if (FV0A > fit_cut[0] || FT0A > fit_cut[1] || ZNA > zdc_cut) - true_gap = -1; - } else if (gap == 1) { + true_gap = o2::aod::sgselector::NoGap; // -1 + } else if (gap == o2::aod::sgselector::SingleGapC) { // gap == 1 if (FT0C > fit_cut[2] || ZNC > zdc_cut) - true_gap = -1; - } else if (gap == 2) { + true_gap = o2::aod::sgselector::NoGap; // -1 + } else if (gap == o2::aod::sgselector::DoubleGap) { // gap == 2 if ((FV0A > fit_cut[0] || FT0A > fit_cut[1] || ZNA > zdc_cut) && (FT0C > fit_cut[2] || ZNC > zdc_cut)) - true_gap = -1; + true_gap = o2::aod::sgselector::NoGap; // -1 else if ((FV0A > fit_cut[0] || FT0A > fit_cut[1] || ZNA > zdc_cut) && (FT0C <= fit_cut[2] && ZNC <= zdc_cut)) - true_gap = 1; + true_gap = o2::aod::sgselector::SingleGapC; // 1 else if ((FV0A <= fit_cut[0] && FT0A <= fit_cut[1] && ZNA <= zdc_cut) && (FT0C > fit_cut[2] || ZNC > zdc_cut)) - true_gap = 0; + true_gap = o2::aod::sgselector::SingleGapA; // 0 else if (FV0A <= fit_cut[0] && FT0A <= fit_cut[1] && ZNA <= zdc_cut && FT0C <= fit_cut[2] && ZNC <= zdc_cut) - true_gap = 2; + true_gap = o2::aod::sgselector::DoubleGap; // 2 else - std::cout << "Something wrong with DG" << std::endl; + LOGF(info, "Something wrong with DG"); } return true_gap; } + // check CBT flags + template + bool isCBTOk(CC& collision) + { + if (myRCTChecker(collision)) + return true; + return false; + } + + // check CBT+hadronPID flags + template + bool isCBTHadronOk(CC& collision) + { + if (myRCTCheckerHadron(collision)) + return true; + return false; + } + + // check CBT+ZDC flags + template + bool isCBTZdcOk(CC& collision) + { + if (myRCTCheckerZDC(collision)) + return true; + return false; + } + + // check CBT+hadronPID+ZDC flags + template + bool isCBTHadronZdcOk(CC& collision) + { + if (myRCTCheckerHadronZDC(collision)) + return true; + return false; + } + private: - TDatabasePDG* fPDG; + o2::aod::rctsel::RCTFlagsChecker myRCTChecker; + o2::aod::rctsel::RCTFlagsChecker myRCTCheckerHadron; + o2::aod::rctsel::RCTFlagsChecker myRCTCheckerZDC; + o2::aod::rctsel::RCTFlagsChecker myRCTCheckerHadronZDC; }; #endif // PWGUD_CORE_SGSELECTOR_H_ diff --git a/PWGUD/DataModel/UDTables.h b/PWGUD/DataModel/UDTables.h index b84f6cd26e7..8a4251ec74d 100644 --- a/PWGUD/DataModel/UDTables.h +++ b/PWGUD/DataModel/UDTables.h @@ -8,18 +8,29 @@ // 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 UDTables.h +/// \brief Defines tables and colums for derived data used by UD group +/// \author Paul Buhler , Wiena +/// \since January 2023 +/// \author Sasha Bylinkin , Bergen +/// \since January 2024 +/// \author Adam Matyja , INP PAN Krakow, Poland +/// \since May 2025 #ifndef PWGUD_DATAMODEL_UDTABLES_H_ #define PWGUD_DATAMODEL_UDTABLES_H_ -#include -#include +#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/TrackSelectionTables.h" + #include "Framework/ASoA.h" #include "Framework/AnalysisDataModel.h" #include "Framework/DataTypes.h" #include "MathUtils/Utils.h" -#include "Common/DataModel/PIDResponse.h" -#include "Common/DataModel/TrackSelectionTables.h" + +#include +#include namespace o2::aod { @@ -111,6 +122,10 @@ DECLARE_SOA_COLUMN(ITSROFb, itsROFb, int); DECLARE_SOA_COLUMN(Sbp, sbp, int); DECLARE_SOA_COLUMN(ZvtxFT0vPV, zVtxFT0vPV, int); DECLARE_SOA_COLUMN(VtxITSTPC, vtxITSTPC, int); +// information about mask names -> Common/CCDB/RCTSelectionFlags.h +// DECLARE_SOA_COLUMN(Rct, rct, uint32_t); //! run condition table mask +DECLARE_SOA_BITMAP_COLUMN(Rct, rct, 32); //! run condition table mask + // Gap Side Information DECLARE_SOA_COLUMN(GapSide, gapSide, uint8_t); // 0 for side A, 1 for side C, 2 for both sides (or use an enum for better readability) // FIT selection flags @@ -249,6 +264,24 @@ DECLARE_SOA_TABLE_VERSIONED(UDCollisionSelExtras_002, "AOD", "UDCOLSELEXTRA", 2, udcollision::ZvtxFT0vPV, //! kIsGoodZvtxFT0vsPV udcollision::VtxITSTPC); //! kIsVertexITSTPC +DECLARE_SOA_TABLE_VERSIONED(UDCollisionSelExtras_003, "AOD", "UDCOLSELEXTRA", 3, + udcollision::ChFT0A, //! number of active channels in FT0A + udcollision::ChFT0C, //! number of active channels in FT0C + udcollision::ChFDDA, //! number of active channels in FDDA + udcollision::ChFDDC, //! number of active channels in FDDC + udcollision::ChFV0A, //! number of active channels in FV0A + udcollision::OccupancyInTime, //! Occupancy + udcollision::HadronicRate, //! Interaction Rate + udcollision::Trs, //! kNoCollInTimeRangeStandard + udcollision::Trofs, //! kNoCollInRofStandard + udcollision::Hmpr, //! kNoHighMultCollInPrevRof + udcollision::TFb, //! kNoTimeFrameBorder + udcollision::ITSROFb, //! kNoITSROFrameBorder + udcollision::Sbp, //! kNoSameBunchPileup + udcollision::ZvtxFT0vPV, //! kIsGoodZvtxFT0vsPV + udcollision::VtxITSTPC, //! kIsVertexITSTPC + udcollision::Rct); //! RCT mask + // central barrel-specific selections DECLARE_SOA_TABLE(UDCollisionsSelsCent, "AOD", "UDCOLSELCNT", udcollision::DBcTOR, @@ -272,7 +305,7 @@ DECLARE_SOA_TABLE(UDMcCollsLabels, "AOD", "UDMCCOLLSLABEL", udcollision::UDMcCollisionId); using UDCollisions = UDCollisions_001; -using UDCollisionSelExtras = UDCollisionSelExtras_002; +using UDCollisionSelExtras = UDCollisionSelExtras_003; using UDCollision = UDCollisions::iterator; using SGCollision = SGCollisions::iterator; diff --git a/PWGUD/TableProducer/Converters/CMakeLists.txt b/PWGUD/TableProducer/Converters/CMakeLists.txt index 8230278b45c..7d5a6297ba1 100644 --- a/PWGUD/TableProducer/Converters/CMakeLists.txt +++ b/PWGUD/TableProducer/Converters/CMakeLists.txt @@ -29,3 +29,8 @@ o2physics_add_dpl_workflow(collisionselextras-converter-v002 SOURCES UDCollisionSelExtrasV002Converter.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(collisionselextras-converter-v003 + SOURCES UDCollisionSelExtrasV003Converter.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) diff --git a/PWGUD/TableProducer/Converters/UDCollisionSelExtrasV003Converter.cxx b/PWGUD/TableProducer/Converters/UDCollisionSelExtrasV003Converter.cxx new file mode 100644 index 00000000000..a41b2c4efa6 --- /dev/null +++ b/PWGUD/TableProducer/Converters/UDCollisionSelExtrasV003Converter.cxx @@ -0,0 +1,126 @@ +// 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 UDCollisionSelExtrasV003Converter.cxx +/// \brief Converts UDCollisionSelExtras table from version 000 to 003 and 001 to 003 and 002 to 003 +/// \author Adam Matyja + +#include "PWGUD/DataModel/UDTables.h" + +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" + +using namespace o2; +using namespace o2::framework; + +// Converts UDCollisions for version 000 to 003 and 001 to 003 and 002 to 003 +struct UDCollisionSelExtrasV003Converter { + Produces udCollisionSelExtras_003; + + void init(InitContext const&) + { + if (!doprocessV000ToV003 && !doprocessV001ToV003 && !doprocessV002ToV003) { + LOGF(fatal, "Neither processV000ToV003 nor processV001ToV003 nor processV002ToV003 is enabled. Please choose one!"); + } + if (static_cast(doprocessV000ToV003) + static_cast(doprocessV001ToV003) + static_cast(doprocessV002ToV003) > 1) { + LOGF(fatal, "More than one among processV000ToV003, processV001ToV003, processV002ToV003 is enabled. Please choose only one!"); + } + } + + void processV000ToV003(o2::aod::UDCollisionSelExtras_000 const& collisions) + { + + for (const auto& collision : collisions) { + + udCollisionSelExtras_003(collision.chFT0A(), + collision.chFT0C(), + collision.chFDDA(), + collision.chFDDC(), + collision.chFV0A(), + 0, // dummy occupancy + 0.0f, // dummy rate + 0, // dummy trs + 0, // dummy trofs + 0, // dummy hmpr + 0, // dummy tfb + 0, // dummy itsROFb + 0, // dummy sbp + 0, // dummy zVtxFT0vPV + 0, // dummy vtxITSTPC + 0); // dummy rct + } + } + PROCESS_SWITCH(UDCollisionSelExtrasV003Converter, processV000ToV003, "process v000-to-v003 conversion", false); + + void processV001ToV003(o2::aod::UDCollisionSelExtras_001 const& collisions) + { + + for (const auto& collision : collisions) { + + udCollisionSelExtras_003(collision.chFT0A(), + collision.chFT0C(), + collision.chFDDA(), + collision.chFDDC(), + collision.chFV0A(), + collision.occupancyInTime(), + collision.hadronicRate(), + collision.trs(), + collision.trofs(), + collision.hmpr(), + 0, // dummy tfb + 0, // dummy itsROFb + 0, // dummy sbp + 0, // dummy zVtxFT0vPV + 0, // dummy vtxITSTPC + 0); // dummy rct + } + } + PROCESS_SWITCH(UDCollisionSelExtrasV003Converter, processV001ToV003, "process v001-to-v003 conversion", false); + + void processV002ToV003(o2::aod::UDCollisionSelExtras_002 const& collisions) + { + + for (const auto& collision : collisions) { + + udCollisionSelExtras_003(collision.chFT0A(), + collision.chFT0C(), + collision.chFDDA(), + collision.chFDDC(), + collision.chFV0A(), + collision.occupancyInTime(), + collision.hadronicRate(), + collision.trs(), + collision.trofs(), + collision.hmpr(), + collision.tfb(), + collision.itsROFb(), + collision.sbp(), + collision.zVtxFT0vPV(), + collision.vtxITSTPC(), + 0); // dummy rct + } + } + PROCESS_SWITCH(UDCollisionSelExtrasV003Converter, processV002ToV003, "process v002-to-v003 conversion", true); +}; + +/// Spawn the extended table for UDCollisionSelExtras003 to avoid the call to the internal spawner and a consequent circular dependency +// struct UDCollisionSelExtrasSpawner { +// Spawns udCollisionSelExtras_003; +// }; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc), + // adaptAnalysisTask(cfgc), + }; +} diff --git a/PWGUD/TableProducer/DGCandProducer.cxx b/PWGUD/TableProducer/DGCandProducer.cxx index 54c353d3d9a..84c892f5660 100644 --- a/PWGUD/TableProducer/DGCandProducer.cxx +++ b/PWGUD/TableProducer/DGCandProducer.cxx @@ -12,20 +12,23 @@ // \brief Saves relevant information of DG candidates // \author Paul Buehler, paul.buehler@oeaw.ac.at -#include -#include -#include -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "ReconstructionDataFormats/Vertex.h" +#include "PWGUD/Core/DGSelector.h" +#include "PWGUD/Core/UPCHelpers.h" +#include "PWGUD/DataModel/UDTables.h" + +#include "Common/CCDB/ctpRateFetcher.h" #include "EventFiltering/Zorro.h" #include "EventFiltering/ZorroSummary.h" + #include "CCDB/BasicCCDBManager.h" -#include "Common/CCDB/ctpRateFetcher.h" -#include "PWGUD/DataModel/UDTables.h" -#include "PWGUD/Core/UPCHelpers.h" -#include "PWGUD/Core/DGSelector.h" +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/runDataProcessing.h" +#include "ReconstructionDataFormats/Vertex.h" + +#include +#include +#include using namespace o2; using namespace o2::framework; @@ -354,7 +357,7 @@ struct DGCandProducer { fitInfo.BBFT0Apf, fitInfo.BBFT0Cpf, fitInfo.BGFT0Apf, fitInfo.BGFT0Cpf, fitInfo.BBFV0Apf, fitInfo.BGFV0Apf, fitInfo.BBFDDApf, fitInfo.BBFDDCpf, fitInfo.BGFDDApf, fitInfo.BGFDDCpf); - outputCollisionSelExtras(chFT0A, chFT0C, chFDDA, chFDDC, chFV0A, occ, ir, trs, trofs, hmpr, tfb, itsROFb, sbp, zVtxFT0vPv, vtxITSTPC); + outputCollisionSelExtras(chFT0A, chFT0C, chFDDA, chFDDC, chFV0A, occ, ir, trs, trofs, hmpr, tfb, itsROFb, sbp, zVtxFT0vPv, vtxITSTPC, collision.rct_raw()); outputCollsLabels(collision.globalIndex()); // update DGTracks tables diff --git a/PWGUD/TableProducer/SGCandProducer.cxx b/PWGUD/TableProducer/SGCandProducer.cxx index de75fff3e72..37fba3120db 100644 --- a/PWGUD/TableProducer/SGCandProducer.cxx +++ b/PWGUD/TableProducer/SGCandProducer.cxx @@ -14,38 +14,43 @@ /// /// \author Alexander Bylinkin , Uniersity of Bergen /// \since 23.11.2023 +/// \author Adam Matyja , INP PAN Krakow, Poland +/// \since May 2025 // -#include -#include -#include -#include +#include "PWGUD/Core/SGSelector.h" +#include "PWGUD/Core/UPCHelpers.h" +#include "PWGUD/DataModel/UDTables.h" + +#include "Common/CCDB/EventSelectionParams.h" +#include "Common/CCDB/ctpRateFetcher.h" +#include "Common/DataModel/EventSelection.h" + #include "CCDB/BasicCCDBManager.h" -#include "Framework/ASoA.h" -#include "Framework/AnalysisDataModel.h" -#include "ReconstructionDataFormats/Vertex.h" #include "CommonConstants/LHCConstants.h" #include "DataFormatsFIT/Triggers.h" +#include "DataFormatsParameters/AggregatedRunInfo.h" +#include "DataFormatsParameters/GRPLHCIFData.h" #include "DataFormatsParameters/GRPMagField.h" #include "DataFormatsParameters/GRPObject.h" -#include "DataFormatsParameters/GRPLHCIFData.h" -#include "DataFormatsParameters/AggregatedRunInfo.h" - -#include "Framework/AnalysisTask.h" +#include "Framework/ASoA.h" #include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" #include "Framework/runDataProcessing.h" -#include "Common/CCDB/EventSelectionParams.h" -#include "Common/CCDB/ctpRateFetcher.h" -#include "Common/DataModel/EventSelection.h" -#include "PWGUD/DataModel/UDTables.h" -#include "PWGUD/Core/UPCHelpers.h" -#include "PWGUD/Core/SGSelector.h" +#include "ReconstructionDataFormats/Vertex.h" + +#include +#include +#include +#include using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; using namespace o2::dataformats; +using namespace o2::aod::rctsel; #define getHist(type, name) std::get>(histPointers[name]) @@ -80,6 +85,9 @@ struct SGCandProducer { Configurable ITSTPCVertex{"ITSTPCVertex", true, "reject ITS-only vertex"}; // if one wants to look at Single Gap pp events Configurable> generatorIds{"generatorIds", std::vector{-1}, "MC generatorIds to process"}; + Configurable isGoodRCTCollision{"isGoodRCTCollision", true, "Check RCT flags for FT0,ITS,TPC and tracking"}; + Configurable isGoodRCTZdc{"isGoodRCTZdc", false, "Check RCT flags for ZDC if present in run"}; + // Configurables to decide which tables are filled Configurable fillTrackTables{"fillTrackTables", true, "Fill track tables"}; Configurable fillFwdTrackTables{"fillFwdTrackTables", true, "Fill forward track tables"}; @@ -88,6 +96,9 @@ struct SGCandProducer { SGSelector sgSelector; ctpRateFetcher mRateFetcher; + // initialize RCT flag checker + RCTFlagsChecker myRCTChecker{"CBT"}; + // data tables Produces outputSGCollisions; Produces outputCollisions; @@ -303,6 +314,18 @@ struct SGCandProducer { return; } getHist(TH1, histdir + "/Stat")->Fill(6., 1.); + // RCT CBT for collision check + if (isGoodRCTCollision && !myRCTChecker(collision)) { + return; + } + getHist(TH1, histdir + "/Stat")->Fill(7., 1.); + // RCT CBT+ZDC for collision check + if (isGoodRCTZdc && !myRCTChecker(collision)) { + return; + } + getHist(TH1, histdir + "/Stat")->Fill(8., 1.); + + // int trs = collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard) ? 1 : 0; int trofs = collision.selection_bit(o2::aod::evsel::kNoCollInRofStandard) ? 1 : 0; int hmpr = collision.selection_bit(o2::aod::evsel::kNoHighMultCollInPrevRof) ? 1 : 0; @@ -331,7 +354,7 @@ struct SGCandProducer { if (verboseInfo) LOGF(info, "No Newbc %i", bc.globalBC()); } - getHist(TH1, histdir + "/Stat")->Fill(issgevent + 8, 1.); + getHist(TH1, histdir + "/Stat")->Fill(issgevent + 10, 1.); if (issgevent <= 2) { if (verboseInfo) LOGF(info, "Current BC: %i, %i, %i", bc.globalBC(), newbc.globalBC(), issgevent); @@ -363,7 +386,7 @@ struct SGCandProducer { fitInfo.BBFT0Apf, fitInfo.BBFT0Cpf, fitInfo.BGFT0Apf, fitInfo.BGFT0Cpf, fitInfo.BBFV0Apf, fitInfo.BGFV0Apf, fitInfo.BBFDDApf, fitInfo.BBFDDCpf, fitInfo.BGFDDApf, fitInfo.BGFDDCpf); - outputCollisionSelExtras(chFT0A, chFT0C, chFDDA, chFDDC, chFV0A, occ, ir, trs, trofs, hmpr, tfb, itsROFb, sbp, zVtxFT0vPv, vtxITSTPC); + outputCollisionSelExtras(chFT0A, chFT0C, chFDDA, chFDDC, chFV0A, occ, ir, trs, trofs, hmpr, tfb, itsROFb, sbp, zVtxFT0vPv, vtxITSTPC, collision.rct_raw()); outputCollsLabels(collision.globalIndex()); if (newbc.has_zdc()) { auto zdc = newbc.zdc(); @@ -428,6 +451,10 @@ struct SGCandProducer { if (context.mOptions.get("processMcData")) { histPointers.insert({"MCreco/Stat", registry.add("MCreco/Stat", "Cut statistics; Selection criterion; Collisions", {HistType::kTH1F, {{14, -0.5, 13.5}}})}); } + + if (isGoodRCTZdc) { + myRCTChecker.init("CBT", true); + } } // process function for reconstructed data diff --git a/PWGUD/TableProducer/UPCCandidateProducer.cxx b/PWGUD/TableProducer/UPCCandidateProducer.cxx index e7f029ae91d..2208060bd59 100644 --- a/PWGUD/TableProducer/UPCCandidateProducer.cxx +++ b/PWGUD/TableProducer/UPCCandidateProducer.cxx @@ -12,24 +12,27 @@ /// \author Diana Krupova, diana.krupova@cern.ch /// \since 04.06.2024 -#include -#include -#include -#include -#include -#include -#include -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" +#include "PWGUD/Core/UPCCutparHolder.h" +#include "PWGUD/Core/UPCHelpers.h" +#include "PWGUD/DataModel/UDTables.h" + #include "Common/CCDB/EventSelectionParams.h" #include "Common/DataModel/EventSelection.h" + #include "CommonConstants/LHCConstants.h" #include "DataFormatsFIT/Triggers.h" -#include "PWGUD/Core/UPCCutparHolder.h" -#include "PWGUD/Core/UPCHelpers.h" -#include "PWGUD/DataModel/UDTables.h" #include "DataFormatsITSMFT/ROFRecord.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" + +#include +#include +#include +#include +#include +#include +#include using namespace o2::framework; using namespace o2::framework::expressions; @@ -1512,7 +1515,7 @@ struct UpcCandProducer { fitInfo.BBFT0Apf, fitInfo.BBFT0Cpf, fitInfo.BGFT0Apf, fitInfo.BGFT0Cpf, fitInfo.BBFV0Apf, fitInfo.BGFV0Apf, fitInfo.BBFDDApf, fitInfo.BBFDDCpf, fitInfo.BGFDDApf, fitInfo.BGFDDCpf); - eventCandidatesSelExtras(chFT0A, chFT0C, chFDDA, chFDDC, chFV0A, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + eventCandidatesSelExtras(chFT0A, chFT0C, chFDDA, chFDDC, chFV0A, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); eventCandidatesSelsFwd(fitInfo.distClosestBcV0A, fitInfo.distClosestBcT0A, amplitudesT0A, @@ -1828,7 +1831,7 @@ struct UpcCandProducer { fitInfo.BBFT0Apf, fitInfo.BBFT0Cpf, fitInfo.BGFT0Apf, fitInfo.BGFT0Cpf, fitInfo.BBFV0Apf, fitInfo.BGFV0Apf, fitInfo.BBFDDApf, fitInfo.BBFDDCpf, fitInfo.BGFDDApf, fitInfo.BGFDDCpf); - eventCandidatesSelExtras(chFT0A, chFT0C, chFDDA, chFDDC, chFV0A, 0, 0, trs, trofs, hmpr, tfb, itsROFb, sbp, zVtxFT0vPv, vtxITSTPC); + eventCandidatesSelExtras(chFT0A, chFT0C, chFDDA, chFDDC, chFV0A, 0, 0, trs, trofs, hmpr, tfb, itsROFb, sbp, zVtxFT0vPv, vtxITSTPC, 0); eventCandidatesSelsFwd(fitInfo.distClosestBcV0A, fitInfo.distClosestBcT0A, amplitudesT0A, From c6068451f5dd3c19be679d50d4ded3d925bb5dae Mon Sep 17 00:00:00 2001 From: Hirak Koley Date: Wed, 25 Jun 2025 03:37:02 +0530 Subject: [PATCH 205/871] [PWGLF] update PID and MC process (#11749) --- PWGLF/Tasks/Resonances/lstaranalysis.cxx | 260 +++++++++++------------ 1 file changed, 122 insertions(+), 138 deletions(-) diff --git a/PWGLF/Tasks/Resonances/lstaranalysis.cxx b/PWGLF/Tasks/Resonances/lstaranalysis.cxx index 2e871bdae5a..2603058f795 100644 --- a/PWGLF/Tasks/Resonances/lstaranalysis.cxx +++ b/PWGLF/Tasks/Resonances/lstaranalysis.cxx @@ -82,6 +82,7 @@ struct Lstaranalysis { 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 cfgMinCrossedRows{"cfgMinCrossedRows", 70, "min crossed rows for good track"}; // DCA Selections // DCAr to PV @@ -111,7 +112,6 @@ struct Lstaranalysis { Configurable> kaonTOFPIDcuts{"kaonTOFPIDcuts", {2}, "nSigma list for Kaon TOF PID cuts"}; Configurable> kaonTPCTOFCombinedpTintv{"kaonTPCTOFCombinedpTintv", {999.}, "pT intervals for Kaon TPC-TOF PID cuts"}; Configurable> kaonTPCTOFCombinedPIDcuts{"kaonTPCTOFCombinedPIDcuts", {2}, "nSigma list for Kaon TPC-TOF PID cuts"}; - Configurable cMaxTPCnSigmaKaonVETO{"cMaxTPCnSigmaKaonVETO", 3.0, "TPC nSigma VETO cut for Kaon"}; // TPC // Proton Configurable> protonTPCPIDpTintv{"protonTPCPIDpTintv", {0.9}, "pT intervals for Kaon TPC PID cuts"}; @@ -120,7 +120,6 @@ struct Lstaranalysis { Configurable> protonTOFPIDcuts{"protonTOFPIDcuts", {2}, "nSigma list for Kaon TOF PID cuts"}; Configurable> protonTPCTOFCombinedpTintv{"protonTPCTOFCombinedpTintv", {999.}, "pT intervals for Proton TPC-TOF PID cuts"}; Configurable> protonTPCTOFCombinedPIDcuts{"protonTPCTOFCombinedPIDcuts", {2}, "nSigma list for Proton TPC-TOF PID cuts"}; - Configurable cMaxTPCnSigmaProtonVETO{"cMaxTPCnSigmaProtonVETO", 3.0, "TPC nSigma VETO cut for Proton"}; // TPC // Additional purity check Configurable crejectPion{"crejectPion", false, "Switch to turn on/off pion contamination"}; @@ -258,17 +257,17 @@ struct Lstaranalysis { if (doprocessData) { // Track QA before cuts // --- Track - histos.add("QA/QAbefore/Track/TOF_TPC_Map_ka_all", "TOF + TPC Combined PID for Kaon;#sigma_{TOF}^{Kaon};#sigma_{TPC}^{Kaon}", {HistType::kTHnSparseF, {axisPIDQA, axisPIDQA}}); - histos.add("QA/QAbefore/Track/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/QAbefore/Track/TPC_Nsigma_ka_all", "TPC NSigma for Kaon;#it{p}_{T} (GeV/#it{c});#sigma_{TPC}^{Kaon};", {HistType::kTHnSparseF, {axisMult, axisPt, axisPIDQA}}); - histos.add("QA/QAbefore/Track/TPConly_Nsigma_ka", "TPC NSigma for Kaon;#it{p}_{T} (GeV/#it{c});#sigma_{TPC}^{Kaon};", {HistType::kTHnSparseF, {axisPt, axisPIDQA}}); - histos.add("QA/QAbefore/Track/TOF_TPC_Map_pr_all", "TOF + TPC Combined PID for Proton;#sigma_{TOF}^{Proton};#sigma_{TPC}^{Proton}", {HistType::kTHnSparseF, {axisPIDQA, axisPIDQA}}); - histos.add("QA/QAbefore/Track/TOF_Nsigma_pr_all", "TOF NSigma for Proton;#it{p}_{T} (GeV/#it{c});#sigma_{TOF}^{Proton};", {HistType::kTHnSparseF, {axisMult, axisPt, axisPIDQA}}); - histos.add("QA/QAbefore/Track/TPC_Nsigma_pr_all", "TPC NSigma for Proton;#it{p}_{T} (GeV/#it{c});#sigma_{TPC}^{Proton};", {HistType::kTHnSparseF, {axisMult, axisPt, axisPIDQA}}); - histos.add("QA/QAbefore/Track/TPConly_Nsigma_pr", "TPC NSigma for Proton;#it{p}_{T} (GeV/#it{c});#sigma_{TPC}^{Proton};", {HistType::kTHnSparseF, {axisPt, axisPIDQA}}); - histos.add("QA/QAbefore/Track/dcaZ", "DCA_{Z} distribution of selected Kaons; #it{p}_{T} (GeV/#it{c}); DCA_{Z} (cm); ", HistType::kTHnSparseF, {axisPt, axisDCAz}); - histos.add("QA/QAbefore/Track/dcaXY", "DCA_{XY} momentum distribution of selected Kaons; #it{p}_{T} (GeV/#it{c}); DCA_{XY} (cm);", HistType::kTHnSparseF, {axisPt, axisDCAxy}); - histos.add("QA/QAbefore/Track/TPC_CR", "# TPC Xrows distribution of selected Kaons; #it{p}_{T} (GeV/#it{c}); TPC X rows", HistType::kTHnSparseF, {axisPt, axisTPCXrow}); + histos.add("QA/QAbefore/Track/TOF_TPC_Map_ka_all", "TOF + TPC Combined PID for Kaon;{#sigma_{TOF}^{Kaon}};{#sigma_{TPC}^{Kaon}}", {HistType::kTH2F, {axisPIDQA, axisPIDQA}}); + histos.add("QA/QAbefore/Track/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/QAbefore/Track/TPC_Nsigma_ka_all", "TPC NSigma for Kaon;#it{p}_{T} (GeV/#it{c});{#sigma_{TPC}^{Kaon}};", {HistType::kTHnSparseF, {axisMult, axisPt, axisPIDQA}}); + histos.add("QA/QAbefore/Track/TPConly_Nsigma_ka", "TPC NSigma for Kaon;#it{p}_{T} (GeV/#it{c});{#sigma_{TPC}^{Kaon}};", {HistType::kTH2F, {axisPt, axisPIDQA}}); + histos.add("QA/QAbefore/Track/TOF_TPC_Map_pr_all", "TOF + TPC Combined PID for Proton;{#sigma_{TOF}^{Proton}};{#sigma_{TPC}^{Proton}}", {HistType::kTH2F, {axisPIDQA, axisPIDQA}}); + histos.add("QA/QAbefore/Track/TOF_Nsigma_pr_all", "TOF NSigma for Proton;#it{p}_{T} (GeV/#it{c});{#sigma_{TOF}^{Proton}};", {HistType::kTHnSparseF, {axisMult, axisPt, axisPIDQA}}); + histos.add("QA/QAbefore/Track/TPC_Nsigma_pr_all", "TPC NSigma for Proton;#it{p}_{T} (GeV/#it{c});{#sigma_{TPC}^{Proton}};", {HistType::kTHnSparseF, {axisMult, axisPt, axisPIDQA}}); + histos.add("QA/QAbefore/Track/TPConly_Nsigma_pr", "TPC NSigma for Proton;#it{p}_{T} (GeV/#it{c});{#sigma_{TPC}^{Proton}};", {HistType::kTH2F, {axisPt, axisPIDQA}}); + histos.add("QA/QAbefore/Track/dcaZ", "DCA_{Z} distribution of selected Kaons; #it{p}_{T} (GeV/#it{c}); DCA_{Z} (cm); ", HistType::kTH2F, {axisPt, axisDCAz}); + histos.add("QA/QAbefore/Track/dcaXY", "DCA_{XY} momentum distribution of selected Kaons; #it{p}_{T} (GeV/#it{c}); DCA_{XY} (cm);", HistType::kTH2F, {axisPt, axisDCAxy}); + histos.add("QA/QAbefore/Track/TPC_CR", "# TPC Xrows distribution of selected Kaons; #it{p}_{T} (GeV/#it{c}); TPC X rows", HistType::kTH2F, {axisPt, axisTPCXrow}); histos.add("QA/QAbefore/Track/pT", "pT distribution of Kaons; #it{p}_{T} (GeV/#it{c}); Counts;", {HistType::kTH1F, {axisPt}}); histos.add("QA/QAbefore/Track/eta", "#eta distribution of Kaons; #eta; Counts;", {HistType::kTH1F, {axisEta}}); @@ -280,29 +279,29 @@ struct Lstaranalysis { // PID QA after cuts // --- Kaon - histos.add("QA/QAafter/Kaon/TOF_TPC_Map_ka_all", "TOF + TPC Combined PID for Kaon;#sigma_{TOF}^{Kaon};#sigma_{TPC}^{Kaon}", {HistType::kTHnSparseF, {axisPIDQA, axisPIDQA}}); - histos.add("QA/QAafter/Kaon/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/QAafter/Kaon/TPC_Nsigma_ka_all", "TPC NSigma for Kaon;#it{p}_{T} (GeV/#it{c});#sigma_{TPC}^{Kaon};", {HistType::kTHnSparseF, {axisMult, axisPt, axisPIDQA}}); - histos.add("QA/QAafter/Kaon/TPC_Nsigma_ka_TPConly", "TPC NSigma for Kaon;#it{p}_{T} (GeV/#it{c});#sigma_{TPC}^{Kaon};", {HistType::kTHnSparseF, {axisPt, axisPIDQA}}); - histos.add("QA/QAafter/Kaon/dcaZ", "DCA_{Z} distribution of selected Kaons; #it{p}_{T} (GeV/#it{c}); DCA_{Z} (cm); ", HistType::kTHnSparseF, {axisPt, axisDCAz}); - histos.add("QA/QAafter/Kaon/dcaXY", "DCA_{XY} momentum distribution of selected Kaons; #it{p}_{T} (GeV/#it{c}); DCA_{XY} (cm);", HistType::kTHnSparseF, {axisPt, axisDCAxy}); - histos.add("QA/QAafter/Kaon/TPC_CR", "# TPC Xrows distribution of selected Kaons; #it{p}_{T} (GeV/#it{c}); TPC X rows", HistType::kTHnSparseF, {axisPt, axisTPCXrow}); + histos.add("QA/QAafter/Kaon/TOF_TPC_Map_ka_all", "TOF + TPC Combined PID for Kaon;{#sigma_{TOF}^{Kaon}};{#sigma_{TPC}^{Kaon}}", {HistType::kTH2F, {axisPIDQA, axisPIDQA}}); + histos.add("QA/QAafter/Kaon/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/QAafter/Kaon/TPC_Nsigma_ka_all", "TPC NSigma for Kaon;#it{p}_{T} (GeV/#it{c});{#sigma_{TPC}^{Kaon}};", {HistType::kTHnSparseF, {axisMult, axisPt, axisPIDQA}}); + histos.add("QA/QAafter/Kaon/TPC_Nsigma_ka_TPConly", "TPC NSigma for Kaon;#it{p}_{T} (GeV/#it{c});{#sigma_{TPC}^{Kaon}};", {HistType::kTH2F, {axisPt, axisPIDQA}}); + histos.add("QA/QAafter/Kaon/dcaZ", "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", "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", "# 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", "pT distribution of Kaons; #it{p}_{T} (GeV/#it{c}); Counts;", {HistType::kTH1F, {axisPt}}); histos.add("QA/QAafter/Kaon/eta", "#eta distribution of Kaons; #eta; Counts;", {HistType::kTH1F, {axisEta}}); - histos.add("QA/QAafter/Kaon/TPC_Signal_ka_all", "TPC Signal for Kaon;#it{p}_{T} (GeV/#it{c});TPC Signal (A.U.)", {HistType::kTHnSparseF, {axisPt, axisTPCSignal}}); + histos.add("QA/QAafter/Kaon/TPC_Signal_ka_all", "TPC Signal for Kaon;#it{p} (GeV/#it{c});TPC Signal (A.U.)", {HistType::kTH2F, {axisPt, axisTPCSignal}}); histos.add("QA/QAafter/Kaon/TPCnclusterPhika", "TPC ncluster vs phi", kTHnSparseF, {{160, 0, 160, "TPC nCluster"}, {63, 0, 6.28, "#phi"}}); // --- Proton - histos.add("QA/QAafter/Proton/TOF_TPC_Map_pr_all", "TOF + TPC Combined PID for Proton;#sigma_{TOF}^{Proton};#sigma_{TPC}^{Proton}", {HistType::kTHnSparseF, {axisPIDQA, axisPIDQA}}); - histos.add("QA/QAafter/Proton/TOF_Nsigma_pr_all", "TOF NSigma for Proton;#it{p}_{T} (GeV/#it{c});#sigma_{TOF}^{Proton};", {HistType::kTHnSparseF, {axisMult, axisPt, axisPIDQA}}); - histos.add("QA/QAafter/Proton/TPC_Nsigma_pr_all", "TPC NSigma for Proton;#it{p}_{T} (GeV/#it{c});#sigma_{TPC}^{Proton};", {HistType::kTHnSparseF, {axisMult, axisPt, axisPIDQA}}); - histos.add("QA/QAafter/Proton/TPC_Nsigma_pr_TPConly", "TPC NSigma for Proton;#it{p}_{T} (GeV/#it{c});#sigma_{TPC}^{Proton};", {HistType::kTHnSparseF, {axisPt, axisPIDQA}}); - histos.add("QA/QAafter/Proton/dcaZ", "DCA_{Z} distribution of selected Protons; #it{p}_{T} (GeV/#it{c}); DCA_{Z} (cm);", HistType::kTHnSparseF, {axisPt, axisDCAz}); - histos.add("QA/QAafter/Proton/dcaXY", "DCA_{XY} momentum distribution of selected Protons; #it{p}_{T} (GeV/#it{c}); DCA_{XY} (cm);", HistType::kTHnSparseF, {axisPt, axisDCAxy}); - histos.add("QA/QAafter/Proton/TPC_CR", "# TPC Xrows distribution of selected Protons; #it{p}_{T} (GeV/#it{c}); TPC X rows", HistType::kTHnSparseF, {axisPt, axisTPCXrow}); + histos.add("QA/QAafter/Proton/TOF_TPC_Map_pr_all", "TOF + TPC Combined PID for Proton;{#sigma_{TOF}^{Proton}};{#sigma_{TPC}^{Proton}}", {HistType::kTH2F, {axisPIDQA, axisPIDQA}}); + histos.add("QA/QAafter/Proton/TOF_Nsigma_pr_all", "TOF NSigma for Proton;#it{p}_{T} (GeV/#it{c});{#sigma_{TOF}^{Proton}};", {HistType::kTHnSparseF, {axisMult, axisPt, axisPIDQA}}); + histos.add("QA/QAafter/Proton/TPC_Nsigma_pr_all", "TPC NSigma for Proton;#it{p}_{T} (GeV/#it{c});{#sigma_{TPC}^{Proton}};", {HistType::kTHnSparseF, {axisMult, axisPt, axisPIDQA}}); + histos.add("QA/QAafter/Proton/TPC_Nsigma_pr_TPConly", "TPC NSigma for Proton;#it{p}_{T} (GeV/#it{c});{#sigma_{TPC}^{Proton}};", {HistType::kTH2F, {axisPt, axisPIDQA}}); + histos.add("QA/QAafter/Proton/dcaZ", "DCA_{Z} distribution of selected Protons; #it{p}_{T} (GeV/#it{c}); DCA_{Z} (cm);", HistType::kTH2F, {axisPt, axisDCAz}); + histos.add("QA/QAafter/Proton/dcaXY", "DCA_{XY} momentum distribution of selected Protons; #it{p}_{T} (GeV/#it{c}); DCA_{XY} (cm);", HistType::kTH2F, {axisPt, axisDCAxy}); + histos.add("QA/QAafter/Proton/TPC_CR", "# TPC Xrows distribution of selected Protons; #it{p}_{T} (GeV/#it{c}); TPC X rows", HistType::kTH2F, {axisPt, axisTPCXrow}); histos.add("QA/QAafter/Proton/pT", "pT distribution of Protons; #it{p}_{T} (GeV/#it{c}); Counts;", {HistType::kTH1F, {axisPt}}); histos.add("QA/QAafter/Proton/eta", "#eta distribution of Protons; #eta; Counts;", {HistType::kTH1F, {axisEta}}); - histos.add("QA/QAafter/Proton/TPC_Signal_pr_all", "TPC Signal for Proton;#it{p}_{T} (GeV/#it{c});TPC Signal (A.U.)", {HistType::kTHnSparseF, {axisPt, axisTPCSignal}}); + histos.add("QA/QAafter/Proton/TPC_Signal_pr_all", "TPC Signal for Proton;#it{p} (GeV/#it{c});TPC Signal (A.U.)", {HistType::kTH2F, {axisPt, axisTPCSignal}}); histos.add("QA/QAafter/Proton/TPCnclusterPhipr", "TPC ncluster vs phi", kTHnSparseF, {{160, 0, 160, "TPC nCluster"}, {63, 0, 6.28, "#phi"}}); // Mass QA 1D for quick check @@ -349,7 +348,7 @@ struct Lstaranalysis { histos.add("Result/Data/h3lambda1520invmassME_DSAnti", "Invariant mass of #Lambda(1520) mixed event DSAnti", kTHnSparseF, {axisMult, axisPt, axisMassLambda1520}); } } - histos.add("QAMC", "all Lambda", kTH1F, {{1000, -0.5, 999.5}}); + // MC QA if (doprocessMCTrue) { histos.add("QA/MC/h2GenEtaPt_beforeanycut", " #eta-#it{p}_{T} distribution of Generated #Lambda(1520); #eta; #it{p}_{T}; Counts;", HistType::kTHnSparseF, {axisEta, axisPtQA}); @@ -370,10 +369,10 @@ struct Lstaranalysis { histos.add("QA/MC/trkDCAxy_ka", "DCAxy distribution of kaon track candidates", HistType::kTHnSparseF, {axisPt, axisDCAxy}); histos.add("QA/MC/trkDCAz_pr", "DCAz distribution of proton 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_pr_all", "TOF NSigma for Proton;#it{p}_{T} (GeV/#it{c});#sigma_{TOF}^{Proton};", {HistType::kTHnSparseF, {axisMult, axisPt, axisPIDQA}}); - histos.add("QA/MC/TPC_Nsigma_pr_all", "TPC NSigma for Proton;#it{p}_{T} (GeV/#it{c});#sigma_{TPC}^{Proton};", {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("QA/MC/TOF_Nsigma_pr_all", "TOF NSigma for Proton;#it{p}_{T} (GeV/#it{c});{#sigma_{TOF}^{Proton}};", {HistType::kTHnSparseF, {axisMult, axisPt, axisPIDQA}}); + histos.add("QA/MC/TPC_Nsigma_pr_all", "TPC NSigma for Proton;#it{p}_{T} (GeV/#it{c});{#sigma_{TPC}^{Proton}};", {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/h3lambda1520Recoinvmass", "Invariant mass of Reconstructed MC #Lambda(1520)0", kTHnSparseF, {axisMult, axisPt, axisMassLambda1520}); histos.add("Result/MC/h3antilambda1520Recoinvmass", "Invariant mass of Reconstructed MC Anti-#Lambda(1520)0", kTHnSparseF, {axisMult, axisPt, axisMassLambda1520}); @@ -418,6 +417,8 @@ struct Lstaranalysis { return false; if (cTPCNClsFound && (track.tpcNClsFound() < cMinTPCNClsFound)) return false; + if (track.tpcNClsCrossedRows() < cfgMinCrossedRows) + return false; if (cfgHasTOF && !track.hasTOF()) return false; if (cfgPrimaryTrack && !track.isPrimaryTrack()) @@ -436,7 +437,9 @@ struct Lstaranalysis { return true; } - // PID selection old PID method + // 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 pTdependentPIDProton(const T& candidate) { @@ -447,69 +450,58 @@ struct Lstaranalysis { auto vProtonTPCTOFCombinedpTintv = static_cast>(protonTPCTOFCombinedpTintv); auto vProtonTPCTOFCombinedPIDcuts = static_cast>(protonTPCTOFCombinedPIDcuts); auto vProtonTOFPIDcuts = static_cast>(protonTOFPIDcuts); - auto lengthOfprotonTPCPIDpTintv = static_cast(vProtonTPCPIDpTintv.size()); - auto lengthOfprotonTOFPIDpTintv = static_cast(vProtonTOFPIDpTintv.size()); - auto lengthOfprotonTPCTOFCombinedPIDpTintv = static_cast(vProtonTPCTOFCombinedpTintv.size()); - bool tpcPIDPassed{false}, tofPIDPassed{false}; + float pt = candidate.pt(); + float ptSwitchToTOF = vProtonTPCPIDpTintv.back(); - // For Proton candidate: - // TPC PID - if (lengthOfprotonTPCPIDpTintv > 0) { - if (candidate.pt() > vProtonTPCPIDpTintv[lengthOfprotonTPCPIDpTintv - 1]) { - tpcPIDPassed = false; - } else { - for (int i = 0; i < lengthOfprotonTPCPIDpTintv; i++) { - if (candidate.pt() > vProtonTPCPIDpTintv[i] && candidate.pt() < vProtonTPCPIDpTintv[i + 1]) { - if (std::abs(candidate.tpcNSigmaPr()) < vProtonTPCPIDcuts[i]) - tpcPIDPassed = true; - } - } + bool tpcPIDPassed = false; + + // TPC PID (interval check) + for (size_t i = 0; i < vProtonTPCPIDpTintv.size() - 1; ++i) { + if (pt > vProtonTPCPIDpTintv[i] && pt < vProtonTPCPIDpTintv[i + 1]) { + if (std::abs(candidate.tpcNSigmaPr()) < vProtonTPCPIDcuts[i]) + tpcPIDPassed = true; } } - // bypass TOF - if (cByPassTOF && tpcPIDPassed) { - return true; + // TOF bypass option (for QA or MC) + if (cByPassTOF) { + return std::abs(candidate.tpcNSigmaPr()) < vProtonTPCPIDcuts.back(); } - // TOF PID - if (candidate.hasTOF() && candidate.pt() > vProtonTPCPIDpTintv[lengthOfprotonTPCPIDpTintv - 1]) { - if (cPIDcutType == 1) { - if (lengthOfprotonTOFPIDpTintv > 0) { - if (candidate.pt() > vProtonTOFPIDpTintv[lengthOfprotonTOFPIDpTintv - 1]) { - tofPIDPassed = false; - } else { - for (int i = 0; i < lengthOfprotonTOFPIDpTintv; i++) { - if (candidate.pt() < vProtonTOFPIDpTintv[i]) { + // Case 1: No TOF and pt ≤ threshold → accept only via TPC PID + if (!candidate.hasTOF() && pt <= ptSwitchToTOF) { + return tpcPIDPassed; + } - if (std::abs(candidate.tofNSigmaPr()) < vProtonTOFPIDcuts[i] && std::abs(candidate.tpcNSigmaPr()) < cMaxTPCnSigmaProtonVETO) - tofPIDPassed = true; - } - } + // 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 (cPIDcutType == 1) { + // Rectangular cut + for (size_t i = 0; i < vProtonTOFPIDpTintv.size(); ++i) { + if (pt < vProtonTOFPIDpTintv[i]) { + if (std::abs(candidate.tofNSigmaPr()) < vProtonTOFPIDcuts[i] && + std::abs(candidate.tpcNSigmaPr()) < vProtonTPCPIDcuts.back()) + return true; } } - } else if (cPIDcutType == static_cast(2)) { - if (lengthOfprotonTPCTOFCombinedPIDpTintv > 0) { - if (candidate.pt() > vProtonTPCTOFCombinedpTintv[lengthOfprotonTPCTOFCombinedPIDpTintv - 1]) { - tofPIDPassed = false; - } else { - for (int i = 0; i < lengthOfprotonTPCTOFCombinedPIDpTintv; i++) { - if (candidate.pt() < vProtonTPCTOFCombinedpTintv[i]) { - if ((candidate.tpcNSigmaPr() * candidate.tpcNSigmaPr() + candidate.tofNSigmaPr() * candidate.tofNSigmaPr()) < (vProtonTPCTOFCombinedPIDcuts[i] * vProtonTPCTOFCombinedPIDcuts[i])) - tofPIDPassed = true; - } - } + } else if (cPIDcutType == 2) { + // Circular cut + for (size_t i = 0; i < vProtonTPCTOFCombinedpTintv.size(); ++i) { + if (pt < vProtonTPCTOFCombinedpTintv[i]) { + float combinedSigma2 = + candidate.tpcNSigmaPr() * candidate.tpcNSigmaPr() + + candidate.tofNSigmaPr() * candidate.tofNSigmaPr(); + if (combinedSigma2 < vProtonTPCTOFCombinedPIDcuts[i] * vProtonTPCTOFCombinedPIDcuts[i]) + return true; } } } - } else { - tofPIDPassed = true; - } - - // TPC-TOF Combined PID - if (tpcPIDPassed && tofPIDPassed) { - return true; } return false; @@ -525,69 +517,61 @@ struct Lstaranalysis { auto vKaonTPCTOFCombinedpTintv = static_cast>(kaonTPCTOFCombinedpTintv); auto vKaonTPCTOFCombinedPIDcuts = static_cast>(kaonTPCTOFCombinedPIDcuts); auto vKaonTOFPIDcuts = static_cast>(kaonTOFPIDcuts); - auto lengthOfkaonTPCPIDpTintv = static_cast(vKaonTPCPIDpTintv.size()); - auto lengthOfkaonTOFPIDpTintv = static_cast(vKaonTOFPIDpTintv.size()); - auto lengthOfkaonTPCTOFCombinedPIDpTintv = static_cast(vKaonTPCTOFCombinedpTintv.size()); - bool tpcPIDPassed{false}, tofPIDPassed{false}; + float pt = candidate.pt(); + float ptSwitchToTOF = vKaonTPCPIDpTintv.back(); - // For Kaon candidate: - // TPC PID - if (lengthOfkaonTPCPIDpTintv > 0) { - if (candidate.pt() > vKaonTPCPIDpTintv[lengthOfkaonTPCPIDpTintv - 1]) { - tpcPIDPassed = false; - } else { - for (int i = 0; i < lengthOfkaonTPCPIDpTintv; i++) { - if (candidate.pt() > vKaonTPCPIDpTintv[i] && candidate.pt() < vKaonTPCPIDpTintv[i + 1]) { - if (std::abs(candidate.tpcNSigmaKa()) < vKaonTPCPIDcuts[i]) - tpcPIDPassed = true; - } + 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(candidate.tpcNSigmaKa()) < vKaonTPCPIDcuts[i]) { + tpcPIDPassed = true; + break; } } } - // bypass TOF - if (cByPassTOF && tpcPIDPassed) { - return true; + // TOF bypass option + if (cByPassTOF) { + return std::abs(candidate.tpcNSigmaKa()) < vKaonTPCPIDcuts.back(); } - // TOF PID - if (candidate.hasTOF() && candidate.pt() > vKaonTPCPIDpTintv[lengthOfkaonTPCPIDpTintv - 1]) { - if (cPIDcutType == 1) { - if (lengthOfkaonTOFPIDpTintv > 0) { - if (candidate.pt() > vKaonTOFPIDpTintv[lengthOfkaonTOFPIDpTintv - 1]) { - tofPIDPassed = false; - } else { - for (int i = 0; i < lengthOfkaonTOFPIDpTintv; i++) { - if (candidate.pt() < vKaonTOFPIDpTintv[i]) { + // Case 1: No TOF and pt ≤ ptSwitch → use TPC-only + if (!candidate.hasTOF() && pt <= ptSwitchToTOF) { + return tpcPIDPassed; + } - if (std::abs(candidate.tofNSigmaKa()) < vKaonTOFPIDcuts[i] && std::abs(candidate.tpcNSigmaKa()) < cMaxTPCnSigmaKaonVETO) - tofPIDPassed = true; - } + // 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 (cPIDcutType == 1) { + // Rectangular cut + for (size_t i = 0; i < vKaonTOFPIDpTintv.size(); ++i) { + if (pt < vKaonTOFPIDpTintv[i]) { + if (std::abs(candidate.tofNSigmaKa()) < vKaonTOFPIDcuts[i] && + std::abs(candidate.tpcNSigmaKa()) < vKaonTPCPIDcuts.back()) { + return true; } } } - } else if (cPIDcutType == static_cast(2)) { - if (lengthOfkaonTPCTOFCombinedPIDpTintv > 0) { - if (candidate.pt() > vKaonTPCTOFCombinedpTintv[lengthOfkaonTPCTOFCombinedPIDpTintv - 1]) { - tofPIDPassed = false; - } else { - for (int i = 0; i < lengthOfkaonTPCTOFCombinedPIDpTintv; i++) { - if (candidate.pt() < vKaonTPCTOFCombinedpTintv[i]) { - if ((candidate.tpcNSigmaKa() * candidate.tpcNSigmaKa() + candidate.tofNSigmaKa() * candidate.tofNSigmaKa()) < (vKaonTPCTOFCombinedPIDcuts[i] * vKaonTPCTOFCombinedPIDcuts[i])) - tofPIDPassed = true; - } + } else if (cPIDcutType == 2) { + // Circular cut + for (size_t i = 0; i < vKaonTPCTOFCombinedpTintv.size(); ++i) { + if (pt < vKaonTPCTOFCombinedpTintv[i]) { + float combinedSigma2 = candidate.tpcNSigmaKa() * candidate.tpcNSigmaKa() + + candidate.tofNSigmaKa() * candidate.tofNSigmaKa(); + if (combinedSigma2 < vKaonTPCTOFCombinedPIDcuts[i] * vKaonTPCTOFCombinedPIDcuts[i]) { + return true; } } } } - } else { - tofPIDPassed = true; - } - - // TPC-TOF Combined PID - if (tpcPIDPassed && tofPIDPassed) { - return true; } return false; @@ -706,7 +690,7 @@ struct Lstaranalysis { //// QA plots after the selection if constexpr (IsData) { // --- PID QA Proton histos.fill(HIST("QA/QAafter/Proton/TPC_Nsigma_pr_all"), multiplicity, trk1ptPr, trk1NSigmaPrTPC); - histos.fill(HIST("QA/QAafter/Proton/TPC_Signal_pr_all"), trk1ptPr, trk1.tpcSignal()); + histos.fill(HIST("QA/QAafter/Proton/TPC_Signal_pr_all"), trk1.tpcInnerParam(), trk1.tpcSignal()); if (isTrk1hasTOF) { histos.fill(HIST("QA/QAafter/Proton/TOF_Nsigma_pr_all"), multiplicity, trk1ptPr, trk1NSigmaPrTOF); histos.fill(HIST("QA/QAafter/Proton/TOF_TPC_Map_pr_all"), trk1NSigmaPrTOF, trk1NSigmaPrTPC); @@ -723,7 +707,7 @@ struct Lstaranalysis { // --- PID QA Kaon histos.fill(HIST("QA/QAafter/Kaon/TPC_Nsigma_ka_all"), multiplicity, trk2ptKa, trk2NSigmaKaTPC); - histos.fill(HIST("QA/QAafter/Kaon/TPC_Signal_ka_all"), trk2ptKa, trk2.tpcSignal()); + histos.fill(HIST("QA/QAafter/Kaon/TPC_Signal_ka_all"), trk2.tpcInnerParam(), trk2.tpcSignal()); if (isTrk2hasTOF) { histos.fill(HIST("QA/QAafter/Kaon/TOF_Nsigma_ka_all"), multiplicity, trk2ptKa, trk2NSigmaKaTOF); histos.fill(HIST("QA/QAafter/Kaon/TOF_TPC_Map_ka_all"), trk2NSigmaKaTOF, trk2NSigmaKaTPC); @@ -965,7 +949,7 @@ struct Lstaranalysis { void processMCTrue(MCEventCandidates::iterator const& collision, aod::McCollisions const&, aod::McParticles const& mcParticles) { - bool IsInAfterAllCuts = colCuts.isSelected(collision); + bool isInAfterAllCuts = colCuts.isSelected(collision); bool inVtx10 = (std::abs(collision.mcCollision().posZ()) > 10.) ? false : true; bool isTriggerTVX = collision.selection_bit(aod::evsel::kIsTriggerTVX); bool isSel8 = collision.sel8(); @@ -989,8 +973,8 @@ struct Lstaranalysis { daughterPDGs = {-1, -1}; } - bool pass1 = std::abs(daughterPDGs[0]) == 321 || std::abs(daughterPDGs[1]) == 321; // At least one decay to Kaon - bool pass2 = std::abs(daughterPDGs[0]) == 2212 || std::abs(daughterPDGs[1]) == 2212; // At least one decay to Proton + bool pass1 = std::abs(daughterPDGs[0]) == kKPlus || std::abs(daughterPDGs[1]) == kKPlus; // At least one decay to Kaon + bool pass2 = std::abs(daughterPDGs[0]) == kProton || std::abs(daughterPDGs[1]) == kProton; // At least one decay to Proton // Checking if we have both decay products if (!pass1 || !pass2) @@ -1040,7 +1024,7 @@ struct Lstaranalysis { else histos.fill(HIST("Result/MC/Genantilambda1520pt"), 3, part.pt(), multiplicity); } - if (IsInAfterAllCuts) // after all event selection + if (isInAfterAllCuts) // after all event selection { if (part.pdgCode() > 0) histos.fill(HIST("Result/MC/Genlambda1520pt"), 4, part.pt(), multiplicity); From a00927f2eae9832e5253d66b557b471c49d9e43d Mon Sep 17 00:00:00 2001 From: hernasab Date: Wed, 25 Jun 2025 01:32:50 -0500 Subject: [PATCH 206/871] [PWGCF] changed histo name (#11757) Co-authored-by: Sabrina Hernandez --- PWGCF/Flow/Tasks/flowZdcTask.cxx | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/PWGCF/Flow/Tasks/flowZdcTask.cxx b/PWGCF/Flow/Tasks/flowZdcTask.cxx index 341b93aaa12..94ff1549a40 100644 --- a/PWGCF/Flow/Tasks/flowZdcTask.cxx +++ b/PWGCF/Flow/Tasks/flowZdcTask.cxx @@ -216,6 +216,8 @@ struct FlowZdcTask { histos.add("ZposVsEta", "", kTProfile, {axisZpos}); histos.add("sigma1Pt", ";;#sigma(p_{T})/p_{T};", kTProfile, {axisPt}); histos.add("dcaXYvspT", ";DCA_{xy} (cm);;", kTH2F, {{{50, -1., 1.}, {axisPt}}}); + histos.add("GlobalMult_vs_FT0C", "GlobalMult_vs_FT0C", kTH2F, {axisMult, axisFT0CMult}); + histos.add("VtxZHist", "VtxZHist", kTH1D, {axisVtxZ}); // event selection steps histos.add("eventSelectionSteps", "eventSelectionSteps", kTH1D, {axisEvent}); @@ -239,9 +241,6 @@ struct FlowZdcTask { xAxis->SetBinLabel(16, "Within TDC cut?"); xAxis->SetBinLabel(17, "Within ZEM cut?"); - histos.add("GlobalMult_vs_FT0C", "GlobalMult_vs_FT0C", kTH2F, {axisMult, axisFT0CMult}); - histos.add("VtxZHist", "VtxZHist", kTH1D, {axisVtxZ}); - if (doprocessZdcCollAssoc) { // Check if the process function for ZDCCollAssoc is enabled histos.add("ZNAcoll", "ZNAcoll; ZNA amplitude; Entries", {HistType::kTH1F, {{nBinsAmp, -0.5, maxZn}}}); histos.add("ZNCcoll", "ZNCcoll; ZNC amplitude; Entries", {HistType::kTH1F, {{nBinsAmp, -0.5, maxZn}}}); @@ -295,7 +294,7 @@ struct FlowZdcTask { histos.add("ZEM2Vstdc", ";t_{ZEM2};ZEM2;", kTH2F, {{{30, -15., 15.}, {30, -0.5, 2000.5}}}); histos.add("debunch", ";t_{ZDC}-t_{ZDA};t_{ZDC}+t_{ZDA}", kTH2F, {{{nBinsTDC, minTdc, maxTdc}, {nBinsTDC, minTdc, maxTdc}}}); - histos.add("Nch", "Nch", kTH1F, {{nBinsNch, minNch, maxNch}}); + histos.add("GlbTracks", "Nch", kTH1F, {{nBinsNch, minNch, maxNch}}); 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., 3000.}, {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}}}); @@ -541,7 +540,7 @@ struct FlowZdcTask { histos.fill(HIST("ZPCcvsZPCsum"), sumZPC / cfgCollisionEnergy, zdc.energyCommonZPC() / cfgCollisionEnergy); histos.fill(HIST("ZPAcvsZPAsum"), sumZPA / cfgCollisionEnergy, zdc.energyCommonZPA() / cfgCollisionEnergy); - histos.fill(HIST("Nch"), glbTracks); + histos.fill(HIST("GlbTracks"), glbTracks); histos.fill(HIST("ZNA"), znA); histos.fill(HIST("ZNC"), znC); histos.fill(HIST("ZPA"), zpA); @@ -614,7 +613,6 @@ struct FlowZdcTask { } } const double normT0M{(ft0aAmp + ft0aAmp) / 100.}; - histos.fill(HIST("hFT0MAmp"), normT0M); const auto& zdcread = foundBC.zdc(); const auto cent = collision.centFT0C(); @@ -708,8 +706,6 @@ struct FlowZdcTask { if (!skipEvent) { return; } - std::vector pTs; - std::vector vecFD; std::vector vecOneOverEff; auto efficiency = ccdb->getForTimeStamp(paTHEff.value, foundBC.timestamp()); if (!efficiency) { From 148b531b703890b98c587870eb70e567cb119561 Mon Sep 17 00:00:00 2001 From: Paola Vargas Torres <88360333+PaolaVT@users.noreply.github.com> Date: Wed, 25 Jun 2025 02:02:49 -0600 Subject: [PATCH 207/871] [PWGLF] Sixteen plots and a new cut were added (#11758) --- PWGMM/UE/Tasks/dedxAnalysis.cxx | 129 +++++++++++++++++++++++++++++++- 1 file changed, 128 insertions(+), 1 deletion(-) diff --git a/PWGMM/UE/Tasks/dedxAnalysis.cxx b/PWGMM/UE/Tasks/dedxAnalysis.cxx index 21a90b0dd50..af5cfcefd8a 100644 --- a/PWGMM/UE/Tasks/dedxAnalysis.cxx +++ b/PWGMM/UE/Tasks/dedxAnalysis.cxx @@ -64,6 +64,7 @@ struct DedxAnalysis { float invMassCutGamma = 0.0015; float magField = 1; float pTcut = 2.0; + float nclCut = 120.0; // Configurable Parameters // Tracks cuts @@ -99,11 +100,15 @@ struct DedxAnalysis { "Minimum Mass Gamma"}; Configurable maxMassGamma{"maxMassGamma", 0.002022f, "Maximum Mass Gamma"}; - Configurable calibrationMode{"calibrationMode", true, "calibration mode"}; + Configurable calibrationMode{"calibrationMode", false, "calibration mode"}; Configurable additionalCuts{"additionalCuts", true, "additional cuts"}; // Histograms names static constexpr std::string_view kDedxvsMomentumPos[kParticlesType] = {"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 kDedxvsMomentumNeg[kParticlesType] = {"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 kNclDedxMomentumNegBefore[kEtaIntervals] = {"Ncl_vs_dEdx_vs_Momentum_Neg_1_Before", "Ncl_vs_dEdx_vs_Momentum_Neg_2_Before", "Ncl_vs_dEdx_vs_Momentum_Neg_3_Before", "Ncl_vs_dEdx_vs_Momentum_Neg_4_Before", "Ncl_vs_dEdx_vs_Momentum_Neg_5_Before", "Ncl_vs_dEdx_vs_Momentum_Neg_6_Before", "Ncl_vs_dEdx_vs_Momentum_Neg_7_Before", "Ncl_vs_dEdx_vs_Momentum_Neg_8_Before"}; + static constexpr std::string_view kNclDedxMomentumPosBefore[kEtaIntervals] = {"Ncl_vs_dEdx_vs_Momentum_Pos_1_Before", "Ncl_vs_dEdx_vs_Momentum_Pos_2_Before", "Ncl_vs_dEdx_vs_Momentum_Pos_3_Before", "Ncl_vs_dEdx_vs_Momentum_Pos_4_Before", "Ncl_vs_dEdx_vs_Momentum_Pos_5_Before", "Ncl_vs_dEdx_vs_Momentum_Pos_6_Before", "Ncl_vs_dEdx_vs_Momentum_Pos_7_Before", "Ncl_vs_dEdx_vs_Momentum_Pos_8_Before"}; + static constexpr std::string_view kNclDedxMomentumNegAfter[kEtaIntervals] = {"Ncl_vs_dEdx_vs_Momentum_Neg_1_After", "Ncl_vs_dEdx_vs_Momentum_Neg_2_After", "Ncl_vs_dEdx_vs_Momentum_Neg_3_After", "Ncl_vs_dEdx_vs_Momentum_Neg_4_After", "Ncl_vs_dEdx_vs_Momentum_Neg_5_After", "Ncl_vs_dEdx_vs_Momentum_Neg_6_After", "Ncl_vs_dEdx_vs_Momentum_Neg_7_After", "Ncl_vs_dEdx_vs_Momentum_Neg_8_After"}; + static constexpr std::string_view kNclDedxMomentumPosAfter[kEtaIntervals] = {"Ncl_vs_dEdx_vs_Momentum_Pos_1_After", "Ncl_vs_dEdx_vs_Momentum_Pos_2_After", "Ncl_vs_dEdx_vs_Momentum_Pos_3_After", "Ncl_vs_dEdx_vs_Momentum_Pos_4_After", "Ncl_vs_dEdx_vs_Momentum_Pos_5_After", "Ncl_vs_dEdx_vs_Momentum_Pos_6_After", "Ncl_vs_dEdx_vs_Momentum_Pos_7_After", "Ncl_vs_dEdx_vs_Momentum_Pos_8_After"}; static constexpr double EtaCut[kEtaIntervals + 1] = {-0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8}; Configurable> calibrationFactorNeg{"calibrationFactorNeg", {50.4011, 50.4764, 50.186, 49.2955, 48.8222, 49.4273, 49.9292, 50.0556}, "negative calibration factors"}; Configurable> calibrationFactorPos{"calibrationFactorPos", {50.5157, 50.6359, 50.3198, 49.3345, 48.9197, 49.4931, 50.0188, 50.1406}, "positive calibration factors"}; @@ -223,6 +228,20 @@ struct DedxAnalysis { "hpt_vs_phi_Ncl_Before", "phi cut", HistType::kTH3F, {{ptAxis}, {100, 0.0, 0.4, "#varphi^{'}"}, {100, 0, 160, "N_{cl}"}}); + // Ncl vs de/dx + + for (int i = 0; i < kEtaIntervals; ++i) { + registryDeDx.add(kNclDedxMomentumPosBefore[i].data(), "Ncl vs dE/dx vs Momentum Positive before", HistType::kTH3F, + {{100, 0, 160, "N_{cl}"}, {dedxAxis}, {pAxis}}); + registryDeDx.add(kNclDedxMomentumNegBefore[i].data(), "Ncl vs dE/dx vs Momentum Negative before", HistType::kTH3F, + {{100, 0, 160, "N_{cl}"}, {dedxAxis}, {pAxis}}); + + registryDeDx.add(kNclDedxMomentumPosAfter[i].data(), "Ncl vs dE/dx vs Momentum Positive after", HistType::kTH3F, + {{100, 0, 160, "N_{cl}"}, {dedxAxis}, {pAxis}}); + registryDeDx.add(kNclDedxMomentumNegAfter[i].data(), "Ncl vs dE/dx vs Momentum Negative after", HistType::kTH3F, + {{100, 0, 160, "N_{cl}"}, {dedxAxis}, {pAxis}}); + } + // beta plot registryDeDx.add( "hbeta_vs_p_Neg", "beta", HistType::kTH2F, @@ -405,7 +424,9 @@ struct DedxAnalysis { float pt = trk.pt(); float phi = trk.phi(); int charge = trk.sign(); + float eta = trk.eta(); auto nTPCCl = trk.tpcNClsFindable() - trk.tpcNClsFindableMinusFound(); + float sigP = trk.sign() * trk.tpcInnerParam(); if (pt < pTcut) return true; @@ -421,10 +442,116 @@ struct DedxAnalysis { registryDeDx.fill(HIST("hpt_vs_phi_Ncl_Before"), pt, phi, nTPCCl); + // cut phi if (phi < fphiCutHigh.Eval(pt) && phi > fphiCutLow.Eval(pt)) return false; // reject track + if (eta > EtaCut[0] && eta < EtaCut[1]) { + if (sigP < 0) { + registryDeDx.fill(HIST(kNclDedxMomentumNegBefore[0]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); + } else { + registryDeDx.fill(HIST(kNclDedxMomentumPosBefore[0]), nTPCCl, trk.tpcSignal(), sigP); + } + } else if (eta > EtaCut[1] && eta < EtaCut[2]) { + if (sigP < 0) { + registryDeDx.fill(HIST(kNclDedxMomentumNegBefore[1]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); + } else { + registryDeDx.fill(HIST(kNclDedxMomentumPosBefore[1]), nTPCCl, trk.tpcSignal(), sigP); + } + } else if (eta > EtaCut[2] && eta < EtaCut[3]) { + if (sigP < 0) { + registryDeDx.fill(HIST(kNclDedxMomentumNegBefore[2]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); + } else { + registryDeDx.fill(HIST(kNclDedxMomentumPosBefore[2]), nTPCCl, trk.tpcSignal(), sigP); + } + } else if (eta > EtaCut[3] && eta < EtaCut[4]) { + if (sigP < 0) { + registryDeDx.fill(HIST(kNclDedxMomentumNegBefore[3]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); + } else { + registryDeDx.fill(HIST(kNclDedxMomentumPosBefore[3]), nTPCCl, trk.tpcSignal(), sigP); + } + } else if (eta > EtaCut[4] && eta < EtaCut[5]) { + if (sigP < 0) { + registryDeDx.fill(HIST(kNclDedxMomentumNegBefore[4]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); + } else { + registryDeDx.fill(HIST(kNclDedxMomentumPosBefore[4]), nTPCCl, trk.tpcSignal(), sigP); + } + } else if (eta > EtaCut[5] && eta < EtaCut[6]) { + if (sigP < 0) { + registryDeDx.fill(HIST(kNclDedxMomentumNegBefore[5]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); + } else { + registryDeDx.fill(HIST(kNclDedxMomentumPosBefore[5]), nTPCCl, trk.tpcSignal(), sigP); + } + } else if (eta > EtaCut[6] && eta < EtaCut[7]) { + if (sigP < 0) { + registryDeDx.fill(HIST(kNclDedxMomentumNegBefore[6]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); + } else { + registryDeDx.fill(HIST(kNclDedxMomentumPosBefore[6]), nTPCCl, trk.tpcSignal(), sigP); + } + } else if (eta > EtaCut[7] && eta < EtaCut[8]) { + if (sigP < 0) { + registryDeDx.fill(HIST(kNclDedxMomentumNegBefore[7]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); + } else { + registryDeDx.fill(HIST(kNclDedxMomentumPosBefore[7]), nTPCCl, trk.tpcSignal(), sigP); + } + } + + // cut Ncl + if (nTPCCl < nclCut) + return false; + registryDeDx.fill(HIST("hpt_vs_phi_Ncl_After"), pt, phi, nTPCCl); + + if (eta > EtaCut[0] && eta < EtaCut[1]) { + if (sigP < 0) { + registryDeDx.fill(HIST(kNclDedxMomentumNegAfter[0]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); + } else { + registryDeDx.fill(HIST(kNclDedxMomentumPosAfter[0]), nTPCCl, trk.tpcSignal(), sigP); + } + } else if (eta > EtaCut[1] && eta < EtaCut[2]) { + if (sigP < 0) { + registryDeDx.fill(HIST(kNclDedxMomentumNegAfter[1]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); + } else { + registryDeDx.fill(HIST(kNclDedxMomentumPosAfter[1]), nTPCCl, trk.tpcSignal(), sigP); + } + } else if (eta > EtaCut[2] && eta < EtaCut[3]) { + if (sigP < 0) { + registryDeDx.fill(HIST(kNclDedxMomentumNegAfter[2]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); + } else { + registryDeDx.fill(HIST(kNclDedxMomentumPosAfter[2]), nTPCCl, trk.tpcSignal(), sigP); + } + } else if (eta > EtaCut[3] && eta < EtaCut[4]) { + if (sigP < 0) { + registryDeDx.fill(HIST(kNclDedxMomentumNegAfter[3]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); + } else { + registryDeDx.fill(HIST(kNclDedxMomentumPosAfter[3]), nTPCCl, trk.tpcSignal(), sigP); + } + } else if (eta > EtaCut[4] && eta < EtaCut[5]) { + if (sigP < 0) { + registryDeDx.fill(HIST(kNclDedxMomentumNegAfter[4]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); + } else { + registryDeDx.fill(HIST(kNclDedxMomentumPosAfter[4]), nTPCCl, trk.tpcSignal(), sigP); + } + } else if (eta > EtaCut[5] && eta < EtaCut[6]) { + if (sigP < 0) { + registryDeDx.fill(HIST(kNclDedxMomentumNegAfter[5]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); + } else { + registryDeDx.fill(HIST(kNclDedxMomentumPosAfter[5]), nTPCCl, trk.tpcSignal(), sigP); + } + } else if (eta > EtaCut[6] && eta < EtaCut[7]) { + if (sigP < 0) { + registryDeDx.fill(HIST(kNclDedxMomentumNegAfter[6]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); + } else { + registryDeDx.fill(HIST(kNclDedxMomentumPosAfter[6]), nTPCCl, trk.tpcSignal(), sigP); + } + } else if (eta > EtaCut[7] && eta < EtaCut[8]) { + if (sigP < 0) { + registryDeDx.fill(HIST(kNclDedxMomentumNegAfter[7]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); + } else { + registryDeDx.fill(HIST(kNclDedxMomentumPosAfter[7]), nTPCCl, trk.tpcSignal(), sigP); + } + } + return true; } From c1e11ec943b477eba0eb3ac175e275929b9373f5 Mon Sep 17 00:00:00 2001 From: Zhenjun Xiong <108917659+zjxiongOvO@users.noreply.github.com> Date: Wed, 25 Jun 2025 10:26:26 +0200 Subject: [PATCH 208/871] [PWGDQ] Add variables related to global polarization (#11744) Co-authored-by: ALICE Action Bot --- PWGDQ/Core/CutsLibrary.cxx | 2 +- PWGDQ/Core/HistogramsLibrary.cxx | 23 +++++++++++++++++++++++ PWGDQ/Core/VarManager.cxx | 9 +++++++++ PWGDQ/Core/VarManager.h | 26 ++++++++++++++++++++++++++ PWGDQ/Tasks/tableReader_withAssoc.cxx | 27 +++++++++++++++++++++++++-- 5 files changed, 84 insertions(+), 3 deletions(-) diff --git a/PWGDQ/Core/CutsLibrary.cxx b/PWGDQ/Core/CutsLibrary.cxx index 1feb6d88b0d..ec017da8ac8 100644 --- a/PWGDQ/Core/CutsLibrary.cxx +++ b/PWGDQ/Core/CutsLibrary.cxx @@ -3827,9 +3827,9 @@ AnalysisCut* o2::aod::dqcuts::GetAnalysisCut(const char* cutName) cut->AddCut(VarManager::kIsGoodZvtxFT0vsPV, 0.5, 1.5); cut->AddCut(VarManager::kCentFT0C, 0.0, 90.0); cut->AddCut(VarManager::kTrackOccupancyInTimeRange, 0., 1000); - return cut; } + if (!nameStr.compare("eventStandardSel8PbPbQualityFirmTrackOccupancy")) { cut->AddCut(VarManager::kVtxZ, -10.0, 10.0); cut->AddCut(VarManager::kIsSel8, 0.5, 1.5); diff --git a/PWGDQ/Core/HistogramsLibrary.cxx b/PWGDQ/Core/HistogramsLibrary.cxx index 7ac7e6d2e66..4018486eff6 100644 --- a/PWGDQ/Core/HistogramsLibrary.cxx +++ b/PWGDQ/Core/HistogramsLibrary.cxx @@ -194,6 +194,18 @@ void o2::aod::dqhistograms::DefineHistograms(HistogramManager* hm, const char* h if (subGroupStr.Contains("occupancy")) { hm->AddHistogram(histClass, "ITStrackOccupancy", "ITStrackOccupancy", false, 200, 0.0, 20000.0, VarManager::kTrackOccupancyInTimeRange); hm->AddHistogram(histClass, "Ft0cOccupancy", "Ft0cOccupancy", false, 200, 0.0, 20000.0, VarManager::kFT0COccupancyInTimeRange); + if (subGroupStr.Contains("qvector")) { + hm->AddHistogram(histClass, "Psi2A_ITStrackOccupancy", "", false, 200, 0.0, 20000.0, VarManager::kTrackOccupancyInTimeRange, 100, -TMath::Pi() / 2, TMath::Pi() / 2, VarManager::kPsi2A); + hm->AddHistogram(histClass, "Psi2B_ITStrackOccupancy", "", true, 200, 0.0, 20000.0, VarManager::kTrackOccupancyInTimeRange, 100, -TMath::Pi() / 2, TMath::Pi() / 2, VarManager::kPsi2B); + hm->AddHistogram(histClass, "Psi2C_ITStrackOccupancy", "", true, 200, 0.0, 20000.0, VarManager::kTrackOccupancyInTimeRange, 100, -TMath::Pi() / 2, TMath::Pi() / 2, VarManager::kPsi2C); + hm->AddHistogram(histClass, "Psi2APOS_ITStrackOccupancy", "", true, 200, 0.0, 20000.0, VarManager::kTrackOccupancyInTimeRange, 100, -TMath::Pi() / 2, TMath::Pi() / 2, VarManager::kPsi2APOS); + hm->AddHistogram(histClass, "Psi2ANEG_ITStrackOccupancy", "", true, 200, 0.0, 20000.0, VarManager::kTrackOccupancyInTimeRange, 100, -TMath::Pi() / 2, TMath::Pi() / 2, VarManager::kPsi2ANEG); + hm->AddHistogram(histClass, "Psi2A_Ft0cOccupancy", "", false, 200, 0.0, 20000.0, VarManager::kFT0COccupancyInTimeRange, 100, -TMath::Pi() / 2, TMath::Pi() / 2, VarManager::kPsi2A); + hm->AddHistogram(histClass, "Psi2B_Ft0cOccupancy", "", true, 200, 0.0, 20000.0, VarManager::kFT0COccupancyInTimeRange, 100, -TMath::Pi() / 2, TMath::Pi() / 2, VarManager::kPsi2B); + hm->AddHistogram(histClass, "Psi2C_Ft0cOccupancy", "", true, 200, 0.0, 20000.0, VarManager::kFT0COccupancyInTimeRange, 100, -TMath::Pi() / 2, TMath::Pi() / 2, VarManager::kPsi2C); + hm->AddHistogram(histClass, "Psi2APOS_Ft0cOccupancy", "", true, 200, 0.0, 20000.0, VarManager::kFT0COccupancyInTimeRange, 100, -TMath::Pi() / 2, TMath::Pi() / 2, VarManager::kPsi2APOS); + hm->AddHistogram(histClass, "Psi2ANEG_Ft0cOccupancy", "", true, 200, 0.0, 20000.0, VarManager::kFT0COccupancyInTimeRange, 100, -TMath::Pi() / 2, TMath::Pi() / 2, VarManager::kPsi2ANEG); + } } if (subGroupStr.Contains("mc")) { hm->AddHistogram(histClass, "MCVtxX_VtxX", "Vtx X (MC vs rec)", false, 100, -0.5, 0.5, VarManager::kVtxX, 100, -0.5, 0.5, VarManager::kMCVtxX); @@ -242,6 +254,10 @@ void o2::aod::dqhistograms::DefineHistograms(HistogramManager* hm, const char* h hm->AddHistogram(histClass, "Q2X0A", "", false, 500, -10.0, 10.0, VarManager::kQ2X0A); hm->AddHistogram(histClass, "Q2Y0A", "", false, 500, -10.0, 10.0, VarManager::kQ2Y0A); + hm->AddHistogram(histClass, "Q2X0APOS", "", false, 500, -10.0, 10.0, VarManager::kQ2X0APOS); + hm->AddHistogram(histClass, "Q2Y0APOS", "", false, 500, -10.0, 10.0, VarManager::kQ2Y0APOS); + hm->AddHistogram(histClass, "Q2X0ANEG", "", false, 500, -10.0, 10.0, VarManager::kQ2X0ANEG); + hm->AddHistogram(histClass, "Q2Y0ANEG", "", false, 500, -10.0, 10.0, VarManager::kQ2Y0ANEG); hm->AddHistogram(histClass, "Q2X0B", "", false, 500, -10.0, 10.0, VarManager::kQ2X0B); hm->AddHistogram(histClass, "Q2Y0B", "", false, 500, -10.0, 10.0, VarManager::kQ2Y0B); hm->AddHistogram(histClass, "Q2X0C", "", false, 500, -10.0, 10.0, VarManager::kQ2X0C); @@ -285,6 +301,8 @@ void o2::aod::dqhistograms::DefineHistograms(HistogramManager* hm, const char* h hm->AddHistogram(histClass, "Q3X0A_CentFT0C", "", false, 18, 0.0, 90.0, VarManager::kCentFT0C, 500, -10.0, 10.0, VarManager::kQ3X0A); hm->AddHistogram(histClass, "Q3Y0A_CentFT0C", "", false, 18, 0.0, 90.0, VarManager::kCentFT0C, 500, -10.0, 10.0, VarManager::kQ3Y0A); hm->AddHistogram(histClass, "Psi2A", "", false, 100, -2.0, 2.0, VarManager::kPsi2A); + hm->AddHistogram(histClass, "Psi2APOS", "", false, 100, -2.0, 2.0, VarManager::kPsi2APOS); + hm->AddHistogram(histClass, "Psi2ANEG", "", false, 100, -2.0, 2.0, VarManager::kPsi2ANEG); hm->AddHistogram(histClass, "Psi2B", "", false, 100, -2.0, 2.0, VarManager::kPsi2B); hm->AddHistogram(histClass, "Psi2C", "", false, 100, -2.0, 2.0, VarManager::kPsi2C); hm->AddHistogram(histClass, "Psi2A_CentFT0C", "", false, 90, 0.0, 90.0, VarManager::kCentFT0C, 100, -2.0, 2.0, VarManager::kPsi2A); @@ -1018,6 +1036,11 @@ void o2::aod::dqhistograms::DefineHistograms(HistogramManager* hm, const char* h hm->AddHistogram(histClass, "Mass_Pt_CosThetaRM", "", false, 200, 1.0, 5.0, VarManager::kMass, 40, 0.0, 20.0, VarManager::kPt, 20, -1., 1., VarManager::kCosThetaRM); } } + if (subGroupStr.Contains("globalpolarization")) { + hm->AddHistogram(histClass, "CosThetaStarTPC", "", false, 100, -1.0, 1.0, VarManager::kCosThetaStarTPC); + hm->AddHistogram(histClass, "CosThetaStarFT0A", "", false, 100, -1.0, 1.0, VarManager::kCosThetaStarFT0A); + hm->AddHistogram(histClass, "CosThetaStarFT0C", "", false, 100, -1.0, 1.0, VarManager::kCosThetaStarFT0C); + } if (subGroupStr.Contains("upsilon")) { hm->AddHistogram(histClass, "MassUpsilon_Pt", "", false, 500, 7.0, 12.0, VarManager::kMass, 400, 0.0, 40.0, VarManager::kPt); } diff --git a/PWGDQ/Core/VarManager.cxx b/PWGDQ/Core/VarManager.cxx index a113f0571d3..00e07e5a38a 100644 --- a/PWGDQ/Core/VarManager.cxx +++ b/PWGDQ/Core/VarManager.cxx @@ -967,6 +967,12 @@ void VarManager::SetDefaultVarNames() fgVariableUnits[kPhiTildePP] = "rad."; fgVariableNames[kCosThetaRM] = "cos#it{#theta}_{RM}"; fgVariableUnits[kCosThetaRM] = ""; + fgVariableNames[kCosThetaStarTPC] = "cos#it{#theta}^{*}_{TPC}"; + fgVariableUnits[kCosThetaStarTPC] = ""; + fgVariableNames[kCosThetaStarFT0A] = "cos#it{#theta}^{*}_{FT0A}"; + fgVariableUnits[kCosThetaStarFT0A] = ""; + fgVariableNames[kCosThetaStarFT0C] = "cos#it{#theta}^{*}_{FT0C}"; + fgVariableUnits[kCosThetaStarFT0C] = ""; fgVariableNames[kCosPhiVP] = "cos#it{#varphi}_{VP}"; fgVariableUnits[kCosPhiVP] = ""; fgVariableNames[kPhiVP] = "#varphi_{VP} - #Psi_{2}"; @@ -1532,6 +1538,9 @@ void VarManager::SetDefaultVarNames() fgVarNamesMap["kPhiPP"] = kPhiPP; fgVarNamesMap["kPhiTildePP"] = kPhiTildePP; fgVarNamesMap["kCosThetaRM"] = kCosThetaRM; + fgVarNamesMap["kCosThetaStarTPC"] = kCosThetaStarTPC; + fgVarNamesMap["kCosThetaStarFT0A"] = kCosThetaStarFT0A; + fgVarNamesMap["kCosThetaStarFT0C"] = kCosThetaStarFT0C; fgVarNamesMap["kCosPhiVP"] = kCosPhiVP; fgVarNamesMap["kPhiVP"] = kPhiVP; fgVarNamesMap["kDeltaPhiPair2"] = kDeltaPhiPair2; diff --git a/PWGDQ/Core/VarManager.h b/PWGDQ/Core/VarManager.h index 83b8df8906f..f0537a41d66 100644 --- a/PWGDQ/Core/VarManager.h +++ b/PWGDQ/Core/VarManager.h @@ -670,6 +670,9 @@ class VarManager : public TObject kPhiPP, kPhiTildePP, kCosThetaRM, + kCosThetaStarTPC, + kCosThetaStarFT0A, + kCosThetaStarFT0C, kCosPhiVP, kPhiVP, kDeltaPhiPair2, @@ -4842,6 +4845,29 @@ void VarManager::FillPairVn(T1 const& t1, T2 const& t2, float* values) values[kR3EP] = -999.; } + // global polarization parameters + bool useGlobalPolarizatiobSpinOne = fgUsedVars[kCosThetaStarTPC] || fgUsedVars[kCosThetaStarFT0A] || fgUsedVars[kCosThetaStarFT0C]; + if (useGlobalPolarizatiobSpinOne) { + double BeamMomentum = TMath::Sqrt(fgCenterOfMassEnergy * fgCenterOfMassEnergy / 4 - fgMassofCollidingParticle * fgMassofCollidingParticle); // GeV + ROOT::Math::PxPyPzEVector Beam1(0., 0., -BeamMomentum, fgCenterOfMassEnergy / 2); + + ROOT::Math::Boost boostv12{v12.BoostToCM()}; + ROOT::Math::XYZVectorF v1_CM{(boostv12(v1).Vect()).Unit()}; + ROOT::Math::XYZVectorF v2_CM{(boostv12(v2).Vect()).Unit()}; + + // using positive sign convention for the first track + ROOT::Math::XYZVectorF v_CM = (t1.sign() > 0 ? v1_CM : v2_CM); + + ROOT::Math::XYZVector zaxisTPC = ROOT::Math::XYZVector(TMath::Cos(Psi2A), TMath::Sin(Psi2A), 0).Unit(); + values[kCosThetaStarTPC] = v_CM.Dot(zaxisTPC); + + ROOT::Math::XYZVector zaxisFT0A = ROOT::Math::XYZVector(TMath::Cos(Psi2B), TMath::Sin(Psi2B), 0).Unit(); + values[kCosThetaStarFT0A] = v_CM.Dot(zaxisFT0A); + + ROOT::Math::XYZVector zaxisFT0C = ROOT::Math::XYZVector(TMath::Cos(Psi2C), TMath::Sin(Psi2C), 0).Unit(); + values[kCosThetaStarFT0C] = v_CM.Dot(zaxisFT0C); + } + // kV4, kC4POI, kC4REF etc. if constexpr ((fillMap & ReducedEventQvectorExtra) > 0) { complex Q21(values[kQ2X0A] * values[kS11A], values[kQ2Y0A] * values[kS11A]); diff --git a/PWGDQ/Tasks/tableReader_withAssoc.cxx b/PWGDQ/Tasks/tableReader_withAssoc.cxx index af6ea738a60..ebb21398062 100644 --- a/PWGDQ/Tasks/tableReader_withAssoc.cxx +++ b/PWGDQ/Tasks/tableReader_withAssoc.cxx @@ -182,6 +182,8 @@ using MyEventsVtxCovZdcSelected = soa::Join; using MyEventsQvector = soa::Join; using MyEventsHashSelectedQvector = soa::Join; +using MyEventsQvectorCentr = soa::Join; +using MyEventsQvectorCentrSelected = soa::Join; using MyBarrelTracks = soa::Join; using MyBarrelTracksWithAmbiguities = soa::Join; @@ -204,6 +206,7 @@ constexpr static uint32_t gkEventFillMapWithCovZdc = VarManager::ObjTypes::Reduc constexpr static uint32_t gkEventFillMapWithMultExtra = VarManager::ObjTypes::ReducedEvent | VarManager::ObjTypes::ReducedEventExtended | VarManager::ObjTypes::ReducedEventMultExtra; constexpr static uint32_t gkEventFillMapWithMultExtraZdc = VarManager::ObjTypes::ReducedEvent | VarManager::ObjTypes::ReducedEventExtended | VarManager::ObjTypes::ReducedEventMultExtra | VarManager::ReducedZdc; constexpr static uint32_t gkEventFillMapWithCovZdcMultExtra = VarManager::ObjTypes::ReducedEvent | VarManager::ObjTypes::ReducedEventExtended | VarManager::ObjTypes::ReducedEventVtxCov | VarManager::ReducedZdc | VarManager::ReducedEventMultExtra; +constexpr static uint32_t gkEventFillMapWithQvectorCentr = VarManager::ObjTypes::ReducedEvent | VarManager::ObjTypes::ReducedEventExtended | VarManager::ObjTypes::CollisionQvect | VarManager::ObjTypes::ReducedEventMultExtra; // constexpr static uint32_t gkEventFillMapWithQvector = VarManager::ObjTypes::ReducedEvent | VarManager::ObjTypes::ReducedEventExtended | VarManager::ObjTypes::ReducedEventQvector; // constexpr static uint32_t gkEventFillMapWithCovQvector = VarManager::ObjTypes::ReducedEvent | VarManager::ObjTypes::ReducedEventExtended | VarManager::ObjTypes::ReducedEventVtxCov | VarManager::ObjTypes::ReducedEventQvector; constexpr static uint32_t gkTrackFillMap = VarManager::ObjTypes::ReducedTrack | VarManager::ObjTypes::ReducedTrackBarrel | VarManager::ObjTypes::ReducedTrackBarrelPID; @@ -270,7 +273,7 @@ struct AnalysisEventSelection { { LOG(info) << "Starting initialization of AnalysisEventSelection (idstoreh)"; - bool isAnyProcessEnabled = context.mOptions.get("processSkimmed") || context.mOptions.get("processSkimmedWithZdc") || context.mOptions.get("processSkimmedWithMultExtra") || context.mOptions.get("processSkimmedWithMultExtraZdc"); + bool isAnyProcessEnabled = context.mOptions.get("processSkimmed") || context.mOptions.get("processSkimmedWithZdc") || context.mOptions.get("processSkimmedWithMultExtra") || context.mOptions.get("processSkimmedWithMultExtraZdc") || context.mOptions.get("processSkimmedWithQvectorCentr"); bool isDummyEnabled = context.mOptions.get("processDummy"); if (isDummyEnabled) { @@ -507,6 +510,11 @@ struct AnalysisEventSelection { runEventSelection(events); publishSelections(events); } + void processSkimmedWithQvectorCentr(MyEventsQvectorCentr const& events) + { + runEventSelection(events); + publishSelections(events); + } void processDummy(MyEvents&) { // do nothing @@ -516,6 +524,7 @@ struct AnalysisEventSelection { 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, processSkimmedWithMultExtraZdc, "Run event selection on DQ skimmed events, with mult extra and ZDC", false); + PROCESS_SWITCH(AnalysisEventSelection, processSkimmedWithQvectorCentr, "Run event selection on DQ skimmed events, with Q-vector", false); PROCESS_SWITCH(AnalysisEventSelection, processDummy, "Dummy function", false); }; @@ -1258,7 +1267,7 @@ struct AnalysisSameEventPairing { void init(o2::framework::InitContext& context) { LOG(info) << "Starting initialization of AnalysisSameEventPairing (idstoreh)"; - fEnableBarrelHistos = context.mOptions.get("processAllSkimmed") || context.mOptions.get("processBarrelOnlySkimmed") || context.mOptions.get("processBarrelOnlyWithCollSkimmed") || context.mOptions.get("processBarrelOnlySkimmedNoCov") || context.mOptions.get("processBarrelOnlySkimmedNoCovWithMultExtra"); + 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"); fEnableMuonHistos = context.mOptions.get("processAllSkimmed") || context.mOptions.get("processMuonOnlySkimmed") || context.mOptions.get("processMuonOnlySkimmedMultExtra") || context.mOptions.get("processMixingMuonSkimmed"); fEnableMuonMixingHistos = context.mOptions.get("processMixingAllSkimmed") || context.mOptions.get("processMixingMuonSkimmed"); @@ -1654,6 +1663,9 @@ struct AnalysisSameEventPairing { if constexpr (eventHasQvector) { VarManager::FillPairVn(t1, t2); } + if constexpr (eventHasQvectorCentr) { + VarManager::FillPairVn(t1, t2); + } dielectronList(event.globalIndex(), VarManager::fgValues[VarManager::kMass], VarManager::fgValues[VarManager::kPt], VarManager::fgValues[VarManager::kEta], VarManager::fgValues[VarManager::kPhi], @@ -1719,6 +1731,9 @@ struct AnalysisSameEventPairing { if constexpr (eventHasQvector) { VarManager::FillPairVn(t1, t2); } + if constexpr (eventHasQvectorCentr) { + VarManager::FillPairVn(t1, t2); + } dimuonList(event.globalIndex(), VarManager::fgValues[VarManager::kMass], VarManager::fgValues[VarManager::kPt], VarManager::fgValues[VarManager::kEta], VarManager::fgValues[VarManager::kPhi], @@ -2101,6 +2116,13 @@ struct AnalysisSameEventPairing { runSameEventPairing(events, trackAssocsPerCollision, barrelAssocs, barrelTracks); } + void processBarrelOnlyWithQvectorCentrSkimmedNoCov(MyEventsQvectorCentrSelected const& events, + soa::Join const& barrelAssocs, + MyBarrelTracksWithAmbiguities const& barrelTracks) + { + runSameEventPairing(events, trackAssocsPerCollision, barrelAssocs, barrelTracks); + } + void processMuonOnlySkimmed(MyEventsVtxCovSelected const& events, soa::Join const& muonAssocs, MyMuonTracksWithCovWithAmbiguities const& muons) { @@ -2143,6 +2165,7 @@ struct AnalysisSameEventPairing { PROCESS_SWITCH(AnalysisSameEventPairing, processBarrelOnlyWithCollSkimmed, "Run barrel only pairing, with skimmed tracks and with collision information", false); PROCESS_SWITCH(AnalysisSameEventPairing, processBarrelOnlySkimmedNoCov, "Run barrel only pairing (no covariances), with skimmed tracks and with collision information", false); PROCESS_SWITCH(AnalysisSameEventPairing, processBarrelOnlySkimmedNoCovWithMultExtra, "Run barrel only pairing (no covariances), with skimmed tracks, with collision information, with MultsExtra", false); + PROCESS_SWITCH(AnalysisSameEventPairing, processBarrelOnlyWithQvectorCentrSkimmedNoCov, "Run barrel only pairing (no covariances), with skimmed tracks, with Qvector from central framework", false); PROCESS_SWITCH(AnalysisSameEventPairing, processMuonOnlySkimmed, "Run muon only pairing, with skimmed tracks", false); PROCESS_SWITCH(AnalysisSameEventPairing, processMuonOnlySkimmedMultExtra, "Run muon only pairing, with skimmed tracks", false); PROCESS_SWITCH(AnalysisSameEventPairing, processMixingAllSkimmed, "Run all types of mixed pairing, with skimmed tracks/muons", false); From 055c2ece3454507a528116613e3d210189ba7a2a Mon Sep 17 00:00:00 2001 From: Roberta Ferioli <142217183+Roberta-Ferioli@users.noreply.github.com> Date: Wed, 25 Jun 2025 11:46:43 +0200 Subject: [PATCH 209/871] [PWGLF] Evaluate efficiency only for primaries (#11761) --- .../Tasks/Nuspex/nucleiFromHypertritonMap.cxx | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/PWGLF/Tasks/Nuspex/nucleiFromHypertritonMap.cxx b/PWGLF/Tasks/Nuspex/nucleiFromHypertritonMap.cxx index dc4e70c2ee3..2d959f9488d 100644 --- a/PWGLF/Tasks/Nuspex/nucleiFromHypertritonMap.cxx +++ b/PWGLF/Tasks/Nuspex/nucleiFromHypertritonMap.cxx @@ -79,17 +79,17 @@ struct nucleiFromHypertritonMap { void init(InitContext const&) { - registryMC.add("hypertritonPtgen", "hypertritonPtGen", HistType::kTH1F, {{nbin_pt, min_pt, max_pt, "p_{T} (GeV/c)"}}); + registryMC.add("hypertritonPtGen", "hypertritonPtGen", HistType::kTH1F, {{nbin_pt, min_pt, max_pt, "p_{T} (GeV/c)"}}); if (saveHelium) { registryMC.add("he3SecPtRec_from_hypertriton", "he3SecPtRec_from_hypertriton", HistType::kTH1F, {{nbin_pt, min_pt, max_pt, "p_{T} (GeV/c)"}}); - registryMC.add("hyperHe4Ptgen", "hyperHe4PtGen", HistType::kTH1F, {{nbin_pt, min_pt, max_pt, "p_{T} (GeV/c)"}}); + registryMC.add("hyperHe4PtGen", "hyperHe4PtGen", HistType::kTH1F, {{nbin_pt, min_pt, max_pt, "p_{T} (GeV/c)"}}); registryMC.add("he3SecPtRec_from_hyperHe4", "he3SecPtRec_from_hyperHe4", HistType::kTH1F, {{nbin_pt, min_pt, max_pt, "p_{T} (GeV/c)"}}); registryMC.add("he3PtRec", "he3PtRec", HistType::kTH1F, {{nbin_pt, min_pt, max_pt, "p_{T} (GeV/c)"}}); registryMC.add("he3PtGen", "he3PtGen", HistType::kTH1F, {{nbin_pt, min_pt, max_pt, "p_{T} (GeV/c)"}}); } else { registryMC.add("deutSecPtRec_from_hypertriton", "deutSecPtRec_from_hypertriton", HistType::kTH1F, {{nbin_pt, min_pt, max_pt, "p_{T} (GeV/c)"}}); registryMC.add("deutPtRec", "deutPtRec", HistType::kTH1F, {{nbin_pt, min_pt, max_pt, "p_{T} (GeV/c)"}}); - registryMC.add("deutPtgen", "deutPtGen", HistType::kTH1F, {{nbin_pt, min_pt, max_pt, "p_{T} (GeV/c)"}}); + registryMC.add("deutPtGen", "deutPtGen", HistType::kTH1F, {{nbin_pt, min_pt, max_pt, "p_{T} (GeV/c)"}}); } } @@ -107,21 +107,21 @@ struct nucleiFromHypertritonMap { if (mcparticle.pdgCode() == AntiHypertritonPDG) { for (auto& daughter : mcparticle.daughters_as()) { if (daughter.pdgCode() == selectedPDG) { - registryMC.fill(HIST("hypertritonPtgen"), mcparticle.pt()); + registryMC.fill(HIST("hypertritonPtGen"), mcparticle.pt()); } } } if (mcparticle.pdgCode() == AntiHyperHelium4PDG) { for (auto& daughter : mcparticle.daughters_as()) { if (daughter.pdgCode() == selectedPDG) { - registryMC.fill(HIST("hyperHe4Ptgen"), mcparticle.pt()); + registryMC.fill(HIST("hyperHe4PtGen"), mcparticle.pt()); } } } - if (mcparticle.pdgCode() == AntihePDG) { + if (mcparticle.pdgCode() == AntihePDG && mcparticle.isPhysicalPrimary()) { registryMC.fill(HIST("he3PtGen"), mcparticle.pt()); } - if (mcparticle.pdgCode() == AntideuteronPDG) { + if (mcparticle.pdgCode() == AntideuteronPDG && mcparticle.isPhysicalPrimary()) { registryMC.fill(HIST("deutPtGen"), mcparticle.pt()); } } @@ -148,10 +148,10 @@ struct nucleiFromHypertritonMap { track.itsChi2NCl() > 36.f) { continue; } - if (mcparticle.pdgCode() == AntideuteronPDG) { + if (mcparticle.pdgCode() == AntideuteronPDG && mcparticle.isPhysicalPrimary()) { registryMC.fill(HIST("deutPtRec"), track.pt()); } - if (mcparticle.pdgCode() == AntihePDG) { + if (mcparticle.pdgCode() == AntihePDG && mcparticle.isPhysicalPrimary()) { registryMC.fill(HIST("he3PtRec"), 2 * track.pt()); } From 5691e46c091b12f0651269f8aa6858d33cafe0f0 Mon Sep 17 00:00:00 2001 From: blacwovie Date: Wed, 25 Jun 2025 20:30:57 +0800 Subject: [PATCH 210/871] [PWGCF] fixing De mass in computing kstar and adding eta phi histo (#11759) Co-authored-by: ALICE Action Bot --- PWGCF/Femto/TableProducer/PiDeuteronFemto.cxx | 108 ++++++++++-------- 1 file changed, 61 insertions(+), 47 deletions(-) diff --git a/PWGCF/Femto/TableProducer/PiDeuteronFemto.cxx b/PWGCF/Femto/TableProducer/PiDeuteronFemto.cxx index 9acef964220..3bb1c43e499 100644 --- a/PWGCF/Femto/TableProducer/PiDeuteronFemto.cxx +++ b/PWGCF/Femto/TableProducer/PiDeuteronFemto.cxx @@ -15,30 +15,9 @@ /// \author CMY /// \date 2025-04-10 -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include // std::prev - -#include "Framework/ASoAHelpers.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/StepTHn.h" +#include "PWGCF/Femto/DataModel/PionDeuteronTables.h" +#include "PWGLF/DataModel/EPCalibrationTables.h" +#include "PWGLF/Utils/svPoolCreator.h" #include "Common/Core/PID/PIDTOF.h" #include "Common/Core/PID/TPCPIDResponse.h" @@ -52,21 +31,40 @@ #include "Common/DataModel/PIDResponseITS.h" #include "Common/DataModel/TrackSelectionTables.h" #include "Common/TableProducer/PID/pidTOFBase.h" - #include "EventFiltering/Zorro.h" #include "EventFiltering/ZorroSummary.h" #include "CCDB/BasicCCDBManager.h" -#include "DetectorsBase/Propagator.h" -#include "DetectorsBase/GeometryManager.h" -#include "DataFormatsTPC/BetheBlochAleph.h" -#include "DataFormatsParameters/GRPObject.h" #include "DataFormatsParameters/GRPMagField.h" +#include "DataFormatsParameters/GRPObject.h" +#include "DataFormatsTPC/BetheBlochAleph.h" +#include "DetectorsBase/GeometryManager.h" +#include "DetectorsBase/Propagator.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/StepTHn.h" +#include "Framework/runDataProcessing.h" #include "ReconstructionDataFormats/Track.h" -#include "PWGLF/DataModel/EPCalibrationTables.h" -#include "PWGCF/Femto/DataModel/PionDeuteronTables.h" -#include "PWGLF/Utils/svPoolCreator.h" +#include "Math/Boost.h" +#include "Math/Vector4D.h" +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include // std::prev +#include +#include using namespace o2; using namespace o2::framework; @@ -236,6 +234,10 @@ struct PiDeuteronFemto { {"hDePitInvMass", "; M(De + p) (GeV/#it{c}^{2})", {HistType::kTH1F, {{300, 3.74f, 4.34f}}}}, {"hDePt", "#it{p}_{T} distribution; #it{p}_{T} (GeV/#it{c})", {HistType::kTH1F, {{240, -6.0f, 6.0f}}}}, {"hPiPt", "Pt distribution; #it{p}_{T} (GeV/#it{c})", {HistType::kTH1F, {{120, -3.0f, 3.0f}}}}, + {"hDeEta", "eta distribution; #eta(De)", {HistType::kTH1F, {{200, -1.0f, 1.0f}}}}, + {"hPiEta", "eta distribution; #eta(#pi)", {HistType::kTH1F, {{200, -1.0f, 1.0f}}}}, + {"hDePhi", "phi distribution; phi(De)", {HistType::kTH1F, {{600, -4.0f, 4.0f}}}}, + {"hPiPhi", "phi distribution; phi(#pi)", {HistType::kTH1F, {{600, -4.0f, 4.0f}}}}, {"h2dEdxDecandidates", "dEdx distribution; #it{p} (GeV/#it{c}); dE/dx (a.u.)", {HistType::kTH2F, {{200, -5.0f, 5.0f}, {100, 0.0f, 2000.0f}}}}, {"h2NsigmaDeTPC", "NsigmaDe TPC distribution; #it{p}_{T} (GeV/#it{c}); n#sigma_{TPC}(De)", {HistType::kTH2F, {{20, -5.0f, 5.0f}, {200, -5.0f, 5.0f}}}}, {"h2NsigmaDeTPC_preselection", "NsigmaDe TPC distribution; #it{p}_{T} (GeV/#it{c}); n#sigma_{TPC}(De)", {HistType::kTH2F, {{100, -5.0f, 5.0f}, {400, -10.0f, 10.0f}}}}, @@ -250,6 +252,7 @@ struct PiDeuteronFemto { {"hkStar_LS_A", ";kStar (GeV/c)", {HistType::kTH1F, {{300, 0.0f, 3.0f}}}}, {"hkStar_US_M", ";kStar (GeV/c)", {HistType::kTH1F, {{300, 0.0f, 3.0f}}}}, {"hkStar_US_A", ";kStar (GeV/c)", {HistType::kTH1F, {{300, 0.0f, 3.0f}}}}, + {"hkStar_All", ";kStar (GeV/c)", {HistType::kTH1F, {{300, 0.0f, 3.0f}}}}, {"hisBkgEM", "; isBkgEM;", {HistType::kTH1F, {{3, -1, 2}}}}}, OutputObjHandlingPolicy::AnalysisObject, false, @@ -691,6 +694,10 @@ struct PiDeuteronFemto { { mQaRegistry.fill(HIST("hDePt"), piDecand.recoPtDe()); mQaRegistry.fill(HIST("hPiPt"), piDecand.recoPtPi()); + mQaRegistry.fill(HIST("hDeEta"), piDecand.recoEtaDe()); + mQaRegistry.fill(HIST("hPiEta"), piDecand.recoEtaPi()); + mQaRegistry.fill(HIST("hDePhi"), piDecand.recoPhiDe()); + mQaRegistry.fill(HIST("hPiPhi"), piDecand.recoPhiPi()); mQaRegistry.fill(HIST("hDePitInvMass"), piDecand.invMass); mQaRegistry.fill(HIST("hdcaxyDe"), piDecand.dcaxyDe); mQaRegistry.fill(HIST("hdcazDe"), piDecand.dcazDe); @@ -722,21 +729,27 @@ struct PiDeuteronFemto { double computeKstar(const PiDecandidate& piDecand) { - TLorentzVector he3, hadron; - float massHe3 = 2.80839; - float massHad = 0.1395704; - he3.SetPtEtaPhiM(abs(piDecand.recoPtDe()), piDecand.recoEtaDe(), piDecand.recoPhiDe(), massHe3); - hadron.SetPtEtaPhiM(abs(piDecand.recoPtPi()), piDecand.recoEtaPi(), piDecand.recoPhiPi(), massHad); - - TLorentzVector p_total_lab = he3 + hadron; - TVector3 v_cm = p_total_lab.BoostVector(); - TLorentzVector p1_cm = he3; - TLorentzVector p2_cm = hadron; - p1_cm.Boost(-v_cm); - p2_cm.Boost(-v_cm); - TLorentzVector p_diff_cm = p1_cm - p2_cm; - double kStar = sqrt(p_diff_cm.X() * p_diff_cm.X() + p_diff_cm.Y() * p_diff_cm.Y() + p_diff_cm.Z() * p_diff_cm.Z()); - return kStar / 2.0; + constexpr double massDe = o2::constants::physics::MassDeuteron; + constexpr double massHad = o2::constants::physics::MassPiPlus; + + const ROOT::Math::PtEtaPhiMVector De(std::abs(piDecand.recoPtDe()), piDecand.recoEtaDe(), piDecand.recoPhiDe(), massDe); + const ROOT::Math::PtEtaPhiMVector Had(std::abs(piDecand.recoPtPi()), piDecand.recoEtaPi(), piDecand.recoPhiPi(), massHad); + const ROOT::Math::PtEtaPhiMVector trackSum = De + Had; + + const float beta = trackSum.Beta(); + const float betax = beta * std::cos(trackSum.Phi()) * std::sin(trackSum.Theta()); + const float betay = beta * std::sin(trackSum.Phi()) * std::sin(trackSum.Theta()); + const float betaz = beta * std::cos(trackSum.Theta()); + + ROOT::Math::PxPyPzMVector DeCMS(De); + ROOT::Math::PxPyPzMVector HadCMS(Had); + + const ROOT::Math::Boost boostPRF = ROOT::Math::Boost(-betax, -betay, -betaz); + DeCMS = boostPRF(DeCMS); + HadCMS = boostPRF(HadCMS); + + const ROOT::Math::PxPyPzMVector RelKstar = DeCMS - HadCMS; + return 0.5 * RelKstar.P(); } void fillKstar(const PiDecandidate& piDecand) @@ -771,6 +784,7 @@ struct PiDeuteronFemto { mQaRegistry.fill(HIST("hkStar_US_A"), kstar); } } + mQaRegistry.fill(HIST("hkStar_All"), kstar); } // ================================================================================================================== From d7e0aab14e2fea3ced2893851fee3577b557c612 Mon Sep 17 00:00:00 2001 From: alcaliva <32872606+alcaliva@users.noreply.github.com> Date: Wed, 25 Jun 2025 17:37:36 +0200 Subject: [PATCH 211/871] [PWGLF] added DCA templates and function to compute multiplicity in different event classes (#11768) --- PWGLF/Tasks/Nuspex/antinucleiInJets.cxx | 120 +++++++++++++++++++++--- 1 file changed, 109 insertions(+), 11 deletions(-) diff --git a/PWGLF/Tasks/Nuspex/antinucleiInJets.cxx b/PWGLF/Tasks/Nuspex/antinucleiInJets.cxx index 59aca0f7ceb..ad51876259b 100644 --- a/PWGLF/Tasks/Nuspex/antinucleiInJets.cxx +++ b/PWGLF/Tasks/Nuspex/antinucleiInJets.cxx @@ -77,6 +77,7 @@ using std::array; using SelectedCollisions = soa::Join; using SimCollisions = soa::Join; +using GenCollisions = aod::McCollisions; using FullNucleiTracks = soa::Join; @@ -88,9 +89,11 @@ struct AntinucleiInJets { HistogramRegistry registryData{"registryData", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; HistogramRegistry registryMC{"registryMC", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; HistogramRegistry registryQC{"registryQC", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry registryMult{"registryMult", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; // global parameters Configurable minJetPt{"minJetPt", 10.0, "Minimum pt of the jet"}; + Configurable ptLeadingMin{"ptLeadingMin", 5.0, "pt Leading Min"}; Configurable rJet{"rJet", 0.3, "Jet resolution parameter R"}; Configurable zVtx{"zVtx", 10.0, "Maximum zVertex"}; Configurable deltaEtaEdge{"deltaEtaEdge", 0.05, "eta gap from the edge"}; @@ -179,6 +182,11 @@ struct AntinucleiInJets { registryQC.add("jetPtDifference", "jetPtDifference", HistType::kTH1F, {{200, -1, 1, "#Deltap_{T}^{jet}"}}); } + if (doprocessMultEvents) { + registryMult.add("multiplicityEvtsPtLeading", "multiplicityEvtsPtLeading", HistType::kTH1F, {{1000, 0, 1000, "#it{N}_{ch}"}}); + registryMult.add("multiplicityEvtsWithJet", "multiplicityEvtsWithJet", HistType::kTH1F, {{1000, 0, 1000, "#it{N}_{ch}"}}); + } + // data histograms if (doprocessData) { @@ -191,8 +199,8 @@ struct AntinucleiInJets { registryData.add("antiproton_jet_tof", "antiproton_jet_tof", HistType::kTH2F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}, {400, -20.0, 20.0, "n#sigma_{TOF}"}}); registryData.add("antiproton_ue_tpc", "antiproton_ue_tpc", HistType::kTH2F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}, {400, -20.0, 20.0, "n#sigma_{TPC}"}}); registryData.add("antiproton_ue_tof", "antiproton_ue_tof", HistType::kTH2F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}, {400, -20.0, 20.0, "n#sigma_{TOF}"}}); - registryData.add("antiproton_dca_jet", "antiproton_dca_jet", HistType::kTH2F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}, {200, -0.5, 0.5, "DCA_{xy} (cm)"}}); - registryData.add("antiproton_dca_ue", "antiproton_dca_ue", HistType::kTH2F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}, {200, -0.5, 0.5, "DCA_{xy} (cm)"}}); + registryData.add("antiproton_dca_jet", "antiproton_dca_jet", HistType::kTH2F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}, {200, -1, 1, "DCA_{xy} (cm)"}}); + registryData.add("antiproton_dca_ue", "antiproton_dca_ue", HistType::kTH2F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}, {200, -1, 1, "DCA_{xy} (cm)"}}); // antideuterons registryData.add("antideuteron_jet_tpc", "antideuteron_jet_tpc", HistType::kTH2F, {{nbins, min * 2, max * 2, "#it{p}_{T} (GeV/#it{c})"}, {400, -20.0, 20.0, "n#sigma_{TPC}"}}); @@ -271,6 +279,12 @@ struct AntinucleiInJets { registryMC.add("antiproton_prim_ue", "antiproton_prim_ue", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); registryMC.add("antiproton_incl_ue", "antiproton_incl_ue", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); + // DCA Templates + registryData.add("antiproton_prim_dca_jet", "antiproton_prim_dca_jet", HistType::kTH2F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}, {200, -1, 1, "DCA_{xy} (cm)"}}); + registryData.add("antiproton_prim_dca_ue", "antiproton_prim_dca_ue", HistType::kTH2F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}, {200, -1, 1, "DCA_{xy} (cm)"}}); + registryData.add("antiproton_all_dca_jet", "antiproton_all_dca_jet", HistType::kTH2F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}, {200, -1, 1, "DCA_{xy} (cm)"}}); + registryData.add("antiproton_all_dca_ue", "antiproton_all_dca_ue", HistType::kTH2F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}, {200, -1, 1, "DCA_{xy} (cm)"}}); + // antiproton reweighting registryMC.add("antiproton_eta_pt_pythia", "antiproton_eta_pt_pythia", HistType::kTH2F, {{200, 0.0, 10.0, "#it{p}_{T} (GeV/#it{c})"}, {20, -1.0, 1.0, "#it{#eta}"}}); registryMC.add("antiproton_eta_pt_jet", "antiproton_eta_pt_jet", HistType::kTH2F, {{200, 0.0, 10.0, "#it{p}_{T} (GeV/#it{c})"}, {20, -1.0, 1.0, "#it{#eta}"}}); @@ -597,7 +611,8 @@ struct AntinucleiInJets { // jet pt must be larger than threshold auto jetForSub = jet; fastjet::PseudoJet jetMinusBkg = backgroundSub.doRhoAreaSub(jetForSub, rhoPerp, rhoMPerp); - if (getCorrectedPt(jetMinusBkg.pt(), responseMatrix) < minJetPt) + // if (getCorrectedPt(jetMinusBkg.pt(), responseMatrix) < minJetPt) + if (jetMinusBkg.pt() < minJetPt) continue; isAtLeastOneJetSelected = true; @@ -768,6 +783,68 @@ struct AntinucleiInJets { } PROCESS_SWITCH(AntinucleiInJets, processData, "Process Data", true); + void processMultEvents(SelectedCollisions::iterator const& collision, FullNucleiTracks const& tracks) + { + // event selection + if (!collision.sel8() || std::fabs(collision.posZ()) > zVtx) + return; + + // Leading Track + double ptMax(0.0); + + // loop over reconstructed tracks + int id(-1); + std::vector fjParticles; + for (auto const& track : tracks) { + id++; + if (!passedTrackSelectionForJetReconstruction(track)) + continue; + if (track.pt() > ptMax) { + ptMax = track.pt(); + } + + // 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); + } + // reject empty events + if (fjParticles.empty()) { + return; + } + + if (ptMax > ptLeadingMin) { + registryMult.fill(HIST("multiplicityEvtsPtLeading"), fjParticles.size()); + } + + // cluster particles using the anti-kt algorithm + fastjet::JetDefinition jetDef(fastjet::antikt_algorithm, rJet); + fastjet::AreaDefinition areaDef(fastjet::active_area, fastjet::GhostedAreaSpec(1.0)); + fastjet::ClusterSequenceArea cs(fjParticles, jetDef, areaDef); + std::vector jets = fastjet::sorted_by_pt(cs.inclusive_jets()); + auto [rhoPerp, rhoMPerp] = backgroundSub.estimateRhoPerpCone(fjParticles, jets); + + // loop over reconstructed jets + bool isAtLeastOneJetSelected = false; + for (const auto& jet : jets) { + + // jet must be fully contained in the acceptance + if ((std::fabs(jet.eta()) + rJet) > (maxEta - 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; + isAtLeastOneJetSelected = true; + } + if (isAtLeastOneJetSelected) { + registryMult.fill(HIST("multiplicityEvtsWithJet"), fjParticles.size()); + } + } + PROCESS_SWITCH(AntinucleiInJets, processMultEvents, "Process Mult Events", true); + // Process QC void processQC(SelectedCollisions::iterator const& collision, FullNucleiTracks const& tracks) { @@ -1087,13 +1164,13 @@ struct AntinucleiInJets { } PROCESS_SWITCH(AntinucleiInJets, processEfficiency, "process efficiency", false); - void processJetsMCgen(SimCollisions const& collisions, aod::McParticles const& mcParticles) + void processJetsMCgen(GenCollisions const& collisions, aod::McParticles const& mcParticles) { // Loop over all simulated collision events for (const auto& collision : collisions) { - // Apply event selection: require sel8 and vertex position within the allowed z range - if (!collision.sel8() || std::fabs(collision.posZ()) > zVtx) + // Apply event selection: require vertex position within the allowed z range + if (std::fabs(collision.posZ()) > zVtx) continue; // Loop over all MC particles and select physical primaries within acceptance @@ -1256,7 +1333,8 @@ struct AntinucleiInJets { fastjet::PseudoJet jetMinusBkg = backgroundSub.doRhoAreaSub(jetForSub, rhoPerp, rhoMPerp); // Apply jet pT threshold - if (getCorrectedPt(jetMinusBkg.pt(), responseMatrix) < minJetPt) + // if (getCorrectedPt(jetMinusBkg.pt(), responseMatrix) < minJetPt) + if (jetMinusBkg.pt() < minJetPt) continue; // Set up two perpendicular cone axes for underlying event estimation @@ -1271,11 +1349,20 @@ struct AntinucleiInJets { auto const& track = mcTracks.iteratorAt(particle.user_index()); if (!track.has_mcParticle()) continue; + const auto mcparticle = track.mcParticle(); + + // Fill DCA templates + if (mcparticle.pdgCode() == kProtonBar && passedTrackSelection(track) && std::fabs(track.dcaZ()) < maxDcaz) { + if (mcparticle.isPhysicalPrimary()) { + registryMC.fill(HIST("antiproton_prim_dca_jet"), track.pt(), track.dcaXY()); + } else { + registryMC.fill(HIST("antiproton_all_dca_jet"), track.pt(), track.dcaXY()); + } + } // Apply standard track quality and PID selection if (!passedTrackSelection(track) || std::fabs(track.dcaXY()) > maxDcaxy || std::fabs(track.dcaZ()) > maxDcaz) continue; - const auto mcparticle = track.mcParticle(); if (track.sign() > 0 || mcparticle.pdgCode() != kProtonBar) continue; @@ -1310,15 +1397,26 @@ struct AntinucleiInJets { // Analyze antiprotons in the Underlying Event (UE) using perpendicular cones for (auto const& track : mcTracks) { - if (!passedTrackSelection(track) || std::fabs(track.dcaXY()) > maxDcaxy || std::fabs(track.dcaZ()) > maxDcaz) - continue; + if (!track.has_mcParticle()) continue; - const auto mcparticle = track.mcParticle(); if (track.sign() > 0 || mcparticle.pdgCode() != kProtonBar) continue; + // Fill DCA templates + if (mcparticle.pdgCode() == kProtonBar && passedTrackSelection(track) && std::fabs(track.dcaZ()) < maxDcaz) { + if (mcparticle.isPhysicalPrimary()) { + registryMC.fill(HIST("antiproton_prim_dca_ue"), track.pt(), track.dcaXY()); + } else { + registryMC.fill(HIST("antiproton_all_dca_ue"), track.pt(), track.dcaXY()); + } + } + + // Track Selection + if (!passedTrackSelection(track) || std::fabs(track.dcaXY()) > maxDcaxy || std::fabs(track.dcaZ()) > maxDcaz) + continue; + // Compute distance from UE cones double deltaEtaUe1 = track.eta() - ueAxis1.Eta(); double deltaPhiUe1 = getDeltaPhi(track.phi(), ueAxis1.Phi()); From a4b4397c8bd2d7e55479bdf2c2bee64b39789e26 Mon Sep 17 00:00:00 2001 From: Rik Spijkers <78484875+rspijkers@users.noreply.github.com> Date: Wed, 25 Jun 2025 18:33:10 +0200 Subject: [PATCH 212/871] [PWGLF] Add signs to THnSparses, change logic accordingly (#11771) --- .../Tasks/Strangeness/cascadecorrelations.cxx | 409 ++++++------------ 1 file changed, 135 insertions(+), 274 deletions(-) diff --git a/PWGLF/Tasks/Strangeness/cascadecorrelations.cxx b/PWGLF/Tasks/Strangeness/cascadecorrelations.cxx index 4b78f8d6771..13d45dd198b 100644 --- a/PWGLF/Tasks/Strangeness/cascadecorrelations.cxx +++ b/PWGLF/Tasks/Strangeness/cascadecorrelations.cxx @@ -107,6 +107,8 @@ struct CascadeSelector { Configurable minTPCCrossedRows{"minTPCCrossedRows", 80, "min N TPC crossed rows"}; // TODO: finetune! 80 > 159/2, so no split tracks? Configurable minITSClusters{"minITSClusters", 4, "minimum number of ITS clusters"}; Configurable etaTracks{"etaTracks", 1.0, "min/max of eta for tracks"}; + Configurable tpcChi2{"tpcChi2", 4, "TPC Chi2"}; + Configurable itsChi2{"itsChi2", 36, "ITS Chi2"}; // Selection criteria - compatible with core wagon autodetect - copied from cascadeanalysis.cxx //*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+* @@ -171,6 +173,12 @@ struct CascadeSelector { {"hITSnClustersPos", "hITSnClustersPos", {HistType::kTH3F, {itsClustersAxis, invXiMassAxis, ptAxis}}}, {"hITSnClustersNeg", "hITSnClustersNeg", {HistType::kTH3F, {itsClustersAxis, invXiMassAxis, ptAxis}}}, {"hITSnClustersBach", "hITSnClustersBach", {HistType::kTH3F, {itsClustersAxis, invXiMassAxis, ptAxis}}}, + {"hTPCChi2Pos", "hTPCChi2Pos", {HistType::kTH1F, {{100, 0, 10, "TPC Chi2 Pos"}}}}, + {"hTPCChi2Neg", "hTPCChi2Neg", {HistType::kTH1F, {{100, 0, 10, "TPC Chi2 Neg"}}}}, + {"hTPCChi2Bach", "hTPCChi2Bach", {HistType::kTH1F, {{100, 0, 10, "TPC Chi2 Bach"}}}}, + {"hITSChi2Pos", "hITSChi2Pos", {HistType::kTH1F, {{100, 0, 100, "ITS Chi2 Pos"}}}}, + {"hITSChi2Neg", "hITSChi2Neg", {HistType::kTH1F, {{100, 0, 100, "ITS Chi2 Neg"}}}}, + {"hITSChi2Bach", "hITSChi2Bach", {HistType::kTH1F, {{100, 0, 100, "ITS Chi2 Bach"}}}}, {"hTriggerQA", "hTriggerQA", {HistType::kTH1F, {{2, -0.5, 1.5, "Trigger y/n"}}}}, }, @@ -186,11 +194,12 @@ struct CascadeSelector { h->GetXaxis()->SetBinLabel(1, "All"); h->GetXaxis()->SetBinLabel(2, "nTPC OK"); h->GetXaxis()->SetBinLabel(3, "nITS OK"); - h->GetXaxis()->SetBinLabel(4, "Topo OK"); - h->GetXaxis()->SetBinLabel(5, "Track eta OK"); - h->GetXaxis()->SetBinLabel(6, "Cascade eta OK"); - h->GetXaxis()->SetBinLabel(7, "V0 PID OK"); - h->GetXaxis()->SetBinLabel(8, "Bach PID OK"); + h->GetXaxis()->SetBinLabel(4, "track Chi2 OK"); + h->GetXaxis()->SetBinLabel(5, "Topo OK"); + h->GetXaxis()->SetBinLabel(6, "Track eta OK"); + h->GetXaxis()->SetBinLabel(7, "Cascade eta OK"); + h->GetXaxis()->SetBinLabel(8, "V0 PID OK"); + h->GetXaxis()->SetBinLabel(9, "Bach PID OK"); auto hEventSel = registry.add("hEventSel", "hEventSel", HistType::kTH1I, {{10, 0, 10, "selection criteria"}}); hEventSel->GetXaxis()->SetBinLabel(1, "All"); @@ -219,6 +228,12 @@ struct CascadeSelector { registry.add("truerec/hITSnClustersPos", "hITSnClustersPos", HistType::kTH1F, {itsClustersAxis}); registry.add("truerec/hITSnClustersNeg", "hITSnClustersNeg", HistType::kTH1F, {itsClustersAxis}); registry.add("truerec/hITSnClustersBach", "hITSnClustersBach", HistType::kTH1F, {itsClustersAxis}); + registry.add("truerec/hTPCChi2Pos", "hTPCChi2Pos", HistType::kTH1F, {{100, 0, 10, "TPC Chi2 Pos"}}); + registry.add("truerec/hTPCChi2Neg", "hTPCChi2Neg", HistType::kTH1F, {{100, 0, 10, "TPC Chi2 Neg"}}); + registry.add("truerec/hTPCChi2Bach", "hTPCChi2Bach", HistType::kTH1F, {{100, 0, 10, "TPC Chi2 Bach"}}); + registry.add("truerec/hITSChi2Pos", "hITSChi2Pos", HistType::kTH1F, {{100, 0, 100, "ITS Chi2 Pos"}}); + registry.add("truerec/hITSChi2Neg", "hITSChi2Neg", HistType::kTH1F, {{100, 0, 100, "ITS Chi2 Neg"}}); + registry.add("truerec/hITSChi2Bach", "hITSChi2Bach", HistType::kTH1F, {{100, 0, 100, "ITS Chi2 Bach"}}); registry.add("truerec/hXiMinus", "hXiMinus", HistType::kTH2F, {ptAxis, rapidityAxis}); registry.add("truerec/hXiPlus", "hXiPlus", HistType::kTH2F, {ptAxis, rapidityAxis}); registry.add("truerec/hOmegaMinus", "hOmegaMinus", HistType::kTH2F, {ptAxis, rapidityAxis}); @@ -297,6 +312,12 @@ struct CascadeSelector { registry.fill(HIST("truerec/hTPCnCrossedRowsPos"), rec.posTrack_as().tpcNClsCrossedRows()); registry.fill(HIST("truerec/hTPCnCrossedRowsNeg"), rec.negTrack_as().tpcNClsCrossedRows()); registry.fill(HIST("truerec/hTPCnCrossedRowsBach"), rec.bachelor_as().tpcNClsCrossedRows()); + registry.fill(HIST("truerec/hITSChi2Pos"), rec.posTrack_as().itsChi2NCl()); + registry.fill(HIST("truerec/hITSChi2Neg"), rec.negTrack_as().itsChi2NCl()); + registry.fill(HIST("truerec/hITSChi2Bach"), rec.bachelor_as().itsChi2NCl()); + registry.fill(HIST("truerec/hTPCChi2Pos"), rec.posTrack_as().tpcChi2NCl()); + registry.fill(HIST("truerec/hTPCChi2Neg"), rec.negTrack_as().tpcChi2NCl()); + registry.fill(HIST("truerec/hTPCChi2Bach"), rec.bachelor_as().tpcChi2NCl()); switch (genpdg) { // is matched so we can use genpdg case 3312: registry.fill(HIST("truerec/hXiMinus"), rec.pt(), rec.yXi()); @@ -341,6 +362,12 @@ struct CascadeSelector { registry.fill(HIST("hTPCnCrossedRowsPos"), posTrack.tpcNClsCrossedRows(), casc.mXi(), casc.pt()); registry.fill(HIST("hTPCnCrossedRowsNeg"), negTrack.tpcNClsCrossedRows(), casc.mXi(), casc.pt()); registry.fill(HIST("hTPCnCrossedRowsBach"), bachTrack.tpcNClsCrossedRows(), casc.mXi(), casc.pt()); + registry.fill(HIST("hITSChi2Pos"), posTrack.itsChi2NCl()); + registry.fill(HIST("hITSChi2Neg"), negTrack.itsChi2NCl()); + registry.fill(HIST("hITSChi2Bach"), bachTrack.itsChi2NCl()); + registry.fill(HIST("hTPCChi2Pos"), posTrack.tpcChi2NCl()); + registry.fill(HIST("hTPCChi2Neg"), negTrack.tpcChi2NCl()); + registry.fill(HIST("hTPCChi2Bach"), bachTrack.tpcChi2NCl()); registry.fill(HIST("hSelectionStatus"), 0); // all the cascade before selections // registry.fill(HIST("hMassXi0"), casc.mXi(), casc.pt()); @@ -359,6 +386,14 @@ struct CascadeSelector { registry.fill(HIST("hSelectionStatus"), 2); // passes nITS clusters // registry.fill(HIST("hMassXi2"), casc.mXi(), casc.pt()); + // Chi2 cuts + if (posTrack.itsChi2NCl() > itsChi2 || negTrack.itsChi2NCl() > itsChi2 || bachTrack.itsChi2NCl() > itsChi2) + return 0; + if (posTrack.tpcChi2NCl() > tpcChi2 || negTrack.tpcChi2NCl() > tpcChi2 || bachTrack.tpcChi2NCl() > tpcChi2) + return 0; + + registry.fill(HIST("hSelectionStatus"), 3); // passes Chi2 cuts + //// TOPO CUTS //// TODO: improve! double pvx = collision.posX(); double pvy = collision.posY(); @@ -371,18 +406,18 @@ struct CascadeSelector { TMath::Abs(casc.mLambda() - 1.115683) > cascadesetting_v0masswindow) return 0; // It failed at least one topo selection - registry.fill(HIST("hSelectionStatus"), 3); // passes topo + registry.fill(HIST("hSelectionStatus"), 4); // passes topo // registry.fill(HIST("hMassXi3"), casc.mXi(), casc.pt()); if (TMath::Abs(posTrack.eta()) > etaTracks || TMath::Abs(negTrack.eta()) > etaTracks || TMath::Abs(bachTrack.eta()) > etaTracks) return 0; - registry.fill(HIST("hSelectionStatus"), 4); // passes track eta + registry.fill(HIST("hSelectionStatus"), 5); // passes track eta if (TMath::Abs(casc.eta()) > etaCascades) return 0; - registry.fill(HIST("hSelectionStatus"), 5); // passes candidate eta + registry.fill(HIST("hSelectionStatus"), 6); // passes candidate eta // TODO: TOF (for pT > 2 GeV per track?) @@ -403,14 +438,14 @@ struct CascadeSelector { if (TMath::Abs(posTrack.tpcNSigmaPi()) > tpcNsigmaPion) return 0; } - registry.fill(HIST("hSelectionStatus"), 6); // passes V0 daughters PID + registry.fill(HIST("hSelectionStatus"), 7); // passes V0 daughters PID // registry.fill(HIST("hMassXi4"), casc.mXi(), casc.pt()); // Bachelor check if (TMath::Abs(bachTrack.tpcNSigmaPi()) < tpcNsigmaBachelor) { if (TMath::Abs(bachTrack.tpcNSigmaKa()) < tpcNsigmaBachelor) { // consistent with both! - registry.fill(HIST("hSelectionStatus"), 7); // passes bach PID + registry.fill(HIST("hSelectionStatus"), 8); // passes bach PID // registry.fill(HIST("hMassXi5"), casc.mXi(), casc.pt()); if (casc.sign() < 0) { registry.fill(HIST("hMassXiMinus"), casc.mXi(), casc.pt(), casc.yXi()); @@ -421,7 +456,7 @@ struct CascadeSelector { } return 2; } - registry.fill(HIST("hSelectionStatus"), 7); // passes bach PID + registry.fill(HIST("hSelectionStatus"), 8); // passes bach PID // registry.fill(HIST("hMassXi5"), casc.mXi(), casc.pt()); if (casc.sign() < 0) { registry.fill(HIST("hMassXiMinus"), casc.mXi(), casc.pt(), casc.yXi()); @@ -430,7 +465,7 @@ struct CascadeSelector { } return 1; } else if (TMath::Abs(bachTrack.tpcNSigmaKa()) < tpcNsigmaBachelor) { - registry.fill(HIST("hSelectionStatus"), 7); // passes bach PID + registry.fill(HIST("hSelectionStatus"), 8); // passes bach PID if (casc.sign() < 0) { registry.fill(HIST("hMassOmegaMinus"), casc.mOmega(), casc.pt(), casc.yOmega()); } else { @@ -538,8 +573,9 @@ struct CascadeCorrelations { ConfigurableAxis dcaAxis = {"dcaAxis", {100, 0.0f, 2.0f}, "cm"}; ConfigurableAxis multiplicityAxis{"multiplicityAxis", {100, 0, 100}, "Multiplicity (MultFT0M?)"}; ConfigurableAxis invLambdaMassAxis{"invLambdaMassAxis", {100, 1.07f, 1.17f}, "Inv. Mass (GeV/c^{2})"}; - ConfigurableAxis deltaYAxis{"deltaYAxis", {40, -2.f, 2.f}, "#Delta y"}; - ConfigurableAxis rapidityAxis{"rapidityAxis", {100, -1.f, 1.f}, "y"}; + AxisSpec signAxis{3, -1.5, 1.5, "sign of cascade"}; + AxisSpec deltaYAxis{40, -2 * maxRapidity, 2 * maxRapidity, "#Delta y"}; + AxisSpec rapidityAxis{100, -maxRapidity, maxRapidity, "y"}; AxisSpec selectionFlagAxis{4, -0.5f, 3.5f, "Selection flag of casc candidate"}; AxisSpec itsClustersAxis{8, -0.5, 7.5, "number of ITS clusters"}; AxisSpec tpcRowsAxis{160, -0.5, 159.5, "TPC crossed rows"}; @@ -585,6 +621,18 @@ struct CascadeCorrelations { return 1. / eff; } + bool autoCorrelation(std::array triggerTracks, std::array assocTracks) + { + // function that loops over 2 arrays of track indices, checking for common elements + for (int triggerTrack : triggerTracks) { + for (int assocTrack : assocTracks) { + if (triggerTrack == assocTrack) + return true; + } + } + return false; + } + HistogramRegistry registry{ "registry", { @@ -594,8 +642,8 @@ struct CascadeCorrelations { {"hMassOmegaMinus", "hMassOmegaMinus", {HistType::kTH2F, {invMassAxis, ptAxis}}}, {"hMassOmegaPlus", "hMassOmegaPlus", {HistType::kTH2F, {invMassAxis, ptAxis}}}, // efficiency corrected inv mass - {"hMassXiEffCorrected", "hMassXiEffCorrected", {HistType::kTHnSparseF, {invMassAxis, ptAxis, rapidityAxis, vertexAxis, multiplicityAxis}}, true}, - {"hMassOmegaEffCorrected", "hMassOmegaEffCorrected", {HistType::kTHnSparseF, {invMassAxis, ptAxis, rapidityAxis, vertexAxis, multiplicityAxis}}, true}, + {"hMassXiEffCorrected", "hMassXiEffCorrected", {HistType::kTHnSparseF, {invMassAxis, signAxis, ptAxis, rapidityAxis, vertexAxis, multiplicityAxis}}, true}, + {"hMassOmegaEffCorrected", "hMassOmegaEffCorrected", {HistType::kTHnSparseF, {invMassAxis, signAxis, ptAxis, rapidityAxis, vertexAxis, multiplicityAxis}}, true}, // trigger QA {"hTriggerQA", "hTriggerQA", {HistType::kTH1F, {{2, -0.5, 1.5, "Trigger y/n"}}}}, @@ -631,14 +679,9 @@ struct CascadeCorrelations { {"hDeltaPhiSS", "hDeltaPhiSS", {HistType::kTH1F, {deltaPhiAxis}}}, {"hDeltaPhiOS", "hDeltaPhiOS", {HistType::kTH1F, {deltaPhiAxis}}}, - {"hXiXiOS", "hXiXiOS", {HistType::kTHnSparseF, {deltaPhiAxis, deltaYAxis, ptAxis, ptAxis, invMassAxis, invMassAxis, vertexAxis, multiplicityAxis}}, true}, - {"hXiXiSS", "hXiXiSS", {HistType::kTHnSparseF, {deltaPhiAxis, deltaYAxis, ptAxis, ptAxis, invMassAxis, invMassAxis, vertexAxis, multiplicityAxis}}, true}, - {"hXiOmOS", "hXiOmOS", {HistType::kTHnSparseF, {deltaPhiAxis, deltaYAxis, ptAxis, ptAxis, invMassAxis, invMassAxis, vertexAxis, multiplicityAxis}}, true}, - {"hXiOmSS", "hXiOmSS", {HistType::kTHnSparseF, {deltaPhiAxis, deltaYAxis, ptAxis, ptAxis, invMassAxis, invMassAxis, vertexAxis, multiplicityAxis}}, true}, - {"hOmXiOS", "hOmXiOS", {HistType::kTHnSparseF, {deltaPhiAxis, deltaYAxis, ptAxis, ptAxis, invMassAxis, invMassAxis, vertexAxis, multiplicityAxis}}, true}, - {"hOmXiSS", "hOmXiSS", {HistType::kTHnSparseF, {deltaPhiAxis, deltaYAxis, ptAxis, ptAxis, invMassAxis, invMassAxis, vertexAxis, multiplicityAxis}}, true}, - {"hOmOmOS", "hOmOmOS", {HistType::kTHnSparseF, {deltaPhiAxis, deltaYAxis, ptAxis, ptAxis, invMassAxis, invMassAxis, vertexAxis, multiplicityAxis}}, true}, - {"hOmOmSS", "hOmOmSS", {HistType::kTHnSparseF, {deltaPhiAxis, deltaYAxis, ptAxis, ptAxis, invMassAxis, invMassAxis, vertexAxis, multiplicityAxis}}, true}, + {"hXiXi", "hXiXi", {HistType::kTHnSparseF, {deltaPhiAxis, deltaYAxis, signAxis, signAxis, ptAxis, ptAxis, invMassAxis, invMassAxis, vertexAxis, multiplicityAxis}}, true}, + {"hXiOm", "hXiOm", {HistType::kTHnSparseF, {deltaPhiAxis, deltaYAxis, signAxis, signAxis, ptAxis, ptAxis, invMassAxis, invMassAxis, vertexAxis, multiplicityAxis}}, true}, + {"hOmOm", "hOmOm", {HistType::kTHnSparseF, {deltaPhiAxis, deltaYAxis, signAxis, signAxis, ptAxis, ptAxis, invMassAxis, invMassAxis, vertexAxis, multiplicityAxis}}, true}, // Mixed events {"MixedEvents/hMEVz1", "hMEVz1", {HistType::kTH1F, {vertexAxis}}}, @@ -649,14 +692,9 @@ struct CascadeCorrelations { {"MixedEvents/hMEAutoCorrelation", "hMEAutoCorrelation", {HistType::kTH1I, {{4, -0.5f, 3.5f, "Types of SS autocorrelation"}}}}, {"MixedEvents/hMEAutoCorrelationOS", "hMEAutoCorrelationOS", {HistType::kTH1I, {{2, -1.f, 1.f, "Charge of OS autocorrelated track"}}}}, - {"MixedEvents/hMEXiXiOS", "hMEXiXiOS", {HistType::kTHnSparseF, {deltaPhiAxis, deltaYAxis, ptAxis, ptAxis, invMassAxis, invMassAxis, vertexAxis, multiplicityAxis}}, true}, - {"MixedEvents/hMEXiXiSS", "hMEXiXiSS", {HistType::kTHnSparseF, {deltaPhiAxis, deltaYAxis, ptAxis, ptAxis, invMassAxis, invMassAxis, vertexAxis, multiplicityAxis}}, true}, - {"MixedEvents/hMEXiOmOS", "hMEXiOmOS", {HistType::kTHnSparseF, {deltaPhiAxis, deltaYAxis, ptAxis, ptAxis, invMassAxis, invMassAxis, vertexAxis, multiplicityAxis}}, true}, - {"MixedEvents/hMEXiOmSS", "hMEXiOmSS", {HistType::kTHnSparseF, {deltaPhiAxis, deltaYAxis, ptAxis, ptAxis, invMassAxis, invMassAxis, vertexAxis, multiplicityAxis}}, true}, - {"MixedEvents/hMEOmXiOS", "hMEOmXiOS", {HistType::kTHnSparseF, {deltaPhiAxis, deltaYAxis, ptAxis, ptAxis, invMassAxis, invMassAxis, vertexAxis, multiplicityAxis}}, true}, - {"MixedEvents/hMEOmXiSS", "hMEOmXiSS", {HistType::kTHnSparseF, {deltaPhiAxis, deltaYAxis, ptAxis, ptAxis, invMassAxis, invMassAxis, vertexAxis, multiplicityAxis}}, true}, - {"MixedEvents/hMEOmOmOS", "hMEOmOmOS", {HistType::kTHnSparseF, {deltaPhiAxis, deltaYAxis, ptAxis, ptAxis, invMassAxis, invMassAxis, vertexAxis, multiplicityAxis}}, true}, - {"MixedEvents/hMEOmOmSS", "hMEOmOmSS", {HistType::kTHnSparseF, {deltaPhiAxis, deltaYAxis, ptAxis, ptAxis, invMassAxis, invMassAxis, vertexAxis, multiplicityAxis}}, true}, + {"MixedEvents/hMEXiXi", "hMEXiXi", {HistType::kTHnSparseF, {deltaPhiAxis, deltaYAxis, signAxis, signAxis, ptAxis, ptAxis, invMassAxis, invMassAxis, vertexAxis, multiplicityAxis}}, true}, + {"MixedEvents/hMEXiOm", "hMEXiOm", {HistType::kTHnSparseF, {deltaPhiAxis, deltaYAxis, signAxis, signAxis, ptAxis, ptAxis, invMassAxis, invMassAxis, vertexAxis, multiplicityAxis}}, true}, + {"MixedEvents/hMEOmOm", "hMEOmOm", {HistType::kTHnSparseF, {deltaPhiAxis, deltaYAxis, signAxis, signAxis, ptAxis, ptAxis, invMassAxis, invMassAxis, vertexAxis, multiplicityAxis}}, true}, // MC closure {"MC/hMCPlusMinus", "hMCPlusMinus", {HistType::kTHnSparseF, {deltaPhiAxis, deltaYAxis, ptAxis, ptAxis, vertexAxis, multiplicityAxis}}, true}, @@ -760,12 +798,11 @@ struct CascadeCorrelations { auto trigger = *triggerAddress; auto assoc = *assocAddress; - // track indices for posterior checks - // retains logic of V0 index while being safe wrt data model - int posIdTrigg = trigger.posTrackId(); - int negIdTrigg = trigger.negTrackId(); - int posIdAssoc = assoc.posTrackId(); - int negIdAssoc = assoc.negTrackId(); + // autocorrelation check + std::array triggerTracks = {trigger.posTrackId(), trigger.negTrackId(), trigger.bachelorId()}; + std::array assocTracks = {assoc.posTrackId(), assoc.negTrackId(), assoc.bachelorId()}; + if (autoCorrelation(triggerTracks, assocTracks)) + continue; // calculate angular correlations double dphi = RecoDecay::constrainAngle(trigger.phi() - assoc.phi(), -PIHalf); @@ -778,128 +815,42 @@ struct CascadeCorrelations { double weightTrigg = 1.; double weightAssoc = 1.; - // split into opposite-sign or same-sign - if (trigger.sign() * assoc.sign() < 0) { // opposite-sign - // check for autocorrelations between mis-identified kaons (omega bach) and protons (lambda daughter) TODO: improve logic? - if (trigger.isSelected() >= 2) { - if (trigger.sign() > 0 && trigger.bachelorId() == posIdAssoc) { - // K+ from trigger Omega is the same as proton from assoc lambda - registry.fill(HIST("hAutoCorrelationOS"), 1); - continue; - } - if (trigger.sign() < 0 && trigger.bachelorId() == negIdAssoc) { - // K- from trigger Omega is the same as antiproton from assoc antilambda - registry.fill(HIST("hAutoCorrelationOS"), -1); - continue; - } - } - if (assoc.isSelected() >= 2) { - if (assoc.sign() > 0 && assoc.bachelorId() == posIdTrigg) { - // K+ from assoc Omega is the same as proton from trigger lambda - registry.fill(HIST("hAutoCorrelationOS"), 1); - continue; - } - if (assoc.sign() < 0 && assoc.bachelorId() == negIdTrigg) { - // K- from assoc Omega is the same as antiproton from trigger antilambda - registry.fill(HIST("hAutoCorrelationOS"), -1); - continue; - } - } - registry.fill(HIST("hDeltaPhiOS"), dphi); - // Fill the different THnSparses depending on PID logic (important for rapidity & inv mass information) - if (trigger.isSelected() <= 2 && TMath::Abs(trigger.yXi()) < maxRapidity) { // trigger Xi + if (trigger.isSelected() <= 2 && TMath::Abs(trigger.yXi()) < maxRapidity) { // trigger Xi + if (doEfficiencyCorrection) + weightTrigg = trigger.sign() < 0 ? getEfficiency(hEffXiMin, trigger.pt()) : getEfficiency(hEffXiPlus, trigger.pt()); + if (assoc.isSelected() <= 2 && TMath::Abs(assoc.yXi()) < maxRapidity) { // assoc Xi if (doEfficiencyCorrection) - weightTrigg = trigger.sign() < 0 ? getEfficiency(hEffXiMin, trigger.pt()) : getEfficiency(hEffXiPlus, trigger.pt()); - if (assoc.isSelected() <= 2 && TMath::Abs(assoc.yXi()) < maxRapidity) { // assoc Xi - if (doEfficiencyCorrection) - weightAssoc = assoc.sign() < 0 ? getEfficiency(hEffXiMin, assoc.pt()) : getEfficiency(hEffXiPlus, assoc.pt()); - registry.fill(HIST("hXiXiOS"), dphi, trigger.yXi() - assoc.yXi(), trigger.pt(), assoc.pt(), invMassXiTrigg, invMassXiAssoc, collision.posZ(), collision.multFT0M(), weightTrigg * weightAssoc); - } - if (assoc.isSelected() >= 2 && TMath::Abs(assoc.yOmega()) < maxRapidity) { // assoc Omega - if (doEfficiencyCorrection) - weightAssoc = assoc.sign() < 0 ? getEfficiency(hEffOmegaMin, assoc.pt()) : getEfficiency(hEffOmegaPlus, assoc.pt()); - registry.fill(HIST("hXiOmOS"), dphi, trigger.yXi() - assoc.yOmega(), trigger.pt(), assoc.pt(), invMassXiTrigg, invMassOmAssoc, collision.posZ(), collision.multFT0M(), weightTrigg * weightAssoc); - } + weightAssoc = assoc.sign() < 0 ? getEfficiency(hEffXiMin, assoc.pt()) : getEfficiency(hEffXiPlus, assoc.pt()); + registry.fill(HIST("hXiXi"), dphi, trigger.yXi() - assoc.yXi(), trigger.sign(), assoc.sign(), trigger.pt(), assoc.pt(), invMassXiTrigg, invMassXiAssoc, collision.posZ(), collision.multFT0M(), weightTrigg * weightAssoc); } - if (trigger.isSelected() >= 2 && TMath::Abs(trigger.yOmega()) < maxRapidity) { // trigger Omega + if (assoc.isSelected() >= 2 && TMath::Abs(assoc.yOmega()) < maxRapidity) { // assoc Omega if (doEfficiencyCorrection) - weightTrigg = trigger.sign() < 0 ? getEfficiency(hEffOmegaMin, trigger.pt()) : getEfficiency(hEffOmegaPlus, trigger.pt()); - if (assoc.isSelected() <= 2 && TMath::Abs(assoc.yXi()) < maxRapidity) { // assoc Xi - if (doEfficiencyCorrection) - weightAssoc = assoc.sign() < 0 ? getEfficiency(hEffXiMin, assoc.pt()) : getEfficiency(hEffXiPlus, assoc.pt()); - registry.fill(HIST("hOmXiOS"), dphi, trigger.yOmega() - assoc.yXi(), trigger.pt(), assoc.pt(), invMassOmTrigg, invMassXiAssoc, collision.posZ(), collision.multFT0M(), weightTrigg * weightAssoc); - } - if (assoc.isSelected() >= 2 && TMath::Abs(assoc.yOmega()) < maxRapidity) { // assoc Omega - if (doEfficiencyCorrection) - weightAssoc = assoc.sign() < 0 ? getEfficiency(hEffOmegaMin, assoc.pt()) : getEfficiency(hEffOmegaPlus, assoc.pt()); - registry.fill(HIST("hOmOmOS"), dphi, trigger.yOmega() - assoc.yOmega(), trigger.pt(), assoc.pt(), invMassOmTrigg, invMassOmAssoc, collision.posZ(), collision.multFT0M(), weightTrigg * weightAssoc); - } - } - } else { // same-sign - // make sure to check for autocorrelations - only possible in same-sign correlations (if PID is correct) - if (posIdTrigg == posIdAssoc && negIdTrigg == negIdAssoc) { - // LOGF(info, "same v0 in SS correlation! %d %d", v0dataTrigg.v0Id(), v0dataAssoc.v0Id()); - registry.fill(HIST("hAutoCorrelation"), 0); - continue; - } - int bachIdTrigg = trigger.bachelorId(); - int bachIdAssoc = assoc.bachelorId(); - - if (bachIdTrigg == bachIdAssoc) { - // LOGF(info, "same bachelor in SS correlation! %d %d", bachIdTrigg, bachIdAssoc); - registry.fill(HIST("hAutoCorrelation"), 1); - continue; - } - // check for same tracks in v0's of cascades - if (negIdTrigg == negIdAssoc || posIdTrigg == posIdAssoc) { - // LOGF(info, "cascades have a v0-track in common in SS correlation!"); - registry.fill(HIST("hAutoCorrelation"), 2); - continue; + weightAssoc = assoc.sign() < 0 ? getEfficiency(hEffOmegaMin, assoc.pt()) : getEfficiency(hEffOmegaPlus, assoc.pt()); + registry.fill(HIST("hXiOm"), dphi, trigger.yXi() - assoc.yOmega(), trigger.sign(), assoc.sign(), trigger.pt(), assoc.pt(), invMassXiTrigg, invMassOmAssoc, collision.posZ(), collision.multFT0M(), weightTrigg * weightAssoc); } - if (trigger.sign() < 0) { // neg cascade - if (negIdTrigg == bachIdAssoc || negIdAssoc == bachIdTrigg) { - // LOGF(info, "bach of casc == v0-pion of other casc in neg SS correlation!"); - registry.fill(HIST("hAutoCorrelation"), 3); - continue; - } - } else { // pos cascade - if (posIdTrigg == bachIdAssoc || posIdAssoc == bachIdTrigg) { - // LOGF(info, "bach of casc == v0-pion of other casc in pos SS correlation!"); - registry.fill(HIST("hAutoCorrelation"), 3); - continue; - } - } - registry.fill(HIST("hDeltaPhiSS"), dphi); - // Fill the different THnSparses depending on PID logic (important for rapidity & inv mass information) - if (trigger.isSelected() <= 2 && TMath::Abs(trigger.yXi()) < maxRapidity) { // trigger Xi + } + if (trigger.isSelected() >= 2 && TMath::Abs(trigger.yOmega()) < maxRapidity) { // trigger Omega + if (doEfficiencyCorrection) + weightTrigg = trigger.sign() < 0 ? getEfficiency(hEffOmegaMin, trigger.pt()) : getEfficiency(hEffOmegaPlus, trigger.pt()); + if (assoc.isSelected() <= 2 && TMath::Abs(assoc.yXi()) < maxRapidity) { // assoc Xi if (doEfficiencyCorrection) - weightTrigg = trigger.sign() < 0 ? getEfficiency(hEffXiMin, trigger.pt()) : getEfficiency(hEffXiPlus, trigger.pt()); - if (assoc.isSelected() <= 2 && TMath::Abs(assoc.yXi()) < maxRapidity) { // assoc Xi - if (doEfficiencyCorrection) - weightAssoc = assoc.sign() < 0 ? getEfficiency(hEffXiMin, assoc.pt()) : getEfficiency(hEffXiPlus, assoc.pt()); - registry.fill(HIST("hXiXiSS"), dphi, trigger.yXi() - assoc.yXi(), trigger.pt(), assoc.pt(), invMassXiTrigg, invMassXiAssoc, collision.posZ(), collision.multFT0M(), weightTrigg * weightAssoc); - } - if (assoc.isSelected() >= 2 && TMath::Abs(assoc.yOmega()) < maxRapidity) { // assoc Omega - if (doEfficiencyCorrection) - weightAssoc = assoc.sign() < 0 ? getEfficiency(hEffOmegaMin, assoc.pt()) : getEfficiency(hEffOmegaPlus, assoc.pt()); - registry.fill(HIST("hXiOmSS"), dphi, trigger.yXi() - assoc.yOmega(), trigger.pt(), assoc.pt(), invMassXiTrigg, invMassOmAssoc, collision.posZ(), collision.multFT0M(), weightTrigg * weightAssoc); - } + weightAssoc = assoc.sign() < 0 ? getEfficiency(hEffXiMin, assoc.pt()) : getEfficiency(hEffXiPlus, assoc.pt()); + // if Omega-Xi, fill the Xi-Omega histogram (flip the trigger/assoc and dphy,dy signs) + registry.fill(HIST("hXiOm"), RecoDecay::constrainAngle(assoc.phi() - trigger.phi(), -PIHalf), -(trigger.yOmega() - assoc.yXi()), assoc.sign(), trigger.sign(), assoc.pt(), trigger.pt(), invMassXiAssoc, invMassOmTrigg, collision.posZ(), collision.multFT0M(), weightTrigg * weightAssoc); } - if (trigger.isSelected() >= 2 && TMath::Abs(trigger.yOmega()) < maxRapidity) { // trigger Omega + if (assoc.isSelected() >= 2 && TMath::Abs(assoc.yOmega()) < maxRapidity) { // assoc Omega if (doEfficiencyCorrection) - weightTrigg = trigger.sign() < 0 ? getEfficiency(hEffOmegaMin, trigger.pt()) : getEfficiency(hEffOmegaPlus, trigger.pt()); - if (assoc.isSelected() <= 2 && TMath::Abs(assoc.yXi()) < maxRapidity) { // assoc Xi - if (doEfficiencyCorrection) - weightAssoc = assoc.sign() < 0 ? getEfficiency(hEffXiMin, assoc.pt()) : getEfficiency(hEffXiPlus, assoc.pt()); - registry.fill(HIST("hOmXiSS"), dphi, trigger.yOmega() - assoc.yXi(), trigger.pt(), assoc.pt(), invMassOmTrigg, invMassXiAssoc, collision.posZ(), collision.multFT0M(), weightTrigg * weightAssoc); - } - if (assoc.isSelected() >= 2 && TMath::Abs(assoc.yOmega()) < maxRapidity) { // assoc Omega - if (doEfficiencyCorrection) - weightAssoc = assoc.sign() < 0 ? getEfficiency(hEffOmegaMin, assoc.pt()) : getEfficiency(hEffOmegaPlus, assoc.pt()); - registry.fill(HIST("hOmOmSS"), dphi, trigger.yOmega() - assoc.yOmega(), trigger.pt(), assoc.pt(), invMassOmTrigg, invMassOmAssoc, collision.posZ(), collision.multFT0M(), weightTrigg * weightAssoc); - } + weightAssoc = assoc.sign() < 0 ? getEfficiency(hEffOmegaMin, assoc.pt()) : getEfficiency(hEffOmegaPlus, assoc.pt()); + registry.fill(HIST("hOmOm"), dphi, trigger.yOmega() - assoc.yOmega(), trigger.sign(), assoc.sign(), trigger.pt(), assoc.pt(), invMassOmTrigg, invMassOmAssoc, collision.posZ(), collision.multFT0M(), weightTrigg * weightAssoc); } } + + // QA plots + if (trigger.sign() * assoc.sign() < 0) { + registry.fill(HIST("hDeltaPhiOS"), dphi); + } else { + registry.fill(HIST("hDeltaPhiSS"), dphi); + } } // correlations } // process same event @@ -936,6 +887,11 @@ struct CascadeCorrelations { continue; } + std::array triggerTracks = {trigger.posTrackId(), trigger.negTrackId(), trigger.bachelorId()}; + std::array assocTracks = {assoc.posTrackId(), assoc.negTrackId(), assoc.bachelorId()}; + if (autoCorrelation(triggerTracks, assocTracks)) + continue; + double dphi = RecoDecay::constrainAngle(trigger.phi() - assoc.phi(), -PIHalf); double invMassXiTrigg = trigger.mXi(); @@ -943,140 +899,45 @@ struct CascadeCorrelations { double invMassXiAssoc = assoc.mXi(); double invMassOmAssoc = assoc.mOmega(); - // V0 daughter track ID's used for autocorrelation check - int posIdTrigg = trigger.posTrackId(); - int negIdTrigg = trigger.negTrackId(); - int posIdAssoc = assoc.posTrackId(); - int negIdAssoc = assoc.negTrackId(); - double weightTrigg = 1.; double weightAssoc = 1.; - if (trigger.sign() * assoc.sign() < 0) { // opposite-sign - - // check for autocorrelations between mis-identified kaons (omega bach) and protons (lambda daughter) TODO: improve logic? - if (trigger.isSelected() >= 2) { - if (trigger.sign() > 0 && trigger.bachelorId() == posIdAssoc) { - // K+ from trigger Omega is the same as proton from assoc lambda - registry.fill(HIST("MixedEvents/hMEAutoCorrelationOS"), 1); - continue; - } - if (trigger.sign() < 0 && trigger.bachelorId() == negIdAssoc) { - // K- from trigger Omega is the same as antiproton from assoc antilambda - registry.fill(HIST("MixedEvents/hMEAutoCorrelationOS"), -1); - continue; - } - } - if (assoc.isSelected() >= 2) { - if (assoc.sign() > 0 && assoc.bachelorId() == posIdTrigg) { - // K+ from assoc Omega is the same as proton from trigger lambda - registry.fill(HIST("MixedEvents/hMEAutoCorrelationOS"), 1); - continue; - } - if (assoc.sign() < 0 && assoc.bachelorId() == negIdTrigg) { - // K- from assoc Omega is the same as antiproton from trigger antilambda - registry.fill(HIST("MixedEvents/hMEAutoCorrelationOS"), -1); - continue; - } - } - - registry.fill(HIST("MixedEvents/hMEDeltaPhiOS"), dphi); - - // Fill the different THnSparses depending on PID logic (important for rapidity & inv mass information) - if (trigger.isSelected() <= 2 && TMath::Abs(trigger.yXi()) < maxRapidity) { // trigger Xi + if (trigger.isSelected() <= 2 && TMath::Abs(trigger.yXi()) < maxRapidity) { // trigger Xi + if (doEfficiencyCorrection) + weightTrigg = trigger.sign() < 0 ? getEfficiency(hEffXiMin, trigger.pt()) : getEfficiency(hEffXiPlus, trigger.pt()); + if (assoc.isSelected() <= 2 && TMath::Abs(assoc.yXi()) < maxRapidity) { // assoc Xi if (doEfficiencyCorrection) - weightTrigg = trigger.sign() < 0 ? getEfficiency(hEffXiMin, trigger.pt()) : getEfficiency(hEffXiPlus, trigger.pt()); - if (assoc.isSelected() <= 2 && TMath::Abs(assoc.yXi()) < maxRapidity) { // assoc Xi - if (doEfficiencyCorrection) - weightAssoc = assoc.sign() < 0 ? getEfficiency(hEffXiMin, assoc.pt()) : getEfficiency(hEffXiPlus, assoc.pt()); - registry.fill(HIST("MixedEvents/hMEXiXiOS"), dphi, trigger.yXi() - assoc.yXi(), trigger.pt(), assoc.pt(), invMassXiTrigg, invMassXiAssoc, col1.posZ(), col1.multFT0M(), weightTrigg * weightAssoc); - } - if (assoc.isSelected() >= 2 && TMath::Abs(assoc.yOmega()) < maxRapidity) { // assoc Omega - if (doEfficiencyCorrection) - weightAssoc = assoc.sign() < 0 ? getEfficiency(hEffOmegaMin, assoc.pt()) : getEfficiency(hEffOmegaPlus, assoc.pt()); - registry.fill(HIST("MixedEvents/hMEXiOmOS"), dphi, trigger.yXi() - assoc.yOmega(), trigger.pt(), assoc.pt(), invMassXiTrigg, invMassOmAssoc, col1.posZ(), col1.multFT0M(), weightTrigg * weightAssoc); - } + weightAssoc = assoc.sign() < 0 ? getEfficiency(hEffXiMin, assoc.pt()) : getEfficiency(hEffXiPlus, assoc.pt()); + registry.fill(HIST("MixedEvents/hMEXiXi"), dphi, trigger.yXi() - assoc.yXi(), trigger.sign(), assoc.sign(), trigger.pt(), assoc.pt(), invMassXiTrigg, invMassXiAssoc, col1.posZ(), col1.multFT0M(), weightTrigg * weightAssoc); } - if (trigger.isSelected() >= 2 && TMath::Abs(trigger.yOmega()) < maxRapidity) { // trigger Omega + if (assoc.isSelected() >= 2 && TMath::Abs(assoc.yOmega()) < maxRapidity) { // assoc Omega if (doEfficiencyCorrection) - weightTrigg = trigger.sign() < 0 ? getEfficiency(hEffOmegaMin, trigger.pt()) : getEfficiency(hEffOmegaPlus, trigger.pt()); - if (assoc.isSelected() <= 2 && TMath::Abs(assoc.yXi()) < maxRapidity) { // assoc Xi - if (doEfficiencyCorrection) - weightAssoc = assoc.sign() < 0 ? getEfficiency(hEffXiMin, assoc.pt()) : getEfficiency(hEffXiPlus, assoc.pt()); - registry.fill(HIST("MixedEvents/hMEOmXiOS"), dphi, trigger.yOmega() - assoc.yXi(), trigger.pt(), assoc.pt(), invMassOmTrigg, invMassXiAssoc, col1.posZ(), col1.multFT0M(), weightTrigg * weightAssoc); - } - if (assoc.isSelected() >= 2 && TMath::Abs(assoc.yOmega()) < maxRapidity) { // assoc Omega - if (doEfficiencyCorrection) - weightAssoc = assoc.sign() < 0 ? getEfficiency(hEffOmegaMin, assoc.pt()) : getEfficiency(hEffOmegaPlus, assoc.pt()); - registry.fill(HIST("MixedEvents/hMEOmOmOS"), dphi, trigger.yOmega() - assoc.yOmega(), trigger.pt(), assoc.pt(), invMassOmTrigg, invMassOmAssoc, col1.posZ(), col1.multFT0M(), weightTrigg * weightAssoc); - } - } - } else { // same sign - // make sure to check for autocorrelations - only possible in same-sign correlations (if PID is correct) - if (posIdTrigg == posIdAssoc && negIdTrigg == negIdAssoc) { - // LOGF(info, "same v0 in SS correlation! %d %d", v0dataTrigg.v0Id(), v0dataAssoc.v0Id()); - registry.fill(HIST("MixedEvents/hMEAutoCorrelation"), 0); - continue; - } - int bachIdTrigg = trigger.bachelorId(); - int bachIdAssoc = assoc.bachelorId(); - - if (bachIdTrigg == bachIdAssoc) { - // LOGF(info, "same bachelor in SS correlation! %d %d", bachIdTrigg, bachIdAssoc); - registry.fill(HIST("MixedEvents/hMEAutoCorrelation"), 1); - continue; - } - // check for same tracks in v0's of cascades - if (negIdTrigg == negIdAssoc || posIdTrigg == posIdAssoc) { - // LOGF(info, "cascades have a v0-track in common in SS correlation!"); - registry.fill(HIST("MixedEvents/hMEAutoCorrelation"), 2); - continue; - } - if (trigger.sign() < 0) { // neg cascade - if (negIdTrigg == bachIdAssoc || negIdAssoc == bachIdTrigg) { - // LOGF(info, "bach of casc == v0-pion of other casc in neg SS correlation!"); - registry.fill(HIST("MixedEvents/hMEAutoCorrelation"), 3); - continue; - } - } else { // pos cascade - if (posIdTrigg == bachIdAssoc || posIdAssoc == bachIdTrigg) { - // LOGF(info, "bach of casc == v0-pion of other casc in pos SS correlation!"); - registry.fill(HIST("MixedEvents/hMEAutoCorrelation"), 3); - continue; - } + weightAssoc = assoc.sign() < 0 ? getEfficiency(hEffOmegaMin, assoc.pt()) : getEfficiency(hEffOmegaPlus, assoc.pt()); + registry.fill(HIST("MixedEvents/hMEXiOm"), dphi, trigger.yXi() - assoc.yOmega(), trigger.sign(), assoc.sign(), trigger.pt(), assoc.pt(), invMassXiTrigg, invMassOmAssoc, col1.posZ(), col1.multFT0M(), weightTrigg * weightAssoc); } - - registry.fill(HIST("MixedEvents/hMEDeltaPhiSS"), dphi); - - if (trigger.isSelected() <= 2 && TMath::Abs(trigger.yXi()) < maxRapidity) { // trigger Xi + } + if (trigger.isSelected() >= 2 && TMath::Abs(trigger.yOmega()) < maxRapidity) { // trigger Omega + if (doEfficiencyCorrection) + weightTrigg = trigger.sign() < 0 ? getEfficiency(hEffOmegaMin, trigger.pt()) : getEfficiency(hEffOmegaPlus, trigger.pt()); + if (assoc.isSelected() <= 2 && TMath::Abs(assoc.yXi()) < maxRapidity) { // assoc Xi if (doEfficiencyCorrection) - weightTrigg = trigger.sign() < 0 ? getEfficiency(hEffXiMin, trigger.pt()) : getEfficiency(hEffXiPlus, trigger.pt()); - if (assoc.isSelected() <= 2 && TMath::Abs(assoc.yXi()) < maxRapidity) { // assoc Xi - if (doEfficiencyCorrection) - weightAssoc = assoc.sign() < 0 ? getEfficiency(hEffXiMin, assoc.pt()) : getEfficiency(hEffXiPlus, assoc.pt()); - registry.fill(HIST("MixedEvents/hMEXiXiSS"), dphi, trigger.yXi() - assoc.yXi(), trigger.pt(), assoc.pt(), invMassXiTrigg, invMassXiAssoc, col1.posZ(), col1.multFT0M(), weightTrigg * weightAssoc); - } - if (assoc.isSelected() >= 2 && TMath::Abs(assoc.yOmega()) < maxRapidity) { // assoc Omega - if (doEfficiencyCorrection) - weightAssoc = assoc.sign() < 0 ? getEfficiency(hEffOmegaMin, assoc.pt()) : getEfficiency(hEffOmegaPlus, assoc.pt()); - registry.fill(HIST("MixedEvents/hMEXiOmSS"), dphi, trigger.yXi() - assoc.yOmega(), trigger.pt(), assoc.pt(), invMassXiTrigg, invMassOmAssoc, col1.posZ(), col1.multFT0M(), weightTrigg * weightAssoc); - } + weightAssoc = assoc.sign() < 0 ? getEfficiency(hEffXiMin, assoc.pt()) : getEfficiency(hEffXiPlus, assoc.pt()); + // if Omega-Xi, fill the Xi-Omega histogram (flip the trigger/assoc and dphy,dy signs) + registry.fill(HIST("MixedEvents/hMEXiOm"), RecoDecay::constrainAngle(assoc.phi() - trigger.phi(), -PIHalf), -(trigger.yOmega() - assoc.yXi()), assoc.sign(), trigger.sign(), assoc.pt(), trigger.pt(), invMassXiAssoc, invMassOmTrigg, col1.posZ(), col1.multFT0M(), weightTrigg * weightAssoc); } - if (trigger.isSelected() >= 2 && TMath::Abs(trigger.yOmega()) < maxRapidity) { // trigger Omega + if (assoc.isSelected() >= 2 && TMath::Abs(assoc.yOmega()) < maxRapidity) { // assoc Omega if (doEfficiencyCorrection) - weightTrigg = trigger.sign() < 0 ? getEfficiency(hEffOmegaMin, trigger.pt()) : getEfficiency(hEffOmegaPlus, trigger.pt()); - if (assoc.isSelected() <= 2 && TMath::Abs(assoc.yXi()) < maxRapidity) { // assoc Xi - if (doEfficiencyCorrection) - weightAssoc = assoc.sign() < 0 ? getEfficiency(hEffXiMin, assoc.pt()) : getEfficiency(hEffXiPlus, assoc.pt()); - registry.fill(HIST("MixedEvents/hMEOmXiSS"), dphi, trigger.yOmega() - assoc.yXi(), trigger.pt(), assoc.pt(), invMassOmTrigg, invMassXiAssoc, col1.posZ(), col1.multFT0M(), weightTrigg * weightAssoc); - } - if (assoc.isSelected() >= 2 && TMath::Abs(assoc.yOmega()) < maxRapidity) { // assoc Omega - if (doEfficiencyCorrection) - weightAssoc = assoc.sign() < 0 ? getEfficiency(hEffOmegaMin, assoc.pt()) : getEfficiency(hEffOmegaPlus, assoc.pt()); - registry.fill(HIST("MixedEvents/hMEOmOmSS"), dphi, trigger.yOmega() - assoc.yOmega(), trigger.pt(), assoc.pt(), invMassOmTrigg, invMassOmAssoc, col1.posZ(), col1.multFT0M(), weightTrigg * weightAssoc); - } + weightAssoc = assoc.sign() < 0 ? getEfficiency(hEffOmegaMin, assoc.pt()) : getEfficiency(hEffOmegaPlus, assoc.pt()); + registry.fill(HIST("MixedEvents/hMEOmOm"), dphi, trigger.yOmega() - assoc.yOmega(), trigger.sign(), assoc.sign(), trigger.pt(), assoc.pt(), invMassOmTrigg, invMassOmAssoc, col1.posZ(), col1.multFT0M(), weightTrigg * weightAssoc); } - } // same sign + } + + // QA plots + if (trigger.sign() * assoc.sign() < 0) { + registry.fill(HIST("MixedEvents/hMEDeltaPhiOS"), dphi); + } else { + registry.fill(HIST("MixedEvents/hMEDeltaPhiSS"), dphi); + } } // correlations } // collisions } // process mixed events From 4c9b2173d22f3421bdc61c762f63b5b46cb4efd9 Mon Sep 17 00:00:00 2001 From: EmilGorm <50658075+EmilGorm@users.noreply.github.com> Date: Wed, 25 Jun 2025 18:44:43 +0200 Subject: [PATCH 213/871] [PWGCF] Add dedicated light-ion GFW task (#11765) --- .../GenericFramework/Core/BootstrapProfile.h | 4 + PWGCF/GenericFramework/Core/FlowContainer.h | 4 + PWGCF/GenericFramework/Core/GFW.cxx | 13 +- PWGCF/GenericFramework/Core/GFW.h | 19 +- PWGCF/GenericFramework/Core/GFWCumulant.cxx | 10 +- PWGCF/GenericFramework/Core/GFWCumulant.h | 11 +- PWGCF/GenericFramework/Core/GFWPowerArray.h | 4 + PWGCF/GenericFramework/Core/ProfileSubset.h | 6 +- PWGCF/GenericFramework/Tasks/CMakeLists.txt | 5 + .../Tasks/flowGFWLightIons.cxx | 1196 +++++++++++++++++ .../Tasks/flowGenericFramework.cxx | 21 +- 11 files changed, 1244 insertions(+), 49 deletions(-) create mode 100644 PWGCF/GenericFramework/Tasks/flowGFWLightIons.cxx diff --git a/PWGCF/GenericFramework/Core/BootstrapProfile.h b/PWGCF/GenericFramework/Core/BootstrapProfile.h index a0dfde08509..829c58cc11a 100644 --- a/PWGCF/GenericFramework/Core/BootstrapProfile.h +++ b/PWGCF/GenericFramework/Core/BootstrapProfile.h @@ -9,6 +9,10 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. +/// \file BootstrapProfile.h/.cxx +/// \brief Derived class from TProfile that stores extra TProfiles for bootstrap samples +/// \author Emil Gorm Nielsen (ack. V. Vislavicius), NBI, emil.gorm.nielsen@cern.ch + #ifndef PWGCF_GENERICFRAMEWORK_CORE_BOOTSTRAPPROFILE_H_ #define PWGCF_GENERICFRAMEWORK_CORE_BOOTSTRAPPROFILE_H_ diff --git a/PWGCF/GenericFramework/Core/FlowContainer.h b/PWGCF/GenericFramework/Core/FlowContainer.h index 40a379e01a8..bb330c049b6 100644 --- a/PWGCF/GenericFramework/Core/FlowContainer.h +++ b/PWGCF/GenericFramework/Core/FlowContainer.h @@ -9,6 +9,10 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. +/// \file GFW.h/.cxx +/// \brief Container to store correlations and compute common cumulants +/// \author Emil Gorm Nielsen, NBI, emil.gorm.nielsen@cern.ch + #ifndef PWGCF_GENERICFRAMEWORK_CORE_FLOWCONTAINER_H_ #define PWGCF_GENERICFRAMEWORK_CORE_FLOWCONTAINER_H_ #include diff --git a/PWGCF/GenericFramework/Core/GFW.cxx b/PWGCF/GenericFramework/Core/GFW.cxx index 1541aaf8993..350fe752156 100644 --- a/PWGCF/GenericFramework/Core/GFW.cxx +++ b/PWGCF/GenericFramework/Core/GFW.cxx @@ -9,16 +9,13 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -/* -Author: Vytautas Vislavicius -Extention of Generic Flow (https://arxiv.org/abs/1312.3572 by A. Bilandzic et al.) -Class steers the initialization and calculation of n-particle correlations. Uses recursive function, all terms are calculated only once. -Latest version includes the calculation of any number of gaps and any combination of harmonics (including eg symmetric cumulants, etc.) -If used, modified, or distributed, please aknowledge the author of this code. -*/ - #include "GFW.h" +#include +#include +#include +#include + using std::complex; using std::pair; using std::string; diff --git a/PWGCF/GenericFramework/Core/GFW.h b/PWGCF/GenericFramework/Core/GFW.h index 629731bea85..8ec2b78d095 100644 --- a/PWGCF/GenericFramework/Core/GFW.h +++ b/PWGCF/GenericFramework/Core/GFW.h @@ -9,23 +9,22 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -/* -Author: Vytautas Vislavicius -Extention of Generic Flow (https://arxiv.org/abs/1312.3572 by A. Bilandzic et al.) -Class steers the initialization and calculation of n-particle correlations. Uses recursive function, all terms are calculated only once. -Latest version includes the calculation of any number of gaps and any combination of harmonics (including eg symmetric cumulants, etc.) -If used, modified, or distributed, please aknowledge the author of this code. -*/ +/// \file GFW.h/.cxx +/// \brief Class steers the initialization and calculation of n-particle correlations. Uses recursive function, all terms are calculated only once. +/// \author Emil Gorm Nielsen (ack. V. Vislavicius), NBI, emil.gorm.nielsen@cern.ch + #ifndef PWGCF_GENERICFRAMEWORK_CORE_GFW_H_ #define PWGCF_GENERICFRAMEWORK_CORE_GFW_H_ #include "GFWCumulant.h" #include "GFWPowerArray.h" -#include -#include -#include + #include #include +#include +#include +#include +#include class GFW { diff --git a/PWGCF/GenericFramework/Core/GFWCumulant.cxx b/PWGCF/GenericFramework/Core/GFWCumulant.cxx index a82e3bcd08b..f27da24bd27 100644 --- a/PWGCF/GenericFramework/Core/GFWCumulant.cxx +++ b/PWGCF/GenericFramework/Core/GFWCumulant.cxx @@ -9,16 +9,10 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -/* -Author: Vytautas Vislavicius -Extention of Generic Flow (https://arxiv.org/abs/1312.3572 by A. Bilandzic et al.) -A part of -A container to store Q vectors for one subevent with an extra layer to recursively calculate particle correlations. -If used, modified, or distributed, please aknowledge the author of this code. -*/ - #include "GFWCumulant.h" +#include + using std::complex; using std::vector; diff --git a/PWGCF/GenericFramework/Core/GFWCumulant.h b/PWGCF/GenericFramework/Core/GFWCumulant.h index f8cf6624542..2567a2e9c4a 100644 --- a/PWGCF/GenericFramework/Core/GFWCumulant.h +++ b/PWGCF/GenericFramework/Core/GFWCumulant.h @@ -9,13 +9,10 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -/* -Author: Vytautas Vislavicius -Extention of Generic Flow (https://arxiv.org/abs/1312.3572 by A. Bilandzic et al.) -A part of -A container to store Q vectors for one subevent with an extra layer to recursively calculate particle correlations. -If used, modified, or distributed, please aknowledge the author of this code. -*/ +/// \file GFWCumulant.h/.cxx +/// \brief A container to store Q vectors for one subevent with an extra layer to recursively calculate particle correlations. +/// \author Emil Gorm Nielsen (ack. V. Vislavicius), NBI, emil.gorm.nielsen@cern.ch + #ifndef PWGCF_GENERICFRAMEWORK_CORE_GFWCUMULANT_H_ #define PWGCF_GENERICFRAMEWORK_CORE_GFWCUMULANT_H_ diff --git a/PWGCF/GenericFramework/Core/GFWPowerArray.h b/PWGCF/GenericFramework/Core/GFWPowerArray.h index 82314374e00..ba38f2fcc54 100644 --- a/PWGCF/GenericFramework/Core/GFWPowerArray.h +++ b/PWGCF/GenericFramework/Core/GFWPowerArray.h @@ -9,6 +9,10 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. +/// \file GFWPowerArray.h/.cxx +/// \brief Class to compute necessary powers of Q-vectors based on input correlations +/// \author Emil Gorm Nielsen, NBI, emil.gorm.nielsen@cern.ch + #ifndef PWGCF_GENERICFRAMEWORK_CORE_GFWPOWERARRAY_H_ #define PWGCF_GENERICFRAMEWORK_CORE_GFWPOWERARRAY_H_ diff --git a/PWGCF/GenericFramework/Core/ProfileSubset.h b/PWGCF/GenericFramework/Core/ProfileSubset.h index 3d749e06b0e..fc920b898c4 100644 --- a/PWGCF/GenericFramework/Core/ProfileSubset.h +++ b/PWGCF/GenericFramework/Core/ProfileSubset.h @@ -9,9 +9,13 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. +/// \file ProfileSubset.h/.cxx +/// \brief // Helper class to select a subrange of a TProfile +/// \author Emil Gorm Nielsen (ack. V. Vislavicius), NBI, emil.gorm.nielsen@cern.ch + #ifndef PWGCF_GENERICFRAMEWORK_CORE_PROFILESUBSET_H_ #define PWGCF_GENERICFRAMEWORK_CORE_PROFILESUBSET_H_ -// Helper function to select a subrange of a TProfile + #include "TProfile.h" #include "TProfile2D.h" #include "TError.h" diff --git a/PWGCF/GenericFramework/Tasks/CMakeLists.txt b/PWGCF/GenericFramework/Tasks/CMakeLists.txt index ee71394c4cb..80f9072b932 100644 --- a/PWGCF/GenericFramework/Tasks/CMakeLists.txt +++ b/PWGCF/GenericFramework/Tasks/CMakeLists.txt @@ -13,3 +13,8 @@ o2physics_add_dpl_workflow(flow-generic-framework SOURCES flowGenericFramework.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::GFWCore COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(flow-gfw-light-ions + SOURCES flowGFWLightIons.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::GFWCore + COMPONENT_NAME Analysis) diff --git a/PWGCF/GenericFramework/Tasks/flowGFWLightIons.cxx b/PWGCF/GenericFramework/Tasks/flowGFWLightIons.cxx new file mode 100644 index 00000000000..8ed63475f1c --- /dev/null +++ b/PWGCF/GenericFramework/Tasks/flowGFWLightIons.cxx @@ -0,0 +1,1196 @@ +// 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 flowGFWLightIons.cxx +/// \brief Dedicated GFW task to analyse angular correlations in light-ion collision systems +/// \author Emil Gorm Nielsen, NBI, emil.gorm.nielsen@cern.ch + +#include "FlowContainer.h" +#include "FlowPtContainer.h" +#include "GFW.h" +#include "GFWConfig.h" +#include "GFWCumulant.h" +#include "GFWPowerArray.h" +#include "GFWWeights.h" +#include "GFWWeightsList.h" + +#include "Common/Core/TrackSelection.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/RunningWorkflowInfo.h" +#include "Framework/runDataProcessing.h" +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +using namespace o2; +using namespace o2::framework; + +#define O2_DEFINE_CONFIGURABLE(NAME, TYPE, DEFAULT, HELP) Configurable NAME{#NAME, DEFAULT, HELP}; + +namespace o2::analysis::gfw +{ +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}; +float ptpoilow = 0.2, ptpoiup = 10.0; +float ptreflow = 0.2, ptrefup = 3.0; +float ptlow = 0.2, ptup = 10.0; +int etabins = 16; +float etalow = -0.8, etaup = 0.8; +int vtxZbins = 40; +float vtxZlow = -10.0, vtxZup = 10.0; +int phibins = 72; +float philow = 0.0; +float phiup = o2::constants::math::TwoPI; +int nchbins = 300; +float nchlow = 0; +float nchup = 3000; +std::vector centbinning(90); +int nBootstrap = 10; +GFWRegions regions; +GFWCorrConfigs configs; +std::vector multGlobalCorrCutPars; +std::vector multPVCorrCutPars; +} // namespace o2::analysis::gfw + +struct FlowGfwLightIons { + + O2_DEFINE_CONFIGURABLE(cfgNbootstrap, int, 10, "Number of subsamples") + O2_DEFINE_CONFIGURABLE(cfgMpar, int, 4, "Highest order of pt-pt correlations") + O2_DEFINE_CONFIGURABLE(cfgCentEstimator, int, 0, "0:FT0C; 1:FT0CVariant1; 2:FT0M; 3:FT0A") + O2_DEFINE_CONFIGURABLE(cfgUseNch, bool, false, "Do correlations as function of Nch") + 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(cfgUseAdditionalEventCut, 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(cfgEfficiency, std::string, "", "CCDB path to efficiency object") + O2_DEFINE_CONFIGURABLE(cfgAcceptance, std::string, "", "CCDB path to acceptance object") + O2_DEFINE_CONFIGURABLE(cfgDCAxyNSigma, float, 7, "Cut on number of sigma deviations from expected DCA in the transverse direction"); + 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"); + O2_DEFINE_CONFIGURABLE(cfgMinNITSCls, float, 5, "Cut on minimum number of ITS clusters found"); + O2_DEFINE_CONFIGURABLE(cfgChi2PrITSCls, float, 36, "Cut on chi^2 per ITS clusters found"); + O2_DEFINE_CONFIGURABLE(cfgChi2PrTPCCls, float, 2.5, "Cut on chi^2 per TPC clusters found"); + O2_DEFINE_CONFIGURABLE(cfgPtmin, float, 0.2, "minimum pt (GeV/c)"); + O2_DEFINE_CONFIGURABLE(cfgPtmax, float, 10, "maximum pt (GeV/c)"); + O2_DEFINE_CONFIGURABLE(cfgEta, float, 0.8, "eta cut"); + O2_DEFINE_CONFIGURABLE(cfgEtaPtPt, float, 0.4, "eta cut for pt-pt correlations"); + O2_DEFINE_CONFIGURABLE(cfgVtxZ, float, 10, "vertex cut (cm)"); + O2_DEFINE_CONFIGURABLE(cfgOccupancySelection, int, 2000, "Max occupancy selection, -999 to disable"); + 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(cfgDoOccupancySel, bool, true, "Bool for event selection on detector occupancy"); + O2_DEFINE_CONFIGURABLE(cfgMultCut, bool, true, "Use additional event cut on mult correlations"); + O2_DEFINE_CONFIGURABLE(cfgTVXinTRD, bool, true, "Use kTVXinTRD (reject TRD triggered events)"); + O2_DEFINE_CONFIGURABLE(cfgIsVertexITSTPC, bool, true, "Selects collisions with at least one ITS-TPC track"); + O2_DEFINE_CONFIGURABLE(cfgMagField, float, 99999, "Configurable magnetic field; default CCDB will be queried"); + O2_DEFINE_CONFIGURABLE(cfgUseDensityDependentCorrection, bool, false, "Use density dependent efficiency correction based on Run 2 measurements"); + Configurable> cfgTrackDensityP0{"cfgTrackDensityP0", std::vector{0.7217476707, 0.7384792571, 0.7542625668, 0.7640680200, 0.7701951667, 0.7755299053, 0.7805901710, 0.7849446786, 0.7957356586, 0.8113039262, 0.8211968966, 0.8280558878, 0.8329342135}, "parameter 0 for track density efficiency correction"}; + Configurable> cfgTrackDensityP1{"cfgTrackDensityP1", std::vector{-2.169488e-05, -2.191913e-05, -2.295484e-05, -2.556538e-05, -2.754463e-05, -2.816832e-05, -2.846502e-05, -2.843857e-05, -2.705974e-05, -2.477018e-05, -2.321730e-05, -2.203315e-05, -2.109474e-05}, "parameter 1 for track density efficiency correction"}; + Configurable> cfgMultGlobalCutPars{"cfgMultGlobalCutPars", std::vector{2272.16, -76.6932, 1.01204, -0.00631545, 1.59868e-05, 136.336, -4.97006, 0.121199, -0.0015921, 7.66197e-06}, "Global multiplicity cut parameter values"}; + Configurable> cfgMultPVCutPars{"cfgMultPVCutPars", std::vector{3074.43, -106.192, 1.46176, -0.00968364, 2.61923e-05, 182.128, -7.43492, 0.193901, -0.00256715, 1.22594e-05}, "PV multiplicity cut parameter values"}; + O2_DEFINE_CONFIGURABLE(cfgMultCorrHighCutFunction, 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"); + O2_DEFINE_CONFIGURABLE(cfgMultCorrLowCutFunction, 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"); + + Configurable cfgGFWBinning{"cfgGFWBinning", {40, 16, 72, 300, 0, 3000, 0.2, 10.0, 0.2, 3.0, {0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1, 1.25, 1.5, 1.75, 2, 2.25, 2.5, 2.75, 3, 3.25, 3.5, 3.75, 4, 4.5, 5, 5.5, 6, 7, 8, 9, 10}, {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, 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}}, "Configuration for binning"}; + Configurable cfgRegions{"cfgRegions", {{"refN", "refP", "refFull"}, {-0.8, 0.4, -0.8}, {-0.4, 0.8, 0.8}, {0, 0, 0}, {1, 1, 1}}, "Configurations for GFW regions"}; + + Configurable cfgCorrConfig{"cfgCorrConfig", {{"refP {2} refN {-2}", "refP {3} refN {-3}", "refP {4} refN {-4}", "refFull {2 -2}", "refFull {2 2 -2 -2}"}, {"ChGap22", "ChGap32", "ChGap42", "ChFull22", "ChFull24"}, {0, 0, 0, 0, 0}, {15, 1, 1, 0, 0}}, "Configurations for each correlation to calculate"}; + + // Connect to ccdb + Service ccdb; + + struct Config { + TH1D* mEfficiency = nullptr; + GFWWeights* mAcceptance; + bool correctionsLoaded = false; + } cfg; + + // Define output + OutputObj fFC{FlowContainer("FlowContainer")}; + OutputObj fFCpt{FlowPtContainer("FlowPtContainer")}; + OutputObj fFCgen{FlowContainer("FlowContainer_gen")}; + OutputObj fFCptgen{FlowPtContainer("FlowPtContainer_gen")}; + HistogramRegistry registry{"registry"}; + + // QA outputs + std::map>> th1sList; + std::map>> th3sList; + enum OutputTH1Names { + hPhi = 0, + hEta, + hVtxZ, + hMult, + hCent, + hEventSel, + kCount_TH1Names + }; + // NUA outputs + enum OutputTH3Names { + hNUAref = 0, + kCount_TH3Names + }; + enum CentEstimators { + kCentFT0C = 0, + kCentFT0CVariant1, + kCentFT0M, + kCentFV0A, + kCentNTPV + }; + + // Define global variables + // Generic Framework + GFW* fGFW = new GFW(); + std::vector corrconfigs; + + TRandom3* fRndm = new TRandom3(0); + TAxis* fPtAxis; + int lastRun = -1; + std::vector runNumbers; + + // Density dependent eff correction + std::vector funcEff; + TH1D* hFindPtBin; + TF1* funcV2; + TF1* funcV3; + TF1* funcV4; + struct DensityCorr { + double psi2Est; + double psi3Est; + double psi4Est; + double v2; + double v3; + double v4; + int density; + DensityCorr() : psi2Est(0.), psi3Est(0.), psi4Est(0.), v2(0.), v3(0.), v4(0.), density(0) {} + }; + + // Event selection cuts - Alex + TF1* fMultPVCutLow = nullptr; + TF1* fMultPVCutHigh = nullptr; + TF1* fMultCutLow = nullptr; + TF1* fMultCutHigh = nullptr; + + o2::framework::expressions::Filter collisionFilter = nabs(aod::collision::posZ) < cfgVtxZ; + o2::framework::expressions::Filter trackFilter = nabs(aod::track::eta) < cfgEta && aod::track::pt > cfgPtmin&& aod::track::pt < cfgPtmax && ((requireGlobalTrackInFilter()) || (aod::track::isGlobalTrackSDD == (uint8_t) true)) && (aod::track::itsChi2NCl < cfgChi2PrITSCls) && (aod::track::tpcChi2NCl < cfgChi2PrTPCCls) && nabs(aod::track::dcaZ) < cfgDCAz; + + Preslice perCollision = aod::track::collisionId; + o2::framework::expressions::Filter mcCollFilter = nabs(aod::mccollision::posZ) < cfgVtxZ; + o2::framework::expressions::Filter mcParticlesFilter = (aod::mcparticle::eta > o2::analysis::gfw::etalow && aod::mcparticle::eta < o2::analysis::gfw::etaup && aod::mcparticle::pt > o2::analysis::gfw::ptlow && aod::mcparticle::pt < o2::analysis::gfw::ptup); + + using GFWTracks = soa::Filtered>; + + void init(InitContext const&) + { + LOGF(info, "flowGFWLightIons::init()"); + o2::analysis::gfw::regions.SetNames(cfgRegions->GetNames()); + o2::analysis::gfw::regions.SetEtaMin(cfgRegions->GetEtaMin()); + o2::analysis::gfw::regions.SetEtaMax(cfgRegions->GetEtaMax()); + o2::analysis::gfw::regions.SetpTDifs(cfgRegions->GetpTDifs()); + o2::analysis::gfw::regions.SetBitmasks(cfgRegions->GetBitmasks()); + o2::analysis::gfw::configs.SetCorrs(cfgCorrConfig->GetCorrs()); + o2::analysis::gfw::configs.SetHeads(cfgCorrConfig->GetHeads()); + o2::analysis::gfw::configs.SetpTDifs(cfgCorrConfig->GetpTDifs()); + o2::analysis::gfw::configs.SetpTCorrMasks(cfgCorrConfig->GetpTCorrMasks()); + o2::analysis::gfw::regions.Print(); + o2::analysis::gfw::configs.Print(); + o2::analysis::gfw::ptbinning = cfgGFWBinning->GetPtBinning(); + o2::analysis::gfw::ptpoilow = cfgGFWBinning->GetPtPOImin(); + o2::analysis::gfw::ptpoiup = cfgGFWBinning->GetPtPOImax(); + o2::analysis::gfw::ptreflow = cfgGFWBinning->GetPtRefMin(); + o2::analysis::gfw::ptrefup = cfgGFWBinning->GetPtRefMax(); + o2::analysis::gfw::ptlow = cfgPtmin; + o2::analysis::gfw::ptup = cfgPtmax; + o2::analysis::gfw::etabins = cfgGFWBinning->GetEtaBins(); + o2::analysis::gfw::vtxZbins = cfgGFWBinning->GetVtxZbins(); + o2::analysis::gfw::phibins = cfgGFWBinning->GetPhiBins(); + o2::analysis::gfw::philow = 0.0f; + o2::analysis::gfw::phiup = o2::constants::math::TwoPI; + o2::analysis::gfw::nchbins = cfgGFWBinning->GetNchBins(); + o2::analysis::gfw::nchlow = cfgGFWBinning->GetNchMin(); + o2::analysis::gfw::nchup = cfgGFWBinning->GetNchMax(); + o2::analysis::gfw::centbinning = cfgGFWBinning->GetCentBinning(); + cfgGFWBinning->Print(); + o2::analysis::gfw::multGlobalCorrCutPars = cfgMultGlobalCutPars; + o2::analysis::gfw::multPVCorrCutPars = cfgMultPVCutPars; + + AxisSpec phiAxis = {o2::analysis::gfw::phibins, o2::analysis::gfw::philow, o2::analysis::gfw::phiup, "#phi"}; + AxisSpec etaAxis = {o2::analysis::gfw::etabins, -cfgEta, cfgEta, "#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; + switch (cfgCentEstimator) { + case kCentFT0C: + sCentralityEstimator = "FT0C"; + break; + case kCentFT0CVariant1: + sCentralityEstimator = "FT0C variant 1"; + break; + case kCentFT0M: + sCentralityEstimator = "FT0M"; + break; + case kCentFV0A: + sCentralityEstimator = "FV0A"; + break; + case kCentNTPV: + sCentralityEstimator = "NTPV"; + break; + default: + sCentralityEstimator = "FT0C"; + } + sCentralityEstimator += " centrality (%)"; + AxisSpec centAxis = {o2::analysis::gfw::centbinning, sCentralityEstimator.c_str()}; + std::vector nchbinning; + int nchskip = (o2::analysis::gfw::nchup - o2::analysis::gfw::nchlow) / o2::analysis::gfw::nchbins; + for (int i = 0; i <= o2::analysis::gfw::nchbins; ++i) { + nchbinning.push_back(nchskip * i + o2::analysis::gfw::nchlow + 0.5); + } + AxisSpec nchAxis = {nchbinning, "N_{ch}"}; + AxisSpec bAxis = {200, 0, 20, "#it{b}"}; + AxisSpec t0cAxis = {70, 0, 70000, "N_{ch} (T0C)"}; + AxisSpec t0aAxis = {200, 0, 200, "N_{ch} (T0A)"}; + AxisSpec v0aAxis = {200, 0, 200, "N_{ch} (V0A)"}; + AxisSpec multpvAxis = {4000, 0, 4000, "N_{ch} (PV)"}; + AxisSpec multAxis = (doprocessOnTheFly && !cfgUseNch) ? bAxis : (cfgUseNch) ? nchAxis + : centAxis; + AxisSpec dcaZAXis = {200, -2, 2, "DCA_{z} (cm)"}; + AxisSpec dcaXYAXis = {200, -1, 1, "DCA_{xy} (cm)"}; + ccdb->setURL("http://alice-ccdb.cern.ch"); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + + int64_t now = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); + ccdb->setCreatedNotAfter(now); + + int ptbins = o2::analysis::gfw::ptbinning.size() - 1; + fPtAxis = new TAxis(ptbins, &o2::analysis::gfw::ptbinning[0]); + + if (doprocessMCGen || doprocessMCGenNoCent || doprocessOnTheFly) { + registry.add("MCGen/trackQA/nch_pt", "#it{p}_{T} vs multiplicity; N_{ch}; #it{p}_{T}", {HistType::kTH2D, {nchAxis, {100, o2::analysis::gfw::ptpoilow, o2::analysis::gfw::ptpoiup}}}); + registry.add("MCGen/trackQA/phi_eta_vtxZ", "", {HistType::kTH3D, {phiAxis, etaAxis, vtxAxis}}); + registry.add("MCGen/trackQA/pt_ref", "Reference #it{p}_{T}; #it{p}_{T}; Counts", {HistType::kTH1D, {{100, o2::analysis::gfw::ptreflow, o2::analysis::gfw::ptrefup}}}); + registry.add("MCGen/trackQA/pt_poi", "POI #it{p}_{T}; #it{p}_{T}; Counts", {HistType::kTH1D, {{100, o2::analysis::gfw::ptpoilow, o2::analysis::gfw::ptpoiup}}}); + if (doprocessOnTheFly) + registry.add("MCGen/impactParameter", "", {HistType::kTH2D, {{bAxis, nchAxis}}}); + + registry.add("MCGen/eventQA/multiplicity", "", {HistType::kTH1D, {nchAxis}}); + if (doprocessMCGen) + registry.add("MCGen/eventQA/centrality", "", {HistType::kTH1D, {centAxis}}); + } + if (doprocessMCReco || doprocessData || doprocessDataNoCent || doprocessMCRecoNoCent) { + registry.add("trackQA/before/phi_eta_vtxZ", "", {HistType::kTH3D, {phiAxis, etaAxis, vtxAxis}}); + registry.add("trackQA/before/pt_dcaXY_dcaZ", "", {HistType::kTH3D, {ptAxis, dcaXYAXis, dcaZAXis}}); + registry.add("trackQA/before/nch_pt", "#it{p}_{T} vs multiplicity; N_{ch}; #it{p}_{T}", {HistType::kTH2D, {nchAxis, {100, o2::analysis::gfw::ptpoilow, o2::analysis::gfw::ptpoiup}}}); + registry.add("trackQA/before/chi2prTPCcls", "#chi^{2}/cluster for the TPC track segment; #chi^{2}/TPC cluster", {HistType::kTH1D, {{100, 0., 5.}}}); + registry.add("trackQA/before/chi2prITScls", "#chi^{2}/cluster for the ITS track; #chi^{2}/ITS cluster", {HistType::kTH1D, {{100, 0., 50.}}}); + registry.add("trackQA/before/nTPCClusters", "Number of found TPC clusters; TPC N_{cls}; Counts", {HistType::kTH1D, {{100, 40, 180}}}); + registry.add("trackQA/before/nITSClusters", "Number of found ITS clusters; ITS N_{cls}; Counts", {HistType::kTH1D, {{100, 0, 20}}}); + registry.add("trackQA/before/nTPCCrossedRows", "Number of crossed TPC Rows; TPC X-rows; Counts", {HistType::kTH1D, {{100, 40, 180}}}); + + registry.addClone("trackQA/before/", "trackQA/after/"); + registry.add("trackQA/after/pt_ref", "", {HistType::kTH1D, {{100, o2::analysis::gfw::ptreflow, o2::analysis::gfw::ptrefup}}}); + registry.add("trackQA/after/pt_poi", "", {HistType::kTH1D, {{100, o2::analysis::gfw::ptpoilow, o2::analysis::gfw::ptpoiup}}}); + + registry.add("eventQA/before/multiplicity", "", {HistType::kTH1D, {nchAxis}}); + registry.add("eventQA/before/globalTracks_PVTracks", "", {HistType::kTH2D, {multpvAxis, nchAxis}}); + registry.add("eventQA/before/globalTracks_multT0A", "", {HistType::kTH2D, {t0aAxis, nchAxis}}); + registry.add("eventQA/before/globalTracks_multV0A", "", {HistType::kTH2D, {v0aAxis, nchAxis}}); + registry.add("eventQA/before/multV0A_multT0A", "", {HistType::kTH2D, {t0aAxis, v0aAxis}}); + + if (doprocessData || doprocessMCReco) { + registry.add("eventQA/before/centrality", "", {HistType::kTH1D, {centAxis}}); + registry.add("eventQA/before/globalTracks_centT0C", "", {HistType::kTH2D, {centAxis, nchAxis}}); + registry.add("eventQA/before/PVTracks_centT0C", "", {HistType::kTH2D, {centAxis, multpvAxis}}); + registry.add("eventQA/before/multT0C_centT0C", "", {HistType::kTH2D, {centAxis, t0cAxis}}); + } + + registry.addClone("eventQA/before/", "eventQA/after/"); + registry.add("eventQA/eventSel", "Number of Events;; Counts", {HistType::kTH1D, {{11, 0, 11}}}); + registry.get(HIST("eventQA/eventSel"))->GetXaxis()->SetBinLabel(1, "Filtered event"); + registry.get(HIST("eventQA/eventSel"))->GetXaxis()->SetBinLabel(2, "sel8"); + registry.get(HIST("eventQA/eventSel"))->GetXaxis()->SetBinLabel(3, "occupancy"); + registry.get(HIST("eventQA/eventSel"))->GetXaxis()->SetBinLabel(4, "kTVXinTRD"); + registry.get(HIST("eventQA/eventSel"))->GetXaxis()->SetBinLabel(5, "kNoSameBunchPileup"); + registry.get(HIST("eventQA/eventSel"))->GetXaxis()->SetBinLabel(6, "kIsGoodZvtxFT0vsPV"); + registry.get(HIST("eventQA/eventSel"))->GetXaxis()->SetBinLabel(7, "kNoCollInTimeRangeStandard"); + registry.get(HIST("eventQA/eventSel"))->GetXaxis()->SetBinLabel(8, "kIsVertexITSTPC"); + registry.get(HIST("eventQA/eventSel"))->GetXaxis()->SetBinLabel(9, "kIsGoodITSLayersAll"); + registry.get(HIST("eventQA/eventSel"))->GetXaxis()->SetBinLabel(10, "after Mult cuts"); + registry.get(HIST("eventQA/eventSel"))->GetXaxis()->SetBinLabel(11, "has track + within cent"); + + if (!cfgRunByRun) { + registry.add("phi_eta_vtxz_ref", "", {HistType::kTH3D, {phiAxis, etaAxis, vtxAxis}}); + } + } + + 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) { + fGFW->AddRegion(o2::analysis::gfw::regions.GetNames()[i], o2::analysis::gfw::regions.GetEtaMin()[i], o2::analysis::gfw::regions.GetEtaMax()[i], (o2::analysis::gfw::regions.GetpTDifs()[i]) ? ptbins + 1 : 1, o2::analysis::gfw::regions.GetBitmasks()[i]); + } + for (auto i = 0; i < o2::analysis::gfw::configs.GetSize(); ++i) { + corrconfigs.push_back(fGFW->GetCorrelatorConfig(o2::analysis::gfw::configs.GetCorrs()[i], o2::analysis::gfw::configs.GetHeads()[i], o2::analysis::gfw::configs.GetpTDifs()[i])); + } + if (corrconfigs.empty()) + LOGF(error, "Configuration contains vectors of different size - check the GFWCorrConfig configurable"); + fGFW->CreateRegions(); + TObjArray* oba = new TObjArray(); + addConfigObjectsToObjArray(oba, corrconfigs); + if (doprocessData || doprocessMCReco || doprocessDataNoCent || doprocessMCRecoNoCent) { + fFC->SetName("FlowContainer"); + fFC->SetXAxis(fPtAxis); + fFC->Initialize(oba, multAxis, cfgNbootstrap); + } + if (doprocessMCGen || doprocessMCGenNoCent || doprocessOnTheFly) { + fFCgen->SetName("FlowContainer_gen"); + fFCgen->SetXAxis(fPtAxis); + fFCgen->Initialize(oba, multAxis, cfgNbootstrap); + } + delete oba; + fFCpt->setUseCentralMoments(cfgUseCentralMoments); + fFCpt->setUseGapMethod(true); + fFCpt->initialise(multAxis, cfgMpar, o2::analysis::gfw::configs, cfgNbootstrap); + fFCptgen->setUseCentralMoments(cfgUseCentralMoments); + fFCptgen->setUseGapMethod(true); + fFCptgen->initialise(multAxis, cfgMpar, o2::analysis::gfw::configs, cfgNbootstrap); + if (cfgUseAdditionalEventCut) { + fMultPVCutLow = new TF1("fMultPVCutLow", cfgMultCorrLowCutFunction->c_str(), 0, 100); + fMultPVCutLow->SetParameters(&(o2::analysis::gfw::multPVCorrCutPars[0])); + fMultPVCutHigh = new TF1("fMultPVCutHigh", cfgMultCorrHighCutFunction->c_str(), 0, 100); + fMultPVCutHigh->SetParameters(&(o2::analysis::gfw::multPVCorrCutPars[0])); + fMultCutLow = new TF1("fMultCutLow", cfgMultCorrLowCutFunction->c_str(), 0, 100); + fMultCutLow->SetParameters(&(o2::analysis::gfw::multGlobalCorrCutPars[0])); + fMultCutHigh = new TF1("fMultCutHigh", cfgMultCorrHighCutFunction->c_str(), 0, 100); + fMultCutHigh->SetParameters(&(o2::analysis::gfw::multGlobalCorrCutPars[0])); + } + if (cfgUseDensityDependentCorrection) { + 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]); + funcEff.resize(pTEffBins.size() - 1); + // LHC24g3 Eff + std::vector f1p0 = cfgTrackDensityP0; + std::vector f1p1 = cfgTrackDensityP1; + for (uint ifunc = 0; ifunc < pTEffBins.size() - 1; ifunc++) { + funcEff[ifunc] = new TF1(Form("funcEff%i", ifunc), "[0]+[1]*x", 0, 3000); + funcEff[ifunc]->SetParameters(f1p0[ifunc], f1p1[ifunc]); + } + funcV2 = new TF1("funcV2", "[0]+[1]*x+[2]*x*x+[3]*x*x*x+[4]*x*x*x*x", 0, 100); + funcV2->SetParameters(0.0186111, 0.00351907, -4.38264e-05, 1.35383e-07, -3.96266e-10); + funcV3 = new TF1("funcV3", "[0]+[1]*x+[2]*x*x+[3]*x*x*x+[4]*x*x*x*x", 0, 100); + funcV3->SetParameters(0.0174056, 0.000703329, -1.45044e-05, 1.91991e-07, -1.62137e-09); + 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); + } + } + + static constexpr std::string_view FillTimeName[] = {"before/", "after/"}; + + enum QAFillTime { + kBefore, + kAfter + }; + + void addConfigObjectsToObjArray(TObjArray* oba, const std::vector& configs) + { + for (auto it = configs.begin(); it != configs.end(); ++it) { + if (it->pTDif) { + std::string suffix = "_ptDiff"; + for (auto i = 0; i < fPtAxis->GetNbins(); ++i) { + std::string index = Form("_pt_%i", i + 1); + oba->Add(new TNamed(it->Head.c_str() + index, it->Head.c_str() + suffix)); + } + } else { + oba->Add(new TNamed(it->Head.c_str(), it->Head.c_str())); + } + } + } + + int getMagneticField(uint64_t timestamp) + { + static o2::parameters::GRPMagField* grpo = nullptr; + if (grpo == nullptr) { + // grpo = ccdb->getForTimeStamp("GLO/GRP/GRP", timestamp); + grpo = ccdb->getForTimeStamp("GLO/Config/GRPMagField", timestamp); + if (grpo == nullptr) { + LOGF(fatal, "GRP object not found for timestamp %llu", timestamp); + return 0; + } + LOGF(info, "Retrieved GRP for timestamp %llu with magnetic field of %d kG", timestamp, grpo->getNominalL3Field()); + } + return grpo->getNominalL3Field(); + } + + void loadCorrections(aod::BCsWithTimestamps::iterator const& bc) + { + uint64_t timestamp = bc.timestamp(); + if (!cfgRunByRun && cfg.correctionsLoaded) + return; + if (!cfgAcceptance.value.empty()) { + std::string runstr = (cfgRunByRun) ? "RunByRun/" : ""; + cfg.mAcceptance = ccdb->getForTimeStamp(cfgAcceptance.value + runstr, timestamp); + } + if (!cfgEfficiency.value.empty()) { + cfg.mEfficiency = ccdb->getForTimeStamp(cfgEfficiency, timestamp); + if (cfg.mEfficiency == nullptr) { + LOGF(fatal, "Could not load efficiency histogram from %s", cfgEfficiency.value.c_str()); + } + LOGF(info, "Loaded efficiency histogram from %s (%p)", cfgEfficiency.value.c_str(), (void*)cfg.mEfficiency); + } + cfg.correctionsLoaded = true; + } + + template + double getAcceptance(TTrack track, const double& vtxz) + { + double wacc = 1; + if (cfg.mAcceptance) + wacc = cfg.mAcceptance->getNUA(track.phi(), track.eta(), vtxz); + return wacc; + } + + template + double getEfficiency(TTrack track) + { + double eff = 1.; + if (cfg.mEfficiency) + eff = cfg.mEfficiency->GetBinContent(cfg.mEfficiency->FindBin(track.pt())); + if (eff == 0) + return -1.; + else + return 1. / eff; + } + + template + bool eventSelected(TCollision collision, const int& multTrk, const float& centrality, const int& run) + { + if (cfgTVXinTRD) { + if (collision.alias_bit(kTVXinTRD)) { + // TRD triggered + // "CMTVX-B-NOPF-TRD,minbias_TVX" + return 0; + } + registry.fill(HIST("eventQA/eventSel"), 3.5); + if (cfgRunByRun) + th1sList[run][hEventSel]->Fill(3.5); + } + + if (cfgNoSameBunchPileupCut) { + 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 + return 0; + } + registry.fill(HIST("eventQA/eventSel"), 4.5); + if (cfgRunByRun) + th1sList[run][hEventSel]->Fill(4.5); + } + if (cfgIsGoodZvtxFT0vsPV) { + 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 + return 0; + } + registry.fill(HIST("eventQA/eventSel"), 5.5); + if (cfgRunByRun) + th1sList[run][hEventSel]->Fill(5.5); + } + if (cfgNoCollInTimeRangeStandard) { + if (!collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { + // Rejection of the collisions which have other events nearby + return 0; + } + registry.fill(HIST("eventQA/eventSel"), 6.5); + if (cfgRunByRun) + th1sList[run][hEventSel]->Fill(6.5); + } + + if (cfgIsVertexITSTPC) { + 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; + } + registry.fill(HIST("eventQA/eventSel"), 7.5); + if (cfgRunByRun) + th1sList[run][hEventSel]->Fill(7.5); + } + + if (cfgIsGoodITSLayersAll) { + if (!collision.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { + return 0; + } + registry.fill(HIST("eventQA/eventSel"), 8.5); + if (cfgRunByRun) + th1sList[run][hEventSel]->Fill(8.5); + } + float vtxz = -999; + if (collision.numContrib() > 1) { + vtxz = collision.posZ(); + float zRes = std::sqrt(collision.covZZ()); + float minZRes = 0.25; + int minNContrib = 20; + if (zRes > minZRes && collision.numContrib() < minNContrib) + vtxz = -999; + } + // auto multV0A = collision.multFV0A(); + // auto multT0A = collision.multFT0A(); + // auto multT0C = collision.multFT0C(); + auto multNTracksPV = collision.multNTracksPV(); + + if (vtxz > o2::analysis::gfw::vtxZup || vtxz < o2::analysis::gfw::vtxZlow) + return 0; + + if (cfgMultCut) { + if (multNTracksPV < fMultPVCutLow->Eval(centrality)) + return 0; + if (multNTracksPV > fMultPVCutHigh->Eval(centrality)) + return 0; + if (multTrk < fMultCutLow->Eval(centrality)) + return 0; + if (multTrk > fMultCutHigh->Eval(centrality)) + return 0; + registry.fill(HIST("eventQA/eventSel"), 9.5); + if (cfgRunByRun) + th1sList[run][hEventSel]->Fill(9.5); + } + return 1; + } + + template + bool trackSelected(TTrack track) + { + if (cfgDCAxyNSigma && (std::fabs(track.dcaXY()) > cfgDCAxyNSigma / 7. * (0.0105f + 0.0035f / track.pt()))) + return false; + return ((track.tpcNClsCrossedRows() >= cfgNTPCXrows) && (track.tpcNClsFound() >= cfgNTPCCls) && (track.itsNCls() >= cfgMinNITSCls)); + } + + enum DataType { + kReco, + kGen + }; + + template + void fillWeights(const TTrack track, const double vtxz, const int& run) + { + if (cfgRunByRun) + th3sList[run][hNUAref]->Fill(track.phi(), track.eta(), vtxz); + else + registry.fill(HIST("phi_eta_vtxz_ref"), track.phi(), track.eta(), vtxz); + return; + } + + void createRunByRunHistograms(const int& run) + { + AxisSpec phiAxis = {o2::analysis::gfw::phibins, o2::analysis::gfw::philow, o2::analysis::gfw::phiup, "#phi"}; + AxisSpec etaAxis = {o2::analysis::gfw::etabins, -cfgEta, cfgEta, "#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 (%)"}; + std::vector> histos(kCount_TH1Names); + histos[hPhi] = registry.add(Form("%d/phi", run), "", {HistType::kTH1D, {phiAxis}}); + histos[hEta] = registry.add(Form("%d/eta", run), "", {HistType::kTH1D, {etaAxis}}); + histos[hVtxZ] = registry.add(Form("%d/vtxz", run), "", {HistType::kTH1D, {vtxAxis}}); + histos[hMult] = registry.add(Form("%d/mult", run), "", {HistType::kTH1D, {nchAxis}}); + histos[hCent] = registry.add(Form("%d/cent", run), "", {HistType::kTH1D, {centAxis}}); + histos[hEventSel] = registry.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"); + th1sList.insert(std::make_pair(run, histos)); + std::vector> histos3d(kCount_TH3Names); + histos3d[hNUAref] = registry.add(Form("%d/phi_eta_vtxz_ref", run), "", {HistType::kTH3D, {phiAxis, etaAxis, vtxAxis}}); + th3sList.insert(std::make_pair(run, histos3d)); + return; + } + + template + void fillOutputContainers(const float& centmult, const double& rndm) + { + (dt == kGen) ? fFCptgen->calculateCorrelations() : fFCpt->calculateCorrelations(); + (dt == kGen) ? fFCptgen->fillPtProfiles(centmult, rndm) : fFCpt->fillPtProfiles(centmult, rndm); + (dt == kGen) ? fFCptgen->fillCMProfiles(centmult, rndm) : fFCpt->fillCMProfiles(centmult, rndm); + for (uint l_ind = 0; l_ind < corrconfigs.size(); ++l_ind) { + if (!corrconfigs.at(l_ind).pTDif) { + auto dnx = fGFW->Calculate(corrconfigs.at(l_ind), 0, kTRUE).real(); + if (dnx == 0) + 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, dnx, rndm) : fFC->FillProfile(corrconfigs.at(l_ind).Head.c_str(), centmult, val, dnx, rndm); + (dt == kGen) ? fFCptgen->fillVnPtProfiles(centmult, val, dnx, rndm, o2::analysis::gfw::configs.GetpTCorrMasks()[l_ind]) : fFCpt->fillVnPtProfiles(centmult, val, dnx, rndm, o2::analysis::gfw::configs.GetpTCorrMasks()[l_ind]); + } + continue; + } + for (int i = 1; i <= fPtAxis->GetNbins(); i++) { + auto dnx = fGFW->Calculate(corrconfigs.at(l_ind), i - 1, kTRUE).real(); + if (dnx == 0) + 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, dnx, rndm) : fFC->FillProfile(Form("%s_pt_%i", corrconfigs.at(l_ind).Head.c_str(), i), centmult, val, dnx, rndm); + } + } + return; + } + + template + void processCollision(TCollision collision, TTracks tracks, const float& centrality, const int& multiplicity, const int& run) + { + if (tracks.size() < 1) + return; + if (dt != kGen && centrality >= 0 && (centrality < o2::analysis::gfw::centbinning.front() || centrality > o2::analysis::gfw::centbinning.back())) + return; + if (dt != kGen) { + registry.fill(HIST("eventQA/eventSel"), 10.5); + if (cfgRunByRun) + th1sList[run][hEventSel]->Fill(10.5); + } + float vtxz = collision.posZ(); + if (dt != kGen && cfgRunByRun) { + th1sList[run][hVtxZ]->Fill(vtxz); + th1sList[run][hMult]->Fill(multiplicity); + th1sList[run][hCent]->Fill(centrality); + } + fGFW->Clear(); + (dt == kGen) ? fFCptgen->clearVector() : fFCpt->clearVector(); + + float lRandom = fRndm->Rndm(); + + // be cautious, this only works for Pb-Pb + // esimate the Event plane and vn for this event + DensityCorr densitycorrections; + if (cfgUseDensityDependentCorrection) { + double psi2Est = 0, psi3Est = 0, psi4Est = 0; + double v2 = 0, v3 = 0, v4 = 0; + double q2x = 0, q2y = 0; + double q3x = 0, q3y = 0; + double q4x = 0, q4y = 0; + for (const auto& track : tracks) { + bool withinPtRef = (o2::analysis::gfw::ptreflow < track.pt()) && (track.pt() < o2::analysis::gfw::ptrefup); // within RF pT rang + if (withinPtRef) { + q2x += std::cos(2 * track.phi()); + q2y += std::sin(2 * track.phi()); + q3x += std::cos(3 * track.phi()); + q3y += std::sin(3 * track.phi()); + q4x += std::cos(4 * track.phi()); + q4y += std::sin(4 * track.phi()); + } + } + psi2Est = std::atan2(q2y, q2x) / 2.; + psi3Est = std::atan2(q3y, q3x) / 3.; + psi4Est = std::atan2(q4y, q4x) / 4.; + v2 = funcV2->Eval(centrality); + v3 = funcV3->Eval(centrality); + v4 = funcV4->Eval(centrality); + densitycorrections.psi2Est = psi2Est; + densitycorrections.psi3Est = psi3Est; + densitycorrections.psi4Est = psi4Est; + densitycorrections.v2 = v2; + densitycorrections.v3 = v3; + densitycorrections.v4 = v4; + densitycorrections.density = tracks.size(); + } + + for (const auto& track : tracks) { + processTrack(track, vtxz, multiplicity, run, densitycorrections); + } + if (!cfgFillWeights) + fillOutputContainers
((cfgUseNch) ? multiplicity : centrality, lRandom); + } + + bool isStable(int pdg) + { + if (std::abs(pdg) == PDG_t::kPiPlus) + return true; + if (std::abs(pdg) == PDG_t::kKPlus) + return true; + if (std::abs(pdg) == PDG_t::kProton) + return true; + if (std::abs(pdg) == PDG_t::kElectron) + return true; + if (std::abs(pdg) == PDG_t::kMuonMinus) + return true; + return false; + } + + template + inline void processTrack(TTrack const& track, const float& vtxz, const int& multiplicity, const int& run, DensityCorr densitycorrections) + { + if constexpr (framework::has_type_v) { + if (track.mcParticleId() < 0 || !(track.has_mcParticle())) + return; + + auto mcParticle = track.mcParticle(); + if (!mcParticle.isPhysicalPrimary()) + return; + if (!isStable(mcParticle.pdgCode())) + return; + if (cfgFillQA) { + fillTrackQA(track, vtxz); + registry.fill(HIST("trackQA/before/nch_pt"), multiplicity, track.pt()); + } + if (!trackSelected(track)) + return; + + if (cfgFillWeights) { + fillWeights(mcParticle, vtxz, run); + } else { + fillPtSums(track); + fillGFW(mcParticle, vtxz, densitycorrections); + } + + if (cfgFillQA) { + fillTrackQA(track, vtxz); + registry.fill(HIST("trackQA/after/nch_pt"), multiplicity, track.pt()); + if (cfgRunByRun) { + th1sList[run][hPhi]->Fill(track.phi()); + th1sList[run][hEta]->Fill(track.eta()); + } + } + + } else if constexpr (framework::has_type_v) { + if (!track.isPhysicalPrimary() || !isStable(track.pdgCode())) + return; + + fillPtSums(track); + fillGFW(track, vtxz, densitycorrections); + + if (cfgFillQA) { + fillTrackQA(track, vtxz); + registry.fill(HIST("MCGen/trackQA/nch_pt"), multiplicity, track.pt()); + } + } else { + if (cfgFillQA) { + fillTrackQA(track, vtxz); + registry.fill(HIST("trackQA/before/nch_pt"), multiplicity, track.pt()); + } + if (!trackSelected(track)) + return; + + if (cfgFillWeights) { + fillWeights(track, vtxz, run); + } else { + fillPtSums(track); + fillGFW(track, vtxz, densitycorrections); + } + if (cfgFillQA) { + fillTrackQA(track, vtxz); + registry.fill(HIST("trackQA/after/nch_pt"), multiplicity, track.pt()); + if (cfgRunByRun) { + th1sList[run][hPhi]->Fill(track.phi()); + th1sList[run][hEta]->Fill(track.eta()); + } + } + } + } + + template + inline void fillGFW(TTrack track, const double& vtxz, DensityCorr densitycorrections) + { + bool withinPtRef = (track.pt() > o2::analysis::gfw::ptreflow && track.pt() < o2::analysis::gfw::ptrefup); + 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); + if (weff < 0) + return; + if (cfgUseDensityDependentCorrection && withinPtRef && dt != kGen) { + 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()); + if (pTBinForEff >= 1 && pTBinForEff <= hFindPtBin->GetNbinsX()) { + float wEPeff = funcEff[pTBinForEff - 1]->Eval(fphi * densitycorrections.density); + if (wEPeff > 0.) { + wEPeff = 1. / wEPeff; + weff *= wEPeff; + } + } + } + double wacc = (dt == kGen) ? 1. : getAcceptance(track, vtxz); + if (withinPtRef) + fGFW->Fill(track.eta(), fPtAxis->FindBin(track.pt()) - 1, track.phi(), weff * wacc, 1); + if (withinPtPOI) + fGFW->Fill(track.eta(), fPtAxis->FindBin(track.pt()) - 1, track.phi(), weff * wacc, 2); + if (withinPtRef && withinPtPOI) + fGFW->Fill(track.eta(), fPtAxis->FindBin(track.pt()) - 1, track.phi(), weff * wacc, 4); + + return; + } + + template + inline void fillPtSums(TTrack track) + { + double weff = (dt == kGen) ? 1. : getEfficiency(track); + if (weff < 0) + return; + if (std::abs(track.eta()) < cfgEtaPtPt) { + (dt == kGen) ? fFCptgen->fill(1., track.pt()) : fFCpt->fill(weff, track.pt()); + } + } + + template + inline void fillTrackQA(TTrack track, const float vtxz) + { + if constexpr (dt == kGen) { + registry.fill(HIST("MCGen/trackQA/phi_eta_vtxZ"), track.phi(), track.eta(), vtxz); + registry.fill(HIST("MCGen/trackQA/pt_ref"), track.pt()); + registry.fill(HIST("MCGen/trackQA/pt_poi"), track.pt()); + } else { + double wacc = getAcceptance(track, vtxz); + registry.fill(HIST("trackQA/") + HIST(FillTimeName[ft]) + HIST("phi_eta_vtxZ"), track.phi(), track.eta(), vtxz, (ft == kAfter) ? wacc : 1.0); + registry.fill(HIST("trackQA/") + HIST(FillTimeName[ft]) + HIST("pt_dcaXY_dcaZ"), track.pt(), track.dcaXY(), track.dcaZ()); + + registry.fill(HIST("trackQA/") + HIST(FillTimeName[ft]) + HIST("chi2prTPCcls"), track.tpcChi2NCl()); + registry.fill(HIST("trackQA/") + HIST(FillTimeName[ft]) + HIST("chi2prITScls"), track.itsChi2NCl()); + registry.fill(HIST("trackQA/") + HIST(FillTimeName[ft]) + HIST("nTPCClusters"), track.tpcNClsFound()); + registry.fill(HIST("trackQA/") + HIST(FillTimeName[ft]) + HIST("nITSClusters"), track.itsNCls()); + registry.fill(HIST("trackQA/") + HIST(FillTimeName[ft]) + HIST("nTPCCrossedRows"), track.tpcNClsCrossedRows()); + + if (ft == kAfter) { + registry.fill(HIST("trackQA/") + HIST(FillTimeName[ft]) + HIST("pt_ref"), track.pt()); + registry.fill(HIST("trackQA/") + HIST(FillTimeName[ft]) + HIST("pt_poi"), track.pt()); + } + } + } + + template + inline void fillEventQA(TCollision collision, TTracks tracks) + { + if constexpr (framework::has_type_v) { + registry.fill(HIST("eventQA/") + HIST(FillTimeName[ft]) + HIST("globalTracks_centT0C"), collision.centFT0C(), tracks.size()); + registry.fill(HIST("eventQA/") + HIST(FillTimeName[ft]) + HIST("PVTracks_centT0C"), collision.centFT0C(), collision.multNTracksPV()); + registry.fill(HIST("eventQA/") + HIST(FillTimeName[ft]) + HIST("multT0C_centT0C"), collision.centFT0C(), collision.multFT0C()); + } + registry.fill(HIST("eventQA/") + HIST(FillTimeName[ft]) + HIST("globalTracks_PVTracks"), collision.multNTracksPV(), tracks.size()); + registry.fill(HIST("eventQA/") + HIST(FillTimeName[ft]) + HIST("globalTracks_multT0A"), collision.multFT0A(), tracks.size()); + registry.fill(HIST("eventQA/") + HIST(FillTimeName[ft]) + HIST("globalTracks_multV0A"), collision.multFV0A(), tracks.size()); + registry.fill(HIST("eventQA/") + HIST(FillTimeName[ft]) + HIST("multV0A_multT0A"), collision.multFT0A(), collision.multFV0A()); + return; + } + + void processData(soa::Filtered>::iterator const& collision, aod::BCsWithTimestamps const&, GFWTracks const& tracks) + { + auto bc = collision.bc_as(); + int run = bc.runNumber(); + if (run != lastRun) { + lastRun = run; + 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); + runNumbers.push_back(run); + } else { + LOGF(info, "run %d already in runNumbers", run); + } + if (!cfgFillWeights) + loadCorrections(bc); + } + } + if (!cfgFillWeights && !cfgRunByRun) + loadCorrections(bc); + registry.fill(HIST("eventQA/eventSel"), 0.5); + if (cfgRunByRun) + th1sList[run][hEventSel]->Fill(0.5); + if (!collision.sel8()) + return; + registry.fill(HIST("eventQA/eventSel"), 1.5); + if (cfgRunByRun) + th1sList[run][hEventSel]->Fill(1.5); + if (cfgDoOccupancySel) { + int occupancy = collision.trackOccupancyInTimeRange(); + if (occupancy < 0 || occupancy > cfgOccupancySelection) + return; + } + registry.fill(HIST("eventQA/eventSel"), 2.5); + if (cfgRunByRun) + th1sList[run][hEventSel]->Fill(2.5); + float centrality; + switch (cfgCentEstimator) { + case kCentFT0C: + centrality = collision.centFT0C(); + break; + case kCentFT0CVariant1: + centrality = collision.centFT0CVariant1(); + break; + case kCentFT0M: + centrality = collision.centFT0M(); + break; + case kCentFV0A: + centrality = collision.centFV0A(); + break; + case kCentNTPV: + centrality = collision.centNTPV(); + break; + default: + centrality = collision.centFT0C(); + } + if (cfgFillQA) + fillEventQA(collision, tracks); + registry.fill(HIST("eventQA/before/centrality"), centrality); + registry.fill(HIST("eventQA/before/multiplicity"), tracks.size()); + if (cfgUseAdditionalEventCut && !eventSelected(collision, tracks.size(), centrality, run)) + return; + if (cfgFillQA) + fillEventQA(collision, tracks); + registry.fill(HIST("eventQA/after/centrality"), centrality); + registry.fill(HIST("eventQA/after/multiplicity"), tracks.size()); + processCollision(collision, tracks, centrality, tracks.size(), run); + } + PROCESS_SWITCH(FlowGfwLightIons, processData, "Process analysis for non-derived data", true); + + void processDataNoCent(soa::Filtered>::iterator const& collision, aod::BCsWithTimestamps const&, GFWTracks const& tracks) + { + auto bc = collision.bc_as(); + int run = bc.runNumber(); + if (run != lastRun) { + lastRun = run; + 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); + runNumbers.push_back(run); + } else { + LOGF(info, "run %d already in runNumbers", run); + } + if (!cfgFillWeights) + loadCorrections(bc); + } + } + if (!cfgFillWeights && !cfgRunByRun) + loadCorrections(bc); + registry.fill(HIST("eventQA/eventSel"), 0.5); + if (cfgRunByRun) + th1sList[run][hEventSel]->Fill(0.5); + if (!collision.sel8()) + return; + registry.fill(HIST("eventQA/eventSel"), 1.5); + if (cfgRunByRun) + th1sList[run][hEventSel]->Fill(1.5); + if (cfgDoOccupancySel) { + int occupancy = collision.trackOccupancyInTimeRange(); + if (occupancy < 0 || occupancy > cfgOccupancySelection) + return; + } + registry.fill(HIST("eventQA/eventSel"), 2.5); + if (cfgRunByRun) + th1sList[run][hEventSel]->Fill(2.5); + if (cfgFillQA) + fillEventQA(collision, tracks); + registry.fill(HIST("eventQA/before/multiplicity"), tracks.size()); + if (cfgUseAdditionalEventCut && !eventSelected(collision, tracks.size(), -1, run)) + return; + if (cfgFillQA) + fillEventQA(collision, tracks); + registry.fill(HIST("eventQA/after/multiplicity"), tracks.size()); + processCollision(collision, tracks, -1, tracks.size(), run); + } + PROCESS_SWITCH(FlowGfwLightIons, processDataNoCent, "Process analysis for non-derived data without centrality", true); + + void processMCReco(soa::Filtered>::iterator const& collision, aod::BCsWithTimestamps const&, soa::Filtered> const& tracks, aod::McParticles const&) + { + auto bc = collision.bc_as(); + int run = bc.runNumber(); + if (run != lastRun) { + lastRun = run; + if (cfgRunByRun) + createRunByRunHistograms(run); + } + if (!collision.sel8()) + return; + const auto centrality = collision.centFT0C(); + if (cfgFillQA) + fillEventQA(collision, tracks); + registry.fill(HIST("eventQA/before/centrality"), centrality); + registry.fill(HIST("eventQA/before/multiplicity"), tracks.size()); + if (cfgUseAdditionalEventCut && !eventSelected(collision, tracks.size(), centrality, run)) + return; + if (cfgFillQA) + fillEventQA(collision, tracks); + registry.fill(HIST("eventQA/after/centrality"), centrality); + registry.fill(HIST("eventQA/after/multiplicity"), tracks.size()); + + if (!cfgFillWeights) + loadCorrections(bc); + processCollision(collision, tracks, centrality, tracks.size(), run); + } + PROCESS_SWITCH(FlowGfwLightIons, processMCReco, "Process analysis for MC reconstructed events", false); + + void processMCRecoNoCent(soa::Filtered>::iterator const& collision, aod::BCsWithTimestamps const&, soa::Filtered> const& tracks, aod::McParticles const&) + { + auto bc = collision.bc_as(); + int run = bc.runNumber(); + if (run != lastRun) { + lastRun = run; + if (cfgRunByRun) + createRunByRunHistograms(run); + } + registry.fill(HIST("eventQA/eventSel"), 0.5); + if (!collision.sel8()) + return; + const auto centrality = -1.; + registry.fill(HIST("eventQA/eventSel"), 1.5); + if (cfgDoOccupancySel) { + int occupancy = collision.trackOccupancyInTimeRange(); + if (occupancy < 0 || occupancy > cfgOccupancySelection) + return; + } + registry.fill(HIST("eventQA/eventSel"), 2.5); + + registry.fill(HIST("eventQA/before/multiplicity"), tracks.size()); + if (cfgUseAdditionalEventCut) { + if (cfgTVXinTRD) { + if (collision.alias_bit(kTVXinTRD)) { + // TRD triggered + // "CMTVX-B-NOPF-TRD,minbias_TVX" + return; + } + registry.fill(HIST("eventQA/eventSel"), 3.5); + } + if (cfgNoSameBunchPileupCut) { + 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 + return; + } + registry.fill(HIST("eventQA/eventSel"), 4.5); + } + if (cfgIsGoodZvtxFT0vsPV) { + 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 + return; + } + registry.fill(HIST("eventQA/eventSel"), 5.5); + } + if (cfgNoCollInTimeRangeStandard) { + if (!collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { + // Rejection of the collisions which have other events nearby + return; + } + registry.fill(HIST("eventQA/eventSel"), 6.5); + } + if (cfgIsVertexITSTPC) { + 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; + } + registry.fill(HIST("eventQA/eventSel"), 7.5); + } + if (cfgIsGoodITSLayersAll) { + if (!collision.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { + return; + } + registry.fill(HIST("eventQA/eventSel"), 8.5); + } + float vtxz = -999; + if (collision.numContrib() > 1) { + vtxz = collision.posZ(); + float zRes = std::sqrt(collision.covZZ()); + float minZRes = 0.25; + int minNContrib = 20; + if (zRes > minZRes && collision.numContrib() < minNContrib) + vtxz = -999; + } + + if (vtxz > o2::analysis::gfw::vtxZup || vtxz < o2::analysis::gfw::vtxZlow) + return; + } + + registry.fill(HIST("eventQA/after/multiplicity"), tracks.size()); + if (!cfgFillWeights) + loadCorrections(bc); + processCollision(collision, tracks, centrality, tracks.size(), run); + } + PROCESS_SWITCH(FlowGfwLightIons, processMCRecoNoCent, "Process analysis for MC reconstructed events without centrality/mult table", false); + + void processMCGen(soa::Filtered::iterator const& mcCollision, soa::SmallGroups> const& collisions, aod::McParticles const& particles, GFWTracks const& tracks) + { + if (collisions.size() != 1) + return; + float centrality = -1; + for (const auto& collision : collisions) { + centrality = collision.centFT0C(); + } + std::vector numberOfTracks; + for (auto const& collision : collisions) { + auto groupedTracks = tracks.sliceBy(perCollision, collision.globalIndex()); + numberOfTracks.emplace_back(groupedTracks.size()); + } + + int run = 0; + processCollision(mcCollision, particles, centrality, numberOfTracks[0], run); + registry.fill(HIST("MCGen/eventQA/multiplicity"), numberOfTracks[0]); + registry.fill(HIST("MCGen/eventQA/centrality"), centrality); + } + PROCESS_SWITCH(FlowGfwLightIons, processMCGen, "Process analysis for MC generated events", false); + + void processMCGenNoCent(soa::Filtered::iterator const& mcCollision, soa::SmallGroups> const& collisions, aod::McParticles const& particles, GFWTracks const& tracks) + { + if (collisions.size() != 1) + return; + const float centrality = -1; + std::vector numberOfTracks; + for (auto const& collision : collisions) { + auto groupedTracks = tracks.sliceBy(perCollision, collision.globalIndex()); + numberOfTracks.emplace_back(groupedTracks.size()); + } + int run = 0; + registry.fill(HIST("MCGen/eventQA/multiplicity"), numberOfTracks[0]); + processCollision(mcCollision, particles, centrality, numberOfTracks[0], run); + } + PROCESS_SWITCH(FlowGfwLightIons, processMCGenNoCent, "Process analysis for MC generated events", false); + + void processOnTheFly(soa::Filtered::iterator const& mcCollision, aod::McParticles const& mcParticles) + { + int run = 0; + registry.fill(HIST("MCGen/impactParameter"), mcCollision.impactParameter(), mcParticles.size()); + processCollision(mcCollision, mcParticles, mcCollision.impactParameter(), mcParticles.size(), run); + } + PROCESS_SWITCH(FlowGfwLightIons, processOnTheFly, "Process analysis for MC on-the-fly generated events", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc), + }; +} diff --git a/PWGCF/GenericFramework/Tasks/flowGenericFramework.cxx b/PWGCF/GenericFramework/Tasks/flowGenericFramework.cxx index c7d268057e4..79e56fbcff6 100644 --- a/PWGCF/GenericFramework/Tasks/flowGenericFramework.cxx +++ b/PWGCF/GenericFramework/Tasks/flowGenericFramework.cxx @@ -97,6 +97,7 @@ struct FlowGenericFramework { O2_DEFINE_CONFIGURABLE(cfgDCAxyNSigma, float, 7, "Cut on number of sigma deviations from expected DCA in the transverse direction"); O2_DEFINE_CONFIGURABLE(cfgDCAz, float, 2, "Cut on DCA in the longitudinal direction (cm)"); O2_DEFINE_CONFIGURABLE(cfgNTPCCls, float, 70, "Cut on number of TPC clusters found"); + O2_DEFINE_CONFIGURABLE(cfgNTPCXrows, float, 70, "Cut on number of TPC crossed rows"); O2_DEFINE_CONFIGURABLE(cfgMinNITSCls, float, 5, "Cut on minimum number of ITS clusters found"); O2_DEFINE_CONFIGURABLE(cfgChi2PrITSCls, float, 36, "Cut on chi^2 per ITS clusters found"); O2_DEFINE_CONFIGURABLE(cfgChi2PrTPCCls, float, 2.5, "Cut on chi^2 per TPC clusters found"); @@ -298,7 +299,8 @@ struct FlowGenericFramework { registry.add("MCGen/before/pt_gen", "", {HistType::kTH1D, {ptAxis}}); registry.add("MCGen/before/phi_eta_vtxZ_gen", "", {HistType::kTH3D, {phiAxis, etaAxis, vtxAxis}}); registry.addClone("MCGen/before/", "MCGen/after/"); - registry.add("MCGen/impactParameter", "", {HistType::kTH2D, {{bAxis, nchAxis}}}); + if (doprocessOnTheFly) + registry.add("MCGen/impactParameter", "", {HistType::kTH2D, {{bAxis, nchAxis}}}); } if (doprocessMCReco || doprocessData || doprocessRun2) { registry.add("trackQA/before/phi_eta_vtxZ", "", {HistType::kTH3D, {phiAxis, etaAxis, vtxAxis}}); @@ -386,16 +388,6 @@ struct FlowGenericFramework { fMultCutLow->SetParameters(&(o2::analysis::gfw::multGlobalCorrCutPars[0])); fMultCutHigh = new TF1("fMultCutHigh", cfgMultCorrHighCutFunction->c_str(), 0, 100); fMultCutHigh->SetParameters(&(o2::analysis::gfw::multGlobalCorrCutPars[0])); - /* - 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); - fMultPVCutLow->SetParameters(3257.29, -121.848, 1.98492, -0.0172128, 6.47528e-05, 154.756, -1.86072, -0.0274713, 0.000633499, -3.37757e-06); - 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); - fMultPVCutHigh->SetParameters(3257.29, -121.848, 1.98492, -0.0172128, 6.47528e-05, 154.756, -1.86072, -0.0274713, 0.000633499, -3.37757e-06); - - 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); - fMultCutLow->SetParameters(1654.46, -47.2379, 0.449833, -0.0014125, 150.773, -3.67334, 0.0530503, -0.000614061, 3.15956e-06); - 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); - fMultCutHigh->SetParameters(1654.46, -47.2379, 0.449833, -0.0014125, 150.773, -3.67334, 0.0530503, -0.000614061, 3.15956e-06); */ } if (cfgUseDensityDependentCorrection) { 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}; @@ -630,7 +622,7 @@ struct FlowGenericFramework { { if (cfgDCAxyNSigma && (std::fabs(track.dcaXY()) > cfgDCAxyNSigma / 7. * (0.0105f + 0.0035f / track.pt()))) return false; - return ((track.tpcNClsFound() >= cfgNTPCCls) && (track.itsNCls() >= cfgMinNITSCls)); + return ((track.tpcNClsCrossedRows() >= cfgNTPCXrows) && (track.tpcNClsFound() >= cfgNTPCCls) && (track.itsNCls() >= cfgMinNITSCls)); } enum DataType { kReco, @@ -1100,7 +1092,7 @@ struct FlowGenericFramework { } PROCESS_SWITCH(FlowGenericFramework, processData, "Process analysis for non-derived data", true); - void processMCReco(soa::Filtered>::iterator const& collision, aod::BCsWithTimestamps const&, soa::Filtered> const& tracks, aod::McParticles const&) + void processMCReco(soa::Filtered>::iterator const& collision, aod::BCsWithTimestamps const&, soa::Filtered> const& tracks, aod::McParticles const&) { auto bc = collision.bc_as(); int run = bc.runNumber(); @@ -1141,10 +1133,9 @@ struct FlowGenericFramework { void processOnTheFly(soa::Filtered::iterator const& mcCollision, aod::McParticles const& mcParticles) { - float centrality = -1; int run = 0; registry.fill(HIST("MCGen/impactParameter"), mcCollision.impactParameter(), mcParticles.size()); - processCollision(mcCollision, mcParticles, centrality, run); + processCollision(mcCollision, mcParticles, mcCollision.impactParameter(), run); } PROCESS_SWITCH(FlowGenericFramework, processOnTheFly, "Process analysis for MC on-the-fly generated events", false); From 3737c933d97c8023bebc5d2e1f88a5027dadc6da Mon Sep 17 00:00:00 2001 From: sawan <124118453+sawankumawat@users.noreply.github.com> Date: Wed, 25 Jun 2025 22:46:16 +0530 Subject: [PATCH 214/871] [PWGLF] Corrected Helicity angle in rotational background and optimised code (#11769) Co-authored-by: Sawan Sawan --- .../Tasks/Resonances/higherMassResonances.cxx | 185 +++++++++--------- 1 file changed, 93 insertions(+), 92 deletions(-) diff --git a/PWGLF/Tasks/Resonances/higherMassResonances.cxx b/PWGLF/Tasks/Resonances/higherMassResonances.cxx index e9f40c66f05..81f26d94dc6 100644 --- a/PWGLF/Tasks/Resonances/higherMassResonances.cxx +++ b/PWGLF/Tasks/Resonances/higherMassResonances.cxx @@ -174,12 +174,17 @@ struct HigherMassResonances { TRandom* rn = new TRandom(); // variables declaration - TLorentzVector lv1, lv2, lv3, lv4, lv5; float multiplicity = 0.0f; float theta2; - ROOT::Math::PxPyPzMVector daughter1, daughter2, fourVecDau1, fourVecMother, fourVecDauCM; - ROOT::Math::XYZVector threeVecDauCM, helicityVec, randomVec, beamVec, normalVec; - ROOT::Math::XYZVector z_beam; // ẑ: beam direction in lab frame + ROOT::Math::PxPyPzMVector daughter1, daughter2, daughterRot, daughterRotCM, mother, motherRot, fourVecDauCM; + ROOT::Math::XYZVector randomVec, beamVec, normalVec; + ROOT::Math::XYZVectorF v1_CM, zaxis_HE, yaxis_HE, xaxis_HE; + // ROOT::Math::XYZVector threeVecDauCM, helicityVec, randomVec, beamVec, normalVec; + ROOT::Math::XYZVector zBeam; // ẑ: beam direction in lab frame + double BeamMomentum = TMath::Sqrt(13600 * 13600 / 4 - 0.938 * 0.938); // GeV + ROOT::Math::PxPyPzEVector Beam1{0., 0., -BeamMomentum, 13600. / 2.}; + ROOT::Math::PxPyPzEVector Beam2{0., 0., BeamMomentum, 13600. / 2.}; + ROOT::Math::XYZVectorF Beam1_CM, Beam2_CM; // const double massK0s = o2::constants::physics::MassK0Short; bool isMix = false; @@ -584,28 +589,29 @@ struct HigherMassResonances { using EventCandidatesMC = soa::Join; using TrackCandidatesMC = soa::Filtered>; using V0TrackCandidatesMC = soa::Join; - // z_beam direction in lab frame + // zBeam direction in lab frame - template - void fillInvMass(const T2& lv3, const T3& lv5, float multiplicity, const T4& daughter1, bool isMix) + template + void fillInvMass(const T& mother, float multiplicity, const T& daughter1, const T& daughter2, bool isMix) { // //polarization calculations - // z_beam = ROOT::Math::XYZVector(0.f, 0.f, 1.f); // ẑ: beam direction in lab frame + // zBeam = ROOT::Math::XYZVector(0.f, 0.f, 1.f); // ẑ: beam direction in lab frame - fourVecDau1 = ROOT::Math::PxPyPzMVector(daughter1.Px(), daughter1.Py(), daughter1.Pz(), o2::constants::physics::MassK0Short); + ROOT::Math::Boost boost{mother.BoostToCM()}; // define the boost to the center of mass frame + fourVecDauCM = boost(daughter1); // boost the frame of daughter to the center of mass frame + // threeVecDauCM = fourVecDauCM.Vect(); // get the 3 vector of daughter in the frame of mother - fourVecMother = ROOT::Math::PxPyPzMVector(lv3.Px(), lv3.Py(), lv3.Pz(), lv3.M()); // 4 vector of mother particle - ROOT::Math::Boost boost{fourVecMother.BoostToCM()}; // define the boost to the center of mass frame - fourVecDauCM = boost(fourVecDau1); // boost the frame of daughter to the center of mass frame - threeVecDauCM = fourVecDauCM.Vect(); // get the 3 vector of daughter in the frame of mother - // define y = z_beam x z: Normal to the production plane + Beam1_CM = ROOT::Math::XYZVectorF((boost(Beam1).Vect()).Unit()); + Beam2_CM = ROOT::Math::XYZVectorF((boost(Beam2).Vect()).Unit()); + + // define y = zBeam x z: Normal to the production plane // ẑ: mother direction in lab, boosted into mother's rest frame - // auto motherLabDirection = ROOT::Math::XYZVector(0, 0, fourVecMother.Vect().Z()); // ẑ axis in lab frame + // auto motherLabDirection = ROOT::Math::XYZVector(0, 0, mother.Vect().Z()); // ẑ axis in lab frame - // // ŷ = z_beam × ẑ - // auto y_axis = z_beam.Cross(motherLabDirection).Unit(); + // // ŷ = zBeam × ẑ + // auto y_axis = zBeam.Cross(motherLabDirection).Unit(); // // x̂ = ŷ × ẑ // auto x_axis = y_axis.Cross(motherLabDirection).Unit(); @@ -617,19 +623,14 @@ struct HigherMassResonances { // // Calculate φ in [-π, π] // auto angle_phi = std::atan2(p_proj_y, p_proj_x); // φ in radians - double BeamMomentum = TMath::Sqrt(13600 * 13600 / 4 - 0.938 * 0.938); // GeV - ROOT::Math::PxPyPzEVector Beam1(0., 0., -BeamMomentum, 13600 / 2); - ROOT::Math::PxPyPzEVector Beam2(0., 0., BeamMomentum, 13600 / 2); - ROOT::Math::XYZVectorF v1_CM{(boost(fourVecDau1).Vect()).Unit()}; - // ROOT::Math::XYZVectorF v2_CM{(boost(fourVecDau1).Vect()).Unit()}; - ROOT::Math::XYZVectorF Beam1_CM{(boost(Beam1).Vect()).Unit()}; - ROOT::Math::XYZVectorF Beam2_CM{(boost(Beam2).Vect()).Unit()}; + v1_CM = ROOT::Math::XYZVectorF(boost(daughter1).Vect()).Unit(); + // ROOT::Math::XYZVectorF v2_CM{(boost(daughter1).Vect()).Unit()}; // using positive sign convention for the first track // ROOT::Math::XYZVectorF v_CM = (t1.sign() > 0 ? v1_CM : v2_CM); // here selected decay daughter momentum is intested. here you can choose one decay daughter no need to check both case as it is neutral particle for our case // Helicity frame - ROOT::Math::XYZVectorF zaxis_HE{(fourVecMother.Vect()).Unit()}; - ROOT::Math::XYZVectorF yaxis_HE{(Beam1_CM.Cross(Beam2_CM)).Unit()}; - ROOT::Math::XYZVectorF xaxis_HE{(yaxis_HE.Cross(zaxis_HE)).Unit()}; + zaxis_HE = ROOT::Math::XYZVectorF(mother.Vect()).Unit(); + yaxis_HE = ROOT::Math::XYZVectorF(Beam1_CM.Cross(Beam2_CM)).Unit(); + xaxis_HE = ROOT::Math::XYZVectorF(yaxis_HE.Cross(zaxis_HE)).Unit(); // CosThetaHE = zaxis_HE.Dot(v_CM); @@ -638,61 +639,72 @@ struct HigherMassResonances { angle_phi += 2 * TMath::Pi(); // ensure phi is in [0, 2pi] } - if (std::abs(lv3.Rapidity()) < 0.5) { + if (std::abs(mother.Rapidity()) < 0.5) { if (config.activateTHnSparseCosThStarHelicity) { - helicityVec = fourVecMother.Vect(); // 3 vector of mother in COM frame - auto cosThetaStarHelicity = helicityVec.Dot(threeVecDauCM) / (std::sqrt(threeVecDauCM.Mag2()) * std::sqrt(helicityVec.Mag2())); + // helicityVec = mother.Vect(); // 3 vector of mother in COM frame + // auto cosThetaStarHelicity = helicityVec.Dot(threeVecDauCM) / (std::sqrt(threeVecDauCM.Mag2()) * std::sqrt(helicityVec.Mag2())); + auto cosThetaStarHelicity = mother.Vect().Dot(fourVecDauCM.Vect()) / (std::sqrt(fourVecDauCM.Vect().Mag2()) * std::sqrt(mother.Vect().Mag2())); if (!isMix) { - hglue.fill(HIST("h3glueInvMassDS"), multiplicity, lv3.Pt(), lv3.M(), cosThetaStarHelicity, angle_phi); + hglue.fill(HIST("h3glueInvMassDS"), multiplicity, mother.Pt(), mother.M(), cosThetaStarHelicity, angle_phi); for (int i = 0; i < config.cRotations; i++) { theta2 = rn->Uniform(o2::constants::math::PI - o2::constants::math::PI / config.rotationalCut, o2::constants::math::PI + o2::constants::math::PI / config.rotationalCut); - hglue.fill(HIST("h3glueInvMassRot"), multiplicity, lv5.Pt(), lv5.M(), cosThetaStarHelicity, angle_phi); + + 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); + + auto cosThetaStarHelicityRot = motherRot.Vect().Dot(daughterRotCM.Vect()) / (std::sqrt(daughterRotCM.Vect().Mag2()) * std::sqrt(motherRot.Vect().Mag2())); + + hglue.fill(HIST("h3glueInvMassRot"), multiplicity, motherRot.Pt(), motherRot.M(), cosThetaStarHelicityRot, angle_phi); } } else { - hglue.fill(HIST("h3glueInvMassME"), multiplicity, lv3.Pt(), lv3.M(), cosThetaStarHelicity, angle_phi); + hglue.fill(HIST("h3glueInvMassME"), multiplicity, mother.Pt(), mother.M(), cosThetaStarHelicity, angle_phi); } - } else if (config.activateTHnSparseCosThStarProduction) { - normalVec = ROOT::Math::XYZVector(lv3.Py(), -lv3.Px(), 0.f); - auto cosThetaStarProduction = normalVec.Dot(threeVecDauCM) / (std::sqrt(threeVecDauCM.Mag2()) * std::sqrt(normalVec.Mag2())); + normalVec = ROOT::Math::XYZVector(mother.Py(), -mother.Px(), 0.f); + auto cosThetaStarProduction = normalVec.Dot(fourVecDauCM.Vect()) / (std::sqrt(fourVecDauCM.Vect().Mag2()) * std::sqrt(normalVec.Mag2())); if (!isMix) { - hglue.fill(HIST("h3glueInvMassDS"), multiplicity, lv3.Pt(), lv3.M(), cosThetaStarProduction, angle_phi); + hglue.fill(HIST("h3glueInvMassDS"), multiplicity, mother.Pt(), mother.M(), cosThetaStarProduction, angle_phi); for (int i = 0; i < config.cRotations; i++) { - theta2 = rn->Uniform(0, o2::constants::math::PI); - hglue.fill(HIST("h3glueInvMassRot"), multiplicity, lv5.Pt(), lv5.M(), cosThetaStarProduction, angle_phi); + theta2 = rn->Uniform(o2::constants::math::PI - o2::constants::math::PI / config.rotationalCut, o2::constants::math::PI + o2::constants::math::PI / config.rotationalCut); + motherRot = ROOT::Math::PxPyPzMVector(mother.Px() * std::cos(theta2) - mother.Py() * std::sin(theta2), mother.Px() * std::sin(theta2) + mother.Py() * std::cos(theta2), mother.Pz(), mother.M()); + hglue.fill(HIST("h3glueInvMassRot"), multiplicity, motherRot.Pt(), motherRot.M(), cosThetaStarProduction, angle_phi); } } else { - hglue.fill(HIST("h3glueInvMassME"), multiplicity, lv3.Pt(), lv3.M(), cosThetaStarProduction, angle_phi); + hglue.fill(HIST("h3glueInvMassME"), multiplicity, mother.Pt(), mother.M(), cosThetaStarProduction, angle_phi); } - } else if (config.activateTHnSparseCosThStarBeam) { beamVec = ROOT::Math::XYZVector(0.f, 0.f, 1.f); - auto cosThetaStarBeam = beamVec.Dot(threeVecDauCM) / std::sqrt(threeVecDauCM.Mag2()); + auto cosThetaStarBeam = beamVec.Dot(fourVecDauCM.Vect()) / std::sqrt(fourVecDauCM.Vect().Mag2()); if (!isMix) { - hglue.fill(HIST("h3glueInvMassDS"), multiplicity, lv3.Pt(), lv3.M(), cosThetaStarBeam, angle_phi); + hglue.fill(HIST("h3glueInvMassDS"), multiplicity, mother.Pt(), mother.M(), cosThetaStarBeam, angle_phi); for (int i = 0; i < config.cRotations; i++) { - theta2 = rn->Uniform(0, o2::constants::math::PI); - hglue.fill(HIST("h3glueInvMassRot"), multiplicity, lv5.Pt(), lv5.M(), cosThetaStarBeam, angle_phi); + theta2 = rn->Uniform(o2::constants::math::PI - o2::constants::math::PI / config.rotationalCut, o2::constants::math::PI + o2::constants::math::PI / config.rotationalCut); + motherRot = ROOT::Math::PxPyPzMVector(mother.Px() * std::cos(theta2) - mother.Py() * std::sin(theta2), mother.Px() * std::sin(theta2) + mother.Py() * std::cos(theta2), mother.Pz(), mother.M()); + hglue.fill(HIST("h3glueInvMassRot"), multiplicity, motherRot.Pt(), motherRot.M(), cosThetaStarBeam, angle_phi); } } else { - hglue.fill(HIST("h3glueInvMassME"), multiplicity, lv3.Pt(), lv3.M(), cosThetaStarBeam, angle_phi); + hglue.fill(HIST("h3glueInvMassME"), multiplicity, mother.Pt(), mother.M(), cosThetaStarBeam, angle_phi); } - } else if (config.activateTHnSparseCosThStarRandom) { auto phiRandom = gRandom->Uniform(0.f, constants::math::TwoPI); auto thetaRandom = gRandom->Uniform(0.f, constants::math::PI); randomVec = ROOT::Math::XYZVector(std::sin(thetaRandom) * std::cos(phiRandom), std::sin(thetaRandom) * std::sin(phiRandom), std::cos(thetaRandom)); - auto cosThetaStarRandom = randomVec.Dot(threeVecDauCM) / std::sqrt(threeVecDauCM.Mag2()); + auto cosThetaStarRandom = randomVec.Dot(fourVecDauCM.Vect()) / std::sqrt(fourVecDauCM.Vect().Mag2()); if (!isMix) { - hglue.fill(HIST("h3glueInvMassDS"), multiplicity, lv3.Pt(), lv3.M(), cosThetaStarRandom, angle_phi); + hglue.fill(HIST("h3glueInvMassDS"), multiplicity, mother.Pt(), mother.M(), cosThetaStarRandom, angle_phi); for (int i = 0; i < config.cRotations; i++) { - theta2 = rn->Uniform(0, o2::constants::math::PI); - hglue.fill(HIST("h3glueInvMassRot"), multiplicity, lv5.Pt(), lv5.M(), cosThetaStarRandom, angle_phi); + theta2 = rn->Uniform(o2::constants::math::PI - o2::constants::math::PI / config.rotationalCut, o2::constants::math::PI + o2::constants::math::PI / config.rotationalCut); + motherRot = ROOT::Math::PxPyPzMVector(mother.Px() * std::cos(theta2) - mother.Py() * std::sin(theta2), mother.Px() * std::sin(theta2) + mother.Py() * std::cos(theta2), mother.Pz(), mother.M()); + hglue.fill(HIST("h3glueInvMassRot"), multiplicity, motherRot.Pt(), motherRot.M(), cosThetaStarRandom, angle_phi); } } else { - hglue.fill(HIST("h3glueInvMassME"), multiplicity, lv3.Pt(), lv3.M(), cosThetaStarRandom, angle_phi); + hglue.fill(HIST("h3glueInvMassME"), multiplicity, mother.Pt(), mother.M(), cosThetaStarRandom, angle_phi); } } } @@ -798,23 +810,18 @@ struct HigherMassResonances { } allConditionsMet = 1; 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 - lv3.SetPtEtaPhiM(0.0, 0.0, 0.0, 0.0); - lv5.SetPtEtaPhiM(0.0, 0.0, 0.0, 0.0); - lv1.SetPtEtaPhiM(v1.pt(), v1.eta(), v1.phi(), o2::constants::physics::MassK0Short); - lv2.SetPtEtaPhiM(v2.pt(), v2.eta(), v2.phi(), o2::constants::physics::MassK0Short); - lv4.SetPtEtaPhiM(v1.pt(), v1.eta(), v1.phi() + theta2, o2::constants::physics::MassK0Short); // for rotated background - lv3 = lv1 + lv2; - lv5 = lv2 + lv4; + mother = daughter1 + daughter2; // invariant mass of Kshort pair isMix = false; if (!config.selectTWOKsOnly) - fillInvMass(lv3, lv5, multiplicity, daughter1, isMix); + fillInvMass(mother, multiplicity, daughter1, daughter2, isMix); } int sizeofv0indexes = v0indexes.size(); rKzeroShort.fill(HIST("NksProduced"), sizeofv0indexes); if (config.selectTWOKsOnly && sizeofv0indexes == 2 && allConditionsMet) { - fillInvMass(lv3, lv5, multiplicity, daughter1, false); + fillInvMass(mother, multiplicity, daughter1, daughter2, false); } v0indexes.clear(); } @@ -902,15 +909,11 @@ struct HigherMassResonances { } daughter1 = ROOT::Math::PxPyPzMVector(t1.px(), t1.py(), t1.pz(), o2::constants::physics::MassK0Short); // Kshort + daughter2 = ROOT::Math::PxPyPzMVector(t2.px(), t2.py(), t2.pz(), o2::constants::physics::MassK0Short); // Kshort - lv3.SetPtEtaPhiM(0.0, 0.0, 0.0, 0.0); - lv1.SetPtEtaPhiM(t1.pt(), t1.eta(), t1.phi(), o2::constants::physics::MassK0Short); - lv2.SetPtEtaPhiM(t2.pt(), t2.eta(), t2.phi(), o2::constants::physics::MassK0Short); - lv4.SetPtEtaPhiM(t1.pt(), t1.eta(), t1.phi() + theta2, o2::constants::physics::MassK0Short); // for rotated background - lv3 = lv1 + lv2; - lv5 = lv2 + lv4; + mother = daughter1 + daughter2; // invariant mass of Kshort pair isMix = true; - fillInvMass(lv3, lv5, multiplicity, daughter1, isMix); + fillInvMass(mother, multiplicity, daughter1, daughter2, isMix); } } } else { @@ -965,17 +968,12 @@ struct HigherMassResonances { if (!isSelectedV0Daughter(negtrack2, -1, nTPCSigmaNeg2, t2)) { continue; } - daughter1 = ROOT::Math::PxPyPzMVector(t1.px(), t1.py(), t1.pz(), o2::constants::physics::MassK0Short); // Kshort + daughter2 = ROOT::Math::PxPyPzMVector(t2.px(), t2.py(), t2.pz(), o2::constants::physics::MassK0Short); // Kshort - lv3.SetPtEtaPhiM(0.0, 0.0, 0.0, 0.0); - lv1.SetPtEtaPhiM(t1.pt(), t1.eta(), t1.phi(), o2::constants::physics::MassK0Short); - lv2.SetPtEtaPhiM(t2.pt(), t2.eta(), t2.phi(), o2::constants::physics::MassK0Short); - lv4.SetPtEtaPhiM(t1.pt(), t1.eta(), t1.phi() + theta2, o2::constants::physics::MassK0Short); // for rotated background - lv3 = lv1 + lv2; - lv5 = lv2 + lv4; + mother = daughter1 + daughter2; // invariant mass of Kshort pair isMix = true; - fillInvMass(lv3, lv5, multiplicity, daughter1, isMix); + fillInvMass(mother, multiplicity, daughter1, daughter2, isMix); } } } @@ -989,7 +987,7 @@ struct HigherMassResonances { if (config.isMC == false) { return; } - TLorentzVector lResonance_gen; + ROOT::Math::PxPyPzMVector lResonance_gen; hMChists.fill(HIST("events_check"), 0.5); if (std::abs(mcCollision.posZ()) < config.cutzvertex) { hMChists.fill(HIST("events_check"), 1.5); @@ -1075,16 +1073,16 @@ struct HigherMassResonances { if (std::abs(kCurrentDaughter.pdgCode()) == 310) { passKs = true; hMChists.fill(HIST("events_check"), 9.5); - fourVecDau1 = ROOT::Math::PxPyPzMVector(kCurrentDaughter.px(), kCurrentDaughter.py(), kCurrentDaughter.pz(), o2::constants::physics::MassK0Short); + daughter1 = ROOT::Math::PxPyPzMVector(kCurrentDaughter.px(), kCurrentDaughter.py(), kCurrentDaughter.pz(), o2::constants::physics::MassK0Short); } } if (passKs) { - lResonance_gen.SetPtEtaPhiE(mcParticle.pt(), mcParticle.eta(), mcParticle.phi(), mcParticle.e()); - fourVecMother = ROOT::Math::PxPyPzMVector(lResonance_gen.Px(), lResonance_gen.Py(), lResonance_gen.Pz(), lResonance_gen.M()); - ROOT::Math::Boost boost{fourVecMother.BoostToCM()}; - fourVecDauCM = boost(fourVecDau1); // boost the frame of daughter to the center of mass frame + lResonance_gen = ROOT::Math::PxPyPzMVector(mcParticle.pt(), mcParticle.eta(), mcParticle.phi(), mcParticle.e()); + mother = ROOT::Math::PxPyPzMVector(lResonance_gen.Px(), lResonance_gen.Py(), lResonance_gen.Pz(), lResonance_gen.M()); + ROOT::Math::Boost boost{mother.BoostToCM()}; + fourVecDauCM = boost(daughter1); // boost the frame of daughter to the center of mass frame - auto helicity_gen = fourVecDau1.Vect().Dot(fourVecDauCM.Vect()) / (std::sqrt(fourVecDauCM.Vect().Mag2()) * std::sqrt(fourVecDau1.Vect().Mag2())); + auto helicity_gen = daughter1.Vect().Dot(fourVecDauCM.Vect()) / (std::sqrt(fourVecDauCM.Vect().Mag2()) * std::sqrt(daughter1.Vect().Mag2())); hMChists.fill(HIST("Genf1710"), multiplicityGen, mcParticle.pt(), lResonance_gen.M(), helicity_gen); // hMChists.fill(HIST("Genf1710_mass"), lResonance_gen.M()); @@ -1102,7 +1100,7 @@ struct HigherMassResonances { return; } - TLorentzVector lDecayDaughter1, lDecayDaughter2, lResonance; + ROOT::Math::PxPyPzMVector lDecayDaughter1, lDecayDaughter2, lResonance; auto multiplicity = collision.centFT0C(); hMChists.fill(HIST("MC_mult"), multiplicity); @@ -1265,15 +1263,18 @@ struct HigherMassResonances { auto recMass = RecoDecay::m(arrMomrec, std::array{o2::constants::physics::MassK0Short, o2::constants::physics::MassK0Short}); // auto recpt = TMath::Sqrt((track1.px() + track2.px()) * (track1.px() + track2.px()) + (track1.py() + track2.py()) * (track1.py() + track2.py())); //// Resonance reconstruction - lDecayDaughter1.SetXYZM(v01.px(), v01.py(), v01.pz(), o2::constants::physics::MassK0Short); - lDecayDaughter2.SetXYZM(v02.px(), v02.py(), v02.pz(), o2::constants::physics::MassK0Short); + lDecayDaughter1 = ROOT::Math::PxPyPzMVector(v01.px(), v01.py(), v01.pz(), o2::constants::physics::MassK0Short); + lDecayDaughter2 = ROOT::Math::PxPyPzMVector(v02.px(), v02.py(), v02.pz(), o2::constants::physics::MassK0Short); lResonance = lDecayDaughter1 + lDecayDaughter2; - // fourVecDau1, fourVecMother, fourVecDauCM - fourVecMother = ROOT::Math::PxPyPzMVector(lResonance.Px(), lResonance.Py(), lResonance.Pz(), lResonance.M()); - fourVecDau1 = ROOT::Math::PxPyPzMVector(lDecayDaughter1.Px(), lDecayDaughter1.Py(), lDecayDaughter1.Pz(), o2::constants::physics::MassK0Short); - ROOT::Math::Boost boost{fourVecMother.BoostToCM()}; - fourVecDauCM = boost(fourVecDau1); // boost the frame of daughter to the center of mass frame - auto helicity_rec = fourVecDau1.Vect().Dot(fourVecDauCM.Vect()) / (std::sqrt(fourVecDauCM.Vect().Mag2()) * std::sqrt(fourVecDau1.Vect().Mag2())); + if (config.apply_rapidityMC && std::abs(lResonance.Y()) >= 0.5) { + continue; + } + // daughter1, mother, fourVecDauCM + mother = ROOT::Math::PxPyPzMVector(lResonance.Px(), lResonance.Py(), lResonance.Pz(), lResonance.M()); + daughter1 = ROOT::Math::PxPyPzMVector(lDecayDaughter1.Px(), lDecayDaughter1.Py(), lDecayDaughter1.Pz(), o2::constants::physics::MassK0Short); + ROOT::Math::Boost boost{mother.BoostToCM()}; + fourVecDauCM = boost(daughter1); // boost the frame of daughter to the center of mass frame + auto helicity_rec = daughter1.Vect().Dot(fourVecDauCM.Vect()) / (std::sqrt(fourVecDauCM.Vect().Mag2()) * std::sqrt(daughter1.Vect().Mag2())); // hMChists.fill(HIST("Recf1710_p"), motherP); // hMChists.fill(HIST("Recf1710_mass"), recMass); From e4dd7166e054cf046f9a49b06a57f931f7be074c Mon Sep 17 00:00:00 2001 From: yuanzhe <90246048+wang-yuanzhe@users.noreply.github.com> Date: Wed, 25 Jun 2025 20:53:13 +0200 Subject: [PATCH 215/871] [PWGLF] Fix bug in calculation of SV radii for hyphe4s (#11770) --- .../Nuspex/hyperhelium4sigmaRecoTask.cxx | 25 +++++++++++-------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/PWGLF/TableProducer/Nuspex/hyperhelium4sigmaRecoTask.cxx b/PWGLF/TableProducer/Nuspex/hyperhelium4sigmaRecoTask.cxx index cb0b35d8376..3e35c99e2df 100644 --- a/PWGLF/TableProducer/Nuspex/hyperhelium4sigmaRecoTask.cxx +++ b/PWGLF/TableProducer/Nuspex/hyperhelium4sigmaRecoTask.cxx @@ -374,9 +374,9 @@ struct Hyperhelium4sigmaRecoTask { hyphe4sCand.primVtx[0] = collision.posX(); hyphe4sCand.primVtx[1] = collision.posY(); hyphe4sCand.primVtx[2] = collision.posZ(); - hyphe4sCand.decVtx[0] = kinkCand.xDecVtx(); - hyphe4sCand.decVtx[1] = kinkCand.yDecVtx(); - hyphe4sCand.decVtx[2] = kinkCand.zDecVtx(); + hyphe4sCand.decVtx[0] = kinkCand.xDecVtx() + collision.posX(); + hyphe4sCand.decVtx[1] = kinkCand.yDecVtx() + collision.posY(); + hyphe4sCand.decVtx[2] = kinkCand.zDecVtx() + collision.posZ(); hyphe4sCand.momMoth[0] = kinkCand.pxMoth(); hyphe4sCand.momMoth[1] = kinkCand.pyMoth(); @@ -531,10 +531,11 @@ struct Hyperhelium4sigmaRecoTask { if (isTrueSignal) { auto mcMotherTrack = motherTrack.mcParticle_as(); auto mcDauTrack = dauTrack.mcParticle_as(); - float recSVR = std::sqrt(kinkCand.xDecVtx() * kinkCand.xDecVtx() + kinkCand.yDecVtx() * kinkCand.yDecVtx()); - registry.fill(HIST("hDiffSVx"), kinkCand.xDecVtx() - mcDauTrack.vx()); - registry.fill(HIST("hDiffSVy"), kinkCand.yDecVtx() - mcDauTrack.vy()); - registry.fill(HIST("hDiffSVz"), kinkCand.zDecVtx() - mcDauTrack.vz()); + float posDecVtx[3] = {kinkCand.xDecVtx() + collision.posX(), kinkCand.yDecVtx() + collision.posY(), kinkCand.zDecVtx() + collision.posZ()}; + float recSVR = std::sqrt(posDecVtx[0] * posDecVtx[0] + posDecVtx[1] * posDecVtx[1]); + registry.fill(HIST("hDiffSVx"), posDecVtx[0] - mcDauTrack.vx()); + registry.fill(HIST("hDiffSVy"), posDecVtx[1] - mcDauTrack.vy()); + registry.fill(HIST("hDiffSVz"), posDecVtx[2] - mcDauTrack.vz()); registry.fill(HIST("h2RecSVRVsTrueSVR"), recSVR, std::hypot(mcDauTrack.vx(), mcDauTrack.vy())); registry.fill(HIST("h2TrueMotherDiffPtVsRecSVR"), recSVR, mcMotherTrack.pt() - kinkCand.ptMoth()); registry.fill(HIST("h2TrueMotherDiffPzVsRecSVR"), recSVR, mcMotherTrack.pz() - kinkCand.pzMoth()); @@ -557,7 +558,7 @@ struct Hyperhelium4sigmaRecoTask { initCCDB(bc); std::array dcaInfo; auto mcMotherTrackPar = getTrackParFromMC(mcMotherTrack); - o2::base::Propagator::Instance()->propagateToDCABxByBz({kinkCand.xDecVtx(), kinkCand.yDecVtx(), kinkCand.zDecVtx()}, mcMotherTrackPar, 2.f, matCorr, &dcaInfo); + o2::base::Propagator::Instance()->propagateToDCABxByBz({posDecVtx[0], posDecVtx[1], posDecVtx[2]}, mcMotherTrackPar, 2.f, matCorr, &dcaInfo); registry.fill(HIST("hDCAXYMothToRecSV"), dcaInfo[0]); registry.fill(HIST("hDCAZMothToRecSV"), dcaInfo[1]); std::array pMotherAtSV = {-999.f, -999.f, -999.f}; @@ -570,7 +571,7 @@ struct Hyperhelium4sigmaRecoTask { float pMoth = std::hypot(kinkCand.pxMoth(), kinkCand.pyMoth(), kinkCand.pzMoth()); float pDaug = std::hypot(kinkCand.pxDaug(), kinkCand.pyDaug(), kinkCand.pzDaug()); - float mothPDir[3] = {kinkCand.xDecVtx() - collision.posX(), kinkCand.yDecVtx() - collision.posY(), kinkCand.zDecVtx() - collision.posZ()}; + float mothPDir[3] = {kinkCand.xDecVtx(), kinkCand.yDecVtx(), kinkCand.zDecVtx()}; float magMothPDirXY = std::hypot(mothPDir[0], mothPDir[1]); float magMothPDir = std::hypot(mothPDir[0], mothPDir[1], mothPDir[2]); float spKinkSV = mothPDir[0] * kinkCand.pxDaug() + mothPDir[1] * kinkCand.pyDaug() + mothPDir[2] * kinkCand.pzDaug(); @@ -998,8 +999,10 @@ struct Hyperhelium4sigmaQa { recoQAHist.fill(HIST("hDauAlphaIsPVContributer"), daughterTrack.isPVContributor() ? 1.5 : 0.5); float itsNSigma = itsResponse.nSigmaITS(daughterTrack); - recoQAHist.fill(HIST("hDauAlphaPVsITSNSigma"), daughterTrack.sign() * daughterTrack.p(), itsNSigma); - recoQAHist.fill(HIST("hDauAlphaITSCls"), daughterTrack.itsNCls()); + if (daughterTrack.hasITS()) { + recoQAHist.fill(HIST("hDauAlphaPVsITSNSigma"), daughterTrack.sign() * daughterTrack.p(), itsNSigma); + recoQAHist.fill(HIST("hDauAlphaITSCls"), daughterTrack.itsNCls()); + } if (motherTrack.has_collision() && daughterTrack.has_collision()) { recoQAHist.fill(HIST("hReco2BCandidateCount"), 1.5); From ce353243b696f63adfc17890199a54cd8f10654c Mon Sep 17 00:00:00 2001 From: Shirajum Monira <38348689+Eloviyo@users.noreply.github.com> Date: Thu, 26 Jun 2025 07:01:34 +0200 Subject: [PATCH 216/871] [PWGCF] FemtoUniverse V0Cascade task -- combined v0-cascade dataset & v0-cascade correlation task (#11772) Co-authored-by: Shirajum Monira --- .../Core/FemtoUniverseContainer.h | 16 +- .../Core/FemtoUniversePairCleaner.h | 17 + .../femtoUniverseProducerTask.cxx | 23 +- PWGCF/FemtoUniverse/Tasks/CMakeLists.txt | 7 +- ...toUniversePairTaskTrackCascadeExtended.cxx | 5 +- ...femtoUniversePairTaskV0CascadeExtended.cxx | 329 ++++++++++++++++++ 6 files changed, 385 insertions(+), 12 deletions(-) create mode 100644 PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskV0CascadeExtended.cxx diff --git a/PWGCF/FemtoUniverse/Core/FemtoUniverseContainer.h b/PWGCF/FemtoUniverse/Core/FemtoUniverseContainer.h index 04478ec7e0f..fb2af0a02df 100644 --- a/PWGCF/FemtoUniverse/Core/FemtoUniverseContainer.h +++ b/PWGCF/FemtoUniverse/Core/FemtoUniverseContainer.h @@ -20,17 +20,21 @@ #ifndef PWGCF_FEMTOUNIVERSE_CORE_FEMTOUNIVERSECONTAINER_H_ #define PWGCF_FEMTOUNIVERSE_CORE_FEMTOUNIVERSECONTAINER_H_ -#include -#include -#include +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseMath.h" +#include "PWGCF/FemtoUniverse/DataModel/FemtoDerived.h" -#include "Framework/HistogramRegistry.h" #include "Common/Core/RecoDecay.h" -#include "PWGCF/FemtoUniverse/Core/FemtoUniverseMath.h" + +#include "Framework/HistogramRegistry.h" #include "Math/Vector4D.h" -#include "TMath.h" #include "TDatabasePDG.h" +#include "TMath.h" + +#include + +#include +#include using namespace o2::framework; diff --git a/PWGCF/FemtoUniverse/Core/FemtoUniversePairCleaner.h b/PWGCF/FemtoUniverse/Core/FemtoUniversePairCleaner.h index b6a54f60b71..b27d8e25abf 100644 --- a/PWGCF/FemtoUniverse/Core/FemtoUniversePairCleaner.h +++ b/PWGCF/FemtoUniverse/Core/FemtoUniversePairCleaner.h @@ -131,6 +131,23 @@ class FemtoUniversePairCleaner return false; } return part1.globalIndex() != part2.globalIndex(); + } else if constexpr (kPartOneType == o2::aod::femtouniverseparticle::ParticleType::kV0 && kPartTwoType == o2::aod::femtouniverseparticle::ParticleType::kCascade) { + /// V0-Cascade combination where part1 is a V0 and part2 is a cascade + if (part1.partType() != o2::aod::femtouniverseparticle::ParticleType::kV0 || part2.partType() != o2::aod::femtouniverseparticle::ParticleType::kCascade) { + LOG(fatal) << "FemtoUniversePairCleaner: passed arguments don't agree with FemtoUniversePairCleaner instantiation! Please provide first argument kV0 candidate and second argument kCascade candidate."; + return false; + } + // part1 v0 children + const auto& posChild1 = particles.iteratorAt(part1.index() - 2); + const auto& negChild1 = particles.iteratorAt(part1.index() - 1); + // part2 cascade children + const auto& posChild2 = particles.iteratorAt(part2.index() - 3); + const auto& negChild2 = particles.iteratorAt(part2.index() - 2); + const auto& bachelor2 = particles.iteratorAt(part2.index() - 1); + if (posChild1.globalIndex() == posChild2.globalIndex() || negChild1.globalIndex() == negChild2.globalIndex() || posChild1.globalIndex() == bachelor2.globalIndex() || negChild1.globalIndex() == bachelor2.globalIndex()) { + return false; + } + return part1.globalIndex() != part2.globalIndex(); } else if constexpr (kPartOneType == o2::aod::femtouniverseparticle::ParticleType::kTrack && kPartTwoType == o2::aod::femtouniverseparticle::ParticleType::kD0) { /// Track-D0 combination part1 is hadron and part2 is D0 if (part2.partType() != o2::aod::femtouniverseparticle::ParticleType::kD0) { diff --git a/PWGCF/FemtoUniverse/TableProducer/femtoUniverseProducerTask.cxx b/PWGCF/FemtoUniverse/TableProducer/femtoUniverseProducerTask.cxx index 9111f50fa94..acd339fef4c 100644 --- a/PWGCF/FemtoUniverse/TableProducer/femtoUniverseProducerTask.cxx +++ b/PWGCF/FemtoUniverse/TableProducer/femtoUniverseProducerTask.cxx @@ -1907,9 +1907,6 @@ struct FemtoUniverseProducerTask { fillPhi(col, tracks); } } - // if (confIsActivateCascade) { - // fillCascade(col, fullCascades, tracks); - // } } void processFullData(aod::FemtoFullCollision const& col, @@ -1952,6 +1949,26 @@ struct FemtoUniverseProducerTask { } PROCESS_SWITCH(FemtoUniverseProducerTask, processTrackCascadeData, "Provide experimental data for track cascades", false); + void processTrackV0Cascade(aod::FemtoFullCollision const& col, + aod::BCsWithTimestamps const&, + soa::Filtered const& tracks, + o2::aod::V0Datas const& fullV0s, + o2::aod::CascDatas const& fullCascades) + { + getMagneticFieldTesla(col.bc_as()); + const auto colcheck = fillCollisions(col, tracks); + if (colcheck) { + fillTracks(tracks); + if (confIsActivateV0) { + fillV0(col, fullV0s, tracks); + } + if (confIsActivateCascade) { + fillCascade(col, fullCascades, tracks); + } + } + } + PROCESS_SWITCH(FemtoUniverseProducerTask, processTrackV0Cascade, "Provide experimental data for track, v0 and cascades", false); + /*void processTrackV0CentRun3(aod::FemtoFullCollisionCentRun3 const& col, aod::BCsWithTimestamps const&, soa::Filtered const& tracks, diff --git a/PWGCF/FemtoUniverse/Tasks/CMakeLists.txt b/PWGCF/FemtoUniverse/Tasks/CMakeLists.txt index 0a4682a7f7a..cae7a17fc56 100644 --- a/PWGCF/FemtoUniverse/Tasks/CMakeLists.txt +++ b/PWGCF/FemtoUniverse/Tasks/CMakeLists.txt @@ -59,6 +59,11 @@ o2physics_add_dpl_workflow(femtouniverse-pair-track-cascade-extended PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(femtouniverse-pair-v0-cascade-extended + SOURCES femtoUniversePairTaskV0CascadeExtended.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(femtouniverse-pair-track-d0 SOURCES femtoUniversePairTaskTrackD0.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore @@ -97,4 +102,4 @@ o2physics_add_dpl_workflow(femtouniverse-efficiency-base o2physics_add_executable(femtouniverse-cutculator SOURCES femtoUniverseCutCulator.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore - COMPONENT_NAME Analysis) \ No newline at end of file + COMPONENT_NAME Analysis) diff --git a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackCascadeExtended.cxx b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackCascadeExtended.cxx index d17cabb1f50..023117d42f7 100644 --- a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackCascadeExtended.cxx +++ b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackCascadeExtended.cxx @@ -64,8 +64,8 @@ struct femtoUniversePairTaskTrackCascadeExtended { // configurations for correlation part Configurable confTrackChoicePartOne{"confTrackChoicePartOne", 0, "0:Proton, 1:Pion, 2:Kaon"}; Configurable confTrkPDGCodePartOne{"confTrkPDGCodePartOne", 2212, "Particle 1 (Track) - PDG code"}; - Configurable confCascType1{"confCascType1", 0, "select one of the V0s (Omega = 0, Xi = 1, anti-Omega = 2, anti-Xi = 3) for track-cascade combination"}; - Configurable confCascType2{"confCascType2", 0, "select one of the V0s (Omega = 0, Xi = 1, anti-Omega = 2, anti-Xi = 3) for cascade-cascade combination"}; + 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 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"}; @@ -285,6 +285,7 @@ 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); pairCleaner.init(&qaRegistry); + pairCleanerCasc.init(&qaRegistry); if (confIsCPR.value) { pairCloseRejection.init(&resultRegistry, &qaRegistry, confCPRdeltaPhiCutMin.value, confCPRdeltaPhiCutMax.value, confCPRdeltaEtaCutMin.value, confCPRdeltaEtaCutMax.value, confCPRChosenRadii.value, confCPRPlotPerRadii.value, 0, 0, confIsSameSignCPR.value); } diff --git a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskV0CascadeExtended.cxx b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskV0CascadeExtended.cxx new file mode 100644 index 00000000000..a9212ab208a --- /dev/null +++ b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskV0CascadeExtended.cxx @@ -0,0 +1,329 @@ +// 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 femtoUniversePairTaskV0CascadeExtended.cxx +/// \brief Task for v0-cascade correlations and QA +/// \author Shirajum Monira, WUT Warsaw, shirajum.monira@cern.ch + +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseContainer.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseDetaDphiStar.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseEventHisto.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniversePairCleaner.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseParticleHisto.h" +#include "PWGCF/FemtoUniverse/Core/femtoUtils.h" +#include "PWGCF/FemtoUniverse/DataModel/FemtoDerived.h" + +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/O2DatabasePDGPlugin.h" +#include "Framework/RunningWorkflowInfo.h" +#include "Framework/StepTHn.h" +#include "Framework/runDataProcessing.h" + +#include +#include + +using namespace o2; +using namespace o2::soa; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::analysis::femto_universe; +using namespace o2::aod::pidutils; + +struct FemtoUniversePairTaskV0CascadeExtended { + + SliceCache cache; + using FemtoParticles = soa::Join; + Preslice perCol = aod::femtouniverseparticle::fdCollisionId; + + /// applying narrow cut + Configurable confZVertexCut{"confZVertexCut", 10.f, "Event sel: Maximum z-Vertex (cm)"}; + + Filter collisionFilter = (nabs(aod::collision::posZ) < confZVertexCut); + using FilteredFDCollisions = soa::Filtered; + using FilteredFDCollision = FilteredFDCollisions::iterator; + + /// particle 1 (v0) + 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 confV0Type{"confV0Type", 0, "select one of the V0s (lambda = 0, anti-lambda = 1, k0 = 2)"}; + Configurable confV0InvMassLowLimit{"confV0InvMassLowLimit", 1.10, "Lower limit of the V0 invariant mass"}; + Configurable confV0InvMassUpLimit{"confV0InvMassUpLimit", 1.13, "Upper limit of the V0 invariant mass"}; + Configurable confV0PDGCode{"confV0PDGCode", 3122, "Particle 1 (V0) - PDG code"}; + + /// particle 2 (cascade) + 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 confCascType{"confCascType", 0, "select one of the cascades (Omega = 0, Xi = 1, anti-Omega = 2, anti-Xi = 3)"}; + Configurable confCascInvMassLowLimit{"confCascInvMassLowLimit", 1.315, "Lower limit of the cascade invariant mass"}; + Configurable confCascInvMassUpLimit{"confCascInvMassUpLimit", 1.325, "Upper limit of the cascade invariant mass"}; + + /// nSigma cuts + Configurable confmom{"confmom", 0.75, "momentum threshold for particle identification using TOF"}; + Configurable confNsigmaTPCParticleChild{"confNsigmaTPCParticleChild", 3.0, "TPC Sigma for cascade (daugh & bach) momentum < Confmom"}; + Configurable confNsigmaTOFParticleChild{"confNsigmaTOFParticleChild", 3.0, "TOF Sigma for cascade (daugh & bach) momentum > Confmom"}; + + /// for correlation part + Configurable confIsMC{"confIsMC", false, "Enable additional Histograms in the case of a MonteCarlo Run"}; + 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"}; + ConfigurableAxis confmTBins{"confmTBins", {225, 0., 7.5}, "binning mT"}; + ConfigurableAxis confMultBins3D{"confMultBins3D", {VARIABLE_WIDTH, 0.0f, 20.0f, 30.0f, 40.0f, 99999.0f}, "multiplicity Binning for the 3Dimensional plot: k* vs multiplicity vs mT (set <> to true in order to use)"}; + ConfigurableAxis confmTBins3D{"confmTBins3D", {VARIABLE_WIDTH, 1.02f, 1.14f, 1.20f, 1.26f, 1.38f, 1.56f, 1.86f, 4.50f}, "mT Binning for the 3Dimensional plot: k* vs multiplicity vs mT (set <> to true in order to use)"}; + Configurable confEtaBins{"confEtaBins", 29, "Number of eta bins in deta dphi"}; + Configurable confPhiBins{"confPhiBins", 29, "Number of phi bins in deta dphi"}; + Configurable confUse3D{"confUse3D", false, "Enable three dimensional histogramms (to be used only for analysis with high statistics): k* vs mT vs multiplicity"}; + ConfigurableAxis confVtxBins{"confVtxBins", {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 confTrkTempFitVarpTBins{"confTrkTempFitVarpTBins", {20, 0.5, 4.05}, "pT binning of the pT vs. TempFitVar plot"}; + ConfigurableAxis confTrkTempFitVarBins{"confTrkTempFitVarBins", {300, -0.15, 0.15}, "binning of the TempFitVar in the pT vs. TempFitVar plot"}; + ConfigurableAxis confChildTempFitVarBins{"confChildTempFitVarBins", {300, -0.15, 0.15}, "V0 child: binning of the TempFitVar in the pT vs. TempFitVar plot"}; + ConfigurableAxis confChildTempFitVarpTBins{"confChildTempFitVarpTBins", {20, 0.5, 4.05}, "V0 child: pT binning of the pT vs. TempFitVar plot"}; + ConfigurableAxis confV0TempFitVarpTBins{"confV0TempFitVarpTBins", {20, 0.5, 4.05}, "V0: pT binning of the pT vs. TempFitVar plot"}; + ConfigurableAxis confV0TempFitVarBins{"confV0TempFitVarBins", {300, 0.95, 1.}, "V0: binning of the TempFitVar in the pT vs. TempFitVar plot"}; + + /// Partition for particle 1 + Partition partsOne = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kV0)) && (aod::femtouniverseparticle::pt < confHPtPart1) && (aod::femtouniverseparticle::pt > confLPtPart1); + + /// Partition for particle 2 + Partition partsTwo = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kCascade)) && (aod::femtouniverseparticle::pt < confHPtPart2) && (aod::femtouniverseparticle::pt > confLPtPart2); + + /// Histogramming for v0 + FemtoUniverseParticleHisto trackHistoV0; + FemtoUniverseParticleHisto posChildV0; + FemtoUniverseParticleHisto negChildV0; + + /// Histogramming for cascade + FemtoUniverseParticleHisto posChildHistosCasc; + FemtoUniverseParticleHisto negChildHistosCasc; + FemtoUniverseParticleHisto bachHistosCasc; + FemtoUniverseParticleHisto cascQAHistos; + + /// Histogramming for Event + FemtoUniverseEventHisto eventHisto; + + FemtoUniverseContainer sameEventCont; + FemtoUniverseContainer mixedEventCont; + FemtoUniversePairCleaner pairCleaner; + + HistogramRegistry qaRegistry{"TrackQA", {}, OutputObjHandlingPolicy::AnalysisObject}; + HistogramRegistry resultRegistry{"Correlations", {}, OutputObjHandlingPolicy::AnalysisObject}; + + // Table to select v0 daughters + static constexpr unsigned int V0ChildTable[][2] = {{0, 1}, {1, 0}, {1, 1}}; + + bool invMLambda(float invMassLambda, float invMassAntiLambda) + { + if ((invMassLambda < confV0InvMassLowLimit || invMassLambda > confV0InvMassUpLimit) && (invMassAntiLambda < confV0InvMassLowLimit || invMassAntiLambda > confV0InvMassUpLimit)) { + return false; + } + return true; + } + + // Table to select cascade daughters + // Charges: = +--, +--, +-+, +-+ + static constexpr unsigned int CascChildTable[][3] = {{0, 1, 2}, {0, 1, 1}, {1, 0, 2}, {1, 0, 1}}; + + bool invMCascade(float invMassXi, float invMassOmega, int cascType) + { + return (((cascType == 1 || cascType == 3) && (invMassXi > confCascInvMassLowLimit && invMassXi < confCascInvMassUpLimit)) || ((cascType == 0 || cascType == 2) && (invMassOmega > confCascInvMassLowLimit && invMassOmega < confCascInvMassUpLimit))); + } + + bool isNSigmaTPC(float nsigmaTPCParticle) + { + if (std::abs(nsigmaTPCParticle) < confNsigmaTPCParticleChild) { + return true; + } else { + return false; + } + } + + bool isNSigmaTOF(float mom, float nsigmaTOFParticle, float hasTOF) + { + // Cut only on daughter and bachelor tracks, that have TOF signal + if (mom > confmom && hasTOF == 1) { + if (std::abs(nsigmaTOFParticle) < confNsigmaTOFParticleChild) { + return true; + } else { + return false; + } + } else { + return true; + } + } + + template + bool isParticleTPC(const T& part, int id) + { + const float tpcNSigmas[3] = {unPackInTable(part.tpcNSigmaStorePr()), unPackInTable(part.tpcNSigmaStorePi()), unPackInTable(part.tpcNSigmaStoreKa())}; + + return isNSigmaTPC(tpcNSigmas[id]); + } + + template + bool isParticleTOF(const T& part, int id) + { + const float tofNSigmas[3] = {unPackInTable(part.tofNSigmaStorePr()), unPackInTable(part.tofNSigmaStorePi()), unPackInTable(part.tofNSigmaStoreKa())}; + + return isNSigmaTOF(part.p(), tofNSigmas[id], part.tempFitVar()); + } + + void init(InitContext const&) + { + trackHistoV0.init(&qaRegistry, confV0TempFitVarpTBins, confV0TempFitVarBins, confIsMC, confV0PDGCode, true, "trackHistoV0"); + posChildV0.init(&qaRegistry, confChildTempFitVarpTBins, confChildTempFitVarBins, false, 0, true, "posChildV0"); + negChildV0.init(&qaRegistry, confChildTempFitVarpTBins, confChildTempFitVarBins, false, 0, true, "negChildV0"); + + posChildHistosCasc.init(&qaRegistry, confChildTempFitVarpTBins, confChildTempFitVarBins, false, 0, true, "posChildCasc"); + negChildHistosCasc.init(&qaRegistry, confChildTempFitVarpTBins, confChildTempFitVarBins, false, 0, true, "negChildCasc"); + bachHistosCasc.init(&qaRegistry, confChildTempFitVarpTBins, confChildTempFitVarBins, false, 0, true, "hBachelor"); + cascQAHistos.init(&qaRegistry, confChildTempFitVarpTBins, confChildTempFitVarBins, false, 0, true); + + 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); + pairCleaner.init(&qaRegistry); + } + + /// v0-cascade correlations same event + void processSameEvent(const FilteredFDCollision& col, const FemtoParticles& parts) + { + auto groupPartsOne = partsOne->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); + auto groupPartsTwo = partsTwo->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); + + eventHisto.fillQA(col); + + for (const auto& part : groupPartsTwo) { + /// inv Mass check for cascade + if (!invMCascade(part.mLambda(), part.mAntiLambda(), confCascType)) + continue; + + cascQAHistos.fillQA(part); + + const auto& posChild1 = parts.iteratorAt(part.index() - 3); + const auto& negChild1 = parts.iteratorAt(part.index() - 2); + const auto& bachelor1 = parts.iteratorAt(part.index() - 1); + /// Children of cascade must pass this condition to be selected + if (!isParticleTPC(posChild1, CascChildTable[confCascType][0]) || !isParticleTPC(negChild1, CascChildTable[confCascType][1]) || !isParticleTPC(bachelor1, CascChildTable[confCascType][2])) + continue; + + if (!isParticleTOF(posChild1, CascChildTable[confCascType][0]) || !isParticleTOF(negChild1, CascChildTable[confCascType][1]) || !isParticleTOF(bachelor1, CascChildTable[confCascType][2])) + continue; + + posChildHistosCasc.fillQABase(posChild1, HIST("posChildCasc")); + negChildHistosCasc.fillQABase(negChild1, HIST("negChildCasc")); + bachHistosCasc.fillQABase(bachelor1, HIST("hBachelor")); + } + for (const auto& part : groupPartsOne) { + /// inv Mass check for V0s + if (!invMLambda(part.mLambda(), part.mAntiLambda())) + continue; + const auto& posChild2 = parts.iteratorAt(part.index() - 2); + const auto& negChild2 = parts.iteratorAt(part.index() - 1); + /// Daughters of v0 must pass this condition to be selected + if (!isParticleTPC(posChild2, V0ChildTable[confV0Type][0]) || !isParticleTPC(negChild2, V0ChildTable[confV0Type][1])) + continue; + + trackHistoV0.fillQABase(part, HIST("trackHistoV0")); + posChildV0.fillQABase(posChild2, HIST("posChildV0")); + negChildV0.fillQABase(negChild2, HIST("negChildV0")); + } + for (const auto& [p1, p2] : combinations(CombinationsFullIndexPolicy(groupPartsOne, groupPartsTwo))) { + if (!invMLambda(p1.mLambda(), p1.mAntiLambda())) + continue; + // Cascase inv Mass cut (mLambda stores Xi mass, mAntiLambda stored Omega mass) + if (!invMCascade(p2.mLambda(), p2.mAntiLambda(), confCascType)) + continue; + // track cleaning + if (!pairCleaner.isCleanPair(p1, p2, parts)) { + continue; + } + // V0 + const auto& posChild2 = parts.iteratorAt(p1.index() - 2); + const auto& negChild2 = parts.iteratorAt(p1.index() - 1); + /// Daughters of v0 must pass this condition to be selected + if (!isParticleTPC(posChild2, V0ChildTable[confV0Type][0]) || !isParticleTPC(negChild2, V0ChildTable[confV0Type][1])) + continue; + // cascade + const auto& posChild1 = parts.iteratorAt(p2.index() - 3); + const auto& negChild1 = parts.iteratorAt(p2.index() - 2); + const auto& bachelor1 = parts.iteratorAt(p2.index() - 1); + /// Daughters of cascade must pass this condition to be selected + if (!isParticleTPC(posChild1, CascChildTable[confCascType][0]) || !isParticleTPC(negChild1, CascChildTable[confCascType][1]) || !isParticleTPC(bachelor1, CascChildTable[confCascType][2])) + continue; + + if (!isParticleTOF(posChild1, CascChildTable[confCascType][0]) || !isParticleTOF(negChild1, CascChildTable[confCascType][1]) || !isParticleTOF(bachelor1, CascChildTable[confCascType][2])) + continue; + + sameEventCont.setPair(p1, p2, col.multNtr(), confUse3D, 1.0f); + } + } + PROCESS_SWITCH(FemtoUniversePairTaskV0CascadeExtended, processSameEvent, "Enable processing same event for v0 - cascade", false); + + /// v0-cascade correlations mixed event + void processMixedEvent(const FilteredFDCollisions& cols, const FemtoParticles& parts) + { + ColumnBinningPolicy colBinning{{confVtxBins, confMultBins}, true}; + + for (const auto& [collision1, collision2] : soa::selfCombinations(colBinning, 5, -1, cols, cols)) { + const int multCol = 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))) { + if (!invMLambda(p1.mLambda(), p1.mAntiLambda())) + continue; + // Cascase inv Mass cut (mLambda stores Xi mass, mAntiLambda stored Omega mass) + if (!invMCascade(p2.mLambda(), p2.mAntiLambda(), confCascType)) + continue; + // V0 + const auto& posChild2 = parts.iteratorAt(p1.index() - 2); + const auto& negChild2 = parts.iteratorAt(p1.index() - 1); + /// Daughters of v0 must pass this condition to be selected + if (!isParticleTPC(posChild2, V0ChildTable[confV0Type][0]) || !isParticleTPC(negChild2, V0ChildTable[confV0Type][1])) + continue; + // cascade + const auto& posChild1 = parts.iteratorAt(p2.index() - 3); + const auto& negChild1 = parts.iteratorAt(p2.index() - 2); + const auto& bachelor1 = parts.iteratorAt(p2.index() - 1); + /// Daughters of cascade must pass this condition to be selected + if (!isParticleTPC(posChild1, CascChildTable[confCascType][0]) || !isParticleTPC(negChild1, CascChildTable[confCascType][1]) || !isParticleTPC(bachelor1, CascChildTable[confCascType][2])) + continue; + + if (!isParticleTOF(posChild1, CascChildTable[confCascType][0]) || !isParticleTOF(negChild1, CascChildTable[confCascType][1]) || !isParticleTOF(bachelor1, CascChildTable[confCascType][2])) + continue; + + // track cleaning + if (!pairCleaner.isCleanPair(p1, p2, parts)) { + continue; + } + + mixedEventCont.setPair(p1, p2, multCol, confUse3D, 1.0f); + } + } + } + PROCESS_SWITCH(FemtoUniversePairTaskV0CascadeExtended, processMixedEvent, "Enable processing mixed event for v0 - cascade", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + WorkflowSpec workflow{ + adaptAnalysisTask(cfgc), + }; + return workflow; +} From f1d4570e879e235fef43c1c3edd4304f9e12bbe6 Mon Sep 17 00:00:00 2001 From: amaringarcia Date: Thu, 26 Jun 2025 09:42:04 +0200 Subject: [PATCH 217/871] [Common,DPG] [DPG][Common] Test of dE/dx correction for occupancy (#11747) --- Common/TableProducer/PID/CMakeLists.txt | 2 +- Common/TableProducer/PID/pidTPC.cxx | 124 +++++- Common/TableProducer/PID/pidTPCBase.cxx | 113 ++++- Common/TableProducer/PID/pidTPCBase.h | 46 ++ DPG/Tasks/TPC/tpcSkimsTableCreator.cxx | 553 +++++++++++++++++++++++- 5 files changed, 794 insertions(+), 44 deletions(-) diff --git a/Common/TableProducer/PID/CMakeLists.txt b/Common/TableProducer/PID/CMakeLists.txt index d28a3268954..afcda3e1be6 100644 --- a/Common/TableProducer/PID/CMakeLists.txt +++ b/Common/TableProducer/PID/CMakeLists.txt @@ -45,7 +45,7 @@ o2physics_add_dpl_workflow(pid-tof-full o2physics_add_dpl_workflow(pid-tpc-base SOURCES pidTPCBase.cxx - PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::AnalysisCCDB COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(pid-tpc diff --git a/Common/TableProducer/PID/pidTPC.cxx b/Common/TableProducer/PID/pidTPC.cxx index 64500a47cb7..6cdca389a65 100644 --- a/Common/TableProducer/PID/pidTPC.cxx +++ b/Common/TableProducer/PID/pidTPC.cxx @@ -18,10 +18,10 @@ /// \brief Task to produce PID tables for TPC split for each particle. /// Only the tables for the mass hypotheses requested are filled, and only for the requested table size ("Full" or "Tiny"). The others are sent empty. /// -#include #include #include #include +#include #include // ROOT includes #include "TFile.h" @@ -29,21 +29,23 @@ #include "TSystem.h" // O2 includes +#include "MetadataHelper.h" +#include "TableHelper.h" +#include "pidTPCBase.h" + +#include "Common/Core/PID/TPCPIDResponse.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/PIDResponseTPC.h" +#include "Tools/ML/model.h" + #include "CCDB/BasicCCDBManager.h" +#include "CCDB/CcdbApi.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" #include "Framework/AnalysisTask.h" #include "Framework/runDataProcessing.h" -#include "Framework/ASoAHelpers.h" #include "ReconstructionDataFormats/Track.h" -#include "CCDB/CcdbApi.h" -#include "Common/DataModel/PIDResponseTPC.h" -#include "Common/Core/PID/TPCPIDResponse.h" -#include "Framework/AnalysisDataModel.h" -#include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/EventSelection.h" -#include "TableHelper.h" -#include "Tools/ML/model.h" -#include "pidTPCBase.h" -#include "MetadataHelper.h" using namespace o2; using namespace o2::framework; @@ -155,8 +157,10 @@ struct tpcPid { void init(o2::framework::InitContext& initContext) { // Protection for process flags - if ((doprocessStandard && doprocessMcTuneOnData) || (!doprocessStandard && !doprocessMcTuneOnData)) { - LOG(fatal) << "pid-tpc must have only one of the options 'processStandard' OR 'processMcTuneOnData' enabled. Please check your configuration."; + if (!((doprocessStandard && !doprocessStandard2 && !doprocessMcTuneOnData) || + (!doprocessStandard && doprocessStandard2 && !doprocessMcTuneOnData) || + (!doprocessStandard && !doprocessStandard2 && doprocessMcTuneOnData))) { + LOG(fatal) << "pid-tpc must have only one of the options 'processStandard', 'processStandard2', 'processMcTuneOnData' enabled. Please check your configuration."; } response = new o2::pid::tpc::Response(); // Checking the tables are requested in the workflow and enabling them @@ -552,6 +556,98 @@ struct tpcPid { Partition mcnotTPCStandaloneTracks = (aod::track::tpcNClsFindable > static_cast(0)) && ((aod::track::itsClusterSizes > static_cast(0)) || (aod::track::trdPattern > static_cast(0)) || (aod::track::tofExpMom > 0.f && aod::track::tofChi2 > 0.f)); // To count number of tracks for use in NN array Partition mctracksWithTPC = (aod::track::tpcNClsFindable > (uint8_t)0); + void processStandard2(Coll const& collisions, Trks const& tracks, aod::DEdxsCorrected const& dedxscorrected, aod::BCsWithTimestamps const& bcs) + { + const uint64_t outTable_size = tracks.size(); + const uint64_t dedxscorrected_size = dedxscorrected.size(); + + if (dedxscorrected_size != outTable_size) { + LOG(fatal) << "Size of dEdx corrected table does not match size of tracks! dEdx size: " << dedxscorrected_size << ", tracks size: " << outTable_size; + } + + auto reserveTable = [&outTable_size](const Configurable& flag, auto& table) { + if (flag.value != 1) { + return; + } + table.reserve(outTable_size); + }; + + // Prepare memory for enabled tables + reserveTable(pidFullEl, tablePIDFullEl); + reserveTable(pidFullMu, tablePIDFullMu); + reserveTable(pidFullPi, tablePIDFullPi); + reserveTable(pidFullKa, tablePIDFullKa); + reserveTable(pidFullPr, tablePIDFullPr); + reserveTable(pidFullDe, tablePIDFullDe); + reserveTable(pidFullTr, tablePIDFullTr); + reserveTable(pidFullHe, tablePIDFullHe); + reserveTable(pidFullAl, tablePIDFullAl); + + reserveTable(pidTinyEl, tablePIDTinyEl); + reserveTable(pidTinyMu, tablePIDTinyMu); + reserveTable(pidTinyPi, tablePIDTinyPi); + reserveTable(pidTinyKa, tablePIDTinyKa); + reserveTable(pidTinyPr, tablePIDTinyPr); + reserveTable(pidTinyDe, tablePIDTinyDe); + reserveTable(pidTinyTr, tablePIDTinyTr); + reserveTable(pidTinyHe, tablePIDTinyHe); + reserveTable(pidTinyAl, tablePIDTinyAl); + + const uint64_t tracksForNet_size = (skipTPCOnly) ? notTPCStandaloneTracks.size() : tracksWithTPC.size(); + std::vector network_prediction; + + if (useNetworkCorrection) { + network_prediction = createNetworkPrediction(collisions, tracks, bcs, tracksForNet_size); + } + + uint64_t count_tracks = 0; + uint64_t count_tracks2 = 0; + + for (auto const& trk : tracks) { + // Loop on Tracks + + const auto& bc = trk.has_collision() ? collisions.iteratorAt(trk.collisionId()).bc_as() : bcs.begin(); + auto dedx_corr = dedxscorrected.iteratorAt(count_tracks2); + count_tracks2++; + if (useCCDBParam && ccdbTimestamp.value == 0 && !ccdb->isCachedObjectValid(ccdbPath.value, bc.timestamp())) { // Updating parametrisation only if the initial timestamp is 0 + if (recoPass.value == "") { + LOGP(info, "Retrieving latest TPC response object for timestamp {}:", bc.timestamp()); + } else { + LOGP(info, "Retrieving TPC Response for timestamp {} and recoPass {}:", bc.timestamp(), recoPass.value); + } + response = ccdb->getSpecific(ccdbPath.value, bc.timestamp(), metadata); + headers = ccdbApi.retrieveHeaders(ccdbPath.value, metadata, bc.timestamp()); + if (!response) { + LOGP(warning, "!! Could not find a valid TPC response object for specific pass name {}! Falling back to latest uploaded object.", metadata["RecoPassName"]); + response = ccdb->getForTimeStamp(ccdbPath.value, bc.timestamp()); + headers = ccdbApi.retrieveHeaders(ccdbPath.value, nullmetadata, bc.timestamp()); + if (!response) { + LOGP(fatal, "Could not find ANY TPC response object for the timestamp {}!", bc.timestamp()); + } + } + LOG(info) << "Successfully retrieved TPC PID object from CCDB for timestamp " << bc.timestamp() << ", period " << headers["LPMProductionTag"] << ", recoPass " << headers["RecoPassName"]; + response->PrintAll(); + } + auto makePidTablesDefault = [&trk, &dedx_corr, &collisions, &network_prediction, &count_tracks, &tracksForNet_size, this](const int flagFull, auto& tableFull, const int flagTiny, auto& tableTiny, const o2::track::PID::ID pid) { + makePidTables(flagFull, tableFull, flagTiny, tableTiny, pid, dedx_corr.tpcSignalCorrected(), trk, collisions, network_prediction, count_tracks, tracksForNet_size); + }; + + makePidTablesDefault(pidFullEl, tablePIDFullEl, pidTinyEl, tablePIDTinyEl, o2::track::PID::Electron); + makePidTablesDefault(pidFullMu, tablePIDFullMu, pidTinyMu, tablePIDTinyMu, o2::track::PID::Muon); + makePidTablesDefault(pidFullPi, tablePIDFullPi, pidTinyPi, tablePIDTinyPi, o2::track::PID::Pion); + makePidTablesDefault(pidFullKa, tablePIDFullKa, pidTinyKa, tablePIDTinyKa, o2::track::PID::Kaon); + makePidTablesDefault(pidFullPr, tablePIDFullPr, pidTinyPr, tablePIDTinyPr, o2::track::PID::Proton); + makePidTablesDefault(pidFullDe, tablePIDFullDe, pidTinyDe, tablePIDTinyDe, o2::track::PID::Deuteron); + makePidTablesDefault(pidFullTr, tablePIDFullTr, pidTinyTr, tablePIDTinyTr, o2::track::PID::Triton); + makePidTablesDefault(pidFullHe, tablePIDFullHe, pidTinyHe, tablePIDTinyHe, o2::track::PID::Helium3); + makePidTablesDefault(pidFullAl, tablePIDFullAl, pidTinyAl, tablePIDTinyAl, o2::track::PID::Alpha); + + if (trk.hasTPC() && (!skipTPCOnly || trk.hasITS() || trk.hasTRD() || trk.hasTOF())) { + count_tracks++; // Increment network track counter only if track has TPC, and (not skipping TPConly) or (is not TPConly) + } + } + } + PROCESS_SWITCH(tpcPid, processStandard2, "Creating PID tables with Corrected dEdx", false); void processMcTuneOnData(CollMC const& collisionsMc, TrksMC const& tracksMc, aod::BCsWithTimestamps const& bcs, aod::McParticles const&) { gRandom->SetSeed(0); // Ensure unique seed from UUID for each process call diff --git a/Common/TableProducer/PID/pidTPCBase.cxx b/Common/TableProducer/PID/pidTPCBase.cxx index cf82ea0c9d5..e28f4a55b4d 100644 --- a/Common/TableProducer/PID/pidTPCBase.cxx +++ b/Common/TableProducer/PID/pidTPCBase.cxx @@ -15,18 +15,21 @@ /// \brief Base to build tasks for TPC PID tasks. /// +#include #include #include -#include // O2 includes -#include "CCDB/BasicCCDBManager.h" -#include "Framework/AnalysisTask.h" -#include "ReconstructionDataFormats/Track.h" -#include "Common/DataModel/FT0Corrected.h" #include "TableHelper.h" #include "pidTPCBase.h" + +#include "Common/CCDB/ctpRateFetcher.h" +#include "Common/DataModel/FT0Corrected.h" + +#include "CCDB/BasicCCDBManager.h" +#include "Framework/AnalysisTask.h" #include "Framework/runDataProcessing.h" +#include "ReconstructionDataFormats/Track.h" using namespace o2; using namespace o2::framework; @@ -76,7 +79,105 @@ struct PidMultiplicity { PROCESS_SWITCH(PidMultiplicity, processStandard, "Process with tracks, needs propagated tracks", true); }; +struct DeDxCorrection { + Produces dEdxCorrected; + using BCsRun3 = soa::Join; + using ColEvSels = soa::Join; + using FullTracksIU = soa::Join; + + uint64_t minGlobalBC = 0; + Service ccdb; + ctpRateFetcher mRateFetcher; + + Str_dEdx_correction str_dedx_correction; + + // void init(InitContext& initContext) + void init(o2::framework::InitContext&) + { + ccdb->setURL("http://alice-ccdb.cern.ch"); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + str_dedx_correction.init(); + } + + void processRun3( + ColEvSels const& cols, + FullTracksIU const& tracks, + aod::BCsWithTimestamps const& bcs) + { + const uint64_t outTable_size = tracks.size(); + dEdxCorrected.reserve(outTable_size); + + for (auto const& trk : tracks) { + double hadronicRate; + int multTPC; + int occupancy; + if (trk.has_collision()) { + auto collision = cols.iteratorAt(trk.collisionId()); + auto bc = collision.bc_as(); + const int runnumber = bc.runNumber(); + hadronicRate = mRateFetcher.fetch(ccdb.service, bc.timestamp(), runnumber, "ZNC hadronic") * 1.e-3; // kHz + multTPC = collision.multTPC(); + occupancy = collision.trackOccupancyInTimeRange(); + } else { + auto bc = bcs.begin(); + const int runnumber = bc.runNumber(); + hadronicRate = mRateFetcher.fetch(ccdb.service, bc.timestamp(), runnumber, "ZNC hadronic") * 1.e-3; // kHz + multTPC = 0; + occupancy = 0; + } + + float fTPCSignal = trk.tpcSignal(); + float fNormMultTPC = multTPC / 11000.; + + float fTrackOccN = occupancy / 1000.; + float fOccTPCN = fNormMultTPC * 10; //(fNormMultTPC*10).clip(0,12) + if (fOccTPCN > 12) + fOccTPCN = 12; + else if (fOccTPCN < 0) + fOccTPCN = 0; + + float fTrackOccMeanN = hadronicRate / 5; + float side = trk.tgl() > 0 ? 1 : 0; + float a1pt = std::abs(trk.signed1Pt()); + float a1pt2 = a1pt * a1pt; + float atgl = std::abs(trk.tgl()); + float mbb0R = 50 / fTPCSignal; + if (mbb0R > 1.05) + mbb0R = 1.05; + else if (mbb0R < 0.05) + mbb0R = 0.05; + // float mbb0R = max(0.05, min(50 / fTPCSignal, 1.05)); + float a1ptmbb0R = a1pt * mbb0R; + float atglmbb0R = atgl * mbb0R; + + std::vector vec_occu = {fTrackOccN, fOccTPCN, fTrackOccMeanN}; + std::vector vec_track = {mbb0R, a1pt, atgl, atglmbb0R, a1ptmbb0R, side, a1pt2}; + + float fTPCSignalN_CR0 = str_dedx_correction.fReal_fTPCSignalN(vec_occu, vec_track); + + float mbb0R1 = 50 / (fTPCSignal / fTPCSignalN_CR0); + if (mbb0R1 > 1.05) + mbb0R1 = 1.05; + else if (mbb0R1 < 0.05) + mbb0R1 = 0.05; + + std::vector vec_track1 = {mbb0R1, a1pt, atgl, atgl * mbb0R1, a1pt * mbb0R1, side, a1pt2}; + float fTPCSignalN_CR1 = str_dedx_correction.fReal_fTPCSignalN(vec_occu, vec_track1); + + float corrected_dEdx = fTPCSignal / fTPCSignalN_CR1; + dEdxCorrected(corrected_dEdx); + } + } + PROCESS_SWITCH(DeDxCorrection, processRun3, "dEdx correction process", false); + + void processDummy(ColEvSels const&) {} + + PROCESS_SWITCH(DeDxCorrection, processDummy, "Do nothing", true); +}; + WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { - return WorkflowSpec{adaptAnalysisTask(cfgc)}; + return WorkflowSpec{adaptAnalysisTask(cfgc), + adaptAnalysisTask(cfgc)}; } diff --git a/Common/TableProducer/PID/pidTPCBase.h b/Common/TableProducer/PID/pidTPCBase.h index 937eea21c48..5fe8bb4726b 100644 --- a/Common/TableProducer/PID/pidTPCBase.h +++ b/Common/TableProducer/PID/pidTPCBase.h @@ -21,13 +21,22 @@ #include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/PIDResponseTPC.h" +#include "TMatrixD.h" + namespace o2::aod { +namespace pid +{ +DECLARE_SOA_COLUMN(TpcSignalCorrected, tpcSignalCorrected, float); //! +}; // namespace pid + DECLARE_SOA_TABLE(PIDMults, "AOD", "PIDMults", //! TPC auxiliary table for the PID o2::soa::Marker<1>, mult::MultTPC); +DECLARE_SOA_TABLE_FULL(DEdxsCorrected, "DEdxsCorrected", "AOD", "DEDXCORR", pid::TpcSignalCorrected); //! using PIDMult = PIDMults::iterator; +using DEdxCorrected = DEdxsCorrected::iterator; //! } // namespace o2::aod @@ -57,4 +66,41 @@ int getPIDIndex(const int pdgCode) // Get O2 PID index corresponding to MC PDG c } } +typedef struct Str_dEdx_correction { + TMatrixD fMatrix; + bool warning = true; + + // void init(std::vector& params) + void init() + { + double elements[32] = {0.99091, -0.015053, 0.0018912, -0.012305, + 0.081387, 0.003205, -0.0087404, -0.0028608, + 0.013066, 0.017012, -0.0018469, -0.0052177, + -0.0035655, 0.0017846, 0.0019127, -0.00012964, + 0.0049428, 0.0055592, -0.0010618, -0.0016134, + -0.0059098, 0.0013335, 0.00052133, 3.1119e-05, + -0.004882, 0.00077317, -0.0013827, 0.003249, + -0.00063689, 0.0016218, -0.00045215, -1.5815e-05}; + fMatrix.ResizeTo(4, 8); + fMatrix.SetMatrixArray(elements); + } + + float fReal_fTPCSignalN(std::vector& vec1, std::vector& vec2) + { + float result = 0.f; + // push 1. + vec1.insert(vec1.begin(), 1.0); + vec2.insert(vec2.begin(), 1.0); + for (int i = 0; i < fMatrix.GetNrows(); i++) { + for (int j = 0; j < fMatrix.GetNcols(); j++) { + double param = fMatrix(i, j); + double value1 = i > static_cast(vec1.size()) ? 0 : vec1[i]; + double value2 = j > static_cast(vec2.size()) ? 0 : vec2[j]; + result += param * value1 * value2; + } + } + return result; + } +} Str_dEdx_correction; + #endif // COMMON_TABLEPRODUCER_PID_PIDTPCBASE_H_ diff --git a/DPG/Tasks/TPC/tpcSkimsTableCreator.cxx b/DPG/Tasks/TPC/tpcSkimsTableCreator.cxx index 6c3d1304cfe..2a2d644e7c4 100644 --- a/DPG/Tasks/TPC/tpcSkimsTableCreator.cxx +++ b/DPG/Tasks/TPC/tpcSkimsTableCreator.cxx @@ -17,29 +17,33 @@ /// \author Jeremy Wilkinson #include "tpcSkimsTableCreator.h" + #include + #include -#include #include +#include /// ROOT #include "TRandom3.h" /// O2 -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" #include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" #include "Framework/runDataProcessing.h" /// O2Physics +#include "PWGDQ/DataModel/ReducedInfoTables.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" + +#include "Common/CCDB/ctpRateFetcher.h" #include "Common/Core/trackUtilities.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/OccupancyTables.h" #include "Common/DataModel/PIDResponse.h" #include "Common/DataModel/PIDResponseITS.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "PWGLF/DataModel/LFStrangenessTables.h" -#include "PWGDQ/DataModel/ReducedInfoTables.h" -#include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/CCDB/ctpRateFetcher.h" -#include "Common/DataModel/OccupancyTables.h" +#include "Common/TableProducer/PID/pidTPCBase.h" using namespace o2; using namespace o2::framework; @@ -52,6 +56,7 @@ struct TreeWriterTpcV0 { Service ccdb; using Trks = soa::Join; + using TrksWithDEdxCorrection = soa::Join; using Colls = soa::Join; using MyBCTable = soa::Join; using V0sWithID = soa::Join; @@ -89,7 +94,7 @@ struct TreeWriterTpcV0 { ctpRateFetcher mRateFetcher; /// Funktion to fill skimmed tables - template + template void fillSkimmedV0Table(V0 const& v0, T const& track, C const& collision, const float nSigmaTPC, const float nSigmaTOF, const float dEdxExp, const o2::track::PID::ID id, int runnumber, double dwnSmplFactor, float hadronicRate) { @@ -111,7 +116,13 @@ struct TreeWriterTpcV0 { const double pseudoRndm = track.pt() * 1000. - static_cast(track.pt() * 1000); if (pseudoRndm < dwnSmplFactor) { - rowTPCTree(track.tpcSignal(), + float usedDedx; + if constexpr (doUseCorreceddEdx) { + usedDedx = track.tpcSignalCorrected(); + } else { + usedDedx = track.tpcSignal(); + } + rowTPCTree(usedDedx, 1. / dEdxExp, track.tpcInnerParam(), track.tgl(), @@ -140,7 +151,7 @@ struct TreeWriterTpcV0 { } }; - template + template void fillSkimmedV0TableWithdEdxTrQA(V0 const& v0, T const& track, TQA const& trackQA, bool existTrkQA, C const& collision, const float nSigmaTPC, const float nSigmaTOF, const float dEdxExp, const o2::track::PID::ID id, int runnumber, double dwnSmplFactor, float hadronicRate) { @@ -162,7 +173,13 @@ struct TreeWriterTpcV0 { const double pseudoRndm = track.pt() * 1000. - static_cast(track.pt() * 1000); if (pseudoRndm < dwnSmplFactor) { - rowTPCTreeWithdEdxTrkQA(track.tpcSignal(), + float usedDedx; + if constexpr (doUseCorreceddEdx) { + usedDedx = track.tpcSignalCorrected(); + } else { + usedDedx = track.tpcSignal(); + } + rowTPCTreeWithdEdxTrkQA(usedDedx, 1. / dEdxExp, track.tpcInnerParam(), track.tgl(), @@ -193,7 +210,7 @@ struct TreeWriterTpcV0 { }; /// Function to fill skimmed tables - template + template void fillSkimmedV0TableWithTrQA(V0 const& v0, T const& track, TQA const& trackQA, bool existTrkQA, C const& collision, const float nSigmaTPC, const float nSigmaTOF, const float dEdxExp, const o2::track::PID::ID id, int runnumber, double dwnSmplFactor, float hadronicRate, int bcGlobalIndex, int bcTimeFrameId, int bcBcInTimeFrame) { @@ -215,7 +232,13 @@ struct TreeWriterTpcV0 { const double pseudoRndm = track.pt() * 1000. - static_cast(track.pt() * 1000); if (pseudoRndm < dwnSmplFactor) { - rowTPCTreeWithTrkQA(track.tpcSignal(), + float usedDedx; + if constexpr (doUseCorreceddEdx) { + usedDedx = track.tpcSignalCorrected(); + } else { + usedDedx = track.tpcSignal(); + } + rowTPCTreeWithTrkQA(usedDedx, 1. / dEdxExp, track.tpcInnerParam(), track.tgl(), @@ -376,6 +399,69 @@ struct TreeWriterTpcV0 { } /// process Standard PROCESS_SWITCH(TreeWriterTpcV0, processStandard, "Standard V0 Samples for PID", true); + void processStandardWithCorrecteddEdx(Colls::iterator const& collision, soa::Filtered const& tracks, V0sWithID const& v0s, aod::BCsWithTimestamps const&) + { + /// Check event slection + if (!isEventSelected(collision, tracks)) { + return; + } + auto bc = collision.bc_as(); + const int runnumber = bc.runNumber(); + float hadronicRate = mRateFetcher.fetch(ccdb.service, bc.timestamp(), runnumber, irSource) * 1.e-3; + + rowTPCTree.reserve(tracks.size()); + + /// Loop over v0 candidates + for (const auto& v0 : v0s) { + auto posTrack = v0.posTrack_as>(); + auto negTrack = v0.negTrack_as>(); + if (v0.v0addid() == -1) { + continue; + } + // gamma + if (static_cast(posTrack.pidbit() & (1 << 0)) && static_cast(negTrack.pidbit() & (1 << 0))) { + if (downsampleTsalisCharged(posTrack.pt(), downsamplingTsalisElectrons, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Electron], maxPt4dwnsmplTsalisElectrons)) { + fillSkimmedV0Table(v0, posTrack, collision, posTrack.tpcNSigmaEl(), posTrack.tofNSigmaEl(), posTrack.tpcExpSignalEl(posTrack.tpcSignalCorrected()), o2::track::PID::Electron, runnumber, dwnSmplFactor_El, hadronicRate); + } + if (downsampleTsalisCharged(negTrack.pt(), downsamplingTsalisElectrons, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Electron], maxPt4dwnsmplTsalisElectrons)) { + fillSkimmedV0Table(v0, negTrack, collision, negTrack.tpcNSigmaEl(), negTrack.tofNSigmaEl(), negTrack.tpcExpSignalEl(negTrack.tpcSignalCorrected()), o2::track::PID::Electron, runnumber, dwnSmplFactor_El, hadronicRate); + } + } + // Ks0 + if (static_cast(posTrack.pidbit() & (1 << 1)) && static_cast(negTrack.pidbit() & (1 << 1))) { + if (downsampleTsalisCharged(posTrack.pt(), downsamplingTsalisPions, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Pion], maxPt4dwnsmplTsalisPions)) { + fillSkimmedV0Table(v0, posTrack, collision, posTrack.tpcNSigmaPi(), posTrack.tofNSigmaPi(), posTrack.tpcExpSignalPi(posTrack.tpcSignalCorrected()), o2::track::PID::Pion, runnumber, dwnSmplFactor_Pi, hadronicRate); + } + if (downsampleTsalisCharged(negTrack.pt(), downsamplingTsalisPions, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Pion], maxPt4dwnsmplTsalisPions)) { + fillSkimmedV0Table(v0, negTrack, collision, negTrack.tpcNSigmaPi(), negTrack.tofNSigmaPi(), negTrack.tpcExpSignalPi(negTrack.tpcSignalCorrected()), o2::track::PID::Pion, runnumber, dwnSmplFactor_Pi, hadronicRate); + } + } + // Lambda + if (static_cast(posTrack.pidbit() & (1 << 2)) && static_cast(negTrack.pidbit() & (1 << 2))) { + if (downsampleTsalisCharged(posTrack.pt(), downsamplingTsalisProtons, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Proton], maxPt4dwnsmplTsalisProtons)) { + if (std::abs(posTrack.tofNSigmaPr()) <= nSigmaTOFdautrack) { + fillSkimmedV0Table(v0, posTrack, collision, posTrack.tpcNSigmaPr(), posTrack.tofNSigmaPr(), posTrack.tpcExpSignalPr(posTrack.tpcSignalCorrected()), o2::track::PID::Proton, runnumber, dwnSmplFactor_Pr, hadronicRate); + } + } + if (downsampleTsalisCharged(negTrack.pt(), downsamplingTsalisPions, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Pion], maxPt4dwnsmplTsalisPions)) { + fillSkimmedV0Table(v0, negTrack, collision, negTrack.tpcNSigmaPi(), negTrack.tofNSigmaPi(), negTrack.tpcExpSignalPi(negTrack.tpcSignalCorrected()), o2::track::PID::Pion, runnumber, dwnSmplFactor_Pi, hadronicRate); + } + } + // Antilambda + if (static_cast(posTrack.pidbit() & (1 << 3)) && static_cast(negTrack.pidbit() & (1 << 3))) { + if (downsampleTsalisCharged(posTrack.pt(), downsamplingTsalisPions, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Pion], maxPt4dwnsmplTsalisPions)) { + fillSkimmedV0Table(v0, posTrack, collision, posTrack.tpcNSigmaPi(), posTrack.tofNSigmaPi(), posTrack.tpcExpSignalPi(posTrack.tpcSignalCorrected()), o2::track::PID::Pion, runnumber, dwnSmplFactor_Pi, hadronicRate); + } + if (downsampleTsalisCharged(negTrack.pt(), downsamplingTsalisProtons, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Proton], maxPt4dwnsmplTsalisProtons)) { + if (std::abs(negTrack.tofNSigmaPr()) <= nSigmaTOFdautrack) { + fillSkimmedV0Table(v0, negTrack, collision, negTrack.tpcNSigmaPr(), negTrack.tofNSigmaPr(), negTrack.tpcExpSignalPr(negTrack.tpcSignalCorrected()), o2::track::PID::Proton, runnumber, dwnSmplFactor_Pr, hadronicRate); + } + } + } + } + } /// process Standard + PROCESS_SWITCH(TreeWriterTpcV0, processStandardWithCorrecteddEdx, "Standard V0 Samples for PID with corrected dEdx", false); + Preslice perCollisionTracks = aod::track::collisionId; Preslice perCollisionV0s = aod::v0data::collisionId; void processWithdEdxTrQA(Colls const& collisions, Trks const& myTracks, V0sWithID const& myV0s, aod::BCsWithTimestamps const&, aod::TracksQAVersion const& tracksQA) @@ -470,6 +556,99 @@ struct TreeWriterTpcV0 { } /// process with dEdx from TrackQA PROCESS_SWITCH(TreeWriterTpcV0, processWithdEdxTrQA, "Standard V0 Samples with dEdx from Track QA for PID", false); + Preslice perCollisionTracksWithNewDEdx = aod::track::collisionId; + void processWithdEdxTrQAWithCorrecteddEdx(Colls const& collisions, TrksWithDEdxCorrection const& myTracks, V0sWithID const& myV0s, aod::BCsWithTimestamps const&, aod::TracksQAVersion const& tracksQA) + { + std::vector labelTrack2TrackQA; + labelTrack2TrackQA.clear(); + labelTrack2TrackQA.resize(myTracks.size(), -1); + for (const auto& trackQA : tracksQA) { + int64_t trackId = trackQA.trackId(); + int64_t trackQAIndex = trackQA.globalIndex(); + labelTrack2TrackQA[trackId] = trackQAIndex; + } + for (const auto& collision : collisions) { + auto tracks = myTracks.sliceBy(perCollisionTracksWithNewDEdx, collision.globalIndex()); + auto v0s = myV0s.sliceBy(perCollisionV0s, collision.globalIndex()); + /// Check event slection + if (!isEventSelected(collision, tracks)) { + continue; + } + auto bc = collision.bc_as(); + const int runnumber = bc.runNumber(); + float hadronicRate = mRateFetcher.fetch(ccdb.service, bc.timestamp(), runnumber, irSource) * 1.e-3; + rowTPCTreeWithTrkQA.reserve(tracks.size()); + /// Loop over v0 candidates + for (const auto& v0 : v0s) { + auto posTrack = v0.posTrack_as(); + auto negTrack = v0.negTrack_as(); + if (v0.v0addid() == -1) { + continue; + } + aod::TracksQA posTrackQA; + aod::TracksQA negTrackQA; + bool existPosTrkQA; + bool existNegTrkQA; + if (labelTrack2TrackQA[posTrack.globalIndex()] != -1) { + posTrackQA = tracksQA.iteratorAt(labelTrack2TrackQA[posTrack.globalIndex()]); + existPosTrkQA = true; + } else { + posTrackQA = tracksQA.iteratorAt(0); + existPosTrkQA = false; + } + if (labelTrack2TrackQA[negTrack.globalIndex()] != -1) { + negTrackQA = tracksQA.iteratorAt(labelTrack2TrackQA[negTrack.globalIndex()]); + existNegTrkQA = true; + } else { + negTrackQA = tracksQA.iteratorAt(0); + existNegTrkQA = false; + } + + // gamma + if (static_cast(posTrack.pidbit() & (1 << 0)) && static_cast(negTrack.pidbit() & (1 << 0))) { + if (downsampleTsalisCharged(posTrack.pt(), downsamplingTsalisElectrons, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Electron], maxPt4dwnsmplTsalisElectrons)) { + fillSkimmedV0TableWithdEdxTrQA(v0, posTrack, posTrackQA, existPosTrkQA, collision, posTrack.tpcNSigmaEl(), posTrack.tofNSigmaEl(), posTrack.tpcExpSignalEl(posTrack.tpcSignalCorrected()), o2::track::PID::Electron, runnumber, dwnSmplFactor_El, hadronicRate); + } + if (downsampleTsalisCharged(negTrack.pt(), downsamplingTsalisElectrons, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Electron], maxPt4dwnsmplTsalisElectrons)) { + fillSkimmedV0TableWithdEdxTrQA(v0, negTrack, negTrackQA, existNegTrkQA, collision, negTrack.tpcNSigmaEl(), negTrack.tofNSigmaEl(), negTrack.tpcExpSignalEl(negTrack.tpcSignalCorrected()), o2::track::PID::Electron, runnumber, dwnSmplFactor_El, hadronicRate); + } + } + // Ks0 + if (static_cast(posTrack.pidbit() & (1 << 1)) && static_cast(negTrack.pidbit() & (1 << 1))) { + if (downsampleTsalisCharged(posTrack.pt(), downsamplingTsalisPions, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Pion], maxPt4dwnsmplTsalisPions)) { + fillSkimmedV0TableWithdEdxTrQA(v0, posTrack, posTrackQA, existPosTrkQA, collision, posTrack.tpcNSigmaPi(), posTrack.tofNSigmaPi(), posTrack.tpcExpSignalPi(posTrack.tpcSignalCorrected()), o2::track::PID::Pion, runnumber, dwnSmplFactor_Pi, hadronicRate); + } + if (downsampleTsalisCharged(negTrack.pt(), downsamplingTsalisPions, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Pion], maxPt4dwnsmplTsalisPions)) { + fillSkimmedV0TableWithdEdxTrQA(v0, negTrack, negTrackQA, existNegTrkQA, collision, negTrack.tpcNSigmaPi(), negTrack.tofNSigmaPi(), negTrack.tpcExpSignalPi(negTrack.tpcSignalCorrected()), o2::track::PID::Pion, runnumber, dwnSmplFactor_Pi, hadronicRate); + } + } + // Lambda + if (static_cast(posTrack.pidbit() & (1 << 2)) && static_cast(negTrack.pidbit() & (1 << 2))) { + if (downsampleTsalisCharged(posTrack.pt(), downsamplingTsalisProtons, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Proton], maxPt4dwnsmplTsalisProtons)) { + if (std::abs(posTrack.tofNSigmaPr()) <= nSigmaTOFdautrack) { + fillSkimmedV0TableWithdEdxTrQA(v0, posTrack, posTrackQA, existPosTrkQA, collision, posTrack.tpcNSigmaPr(), posTrack.tofNSigmaPr(), posTrack.tpcExpSignalPr(posTrack.tpcSignal()), o2::track::PID::Proton, runnumber, dwnSmplFactor_Pr, hadronicRate); + } + } + if (downsampleTsalisCharged(negTrack.pt(), downsamplingTsalisPions, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Pion], maxPt4dwnsmplTsalisPions)) { + fillSkimmedV0TableWithdEdxTrQA(v0, negTrack, negTrackQA, existNegTrkQA, collision, negTrack.tpcNSigmaPi(), negTrack.tofNSigmaPi(), negTrack.tpcExpSignalPi(negTrack.tpcSignalCorrected()), o2::track::PID::Pion, runnumber, dwnSmplFactor_Pi, hadronicRate); + } + } + // Antilambda + if (static_cast(posTrack.pidbit() & (1 << 3)) && static_cast(negTrack.pidbit() & (1 << 3))) { + if (downsampleTsalisCharged(posTrack.pt(), downsamplingTsalisPions, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Pion], maxPt4dwnsmplTsalisPions)) { + fillSkimmedV0TableWithdEdxTrQA(v0, posTrack, posTrackQA, existPosTrkQA, collision, posTrack.tpcNSigmaPi(), posTrack.tofNSigmaPi(), posTrack.tpcExpSignalPi(posTrack.tpcSignalCorrected()), o2::track::PID::Pion, runnumber, dwnSmplFactor_Pi, hadronicRate); + } + if (downsampleTsalisCharged(negTrack.pt(), downsamplingTsalisProtons, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Proton], maxPt4dwnsmplTsalisProtons)) { + if (std::abs(negTrack.tofNSigmaPr()) <= nSigmaTOFdautrack) { + fillSkimmedV0TableWithdEdxTrQA(v0, negTrack, negTrackQA, existNegTrkQA, collision, negTrack.tpcNSigmaPr(), negTrack.tofNSigmaPr(), negTrack.tpcExpSignalPr(negTrack.tpcSignalCorrected()), o2::track::PID::Proton, runnumber, dwnSmplFactor_Pr, hadronicRate); + } + } + } + } + } + } /// process with dEdx from TrackQA + PROCESS_SWITCH(TreeWriterTpcV0, processWithdEdxTrQAWithCorrecteddEdx, "Standard V0 Samples with dEdx from Track QA for PID with corrected dEdx", false); + void processWithTrQA(Colls const& collisions, Trks const& myTracks, V0sWithID const& myV0s, MyBCTable const&, aod::TracksQAVersion const& tracksQA) { std::vector labelTrack2TrackQA; @@ -565,10 +744,105 @@ struct TreeWriterTpcV0 { } /// process with TrackQA PROCESS_SWITCH(TreeWriterTpcV0, processWithTrQA, "Standard V0 Samples with Track QA for PID", false); + void processWithTrQAWithCorrecteddEdx(Colls const& collisions, TrksWithDEdxCorrection const& myTracks, V0sWithID const& myV0s, MyBCTable const&, aod::TracksQAVersion const& tracksQA) + { + std::vector labelTrack2TrackQA; + labelTrack2TrackQA.clear(); + labelTrack2TrackQA.resize(myTracks.size(), -1); + for (const auto& trackQA : tracksQA) { + int64_t trackId = trackQA.trackId(); + int64_t trackQAIndex = trackQA.globalIndex(); + labelTrack2TrackQA[trackId] = trackQAIndex; + } + for (const auto& collision : collisions) { + auto tracks = myTracks.sliceBy(perCollisionTracksWithNewDEdx, collision.globalIndex()); + auto v0s = myV0s.sliceBy(perCollisionV0s, collision.globalIndex()); + /// Check event slection + if (!isEventSelected(collision, tracks)) { + continue; + } + auto bc = collision.bc_as(); + const int runnumber = bc.runNumber(); + float hadronicRate = mRateFetcher.fetch(ccdb.service, bc.timestamp(), runnumber, irSource) * 1.e-3; + const int bcGlobalIndex = bc.globalIndex(); + const int bcTimeFrameId = bc.tfId(); + const int bcBcInTimeFrame = bc.bcInTF(); + rowTPCTreeWithTrkQA.reserve(tracks.size()); + /// Loop over v0 candidates + for (const auto& v0 : v0s) { + auto posTrack = v0.posTrack_as(); + auto negTrack = v0.negTrack_as(); + if (v0.v0addid() == -1) { + continue; + } + aod::TracksQA posTrackQA; + aod::TracksQA negTrackQA; + bool existPosTrkQA; + bool existNegTrkQA; + if (labelTrack2TrackQA[posTrack.globalIndex()] != -1) { + posTrackQA = tracksQA.iteratorAt(labelTrack2TrackQA[posTrack.globalIndex()]); + existPosTrkQA = true; + } else { + posTrackQA = tracksQA.iteratorAt(0); + existPosTrkQA = false; + } + if (labelTrack2TrackQA[negTrack.globalIndex()] != -1) { + negTrackQA = tracksQA.iteratorAt(labelTrack2TrackQA[negTrack.globalIndex()]); + existNegTrkQA = true; + } else { + negTrackQA = tracksQA.iteratorAt(0); + existNegTrkQA = false; + } + + // gamma + if (static_cast(posTrack.pidbit() & (1 << 0)) && static_cast(negTrack.pidbit() & (1 << 0))) { + if (downsampleTsalisCharged(posTrack.pt(), downsamplingTsalisElectrons, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Electron], maxPt4dwnsmplTsalisElectrons)) { + fillSkimmedV0TableWithTrQA(v0, posTrack, posTrackQA, existPosTrkQA, collision, posTrack.tpcNSigmaEl(), posTrack.tofNSigmaEl(), posTrack.tpcExpSignalEl(posTrack.tpcSignalCorrected()), o2::track::PID::Electron, runnumber, dwnSmplFactor_El, hadronicRate, bcGlobalIndex, bcTimeFrameId, bcBcInTimeFrame); + } + if (downsampleTsalisCharged(negTrack.pt(), downsamplingTsalisElectrons, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Electron], maxPt4dwnsmplTsalisElectrons)) { + fillSkimmedV0TableWithTrQA(v0, negTrack, negTrackQA, existNegTrkQA, collision, negTrack.tpcNSigmaEl(), negTrack.tofNSigmaEl(), negTrack.tpcExpSignalEl(negTrack.tpcSignalCorrected()), o2::track::PID::Electron, runnumber, dwnSmplFactor_El, hadronicRate, bcGlobalIndex, bcTimeFrameId, bcBcInTimeFrame); + } + } + // Ks0 + if (static_cast(posTrack.pidbit() & (1 << 1)) && static_cast(negTrack.pidbit() & (1 << 1))) { + if (downsampleTsalisCharged(posTrack.pt(), downsamplingTsalisPions, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Pion], maxPt4dwnsmplTsalisPions)) { + fillSkimmedV0TableWithTrQA(v0, posTrack, posTrackQA, existPosTrkQA, collision, posTrack.tpcNSigmaPi(), posTrack.tofNSigmaPi(), posTrack.tpcExpSignalPi(posTrack.tpcSignalCorrected()), o2::track::PID::Pion, runnumber, dwnSmplFactor_Pi, hadronicRate, bcGlobalIndex, bcTimeFrameId, bcBcInTimeFrame); + } + if (downsampleTsalisCharged(negTrack.pt(), downsamplingTsalisPions, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Pion], maxPt4dwnsmplTsalisPions)) { + fillSkimmedV0TableWithTrQA(v0, negTrack, negTrackQA, existNegTrkQA, collision, negTrack.tpcNSigmaPi(), negTrack.tofNSigmaPi(), negTrack.tpcExpSignalPi(negTrack.tpcSignalCorrected()), o2::track::PID::Pion, runnumber, dwnSmplFactor_Pi, hadronicRate, bcGlobalIndex, bcTimeFrameId, bcBcInTimeFrame); + } + } + // Lambda + if (static_cast(posTrack.pidbit() & (1 << 2)) && static_cast(negTrack.pidbit() & (1 << 2))) { + if (downsampleTsalisCharged(posTrack.pt(), downsamplingTsalisProtons, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Proton], maxPt4dwnsmplTsalisProtons)) { + if (std::abs(posTrack.tofNSigmaPr()) <= nSigmaTOFdautrack) { + fillSkimmedV0TableWithTrQA(v0, posTrack, posTrackQA, existPosTrkQA, collision, posTrack.tpcNSigmaPr(), posTrack.tofNSigmaPr(), posTrack.tpcExpSignalPr(posTrack.tpcSignalCorrected()), o2::track::PID::Proton, runnumber, dwnSmplFactor_Pr, hadronicRate, bcGlobalIndex, bcTimeFrameId, bcBcInTimeFrame); + } + } + if (downsampleTsalisCharged(negTrack.pt(), downsamplingTsalisPions, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Pion], maxPt4dwnsmplTsalisPions)) { + fillSkimmedV0TableWithTrQA(v0, negTrack, negTrackQA, existNegTrkQA, collision, negTrack.tpcNSigmaPi(), negTrack.tofNSigmaPi(), negTrack.tpcExpSignalPi(negTrack.tpcSignalCorrected()), o2::track::PID::Pion, runnumber, dwnSmplFactor_Pi, hadronicRate, bcGlobalIndex, bcTimeFrameId, bcBcInTimeFrame); + } + } + // Antilambda + if (static_cast(posTrack.pidbit() & (1 << 3)) && static_cast(negTrack.pidbit() & (1 << 3))) { + if (downsampleTsalisCharged(posTrack.pt(), downsamplingTsalisPions, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Pion], maxPt4dwnsmplTsalisPions)) { + fillSkimmedV0TableWithTrQA(v0, posTrack, posTrackQA, existPosTrkQA, collision, posTrack.tpcNSigmaPi(), posTrack.tofNSigmaPi(), posTrack.tpcExpSignalPi(posTrack.tpcSignalCorrected()), o2::track::PID::Pion, runnumber, dwnSmplFactor_Pi, hadronicRate, bcGlobalIndex, bcTimeFrameId, bcBcInTimeFrame); + } + if (downsampleTsalisCharged(negTrack.pt(), downsamplingTsalisProtons, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Proton], maxPt4dwnsmplTsalisProtons)) { + if (std::abs(negTrack.tofNSigmaPr()) <= nSigmaTOFdautrack) { + fillSkimmedV0TableWithTrQA(v0, negTrack, negTrackQA, existNegTrkQA, collision, negTrack.tpcNSigmaPr(), negTrack.tofNSigmaPr(), negTrack.tpcExpSignalPr(negTrack.tpcSignalCorrected()), o2::track::PID::Proton, runnumber, dwnSmplFactor_Pr, hadronicRate, bcGlobalIndex, bcTimeFrameId, bcBcInTimeFrame); + } + } + } + } + } + } /// process with TrackQA + PROCESS_SWITCH(TreeWriterTpcV0, processWithTrQAWithCorrecteddEdx, "Standard V0 Samples with Track QA for PID with corrected dEdx", false); + void processDummy(Colls const&) {} PROCESS_SWITCH(TreeWriterTpcV0, processDummy, "Dummy function", false); -}; /// struct TreeWriterTpcV0 +}; /// struct TreeWriterTpcV0 struct TreeWriterTPCTOF { @@ -580,6 +854,12 @@ struct TreeWriterTPCTOF { aod::pidTOFFullEl, aod::pidTOFFullPi, aod::pidTOFFullKa, aod::pidTOFFullPr, aod::pidTOFFullDe, aod::pidTOFFullTr, aod::TrackSelection>; + using TrksWithDEdxCorrection = soa::Join; using Colls = soa::Join; using MyBCTable = soa::Join; @@ -674,7 +954,7 @@ struct TreeWriterTPCTOF { }; /// Function to fill trees - template + template void fillSkimmedTPCTOFTable(T const& track, C const& collision, const float nSigmaTPC, const float nSigmaTOF, const float dEdxExp, const o2::track::PID::ID id, int runnumber, double dwnSmplFactor, double hadronicRate) { @@ -689,7 +969,13 @@ struct TreeWriterTPCTOF { const double pseudoRndm = track.pt() * 1000. - static_cast(track.pt() * 1000); if (pseudoRndm < dwnSmplFactor) { - rowTPCTOFTree(track.tpcSignal(), + float usedEdx; + if constexpr (doCorrectdEdx) { + usedEdx = track.tpcSignalCorrected(); + } else { + usedEdx = track.tpcSignal(); + } + rowTPCTOFTree(usedEdx, 1. / dEdxExp, track.tpcInnerParam(), track.tgl(), @@ -711,7 +997,7 @@ struct TreeWriterTPCTOF { hadronicRate); } }; - template + template void fillSkimmedTPCTOFTableWithdEdxTrkQA(T const& track, TQA const& trackQA, bool existTrkQA, C const& collision, const float nSigmaTPC, const float nSigmaTOF, const float nSigmaITS, const float dEdxExp, const o2::track::PID::ID id, int runnumber, double dwnSmplFactor, double hadronicRate) { @@ -726,7 +1012,13 @@ struct TreeWriterTPCTOF { const double pseudoRndm = track.pt() * 1000. - static_cast(track.pt() * 1000); if (pseudoRndm < dwnSmplFactor) { - rowTPCTOFTreeWithdEdxTrkQA(track.tpcSignal(), + float usedEdx; + if constexpr (doCorrectdEdx) { + usedEdx = track.tpcSignalCorrected(); + } else { + usedEdx = track.tpcSignal(); + } + rowTPCTOFTreeWithdEdxTrkQA(usedEdx, 1. / dEdxExp, track.tpcInnerParam(), track.tgl(), @@ -751,7 +1043,7 @@ struct TreeWriterTPCTOF { } }; /// Function to fill trees - template + template void fillSkimmedTPCTOFTableWithTrkQA(T const& track, TQA const& trackQA, bool existTrkQA, C const& collision, const float nSigmaTPC, const float nSigmaTOF, const float nSigmaITS, const float dEdxExp, const o2::track::PID::ID id, int runnumber, double dwnSmplFactor, double hadronicRate, int bcGlobalIndex, int bcTimeFrameId, int bcBcInTimeFrame) { @@ -766,7 +1058,13 @@ struct TreeWriterTPCTOF { const double pseudoRndm = track.pt() * 1000. - static_cast(track.pt() * 1000); if (pseudoRndm < dwnSmplFactor) { - rowTPCTOFTreeWithTrkQA(track.tpcSignal(), + float usedEdx; + if constexpr (doCorrectdEdx) { + usedEdx = track.tpcSignalCorrected(); + } else { + usedEdx = track.tpcSignal(); + } + rowTPCTOFTreeWithTrkQA(usedEdx, 1. / dEdxExp, track.tpcInnerParam(), track.tgl(), @@ -869,8 +1167,55 @@ struct TreeWriterTPCTOF { fillSkimmedTPCTOFTable(trk, collision, trk.tpcNSigmaPi(), trk.tofNSigmaPi(), trk.tpcExpSignalPi(trk.tpcSignal()), o2::track::PID::Pion, runnumber, dwnSmplFactor_Pi, hadronicRate); } } /// Loop tracks - } /// process + } /// process PROCESS_SWITCH(TreeWriterTPCTOF, processStandard, "Standard Samples for PID", true); + + void processStandard2(Colls::iterator const& collision, soa::Filtered const& tracks, aod::BCsWithTimestamps const&) + { + /// Check event selection + if (!isEventSelected(collision, tracks)) { + return; + } + auto bc = collision.bc_as(); + const int runnumber = bc.runNumber(); + float hadronicRate = mRateFetcher.fetch(ccdb.service, bc.timestamp(), runnumber, irSource) * 1.e-3; + + rowTPCTOFTree.reserve(tracks.size()); + for (auto const& trk : tracks) { + /// Fill tree for tritons/* */ + if (trk.tpcInnerParam() < maxMomHardCutOnlyTr && trk.tpcInnerParam() <= maxMomTPCOnlyTr && std::abs(trk.tpcNSigmaTr()) < nSigmaTPCOnlyTr && downsampleTsalisCharged(trk.pt(), downsamplingTsalisProtons, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Triton])) { + fillSkimmedTPCTOFTable(trk, collision, trk.tpcNSigmaTr(), trk.tofNSigmaTr(), trk.tpcExpSignalTr(trk.tpcSignalCorrected()), o2::track::PID::Triton, runnumber, dwnSmplFactor_Tr, hadronicRate); + } else if (trk.tpcInnerParam() < maxMomHardCutOnlyTr && trk.tpcInnerParam() > maxMomTPCOnlyTr && std::abs(trk.tofNSigmaTr()) < nSigmaTOF_TPCTOF_Tr && std::abs(trk.tpcNSigmaTr()) < nSigmaTPC_TPCTOF_Tr && downsampleTsalisCharged(trk.pt(), downsamplingTsalisProtons, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Triton])) { + fillSkimmedTPCTOFTable(trk, collision, trk.tpcNSigmaTr(), trk.tofNSigmaTr(), trk.tpcExpSignalTr(trk.tpcSignalCorrected()), o2::track::PID::Triton, runnumber, dwnSmplFactor_Tr, hadronicRate); + } + /// Fill tree for deuterons + if (trk.tpcInnerParam() < maxMomHardCutOnlyDe && trk.tpcInnerParam() <= maxMomTPCOnlyDe && std::abs(trk.tpcNSigmaDe()) < nSigmaTPCOnlyDe && downsampleTsalisCharged(trk.pt(), downsamplingTsalisProtons, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Deuteron])) { + fillSkimmedTPCTOFTable(trk, collision, trk.tpcNSigmaDe(), trk.tofNSigmaDe(), trk.tpcExpSignalDe(trk.tpcSignalCorrected()), o2::track::PID::Deuteron, runnumber, dwnSmplFactor_De, hadronicRate); + } else if (trk.tpcInnerParam() < maxMomHardCutOnlyDe && trk.tpcInnerParam() > maxMomTPCOnlyDe && std::abs(trk.tofNSigmaDe()) < nSigmaTOF_TPCTOF_De && std::abs(trk.tpcNSigmaDe()) < nSigmaTPC_TPCTOF_De && downsampleTsalisCharged(trk.pt(), downsamplingTsalisProtons, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Deuteron])) { + fillSkimmedTPCTOFTable(trk, collision, trk.tpcNSigmaDe(), trk.tofNSigmaDe(), trk.tpcExpSignalDe(trk.tpcSignalCorrected()), o2::track::PID::Deuteron, runnumber, dwnSmplFactor_De, hadronicRate); + } + /// Fill tree for protons + if (trk.tpcInnerParam() <= maxMomTPCOnlyPr && std::abs(trk.tpcNSigmaPr()) < nSigmaTPCOnlyPr && downsampleTsalisCharged(trk.pt(), downsamplingTsalisProtons, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Proton])) { + fillSkimmedTPCTOFTable(trk, collision, trk.tpcNSigmaPr(), trk.tofNSigmaPr(), trk.tpcExpSignalPr(trk.tpcSignalCorrected()), o2::track::PID::Proton, runnumber, dwnSmplFactor_Pr, hadronicRate); + } else if (trk.tpcInnerParam() > maxMomTPCOnlyPr && std::abs(trk.tofNSigmaPr()) < nSigmaTOF_TPCTOF_Pr && std::abs(trk.tpcNSigmaPr()) < nSigmaTPC_TPCTOF_Pr && downsampleTsalisCharged(trk.pt(), downsamplingTsalisProtons, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Proton])) { + fillSkimmedTPCTOFTable(trk, collision, trk.tpcNSigmaPr(), trk.tofNSigmaPr(), trk.tpcExpSignalPr(trk.tpcSignalCorrected()), o2::track::PID::Proton, runnumber, dwnSmplFactor_Pr, hadronicRate); + } + /// Fill tree for kaons + if (trk.tpcInnerParam() < maxMomHardCutOnlyKa && trk.tpcInnerParam() <= maxMomTPCOnlyKa && std::abs(trk.tpcNSigmaKa()) < nSigmaTPCOnlyKa && downsampleTsalisCharged(trk.pt(), downsamplingTsalisKaons, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Kaon])) { + fillSkimmedTPCTOFTable(trk, collision, trk.tpcNSigmaKa(), trk.tofNSigmaKa(), trk.tpcExpSignalKa(trk.tpcSignalCorrected()), o2::track::PID::Kaon, runnumber, dwnSmplFactor_Ka, hadronicRate); + } else if (trk.tpcInnerParam() < maxMomHardCutOnlyKa && trk.tpcInnerParam() > maxMomTPCOnlyKa && std::abs(trk.tofNSigmaKa()) < nSigmaTOF_TPCTOF_Ka && std::abs(trk.tpcNSigmaKa()) < nSigmaTPC_TPCTOF_Ka && downsampleTsalisCharged(trk.pt(), downsamplingTsalisKaons, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Kaon])) { + fillSkimmedTPCTOFTable(trk, collision, trk.tpcNSigmaKa(), trk.tofNSigmaKa(), trk.tpcExpSignalKa(trk.tpcSignalCorrected()), o2::track::PID::Kaon, runnumber, dwnSmplFactor_Ka, hadronicRate); + } + /// Fill tree pions + if (trk.tpcInnerParam() <= maxMomTPCOnlyPi && std::abs(trk.tpcNSigmaPi()) < nSigmaTPCOnlyPi && downsampleTsalisCharged(trk.pt(), downsamplingTsalisPions, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Pion])) { + fillSkimmedTPCTOFTable(trk, collision, trk.tpcNSigmaPi(), trk.tofNSigmaPi(), trk.tpcExpSignalPi(trk.tpcSignalCorrected()), o2::track::PID::Pion, runnumber, dwnSmplFactor_Pi, hadronicRate); + } else if (trk.tpcInnerParam() > maxMomTPCOnlyPi && std::abs(trk.tofNSigmaPi()) < nSigmaTOF_TPCTOF_Pi && std::abs(trk.tpcNSigmaPi()) < nSigmaTPC_TPCTOF_Pi && downsampleTsalisCharged(trk.pt(), downsamplingTsalisPions, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Pion])) { + fillSkimmedTPCTOFTable(trk, collision, trk.tpcNSigmaPi(), trk.tofNSigmaPi(), trk.tpcExpSignalPi(trk.tpcSignalCorrected()), o2::track::PID::Pion, runnumber, dwnSmplFactor_Pi, hadronicRate); + } + } /// Loop tracks + } /// process + PROCESS_SWITCH(TreeWriterTPCTOF, processStandard2, "Standard Samples for PID with corrected dEdx", false); + Preslice perCollisionTracks = aod::track::collisionId; void processWithdEdxTrQA(Colls const& collisions, Trks const& myTracks, aod::BCsWithTimestamps const&, aod::TracksQAVersion const& tracksQA) { @@ -949,6 +1294,86 @@ struct TreeWriterTPCTOF { } } /// process PROCESS_SWITCH(TreeWriterTPCTOF, processWithdEdxTrQA, "Samples for PID with TrackQA info", false); + + Preslice perCollisionTracksWithCorrecteddEdx = aod::track::collisionId; + void processWithdEdxTrQAWithCorrecteddEdx(Colls const& collisions, TrksWithDEdxCorrection const& myTracks, aod::BCsWithTimestamps const&, aod::TracksQAVersion const& tracksQA) + { + std::vector labelTrack2TrackQA; + labelTrack2TrackQA.clear(); + labelTrack2TrackQA.resize(myTracks.size(), -1); + for (const auto& trackQA : tracksQA) { + int64_t trackId = trackQA.trackId(); + int64_t trackQAIndex = trackQA.globalIndex(); + labelTrack2TrackQA[trackId] = trackQAIndex; + } + for (const auto& collision : collisions) { + auto tracks = myTracks.sliceBy(perCollisionTracksWithCorrecteddEdx, collision.globalIndex()); + auto tracksWithITSPid = soa::Attach(tracks); + /// Check event selection + if (!isEventSelected(collision, tracks)) { + continue; + } + auto bc = collision.bc_as(); + const int runnumber = bc.runNumber(); + float hadronicRate = mRateFetcher.fetch(ccdb.service, bc.timestamp(), runnumber, irSource) * 1.e-3; + rowTPCTOFTreeWithTrkQA.reserve(tracks.size()); + for (auto const& trk : tracksWithITSPid) { + if (!((trackSelection == 0) || + ((trackSelection == 1) && trk.isGlobalTrack()) || + ((trackSelection == 2) && trk.isGlobalTrackWoPtEta()) || + ((trackSelection == 3) && trk.isGlobalTrackWoDCA()) || + ((trackSelection == 4) && trk.isQualityTrack()) || + ((trackSelection == 5) && trk.isInAcceptanceTrack()))) { + continue; + } + // get the corresponding trackQA using labelTracks2TracKQA and get variables of interest + aod::TracksQA trackQA; + bool existTrkQA; + if (labelTrack2TrackQA[trk.globalIndex()] != -1) { + trackQA = tracksQA.iteratorAt(labelTrack2TrackQA[trk.globalIndex()]); + existTrkQA = true; + } else { + trackQA = tracksQA.iteratorAt(0); + existTrkQA = false; + } + /// Fill tree for tritons + if (trk.tpcInnerParam() < maxMomHardCutOnlyTr && trk.tpcInnerParam() <= maxMomTPCOnlyTr && std::abs(trk.tpcNSigmaTr()) < nSigmaTPCOnlyTr && downsampleTsalisCharged(trk.pt(), downsamplingTsalisProtons, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Triton])) { + fillSkimmedTPCTOFTableWithdEdxTrkQA(trk, trackQA, existTrkQA, collision, trk.tpcNSigmaTr(), trk.tofNSigmaTr(), trk.itsNSigmaTr(), trk.tpcExpSignalTr(trk.tpcSignalCorrected()), o2::track::PID::Triton, runnumber, dwnSmplFactor_Tr, hadronicRate); + } else if (trk.tpcInnerParam() < maxMomHardCutOnlyTr && trk.tpcInnerParam() > maxMomTPCOnlyTr && std::abs(trk.tofNSigmaTr()) < nSigmaTOF_TPCTOF_Tr && std::abs(trk.tpcNSigmaTr()) < nSigmaTPC_TPCTOF_Tr && downsampleTsalisCharged(trk.pt(), downsamplingTsalisProtons, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Triton])) { + fillSkimmedTPCTOFTableWithdEdxTrkQA(trk, trackQA, existTrkQA, collision, trk.tpcNSigmaTr(), trk.tofNSigmaTr(), trk.itsNSigmaTr(), trk.tpcExpSignalTr(trk.tpcSignalCorrected()), o2::track::PID::Triton, runnumber, dwnSmplFactor_Tr, hadronicRate); + } + /// Fill tree for deuterons + if (trk.tpcInnerParam() < maxMomHardCutOnlyDe && trk.tpcInnerParam() <= maxMomTPCOnlyDe && std::abs(trk.tpcNSigmaDe()) < nSigmaTPCOnlyDe && downsampleTsalisCharged(trk.pt(), downsamplingTsalisProtons, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Deuteron])) { + fillSkimmedTPCTOFTableWithdEdxTrkQA(trk, trackQA, existTrkQA, collision, trk.tpcNSigmaDe(), trk.tofNSigmaDe(), trk.itsNSigmaDe(), trk.tpcExpSignalDe(trk.tpcSignalCorrected()), o2::track::PID::Deuteron, runnumber, dwnSmplFactor_De, hadronicRate); + } else if (trk.tpcInnerParam() < maxMomHardCutOnlyDe && trk.tpcInnerParam() > maxMomTPCOnlyDe && std::abs(trk.tofNSigmaDe()) < nSigmaTOF_TPCTOF_De && std::abs(trk.tpcNSigmaDe()) < nSigmaTPC_TPCTOF_De && downsampleTsalisCharged(trk.pt(), downsamplingTsalisProtons, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Deuteron])) { + fillSkimmedTPCTOFTableWithdEdxTrkQA(trk, trackQA, existTrkQA, collision, trk.tpcNSigmaDe(), trk.tofNSigmaDe(), trk.itsNSigmaDe(), trk.tpcExpSignalDe(trk.tpcSignalCorrected()), o2::track::PID::Deuteron, runnumber, dwnSmplFactor_De, hadronicRate); + } + /// Fill tree for protons + if (trk.tpcInnerParam() <= maxMomTPCOnlyPr && std::abs(trk.tpcNSigmaPr()) < nSigmaTPCOnlyPr && downsampleTsalisCharged(trk.pt(), downsamplingTsalisProtons, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Proton])) { + fillSkimmedTPCTOFTableWithdEdxTrkQA(trk, trackQA, existTrkQA, collision, trk.tpcNSigmaPr(), trk.tofNSigmaPr(), trk.itsNSigmaPr(), trk.tpcExpSignalPr(trk.tpcSignalCorrected()), o2::track::PID::Proton, runnumber, dwnSmplFactor_Pr, hadronicRate); + } else if (trk.tpcInnerParam() > maxMomTPCOnlyPr && std::abs(trk.tofNSigmaPr()) < nSigmaTOF_TPCTOF_Pr && std::abs(trk.tpcNSigmaPr()) < nSigmaTPC_TPCTOF_Pr && downsampleTsalisCharged(trk.pt(), downsamplingTsalisProtons, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Proton])) { + fillSkimmedTPCTOFTableWithdEdxTrkQA(trk, trackQA, existTrkQA, collision, trk.tpcNSigmaPr(), trk.tofNSigmaPr(), trk.itsNSigmaPr(), trk.tpcExpSignalPr(trk.tpcSignalCorrected()), o2::track::PID::Proton, runnumber, dwnSmplFactor_Pr, hadronicRate); + } + /// Fill tree for kaons + if (trk.tpcInnerParam() < maxMomHardCutOnlyKa && trk.tpcInnerParam() <= maxMomTPCOnlyKa && std::abs(trk.tpcNSigmaKa()) < nSigmaTPCOnlyKa && downsampleTsalisCharged(trk.pt(), downsamplingTsalisKaons, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Kaon])) { + fillSkimmedTPCTOFTableWithdEdxTrkQA(trk, trackQA, existTrkQA, collision, trk.tpcNSigmaKa(), trk.tofNSigmaKa(), trk.itsNSigmaKa(), trk.tpcExpSignalKa(trk.tpcSignalCorrected()), o2::track::PID::Kaon, runnumber, dwnSmplFactor_Ka, hadronicRate); + } else if (trk.tpcInnerParam() < maxMomHardCutOnlyKa && trk.tpcInnerParam() > maxMomTPCOnlyKa && std::abs(trk.tofNSigmaKa()) < nSigmaTOF_TPCTOF_Ka && std::abs(trk.tpcNSigmaKa()) < nSigmaTPC_TPCTOF_Ka && downsampleTsalisCharged(trk.pt(), downsamplingTsalisKaons, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Kaon])) { + fillSkimmedTPCTOFTableWithdEdxTrkQA(trk, trackQA, existTrkQA, collision, trk.tpcNSigmaKa(), trk.tofNSigmaKa(), trk.itsNSigmaKa(), trk.tpcExpSignalKa(trk.tpcSignalCorrected()), o2::track::PID::Kaon, runnumber, dwnSmplFactor_Ka, hadronicRate); + } + /// Fill tree pions + if (trk.tpcInnerParam() <= maxMomTPCOnlyPi && std::abs(trk.tpcNSigmaPi()) < nSigmaTPCOnlyPi && downsampleTsalisCharged(trk.pt(), downsamplingTsalisPions, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Pion])) { + fillSkimmedTPCTOFTableWithdEdxTrkQA(trk, trackQA, existTrkQA, collision, trk.tpcNSigmaPi(), trk.tofNSigmaPi(), trk.itsNSigmaPi(), trk.tpcExpSignalPi(trk.tpcSignalCorrected()), o2::track::PID::Pion, runnumber, dwnSmplFactor_Pi, hadronicRate); + } else if (trk.tpcInnerParam() > maxMomTPCOnlyPi && std::abs(trk.tofNSigmaPi()) < nSigmaTOF_TPCTOF_Pi && std::abs(trk.tpcNSigmaPi()) < nSigmaTPC_TPCTOF_Pi && downsampleTsalisCharged(trk.pt(), downsamplingTsalisPions, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Pion])) { + fillSkimmedTPCTOFTableWithdEdxTrkQA(trk, trackQA, existTrkQA, collision, trk.tpcNSigmaPi(), trk.tofNSigmaPi(), trk.itsNSigmaPi(), trk.tpcExpSignalPi(trk.tpcSignalCorrected()), o2::track::PID::Pion, runnumber, dwnSmplFactor_Pi, hadronicRate); + } + } /// Loop tracks + } + } /// process + PROCESS_SWITCH(TreeWriterTPCTOF, processWithdEdxTrQAWithCorrecteddEdx, "Samples for PID with TrackQA info with corrected dEdx", false); + void processWithTrQA(Colls const& collisions, Trks const& myTracks, MyBCTable const&, aod::TracksQAVersion const& tracksQA) { std::vector labelTrack2TrackQA; @@ -1029,6 +1454,88 @@ struct TreeWriterTPCTOF { } } /// process PROCESS_SWITCH(TreeWriterTPCTOF, processWithTrQA, "Samples for PID with TrackQA info", false); + + void processWithTrQAWithCorrecteddEdx(Colls const& collisions, TrksWithDEdxCorrection const& myTracks, MyBCTable const&, aod::TracksQAVersion const& tracksQA) + { + std::vector labelTrack2TrackQA; + labelTrack2TrackQA.clear(); + labelTrack2TrackQA.resize(myTracks.size(), -1); + for (const auto& trackQA : tracksQA) { + int64_t trackId = trackQA.trackId(); + int64_t trackQAIndex = trackQA.globalIndex(); + labelTrack2TrackQA[trackId] = trackQAIndex; + } + for (const auto& collision : collisions) { + auto tracks = myTracks.sliceBy(perCollisionTracks, collision.globalIndex()); + auto tracksWithITSPid = soa::Attach(tracks); + /// Check event selection + if (!isEventSelected(collision, tracks)) { + continue; + } + auto bc = collision.bc_as(); + const int runnumber = bc.runNumber(); + float hadronicRate = mRateFetcher.fetch(ccdb.service, bc.timestamp(), runnumber, irSource) * 1.e-3; + const int bcGlobalIndex = bc.globalIndex(); + const int bcTimeFrameId = bc.tfId(); + const int bcBcInTimeFrame = bc.bcInTF(); + rowTPCTOFTreeWithTrkQA.reserve(tracks.size()); + for (auto const& trk : tracksWithITSPid) { + if (!((trackSelection == 0) || + ((trackSelection == 1) && trk.isGlobalTrack()) || + ((trackSelection == 2) && trk.isGlobalTrackWoPtEta()) || + ((trackSelection == 3) && trk.isGlobalTrackWoDCA()) || + ((trackSelection == 4) && trk.isQualityTrack()) || + ((trackSelection == 5) && trk.isInAcceptanceTrack()))) { + continue; + } + // get the corresponding trackQA using labelTracks2TracKQA and get variables of interest + aod::TracksQA trackQA; + bool existTrkQA; + if (labelTrack2TrackQA[trk.globalIndex()] != -1) { + trackQA = tracksQA.iteratorAt(labelTrack2TrackQA[trk.globalIndex()]); + existTrkQA = true; + } else { + trackQA = tracksQA.iteratorAt(0); + existTrkQA = false; + } + /// Fill tree for tritons + if (trk.tpcInnerParam() < maxMomHardCutOnlyTr && trk.tpcInnerParam() <= maxMomTPCOnlyTr && std::abs(trk.tpcNSigmaTr()) < nSigmaTPCOnlyTr && downsampleTsalisCharged(trk.pt(), downsamplingTsalisProtons, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Triton])) { + fillSkimmedTPCTOFTableWithTrkQA(trk, trackQA, existTrkQA, collision, trk.tpcNSigmaTr(), trk.tofNSigmaTr(), trk.itsNSigmaTr(), trk.tpcExpSignalTr(trk.tpcSignalCorrected()), o2::track::PID::Triton, runnumber, dwnSmplFactor_Tr, hadronicRate, bcGlobalIndex, bcTimeFrameId, bcBcInTimeFrame); + } else if (trk.tpcInnerParam() < maxMomHardCutOnlyTr && trk.tpcInnerParam() > maxMomTPCOnlyTr && std::abs(trk.tofNSigmaTr()) < nSigmaTOF_TPCTOF_Tr && std::abs(trk.tpcNSigmaTr()) < nSigmaTPC_TPCTOF_Tr && downsampleTsalisCharged(trk.pt(), downsamplingTsalisProtons, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Triton])) { + fillSkimmedTPCTOFTableWithTrkQA(trk, trackQA, existTrkQA, collision, trk.tpcNSigmaTr(), trk.tofNSigmaTr(), trk.itsNSigmaTr(), trk.tpcExpSignalTr(trk.tpcSignalCorrected()), o2::track::PID::Triton, runnumber, dwnSmplFactor_Tr, hadronicRate, bcGlobalIndex, bcTimeFrameId, bcBcInTimeFrame); + } + /// Fill tree for deuterons + if (trk.tpcInnerParam() < maxMomHardCutOnlyDe && trk.tpcInnerParam() <= maxMomTPCOnlyDe && std::abs(trk.tpcNSigmaDe()) < nSigmaTPCOnlyDe && downsampleTsalisCharged(trk.pt(), downsamplingTsalisProtons, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Deuteron])) { + fillSkimmedTPCTOFTableWithTrkQA(trk, trackQA, existTrkQA, collision, trk.tpcNSigmaDe(), trk.tofNSigmaDe(), trk.itsNSigmaDe(), trk.tpcExpSignalDe(trk.tpcSignalCorrected()), o2::track::PID::Deuteron, runnumber, dwnSmplFactor_De, hadronicRate, bcGlobalIndex, bcTimeFrameId, bcBcInTimeFrame); + } else if (trk.tpcInnerParam() < maxMomHardCutOnlyDe && trk.tpcInnerParam() > maxMomTPCOnlyDe && std::abs(trk.tofNSigmaDe()) < nSigmaTOF_TPCTOF_De && std::abs(trk.tpcNSigmaDe()) < nSigmaTPC_TPCTOF_De && downsampleTsalisCharged(trk.pt(), downsamplingTsalisProtons, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Deuteron])) { + fillSkimmedTPCTOFTableWithTrkQA(trk, trackQA, existTrkQA, collision, trk.tpcNSigmaDe(), trk.tofNSigmaDe(), trk.itsNSigmaDe(), trk.tpcExpSignalDe(trk.tpcSignalCorrected()), o2::track::PID::Deuteron, runnumber, dwnSmplFactor_De, hadronicRate, bcGlobalIndex, bcTimeFrameId, bcBcInTimeFrame); + } + /// Fill tree for protons + if (trk.tpcInnerParam() <= maxMomTPCOnlyPr && std::abs(trk.tpcNSigmaPr()) < nSigmaTPCOnlyPr && downsampleTsalisCharged(trk.pt(), downsamplingTsalisProtons, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Proton])) { + fillSkimmedTPCTOFTableWithTrkQA(trk, trackQA, existTrkQA, collision, trk.tpcNSigmaPr(), trk.tofNSigmaPr(), trk.itsNSigmaPr(), trk.tpcExpSignalPr(trk.tpcSignalCorrected()), o2::track::PID::Proton, runnumber, dwnSmplFactor_Pr, hadronicRate, bcGlobalIndex, bcTimeFrameId, bcBcInTimeFrame); + } else if (trk.tpcInnerParam() > maxMomTPCOnlyPr && std::abs(trk.tofNSigmaPr()) < nSigmaTOF_TPCTOF_Pr && std::abs(trk.tpcNSigmaPr()) < nSigmaTPC_TPCTOF_Pr && downsampleTsalisCharged(trk.pt(), downsamplingTsalisProtons, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Proton])) { + fillSkimmedTPCTOFTableWithTrkQA(trk, trackQA, existTrkQA, collision, trk.tpcNSigmaPr(), trk.tofNSigmaPr(), trk.itsNSigmaPr(), trk.tpcExpSignalPr(trk.tpcSignalCorrected()), o2::track::PID::Proton, runnumber, dwnSmplFactor_Pr, hadronicRate, bcGlobalIndex, bcTimeFrameId, bcBcInTimeFrame); + } + /// Fill tree for kaons + if (trk.tpcInnerParam() < maxMomHardCutOnlyKa && trk.tpcInnerParam() <= maxMomTPCOnlyKa && std::abs(trk.tpcNSigmaKa()) < nSigmaTPCOnlyKa && downsampleTsalisCharged(trk.pt(), downsamplingTsalisKaons, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Kaon])) { + fillSkimmedTPCTOFTableWithTrkQA(trk, trackQA, existTrkQA, collision, trk.tpcNSigmaKa(), trk.tofNSigmaKa(), trk.itsNSigmaKa(), trk.tpcExpSignalKa(trk.tpcSignalCorrected()), o2::track::PID::Kaon, runnumber, dwnSmplFactor_Ka, hadronicRate, bcGlobalIndex, bcTimeFrameId, bcBcInTimeFrame); + } else if (trk.tpcInnerParam() < maxMomHardCutOnlyKa && trk.tpcInnerParam() > maxMomTPCOnlyKa && std::abs(trk.tofNSigmaKa()) < nSigmaTOF_TPCTOF_Ka && std::abs(trk.tpcNSigmaKa()) < nSigmaTPC_TPCTOF_Ka && downsampleTsalisCharged(trk.pt(), downsamplingTsalisKaons, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Kaon])) { + fillSkimmedTPCTOFTableWithTrkQA(trk, trackQA, existTrkQA, collision, trk.tpcNSigmaKa(), trk.tofNSigmaKa(), trk.itsNSigmaKa(), trk.tpcExpSignalKa(trk.tpcSignalCorrected()), o2::track::PID::Kaon, runnumber, dwnSmplFactor_Ka, hadronicRate, bcGlobalIndex, bcTimeFrameId, bcBcInTimeFrame); + } + /// Fill tree pions + if (trk.tpcInnerParam() <= maxMomTPCOnlyPi && std::abs(trk.tpcNSigmaPi()) < nSigmaTPCOnlyPi && downsampleTsalisCharged(trk.pt(), downsamplingTsalisPions, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Pion])) { + fillSkimmedTPCTOFTableWithTrkQA(trk, trackQA, existTrkQA, collision, trk.tpcNSigmaPi(), trk.tofNSigmaPi(), trk.itsNSigmaPi(), trk.tpcExpSignalPi(trk.tpcSignalCorrected()), o2::track::PID::Pion, runnumber, dwnSmplFactor_Pi, hadronicRate, bcGlobalIndex, bcTimeFrameId, bcBcInTimeFrame); + } else if (trk.tpcInnerParam() > maxMomTPCOnlyPi && std::abs(trk.tofNSigmaPi()) < nSigmaTOF_TPCTOF_Pi && std::abs(trk.tpcNSigmaPi()) < nSigmaTPC_TPCTOF_Pi && downsampleTsalisCharged(trk.pt(), downsamplingTsalisPions, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Pion])) { + fillSkimmedTPCTOFTableWithTrkQA(trk, trackQA, existTrkQA, collision, trk.tpcNSigmaPi(), trk.tofNSigmaPi(), trk.itsNSigmaPi(), trk.tpcExpSignalPi(trk.tpcSignalCorrected()), o2::track::PID::Pion, runnumber, dwnSmplFactor_Pi, hadronicRate, bcGlobalIndex, bcTimeFrameId, bcBcInTimeFrame); + } + } /// Loop tracks + } + } /// process + PROCESS_SWITCH(TreeWriterTPCTOF, processWithTrQAWithCorrecteddEdx, "Samples for PID with TrackQA info with correced dEdx", false); + void processDummy(Colls const&) {} PROCESS_SWITCH(TreeWriterTPCTOF, processDummy, "Dummy function", false); From 5b9c96d1d6cc5ea3c5753ba6a0fca134894dd9b2 Mon Sep 17 00:00:00 2001 From: Francesco Mazzaschi <43742195+fmazzasc@users.noreply.github.com> Date: Thu, 26 Jun 2025 10:58:53 +0200 Subject: [PATCH 218/871] [PWGLF] Add task for lambda1405 search (#11755) Co-authored-by: Francesco Mazzaschi --- PWGLF/Tasks/Resonances/CMakeLists.txt | 5 + PWGLF/Tasks/Resonances/lambda1405analysis.cxx | 250 ++++++++++++++++++ 2 files changed, 255 insertions(+) create mode 100644 PWGLF/Tasks/Resonances/lambda1405analysis.cxx diff --git a/PWGLF/Tasks/Resonances/CMakeLists.txt b/PWGLF/Tasks/Resonances/CMakeLists.txt index 23eb01caf39..de63b597420 100644 --- a/PWGLF/Tasks/Resonances/CMakeLists.txt +++ b/PWGLF/Tasks/Resonances/CMakeLists.txt @@ -39,6 +39,11 @@ o2physics_add_dpl_workflow(k892pmanalysis PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(lambda1405analysis + SOURCES lambda1405analysis.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(lambda1520analysis SOURCES lambda1520analysis.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore diff --git a/PWGLF/Tasks/Resonances/lambda1405analysis.cxx b/PWGLF/Tasks/Resonances/lambda1405analysis.cxx new file mode 100644 index 00000000000..205503c4438 --- /dev/null +++ b/PWGLF/Tasks/Resonances/lambda1405analysis.cxx @@ -0,0 +1,250 @@ +// 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 lambda1405analysis.cxx +/// \brief Analysis task for lambda1405 via sigma kink decay +/// \author Francesco Mazzaschi + +#include "PWGLF/DataModel/LFKinkDecayTables.h" + +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/PIDResponse.h" + +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" +#include "ReconstructionDataFormats/PID.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +using TracksFull = soa::Join; +using CollisionsFull = soa::Join; +using CollisionsFullMC = soa::Join; + +struct lambda1405candidate { + // Columns for Lambda(1405) candidate + float mass = -1; // Invariant mass of the Lambda(1405) candidate + float sigmaMass = -1; // Invariant mass of the Sigma candidate + float pt = -1; // pT of the Lambda(1405) candidate + int sigmaSign = 0; // Sign of the Sigma candidate: 1 for matter, -1 for antimatter + float sigmaPt = -1; // pT of the Sigma daughter + float piPt = -1; // pT of the pion daughter + float nSigmaTPCPi = -1; // Number of sigmas for the pion candidate + int piFromSigmaID = 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 +}; + +struct lambda1405analysis { + int lambda1405PdgCode = 102132; // PDG code for Lambda(1405) + lambda1405candidate lambda1405Cand; // Lambda(1405) candidate structure + // Histograms are defined with HistogramRegistry + HistogramRegistry rEventSelection{"eventSelection", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry rLambda1405{"lambda1405", {}, 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, "DCA to primary vertex for Sigma candidates (cm)"}; + 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 cutNSigmaPi{"cutNSigmaPi", 3, "NSigmaTPCPion"}; + + void init(InitContext const&) + { + // Axes + const AxisSpec ptAxis{50, -5, 5, "#it{p}_{T} (GeV/#it{c})"}; + const AxisSpec ptPiAxis{50, -2, 2, "#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.5, "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]"}; + rEventSelection.add("hVertexZRec", "hVertexZRec", {HistType::kTH1F, {vertexZAxis}}); + rLambda1405.add("h2PtMass", "h2PtMass", {HistType::kTH2F, {ptAxis, massAxis}}); + rLambda1405.add("h2PtMassSigmaBeforeCuts", "h2PtMassSigmaBeforeCuts", {HistType::kTH2F, {ptAxis, sigmaMassAxis}}); + rLambda1405.add("h2PtMassSigma", "h2PtMassSigma", {HistType::kTH2F, {ptAxis, sigmaMassAxis}}); + rLambda1405.add("h2SigmaMassVsMass", "h2SigmaMassVsMass", {HistType::kTH2F, {massAxis, sigmaMassAxis}}); + rLambda1405.add("h2PtPiNSigma", "h2PtPiNSigma", {HistType::kTH2F, {ptPiAxis, nSigmaPiAxis}}); + + if (doprocessMC) { + // Add MC histograms if needed + rLambda1405.add("h2MassResolution", "h2MassResolution", {HistType::kTH2F, {massAxis, massResolutionAxis}}); + rLambda1405.add("h2PtResolution", "h2PtResolution", {HistType::kTH2F, {ptAxis, ptResolutionAxis}}); + rLambda1405.add("h2PtMassMC", "h2PtMassMC", {HistType::kTH2F, {ptAxis, massAxis}}); + } + } + + template + bool selectPiTrack(const Ttrack& candidate, bool piFromSigma) + { + if (std::abs(candidate.tpcNSigmaPi()) > cutNSigmaPi || candidate.tpcNClsFound() < cutNTPCClusPi || std::abs(candidate.eta()) > cutEtaDaught) { + return false; + } + if (!piFromSigma && candidate.itsNCls() < cutNITSClusPi) { + return false; + } + return true; + } + + bool selectCandidate(aod::KinkCands::iterator const& sigmaCand, TracksFull const& tracks) + { + auto piKinkTrack = sigmaCand.trackDaug_as(); + if (!selectPiTrack(piKinkTrack, true)) { + return false; + } + if (sigmaCand.mSigmaMinus() < o2::constants::physics::MassSigmaMinus - cutSigmaMass || sigmaCand.mSigmaMinus() > o2::constants::physics::MassSigmaMinus + cutSigmaMass) { + return false; + } + float sigmaRad = std::hypot(sigmaCand.xDecVtx(), sigmaCand.yDecVtx()); + if (sigmaCand.dcaMothPv() > cutDCAtoPVSigma || sigmaRad < cutSigmaRadius) { + return false; + } + rLambda1405.fill(HIST("h2PtMassSigmaBeforeCuts"), sigmaCand.mothSign() * sigmaCand.ptMoth(), sigmaCand.mSigmaMinus()); + for (const auto& piTrack : tracks) { + if (piTrack.sign() == sigmaCand.mothSign() || !selectPiTrack(piTrack, false)) { + continue; // Skip if the pion has the same sign as the Sigma or does not pass selection + } + auto sigmaMom = std::array{sigmaCand.pxMoth(), sigmaCand.pyMoth(), sigmaCand.pzMoth()}; + auto piMom = std::array{piTrack.px(), piTrack.py(), piTrack.pz()}; + float pt = std::hypot(sigmaMom[0] + piMom[0], sigmaMom[1] + piMom[1]); + float invMass = RecoDecay::m(std::array{sigmaMom, piMom}, std::array{o2::constants::physics::MassSigmaMinus, o2::constants::physics::MassPiPlus}); + if (invMass < 1.3 || invMass > 1.5) { + continue; + } + lambda1405Cand.piFromSigmaID = piKinkTrack.globalIndex(); + lambda1405Cand.sigmaID = sigmaCand.globalIndex(); + lambda1405Cand.piID = piTrack.globalIndex(); + lambda1405Cand.mass = invMass; + lambda1405Cand.sigmaMass = sigmaCand.mSigmaMinus(); + lambda1405Cand.sigmaSign = sigmaCand.mothSign(); + lambda1405Cand.pt = pt; + lambda1405Cand.sigmaPt = sigmaCand.ptMoth(); + lambda1405Cand.piPt = piTrack.pt(); + lambda1405Cand.nSigmaTPCPi = piTrack.tpcNSigmaPi(); + return true; // Candidate is selected + } + return false; // No valid pion track found + } + + void processData(CollisionsFull::iterator const& collision, aod::KinkCands const& KinkCands, TracksFull const& tracks) + { + if (std::abs(collision.posZ()) > cutzvertex || !collision.sel8()) { + return; + } + rEventSelection.fill(HIST("hVertexZRec"), collision.posZ()); + for (const auto& sigmaCand : KinkCands) { + if (selectCandidate(sigmaCand, tracks)) { + rLambda1405.fill(HIST("h2PtMass"), lambda1405Cand.sigmaSign * lambda1405Cand.pt, lambda1405Cand.mass); + rLambda1405.fill(HIST("h2PtMassSigma"), lambda1405Cand.sigmaSign * lambda1405Cand.sigmaPt, lambda1405Cand.sigmaMass); + rLambda1405.fill(HIST("h2SigmaMassVsMass"), lambda1405Cand.mass, lambda1405Cand.sigmaMass); + rLambda1405.fill(HIST("h2PtPiNSigma"), lambda1405Cand.piPt, lambda1405Cand.nSigmaTPCPi); + } + } + } + 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) + { + for (const auto& collision : collisions) { + if (std::abs(collision.posZ()) > cutzvertex || !collision.sel8()) { + continue; + } + rEventSelection.fill(HIST("hVertexZRec"), collision.posZ()); + for (const auto& sigmaCand : KinkCands) { + if (selectCandidate(sigmaCand, tracks)) { + // Do MC association + auto mcLabPiKink = trackLabelsMC.rawIteratorAt(lambda1405Cand.piFromSigmaID); + 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 + } + auto mcTrackPiKink = mcLabPiKink.mcParticle_as(); + auto mcTrackSigma = mcLabSigma.mcParticle_as(); + auto mcTrackPi = mcLabPi.mcParticle_as(); + if (std::abs(mcTrackPiKink.pdgCode()) != 211 || std::abs(mcTrackSigma.pdgCode()) != 3122 || std::abs(mcTrackPi.pdgCode()) != 211) { + continue; // Skip if not a valid pion or Sigma candidate + } + if (!mcTrackPiKink.has_mothers() || !mcTrackSigma.has_mothers() || !mcTrackPi.has_mothers()) { + continue; // Skip if no mothers found + } + // check if kink pi comes from the sigma + bool isPiFromSigma = false; + for (const auto& piMother : mcTrackPiKink.mothers_as()) { + if (piMother.globalIndex() == mcTrackSigma.globalIndex()) { + isPiFromSigma = true; + break; // Found the mother, exit loop + } + } + if (!isPiFromSigma) { + continue; // Skip if the pion does not come from the Sigma + } + // check that labpi and labsigma have the same mother (a lambda1405 candidate) + int lambda1405Id = -1; + for (const auto& piMother : mcTrackPi.mothers_as()) { + for (const auto& sigmaMother : mcTrackSigma.mothers_as()) { + if (piMother.globalIndex() == sigmaMother.globalIndex() && std::abs(piMother.pdgCode()) == lambda1405PdgCode) { + lambda1405Id = piMother.globalIndex(); + break; // Found the mother, exit loop + } + } + } + if (lambda1405Id == -1) { + continue; // Skip if the Sigma and pion do not share the same lambda1405 candidate + } + auto lambda1405Mother = particlesMC.rawIteratorAt(lambda1405Id); + LOG(info) << "Particle selected!"; + float lambda1405Mass = std::sqrt(lambda1405Mother.e() * lambda1405Mother.e() - lambda1405Mother.p() * lambda1405Mother.p()); + rLambda1405.fill(HIST("h2PtMass"), lambda1405Cand.sigmaSign * lambda1405Cand.pt, lambda1405Cand.mass); + rLambda1405.fill(HIST("h2PtMassSigma"), lambda1405Cand.sigmaSign * lambda1405Cand.sigmaPt, lambda1405Cand.sigmaMass); + rLambda1405.fill(HIST("h2SigmaMassVsMass"), lambda1405Cand.mass, lambda1405Cand.sigmaMass); + rLambda1405.fill(HIST("h2PtPiNSigma"), lambda1405Cand.piPt, lambda1405Cand.nSigmaTPCPi); + rLambda1405.fill(HIST("h2MassResolution"), lambda1405Mass, lambda1405Mass - lambda1405Cand.mass); + rLambda1405.fill(HIST("h2PtResolution"), lambda1405Cand.pt, lambda1405Cand.pt - lambda1405Mother.pt()); + } + } + } + // Loop over generated particles to fill MC histograms + for (const auto& mcPart : particlesMC) { + if (std::abs(mcPart.pdgCode()) != lambda1405PdgCode) { + continue; // Only consider Lambda(1405) candidates + } + + if (!mcPart.has_daughters()) { + continue; // Skip if no daughters + } + // Check if the Lambda(1405) has a Sigma daughter + bool hasSigmaDaughter = false; + for (const auto& daughter : mcPart.daughters_as()) { + if (std::abs(daughter.pdgCode()) == 3122) { // Sigma PDG code + hasSigmaDaughter = true; + break; // Found a Sigma daughter, exit loop + } + } + if (!hasSigmaDaughter) { + continue; // Skip if no Sigma daughter found + } + + float mcMass = std::sqrt(mcPart.e() * mcPart.e() - mcPart.p() * mcPart.p()); + rLambda1405.fill(HIST("h2PtMassMC"), mcPart.pt(), mcMass); + } + } + PROCESS_SWITCH(lambda1405analysis, processMC, "MC processing", false); +}; +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +} From 536782db68ce572b80fbea7bdfd174138f61bd9a Mon Sep 17 00:00:00 2001 From: ddobrigk Date: Thu, 26 Jun 2025 15:23:45 +0200 Subject: [PATCH 219/871] [Common] Fix autodetection string typos, add autodependency enabling (#11778) --- Common/Tools/MultModule.h | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/Common/Tools/MultModule.h b/Common/Tools/MultModule.h index 07397131b68..bb6e1760344 100644 --- a/Common/Tools/MultModule.h +++ b/Common/Tools/MultModule.h @@ -62,9 +62,9 @@ static const std::vector tableNames{ "FDDMultZeqs", "PVMultZeqs", "MultMCExtras", - "kMult2MCExtras", - "kMFTMults", - "kMultsGlobal", + "Mult2MCExtras", + "MFTMults", + "MultsGlobal", // centrality subcomponent "CentRun2V0Ms", @@ -475,6 +475,14 @@ class MultModule internalOpts.mEnabledTables[kFDDMultZeqs] = 1; listOfRequestors[kFDDMultZeqs].Append(Form("%s ", "dependency check")); } + if (internalOpts.mEnabledTables[kCentMFTs] && !internalOpts.mEnabledTables[kMFTMults]) { + internalOpts.mEnabledTables[kMFTMults] = 1; + listOfRequestors[kMFTMults].Append(Form("%s ", "dependency check")); + } + if (internalOpts.mEnabledTables[kCentNGlobals] && !internalOpts.mEnabledTables[kMultsGlobal]) { + internalOpts.mEnabledTables[kMultsGlobal] = 1; + listOfRequestors[kMultsGlobal].Append(Form("%s ", "dependency check")); + } mRunNumber = 0; mRunNumberCentrality = 0; From 4b0527db439aabc56b8b47e258c894170481891c Mon Sep 17 00:00:00 2001 From: Jaideep Tanwar <141036812+jtanwar2212@users.noreply.github.com> Date: Thu, 26 Jun 2025 20:03:37 +0530 Subject: [PATCH 220/871] [PWGLF] corrected the ITS response (#11748) Co-authored-by: ALICE Action Bot --- PWGLF/Tasks/Nuspex/nucleitpcpbpb.cxx | 49 +++++++++++++++++----------- 1 file changed, 30 insertions(+), 19 deletions(-) diff --git a/PWGLF/Tasks/Nuspex/nucleitpcpbpb.cxx b/PWGLF/Tasks/Nuspex/nucleitpcpbpb.cxx index b833a4cf0de..110afcc0a19 100644 --- a/PWGLF/Tasks/Nuspex/nucleitpcpbpb.cxx +++ b/PWGLF/Tasks/Nuspex/nucleitpcpbpb.cxx @@ -157,6 +157,8 @@ struct NucleitpcPbPb { int mRunNumber, occupancy; float dBz, momn; TRandom3 rand; + float He3 = 4; + float He4 = 5; //---------------------------------------------------------------------------------------------------------------- void init(InitContext const&) { @@ -257,20 +259,20 @@ struct NucleitpcPbPb { continue; if ((getRigidity(track) < cfgTrackPIDsettings->get(i, "minRigidity") || getRigidity(track) > cfgTrackPIDsettings->get(i, "maxRigidity")) && cfgRigidityCutRequire) continue; - float pt_momn; + float ptMomn; setTrackParCov(track, mTrackParCov); mTrackParCov.setPID(track.pidForTracking()); - pt_momn = (i == 4 || i == 5) ? 2 * mTrackParCov.getPt() : mTrackParCov.getPt(); - bool insideDCAxy = (std::abs(track.dcaXY()) <= (cfgTrackPIDsettings->get(i, "maxDcaXY") * (0.0105f + 0.0350f / std::pow(pt_momn, 1.1f)))); - if ((!(insideDCAxy) || std::abs(track.dcaZ()) > DCAzSigma(pt_momn, cfgTrackPIDsettings->get(i, "maxDcaZ"))) && cfgDCAwithptRequire) + ptMomn = (i == He3 || i == He4) ? 2 * mTrackParCov.getPt() : mTrackParCov.getPt(); + bool insideDCAxy = (std::abs(track.dcaXY()) <= (cfgTrackPIDsettings->get(i, "maxDcaXY") * (0.0105f + 0.0350f / std::pow(ptMomn, 1.1f)))); // o2-linter: disable=magic-number (To be checked) + if ((!(insideDCAxy) || std::abs(track.dcaZ()) > DCAzSigma(ptMomn, cfgTrackPIDsettings->get(i, "maxDcaZ"))) && cfgDCAwithptRequire) continue; if (track.sign() > 0) { - histos.fill(HIST("histDcaZVsPtData_particle"), pt_momn, track.dcaZ()); - histos.fill(HIST("histDcaXYVsPtData_particle"), pt_momn, track.dcaXY()); + histos.fill(HIST("histDcaZVsPtData_particle"), ptMomn, track.dcaZ()); + histos.fill(HIST("histDcaXYVsPtData_particle"), ptMomn, track.dcaXY()); } if (track.sign() < 0) { - histos.fill(HIST("histDcaZVsPtData_antiparticle"), pt_momn, track.dcaZ()); - histos.fill(HIST("histDcaXYVsPtData_antiparticle"), pt_momn, track.dcaXY()); + histos.fill(HIST("histDcaZVsPtData_antiparticle"), ptMomn, track.dcaZ()); + histos.fill(HIST("histDcaXYVsPtData_antiparticle"), ptMomn, track.dcaXY()); } float tpcNsigma = getTPCnSigma(track, primaryParticles.at(i)); if ((std::abs(tpcNsigma) > cfgTrackPIDsettings->get(i, "maxTPCnSigma")) && cfgmaxTPCnSigmaRequire) @@ -284,7 +286,7 @@ struct NucleitpcPbPb { if (!track.hasTOF() && cfgTrackPIDsettings->get(i, "TOFrequiredabove") < 1) continue; float beta{o2::pid::tof::Beta::GetBeta(track)}; - float charge{1.f + static_cast(i == 4 || i == 5)}; + float charge{1.f + static_cast(i == He3 || i == He4)}; float tofMasses = getRigidity(track) * charge * std::sqrt(1.f / (beta * beta) - 1.f); if ((getRigidity(track) > cfgTrackPIDsettings->get(i, "TOFrequiredabove") && (tofMasses < cfgTrackPIDsettings->get(i, "minTOFmass") || tofMasses > cfgTrackPIDsettings->get(i, "maxTOFmass"))) && cfgmassRequire) continue; @@ -399,15 +401,15 @@ struct NucleitpcPbPb { if (cfgFillnsigma) { int i = species; const float tpcNsigma = getTPCnSigma(track, primaryParticles.at(i)); - float pt_momn; + float ptMomn; setTrackParCov(track, mTrackParCov); mTrackParCov.setPID(track.pidForTracking()); - pt_momn = (i == 4 || i == 5) ? 2 * mTrackParCov.getPt() : mTrackParCov.getPt(); + ptMomn = (i == He3 || i == He4) ? 2 * mTrackParCov.getPt() : mTrackParCov.getPt(); if (track.sign() > 0) { - hNsigmaPt[2 * species]->Fill(pt_momn, tpcNsigma); + hNsigmaPt[2 * species]->Fill(ptMomn, tpcNsigma); } if (track.sign() < 0) { - hNsigmaPt[2 * species]->Fill(pt_momn, tpcNsigma); + hNsigmaPt[2 * species]->Fill(ptMomn, tpcNsigma); } } } @@ -422,20 +424,20 @@ struct NucleitpcPbPb { float beta{o2::pid::tof::Beta::GetBeta(track)}; if (beta <= 0.f || beta >= 1.f) return; - float charge = (species == 4 || species == 5) ? 2.f : 1.f; + float charge = (species == He3 || species == He4) ? 2.f : 1.f; float p = getRigidity(track); // assuming this is the momentum from inner TPC float massTOF = p * charge * std::sqrt(1.f / (beta * beta) - 1.f); // get PDG mass float pdgMass = particleMasses[species]; float massDiff = massTOF - pdgMass; - float pt_momn; + float ptMomn; setTrackParCov(track, mTrackParCov); mTrackParCov.setPID(track.pidForTracking()); - pt_momn = (species == 4 || species == 5) ? 2 * mTrackParCov.getPt() : mTrackParCov.getPt(); + ptMomn = (species == He3 || species == He4) ? 2 * mTrackParCov.getPt() : mTrackParCov.getPt(); if (track.sign() > 0) { - hmass[2 * species]->Fill(pt_momn, massDiff * massDiff); + hmass[2 * species]->Fill(ptMomn, massDiff * massDiff); } else if (track.sign() < 0) { - hmass[2 * species + 1]->Fill(pt_momn, massDiff * massDiff); + hmass[2 * species + 1]->Fill(ptMomn, massDiff * massDiff); } } @@ -471,9 +473,18 @@ struct NucleitpcPbPb { if (!track.hasITS()) return -999; o2::aod::ITSResponse itsResponse; + if (particle.name == "pion") + return itsResponse.nSigmaITS(track); + if (particle.name == "proton") + return itsResponse.nSigmaITS(track); + if (particle.name == "deuteron") + return itsResponse.nSigmaITS(track); + if (particle.name == "triton") + return itsResponse.nSigmaITS(track); if (particle.name == "helion") return itsResponse.nSigmaITS(track); - + if (particle.name == "alpha") + return itsResponse.nSigmaITS(track); return -999; // fallback if no match } From 5d40191538e5908bed09551cfd4c0d2ca27dfecc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Jacazio?= Date: Thu, 26 Jun 2025 18:26:54 +0200 Subject: [PATCH 221/871] [Common,DPG] PIDResponseITS inherit parameters from base task, manage arrays in TableHelper, align QA (#11777) --- Common/Core/TableHelper.h | 12 ++++---- Common/DataModel/PIDResponseITS.h | 38 ++++++++++++++++++++++++- DPG/Tasks/AOTTrack/PID/ITS/qaPIDITS.cxx | 18 ++++++------ 3 files changed, 54 insertions(+), 14 deletions(-) diff --git a/Common/Core/TableHelper.h b/Common/Core/TableHelper.h index f4faf9dc8c8..afb42c5669a 100644 --- a/Common/Core/TableHelper.h +++ b/Common/Core/TableHelper.h @@ -18,12 +18,12 @@ #ifndef COMMON_CORE_TABLEHELPER_H_ #define COMMON_CORE_TABLEHELPER_H_ -#include - #include "Framework/Configurable.h" #include "Framework/InitContext.h" #include "Framework/RunningWorkflowInfo.h" +#include + /// Function to print the table required in the full workflow /// @param initContext initContext of the init function void printTablesInWorkflow(o2::framework::InitContext& initContext); @@ -76,14 +76,16 @@ bool getTaskOptionValue(o2::framework::InitContext& initContext, const std::stri } if (device.name == taskName) { // Found the mother task int optionCounter = 0; - for (auto const& option : device.options) { + for (const o2::framework::ConfigParamSpec& option : device.options) { if (verbose) { - LOG(info) << " Option " << optionCounter++ << " " << option.name << " = '" << option.defaultValue.asString() << "'"; + LOG(info) << " Option " << optionCounter++ << " " << option.name << " of type " << static_cast(option.type) << " = '" << option.defaultValue.asString() << "'"; } if (option.name == optName) { value = option.defaultValue.get(); if (verbose) { - LOG(info) << " Found option '" << optName << "' with value '" << value << "'"; + if constexpr (!std::is_same_v>) { + LOG(info) << " Found option '" << optName << "' with value '" << value << "'"; + } found = true; } else { return true; diff --git a/Common/DataModel/PIDResponseITS.h b/Common/DataModel/PIDResponseITS.h index 6a6afdc8827..1eca2bd164d 100644 --- a/Common/DataModel/PIDResponseITS.h +++ b/Common/DataModel/PIDResponseITS.h @@ -23,10 +23,12 @@ #define COMMON_DATAMODEL_PIDRESPONSEITS_H_ // O2 includes +#include "TableHelper.h" + #include "Framework/ASoA.h" #include "Framework/AnalysisDataModel.h" -#include "ReconstructionDataFormats/PID.h" #include "Framework/Logger.h" +#include "ReconstructionDataFormats/PID.h" namespace o2::aod { @@ -125,6 +127,40 @@ struct ITSResponse { 0.09, -999., -999.); } + /// Initialize the TOF response parameters in the init function of each task + /// \param initContext Initialization context. Gets the configuration parameters from the pidITS task + static void setParameters(o2::framework::InitContext& initContext, bool isMC = false) + { + float p0 = 0, p1 = 0, p2 = 0; + float p0_Z2 = 0, p1_Z2 = 0, p2_Z2 = 0; + float p0_res = 0, p1_res = 0, p2_res = 0; + float p0_res_Z2 = 0, p1_res_Z2 = 0, p2_res_Z2 = 0; + o2::framework::LabeledArray itsParams; + getTaskOptionValue(initContext, "its-pid", "itsParams", itsParams, true); + auto data = itsParams.getData(); + const int col = isMC ? 1 : 0; // 0 for Data, 1 for MC + if (data.rows != 2 || data.cols != 12) { + LOG(fatal) << "ITSResponse parameters not initialized, check the itsParams configuration"; + } + p0 = data(col, 0); + p1 = data(col, 1); + p2 = data(col, 2); + p0_Z2 = data(col, 3); + p1_Z2 = data(col, 4); + p2_Z2 = data(col, 5); + p0_res = data(col, 6); + p1_res = data(col, 7); + p2_res = data(col, 8); + p0_res_Z2 = data(col, 9); + p1_res_Z2 = data(col, 10); + p2_res_Z2 = data(col, 11); + + setParameters(p0, p1, p2, + p0_Z2, p1_Z2, p2_Z2, + p0_res, p1_res, p2_res, + p0_res_Z2, p1_res_Z2, p2_res_Z2); + } + private: static std::array mITSRespParams; static std::array mITSRespParamsZ2; diff --git a/DPG/Tasks/AOTTrack/PID/ITS/qaPIDITS.cxx b/DPG/Tasks/AOTTrack/PID/ITS/qaPIDITS.cxx index c93d5980498..f247426df34 100644 --- a/DPG/Tasks/AOTTrack/PID/ITS/qaPIDITS.cxx +++ b/DPG/Tasks/AOTTrack/PID/ITS/qaPIDITS.cxx @@ -14,17 +14,18 @@ /// \brief Implementation for QA tasks of the ITS PID quantities /// -#include -#include +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/PIDResponseITS.h" +#include "Common/DataModel/TrackSelectionTables.h" #include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" #include "Framework/HistogramRegistry.h" #include "Framework/StaticFor.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/PIDResponse.h" -#include "Common/DataModel/PIDResponseITS.h" +#include "Framework/runDataProcessing.h" + +#include +#include using namespace o2; using namespace o2::framework; @@ -183,8 +184,9 @@ struct itsPidQa { return averageClusterSizePerCoslInv(track.itsClusterSizes(), track.eta()); } - void init(o2::framework::InitContext&) + void init(o2::framework::InitContext& context) { + o2::aod::ITSResponse::setParameters(context); const AxisSpec vtxZAxis{100, -20, 20, "Vtx_{z} (cm)"}; const AxisSpec etaAxis{etaBins, "#it{#eta}"}; const AxisSpec phiAxis{phiBins, "#it{#phi}"}; From a012c2b36f82294664493bcbd120dbebb6122a05 Mon Sep 17 00:00:00 2001 From: Noor Koster <82090643+cnkoster@users.noreply.github.com> Date: Thu, 26 Jun 2025 18:27:31 +0200 Subject: [PATCH 222/871] [PWGCF] Add QA plots and clean up task (#11784) Co-authored-by: ALICE Action Bot --- PWGCF/Flow/TableProducer/zdcQVectors.cxx | 61 ++++++++++++++++++++++-- PWGCF/Flow/Tasks/flowSP.cxx | 11 ----- 2 files changed, 56 insertions(+), 16 deletions(-) diff --git a/PWGCF/Flow/TableProducer/zdcQVectors.cxx b/PWGCF/Flow/TableProducer/zdcQVectors.cxx index eda3fb76aef..1b61d449606 100644 --- a/PWGCF/Flow/TableProducer/zdcQVectors.cxx +++ b/PWGCF/Flow/TableProducer/zdcQVectors.cxx @@ -144,6 +144,7 @@ struct ZdcQVectors { using BCsRun3 = soa::Join; enum SelectionCriteria { + evSel_FilteredEvent, evSel_Zvtx, evSel_sel8, evSel_occupancy, @@ -228,8 +229,8 @@ struct ZdcQVectors { } // end of capCOORDS } // end of sides - registry.add("QA/centrality_before", "centrality_before", kTH1D, {{200, 0, 100}}); - registry.add("QA/centrality_after", "centrality_after", kTH1D, {{200, 0, 100}}); + registry.add("QA/centrality_before", "centrality_before", kTH1D, {{100, 0, 100}}); + registry.add("QA/centrality_after", "centrality_after", kTH1D, {{100, 0, 100}}); registry.add("QA/ZNA_Energy", "ZNA_Energy", kTProfile, {{8, 0, 8}}); registry.add("QA/ZNC_Energy", "ZNC_Energy", kTProfile, {{8, 0, 8}}); @@ -251,12 +252,29 @@ struct ZdcQVectors { registry.add("QA/before/ZNC_Qx", "ZNC_Qx", kTProfile, {{1, 0, 1.}}); registry.add("QA/before/ZNC_Qy", "ZNC_Qy", kTProfile, {{1, 0, 1.}}); + registry.add("QA/before/ZNA_Qx_vs_Centrality", "ZNA_Qx_vs_Centrality", kTH2D, {{100, 0, 100}, {200, -2, 2}}); + registry.add("QA/before/ZNA_Qy_vs_Centrality", "ZNA_Qy_vs_Centrality", kTH2D, {{100, 0, 100}, {200, -2, 2}}); + registry.add("QA/before/ZNC_Qx_vs_Centrality", "ZNC_Qx_vs_Centrality", kTH2D, {{100, 0, 100}, {200, -2, 2}}); + registry.add("QA/before/ZNC_Qy_vs_Centrality", "ZNC_Qy_vs_Centrality", kTH2D, {{100, 0, 100}, {200, -2, 2}}); + + registry.add("QA/before/ZNA_pmC_vs_Centrality", "ZNA_pmC_vs_Centrality", kTH2D, {{100, 0, 100}, {300, 0, 300}}); + registry.add("QA/before/ZNA_pm1_vs_Centrality", "ZNA_pm1_vs_Centrality", kTH2D, {{100, 0, 100}, {150, 0, 150}}); + registry.add("QA/before/ZNA_pm2_vs_Centrality", "ZNA_pm2_vs_Centrality", kTH2D, {{100, 0, 100}, {150, 0, 150}}); + registry.add("QA/before/ZNA_pm3_vs_Centrality", "ZNA_pm3_vs_Centrality", kTH2D, {{100, 0, 100}, {150, 0, 150}}); + registry.add("QA/before/ZNA_pm4_vs_Centrality", "ZNA_pm4_vs_Centrality", kTH2D, {{100, 0, 100}, {150, 0, 150}}); + + registry.add("QA/before/ZNC_pmC_vs_Centrality", "ZNC_pmC_vs_Centrality", kTH2D, {{100, 0, 100}, {300, 0, 300}}); + registry.add("QA/before/ZNC_pm1_vs_Centrality", "ZNC_pm1_vs_Centrality", kTH2D, {{100, 0, 100}, {150, 0, 150}}); + registry.add("QA/before/ZNC_pm2_vs_Centrality", "ZNC_pm2_vs_Centrality", kTH2D, {{100, 0, 100}, {150, 0, 150}}); + registry.add("QA/before/ZNC_pm3_vs_Centrality", "ZNC_pm3_vs_Centrality", kTH2D, {{100, 0, 100}, {150, 0, 150}}); + registry.add("QA/before/ZNC_pm4_vs_Centrality", "ZNC_pm4_vs_Centrality", kTH2D, {{100, 0, 100}, {150, 0, 150}}); + + registry.addClone("QA/before/", "QA/after/"); + registry.add("QA/before/ZNA_Qx_noEq", "ZNA_Qx_noEq", kTProfile, {{1, 0, 1.}}); registry.add("QA/before/ZNA_Qy_noEq", "ZNA_Qy_noEq", kTProfile, {{1, 0, 1.}}); registry.add("QA/before/ZNC_Qx_noEq", "ZNC_Qx_noEq", kTProfile, {{1, 0, 1.}}); registry.add("QA/before/ZNC_Qy_noEq", "ZNC_Qy_noEq", kTProfile, {{1, 0, 1.}}); - - registry.addClone("QA/before/", "QA/after/"); } // Tower mean energies vs. centrality used for tower gain equalisation @@ -273,6 +291,7 @@ struct ZdcQVectors { registry.add("vmean/hvertex_vz", "hvertex_vz", kTProfile, {{1, 0., 1.}}); registry.add("hEventCount", "Number of Event; Cut; #Events Passed Cut", {HistType::kTH1D, {{nEventSelections, 0, nEventSelections}}}); + registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(evSel_FilteredEvent + 1, "Filtered events"); registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(evSel_Zvtx + 1, "Z vertex cut event"); registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(evSel_sel8 + 1, "Sel8"); registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(evSel_occupancy + 1, "kOccupancy"); @@ -290,7 +309,7 @@ struct ZdcQVectors { { if (std::fabs(collision.posZ()) > cfgVtxZ) return 0; - registry.fill(HIST("hEventCount"), evSel_sel8); + registry.fill(HIST("hEventCount"), evSel_Zvtx); if (!collision.sel8()) return 0; @@ -403,6 +422,11 @@ struct ZdcQVectors { registry.fill(HIST("QA/") + HIST(Time[ft]) + HIST("/hQYA_QXC_vs_vz"), v[2], qya * qxc); registry.fill(HIST("QA/") + HIST(Time[ft]) + HIST("/hQXA_QYC_vs_vz"), v[2], qxa * qyc); + registry.fill(HIST("QA/") + HIST(Time[ft]) + HIST("/ZNA_Qx_vs_Centrality"), centrality, qxa); + registry.fill(HIST("QA/") + HIST(Time[ft]) + HIST("/ZNA_Qy_vs_Centrality"), centrality, qya); + registry.fill(HIST("QA/") + HIST(Time[ft]) + HIST("/ZNC_Qx_vs_Centrality"), centrality, qxc); + registry.fill(HIST("QA/") + HIST(Time[ft]) + HIST("/ZNC_Qy_vs_Centrality"), centrality, qyc); + // add psi!! double psiA = 1.0 * std::atan2(qxc, qxa); registry.fill(HIST("QA/") + HIST(Time[ft]) + HIST("/hSPplaneA"), psiA, centrality, 1); @@ -536,6 +560,8 @@ struct ZdcQVectors { if (cfgFillCommonRegistry) registry.fill(HIST("QA/centrality_before"), cent); + registry.fill(HIST("hEventCount"), evSel_FilteredEvent); + if (!eventSelected(collision, cent)) { // event not selected isSelected = false; @@ -678,6 +704,7 @@ struct ZdcQVectors { registry.get(HIST("QA/before/ZNC_pm3"))->Fill(Form("%d", runnumber), eZN[6]); registry.get(HIST("QA/before/ZNC_pm4"))->Fill(Form("%d", runnumber), eZN[7]); + registry.get(HIST("QA/after/ZNA_pm1"))->Fill(Form("%d", runnumber), e[0]); registry.get(HIST("QA/after/ZNA_pm2"))->Fill(Form("%d", runnumber), e[1]); registry.get(HIST("QA/after/ZNA_pm3"))->Fill(Form("%d", runnumber), e[2]); registry.get(HIST("QA/after/ZNA_pm4"))->Fill(Form("%d", runnumber), e[3]); @@ -685,6 +712,30 @@ struct ZdcQVectors { registry.get(HIST("QA/after/ZNC_pm2"))->Fill(Form("%d", runnumber), e[5]); registry.get(HIST("QA/after/ZNC_pm3"))->Fill(Form("%d", runnumber), e[6]); registry.get(HIST("QA/after/ZNC_pm4"))->Fill(Form("%d", runnumber), e[7]); + + registry.fill(HIST("QA/") + HIST("before") + HIST("/ZNA_pmC_vs_Centrality"), centrality, zdcCol.energyCommonZNA()); + registry.fill(HIST("QA/") + HIST("before") + HIST("/ZNA_pm1_vs_Centrality"), centrality, eZN[0]); + registry.fill(HIST("QA/") + HIST("before") + HIST("/ZNA_pm2_vs_Centrality"), centrality, eZN[1]); + registry.fill(HIST("QA/") + HIST("before") + HIST("/ZNA_pm3_vs_Centrality"), centrality, eZN[2]); + registry.fill(HIST("QA/") + HIST("before") + HIST("/ZNA_pm4_vs_Centrality"), centrality, eZN[3]); + + registry.fill(HIST("QA/") + HIST("before") + HIST("/ZNC_pmC_vs_Centrality"), centrality, zdcCol.energyCommonZNC()); + registry.fill(HIST("QA/") + HIST("before") + HIST("/ZNC_pm1_vs_Centrality"), centrality, eZN[4]); + registry.fill(HIST("QA/") + HIST("before") + HIST("/ZNC_pm2_vs_Centrality"), centrality, eZN[5]); + registry.fill(HIST("QA/") + HIST("before") + HIST("/ZNC_pm3_vs_Centrality"), centrality, eZN[6]); + registry.fill(HIST("QA/") + HIST("before") + HIST("/ZNC_pm4_vs_Centrality"), centrality, eZN[7]); + + registry.fill(HIST("QA/") + HIST("after") + HIST("/ZNA_pmC_vs_Centrality"), centrality, zdcCol.energyCommonZNA()); + registry.fill(HIST("QA/") + HIST("after") + HIST("/ZNA_pm1_vs_Centrality"), centrality, e[0]); + registry.fill(HIST("QA/") + HIST("after") + HIST("/ZNA_pm2_vs_Centrality"), centrality, e[1]); + registry.fill(HIST("QA/") + HIST("after") + HIST("/ZNA_pm3_vs_Centrality"), centrality, e[2]); + registry.fill(HIST("QA/") + HIST("after") + HIST("/ZNA_pm4_vs_Centrality"), centrality, e[3]); + + registry.fill(HIST("QA/") + HIST("after") + HIST("/ZNC_pmC_vs_Centrality"), centrality, zdcCol.energyCommonZNC()); + registry.fill(HIST("QA/") + HIST("after") + HIST("/ZNC_pm1_vs_Centrality"), centrality, e[4]); + registry.fill(HIST("QA/") + HIST("after") + HIST("/ZNC_pm2_vs_Centrality"), centrality, e[5]); + registry.fill(HIST("QA/") + HIST("after") + HIST("/ZNC_pm3_vs_Centrality"), centrality, e[6]); + registry.fill(HIST("QA/") + HIST("after") + HIST("/ZNC_pm4_vs_Centrality"), centrality, e[7]); } // Now calculate Q-vector diff --git a/PWGCF/Flow/Tasks/flowSP.cxx b/PWGCF/Flow/Tasks/flowSP.cxx index b8e6a4781db..f1d28c67369 100644 --- a/PWGCF/Flow/Tasks/flowSP.cxx +++ b/PWGCF/Flow/Tasks/flowSP.cxx @@ -311,9 +311,7 @@ struct FlowSP { registry.add("QA/after/hCentFV0A", "; Cent FV0A (%); ", {HistType::kTH1D, {axisCent}}); registry.add("QA/after/hCentNGlobal", "; Cent NGlobal (%); ", {HistType::kTH1D, {axisCent}}); registry.add("QA/after/globalTracks_centT0C", "", {HistType::kTH2D, {axisCent, axisNch}}); - // registry.add("QA/after/globalTracks_centNGlobal", "", {HistType::kTH2D, {axisCent, axisNch}}); registry.add("QA/after/PVTracks_centT0C", "", {HistType::kTH2D, {axisCent, axisMultpv}}); - // registry.add("QA/after/PVTracks_centNGlobal", "", {HistType::kTH2D, {axisCent, axisMultpv}}); registry.add("QA/after/globalTracks_PVTracks", "", {HistType::kTH2D, {axisMultpv, axisNch}}); registry.add("QA/after/globalTracks_multT0A", "", {HistType::kTH2D, {axisT0a, axisNch}}); registry.add("QA/after/globalTracks_multV0A", "", {HistType::kTH2D, {axisV0a, axisNch}}); @@ -607,12 +605,10 @@ struct FlowSP { } if (nIdentified == 0) { - // LOGF(warning, "No PID match found for |nSigma| < %.2f", cfgTrackSelsPIDNsigma); return kUnidentified; // No PID match found } else if (nIdentified == 1) { return valPID; } else { - // LOGF(warning, "Track identified as %i particles for |nSigma| < %.2f", nIdentified, cfgTrackSelsPIDNsigma); return kUnidentified; // Multiple PID matches found } @@ -622,10 +618,8 @@ struct FlowSP { int getMagneticField(uint64_t timestamp) { // TODO done only once (and not per run). Will be replaced by CCDBConfigurable - // static o2::parameters::GRPObject* grpo = nullptr; static o2::parameters::GRPMagField* grpo = nullptr; if (grpo == nullptr) { - // grpo = ccdb->getForTimeStamp("GLO/GRP/GRP", timestamp); grpo = ccdb->getForTimeStamp("GLO/Config/GRPMagField", timestamp); if (grpo == nullptr) { LOGF(fatal, "GRP object not found for timestamp %llu", timestamp); @@ -816,8 +810,6 @@ struct FlowSP { registry.fill(HIST("hTrackCount"), trackSel_DCAz); - // registry.fill(HIST("hTrackCount"), trackSel_GlobalTracks); - if (track.tpcNClsFound() < cfgTrackSelsNcls) return false; registry.fill(HIST("hTrackCount"), trackSel_NCls); @@ -1363,7 +1355,6 @@ struct FlowSP { fillEventQA(collision, tracks); - // LOGF(info, "Size of tracks: %i", tracks.size()); registry.fill(HIST("trackMCReco/hTrackSize_unFiltered"), tracks.size()); registry.fill(HIST("trackMCReco/hTrackSize_Filtered"), filteredTracks.size()); @@ -1388,10 +1379,8 @@ struct FlowSP { } PROCESS_SWITCH(FlowSP, processMCReco, "Process analysis for MC reconstructed events", false); - // Filter mcCollFilter = nabs(aod::mccollision::posZ) < cfgEvSelsVtxZ; void processMCGen(aod::McCollisions const& mcCollisions, CCs const& collisions, TCs const& tracks, FilteredTCs const& filteredTracks, MCs const& McParts) { - // LOGF(info, "Size of mccollisions: %i", mcCollisions.size()); for (const auto& mcCollision : mcCollisions) { float centrality = -1; From 3ad41db25ccad36f5a9c2e4a7ecd35b3a7169906 Mon Sep 17 00:00:00 2001 From: Ravindra Singh <56298081+singhra1994@users.noreply.github.com> Date: Thu, 26 Jun 2025 18:40:57 +0200 Subject: [PATCH 223/871] [PWGHF] Add processes to select Sc collisions. Fix rapidity bug for proton. (#11678) --- .../HFC/TableProducer/correlatorLcHadrons.cxx | 20 +- .../TableProducer/correlatorLcScHadrons.cxx | 429 +++++++++++------- PWGHF/HFC/Utils/utilsCorrelations.h | 72 ++- 3 files changed, 334 insertions(+), 187 deletions(-) diff --git a/PWGHF/HFC/TableProducer/correlatorLcHadrons.cxx b/PWGHF/HFC/TableProducer/correlatorLcHadrons.cxx index c76ec3d62d2..7dc6d877a8b 100644 --- a/PWGHF/HFC/TableProducer/correlatorLcHadrons.cxx +++ b/PWGHF/HFC/TableProducer/correlatorLcHadrons.cxx @@ -211,7 +211,7 @@ struct HfCorrelatorLcHadrons { Service pdg; int leadingIndex = 0; bool correlationStatus = false; - static constexpr size_t nDaughters{3u}; + static constexpr std::size_t NDaughters{3u}; TRandom3* rnd = new TRandom3(0); // Event Mixing for the Data Mode @@ -232,8 +232,10 @@ struct HfCorrelatorLcHadrons { 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); - // Preslice perTrueCollision = o2::aod::mcparticle::McCollisionId; Preslice perTrueCollision = o2::aod::mcparticle::mcCollisionId; + Preslice perCollisionID = aod::track::collisionId; + Preslice cand3ProngPerCol = aod::hf_cand::collisionId; + // configurable axis definition 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"}; @@ -441,7 +443,7 @@ struct HfCorrelatorLcHadrons { track.pt() * track.sign(), poolBin, correlationStatus); - entryLcHadronPairY(track.y() - hfHelper.yLc(candidate)); + entryLcHadronPairY(track.rapidity(MassProton) - hfHelper.yLc(candidate)); // only for proton as of now entryLcHadronRecoInfo(hfHelper.invMassLcToPKPi(candidate), false); entryLcHadronGenInfo(false, false, 0); entryLcHadronMlInfo(outputMl[0], outputMl[1]); @@ -457,7 +459,7 @@ struct HfCorrelatorLcHadrons { track.pt() * track.sign(), poolBin, correlationStatus); - entryLcHadronPairY(track.y() - hfHelper.yLc(candidate)); + entryLcHadronPairY(track.rapidity(MassProton) - hfHelper.yLc(candidate)); // only for proton as of now entryLcHadronRecoInfo(hfHelper.invMassLcToPiKP(candidate), false); entryLcHadronGenInfo(false, false, 0); entryLcHadronMlInfo(outputMl[0], outputMl[1]); @@ -694,7 +696,7 @@ struct HfCorrelatorLcHadrons { track.pt() * track.sign(), poolBin, correlationStatus); - entryLcHadronPairY(track.y() - hfHelper.yLc(candidate)); + entryLcHadronPairY(track.rapidity(MassProton) - hfHelper.yLc(candidate)); // only for proton as of now entryLcHadronRecoInfo(hfHelper.invMassLcToPKPi(candidate), isLcSignal); if (fillTrkPID) { entryLcHadronPairTrkPID(track.tpcNSigmaPr(), track.tpcNSigmaKa(), track.tpcNSigmaPi(), track.tofNSigmaPr(), track.tofNSigmaKa(), track.tofNSigmaPi()); @@ -724,7 +726,7 @@ struct HfCorrelatorLcHadrons { track.pt() * track.sign(), poolBin, correlationStatus); - entryLcHadronPairY(track.y() - hfHelper.yLc(candidate)); + entryLcHadronPairY(track.rapidity(MassProton) - hfHelper.yLc(candidate)); // only for proton as of now entryLcHadronRecoInfo(hfHelper.invMassLcToPiKP(candidate), isLcSignal); if (fillTrkPID) { entryLcHadronPairTrkPID(track.tpcNSigmaPr(), track.tpcNSigmaKa(), track.tpcNSigmaPi(), track.tofNSigmaPr(), track.tofNSigmaKa(), track.tofNSigmaPi()); @@ -801,12 +803,12 @@ struct HfCorrelatorLcHadrons { // prompt and non-prompt division std::vector listDaughters{}; - std::array arrDaughLcPDG = {kProton, -kKPlus, kPiPlus}; - std::array prongsId; + std::array arrDaughLcPDG = {kProton, -kKPlus, kPiPlus}; + std::array prongsId; listDaughters.clear(); RecoDecay::getDaughters(particle, &listDaughters, arrDaughLcPDG, 2); int counterDaughters = 0; - if (listDaughters.size() == nDaughters) { + if (listDaughters.size() == NDaughters) { for (const auto& dauIdx : listDaughters) { auto daughI = mcParticles.rawIteratorAt(dauIdx - mcParticles.offset()); counterDaughters += 1; diff --git a/PWGHF/HFC/TableProducer/correlatorLcScHadrons.cxx b/PWGHF/HFC/TableProducer/correlatorLcScHadrons.cxx index 77c31d17969..21d3b4b6458 100644 --- a/PWGHF/HFC/TableProducer/correlatorLcScHadrons.cxx +++ b/PWGHF/HFC/TableProducer/correlatorLcScHadrons.cxx @@ -60,7 +60,7 @@ using BinningTypeMcGen = ColumnBinningPolicy lcSel; + Produces candSel; Configurable useSel8{"useSel8", true, "Flag for applying sel8 for collision selection"}; Configurable selNoSameBunchPileUpColl{"selNoSameBunchPileUpColl", true, "Flag for rejecting the collisions associated with the same bunch crossing"}; @@ -75,54 +75,42 @@ struct HfCorrelatorLcScHadronsSelection { using SelCollisions = soa::Join; using CandsLcDataFiltered = soa::Filtered>; using CandsLcMcRecFiltered = soa::Filtered>; + using CandsScMcRec = soa::Join; using CandidatesLcMcGen = soa::Join; - + using CandidatesScMcGen = soa::Join; // filter on selection of Lc and decay channel Lc->PKPi 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); - /// Code to select collisions with at least one Lc - for real data and data-like analysis - void processLcSelectionData(SelCollisions::iterator const& collision, - CandsLcDataFiltered const& candidates) + template + void selectionCollision(CollType const& collision, CandType const& candidates) { bool isSelColl = true; - bool isLcFound = true; + bool isCandFound = false; bool isSel8 = true; bool isNosameBunchPileUp = true; + double yCand = -999.; + const int chargeScZero = 0; if (doSelLcCollision) { for (const auto& candidate : candidates) { - if (std::abs(hfHelper.yLc(candidate)) > yCandMax || candidate.pt() < ptCandMin) { - isLcFound = false; - continue; + + if constexpr (isCandSc) { + int8_t chargeCand = candidate.charge(); + + if (chargeCand == chargeScZero) { + yCand = hfHelper.ySc0(candidate); + } else { + yCand = hfHelper.yScPlusPlus(candidate); + } + + } else { + yCand = hfHelper.yLc(candidate); } - isLcFound = true; - break; - } - } - if (useSel8) { - isSel8 = collision.sel8(); - } - if (selNoSameBunchPileUpColl) { - isNosameBunchPileUp = static_cast(collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)); - } - isSelColl = isLcFound && isSel8 && isNosameBunchPileUp; - lcSel(isSelColl); - } - PROCESS_SWITCH(HfCorrelatorLcScHadronsSelection, processLcSelectionData, "Process Lc Collision Selection Data", true); - void processLcSelectionMcRec(SelCollisions::iterator const& collision, - CandsLcMcRecFiltered const& candidates) - { - bool isSelColl = true; - bool isLcFound = true; - bool isSel8 = true; - bool isNosameBunchPileUp = true; - if (doSelLcCollision) { - for (const auto& candidate : candidates) { - if (std::abs(hfHelper.yLc(candidate)) > yCandMax || candidate.pt() < ptCandMin) { - isLcFound = false; + if (std::abs(yCand) > yCandMax || candidate.pt() < ptCandMin) { + isCandFound = false; continue; } - isLcFound = true; + isCandFound = true; break; } } @@ -132,31 +120,76 @@ struct HfCorrelatorLcScHadronsSelection { if (selNoSameBunchPileUpColl) { isNosameBunchPileUp = static_cast(collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)); } - isSelColl = isLcFound && isSel8 && isNosameBunchPileUp; - lcSel(isSelColl); + isSelColl = isCandFound && isSel8 && isNosameBunchPileUp; + candSel(isSelColl); } - PROCESS_SWITCH(HfCorrelatorLcScHadronsSelection, processLcSelectionMcRec, "Process Lc Selection McRec", false); - void processLcSelectionMcGen(aod::McCollision const&, - CandidatesLcMcGen const& mcParticles) + template + void selectionCollisionMcGen(CandType const& mcParticles) { - bool isLcFound = true; + bool isCandFound = false; + double massCand = -999.0; for (const auto& particle : mcParticles) { - if (std::abs(particle.pdgCode()) != Pdg::kLambdaCPlus) { - isLcFound = false; + + isCandFound = matchCandAndMass(particle, massCand); + if (!isCandFound) { continue; } - double yL = RecoDecay::y(particle.pVector(), MassLambdaCPlus); - if (std::abs(yL) > yCandMax || particle.pt() < ptCandMin) { - isLcFound = false; + + double yCand = RecoDecay::y(particle.pVector(), massCand); + if (std::abs(yCand) > yCandMax || particle.pt() < ptCandMin) { + isCandFound = false; continue; } - isLcFound = true; + + isCandFound = true; break; } - lcSel(isLcFound); + candSel(isCandFound); + } + + /// Code to select collisions with at least one Lc - for real data and data-like analysis + void processLcSelection(SelCollisions::iterator const& collision, + CandsLcDataFiltered const& candidates) + { + selectionCollision(collision, candidates); + } + PROCESS_SWITCH(HfCorrelatorLcScHadronsSelection, processLcSelection, "Process Lc Collision Selection for Data and Mc", true); + + void processScSelection(SelCollisions::iterator const& collision, + aod::HfCandSc const& candidates) + { + selectionCollision(collision, candidates); + } + PROCESS_SWITCH(HfCorrelatorLcScHadronsSelection, processScSelection, "Process Sc Collision Selection for Data and Mc", false); + + void processLcSelectionMcRec(SelCollisions::iterator const& collision, + CandsLcMcRecFiltered const& candidates) + { + selectionCollision(collision, candidates); + } + PROCESS_SWITCH(HfCorrelatorLcScHadronsSelection, processLcSelectionMcRec, "Process Lc Selection McRec", false); + + void processScSelectionMcRec(SelCollisions::iterator const& collision, + CandsScMcRec const& candidates) + { + selectionCollision(collision, candidates); + } + PROCESS_SWITCH(HfCorrelatorLcScHadronsSelection, processScSelectionMcRec, "Process Sc Selection McRec", false); + + void processLcSelectionMcGen(aod::McCollision const&, + CandidatesLcMcGen const& mcParticles) + { + selectionCollisionMcGen(mcParticles); } PROCESS_SWITCH(HfCorrelatorLcScHadronsSelection, processLcSelectionMcGen, "Process Lc Selection McGen", false); + + void processScSelectionMcGen(aod::McCollision const&, + CandidatesScMcGen const& mcParticles) + { + selectionCollisionMcGen(mcParticles); + } + PROCESS_SWITCH(HfCorrelatorLcScHadronsSelection, processScSelectionMcGen, "Process Lc Selection McGen", false); }; // Lc-Hadron correlation pair builder - for real data and data-like analysis (i.e. reco-level w/o matching request via Mc truth) @@ -220,16 +253,15 @@ struct HfCorrelatorLcScHadrons { bool isNonPrompt = false; bool isSignal = false; - static constexpr size_t NDaughters{3u}; TRandom3* rnd = new TRandom3(0); - std::vector outputMl = {-1., -1., -1.}; + // std::vector outputMl = {-1., -1., -1.}; std::vector outputMlPKPi = {-1., -1., -1.}; std::vector outputMlPiKP = {-1., -1., -1.}; // Event Mixing for the Data Mode - using SelCollisionsWithSc = soa::Join; - using SelCollisionsWithLc = soa::Filtered>; - using SelCollisionsWithLcMc = soa::Filtered>; // collisionFilter applied + // using SelCollisionsWithSc = soa::Join; + using SelCollisions = soa::Filtered>; + using SelCollisionsMc = soa::Filtered>; // collisionFilter applied using CandsLcData = soa::Join; using CandsLcDataFiltered = soa::Filtered; @@ -238,6 +270,8 @@ struct HfCorrelatorLcScHadrons { using CandsLcMcRec = soa::Join; using CandsLcMcRecFiltered = soa::Filtered; using CandidatesLcMcGen = soa::Join; // flagLcFilter applied + using CandsScMcRec = soa::Join; + using CandidatesScMcGen = soa::Join; // Event Mixing for the MCGen Mode using McCollisionsSel = soa::Filtered>; using McParticlesSel = soa::Filtered; @@ -249,8 +283,11 @@ struct HfCorrelatorLcScHadrons { 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); - // Preslice perTrueCollision = o2::aod::mcparticle::McCollisionId; Preslice perTrueCollision = o2::aod::mcparticle::mcCollisionId; + Preslice perCollisionID = aod::track::collisionId; + Preslice cand3ProngPerCol = aod::hf_cand::collisionId; + Preslice csndScPerCol = aod::hf_cand::collisionId; + // configurable axis definition 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"}; @@ -279,7 +316,7 @@ struct HfCorrelatorLcScHadrons { AxisSpec axisBdtScore = {binsBdtScore, "Bdt score"}; AxisSpec axisPoolBin = {binsPoolBin, "PoolBin"}; AxisSpec axisRapidity = {100, -2, 2, "Rapidity"}; - AxisSpec axisSign = {2, -1, 1, "Sign"}; + AxisSpec axisSign = {5, -2.5, 2.5, "Sign"}; registry.add("hPtCand", "Lc,Hadron candidates;candidate #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {axisPtLc}}); registry.add("hPtProng0", "Lc,Hadron candidates;prong 0 #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {axisPtLc}}); @@ -297,6 +334,7 @@ struct HfCorrelatorLcScHadrons { registry.add("hCandBin", "Lc selected in pool Bin;pool Bin;entries", {HistType::kTH1F, {{9, 0., 9.}}}); registry.add("hTracksBin", "Tracks selected in pool Bin;pool Bin;entries", {HistType::kTH1F, {{9, 0., 9.}}}); registry.add("hMassLcVsPt", "Lc candidates;inv. mass (p K #pi) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {{axisCandMass}, {axisPtLc}}}); + registry.add("hMassScVsPtVsSign", "Sc candidates;inv. mass (p K #pi) (GeV/#it{c}^{2});sign;entries", {HistType::kTH3F, {{axisCandMass}, {axisPtLc}, {axisSign}}}); registry.add("hMassLcData", "Lc candidates;inv. mass (p K #pi) (GeV/#it{c}^{2});entries", {HistType::kTH1F, {{axisCandMass}}}); registry.add("hLcPoolBin", "Lc candidates pool bin", {HistType::kTH1F, {axisPoolBin}}); registry.add("hTracksPoolBin", "Particles associated pool bin", {HistType::kTH1F, {axisPoolBin}}); @@ -329,7 +367,9 @@ struct HfCorrelatorLcScHadrons { registry.add("hPtCandMcGen", "Lc,Hadron particles - MC gen;particle #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {axisPtLc}}); registry.add("hYMcGen", "Lc,Hadron candidates - MC gen;candidate #it{#y};entries", {HistType::kTH1F, {axisRapidity}}); registry.add("hPtCandMcGenPrompt", "Lc,Hadron particles - MC Gen Prompt", {HistType::kTH1F, {axisPtLc}}); - registry.add("hPtCandMcGenNonPrompt", "Lc,Hadron particles - MC Gen Non Prompt", {HistType::kTH1F, {axisPtLc}}); + registry.add("hPtCandVsChargeMcGenPrompt", "Charm Hadron particles - MC Gen Prompt", {HistType::kTH2F, {{axisPtLc}, {axisSign}}}); + registry.add("hPtCandMcGenNonPrompt", "Charm Hadron particles - MC Gen Non Prompt", {HistType::kTH1F, {axisPtLc}}); + registry.add("hPtCandVsChargeMcGenNonPrompt", "Lc,Hadron particles - MC Gen Non Prompt", {HistType::kTH2F, {{axisPtLc}, {axisSign}}}); registry.add("hPtParticleAssocMcGen", "Associated Particle - MC Gen", {HistType::kTH1F, {axisPtHadron}}); registry.add("hEtaMcGen", "Lc,Hadron particles - MC Gen", {HistType::kTH1F, {axisEta}}); registry.add("hPhiMcGen", "Lc,Hadron particles - MC Gen", {HistType::kTH1F, {axisPhi}}); @@ -399,7 +439,7 @@ struct HfCorrelatorLcScHadrons { continue; auto chargeTrack = pdg->GetParticle(track.pdgCode())->Charge(); // Retrieve charge - registry.fill(HIST("hPtTracksVsSignGen"), track.pt(), chargeTrack / (2 * std::abs(chargeTrack))); + registry.fill(HIST("hPtTracksVsSignGen"), track.pt(), chargeTrack / (std::abs(chargeTrack))); } } template @@ -416,7 +456,7 @@ struct HfCorrelatorLcScHadrons { track.pt() * track.sign(), binPool, correlStatus); - entryCandHadronPairY(track.y() - yCand); + entryCandHadronPairY(track.rapidity(MassProton) - yCand); entryCandHadronMlInfo(outMl[0], outMl[1]); entryTrackRecoInfo(track.dcaXY(), track.dcaZ(), track.tpcNClsCrossedRows()); entryPairCandCharge(signCand); @@ -599,6 +639,7 @@ struct HfCorrelatorLcScHadrons { if (selLcPKPi) { 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) { @@ -619,6 +660,7 @@ struct HfCorrelatorLcScHadrons { if (selLcPiKP) { 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) { @@ -678,9 +720,9 @@ struct HfCorrelatorLcScHadrons { if (std::abs(motherTrk.pdgCode()) == kLambdaCPlus) continue; - registry.fill(HIST("hPtTracksVsSignRec"), track.pt(), track.sign() / 2.); + registry.fill(HIST("hPtTracksVsSignRec"), track.pt(), track.sign()); if (std::abs(mcParticle.pdgCode()) == kProton) - registry.fill(HIST("hPtTracksVsSignRecTrue"), track.pt(), track.sign() / 2.); + registry.fill(HIST("hPtTracksVsSignRecTrue"), track.pt(), track.sign()); } } @@ -827,99 +869,12 @@ struct HfCorrelatorLcScHadrons { } } - //} - - /// Lc-hadron correlation pair builder - for real data and data-like analysis (i.e. reco-level w/o matching request via MC truth) - void processDataLc(SelCollisionsWithLc::iterator const& collision, - TracksData const& tracks, - CandsLcDataFiltered const& candidates, - aod::BCsWithTimestamps const&) - { - doSameEvent(collision, tracks, candidates); - } - PROCESS_SWITCH(HfCorrelatorLcScHadrons, processDataLc, "Process data", true); - - void processDataSc(SelCollisionsWithSc::iterator const& collision, - TracksData const& tracks, - aod::Tracks const&, - aod::HfCandSc const& candidates, - CandsLcData const&, - aod::BCsWithTimestamps const&) // MUST be last among index-compatible - { - doSameEvent(collision, tracks, candidates); - } - PROCESS_SWITCH(HfCorrelatorLcScHadrons, processDataSc, "Process data Sc", false); - - /// Lc-Hadron correlation process starts for McRec - void processMcRecLc(SelCollisionsWithLc::iterator const& collision, - TracksWithMc const& tracks, - CandsLcMcRecFiltered const& candidates, - aod::McParticles const& mcParticles) - { - doSameEvent(collision, tracks, candidates, &mcParticles); - } - PROCESS_SWITCH(HfCorrelatorLcScHadrons, processMcRecLc, "Process Mc Reco mode", false); - - /// Lc-Hadron correlation process starts for McRec - void processMcRecSc(SelCollisionsWithSc::iterator const& collision, - TracksWithMc const& tracks, - aod::TracksWMc const&, - soa::Join const& candidates, - CandsLcData const&, - aod::McParticles const& mcParticles) - { - doSameEvent(collision, tracks, candidates, &mcParticles); - } - PROCESS_SWITCH(HfCorrelatorLcScHadrons, processMcRecSc, "Process Mc Reco mode", false); - - void processDataMixedEventSc(SelCollisionsWithSc const& collisions, - TracksData const& tracks, - aod::Tracks const&, - aod::HfCandSc const& candidates, - CandsLcData const&) - { - doMixEvent(collisions, tracks, candidates); - } - PROCESS_SWITCH(HfCorrelatorLcScHadrons, processDataMixedEventSc, "Process Mixed Event Data", false); - - void processDataMixedEventLc(SelCollisionsWithLc const& collisions, - CandsLcDataFiltered const& candidates, - TracksData const& tracks) - { - - doMixEvent(collisions, tracks, candidates); - } - PROCESS_SWITCH(HfCorrelatorLcScHadrons, processDataMixedEventLc, "Process Mixed Event Data", false); - - void processMcRecMixedEventSc(SelCollisionsWithSc const& collisions, - TracksWithMc const& tracks, - aod::TracksWMc const&, - soa::Join const& candidates, - CandsLcData const&, - aod::McParticles const& mcParticles) - { - doMixEvent(collisions, tracks, candidates, &mcParticles); - } - PROCESS_SWITCH(HfCorrelatorLcScHadrons, processMcRecMixedEventSc, "Process Mixed Event McRec", false); - - void processMcRecMixedEventLc(SelCollisionsWithLc const& collisions, - CandsLcMcRecFiltered const& candidates, - TracksWithMc const& tracks, - aod::McParticles const& mcParticles) + template + void doSameEventMcGen(CollisionType const& mcCollision, PartType const& mcParticles) { - doMixEvent(collisions, tracks, candidates, &mcParticles); - } - PROCESS_SWITCH(HfCorrelatorLcScHadrons, processMcRecMixedEventLc, "Process Mixed Event McRec", false) - /// Lc-Hadron correlation pair builder - for Mc Gen-level analysis - void processMcGen(SelCollisionsWithLcMc::iterator const& mcCollision, - CandidatesLcMcGen const& mcParticles) - { - int counterLcHadron = 0; + int counterCharmCand = 0; registry.fill(HIST("hMcEvtCount"), 0); - BinningTypeMcGen corrBinningMcGen{{binsZVtx, binsMultiplicityMc}, true}; poolBin = corrBinningMcGen.getBin(std::make_tuple(mcCollision.posZ(), mcCollision.multMCFT0A())); registry.fill(HIST("hMultFT0AMcGen"), mcCollision.multMCFT0A()); @@ -928,48 +883,70 @@ struct HfCorrelatorLcScHadrons { if (correlateLcWithLeadingParticle) { leadingIndex = findLeadingParticleMcGen(mcParticles, etaTrackMax.value, ptTrackMin.value); } - // Mc Gen level for (const auto& particle : mcParticles) { - if (std::abs(particle.pdgCode()) != Pdg::kLambdaCPlus) { - continue; - } - if (!TESTBIT(std::abs(particle.flagMcMatchGen()), aod::hf_cand_3prong::DecayType::LcToPKPi)) { + + double massCand = -999.0; + bool isCandFound = isCandSc ? matchCandAndMass(particle, massCand) : matchCandAndMass(particle, massCand); + if (!isCandFound) { continue; } - double yL = RecoDecay::y(particle.pVector(), MassLambdaCPlus); - if (std::abs(yL) > yCandGenMax || particle.pt() < ptCandMin) { + double yCand = RecoDecay::y(particle.pVector(), massCand); + + if (std::abs(yCand) > yCandGenMax || particle.pt() < ptCandMin) { continue; } registry.fill(HIST("hCandBin"), poolBin); registry.fill(HIST("hPtCandMcGen"), particle.pt()); registry.fill(HIST("hEtaMcGen"), particle.eta()); registry.fill(HIST("hPhiMcGen"), RecoDecay::constrainAngle(particle.phi(), -PIHalf)); - registry.fill(HIST("hYMcGen"), yL); + registry.fill(HIST("hYMcGen"), yCand); + + int8_t chargeLc = pdg->GetParticle(particle.pdgCode())->Charge(); // Retrieve charge + if (chargeLc != 0) { + chargeLc = chargeLc / std::abs(chargeLc); + } isPrompt = particle.originMcGen() == RecoDecay::OriginType::Prompt; isNonPrompt = particle.originMcGen() == RecoDecay::OriginType::NonPrompt; if (isPrompt) { registry.fill(HIST("hPtCandMcGenPrompt"), particle.pt()); + registry.fill(HIST("hPtCandVsChargeMcGenPrompt"), particle.pt(), chargeLc); } else if (isNonPrompt) { registry.fill(HIST("hPtCandMcGenNonPrompt"), particle.pt()); + registry.fill(HIST("hPtCandVsChargeMcGenNonPrompt"), particle.pt(), chargeLc); } - // prompt and non-prompt division + static constexpr std::size_t NDaughtersSc{4u}; + static constexpr std::size_t NDaughtersLc{3u}; std::vector listDaughters{}; - std::array arrDaughLcPDG = {kProton, -kKPlus, kPiPlus}; - std::array prongsId; listDaughters.clear(); - RecoDecay::getDaughters(particle, &listDaughters, arrDaughLcPDG, 2); + const std::size_t nDaughtersExpected = isCandSc ? NDaughtersSc : NDaughtersLc; + + if (isCandSc) { + if (massCand == o2::constants::physics::MassSigmaC0 || massCand == o2::constants::physics::MassSigmaCStar0) { + std::array arrDaughSc0PDG = {kProton, -kKPlus, kPiPlus, kPiMinus}; + RecoDecay::getDaughters(particle, &listDaughters, arrDaughSc0PDG, 2); + } else { + std::array arrDaughScPlusPDG = {kProton, -kKPlus, kPiPlus, kPiPlus}; + RecoDecay::getDaughters(particle, &listDaughters, arrDaughScPlusPDG, 2); + } + } else { + std::array arrDaughLcPDG = {kProton, -kKPlus, kPiPlus}; + RecoDecay::getDaughters(particle, &listDaughters, arrDaughLcPDG, 2); + } + int counterDaughters = 0; - if (listDaughters.size() == NDaughters) { + std::vector prongsId(nDaughtersExpected); + if (listDaughters.size() == nDaughtersExpected) { for (const auto& dauIdx : listDaughters) { auto daughI = mcParticles.rawIteratorAt(dauIdx - mcParticles.offset()); counterDaughters += 1; prongsId[counterDaughters - 1] = daughI.globalIndex(); } } - counterLcHadron++; + counterCharmCand++; + // Lc Hadron correlation dedicated section // 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 @@ -977,7 +954,8 @@ struct HfCorrelatorLcScHadrons { if (std::abs(particleAssoc.eta()) > etaTrackMax || particleAssoc.pt() < ptTrackMin || particleAssoc.pt() > ptTrackMax) { continue; } - if (particleAssoc.globalIndex() == prongsId[0] || particleAssoc.globalIndex() == prongsId[1] || particleAssoc.globalIndex() == prongsId[2]) { + + if (std::find(prongsId.begin(), prongsId.end(), particleAssoc.globalIndex()) != prongsId.end()) { if (!storeAutoCorrelationFlag) { continue; } @@ -1001,33 +979,132 @@ struct HfCorrelatorLcScHadrons { } } - int8_t chargeLc = pdg->GetParticle(particle.pdgCode())->Charge(); // Retrieve charge - int8_t chargeAssoc = pdg->GetParticle(particleAssoc.pdgCode())->Charge(); // Retrieve charge - int trackOrigin = RecoDecay::getCharmHadronOrigin(mcParticles, particleAssoc, true); + int8_t chargeAssoc = pdg->GetParticle(particleAssoc.pdgCode())->Charge(); // Retrieve charge + chargeAssoc = chargeAssoc / std::abs(chargeAssoc); registry.fill(HIST("hPtParticleAssocMcGen"), particleAssoc.pt()); entryCandHadronPair(getDeltaPhi(particleAssoc.phi(), particle.phi()), particleAssoc.eta() - particle.eta(), - particle.pt() * chargeLc / std::abs(chargeLc), - particleAssoc.pt() * chargeAssoc / std::abs(chargeAssoc), + particle.pt(), + particleAssoc.pt() * chargeAssoc, poolBin, correlationStatus); - entryCandHadronPairY(particleAssoc.y() - yL); - entryCandHadronRecoInfo(MassLambdaCPlus, true); + entryCandHadronPairY(particleAssoc.y() - yCand); + entryCandHadronRecoInfo(massCand, true); entryCandHadronGenInfo(isPrompt, particleAssoc.isPhysicalPrimary(), trackOrigin); + entryPairCandCharge(chargeLc); } // end inner loop } // end outer loop - registry.fill(HIST("hcountCandHadronPerEvent"), counterLcHadron); + registry.fill(HIST("hcountCandHadronPerEvent"), counterCharmCand); registry.fill(HIST("hZvtx"), mcCollision.posZ()); } - PROCESS_SWITCH(HfCorrelatorLcScHadrons, processMcGen, "Process Mc Gen mode", false); - void processMcGenMixedEvent(SelCollisionsWithLcMc const& collisions, + //} + + /// Lc-hadron correlation pair builder - for real data and data-like analysis (i.e. reco-level w/o matching request via MC truth) + void processDataLc(SelCollisions::iterator const& collision, + TracksData const& tracks, + CandsLcDataFiltered const& candidates, + aod::BCsWithTimestamps const&) + { + doSameEvent(collision, tracks, candidates); + } + PROCESS_SWITCH(HfCorrelatorLcScHadrons, processDataLc, "Process data", true); + + void processDataSc(SelCollisions::iterator const& collision, + TracksData const& tracks, + aod::Tracks const&, + aod::HfCandSc const& candidates, + CandsLcData const&, + aod::BCsWithTimestamps const&) // MUST be last among index-compatible + { + doSameEvent(collision, tracks, candidates); + } + PROCESS_SWITCH(HfCorrelatorLcScHadrons, processDataSc, "Process data Sc", false); + + /// Lc-Hadron correlation process starts for McRec + void processMcRecLc(SelCollisions::iterator const& collision, + TracksWithMc const& tracks, + CandsLcMcRecFiltered const& candidates, + aod::McParticles const& mcParticles) + { + doSameEvent(collision, tracks, candidates, &mcParticles); + } + PROCESS_SWITCH(HfCorrelatorLcScHadrons, processMcRecLc, "Process Mc Reco mode", false); + + /// Lc-Hadron correlation process starts for McRec + void processMcRecSc(SelCollisions::iterator const& collision, + TracksWithMc const& tracks, + aod::TracksWMc const&, + CandsScMcRec const& candidates, + CandsLcData const&, + aod::McParticles const& mcParticles) + { + doSameEvent(collision, tracks, candidates, &mcParticles); + } + PROCESS_SWITCH(HfCorrelatorLcScHadrons, processMcRecSc, "Process Mc Reco mode", false); + + void processDataMixedEventSc(SelCollisions const& collisions, + TracksData const& tracks, + aod::Tracks const&, + aod::HfCandSc const& candidates, + CandsLcData const&) + { + doMixEvent(collisions, tracks, candidates); + } + PROCESS_SWITCH(HfCorrelatorLcScHadrons, processDataMixedEventSc, "Process Mixed Event Data", false); + + void processDataMixedEventLc(SelCollisions const& collisions, + CandsLcDataFiltered const& candidates, + TracksData const& tracks) + { + + doMixEvent(collisions, tracks, candidates); + } + PROCESS_SWITCH(HfCorrelatorLcScHadrons, processDataMixedEventLc, "Process Mixed Event Data", false); + + void processMcRecMixedEventSc(SelCollisions const& collisions, + TracksWithMc const& tracks, + aod::TracksWMc const&, + soa::Join const& candidates, + CandsLcData const&, + aod::McParticles const& mcParticles) + { + doMixEvent(collisions, tracks, candidates, &mcParticles); + } + PROCESS_SWITCH(HfCorrelatorLcScHadrons, processMcRecMixedEventSc, "Process Mixed Event McRec", false); + + void processMcRecMixedEventLc(SelCollisions const& collisions, + CandsLcMcRecFiltered const& candidates, + TracksWithMc const& tracks, + aod::McParticles const& mcParticles) + { + doMixEvent(collisions, tracks, candidates, &mcParticles); + } + PROCESS_SWITCH(HfCorrelatorLcScHadrons, processMcRecMixedEventLc, "Process Mixed Event McRec", false) + + /// Lc-Hadron correlation pair builder - for Mc Gen-level analysis + void processMcGenLc(SelCollisionsMc::iterator const& mcCollision, + CandidatesLcMcGen const& mcParticles) + { + doSameEventMcGen(mcCollision, mcParticles); + } + PROCESS_SWITCH(HfCorrelatorLcScHadrons, processMcGenLc, "Process Mc Gen Lc mode", false); + + void processMcGenSc(SelCollisionsMc::iterator const& mcCollision, + CandidatesScMcGen const& mcParticles) + { + doSameEventMcGen(mcCollision, mcParticles); + } + PROCESS_SWITCH(HfCorrelatorLcScHadrons, processMcGenSc, "Process Mc Gen Sc mode", false); + + void processMcGenMixedEvent(SelCollisionsMc const& collisions, CandidatesLcMcGen const& mcParticles) { BinningTypeMcGen corrBinningMcGen{{binsZVtx, binsMultiplicityMc}, true}; auto tracksTuple = std::make_tuple(mcParticles, mcParticles); - Pair pairMcGen{corrBinningMcGen, numberEventsMixed, -1, collisions, tracksTuple, &cache}; + Pair pairMcGen{corrBinningMcGen, 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))) { diff --git a/PWGHF/HFC/Utils/utilsCorrelations.h b/PWGHF/HFC/Utils/utilsCorrelations.h index 90f7b8524d9..b830eedcfef 100644 --- a/PWGHF/HFC/Utils/utilsCorrelations.h +++ b/PWGHF/HFC/Utils/utilsCorrelations.h @@ -45,12 +45,16 @@ enum PairSign { LcNegTrkNeg }; +constexpr float PhiTowardMax{o2::constants::math::PIThird}; +constexpr float PhiAwayMin{2.f * o2::constants::math::PIThird}; +constexpr float PhiAwayMax{4.f * o2::constants::math::PIThird}; + template Region getRegion(T const deltaPhi) { - if (std::abs(deltaPhi) < o2::constants::math::PIThird) { + if (std::abs(deltaPhi) < PhiTowardMax) { return Toward; - } else if (deltaPhi > 2. * o2::constants::math::PIThird && deltaPhi < 4. * o2::constants::math::PIThird) { + } else if (deltaPhi > PhiAwayMin && deltaPhi < PhiAwayMax) { return Away; } else { return Transverse; @@ -119,6 +123,70 @@ bool passPIDSelection(Atrack const& track, SpeciesContainer const mPIDspecies, return true; // Passed all checks } +/// @brief Selects a candidate based on its PDG code, decay channel, and assigns the corresponding mass. +/// +/// @tparam isScCandidate Boolean template parameter: +/// - `true` to check for Sigma_c candidates +/// - `false` to check for Lambda_c candidates +/// @tparam McParticleType Type representing the MC particle, must provide `pdgCode()` and `flagMcMatchGen()` +/// +/// @param[in] particle MC particle whose PDG code and decay flag are evaluated +/// @param[out] massCand Mass of the matched candidate is set here, if a valid match is found +/// +/// @return `true` if candidate matches expected PDG and decay flag, and mass is set; `false` otherwise +template +bool matchCandAndMass(McParticleType const& particle, double& massCand) +{ + const auto pdgCand = std::abs(particle.pdgCode()); + const auto matchGenFlag = std::abs(particle.flagMcMatchGen()); + + // Validate PDG code based on candidate type + if (isScCandidate) { + if (!(pdgCand == o2::constants::physics::Pdg::kSigmaC0 || + pdgCand == o2::constants::physics::Pdg::kSigmaCPlusPlus || + pdgCand == o2::constants::physics::Pdg::kSigmaCStar0 || + pdgCand == o2::constants::physics::Pdg::kSigmaCStarPlusPlus)) { + return false; + } + } else { + if (pdgCand != o2::constants::physics::Pdg::kLambdaCPlus) { + return false; + } + } + + // Map decay type to mass + switch (matchGenFlag) { + case BIT(aod::hf_cand_sigmac::DecayType::Sc0ToPKPiPi): { + massCand = o2::constants::physics::MassSigmaC0; + return true; + } + + case BIT(aod::hf_cand_sigmac::DecayType::ScStar0ToPKPiPi): { + massCand = o2::constants::physics::MassSigmaCStar0; + return true; + } + + case BIT(aod::hf_cand_sigmac::DecayType::ScplusplusToPKPiPi): { + massCand = o2::constants::physics::MassSigmaCStarPlusPlus; + return true; + } + + case BIT(aod::hf_cand_sigmac::DecayType::ScStarPlusPlusToPKPiPi): { + massCand = o2::constants::physics::MassSigmaCStarPlusPlus; + return true; + } + + case hf_decay::hf_cand_3prong::DecayChannelMain::LcToPKPi: { + massCand = o2::constants::physics::MassLambdaCPlus; + return true; + } + + default: { + return false; + } + } +} + // ========= Find Leading Particle ============== template //// FIXME: 14 days int findLeadingParticle(TTracks const& tracks, T1 const etaTrackMax) From ee36e4d2251fc9edceb1b72c9b3b5da957c1b3d3 Mon Sep 17 00:00:00 2001 From: Mario Ciacco Date: Thu, 26 Jun 2025 19:13:33 +0200 Subject: [PATCH 224/871] [PWGLF] add ntracks to the minicoll table + make trkl eta cuts configurable (#11785) --- PWGLF/DataModel/LFEbyeTables.h | 4 +++- PWGLF/TableProducer/Nuspex/ebyeMaker.cxx | 15 ++++++++------- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/PWGLF/DataModel/LFEbyeTables.h b/PWGLF/DataModel/LFEbyeTables.h index d7ff437ece4..a155697fd9c 100644 --- a/PWGLF/DataModel/LFEbyeTables.h +++ b/PWGLF/DataModel/LFEbyeTables.h @@ -26,6 +26,7 @@ DECLARE_SOA_COLUMN(ZvtxMask, zvtxMask, int8_t); DECLARE_SOA_COLUMN(TriggerMask, triggerMask, uint8_t); DECLARE_SOA_COLUMN(Ntracklets, ntracklets, uint8_t); DECLARE_SOA_COLUMN(V0Multiplicity, v0Multiplicity, uint8_t); +DECLARE_SOA_COLUMN(Ntracks, ntracks, uint8_t); } // namespace LFEbyeCollTable DECLARE_SOA_TABLE(CollEbyeTables, "AOD", "COLLEBYETABLE", @@ -39,7 +40,8 @@ DECLARE_SOA_TABLE(MiniCollTables, "AOD", "MINICOLLTABLE", LFEbyeCollTable::ZvtxMask, LFEbyeCollTable::TriggerMask, LFEbyeCollTable::Ntracklets, - LFEbyeCollTable::V0Multiplicity); + LFEbyeCollTable::V0Multiplicity, + LFEbyeCollTable::Ntracks); using MiniCollTable = MiniCollTables::iterator; namespace LFEbyeTable diff --git a/PWGLF/TableProducer/Nuspex/ebyeMaker.cxx b/PWGLF/TableProducer/Nuspex/ebyeMaker.cxx index ae78ecdb735..36c368a28e0 100644 --- a/PWGLF/TableProducer/Nuspex/ebyeMaker.cxx +++ b/PWGLF/TableProducer/Nuspex/ebyeMaker.cxx @@ -64,6 +64,7 @@ namespace constexpr int kNpart = 2; constexpr float trackSels[12]{/* 60, */ 80, 100, 2, 3, /* 4, */ 0.05, 0.1, /* 0.15, */ 0.5, 1, /* 1.5, */ 2, 3 /* , 4 */, 2, 3, /*, 4 */}; constexpr float dcaSels[3]{10., 10., 10.}; +constexpr float trklSels[3]{1.2, 0.6, 0.7}; constexpr double betheBlochDefault[kNpart][6]{{-1.e32, -1.e32, -1.e32, -1.e32, -1.e32, -1.e32}, {-1.e32, -1.e32, -1.e32, -1.e32, -1.e32, -1.e32}}; constexpr double betheBlochDefaultITS[6]{-1.e32, -1.e32, -1.e32, -1.e32, -1.e32, -1.e32}; constexpr double estimatorsCorrelationCoef[2]{-0.669108, 1.04489}; @@ -76,6 +77,7 @@ static const std::vector particleNamesPar{"p", "d"}; static const std::vector trackSelsNames{"tpcClsMid", "tpcClsTight", "chi2TpcTight", "chi2TpcMid", "dcaxyTight", "dcaxyMid", "dcazTight", "dcazMid", "tpcNsigmaTight", "tpcNsigmaMid", "itsNsigmaTight", "itsNsigmaMid"}; static const std::vector dcaSelsNames{"dcaxy", "dcaz", "dca"}; static const std::vector particleName{"p"}; +static const std::vector trklSelsNames{"etaMaxTot", "etaMaxInner", "etaMinOuter"}; std::array, kNpart> tofMass; void momTotXYZ(std::array& momA, std::array const& momB, std::array const& momC) { @@ -248,7 +250,6 @@ struct EbyeMaker { Configurable etaMaxV0dau{"etaMaxV0dau", 0.8f, "maximum eta V0 daughters"}; Configurable outerPIDMin{"outerPIDMin", -4.f, "minimum outer PID"}; - Configurable storeTracksNum{"storeTracksNum", false, "store the number of tracks instead of tracklets"}; Configurable genName{"genname", "", "Genearator name: HIJING, PYTHIA8, ... Default: \"\""}; Configurable triggerCut{"triggerCut", 0x0, "trigger cut to select"}; @@ -307,6 +308,7 @@ struct EbyeMaker { Configurable antidPtItsClsSizeCut{"antidPtItsClsSizeCut", 10.f, "pt for cluster size cut for antideuterons"}; Configurable> cfgTrackSels{"cfgTrackSels", {trackSels, 1, 12, particleName, trackSelsNames}, "Track selections"}; + Configurable> cfgTrklSels{"cfgTrklSels", {trklSels, 1, 3, particleName, trklSelsNames}, "Tracklet selections (eta)"}; std::array ptMin; std::array ptTof; @@ -673,13 +675,12 @@ struct EbyeMaker { std::array dcaInfo; uint8_t nTracklets[2]{0, 0}; uint8_t nTracks{0}; - const float tklEtaCuts[]{1.2, 0.6, 0.7}; for (const auto& track : tracks) { - if (track.trackType() == o2::aod::track::TrackTypeEnum::Run2Tracklet && std::abs(track.eta()) < tklEtaCuts[0]) { // tracklet - if (std::abs(track.eta()) < tklEtaCuts[1]) + if (track.trackType() == o2::aod::track::TrackTypeEnum::Run2Tracklet && std::abs(track.eta()) < cfgTrklSels->get("etaMaxTot")) { // tracklet + if (std::abs(track.eta()) < cfgTrklSels->get("etaMaxInner")) nTracklets[0]++; - else if (std::abs(track.eta()) > tklEtaCuts[2]) + else if (std::abs(track.eta()) > cfgTrklSels->get("etaMinOuter")) nTracklets[1]++; } @@ -1251,7 +1252,7 @@ struct EbyeMaker { if (triggerCut != 0x0 && (trigger & triggerCut) != triggerCut) { continue; } - miniCollTable(static_cast(collision.posZ() * 10), trigger, storeTracksNum ? nTracksColl : nTrackletsColl, cV0M); + miniCollTable(static_cast(collision.posZ() * 10), trigger, nTrackletsColl, cV0M, nTracksColl); for (auto& candidateTrack : candidateTracks[0]) { // o2-linter: disable=const-ref-in-for-loop (not a const ref) auto tk = tracks.rawIteratorAt(candidateTrack.globalIndex); @@ -1443,7 +1444,7 @@ struct EbyeMaker { fillMcEvent(collision, tracks, v0TableThisCollision, cV0M, mcParticles, mcLab); fillMcGen(mcParticles, mcLab, collision.mcCollisionId()); - miniCollTable(static_cast(collision.posZ() * 10), 0x0, storeTracksNum ? nTracksColl : nTrackletsColl, cV0M); + miniCollTable(static_cast(collision.posZ() * 10), 0x0, nTrackletsColl, cV0M, nTracksColl); for (auto& candidateTrack : candidateTracks[0]) { // o2-linter: disable=const-ref-in-for-loop (not a const ref) int selMask = -1; From 4e4770470ac9ee5f66fbffc967d048b17a0256fe Mon Sep 17 00:00:00 2001 From: sashingo Date: Fri, 27 Jun 2025 03:59:11 +0900 Subject: [PATCH 225/871] [PWGHF] implemented mass reco by KFParticle and changed name of parameters (#11760) --- PWGHF/HFL/Tasks/CMakeLists.txt | 2 +- PWGHF/HFL/Tasks/taskElectronWeakBoson.cxx | 142 ++++++++++++++++++---- 2 files changed, 118 insertions(+), 26 deletions(-) diff --git a/PWGHF/HFL/Tasks/CMakeLists.txt b/PWGHF/HFL/Tasks/CMakeLists.txt index 7c87297ca23..ecf72fbdedd 100644 --- a/PWGHF/HFL/Tasks/CMakeLists.txt +++ b/PWGHF/HFL/Tasks/CMakeLists.txt @@ -11,7 +11,7 @@ o2physics_add_dpl_workflow(task-electron-weak-boson SOURCES taskElectronWeakBoson.cxx - PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::EventFilteringUtils + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::EventFilteringUtils KFParticle::KFParticle COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(task-muon-charm-beauty-separation diff --git a/PWGHF/HFL/Tasks/taskElectronWeakBoson.cxx b/PWGHF/HFL/Tasks/taskElectronWeakBoson.cxx index cbe388235bb..f740814eedb 100644 --- a/PWGHF/HFL/Tasks/taskElectronWeakBoson.cxx +++ b/PWGHF/HFL/Tasks/taskElectronWeakBoson.cxx @@ -12,31 +12,46 @@ /// \file taskElectronWeakBoson.cxx /// \brief task for WeakBoson (W/Z) based on electron in mid-rapidity /// \author S. Sakai & S. Ito (Univ. of Tsukuba) -#include -#include - -#include "CCDB/BasicCCDBManager.h" +#ifndef HomogeneousField +#define HomogeneousField // o2-linter: disable=name/macro (required by KFParticle) +#endif -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/ASoAHelpers.h" +#include "PWGHF/Core/HfHelper.h" +#include "PWGJE/DataModel/EMCALClusters.h" -#include "EMCALBase/Geometry.h" -#include "EMCALCalib/BadChannelMap.h" +#include "Common/Core/RecoDecay.h" +#include "Common/Core/TrackSelection.h" +#include "Common/Core/trackUtilities.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "EventFiltering/Zorro.h" +#include "Tools/KFparticle/KFUtilities.h" +#include "CCDB/BasicCCDBManager.h" +#include "DataFormatsEMCAL/AnalysisCluster.h" #include "DataFormatsEMCAL/Cell.h" #include "DataFormatsEMCAL/Constants.h" -#include "DataFormatsEMCAL/AnalysisCluster.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "DataFormatsParameters/GRPObject.h" +#include "DetectorsBase/GeometryManager.h" +#include "DetectorsBase/Propagator.h" +#include "EMCALBase/Geometry.h" +#include "EMCALCalib/BadChannelMap.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" -#include "Common/Core/RecoDecay.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "Common/DataModel/PIDResponse.h" +#include "TPDGCode.h" -#include "EventFiltering/Zorro.h" +#include "KFPTrack.h" +#include "KFPVertex.h" +#include "KFParticle.h" +#include "KFParticleBase.h" +#include "KFVertex.h" -#include "PWGJE/DataModel/EMCALClusters.h" -#include "PWGHF/Core/HfHelper.h" +#include +#include using namespace o2; using namespace o2::framework; @@ -52,9 +67,9 @@ struct HfTaskElectronWeakBoson { Configurable vtxZ{"vtxZ", 10.f, ""}; - Configurable etaTrLow{"etaTrLow", -1.0f, "minimun track eta"}; - Configurable etaTrUp{"etaTrUp", 1.0f, "maximum track eta"}; - Configurable etaEmcAcc{"etaEmcAcc", 0.6f, "maximum track eta"}; + Configurable etaTrMim{"etaTrMim", -1.0f, "minimun track eta"}; + Configurable etaTrMax{"etaTrMax", 1.0f, "maximum track eta"}; + Configurable etaEmcMax{"etaEmcMax", 0.6f, "maximum track eta"}; Configurable dcaxyMax{"dcaxyMax", 2.0f, "mximum DCA xy"}; Configurable chi2ItsMax{"chi2ItsMax", 15.0f, "its chi2 cut"}; Configurable ptMin{"ptMin", 3.0f, "minimum pT cut"}; @@ -90,8 +105,15 @@ struct HfTaskElectronWeakBoson { Configurable cfgSkimmedProcessing{"cfgSkimmedProcessing", true, "Enables processing of skimmed datasets"}; Configurable cfgTriggerName{"cfgTriggerName", "fGammaHighPtEMCAL", "Trigger of interest (comma separated for multiple)"}; - // CCDB service object + // CCDB service configurations Configurable cfgCCDBPath{"cfgCCDBPath", "Users/m/mpuccio/EventFiltering/OTS/", "Path to CCDB for trigger data"}; + Configurable ccdbPathGrpMag{"ccdbPathGrpMag", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object (Run 3)"}; + + // KFParticle + Configurable kfConstructMethod{"kfConstructMethod", 2, "KF Construct Method"}; + Configurable kfChisqMassMax{"kfChisqMassMax", 10, "Chi2 Max for mass reco by KF particle"}; + + // CCDB service object Service ccdb; struct HfElectronCandidate { @@ -104,10 +126,12 @@ struct HfTaskElectronWeakBoson { }; std::vector selectedElectronsIso; std::vector selectedElectronsAss; + std::vector reconstructedZ; using SelectedClusters = o2::aod::EMCALClusters; // PbPb - using TrackEle = o2::soa::Join; + // using TrackEle = o2::soa::Join; + using TrackEle = o2::soa::Join; // pp // using TrackEle = o2::soa::Filtered>; @@ -116,7 +140,7 @@ struct HfTaskElectronWeakBoson { Filter eventFilter = (o2::aod::evsel::sel8 == true); Filter posZFilter = (nabs(o2::aod::collision::posZ) < vtxZ); - Filter etafilter = (aod::track::eta < etaTrUp) && (aod::track::eta > etaTrLow); + Filter etafilter = (aod::track::eta < etaTrMax) && (aod::track::eta > etaTrMim); Filter dcaxyfilter = (nabs(aod::track::dcaXY) < dcaxyMax); Filter filterGlobalTr = requireGlobalTrackInFilter(); @@ -201,6 +225,8 @@ struct HfTaskElectronWeakBoson { registry.add("hIsolationTrack", "Isolation Track", kTH2F, {{axisE}, {axisIsoTrack}}); registry.add("hInvMassZeeLs", "invariant mass for Z LS pair", kTH2F, {{axisPt}, {axisInvMassZ}}); registry.add("hInvMassZeeUls", "invariant mass for Z ULS pair", kTH2F, {{axisPt}, {axisInvMassZ}}); + registry.add("hKfInvMassZeeLs", "invariant mass for Z LS pair KFp", kTH2F, {{axisPt}, {axisInvMassZ}}); + registry.add("hKfInvMassZeeUls", "invariant mass for Z ULS pair KFp", kTH2F, {{axisPt}, {axisInvMassZ}}); registry.add("hTHnElectrons", "electron info", HistType::kTHnSparseF, {axisPt, axisNsigma, axisM02, axisEop, axisIsoEnergy, axisIsoTrack}); registry.add("hTHnTrMatch", "Track EMC Match", HistType::kTHnSparseF, {axisPt, axisdPhi, axisdEta}); @@ -266,6 +292,56 @@ struct HfTaskElectronWeakBoson { return (trackCount); } + void recoMassZee(KFParticle kfpIsoEle, + int charge, + TrackEle const& tracks) + { + // LOG(info) << "Invarimass cal by KF particle "; + for (const auto& track : tracks) { + + if (track.pt() < ptZeeMin) + continue; + if (std::abs(track.tpcNSigmaEl()) > nsigTpcMax) + continue; + if (std::abs(track.eta()) > etaTrMax) + continue; + + int pdgAss = kElectron; + if (track.sign() > 0) { + pdgAss = kPositron; + } + + KFPTrack kfpTrackAssEle = createKFPTrackFromTrack(track); + KFParticle kfpAssEle(kfpTrackAssEle, pdgAss); + const KFParticle* electronPairs[2] = {&kfpIsoEle, &kfpAssEle}; + KFParticle zeeKF; + zeeKF.SetConstructMethod(kfConstructMethod); + zeeKF.Construct(electronPairs, 2); + // LOG(info) << "Invarimass cal by KF particle Chi2/NDF = " << zeeKF.GetChi2()/zeeKF.GetNDF(); + float massZeeChi2 = zeeKF.GetChi2() / zeeKF.GetNDF(); + if (zeeKF.GetNDF() < 1) + continue; + if (std::abs(massZeeChi2) > kfChisqMassMax) + continue; + float massZee, massZeeErr; + zeeKF.GetMass(massZee, massZeeErr); + // LOG(info) << "Invarimass cal by KF particle mass = " << massZee; + + if (track.sign() * charge > 0) { + registry.fill(HIST("hKfInvMassZeeLs"), kfpIsoEle.GetPt(), massZee); + } else { + registry.fill(HIST("hKfInvMassZeeUls"), kfpIsoEle.GetPt(), massZee); + } + + reconstructedZ.emplace_back( + zeeKF.GetPt(), + zeeKF.GetEta(), + zeeKF.GetPhi(), + massZee, + track.sign() * charge); + } + } + void process(soa::Filtered::iterator const& collision, aod::BCsWithTimestamps const&, SelectedClusters const& emcClusters, @@ -294,6 +370,14 @@ struct HfTaskElectronWeakBoson { zorro.initCCDB(ccdb.service, runNumber, currentTimestamp, cfgTriggerName); isFirstEvent = false; lastRunNumber = runNumber; + + // initialize magnetic field + o2::parameters::GRPMagField* grpo = ccdb->getForTimeStamp(ccdbPathGrpMag, currentTimestamp); + o2::base::Propagator::initFieldFromGRP(grpo); + double magneticField = o2::base::Propagator::Instance()->getNominalBz(); + LOG(info) << "magneticField = " << magneticField; + if (magneticField) + KFParticle::SetField(magneticField); } // Check if this is a triggered event using Zorro @@ -310,6 +394,7 @@ struct HfTaskElectronWeakBoson { // initialze for inclusive-electron selectedElectronsIso.clear(); selectedElectronsAss.clear(); + reconstructedZ.clear(); registry.fill(HIST("hEventCounter"), 0.5); @@ -321,7 +406,7 @@ struct HfTaskElectronWeakBoson { for (const auto& track : tracks) { - if (std::abs(track.eta()) > etaTrUp) + if (std::abs(track.eta()) > etaTrMax) continue; if (track.tpcNClsCrossedRows() < nclcrossTpcMin) continue; @@ -363,7 +448,7 @@ struct HfTaskElectronWeakBoson { // continue; if (track.phi() < phiEmcMin || track.phi() > phiEmcMax) continue; - if (std::abs(track.eta()) > etaEmcAcc) + if (std::abs(track.eta()) > etaEmcMax) continue; auto tracksofcluster = matchedtracks.sliceBy(perClusterMatchedTracks, track.globalIndex()); @@ -441,6 +526,13 @@ struct HfTaskElectronWeakBoson { registry.fill(HIST("hEopIsolation"), match.track_as().pt(), eop); if (match.track_as().pt() > ptZeeMin) { + int pdgIso = kElectron; + if (match.track_as().sign() > 0) { + pdgIso = kPositron; + } + KFPTrack kfpTrackIsoEle = createKFPTrackFromTrack(match.track_as()); + KFParticle kfpIsoEle(kfpTrackIsoEle, pdgIso); + recoMassZee(kfpIsoEle, match.track_as().sign(), tracks); selectedElectronsIso.emplace_back( match.track_as().pt(), From be2946c926df96229f4cd41b31ec6e1cd1759240 Mon Sep 17 00:00:00 2001 From: skundu692 <86804743+skundu692@users.noreply.github.com> Date: Fri, 27 Jun 2025 00:45:37 +0200 Subject: [PATCH 226/871] [PWGLF] Add new analysis task for lambda spin correlation study using derived data (#11783) --- PWGLF/Tasks/Strangeness/CMakeLists.txt | 5 + .../Strangeness/lambdaspincorrderived.cxx | 321 ++++++++++++++++++ 2 files changed, 326 insertions(+) create mode 100644 PWGLF/Tasks/Strangeness/lambdaspincorrderived.cxx diff --git a/PWGLF/Tasks/Strangeness/CMakeLists.txt b/PWGLF/Tasks/Strangeness/CMakeLists.txt index 569768bd273..a6bc1f60334 100644 --- a/PWGLF/Tasks/Strangeness/CMakeLists.txt +++ b/PWGLF/Tasks/Strangeness/CMakeLists.txt @@ -145,3 +145,8 @@ o2physics_add_dpl_workflow(lambdajetpolarization SOURCES lambdaJetpolarization.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGJECore FastJet::FastJet FastJet::Contrib O2Physics::EventFilteringUtils COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(lambdaspincorrderived + SOURCES lambdaspincorrderived.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) diff --git a/PWGLF/Tasks/Strangeness/lambdaspincorrderived.cxx b/PWGLF/Tasks/Strangeness/lambdaspincorrderived.cxx new file mode 100644 index 00000000000..0dd9b2ac542 --- /dev/null +++ b/PWGLF/Tasks/Strangeness/lambdaspincorrderived.cxx @@ -0,0 +1,321 @@ +// 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 taskLambdaSpinCorr.cxx +/// \brief Analysis task for Lambda spin spin correlation +/// +/// \author sourav.kundu@cern.ch + +#include "PWGLF/DataModel/LFSpincorrelationTables.h" + +#include "Common/Core/trackUtilities.h" + +#include "CommonConstants/PhysicsConstants.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/StepTHn.h" +#include "Framework/runDataProcessing.h" +#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::soa; + +struct lambdaspincorrderived { + // event sel///////// + Configurable centMin{"centMin", 0, "Minimum Centrality"}; + Configurable centMax{"centMax", 80, "Maximum Centrality"}; + + // Lambda selection //////////// + Configurable usePDGM{"usePDGM", 1, "Use PDG mass"}; + Configurable checkDoubleStatus{"checkDoubleStatus", 0, "Check Double status"}; + Configurable cosPA{"cosPA", 0.995, "Cosine Pointing Angle"}; + Configurable radiusMin{"radiusMin", 3, "Minimum V0 radius"}; + Configurable radiusMax{"radiusMax", 30, "Maximum V0 radius"}; + Configurable dcaProton{"dcaProton", 0.1, "DCA Proton"}; + Configurable dcaPion{"dcaPion", 0.2, "DCA Pion"}; + Configurable dcaDaughters{"dcaDaughters", 1.0, "DCA between daughters"}; + Configurable ptMin{"ptMin", 0.5, "V0 Pt minimum"}; + Configurable ptMax{"ptMax", 3.0, "V0 Pt maximum"}; + Configurable rapidity{"rapidity", 0.5, "Rapidity cut on lambda"}; + + // Event Mixing + Configurable nEvtMixing{"nEvtMixing", 10, "Number of events to mix"}; + ConfigurableAxis CfgVtxBins{"CfgVtxBins", {10, -10, 10}, "Mixing bins - z-vertex"}; + ConfigurableAxis CfgMultBins{"CfgMultBins", {8, 0.0, 80}, "Mixing bins - centrality"}; + Configurable etaMix{"etaMix", 0.1, "Eta cut on event mixing"}; + Configurable ptMix{"ptMix", 0.1, "Pt cut on event mixing"}; + Configurable phiMix{"phiMix", 0.1, "Phi cut on event mixing"}; + Configurable massMix{"massMix", 0.0028, "Masscut on event mixing"}; + + // THnsparse bining + ConfigurableAxis configThnAxisInvMass{"configThnAxisInvMass", {50, 1.09, 1.14}, "#it{M} (GeV/#it{c}^{2})"}; + ConfigurableAxis configThnAxisR{"configThnAxisR", {80, 0.0, 8.0}, "#it{R}"}; + ConfigurableAxis configThnAxisPol{"configThnAxisPol", {80, 0.0, 8.0}, "cos#it{#theta *}"}; + ConfigurableAxis configThnAxisCentrality{"configThnAxisCentrality", {8, 0.0, 80.0}, "Centrality"}; + HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + + void init(o2::framework::InitContext&) + { + histos.add("hCentrality", "Centrality distribution", kTH1F, {{configThnAxisCentrality}}); + + histos.add("hSparseLambdaLambda", "hSparseLambdaLambda", HistType::kTHnSparseF, {configThnAxisInvMass, configThnAxisInvMass, configThnAxisPol, configThnAxisCentrality, configThnAxisR}, true); + histos.add("hSparseLambdaAntiLambda", "hSparseLambdaAntiLambda", HistType::kTHnSparseF, {configThnAxisInvMass, configThnAxisInvMass, configThnAxisPol, configThnAxisCentrality, configThnAxisR}, true); + histos.add("hSparseAntiLambdaAntiLambda", "hSparseAntiLambdaAntiLambda", HistType::kTHnSparseF, {configThnAxisInvMass, configThnAxisInvMass, configThnAxisPol, configThnAxisCentrality, configThnAxisR}, true); + + histos.add("hSparseLambdaLambdaMixed", "hSparseLambdaLambdaMixed", HistType::kTHnSparseF, {configThnAxisInvMass, configThnAxisInvMass, configThnAxisPol, configThnAxisCentrality, configThnAxisR}, true); + histos.add("hSparseLambdaAntiLambdaMixed", "hSparseLambdaAntiLambdaMixed", HistType::kTHnSparseF, {configThnAxisInvMass, configThnAxisInvMass, configThnAxisPol, configThnAxisCentrality, configThnAxisR}, true); + histos.add("hSparseAntiLambdaAntiLambdaMixed", "hSparseAntiLambdaAntiLambdaMixed", HistType::kTHnSparseF, {configThnAxisInvMass, configThnAxisInvMass, configThnAxisPol, configThnAxisCentrality, configThnAxisR}, true); + } + + template + bool selectionV0(T const& candidate) + { + if (candidate.v0Cospa() < cosPA) { + return false; + } + if (checkDoubleStatus && candidate.doubleStatus()) { + return false; + } + if (candidate.v0Radius() > radiusMax) { + return false; + } + if (candidate.v0Radius() < radiusMin) { + return false; + } + if (candidate.dcaBetweenDaughter() > dcaDaughters) { + return false; + } + if (candidate.v0Status() == 0 && std::abs(candidate.dcaPositive()) < dcaProton && std::abs(candidate.dcaNegative()) < dcaPion) { + return false; + } + if (candidate.v0Status() == 1 && std::abs(candidate.dcaPositive()) < dcaPion && std::abs(candidate.dcaNegative()) < dcaProton) { + return false; + } + if (candidate.lambdaPt() < ptMin) { + return false; + } + if (candidate.lambdaPt() > ptMax) { + return false; + } + return true; + } + + template + bool checkKinematics(T1 const& candidate1, T2 const& candidate2) + { + if (std::abs(candidate1.lambdaPt() - candidate2.lambdaPt()) > ptMix) { + return false; + } + if (std::abs(candidate1.lambdaEta() - candidate2.lambdaEta()) > etaMix) { + return false; + } + if (std::abs(candidate1.lambdaPhi() - candidate2.lambdaPhi()) > phiMix) { + return false; + } + if (std::abs(candidate1.lambdaMass() - candidate2.lambdaMass()) > massMix) { + return false; + } + return true; + } + + void fillHistograms(int tag1, int tag2, + const ROOT::Math::PtEtaPhiMVector& particle1, const ROOT::Math::PtEtaPhiMVector& particle2, + const ROOT::Math::PtEtaPhiMVector& daughpart1, const ROOT::Math::PtEtaPhiMVector& daughpart2, + double centrality, int datatype) + { + auto lambda1Mass = 0.0; + auto lambda2Mass = 0.0; + if (!usePDGM) { + lambda1Mass = particle1.M(); + lambda2Mass = particle2.M(); + } else { + lambda1Mass = o2::constants::physics::MassLambda; + lambda2Mass = o2::constants::physics::MassLambda; + } + auto particle1Dummy = ROOT::Math::PtEtaPhiMVector(particle1.Pt(), particle1.Eta(), particle1.Phi(), lambda1Mass); + auto particle2Dummy = ROOT::Math::PtEtaPhiMVector(particle2.Pt(), particle2.Eta(), particle2.Phi(), lambda2Mass); + auto pairDummy = particle1Dummy + particle2Dummy; + ROOT::Math::Boost boostPairToCM{pairDummy.BoostToCM()}; // boosting vector for pair CM + + // Step1: Boosting both Lambdas to Lambda-Lambda pair rest frame + auto lambda1CM = boostPairToCM(particle1Dummy); + auto lambda2CM = boostPairToCM(particle2Dummy); + + // Step 2: Boost Each Lambda to its Own Rest Frame + ROOT::Math::Boost boostLambda1ToCM{lambda1CM.BoostToCM()}; + ROOT::Math::Boost boostLambda2ToCM{lambda2CM.BoostToCM()}; + + // Also boost the daughter protons to the same frame + auto proton1pairCM = boostPairToCM(daughpart1); // proton1 to pair CM + auto proton2pairCM = boostPairToCM(daughpart2); // proton2 to pair CM + + // Boost protons into their respective Lambda rest frames + auto proton1LambdaRF = boostLambda1ToCM(proton1pairCM); + auto proton2LambdaRF = boostLambda2ToCM(proton2pairCM); + + auto cosThetaDiff = -999.0; + cosThetaDiff = proton1LambdaRF.Vect().Unit().Dot(proton2LambdaRF.Vect().Unit()); + double deltaPhi = RecoDecay::constrainAngle(particle1Dummy.Phi() - particle2Dummy.Phi(), 0.0F, 2U); + double deltaEta = particle1Dummy.Eta() - particle2Dummy.Eta(); + double deltaR = TMath::Sqrt(deltaEta * deltaEta + deltaPhi * deltaPhi); + + if (datatype == 0) { + if (tag1 == 0 && tag2 == 0) { + histos.fill(HIST("hSparseLambdaLambda"), particle1.M(), particle2.M(), cosThetaDiff, centrality, deltaR); + } else if ((tag1 == 0 && tag2 == 1) || (tag1 == 1 && tag2 == 0)) { + histos.fill(HIST("hSparseLambdaAntiLambda"), particle1.M(), particle2.M(), cosThetaDiff, centrality, deltaR); + } else if (tag1 == 1 && tag2 == 1) { + histos.fill(HIST("hSparseAntiLambdaAntiLambda"), particle1.M(), particle2.M(), cosThetaDiff, centrality, deltaR); + } + } else if (datatype == 1) { + if (tag1 == 0 && tag2 == 0) { + histos.fill(HIST("hSparseLambdaLambdaMixed"), particle1.M(), particle2.M(), cosThetaDiff, centrality, deltaR); + } else if ((tag1 == 0 && tag2 == 1) || (tag1 == 1 && tag2 == 0)) { + histos.fill(HIST("hSparseLambdaAntiLambdaMixed"), particle1.M(), particle2.M(), cosThetaDiff, centrality, deltaR); + } else if (tag1 == 1 && tag2 == 1) { + histos.fill(HIST("hSparseAntiLambdaAntiLambdaMixed"), particle1.M(), particle2.M(), cosThetaDiff, centrality, deltaR); + } + } + } + + ROOT::Math::PtEtaPhiMVector lambda0, proton0; + ROOT::Math::PtEtaPhiMVector lambda, proton; + ROOT::Math::PtEtaPhiMVector lambda2, proton2; + + Filter centralityFilter = (nabs(aod::lambdaevent::cent) < centMax && nabs(aod::lambdaevent::cent) > centMin); + + using EventCandidates = soa::Filtered; + using AllTrackCandidates = aod::LambdaPairs; + + void processData(EventCandidates::iterator const& collision, AllTrackCandidates const& V0s) + { + auto centrality = collision.cent(); + for (const auto& v0 : V0s) { + if (!selectionV0(v0)) { + continue; + } + proton = ROOT::Math::PtEtaPhiMVector(v0.protonPt(), v0.protonEta(), v0.protonPhi(), o2::constants::physics::MassProton); + lambda = ROOT::Math::PtEtaPhiMVector(v0.lambdaPt(), v0.lambdaEta(), v0.lambdaPhi(), v0.lambdaMass()); + for (const auto& v02 : V0s) { + if (v02.index() <= v0.index()) { + continue; + } + if (!selectionV0(v02)) { + continue; + } + if (v0.protonIndex() == v02.protonIndex()) { + continue; + } + if (v0.pionIndex() == v02.pionIndex()) { + continue; + } + proton2 = ROOT::Math::PtEtaPhiMVector(v02.protonPt(), v02.protonEta(), v02.protonPhi(), o2::constants::physics::MassProton); + lambda2 = ROOT::Math::PtEtaPhiMVector(v02.lambdaPt(), v02.lambdaEta(), v02.lambdaPhi(), v02.lambdaMass()); + if (v0.v0Status() == 0 && v02.v0Status() == 0) { + fillHistograms(0, 0, lambda, lambda2, proton, proton2, centrality, 0); + } + if (v0.v0Status() == 0 && v02.v0Status() == 1) { + fillHistograms(0, 1, lambda, lambda2, proton, proton2, centrality, 0); + } + if (v0.v0Status() == 1 && v02.v0Status() == 0) { + fillHistograms(1, 0, lambda2, lambda, proton2, proton, centrality, 0); + } + if (v0.v0Status() == 1 && v02.v0Status() == 1) { + fillHistograms(1, 1, lambda, lambda2, proton, proton2, centrality, 0); + } + } + } + } + PROCESS_SWITCH(lambdaspincorrderived, processData, "Process data", true); + + // Processing Event Mixing + SliceCache cache; + using BinningType = ColumnBinningPolicy; + BinningType colBinning{{CfgVtxBins, CfgMultBins}, true}; + Preslice tracksPerCollisionV0 = aod::lambdapair::lambdaeventId; + void processME(EventCandidates const& collisions, AllTrackCandidates const& V0s) + { + for (auto& [collision1, collision2] : selfCombinations(colBinning, nEvtMixing, -1, collisions, collisions)) { + // LOGF(info, "Mixed event collisions: (%d, %d)", collision1.index(), collision2.index()); + auto centrality = collision1.cent(); + auto groupV01 = V0s.sliceBy(tracksPerCollisionV0, collision1.globalIndex()); + auto groupV02 = V0s.sliceBy(tracksPerCollisionV0, collision1.globalIndex()); + auto groupV03 = V0s.sliceBy(tracksPerCollisionV0, collision2.globalIndex()); + std::vector t1Used(groupV01.size(), false); // <-- reset here + for (auto& [t1, t3] : soa::combinations(o2::soa::CombinationsFullIndexPolicy(groupV01, groupV03))) { + if (t1Used[t1.index()]) { + continue; + } + if (!checkKinematics(t1, t3)) { + continue; + } + if (!selectionV0(t1)) { + continue; + } + if (!selectionV0(t3)) { + continue; + } + t1Used[t1.index()] = true; + for (const auto& t2 : groupV02) { + if (t2.index() <= t1.index()) { + continue; + } + if (!selectionV0(t2)) { + continue; + } + if (t1.protonIndex() == t2.protonIndex()) { + continue; + } + if (t1.pionIndex() == t2.pionIndex()) { + continue; + } + proton = ROOT::Math::PtEtaPhiMVector(t3.protonPt(), t3.protonEta(), t3.protonPhi(), o2::constants::physics::MassProton); + lambda = ROOT::Math::PtEtaPhiMVector(t3.lambdaPt(), t3.lambdaEta(), t3.lambdaPhi(), t3.lambdaMass()); + proton2 = ROOT::Math::PtEtaPhiMVector(t2.protonPt(), t2.protonEta(), t2.protonPhi(), o2::constants::physics::MassProton); + lambda2 = ROOT::Math::PtEtaPhiMVector(t2.lambdaPt(), t2.lambdaEta(), t2.lambdaPhi(), t2.lambdaMass()); + if (t3.v0Status() == 0 && t2.v0Status() == 0) { + fillHistograms(0, 0, lambda, lambda2, proton, proton2, centrality, 1); + } + if (t3.v0Status() == 0 && t2.v0Status() == 1) { + fillHistograms(0, 1, lambda, lambda2, proton, proton2, centrality, 1); + } + if (t3.v0Status() == 1 && t2.v0Status() == 0) { + fillHistograms(1, 0, lambda2, lambda, proton2, proton, centrality, 1); + } + if (t3.v0Status() == 1 && t2.v0Status() == 1) { + fillHistograms(1, 1, lambda, lambda2, proton, proton2, centrality, 1); + } + } + } // replacement track pair + } // collision pair + } + PROCESS_SWITCH(lambdaspincorrderived, processME, "Process data ME", true); +}; +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} From 6faba4c5febc2db0b856fc128c85c820dba18855 Mon Sep 17 00:00:00 2001 From: Anantha Padmanabhan M Nair <82643666+ananthapadmanabhan18@users.noreply.github.com> Date: Fri, 27 Jun 2025 05:46:38 +0530 Subject: [PATCH 227/871] [PWGUD] Added different processes for pass4 and pass5 (#11766) --- PWGUD/Tasks/exclusiveRhoTo4Pi.cxx | 218 ++++++++++++++++++++---------- 1 file changed, 144 insertions(+), 74 deletions(-) diff --git a/PWGUD/Tasks/exclusiveRhoTo4Pi.cxx b/PWGUD/Tasks/exclusiveRhoTo4Pi.cxx index 2c82c90a38b..153eb19907e 100644 --- a/PWGUD/Tasks/exclusiveRhoTo4Pi.cxx +++ b/PWGUD/Tasks/exclusiveRhoTo4Pi.cxx @@ -565,62 +565,98 @@ struct ExclusiveRhoTo4Pi { void init(InitContext const&) { + // QA plots: event selection + histosData.add("FT0A", "T0A amplitude", kTH1F, {{2000, 0.0, 500.0}}); + histosData.add("FT0C", "T0C amplitude", kTH1F, {{2000, 0.0, 500.0}}); + histosData.add("ZDC_A", "ZDC amplitude", kTH1F, {{1000, 0.0, 15}}); + histosData.add("ZDC_C", "ZDC amplitude", kTH1F, {{1000, 0.0, 15}}); + histosData.add("V0A", "V0A amplitude", kTH1F, {{1000, 0.0, 100}}); + + // QA plots: tracks histosData.add("GapSide", "Gap Side; Events", kTH1F, {{4, -1.5, 2.5}}); histosData.add("TrueGapSide", "Gap Side; Events", kTH1F, {{4, -1.5, 2.5}}); - histosData.add("EventCounts", "Total Events; Events", kTH1F, {{10, 0, 10}}); + histosData.add("EventsCounts_vs_runNo", "Number of Selected 4-Pion Events per Run; Run Number; Number of Events", kTH2F, {{1355, 544013, 545367}, {10, 0, 10}}); + histosData.add("vertexX", "Vertex X; Vertex X [cm]; Counts", kTH1F, {{2000, -0.05, 0.05}}); + histosData.add("vertexY", "Vertex Y; Vertex Y [cm]; Counts", kTH1F, {{2000, -0.05, 0.05}}); histosData.add("vertexZ", "Vertex Z; Vertex Z [cm]; Counts", kTH1F, {{2000, -15, 15}}); histosData.add("occupancy", "Occupancy; Occupancy; Counts", kTH1F, {{20000, 0, 20000}}); - histosData.add("dcaXY", "dcaXY; dcaXY [cm]; Counts", kTH1F, {{5000, -0.5, 0.5}}); - histosData.add("dcaZ", "dcaZ; dcaZ [cm]; Counts", kTH1F, {{5000, -0.5, 0.5}}); + histosData.add("dcaXY", "dcaXY; dcaXY [cm]; Counts", kTH1F, {{5000, -1, 1}}); + histosData.add("dcaXY_pions", "dcaXY_pions; dcaXY of Pions [cm]; Counts", kTH1F, {{5000, -1, 1}}); + histosData.add("dcaZ", "dcaZ; dcaZ [cm]; Counts", kTH1F, {{5000, -1, 1}}); + histosData.add("dcaZ_pions", "dcaZ_pions; dcaZ of Pions [cm]; Counts", kTH1F, {{5000, -1, 1}}); histosData.add("tpcChi2NCl", "TPC Chi2/NCl; Chi2/NCl; Counts", kTH1F, {{250, 0, 50}}); histosData.add("itsChi2NCl", "ITS Chi2/NCl; Chi2/NCl; Counts", kTH1F, {{250, 0, 50}}); histosData.add("tpcNClsFindable", "TPC N Cls Findable; N Cls Findable; Counts", kTH1F, {{200, 0, 200}}); - // TPC nSigma + // QA plots: PID + histosData.add("tpcSignal", "TPC dEdx vs p; p [GeV/c]; dEdx [a.u.]", kTH2F, {{500, 0, 10}, {5000, 0.0, 5000.0}}); + histosData.add("tpcSignal_pions", "TPC dEdx vs p for pions; p [GeV/c]; dEdx [a.u.]", kTH2F, {{500, 0, 10}, {5000, 0.0, 5000.0}}); histosData.add("tpcNSigmaPi_all", "TPC nSigma Pion with track selection; Events", kTH2F, {{1000, -15, 15}, {1000, 0, 10}}); histosData.add("tpcNSigmaPi_pions", "TPC nSigma Pion with track selection and PID Selection of Pi; Entries", kTH2F, {{1000, -15, 15}, {1000, 0, 10}}); - - // TPC nSigma of other particles with selected pion tracks histosData.add("tpcNSigmaKa_pions", "TPC nSigma Kaon with track selection and PID Selection of Pion; Entries", kTH2F, {{1000, -15, 15}, {1000, 0, 10}}); histosData.add("tpcNSigmaPr_pions", "TPC nSigma Proton with track selection and PID Selection of Pion; Entries", kTH2F, {{1000, -15, 15}, {1000, 0, 10}}); histosData.add("tpcNSigmaEl_pions", "TPC nSigma Electron with track selection and PID Selection of Pion; Entries", kTH2F, {{1000, -15, 15}, {1000, 0, 10}}); histosData.add("tpcNSigmaMu_pions", "TPC nSigma Muon with track selection and PID Selection of Pion; Entries", kTH2F, {{1000, -15, 15}, {1000, 0, 10}}); - - // TOF nSigma + histosData.add("tofBeta", "TOF beta vs p; p [GeV/c]; #beta", kTH2F, {{500, 0, 10}, {500, 0.0, 1.0}}); + histosData.add("tofBeta_pions", "TOF beta vs p for pions; p [GeV/c]; #beta", kTH2F, {{500, 0, 10}, {500, 0.0, 1.0}}); histosData.add("tofNSigmaPi_all", "TOF nSigma Pion with track selection; Events", kTH2F, {{1000, -15, 15}, {1000, 0, 10}}); histosData.add("tofNSigmaPi_pions", "TOF nSigma Pion with track selection and PID Selection of Pi; Entries", kTH2F, {{1000, -15, 15}, {1000, 0, 10}}); - - // TOF nSigma of other particles with selected pion tracks histosData.add("tofNSigmaKa_pions", "TOF nSigma Kaon with track selection and PID Selection of Pion; Entries", kTH2F, {{1000, -15, 15}, {1000, 0, 10}}); histosData.add("tofNSigmaPr_pions", "TOF nSigma Proton with track selection and PID Selection of Pion; Entries", kTH2F, {{1000, -15, 15}, {1000, 0, 10}}); histosData.add("tofNSigmaEl_pions", "TOF nSigma Electron with track selection and PID Selection of Pion; Entries", kTH2F, {{1000, -15, 15}, {1000, 0, 10}}); histosData.add("tofNSigmaMu_pions", "TOF nSigma Muon with track selection and PID Selection of Pion; Entries", kTH2F, {{1000, -15, 15}, {1000, 0, 10}}); + // QA averages + histosData.add("avg_pT_pi_vs_runNo", "Average pion p_{T} vs run number; Run Number; p_{T} [GeV/c]", kTH2F, {{1355, 544013, 545367}, {1000, -0.1, 2}}); + histosData.add("avg_eta_pi_vs_runNo", "Average pion #eta vs run number; Run Number; #eta", kTH2F, {{1355, 544013, 545367}, {1000, -1.1, 1.1}}); + histosData.add("avg_phi_pi_vs_runNo", "Average pion #phi vs run number; Run Number; #phi [rad]", kTH2F, {{1355, 544013, 545367}, {1000, -1 * o2::constants::math::PI, o2::constants::math::PI}}); + histosData.add("avg_dcaxy_vs_runNo", "Average pion DCA XY vs run number; Run Number; DCA XY [cm]", kTH2F, {{1355, 544013, 545367}, {1000, -0.2, 0.2}}); + histosData.add("avg_dcaz_vs_runNo", "Average pion DCA Z vs run number; Run Number; DCA Z [cm]", kTH2F, {{1355, 544013, 545367}, {1000, -0.2, 0.2}}); + histosData.add("avg_pT_pi_vs_runNo_selected4piEvents", "Average pion p_{T} vs run number; Run Number; p_{T} [GeV/c]", kTH2F, {{1355, 544013, 545367}, {1000, -0.1, 2}}); + histosData.add("avg_eta_pi_vs_runNo_selected4piEvents", "Average pion #eta vs run number; Run Number; #eta", kTH2F, {{1355, 544013, 545367}, {1000, -1.1, 1.1}}); + histosData.add("avg_phi_pi_vs_runNo_selected4piEvents", "Average pion #phi vs run number; Run Number; #phi [rad]", kTH2F, {{1355, 544013, 545367}, {1000, -1 * o2::constants::math::PI, o2::constants::math::PI}}); + histosData.add("avg_dcaxy_vs_runNo_selected4piEvents", "Average pion DCA XY vs run number; Run Number; DCA XY [cm]", kTH2F, {{1355, 544013, 545367}, {1000, -0.2, 0.2}}); + histosData.add("avg_dcaz_vs_runNo_selected4piEvents", "Average pion DCA Z vs run number; Run Number; DCA Z [cm]", kTH2F, {{1355, 544013, 545367}, {1000, -0.2, 0.2}}); + // Track Transverse Momentum histosData.add("pT_track_all", "pT with track selection; pT [GeV/c]; Counts", kTH1F, {pTAxis}); histosData.add("pT_track_pions", "pT with track selection and PID selection of Pi; pT [GeV/c]; Events", kTH1F, {pTAxis}); histosData.add("pT_track_pions_contributed", "pT with track selection and PID selection of Pi which are contributed to selected event; pT [GeV/c]; Events", kTH1F, {pTAxis}); + // Track Pseudorapidity + histosData.add("eta_track_all", "Pseudorapidity with track selection; #eta; Counts", kTH1F, {{1000, -1.1, 1.1}}); + histosData.add("eta_track_pions", "Pseudorapidity with track selection and PID selection of Pi; #eta; Events", kTH1F, {{1000, -1.1, 1.1}}); + histosData.add("eta_track_pions_contributed", "Pseudorapidity with track selection and PID selection of Pi which are contributed to selected event; #eta; Events", kTH1F, {{1000, -1.1, 1.1}}); + + // Track Phi + histosData.add("phi_track_all", "Phi with track selection; #phi [rad]; Counts", kTH1F, {phiAxis}); + histosData.add("phi_track_pions", "Phi with track selection and PID selection of Pi; #phi [rad]; Events", kTH1F, {phiAxis}); + histosData.add("phi_track_pions_contributed", "Phi with track selection and PID selection of Pi which are contributed to selected event; #phi [rad]; Events", kTH1F, {phiAxis}); + // Track Rapidity histosData.add("rapidity_track_all", "Rapidity with track selection; y; Counts", kTH1F, {rapidityAxis}); histosData.add("rapidity_track_pions", "Rapidity with track selection and PID selection of Pi; y; Events", kTH1F, {rapidityAxis}); histosData.add("rapidity_track_pions_contributed", "Rapidity with track selection and PID selection of Pi which are contributed to selected event; y; Events", kTH1F, {rapidityAxis}); - // Zero charge Event Transverse Momentum + // Four Pion Transverse Momentum histosData.add("fourpion_pT_0_charge", "Event pT in 0 Charge Events With Track Selection and PID Selection of Pi; pT [GeV/c]; Events", kTH1F, {pTAxis}); - - // Non Zero charge Event Transverse Momentum histosData.add("fourpion_pT_non_0_charge", "Event pT in Non 0 Charge Events With Track Selection and PID Selection of Pi; pT [GeV/c]; Events", kTH1F, {pTAxis}); - // Rapidity of 0 charge Events - histosData.add("fourpion_rap_0_charge_domA", "Rapidity of Events With Track Selection and PID Selection of Pi for p_{T} < 0.15 GeV/c; y; Events", kTH1F, {{1000, -2.5, 2.5}}); - histosData.add("fourpion_rap_0_charge_domB", "Rapidity of Events With Track Selection and PID Selection of Pi for 0.15< p_{T} < 0.80 GeV/c; y; Events", kTH1F, {{1000, -2.5, 2.5}}); - histosData.add("fourpion_rap_0_charge_domC", "Rapidity of Events With Track Selection and PID Selection of Pi for p_{T} > 0.80 GeV/c; y; Events", kTH1F, {{1000, -2.5, 2.5}}); + // Four Pion Eta + histosData.add("fourpion_eta_0_charge", "Four Pion #eta (0 charge); #eta; Events", kTH1F, {{1000, -1.1, 1.1}}); + histosData.add("fourpion_eta_non_0_charge", "Four Pion #eta (non 0 charge); #eta; #eta; Events", kTH1F, {{1000, -1.1, 1.1}}); - // Rapidity of non 0 charge Events - histosData.add("fourpion_rap_non_0_charge_domA", "Rapidity of Events With Track Selection and PID Selection of Pi for p_{T} < 0.15 GeV/c; y; Events", kTH1F, {rapidityAxis}); - histosData.add("fourpion_rap_non_0_charge_domB", "Rapidity of Events With Track Selection and PID Selection of Pi for 0.15< p_{T} < 0.80 GeV/c$; y; Events", kTH1F, {rapidityAxis}); - histosData.add("fourpion_rap_non_0_charge_domC", "Rapidity of Events With Track Selection and PID Selection of Pi for p_{T} > 0.80 GeV/c; y; Events", kTH1F, {rapidityAxis}); + // Four Pion Phi + histosData.add("fourpion_phi_0_charge", "Four Pion #phi (0 charge); #phi [rad]; Events", kTH1F, {phiAxis}); + histosData.add("fourpion_phi_non_0_charge", "Four Pion #phi (non 0 charge); #phi [rad]; Events", kTH1F, {phiAxis}); + + // Four Pion Rapidity + histosData.add("fourpion_rap_0_charge", "Four Pion Rapidity (0 charge); y; Events", kTH1F, {{1000, -2.5, 2.5}}); + histosData.add("fourpion_rap_non_0_charge", "Four Pion Rapidity (non 0 charge); y; Events", kTH1F, {rapidityAxis}); + + // Four Pion Mass + histosData.add("fourpion_mass_0_charge", "Four Pion Invariant Mass (0 charge); m(#pi^{+}#pi^{-}#pi^{+}#pi^{-}) [GeV/c]; Events", kTH1F, {invMassAxis}); + histosData.add("fourpion_mass_non_0_charge", "Four Pion Invariant Mass (non 0 charge); m(#pi^{+}#pi^{-}#pi^{+}#pi^{-}) [GeV/c]; Events", kTH1F, {invMassAxis}); // Pair Invariant Mass histosData.add("twopion_mass_1", "Invariant Mass Distribution of 2 pions 1 ; m(#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {{5000, 0, 5}}); @@ -628,31 +664,14 @@ struct ExclusiveRhoTo4Pi { histosData.add("twopion_mass_3", "Invariant Mass Distribution of 2 pions 3 ; m(#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {{5000, 0, 5}}); histosData.add("twopion_mass_4", "Invariant Mass Distribution of 2 pions 4 ; m(#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {{5000, 0, 5}}); - // Invariant Mass of 0 charge events - histosData.add("fourpion_mass_0_charge_domA", "Invariant Mass Distribution of 0 charge Events with PID Selection of Pi for p_{T} < 0.15 GeV/c; m(#pi^{+}#pi^{-}#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {invMassAxis}); // pT < 0.15GeV - histosData.add("fourpion_mass_0_charge_domB", "Invariant Mass Distribution of 0 charge Events with PID Selection of Pi for 0.15< p_{T} < 0.80 GeV/c; m(#pi^{+}#pi^{-}#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {invMassAxis}); // 0.15GeV < pT < 0.8GeV - histosData.add("fourpion_mass_0_charge_domC", "Invariant Mass Distribution of 0 charge Events with PID Selection of Pi for p_{T} > 0.80 GeV/c; m(#pi^{+}#pi^{-}#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {invMassAxis}); // 0.8GeV < pT - - // Invariant mass of non 0 charge events + // Four Pion Invariant Mass + histosData.add("fourpion_mass_0_charge_domA", "Invariant Mass Distribution of 0 charge Events with PID Selection of Pi for p_{T} < 0.15 GeV/c; m(#pi^{+}#pi^{-}#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {invMassAxis}); // pT < 0.15GeV + histosData.add("fourpion_mass_0_charge_domB", "Invariant Mass Distribution of 0 charge Events with PID Selection of Pi for 0.15< p_{T} < 0.80 GeV/c; m(#pi^{+}#pi^{-}#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {invMassAxis}); // 0.15GeV < pT < 0.8GeV + histosData.add("fourpion_mass_0_charge_domC", "Invariant Mass Distribution of 0 charge Events with PID Selection of Pi for p_{T} > 0.80 GeV/c; m(#pi^{+}#pi^{-}#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {invMassAxis}); // 0.8GeV < pT histosData.add("fourpion_mass_non_0_charge_domA", "Invariant Mass Distribution of non 0 charge Events with PID Selection of Pi for p_{T} < 0.15 GeV/c; m(#pi^{+}#pi^{-}#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {invMassAxis}); // pT < 0.15GeV histosData.add("fourpion_mass_non_0_charge_domB", "Invariant Mass Distribution of non 0 charge Events with PID Selection of Pi for 0.15< p_{T} < 0.80 GeV/c; m(#pi^{+}#pi^{-}#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {invMassAxis}); // 0.15GeV < pT < 0.8GeV histosData.add("fourpion_mass_non_0_charge_domC", "Invariant Mass Distribution of non 0 charge Events with PID Selection of Pi for p_{T} > 0.80 GeV/c; m(#pi^{+}#pi^{-}#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {invMassAxis}); // 0.8GeV < pT - // tpc signal - histosData.add("tpcSignal", "TPC dEdx vs p; p [GeV/c]; dEdx [a.u.]", kTH2F, {{500, 0, 10}, {5000, 0.0, 5000.0}}); - histosData.add("tpcSignal_pions", "TPC dEdx vs p for pions; p [GeV/c]; dEdx [a.u.]", kTH2F, {{500, 0, 10}, {5000, 0.0, 5000.0}}); - - // tof beta - histosData.add("tofBeta", "TOF beta vs p; p [GeV/c]; #beta", kTH2F, {{500, 0, 10}, {500, 0.0, 1.0}}); - histosData.add("tofBeta_pions", "TOF beta vs p for pions; p [GeV/c]; #beta", kTH2F, {{500, 0, 10}, {500, 0.0, 1.0}}); - - // Other signals - histosData.add("FT0A", "T0A amplitude", kTH1F, {{2000, 0.0, 500.0}}); - histosData.add("FT0C", "T0C amplitude", kTH1F, {{2000, 0.0, 500.0}}); - histosData.add("ZDC_A", "ZDC amplitude", kTH1F, {{1000, 0.0, 15}}); - histosData.add("ZDC_C", "ZDC amplitude", kTH1F, {{1000, 0.0, 15}}); - histosData.add("V0A", "V0A amplitude", kTH1F, {{1000, 0.0, 100}}); - // Collin Soper Theta and Phi histosData.add("collin_soper_phi_1", "#phi Distribution; #phi; Events", kTH1F, {phiAxis}); histosData.add("collin_soper_phi_2", "#phi Distribution; #phi; Events", kTH1F, {phiAxis}); @@ -697,7 +716,6 @@ struct ExclusiveRhoTo4Pi { histosMCgen.add("phi_vs_costheta_2", "Phi vs cosTheta; #phi; cos(#theta)", kTH2F, {phiAxis, cosThetaAxis}); // MC Reco Stuff - histosMCreco.add("vertexZ", "Vertex Z; Vertex Z [cm]; Counts", kTH1F, {{1000, -20, 20}}); histosMCreco.add("occupancy", "Occupancy; Occupancy; Counts", kTH1F, {{1500, 0, 1500}}); histosMCreco.add("dcaXY", "dcaXY; dcaXY [cm]; Counts", kTH1F, {{10000, -5, 5}}); @@ -705,7 +723,6 @@ struct ExclusiveRhoTo4Pi { histosMCreco.add("tpcChi2NCl", "TPC Chi2/NCl; Chi2/NCl; Counts", kTH1F, {{200, 0, 200}}); histosMCreco.add("itsChi2NCl", "ITS Chi2/NCl; Chi2/NCl; Counts", kTH1F, {{200, 0, 200}}); histosMCreco.add("tpcNClsFindable", "TPC N Cls Findable; N Cls Findable; Counts", kTH1F, {{200, 0, 200}}); - histosMCreco.add("GapSide", "Gap Side; Events", kTH1F, {{4, -1.5, 2.5}}); histosMCreco.add("TrueGapSide", "Gap Side; Events", kTH1F, {{4, -1.5, 2.5}}); histosMCreco.add("EventCounts", "Total Events; Events", kTH1F, {{10, 0, 10}}); @@ -855,28 +872,35 @@ struct ExclusiveRhoTo4Pi { return phi; } // End of phiCollinsSoperFrame function------------------------------------------------------------------------------------------------------------------------ - //---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + // Applied Filters------------------------------------------------------------------------------------------------------------------------- Filter vertexCut = (nabs(o2::aod::collision::posZ) <= vZCut) && (o2::aod::collision::numContrib == numPVContrib); Filter fitcuts = o2::aod::udcollision::totalFV0AmplitudeA < fv0Cut && o2::aod::udcollision::totalFT0AmplitudeA < ft0aCut && o2::aod::udcollision::totalFT0AmplitudeC < ft0cCut; Filter zdcCuts = (o2::aod::udzdc::energyCommonZNA < zdcCut) && (o2::aod::udzdc::energyCommonZNC < zdcCut); - Filter bcSelectionCut = (o2::aod::udcollision::sbp == sbpCut) && (o2::aod::udcollision::itsROFb == itsROFbCut) && (o2::aod::udcollision::vtxITSTPC == vtxITSTPCcut) && (o2::aod::udcollision::tfb == tfbCut); Filter onlyPVtracks = o2::aod::udtrack::isPVContributor == true; Filter occupCut = nabs(o2::aod::udcollision::occupancyInTime) < occupancyCut; + //---------------------------------------------------------------------------------------------------------------------------------------- + + // Process Data pass5---------------------------------------------------------------------------------------------------------------------------- using UDtracks = soa::Filtered>; - using UDCollisions = soa::Filtered>; // + using UDCollisions = soa::Filtered>; using UDCollision = UDCollisions::iterator; - //---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - // Begin of Process function-------------------------------------------------------------------------------------------------------------------------------------------------- void processData(UDCollision const& collision, UDtracks const& tracks) { + if (!(collision.sbp() == sbpCut && collision.itsROFb() == itsROFbCut && collision.vtxITSTPC() == vtxITSTPCcut && collision.tfb() == tfbCut)) { + return; + } + int gapSide = collision.gapSide(); std::vector parameters = {pvCut, dcaZcut, dcaXYcut, tpcChi2Cut, tpcNClsFindableCut, itsChi2Cut, etaCut, pTcut}; int truegapSide = sgSelector.trueGap(collision, fv0Cut, ft0aCut, ft0cCut, zdcCut); + histosData.fill(HIST("GapSide"), gapSide); histosData.fill(HIST("TrueGapSide"), truegapSide); - histosData.fill(HIST("EventCounts"), 1); + histosData.fill(HIST("EventsCounts_vs_runNo"), collision.runNumber(), 1); + histosData.fill(HIST("vertexX"), collision.posX()); + histosData.fill(HIST("vertexY"), collision.posY()); histosData.fill(HIST("vertexZ"), collision.posZ()); histosData.fill(HIST("occupancy"), collision.occupancyInTime()); histosData.fill(HIST("V0A"), collision.totalFV0AmplitudeA()); @@ -890,7 +914,21 @@ struct ExclusiveRhoTo4Pi { std::vector selectedPionPlusTracks; std::vector selectedPionMinusTracks; + double avgpT = 0.0; + double avgEta = 0.0; + double avgPhi = 0.0; + double avgdcaxy = 0.0; + double avgdcaz = 0.0; + for (const auto& t0 : tracks) { + + ROOT::Math::PxPyPzMVector trackVector(t0.px(), t0.py(), t0.pz(), o2::constants::physics::MassPionCharged); + avgpT += trackVector.Pt(); + avgEta += trackVector.Eta(); + avgPhi += trackVector.Phi(); + avgdcaxy += t0.dcaXY(); + avgdcaz += t0.dcaZ(); + if (trackselector(t0, parameters)) { selectedTracks.push_back(t0); if (selectionPIDPion(t0, true, nSigmaTPCcut, nSigmaTOFcut)) { @@ -903,8 +941,15 @@ struct ExclusiveRhoTo4Pi { } } // End of Selection PID Pion } // End of track selections + } // End of loop over tracks + histosData.fill(HIST("avg_pT_pi_vs_runNo"), collision.runNumber(), avgpT / tracks.size()); + histosData.fill(HIST("avg_eta_pi_vs_runNo"), collision.runNumber(), avgEta / tracks.size()); + histosData.fill(HIST("avg_phi_pi_vs_runNo"), collision.runNumber(), avgPhi / tracks.size()); + histosData.fill(HIST("avg_dcaxy_vs_runNo"), collision.runNumber(), avgdcaxy / tracks.size()); + histosData.fill(HIST("avg_dcaz_vs_runNo"), collision.runNumber(), avgdcaz / tracks.size()); + int numSelectedTracks = static_cast(selectedTracks.size()); int numSelectedPionTracks = static_cast(selectedPionTracks.size()); int numPiPlusTracks = static_cast(selectedPionPlusTracks.size()); @@ -917,6 +962,8 @@ struct ExclusiveRhoTo4Pi { histosData.fill(HIST("tpcNSigmaPi_all"), selectedTracks[i].tpcNSigmaPi(), selectedTrackVector.Pt()); histosData.fill(HIST("tofNSigmaPi_all"), selectedTracks[i].tofNSigmaPi(), selectedTrackVector.Pt()); histosData.fill(HIST("pT_track_all"), selectedTrackVector.Pt()); + histosData.fill(HIST("eta_track_all"), selectedTrackVector.Eta()); + histosData.fill(HIST("phi_track_all"), selectedTrackVector.Phi()); histosData.fill(HIST("rapidity_track_all"), selectedTrackVector.Rapidity()); histosData.fill(HIST("itsChi2NCl"), selectedTracks[i].itsChi2NCl()); histosData.fill(HIST("tpcChi2NCl"), selectedTracks[i].tpcChi2NCl()); @@ -940,14 +987,18 @@ struct ExclusiveRhoTo4Pi { histosData.fill(HIST("tofNSigmaEl_pions"), selectedPionTracks[i].tofNSigmaEl(), selectedPionTrackVector.Pt()); histosData.fill(HIST("tofNSigmaMu_pions"), selectedPionTracks[i].tofNSigmaMu(), selectedPionTrackVector.Pt()); histosData.fill(HIST("pT_track_pions"), selectedPionTrackVector.Pt()); + histosData.fill(HIST("eta_track_pions"), selectedPionTrackVector.Eta()); + histosData.fill(HIST("phi_track_pions"), selectedPionTrackVector.Phi()); histosData.fill(HIST("rapidity_track_pions"), selectedPionTrackVector.Rapidity()); + histosData.fill(HIST("dcaXY_pions"), selectedPionTracks[i].dcaXY()); + histosData.fill(HIST("dcaZ_pions"), selectedPionTracks[i].dcaZ()); } // End of loop over tracks with selection and PID selection of Pions if (numSelectedPionTracks != numFourPionTracks) { return; } - histosData.fill(HIST("EventCounts"), 2); + histosData.fill(HIST("EventsCounts_vs_runNo"), collision.runNumber(), 2); // Check if there is at least one track with TOF in the selected events, otherwise return bool hasAtleastOneTOF = false; @@ -960,12 +1011,12 @@ struct ExclusiveRhoTo4Pi { if ((!hasAtleastOneTOF) && (checkOneTof == 1)) { return; } - histosData.fill(HIST("EventCounts"), 3); + histosData.fill(HIST("EventsCounts_vs_runNo"), collision.runNumber(), 3); // Selecting Events with net charge = 0 if (numPionMinusTracks == numPiMinus && numPiPlusTracks == numPiPlus) { - histosData.fill(HIST("EventCounts"), 4); + histosData.fill(HIST("EventsCounts_vs_runNo"), collision.runNumber(), 4); ROOT::Math::PtEtaPhiMVector k1, k2, k3, k4, k1234, k13, k14, k23, k24; @@ -979,11 +1030,27 @@ struct ExclusiveRhoTo4Pi { histosData.fill(HIST("pT_track_pions_contributed"), p3.Pt()); histosData.fill(HIST("pT_track_pions_contributed"), p4.Pt()); + histosData.fill(HIST("eta_track_pions_contributed"), p1.Eta()); + histosData.fill(HIST("eta_track_pions_contributed"), p2.Eta()); + histosData.fill(HIST("eta_track_pions_contributed"), p3.Eta()); + histosData.fill(HIST("eta_track_pions_contributed"), p4.Eta()); + + histosData.fill(HIST("phi_track_pions_contributed"), p1.Phi()); + histosData.fill(HIST("phi_track_pions_contributed"), p2.Phi()); + histosData.fill(HIST("phi_track_pions_contributed"), p3.Phi()); + histosData.fill(HIST("phi_track_pions_contributed"), p4.Phi()); + histosData.fill(HIST("rapidity_track_pions_contributed"), p1.Rapidity()); histosData.fill(HIST("rapidity_track_pions_contributed"), p2.Rapidity()); histosData.fill(HIST("rapidity_track_pions_contributed"), p3.Rapidity()); histosData.fill(HIST("rapidity_track_pions_contributed"), p4.Rapidity()); + histosData.fill(HIST("avg_pT_pi_vs_runNo_selected4piEvents"), collision.runNumber(), (p1.Pt() + p2.Pt() + p3.Pt() + p4.Pt()) / 4.0); + histosData.fill(HIST("avg_eta_pi_vs_runNo_selected4piEvents"), collision.runNumber(), (p1.Eta() + p2.Eta() + p3.Eta() + p4.Eta()) / 4.0); + histosData.fill(HIST("avg_phi_pi_vs_runNo_selected4piEvents"), collision.runNumber(), (p1.Phi() + p2.Phi() + p3.Phi() + p4.Phi()) / 4.0); + histosData.fill(HIST("avg_dcaxy_vs_runNo_selected4piEvents"), collision.runNumber(), (selectedPionPlusTracks[0].dcaXY() + selectedPionPlusTracks[1].dcaXY() + selectedPionMinusTracks[0].dcaXY() + selectedPionMinusTracks[1].dcaXY()) / 4.0); + histosData.fill(HIST("avg_dcaz_vs_runNo_selected4piEvents"), collision.runNumber(), (selectedPionPlusTracks[0].dcaZ() + selectedPionPlusTracks[1].dcaZ() + selectedPionMinusTracks[0].dcaZ() + selectedPionMinusTracks[1].dcaZ()) / 4.0); + k1.SetCoordinates(p1.Pt(), p1.Eta(), p1.Phi(), o2::constants::physics::MassPionCharged); k2.SetCoordinates(p2.Pt(), p2.Eta(), p2.Phi(), o2::constants::physics::MassPionCharged); k3.SetCoordinates(p3.Pt(), p3.Eta(), p3.Phi(), o2::constants::physics::MassPionCharged); @@ -997,6 +1064,12 @@ struct ExclusiveRhoTo4Pi { k23 = k2 + k3; k24 = k2 + k4; + histosData.fill(HIST("fourpion_pT_0_charge"), p1234.Pt()); + histosData.fill(HIST("fourpion_eta_0_charge"), p1234.Eta()); + histosData.fill(HIST("fourpion_phi_0_charge"), p1234.Phi()); + histosData.fill(HIST("fourpion_rap_0_charge"), p1234.Rapidity()); + histosData.fill(HIST("fourpion_mass_0_charge"), p1234.M()); + double fourPiPhiPair1 = phiCollinsSoperFrame(k13, k24, k1234); double fourPiPhiPair2 = phiCollinsSoperFrame(k14, k23, k1234); double fourPiCosThetaPair1 = cosThetaCollinsSoperFrame(k13, k24, k1234); @@ -1036,41 +1109,35 @@ struct ExclusiveRhoTo4Pi { if (std::fabs(p1234.Rapidity()) < rhoRapCut) { histosData.fill(HIST("fourpion_pT_0_charge"), p1234.Pt()); if (p1234.Pt() < rhoPtCut) { - - histosData.fill(HIST("EventCounts"), 5); - - histosData.fill(HIST("fourpion_rap_0_charge_domA"), p1234.Rapidity()); + histosData.fill(HIST("EventsCounts_vs_runNo"), collision.runNumber(), 5); + // Fill the Invariant Mass Histogram histosData.fill(HIST("fourpion_mass_0_charge_domA"), p1234.M()); - + // Two Pion Masses histosData.fill(HIST("twopion_mass_1"), (p1 + p3).M()); histosData.fill(HIST("twopion_mass_2"), (p1 + p4).M()); histosData.fill(HIST("twopion_mass_3"), (p2 + p3).M()); histosData.fill(HIST("twopion_mass_4"), (p2 + p4).M()); - + // Fill the Collins-Soper Frame histograms histosData.fill(HIST("collin_soper_phi_1"), fourPiPhiPair1); histosData.fill(HIST("collin_soper_phi_2"), fourPiPhiPair2); histosData.fill(HIST("collin_soper_costheta_1"), fourPiCosThetaPair1); histosData.fill(HIST("collin_soper_costheta_2"), fourPiCosThetaPair2); - histosData.fill(HIST("phi_vs_costheta_1"), fourPiPhiPair1, fourPiCosThetaPair1); histosData.fill(HIST("phi_vs_costheta_2"), fourPiPhiPair2, fourPiCosThetaPair2); } if (p1234.Pt() > rhoPtCut && p1234.Pt() < zeroPointEight) { - histosData.fill(HIST("fourpion_rap_0_charge_domB"), p1234.Rapidity()); histosData.fill(HIST("fourpion_mass_0_charge_domB"), p1234.M()); } if (p1234.Pt() > zeroPointEight) { - histosData.fill(HIST("fourpion_rap_0_charge_domC"), p1234.Rapidity()); histosData.fill(HIST("fourpion_mass_0_charge_domC"), p1234.M()); } } // End of Rapidity range selection - } // End of Analysis for 0 charge events // Selecting Events with net charge != 0 for estimation of background if (numPionMinusTracks != numPiMinus && numPiPlusTracks != numPiPlus) { - histosData.fill(HIST("EventCounts"), 6); + histosData.fill(HIST("EventsCounts_vs_runNo"), collision.runNumber(), 6); ROOT::Math::PxPyPzMVector p1(selectedPionTracks[0].px(), selectedPionTracks[0].py(), selectedPionTracks[0].pz(), o2::constants::physics::MassPionCharged); ROOT::Math::PxPyPzMVector p2(selectedPionTracks[1].px(), selectedPionTracks[1].py(), selectedPionTracks[1].pz(), o2::constants::physics::MassPionCharged); @@ -1079,6 +1146,12 @@ struct ExclusiveRhoTo4Pi { ROOT::Math::PxPyPzMVector p1234 = p1 + p2 + p3 + p4; + histosData.fill(HIST("fourpion_pT_non_0_charge"), p1234.Pt()); + histosData.fill(HIST("fourpion_eta_non_0_charge"), p1234.Eta()); + histosData.fill(HIST("fourpion_phi_non_0_charge"), p1234.Phi()); + histosData.fill(HIST("fourpion_rap_non_0_charge"), p1234.Rapidity()); + histosData.fill(HIST("fourpion_mass_non_0_charge"), p1234.M()); + bkgFromData( collision.posX(), collision.posY(), collision.posZ(), collision.totalFV0AmplitudeA(), collision.totalFT0AmplitudeA(), collision.totalFT0AmplitudeC(), collision.totalFDDAmplitudeA(), collision.totalFDDAmplitudeC(), @@ -1104,25 +1177,20 @@ struct ExclusiveRhoTo4Pi { histosData.fill(HIST("fourpion_pT_non_0_charge"), p1234.Pt()); if (p1234.Pt() < rhoPtCut) { - histosData.fill(HIST("EventCounts"), 7); - histosData.fill(HIST("fourpion_rap_non_0_charge_domA"), p1234.Rapidity()); + histosData.fill(HIST("EventsCounts_vs_runNo"), collision.runNumber(), 7); histosData.fill(HIST("fourpion_mass_non_0_charge_domA"), p1234.M()); } if (p1234.Pt() > rhoPtCut && p1234.Pt() < zeroPointEight) { - histosData.fill(HIST("fourpion_rap_non_0_charge_domB"), p1234.Rapidity()); histosData.fill(HIST("fourpion_mass_non_0_charge_domB"), p1234.M()); } if (p1234.Pt() > zeroPointEight) { - histosData.fill(HIST("fourpion_rap_non_0_charge_domC"), p1234.Rapidity()); histosData.fill(HIST("fourpion_mass_non_0_charge_domC"), p1234.M()); } } // End of Rapidity range selection } // End of Analysis for non 0 charge events - } // End of 4 Pion Analysis Process function for Data - PROCESS_SWITCH(ExclusiveRhoTo4Pi, processData, "The Process for 4 Pion Analysis from data", false); - //---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + } // End of 4 Pion Analysis Process function for Pass5 Data - // Begin of MC Generation function----------------------------------------------------------------------------------------------------------------------------------------------- + // Analysis for MC generated data---------------------------------------------------------------------------------------------------------------------------- void processMCgen(aod::UDMcCollisions::iterator const&, aod::UDMcParticles const& mcParts) { std::vector piPlusvectors; @@ -1218,9 +1286,8 @@ struct ExclusiveRhoTo4Pi { histosMCgen.fill(HIST("phi_vs_costheta_2"), phiPair2, cosThetaPair2); } // End of 4 Pion MC Generation Process function - PROCESS_SWITCH(ExclusiveRhoTo4Pi, processMCgen, "The Process for 4 Pion Analysis from MC Generation", true); - // Begin of MC Reconstruction function----------------------------------------------------------------------------------------------------------------------------------------------- + // Analysis for MC reconstructed data---------------------------------------------------------------------------------------------------------------------------- using CollisionStuff = soa::Join; using CollisionTotal = CollisionStuff::iterator; using TrackStuff = soa::Join; @@ -1440,6 +1507,9 @@ struct ExclusiveRhoTo4Pi { } // End of Analysis for non 0 charge events } // End of 4 Pion Analysis Process function for MC Reconstruction + + PROCESS_SWITCH(ExclusiveRhoTo4Pi, processData, "The Process for 4 Pion Analysis from data", true); + PROCESS_SWITCH(ExclusiveRhoTo4Pi, processMCgen, "The Process for 4 Pion Analysis from MC Generation", false); PROCESS_SWITCH(ExclusiveRhoTo4Pi, processMCrec, "The Process for 4 Pion Analysis from MC Reconstruction", false); }; // End of Struct exclusiveRhoTo4Pi From 463858e6259cbc861ad6155deeb1262e8ef13eaa Mon Sep 17 00:00:00 2001 From: Francesca Ercolessi Date: Fri, 27 Jun 2025 05:20:32 +0200 Subject: [PATCH 228/871] [PWGLF] nuclei-proton angular correlation: add DCA plots for secondary estimation (#11786) --- .../Tasks/Nuspex/hadronnucleicorrelation.cxx | 66 +++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/PWGLF/Tasks/Nuspex/hadronnucleicorrelation.cxx b/PWGLF/Tasks/Nuspex/hadronnucleicorrelation.cxx index d851ba206c5..318159fcd82 100644 --- a/PWGLF/Tasks/Nuspex/hadronnucleicorrelation.cxx +++ b/PWGLF/Tasks/Nuspex/hadronnucleicorrelation.cxx @@ -298,6 +298,11 @@ struct hadronnucleicorrelation { } } + registry.add("hPrDCAxy", "DCAxy p", {HistType::kTH2D, {{600, -3.f, 3.f, "DCA xy (cm)"}, {100, 0.f, 10.f, "p_{T} GeV/c"}}}); + registry.add("hAntiPrDCAxy", "DCAxy #bar{p}", {HistType::kTH2D, {{600, -3.f, 3.f, "DCA xy (cm)"}, {100, 0.f, 10.f, "p_{T} GeV/c"}}}); + registry.add("hDeDCAxy", "DCAxy d", {HistType::kTH2D, {{600, -3.f, 3.f, "DCA xy (cm)"}, {100, 0.f, 10.f, "p_{T} GeV/c"}}}); + registry.add("hAntiDeDCAxy", "DCAxy #bar{d}", {HistType::kTH2D, {{600, -3.f, 3.f, "DCA xy (cm)"}, {100, 0.f, 10.f, "p_{T} GeV/c"}}}); + if (doQA) { // Track QA QA.add("QA/hVtxZ_trk", "#it{z}_{vtx}", {HistType::kTH1D, {{150, -15.f, 15.f, "#it{z}_{vtx} (cm)"}}}); @@ -332,6 +337,19 @@ struct hadronnucleicorrelation { } if (isMC) { + registry.add("hPrimPrDCAxy", "DCAxy p", {HistType::kTH2D, {{600, -3.f, 3.f, "DCA xy (cm)"}, {100, 0.f, 10.f, "p_{T} GeV/c"}}}); + registry.add("hPrimAntiPrDCAxy", "DCAxy #bar{p}", {HistType::kTH2D, {{600, -3.f, 3.f, "DCA xy (cm)"}, {100, 0.f, 10.f, "p_{T} GeV/c"}}}); + registry.add("hPrimDeDCAxy", "DCAxy d", {HistType::kTH2D, {{600, -3.f, 3.f, "DCA xy (cm)"}, {100, 0.f, 10.f, "p_{T} GeV/c"}}}); + registry.add("hPrimAntiDeDCAxy", "DCAxy #bar{d}", {HistType::kTH2D, {{600, -3.f, 3.f, "DCA xy (cm)"}, {100, 0.f, 10.f, "p_{T} GeV/c"}}}); + registry.add("hSecMatPrDCAxy", "DCAxy p", {HistType::kTH2D, {{600, -3.f, 3.f, "DCA xy (cm)"}, {100, 0.f, 10.f, "p_{T} GeV/c"}}}); + registry.add("hSecMatAntiPrDCAxy", "DCAxy #bar{p}", {HistType::kTH2D, {{600, -3.f, 3.f, "DCA xy (cm)"}, {100, 0.f, 10.f, "p_{T} GeV/c"}}}); + registry.add("hSecMatDeDCAxy", "DCAxy d", {HistType::kTH2D, {{600, -3.f, 3.f, "DCA xy (cm)"}, {100, 0.f, 10.f, "p_{T} GeV/c"}}}); + registry.add("hSecMatAntiDeDCAxy", "DCAxy #bar{d}", {HistType::kTH2D, {{600, -3.f, 3.f, "DCA xy (cm)"}, {100, 0.f, 10.f, "p_{T} GeV/c"}}}); + registry.add("hSecWeakPrDCAxy", "DCAxy p", {HistType::kTH2D, {{600, -3.f, 3.f, "DCA xy (cm)"}, {100, 0.f, 10.f, "p_{T} GeV/c"}}}); + registry.add("hSecWeakAntiPrDCAxy", "DCAxy #bar{p}", {HistType::kTH2D, {{600, -3.f, 3.f, "DCA xy (cm)"}, {100, 0.f, 10.f, "p_{T} GeV/c"}}}); + registry.add("hSecWeakDeDCAxy", "DCAxy d", {HistType::kTH2D, {{600, -3.f, 3.f, "DCA xy (cm)"}, {100, 0.f, 10.f, "p_{T} GeV/c"}}}); + registry.add("hSecWeakAntiDeDCAxy", "DCAxy #bar{d}", {HistType::kTH2D, {{600, -3.f, 3.f, "DCA xy (cm)"}, {100, 0.f, 10.f, "p_{T} GeV/c"}}}); + registry.add("hReco_EtaPhiPt_Proton", "Gen (anti)protons in reco collisions", {HistType::kTH3F, {etaAxis, phiAxis, pTAxis_small}}); registry.add("hReco_EtaPhiPt_Deuteron", "Gen (anti)deuteron in reco collisions", {HistType::kTH3F, {etaAxis, phiAxis, pTAxis_small}}); registry.add("hReco_PID_EtaPhiPt_Proton", "Gen (anti)protons + PID in reco collisions", {HistType::kTH3F, {etaAxis, phiAxis, pTAxis_small}}); @@ -744,6 +762,16 @@ struct hadronnucleicorrelation { continue; if (track.itsNCls() < min_itsNCls) continue; + + if (IsProton(track, +1)) + registry.fill(HIST("hPrDCAxy"), track.dcaXY(), track.pt()); + if (IsProton(track, -1)) + registry.fill(HIST("hAntiPrDCAxy"), track.dcaXY(), track.pt()); + if (IsDeuteron(track, +1)) + registry.fill(HIST("hDeDCAxy"), track.dcaXY(), track.pt()); + if (IsDeuteron(track, -1)) + registry.fill(HIST("hAntiDeDCAxy"), track.dcaXY(), track.pt()); + if (!applyDCAcut(track)) continue; @@ -1130,6 +1158,44 @@ struct hadronnucleicorrelation { continue; if (track.itsNCls() < min_itsNCls) continue; + + if (IsProton(track, +1) && track.pdgCode() == pdgProton) { + registry.fill(HIST("hPrDCAxy"), track.dcaXY(), track.pt()); + if (track.origin() == 0) + registry.fill(HIST("hPrimPrDCAxy"), track.dcaXY(), track.pt()); + if (track.origin() == 1) + registry.fill(HIST("hSecWeakPrDCAxy"), track.dcaXY(), track.pt()); + if (track.origin() == 2) + registry.fill(HIST("hSecMatPrDCAxy"), track.dcaXY(), track.pt()); + } + if (IsProton(track, -1) && track.pdgCode() == -pdgProton) { + registry.fill(HIST("hAntiPrDCAxy"), track.dcaXY(), track.pt()); + if (track.origin() == 0) + registry.fill(HIST("hPrimAntiPrDCAxy"), track.dcaXY(), track.pt()); + if (track.origin() == 1) + registry.fill(HIST("hSecWeakAntiPrDCAxy"), track.dcaXY(), track.pt()); + if (track.origin() == 2) + registry.fill(HIST("hSecMatAntiPrDCAxy"), track.dcaXY(), track.pt()); + } + if (IsDeuteron(track, +1) && track.pdgCode() == pdgDeuteron) { + registry.fill(HIST("hDeDCAxy"), track.dcaXY(), track.pt()); + if (track.origin() == 0) + registry.fill(HIST("hPrimDeDCAxy"), track.dcaXY(), track.pt()); + if (track.origin() == 1) + registry.fill(HIST("hSecWeakDeDCAxy"), track.dcaXY(), track.pt()); + if (track.origin() == 2) + registry.fill(HIST("hSecMatDeDCAxy"), track.dcaXY(), track.pt()); + } + if (IsDeuteron(track, -1) && track.pdgCode() == -pdgDeuteron) { + registry.fill(HIST("hAntiDeDCAxy"), track.dcaXY(), track.pt()); + if (track.origin() == 0) + registry.fill(HIST("hPrimAntiDeDCAxy"), track.dcaXY(), track.pt()); + if (track.origin() == 1) + registry.fill(HIST("hSecWeakAntiDeDCAxy"), track.dcaXY(), track.pt()); + if (track.origin() == 2) + registry.fill(HIST("hSecMatAntiDeDCAxy"), track.dcaXY(), track.pt()); + } + if (!applyDCAcut(track)) continue; From a6fac7d69a07d6d1692904350e977be95a1987f2 Mon Sep 17 00:00:00 2001 From: SCHOTTER Romain <47983209+romainschotter@users.noreply.github.com> Date: Fri, 27 Jun 2025 07:38:07 +0200 Subject: [PATCH 229/871] [Common] Fix global counters constexpr if-condition (#11788) --- Common/Tools/MultModule.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Common/Tools/MultModule.h b/Common/Tools/MultModule.h index bb6e1760344..08904a21f61 100644 --- a/Common/Tools/MultModule.h +++ b/Common/Tools/MultModule.h @@ -789,8 +789,8 @@ class MultModule } // global counters: do them only in case information is provided in tracks table - if constexpr (requires { tracks.isQualityTrack(); }) { - if (track.pt() < internalOpts.maxPtGlobalTrack.value && track.pt() > internalOpts.minPtGlobalTrack.value && std::fabs(track.eta()) < 1.0f && track.isPVContributor() && tracks.isQualityTrack()) { + if constexpr (requires { track.isQualityTrack(); }) { + if (track.pt() < internalOpts.maxPtGlobalTrack.value && track.pt() > internalOpts.minPtGlobalTrack.value && std::fabs(track.eta()) < 1.0f && track.isPVContributor() && track.isQualityTrack()) { if (track.itsNCls() < internalOpts.minNclsITSGlobalTrack || track.itsNClsInnerBarrel() < internalOpts.minNclsITSibGlobalTrack) { continue; } From 536729110d7bbafdc4ccea81e5d534b1b6e71403 Mon Sep 17 00:00:00 2001 From: Francesco Mazzaschi <43742195+fmazzasc@users.noreply.github.com> Date: Fri, 27 Jun 2025 09:27:55 +0200 Subject: [PATCH 230/871] [PWGLF] Add debug table to kink builder + mc info for kink sigma (#11780) Co-authored-by: Francesco Mazzaschi Co-authored-by: ALICE Action Bot --- PWGLF/DataModel/LFKinkDecayTables.h | 31 +++++++++- PWGLF/TableProducer/Common/kinkBuilder.cxx | 57 +++++++++++-------- PWGLF/Tasks/Strangeness/sigmaminustask.cxx | 66 ++++++++++++++++++++-- 3 files changed, 122 insertions(+), 32 deletions(-) diff --git a/PWGLF/DataModel/LFKinkDecayTables.h b/PWGLF/DataModel/LFKinkDecayTables.h index 5f8798856d5..9533bd66116 100644 --- a/PWGLF/DataModel/LFKinkDecayTables.h +++ b/PWGLF/DataModel/LFKinkDecayTables.h @@ -15,10 +15,11 @@ /// \author Francesco Mazzaschi /// -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.h" #include "Common/Core/RecoDecay.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" + #ifndef PWGLF_DATAMODEL_LFKINKDECAYTABLES_H_ #define PWGLF_DATAMODEL_LFKINKDECAYTABLES_H_ @@ -77,6 +78,13 @@ DECLARE_SOA_DYNAMIC_COLUMN(MSigmaPlus, mSigmaPlus, //! mass under sigma plus hyp float pzneut = pzmoth - pzch; return RecoDecay::m(std::array{std::array{pxch, pych, pzch}, std::array{pxneut, pyneut, pzneut}}, std::array{o2::constants::physics::MassProton, o2::constants::physics::MassPionNeutral}); }); +DECLARE_SOA_DYNAMIC_COLUMN(MXiMinus, mXiMinus, //! mass under Xi minus hypothesis + [](float pxmoth, float pymoth, float pzmoth, float pxch, float pych, float pzch) -> float { + float pxneut = pxmoth - pxch; + float pyneut = pymoth - pych; + float pzneut = pzmoth - pzch; + return RecoDecay::m(std::array{std::array{pxch, pych, pzch}, std::array{pxneut, pyneut, pzneut}}, std::array{o2::constants::physics::MassPionCharged, o2::constants::physics::MassLambda}); }); + } // namespace kinkcand DECLARE_SOA_TABLE(KinkCands, "AOD", "KINKCANDS", @@ -93,7 +101,24 @@ DECLARE_SOA_TABLE(KinkCands, "AOD", "KINKCANDS", kinkcand::PtMoth, kinkcand::PtDaug, kinkcand::MSigmaMinus, - kinkcand::MSigmaPlus); + kinkcand::MSigmaPlus, + kinkcand::MXiMinus); + +DECLARE_SOA_TABLE(KinkCandsUnbound, "AOD", "UBKINKCANDS", + o2::soa::Index<>, kinkcand::XDecVtx, kinkcand::YDecVtx, kinkcand::ZDecVtx, + kinkcand::MothSign, kinkcand::PxMoth, kinkcand::PyMoth, kinkcand::PzMoth, + kinkcand::PxDaug, kinkcand::PyDaug, kinkcand::PzDaug, + kinkcand::DcaMothPv, kinkcand::DcaDaugPv, kinkcand::DcaKinkTopo, + + // dynamic columns + kinkcand::PxDaugNeut, + kinkcand::PyDaugNeut, + kinkcand::PzDaugNeut, + kinkcand::PtMoth, + kinkcand::PtDaug, + kinkcand::MSigmaMinus, + kinkcand::MSigmaPlus, + kinkcand::MXiMinus); } // namespace o2::aod diff --git a/PWGLF/TableProducer/Common/kinkBuilder.cxx b/PWGLF/TableProducer/Common/kinkBuilder.cxx index 51be861741a..64605ec9897 100644 --- a/PWGLF/TableProducer/Common/kinkBuilder.cxx +++ b/PWGLF/TableProducer/Common/kinkBuilder.cxx @@ -13,30 +13,31 @@ /// \brief Builder task for kink decay topologies using ITS standalone tracks for the mother /// \author Francesco Mazzaschi -#include -#include -#include -#include -#include +#include "PWGLF/DataModel/LFKinkDecayTables.h" +#include "PWGLF/DataModel/LFParticleIdentification.h" +#include "PWGLF/Utils/svPoolCreator.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.h" -#include "ReconstructionDataFormats/Track.h" +#include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/Centrality.h" -#include "DetectorsBase/Propagator.h" -#include "DetectorsBase/GeometryManager.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DataFormatsParameters/GRPMagField.h" + #include "CCDB/BasicCCDBManager.h" #include "DCAFitter/DCAFitterN.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "DataFormatsParameters/GRPObject.h" +#include "DetectorsBase/GeometryManager.h" +#include "DetectorsBase/Propagator.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" +#include "ReconstructionDataFormats/Track.h" -#include "PWGLF/DataModel/LFParticleIdentification.h" -#include "PWGLF/Utils/svPoolCreator.h" -#include "PWGLF/DataModel/LFKinkDecayTables.h" +#include +#include +#include +#include +#include using namespace o2; using namespace o2::framework; @@ -93,9 +94,12 @@ struct kinkBuilder { kHyperhelium4sigma }; Produces outputDataTable; + Produces outputDataTableUB; + Service ccdb; Configurable hypoMoth{"hypoMoth", kSigmaMinus, "Mother particle hypothesis"}; + Configurable fillDebugTable{"fillDebugTable", false, "If true, fill the debug table with all candidates unbound"}; // Selection criteria Configurable maxDCAMothToPV{"maxDCAMothToPV", 0.1, "Max DCA of the mother to the PV"}; Configurable minDCADaugToPV{"minDCADaugToPV", 0., "Min DCA of the daughter to the PV"}; @@ -430,11 +434,18 @@ struct kinkBuilder { std::sort(kinkCandidates.begin(), kinkCandidates.end(), [](const kinkCandidate& a, const kinkCandidate& b) { return a.collisionID < b.collisionID; }); for (const auto& kinkCand : kinkCandidates) { - 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); + 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); + } } } }; diff --git a/PWGLF/Tasks/Strangeness/sigmaminustask.cxx b/PWGLF/Tasks/Strangeness/sigmaminustask.cxx index 8b309476913..f7332656cb2 100644 --- a/PWGLF/Tasks/Strangeness/sigmaminustask.cxx +++ b/PWGLF/Tasks/Strangeness/sigmaminustask.cxx @@ -13,11 +13,13 @@ /// \brief Example of a simple task for the analysis of the Sigma-minus /// \author Francesco Mazzaschi -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Common/DataModel/EventSelection.h" #include "PWGLF/DataModel/LFKinkDecayTables.h" + +#include "Common/DataModel/EventSelection.h" #include "Common/DataModel/PIDResponse.h" + +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" #include "ReconstructionDataFormats/PID.h" using namespace o2; @@ -26,6 +28,7 @@ using namespace o2::framework::expressions; using TracksFull = soa::Join; using CollisionsFull = soa::Join; +using CollisionsFullMC = soa::Join; struct sigmaminustask { // Histograms are defined with HistogramRegistry @@ -42,18 +45,24 @@ struct sigmaminustask { const AxisSpec ptAxis{50, -10, 10, "#it{p}_{T} (GeV/#it{c})"}; const AxisSpec nSigmaPiAxis{100, -5, 5, "n#sigma_{#pi}"}; const AxisSpec sigmaMassAxis{100, 1.1, 1.4, "m (GeV/#it{c}^{2})"}; + const AxisSpec xiMassAxis{100, 1.2, 1.6, "m_{#Xi} (GeV/#it{c}^{2})"}; + const AxisSpec pdgAxis{10001, -5000, 5000, "PDG code"}; const AxisSpec vertexZAxis{100, -15., 15., "vrtx_{Z} [cm]"}; // Event selection rEventSelection.add("hVertexZRec", "hVertexZRec", {HistType::kTH1F, {vertexZAxis}}); - // Sigma-minus reconstruction rSigmaMinus.add("h2MassSigmaMinusPt", "h2MassSigmaMinusPt", {HistType::kTH2F, {ptAxis, sigmaMassAxis}}); + rSigmaMinus.add("h2SigmaMassVsXiMass", "h2SigmaMassVsXiMass", {HistType::kTH2F, {xiMassAxis, sigmaMassAxis}}); rSigmaMinus.add("h2NSigmaPiPt", "h2NSigmaPiPt", {HistType::kTH2F, {ptAxis, nSigmaPiAxis}}); + + if (doprocessMC) { + // Add MC histograms if needed + rSigmaMinus.add("h2MassSigmaMinusPtMC", "h2MassSigmaMinusPtMC", {HistType::kTH2F, {ptAxis, sigmaMassAxis}}); + } } - void process(soa::Join::iterator const& collision, - aod::KinkCands const& KinkCands, TracksFull const&) + void processData(CollisionsFull::iterator const& collision, aod::KinkCands const& KinkCands, TracksFull const&) { if (std::abs(collision.posZ()) > cutzvertex || !collision.sel8()) { return; @@ -65,9 +74,54 @@ struct sigmaminustask { continue; } rSigmaMinus.fill(HIST("h2MassSigmaMinusPt"), kinkCand.mothSign() * kinkCand.ptMoth(), kinkCand.mSigmaMinus()); + rSigmaMinus.fill(HIST("h2SigmaMassVsXiMass"), kinkCand.mXiMinus(), kinkCand.mSigmaMinus()); rSigmaMinus.fill(HIST("h2NSigmaPiPt"), kinkCand.mothSign() * kinkCand.ptMoth(), dauTrack.tpcNSigmaPi()); } } + PROCESS_SWITCH(sigmaminustask, processData, "Data processing", true); + + void processMC(CollisionsFullMC::iterator const& collision, aod::KinkCands const& KinkCands, aod::McTrackLabels const& trackLabelsMC, aod::McParticles const&, TracksFull const&) + { + if (std::abs(collision.posZ()) > cutzvertex || !collision.sel8()) { + return; + } + rEventSelection.fill(HIST("hVertexZRec"), collision.posZ()); + for (const auto& kinkCand : KinkCands) { + auto dauTrack = kinkCand.trackDaug_as(); + auto mothTrack = kinkCand.trackMoth_as(); + if (dauTrack.sign() != mothTrack.sign()) { + LOG(info) << "Skipping kink candidate with opposite sign daughter and mother: " << kinkCand.globalIndex(); + continue; // Skip if the daughter has the opposite sign as the mother + } + if (abs(dauTrack.tpcNSigmaPi()) > cutNSigmaPi) { + continue; + } + + rSigmaMinus.fill(HIST("h2MassSigmaMinusPt"), kinkCand.mothSign() * kinkCand.ptMoth(), kinkCand.mSigmaMinus()); + rSigmaMinus.fill(HIST("h2SigmaMassVsXiMass"), kinkCand.mXiMinus(), kinkCand.mSigmaMinus()); + rSigmaMinus.fill(HIST("h2NSigmaPiPt"), kinkCand.mothSign() * kinkCand.ptMoth(), dauTrack.tpcNSigmaPi()); + // do MC association + auto mcLabSigma = trackLabelsMC.rawIteratorAt(mothTrack.globalIndex()); + auto mcLabPiDau = trackLabelsMC.rawIteratorAt(dauTrack.globalIndex()); + if (mcLabSigma.has_mcParticle() && mcLabPiDau.has_mcParticle()) { + auto mcTrackSigma = mcLabSigma.mcParticle_as(); + auto mcTrackPiDau = mcLabPiDau.mcParticle_as(); + if (!mcTrackPiDau.has_mothers()) { + continue; + } + for (auto& piMother : mcTrackPiDau.mothers_as()) { + if (piMother.globalIndex() != mcTrackSigma.globalIndex()) { + continue; + } + if (std::abs(mcTrackSigma.pdgCode()) != 3112 || std::abs(mcTrackPiDau.pdgCode()) != 211) { + continue; + } + rSigmaMinus.fill(HIST("h2MassSigmaMinusPtMC"), kinkCand.mothSign() * kinkCand.ptMoth(), kinkCand.mSigmaMinus()); + } + } + } + } + PROCESS_SWITCH(sigmaminustask, processMC, "MC processing", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) From 6c47c04640d365a413b0cb7b8f5aea5869c0f38f Mon Sep 17 00:00:00 2001 From: lauraser <45659867+lauraser@users.noreply.github.com> Date: Fri, 27 Jun 2025 09:34:35 +0200 Subject: [PATCH 231/871] [PWGCF] Updated derived-to-derived producer to include the bitmask check (#11792) Co-authored-by: Laura Serksnyte --- ...toDreamProducerTaskForSpecificAnalysis.cxx | 186 +++++++++++------- 1 file changed, 116 insertions(+), 70 deletions(-) diff --git a/PWGCF/FemtoDream/TableProducer/femtoDreamProducerTaskForSpecificAnalysis.cxx b/PWGCF/FemtoDream/TableProducer/femtoDreamProducerTaskForSpecificAnalysis.cxx index 9e7a30a9719..33f07d2772e 100644 --- a/PWGCF/FemtoDream/TableProducer/femtoDreamProducerTaskForSpecificAnalysis.cxx +++ b/PWGCF/FemtoDream/TableProducer/femtoDreamProducerTaskForSpecificAnalysis.cxx @@ -13,24 +13,24 @@ /// \brief Tasks that reads the track tables and creates track triplets; only three identical particles can be used /// \author Laura Serksnyte, TU München, laura.serksnyte@tum.de -#include -#include +#include "PWGCF/DataModel/FemtoDerived.h" +#include "PWGCF/FemtoDream/Core/femtoDreamContainerThreeBody.h" +#include "PWGCF/FemtoDream/Core/femtoDreamDetaDphiStar.h" +#include "PWGCF/FemtoDream/Core/femtoDreamEventHisto.h" +#include "PWGCF/FemtoDream/Core/femtoDreamPairCleaner.h" +#include "PWGCF/FemtoDream/Core/femtoDreamParticleHisto.h" +#include "PWGCF/FemtoDream/Core/femtoDreamUtils.h" + +#include "Framework/ASoAHelpers.h" #include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" #include "Framework/HistogramRegistry.h" -#include "Framework/ASoAHelpers.h" +#include "Framework/O2DatabasePDGPlugin.h" #include "Framework/RunningWorkflowInfo.h" #include "Framework/StepTHn.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "TDatabasePDG.h" +#include "Framework/runDataProcessing.h" -#include "PWGCF/DataModel/FemtoDerived.h" -#include "PWGCF/FemtoDream/Core/femtoDreamParticleHisto.h" -#include "PWGCF/FemtoDream/Core/femtoDreamEventHisto.h" -#include "PWGCF/FemtoDream/Core/femtoDreamPairCleaner.h" -#include "PWGCF/FemtoDream/Core/femtoDreamContainerThreeBody.h" -#include "PWGCF/FemtoDream/Core/femtoDreamDetaDphiStar.h" -#include "PWGCF/FemtoDream/Core/femtoDreamUtils.h" +#include +#include using namespace o2; using namespace o2::analysis::femtoDream; @@ -38,7 +38,7 @@ using namespace o2::framework; using namespace o2::framework::expressions; using namespace o2::soa; -struct femtoDreamProducerTaskForSpecificAnalysis { +struct FemtoDreamProducerTaskForSpecificAnalysis { SliceCache cache; @@ -49,33 +49,45 @@ struct femtoDreamProducerTaskForSpecificAnalysis { float mMassOne = -999, mMassTwo = -999, mMassThree = -999; int collisions = 0; - Configurable ConfNumberOfTracks{"ConfNumberOfTracks", 3, "Number of tracks"}; - Configurable ConfNumberOfV0{"ConfNumberOfV0", 0, "Number of V0"}; - Configurable ConfNumberOfCascades{"ConfNumberOfCascades", 0, "Number of Cascades"}; + // Require bitmask selection for candidates + Configurable confRequireBitmask{"confRequireBitmask", false, "Require bitmask selection for candidates"}; + + // Number of candidates required + Configurable confNumberOfTracks{"confNumberOfTracks", 3, "Number of tracks"}; + Configurable confNumberOfV0{"confNumberOfV0", 0, "Number of V0"}; + Configurable confNumberOfCascades{"confNumberOfCascades", 0, "Number of Cascades"}; /// Track selection - Configurable ConfPIDthrMom{"ConfPIDthrMom", 1.f, "Momentum threshold from which TPC and TOF are required for PID"}; - Configurable ConfTPCPIDBit{"ConfTPCPIDBit", 16, "PID TPC bit from cutCulator "}; - Configurable ConfTPCTOFPIDBit{"ConfTPCTOFPIDBit", 8, "PID TPCTOF bit from cutCulator"}; + Configurable confPIDthrMom{"confPIDthrMom", 1.f, "Momentum threshold from which TPC and TOF are required for PID"}; + Configurable confTPCPIDBit{"confTPCPIDBit", 16, "PID TPC bit from cutCulator "}; + Configurable confTPCTOFPIDBit{"confTPCTOFPIDBit", 8, "PID TPCTOF bit from cutCulator"}; + Configurable confCutPart{"confCutPart", 0, "Track - Selection bit from cutCulator for part"}; + Configurable confCutPartAntiPart{"confCutPartAntiPart", 0, "Track - Selection bit from cutCulator for antipart"}; /// Partition for selected particles - Partition SelectedParts = (aod::femtodreamparticle::partType == uint8_t(aod::femtodreamparticle::ParticleType::kTrack)) && - ifnode(aod::femtodreamparticle::pt * (nexp(aod::femtodreamparticle::eta) + nexp(-1.f * aod::femtodreamparticle::eta)) / 2.f <= ConfPIDthrMom, ncheckbit(aod::femtodreamparticle::pidcut, ConfTPCPIDBit), ncheckbit(aod::femtodreamparticle::pidcut, ConfTPCTOFPIDBit)); + Partition selectedParts = (aod::femtodreamparticle::partType == uint8_t(aod::femtodreamparticle::ParticleType::kTrack)) && + ifnode(aod::femtodreamparticle::pt * (nexp(aod::femtodreamparticle::eta) + nexp(-1.f * aod::femtodreamparticle::eta)) / 2.f <= confPIDthrMom, ncheckbit(aod::femtodreamparticle::pidcut, confTPCPIDBit), ncheckbit(aod::femtodreamparticle::pidcut, confTPCTOFPIDBit)); /// V0 selection - Configurable Conf_minInvMass_V0{"Conf_minInvMass_V0", 1.08, "Minimum invariant mass of V0 (particle)"}; - Configurable Conf_maxInvMass_V0{"Conf_maxInvMass_V0", 1.15, "Maximum invariant mass of V0 (particle)"}; - Configurable Conf_minInvMassAnti_V0{"Conf_minInvMassAnti_V0", 1.08, "Minimum invariant mass of V0 (antiparticle)"}; - Configurable Conf_maxInvMassAnti_V0{"Conf_maxInvMassAnti_V0", 1.15, "Maximum invariant mass of V0 (antiparticle)"}; + Configurable confMinInvMassV0{"confMinInvMassV0", 1.08, "Minimum invariant mass of V0 (particle)"}; + Configurable confMaxInvMassV0{"confMaxInvMassV0", 1.15, "Maximum invariant mass of V0 (particle)"}; + Configurable confMinInvMassAntiV0{"confMinInvMassAntiV0", 1.08, "Minimum invariant mass of V0 (antiparticle)"}; + Configurable confMaxInvMassAntiV0{"confMaxInvMassAntiV0", 1.15, "Maximum invariant mass of V0 (antiparticle)"}; + Configurable confCutV0SameForAntipart{"confCutV0SameForAntipart", 0, "V0 - Selection bit from cutCulator for part/antipart"}; + Configurable confChildPosCutV0{"confChildPosCutV0", 149, "Selection bit for positive child of V0"}; + Configurable confChildPosTPCBitV0{"confChildPosTPCBitV0", 2, "PID TPC bit for positive child of V0"}; + Configurable confChildNegCutV0{"confChildNegCutV0", 149, "Selection bit for negative child of V0"}; + Configurable confChildNegTPCBitV0{"confChildNegTPCBitV0", 2, "PID TPC bit for negative child of V0"}; + /// Cascade selection - Configurable Conf_minInvMass_Cascade{"Conf_minInvMass_Cascade", 1.2, "Minimum invariant mass of Cascade (particle)"}; - Configurable Conf_maxInvMass_Cascade{"Conf_maxInvMass_Cascade", 1.5, "Maximum invariant mass of Cascade (particle)"}; + Configurable confMinInvMassCascade{"confMinInvMassCascade", 1.2, "Minimum invariant mass of Cascade (particle)"}; + Configurable confMaxInvMassCascade{"confMaxInvMassCascade", 1.5, "Maximum invariant mass of Cascade (particle)"}; // Partition for selected particles - Partition SelectedV0s = (aod::femtodreamparticle::partType == uint8_t(aod::femtodreamparticle::ParticleType::kV0)); - Partition SelectedCascades = (aod::femtodreamparticle::partType == uint8_t(aod::femtodreamparticle::ParticleType::kCascade)); + Partition selectedV0s = (aod::femtodreamparticle::partType == uint8_t(aod::femtodreamparticle::ParticleType::kV0)); + Partition selectedCascades = (aod::femtodreamparticle::partType == uint8_t(aod::femtodreamparticle::ParticleType::kCascade)); - HistogramRegistry EventRegistry{"EventRegistry", {}, OutputObjHandlingPolicy::AnalysisObject}; + HistogramRegistry eventRegistry{"eventRegistry", {}, OutputObjHandlingPolicy::AnalysisObject}; static constexpr uint32_t kSignPlusMask = 1 << 1; @@ -94,9 +106,13 @@ struct femtoDreamProducerTaskForSpecificAnalysis { void init(InitContext&) { - EventRegistry.add("hStatistiscs", ";bin;Entries", kTH1F, {{3, 0, 3}}); - // get bit for the collision mask + eventRegistry.add("hStatistiscs", ";bin;Entries", kTH1F, {{3, 0, 3}}); + // Never run V0s and Cascades together as this will DOUBLE the track number and induce self correlations + if ((doprocessCollisionsWithNTracksAndNCascades && doprocessCollisionsWithNTracksAndNV0)) { + LOG(fatal) << "Never run V0s and Cascades together as this will DOUBLE the track number and induce self correlations!"; + } } + /// This function stores accepted collisions in derived data /// @tparam PartitionType /// @tparam PartType @@ -105,36 +121,66 @@ struct femtoDreamProducerTaskForSpecificAnalysis { /// @param groupSelectedV0s partition for the second particle passed by the process function /// @param parts femtoDreamParticles table template - void createSpecifiedDerivedData(o2::aod::FDCollision& col, PartitionType groupSelectedTracks, PartitionType groupSelectedV0s, PartType parts) + void createSpecifiedDerivedData(const o2::aod::FDCollision& col, PartitionType groupSelectedTracks, PartitionType groupSelectedV0s, PartType parts) { /// check tracks int tracksCount = 0; int antitracksCount = 0; - for (auto& part : groupSelectedTracks) { + for (const auto& part : groupSelectedTracks) { if (part.cut() & 1) { - antitracksCount++; + if (!confRequireBitmask || ncheckbit(part.cut(), confCutPartAntiPart)) { + antitracksCount++; + } } else { - tracksCount++; + if (!confRequireBitmask || ncheckbit(part.cut(), confCutPart)) { + tracksCount++; + } } } /// check V0s - int V0Count = 0; + int v0Count = 0; int antiV0Count = 0; - for (auto& V0 : groupSelectedV0s) { - if ((V0.mLambda() > Conf_minInvMass_V0) && (V0.mLambda() < Conf_maxInvMass_V0)) { - V0Count++; - } else if ((V0.mAntiLambda() > Conf_minInvMassAnti_V0) && (V0.mAntiLambda() < Conf_maxInvMassAnti_V0)) { - antiV0Count++; + for (const auto& V0 : groupSelectedV0s) { + if ((V0.mLambda() > confMinInvMassV0) && (V0.mLambda() < confMaxInvMassV0)) { + if (confRequireBitmask) { + if (ncheckbit(V0.cut(), confCutV0SameForAntipart)) { + const auto& posChild = parts.iteratorAt(V0.index() - 2); + const auto& negChild = parts.iteratorAt(V0.index() - 1); + if (((posChild.cut() & confChildPosCutV0) == confChildPosCutV0 && + (posChild.pidcut() & confChildPosTPCBitV0) == confChildPosTPCBitV0 && + (negChild.cut() & confChildNegCutV0) == confChildNegCutV0 && + (negChild.pidcut() & confChildNegTPCBitV0) == confChildNegTPCBitV0)) { + v0Count++; + } + } + } else { + v0Count++; + } + } else if ((V0.mAntiLambda() > confMinInvMassAntiV0) && (V0.mAntiLambda() < confMaxInvMassAntiV0)) { + if (confRequireBitmask) { + if (ncheckbit(V0.cut(), confCutV0SameForAntipart)) { + const auto& posChild = parts.iteratorAt(V0.index() - 2); + const auto& negChild = parts.iteratorAt(V0.index() - 1); + if (((posChild.cut() & confChildPosCutV0) == confChildPosCutV0 && + (posChild.pidcut() & confChildNegTPCBitV0) == confChildNegTPCBitV0 && // exchanged values because checking antiparticle daughters and pid of particles exchange + (negChild.cut() & confChildNegCutV0) == confChildNegCutV0 && + (negChild.pidcut() & confChildPosTPCBitV0) == confChildPosTPCBitV0)) { // exchanged values because checking antiparticle daughters and pid of particles exchange + antiV0Count++; + } + } + } else { + antiV0Count++; + } } } std::vector tmpIDtrack; - if ((V0Count >= ConfNumberOfV0 && tracksCount >= ConfNumberOfTracks) || (antiV0Count >= ConfNumberOfV0 && antitracksCount >= ConfNumberOfTracks)) { - EventRegistry.fill(HIST("hStatistiscs"), 1); + if ((v0Count >= confNumberOfV0 && tracksCount >= confNumberOfTracks) || (antiV0Count >= confNumberOfV0 && antitracksCount >= confNumberOfTracks)) { + eventRegistry.fill(HIST("hStatistiscs"), 1); outputCollision(col.posZ(), col.multV0M(), col.multNtr(), col.sphericity(), col.magField()); - for (auto& femtoParticle : parts) { + for (const auto& femtoParticle : parts) { if (aod::femtodreamparticle::ParticleType::kTrack == femtoParticle.partType()) { std::vector childIDs = {0, 0}; outputParts(outputCollision.lastIndex(), @@ -190,23 +236,23 @@ struct femtoDreamProducerTaskForSpecificAnalysis { } } } else { - EventRegistry.fill(HIST("hStatistiscs"), 2); + eventRegistry.fill(HIST("hStatistiscs"), 2); } } /// process function to create derived data with only collisions containing n tracks /// \param col subscribe to the collision table (Data) /// \param parts subscribe to the femtoDreamParticleTable - void processCollisionsWithNTracksAndNV0(o2::aod::FDCollision& col, - o2::aod::FDParticles& parts) + void processCollisionsWithNTracksAndNV0(const o2::aod::FDCollision& col, + const o2::aod::FDParticles& parts) { - EventRegistry.fill(HIST("hStatistiscs"), 0); - auto thegroupSelectedParts = SelectedParts->sliceByCached(aod::femtodreamparticle::fdCollisionId, col.globalIndex(), cache); - auto thegroupSelectedV0s = SelectedV0s->sliceByCached(aod::femtodreamparticle::fdCollisionId, col.globalIndex(), cache); + eventRegistry.fill(HIST("hStatistiscs"), 0); + auto thegroupSelectedParts = selectedParts->sliceByCached(aod::femtodreamparticle::fdCollisionId, col.globalIndex(), cache); + auto thegroupSelectedV0s = selectedV0s->sliceByCached(aod::femtodreamparticle::fdCollisionId, col.globalIndex(), cache); createSpecifiedDerivedData(col, thegroupSelectedParts, thegroupSelectedV0s, parts); } - PROCESS_SWITCH(femtoDreamProducerTaskForSpecificAnalysis, processCollisionsWithNTracksAndNV0, "Enable producing data with ppp collisions for data", true); + PROCESS_SWITCH(FemtoDreamProducerTaskForSpecificAnalysis, processCollisionsWithNTracksAndNV0, "Enable producing data with ppp collisions for data", true); /// This function stores accepted collisions in derived data /// @tparam PartitionType @@ -216,13 +262,13 @@ struct femtoDreamProducerTaskForSpecificAnalysis { /// @param groupSelectedV0s partition for the second particle passed by the process function /// @param parts femtoDreamParticles table template - void createSpecifiedDerivedData_TrkCascade(o2::aod::FDCollision& col, PartitionType groupSelectedTracks, PartitionType groupSelectedCascades, PartType parts) + void createSpecifiedDerivedDataTrkCascade(const o2::aod::FDCollision& col, PartitionType groupSelectedTracks, PartitionType groupSelectedCascades, PartType parts) { /// check tracks int tracksCount = 0; int antitracksCount = 0; - for (auto& part : groupSelectedTracks) { + for (const auto& part : groupSelectedTracks) { if (part.cut() & 1) { antitracksCount++; } else { @@ -231,11 +277,11 @@ struct femtoDreamProducerTaskForSpecificAnalysis { } /// check Cascades - int CascadeCount = 0; + int ascadeCount = 0; int antiCascadeCount = 0; - for (auto& casc : groupSelectedCascades) { + for (const auto& casc : groupSelectedCascades) { if ((casc.cut() & kSignPlusMask) == kSignPlusMask) { - CascadeCount++; + ascadeCount++; } else { antiCascadeCount++; } @@ -243,11 +289,11 @@ struct femtoDreamProducerTaskForSpecificAnalysis { std::vector tmpIDtrack; - if ((CascadeCount >= ConfNumberOfCascades && tracksCount >= ConfNumberOfTracks) || (antiCascadeCount >= ConfNumberOfCascades && antitracksCount >= ConfNumberOfTracks)) { - EventRegistry.fill(HIST("hStatistiscs"), 1); + if ((ascadeCount >= confNumberOfCascades && tracksCount >= confNumberOfTracks) || (antiCascadeCount >= confNumberOfCascades && antitracksCount >= confNumberOfTracks)) { + eventRegistry.fill(HIST("hStatistiscs"), 1); outputCollision(col.posZ(), col.multV0M(), col.multNtr(), col.sphericity(), col.magField()); - for (auto& femtoParticle : parts) { + for (const auto& femtoParticle : parts) { if (aod::femtodreamparticle::ParticleType::kTrack == femtoParticle.partType()) { std::vector childIDs = {0, 0}; outputParts(outputCollision.lastIndex(), @@ -323,29 +369,29 @@ struct femtoDreamProducerTaskForSpecificAnalysis { } } } else { - EventRegistry.fill(HIST("hStatistiscs"), 2); + eventRegistry.fill(HIST("hStatistiscs"), 2); } } /// process function to create derived data with only collisions containing n tracks /// \param col subscribe to the collision table (Data) /// \param parts subscribe to the femtoDreamParticleTable - void processCollisionsWithNTracksAndNCascades(o2::aod::FDCollision& col, - o2::aod::FDParticles& parts) + void processCollisionsWithNTracksAndNCascades(const o2::aod::FDCollision& col, + const o2::aod::FDParticles& parts) { - EventRegistry.fill(HIST("hStatistiscs"), 0); - auto thegroupSelectedParts = SelectedParts->sliceByCached(aod::femtodreamparticle::fdCollisionId, col.globalIndex(), cache); - auto thegroupSelectedCascades = SelectedCascades->sliceByCached(aod::femtodreamparticle::fdCollisionId, col.globalIndex(), cache); + eventRegistry.fill(HIST("hStatistiscs"), 0); + auto thegroupSelectedParts = selectedParts->sliceByCached(aod::femtodreamparticle::fdCollisionId, col.globalIndex(), cache); + auto thegroupSelectedCascades = selectedCascades->sliceByCached(aod::femtodreamparticle::fdCollisionId, col.globalIndex(), cache); - createSpecifiedDerivedData_TrkCascade(col, thegroupSelectedParts, thegroupSelectedCascades, parts); + createSpecifiedDerivedDataTrkCascade(col, thegroupSelectedParts, thegroupSelectedCascades, parts); } - PROCESS_SWITCH(femtoDreamProducerTaskForSpecificAnalysis, processCollisionsWithNTracksAndNCascades, "Enable producing data with tracks and Cascades collisions for data", true); + PROCESS_SWITCH(FemtoDreamProducerTaskForSpecificAnalysis, processCollisionsWithNTracksAndNCascades, "Enable producing data with tracks and Cascades collisions for data", true); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { WorkflowSpec workflow{ - adaptAnalysisTask(cfgc), + adaptAnalysisTask(cfgc), }; return workflow; } From 5e04fa888e3f5df67d9f066bbe03a9dfad56e8e8 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: Fri, 27 Jun 2025 10:16:39 +0200 Subject: [PATCH 232/871] [PWGHF] Add UPC event selection (#11518) Co-authored-by: ALICE Action Bot --- PWGHF/D2H/DataModel/ReducedDataModel.h | 2 +- .../dataCreatorCharmHadPiReduced.cxx | 2 +- .../dataCreatorCharmResoReduced.cxx | 2 +- PWGHF/D2H/Tasks/taskFlowCharmHadrons.cxx | 8 +- .../DataModel/CandidateReconstructionTables.h | 3 +- PWGHF/TableProducer/CMakeLists.txt | 6 +- .../TableProducer/candidateCreator2Prong.cxx | 153 ++++++++++++++--- .../TableProducer/candidateCreator3Prong.cxx | 155 +++++++++++++++--- PWGHF/TableProducer/trackIndexSkimCreator.cxx | 69 +++++--- PWGHF/Utils/utilsEvSelHf.h | 93 ++++++++--- 10 files changed, 388 insertions(+), 105 deletions(-) diff --git a/PWGHF/D2H/DataModel/ReducedDataModel.h b/PWGHF/D2H/DataModel/ReducedDataModel.h index 02cab44cb2b..10e997f7ed4 100644 --- a/PWGHF/D2H/DataModel/ReducedDataModel.h +++ b/PWGHF/D2H/DataModel/ReducedDataModel.h @@ -50,7 +50,7 @@ namespace aod namespace hf_reduced_collision { DECLARE_SOA_COLUMN(Bz, bz, float); //! Magnetic field in z-direction -DECLARE_SOA_COLUMN(HfCollisionRejectionMap, hfCollisionRejectionMap, uint16_t); //! Bitmask with failed selection criteria +DECLARE_SOA_COLUMN(HfCollisionRejectionMap, hfCollisionRejectionMap, uint32_t); //! Bitmask with failed selection criteria // keep track of the number of studied events (for normalization purposes) DECLARE_SOA_COLUMN(OriginalCollisionCount, originalCollisionCount, int); //! Size of COLLISION table processed DECLARE_SOA_COLUMN(ZvtxSelectedCollisionCount, zvtxSelectedCollisionCount, int); //! Number of COLLISIONS with |zvtx| < zvtxMax diff --git a/PWGHF/D2H/TableProducer/dataCreatorCharmHadPiReduced.cxx b/PWGHF/D2H/TableProducer/dataCreatorCharmHadPiReduced.cxx index fde8c3b553e..5470de035b0 100644 --- a/PWGHF/D2H/TableProducer/dataCreatorCharmHadPiReduced.cxx +++ b/PWGHF/D2H/TableProducer/dataCreatorCharmHadPiReduced.cxx @@ -1258,7 +1258,7 @@ struct HfDataCreatorCharmHadPiReduced { } registry.fill(HIST("hEvents"), 1 + Event::CharmHadPiSelected); float centrality = -1.f; - uint16_t hfRejMap = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb, registry); + uint32_t hfRejMap = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb, registry); // fill collision table if it contains a DPi pair a minima hfReducedCollision(collision.posX(), collision.posY(), collision.posZ(), collision.numContrib(), hfRejMap, bz); hfReducedCollExtra(collision.covXX(), collision.covXY(), collision.covYY(), diff --git a/PWGHF/D2H/TableProducer/dataCreatorCharmResoReduced.cxx b/PWGHF/D2H/TableProducer/dataCreatorCharmResoReduced.cxx index a424d95d95b..36deb224116 100644 --- a/PWGHF/D2H/TableProducer/dataCreatorCharmResoReduced.cxx +++ b/PWGHF/D2H/TableProducer/dataCreatorCharmResoReduced.cxx @@ -1307,7 +1307,7 @@ struct HfDataCreatorCharmResoReduced { } registry.fill(HIST("hEvents"), 1 + Event::DV0Selected); float centrality = -1.f; - uint16_t hfRejMap = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb, registry); + uint32_t hfRejMap = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb, registry); // fill collision table if it contains a DPi pair a minima hfReducedCollision(collision.posX(), collision.posY(), collision.posZ(), collision.numContrib(), hfRejMap, bz); } // end of runDataCreation function diff --git a/PWGHF/D2H/Tasks/taskFlowCharmHadrons.cxx b/PWGHF/D2H/Tasks/taskFlowCharmHadrons.cxx index 6a090bfd2ed..65608d34ffe 100644 --- a/PWGHF/D2H/Tasks/taskFlowCharmHadrons.cxx +++ b/PWGHF/D2H/Tasks/taskFlowCharmHadrons.cxx @@ -343,7 +343,7 @@ struct HfTaskFlowCharmHadrons { /// Get the event selection flags /// \param hfevselflag is the event selection flag - std::vector getEventSelectionFlags(uint16_t hfevselflag) + std::vector getEventSelectionFlags(uint32_t hfevselflag) { return { TESTBIT(hfevselflag, o2::hf_evsel::EventRejection::NoSameBunchPileup), @@ -373,7 +373,7 @@ struct HfTaskFlowCharmHadrons { float& sp, std::vector& outputMl, float& occupancy, - uint16_t& hfevselflag) + uint32_t& hfevselflag) { if (occEstimator != 0) { std::vector evtSelFlags = getEventSelectionFlags(hfevselflag); @@ -491,7 +491,7 @@ struct HfTaskFlowCharmHadrons { return; } float occupancy = 0.; - uint16_t hfevflag{}; + uint32_t hfevflag{}; if (occEstimator != 0) { occupancy = getOccupancyColl(collision, occEstimator); registry.fill(HIST("trackOccVsFT0COcc"), collision.trackOccupancyInTimeRange(), collision.ft0cOccupancyInTimeRange()); @@ -784,7 +784,7 @@ struct HfTaskFlowCharmHadrons { float occupancy{-1.f}; occupancy = getOccupancyColl(collision, occEstimator); registry.fill(HIST("trackOccVsFT0COcc"), collision.trackOccupancyInTimeRange(), collision.ft0cOccupancyInTimeRange()); - uint16_t hfevflag = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb, registry); + uint32_t hfevflag = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb, registry); std::vector evtSelFlags = getEventSelectionFlags(hfevflag); registry.fill(HIST("spReso/hSparseReso"), centrality, xQVecFT0c * xQVecFV0a + yQVecFT0c * yQVecFV0a, xQVecFT0c * xQVecBTot + yQVecFT0c * yQVecBTot, diff --git a/PWGHF/DataModel/CandidateReconstructionTables.h b/PWGHF/DataModel/CandidateReconstructionTables.h index fd296e328f6..dd6f2f53367 100644 --- a/PWGHF/DataModel/CandidateReconstructionTables.h +++ b/PWGHF/DataModel/CandidateReconstructionTables.h @@ -39,6 +39,7 @@ namespace o2::aod { // Table aliases +using BcFullInfos = soa::Join; using TracksWCov = soa::Join; using TracksWDca = soa::Join; @@ -191,7 +192,7 @@ DECLARE_SOA_TABLE(PidTpcTofTinyPr, "AOD", "PIDTPCTOFTINYPR", //! Table of the TP namespace hf_sel_collision { -DECLARE_SOA_COLUMN(WhyRejectColl, whyRejectColl, uint16_t); //! +DECLARE_SOA_COLUMN(WhyRejectColl, whyRejectColl, uint32_t); //! } // namespace hf_sel_collision DECLARE_SOA_TABLE(HfSelCollision, "AOD", "HFSELCOLLISION", //! diff --git a/PWGHF/TableProducer/CMakeLists.txt b/PWGHF/TableProducer/CMakeLists.txt index 2ec33b5d134..aa94cea8c22 100644 --- a/PWGHF/TableProducer/CMakeLists.txt +++ b/PWGHF/TableProducer/CMakeLists.txt @@ -13,7 +13,7 @@ o2physics_add_dpl_workflow(track-index-skim-creator SOURCES trackIndexSkimCreator.cxx - PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::DetectorsVertexing O2::DCAFitter O2Physics::AnalysisCCDB O2Physics::MLCore O2Physics::EventFilteringUtils + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::DetectorsVertexing O2::DCAFitter O2Physics::AnalysisCCDB O2Physics::MLCore O2Physics::EventFilteringUtils O2Physics::SGCutParHolder COMPONENT_NAME Analysis) # Helpers @@ -37,12 +37,12 @@ o2physics_add_dpl_workflow(mc-pid-tof o2physics_add_dpl_workflow(candidate-creator-2prong SOURCES candidateCreator2Prong.cxx - PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::DCAFitter KFParticle::KFParticle O2Physics::EventFilteringUtils + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::DCAFitter KFParticle::KFParticle O2Physics::EventFilteringUtils O2Physics::SGCutParHolder COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(candidate-creator-3prong SOURCES candidateCreator3Prong.cxx - PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::DCAFitter KFParticle::KFParticle O2Physics::EventFilteringUtils + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::DCAFitter KFParticle::KFParticle O2Physics::EventFilteringUtils O2Physics::SGCutParHolder COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(candidate-creator-b0 diff --git a/PWGHF/TableProducer/candidateCreator2Prong.cxx b/PWGHF/TableProducer/candidateCreator2Prong.cxx index 7396a0b6f0f..851fa76c33d 100644 --- a/PWGHF/TableProducer/candidateCreator2Prong.cxx +++ b/PWGHF/TableProducer/candidateCreator2Prong.cxx @@ -112,18 +112,20 @@ struct HfCandidateCreator2Prong { void init(InitContext const&) { - std::array doprocessDF{doprocessPvRefitWithDCAFitterN, doprocessNoPvRefitWithDCAFitterN, + std::array doprocessDF{doprocessPvRefitWithDCAFitterN, doprocessNoPvRefitWithDCAFitterN, doprocessPvRefitWithDCAFitterNCentFT0C, doprocessNoPvRefitWithDCAFitterNCentFT0C, - doprocessPvRefitWithDCAFitterNCentFT0M, doprocessNoPvRefitWithDCAFitterNCentFT0M}; - std::array doprocessKF{doprocessPvRefitWithKFParticle, doprocessNoPvRefitWithKFParticle, + doprocessPvRefitWithDCAFitterNCentFT0M, doprocessNoPvRefitWithDCAFitterNCentFT0M, doprocessPvRefitWithDCAFitterNUpc, doprocessNoPvRefitWithDCAFitterNUpc}; + std::array doprocessKF{doprocessPvRefitWithKFParticle, doprocessNoPvRefitWithKFParticle, doprocessPvRefitWithKFParticleCentFT0C, doprocessNoPvRefitWithKFParticleCentFT0C, - doprocessPvRefitWithKFParticleCentFT0M, doprocessNoPvRefitWithKFParticleCentFT0M}; + doprocessPvRefitWithKFParticleCentFT0M, doprocessNoPvRefitWithKFParticleCentFT0M, doprocessPvRefitWithKFParticleUpc, doprocessNoPvRefitWithKFParticleUpc}; if ((std::accumulate(doprocessDF.begin(), doprocessDF.end(), 0) + std::accumulate(doprocessKF.begin(), doprocessKF.end(), 0)) != 1) { LOGP(fatal, "One and only one process function must be enabled at a time."); } - std::array processesCollisions = {doprocessCollisions, doprocessCollisionsCentFT0C, doprocessCollisionsCentFT0M}; + std::array processesCollisions = {doprocessCollisions, doprocessCollisionsCentFT0C, doprocessCollisionsCentFT0M, doprocessCollisionsUpc}; const int nProcessesCollisions = std::accumulate(processesCollisions.begin(), processesCollisions.end(), 0); + std::array processesUpc = {doprocessPvRefitWithDCAFitterNUpc, doprocessNoPvRefitWithDCAFitterNUpc, doprocessPvRefitWithKFParticleUpc, doprocessNoPvRefitWithKFParticleUpc, doprocessCollisionsUpc}; + const int nProcessesUpc = std::accumulate(processesUpc.begin(), processesUpc.end(), 0); if (nProcessesCollisions > 1) { LOGP(fatal, "At most one process function for collision monitoring can be enabled at a time."); } @@ -137,6 +139,12 @@ struct HfCandidateCreator2Prong { if ((doprocessPvRefitWithDCAFitterNCentFT0M || doprocessNoPvRefitWithDCAFitterNCentFT0M || doprocessPvRefitWithKFParticleCentFT0M || doprocessNoPvRefitWithKFParticleCentFT0M) && !doprocessCollisionsCentFT0M) { LOGP(fatal, "Process function for collision monitoring not correctly enabled. Did you enable \"processCollisionsCentFT0M\"?"); } + if ((doprocessPvRefitWithDCAFitterNUpc || doprocessNoPvRefitWithDCAFitterNUpc || doprocessPvRefitWithKFParticleUpc || doprocessNoPvRefitWithKFParticleUpc) && !doprocessCollisionsUpc) { + LOGP(fatal, "Process function for collision monitoring not correctly enabled. Did you enable \"processCollisionsUpc\"?"); + } + } + if (nProcessesUpc > 0 && isRun2) { + LOGP(fatal, "Process function for UPC is only available in Run 3!"); } // histograms @@ -185,11 +193,11 @@ struct HfCandidateCreator2Prong { setLabelHistoCands(hCandidates); } - template + template void runCreator2ProngWithDCAFitterN(Coll const&, CandType const& rowsTrackIndexProng2, TTracks const&, - aod::BCsWithTimestamps const& /*bcWithTimeStamps*/) + BCsType const& bcs) { // loop over pairs of track indices for (const auto& rowTrackIndexProng2 : rowsTrackIndexProng2) { @@ -197,7 +205,12 @@ struct HfCandidateCreator2Prong { /// reject candidates not satisfying the event selections auto collision = rowTrackIndexProng2.template collision_as(); float centrality{-1.f}; - const auto rejectionMask = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb, registry); + uint32_t rejectionMask{0}; + if constexpr (applyUpcSel) { + rejectionMask = hfEvSel.getHfCollisionRejectionMaskWithUpc(collision, centrality, ccdb, registry, bcs); + } else { + rejectionMask = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb, registry); + } if (rejectionMask != 0) { /// at least one event selection not satisfied --> reject the candidate continue; @@ -211,7 +224,7 @@ struct HfCandidateCreator2Prong { /// Set the magnetic field from ccdb. /// The static instance of the propagator was already modified in the HFTrackIndexSkimCreator, /// but this is not true when running on Run2 data/MC already converted into AO2Ds. - auto bc = collision.template bc_as(); + auto bc = collision.template bc_as(); if (runNumber != bc.runNumber()) { LOG(info) << ">>>>>>>>>>>> Current run number: " << runNumber; initCCDB(bc, runNumber, ccdb, isRun2 ? ccdbPathGrp : ccdbPathGrpMag, nullptr, isRun2); @@ -333,11 +346,11 @@ struct HfCandidateCreator2Prong { } } - template + template void runCreator2ProngWithKFParticle(Coll const&, CandType const& rowsTrackIndexProng2, TTracks const&, - aod::BCsWithTimestamps const& /*bcWithTimeStamps*/) + BCsType const& bcs) { for (const auto& rowTrackIndexProng2 : rowsTrackIndexProng2) { @@ -345,7 +358,12 @@ struct HfCandidateCreator2Prong { /// reject candidates in collisions not satisfying the event selections auto collision = rowTrackIndexProng2.template collision_as(); float centrality{-1.f}; - const auto rejectionMask = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb, registry); + uint32_t rejectionMask{0}; + if constexpr (applyUpcSel) { + rejectionMask = hfEvSel.getHfCollisionRejectionMaskWithUpc(collision, centrality, ccdb, registry, bcs); + } else { + rejectionMask = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb, registry); + } if (rejectionMask != 0) { /// at least one event selection not satisfied --> reject the candidate continue; @@ -357,7 +375,7 @@ struct HfCandidateCreator2Prong { /// Set the magnetic field from ccdb. /// The static instance of the propagator was already modified in the HFTrackIndexSkimCreator, /// but this is not true when running on Run2 data/MC already converted into AO2Ds. - auto bc = collision.template bc_as(); + auto bc = collision.template bc_as(); if (runNumber != bc.runNumber()) { LOG(info) << ">>>>>>>>>>>> Current run number: " << runNumber; initCCDB(bc, runNumber, ccdb, isRun2 ? ccdbPathGrp : ccdbPathGrpMag, nullptr, isRun2); @@ -497,7 +515,7 @@ struct HfCandidateCreator2Prong { TracksWCovExtraPidPiKa const& tracks, aod::BCsWithTimestamps const& bcWithTimeStamps) { - runCreator2ProngWithDCAFitterN(collisions, rowsTrackIndexProng2, tracks, bcWithTimeStamps); + runCreator2ProngWithDCAFitterN(collisions, rowsTrackIndexProng2, tracks, bcWithTimeStamps); } PROCESS_SWITCH(HfCandidateCreator2Prong, processPvRefitWithDCAFitterN, "Run candidate creator using DCA fitter w/ PV refit and w/o centrality selections", false); @@ -507,7 +525,7 @@ struct HfCandidateCreator2Prong { TracksWCovExtraPidPiKa const& tracks, aod::BCsWithTimestamps const& bcWithTimeStamps) { - runCreator2ProngWithDCAFitterN(collisions, rowsTrackIndexProng2, tracks, bcWithTimeStamps); + runCreator2ProngWithDCAFitterN(collisions, rowsTrackIndexProng2, tracks, bcWithTimeStamps); } PROCESS_SWITCH(HfCandidateCreator2Prong, processNoPvRefitWithDCAFitterN, "Run candidate creator using DCA fitter w/o PV refit and w/o centrality selections", true); @@ -517,7 +535,7 @@ struct HfCandidateCreator2Prong { TracksWCovExtraPidPiKa const& tracks, aod::BCsWithTimestamps const& bcWithTimeStamps) { - runCreator2ProngWithKFParticle(collisions, rowsTrackIndexProng2, tracks, bcWithTimeStamps); + runCreator2ProngWithKFParticle(collisions, rowsTrackIndexProng2, tracks, bcWithTimeStamps); } PROCESS_SWITCH(HfCandidateCreator2Prong, processPvRefitWithKFParticle, "Run candidate creator using KFParticle package w/ PV refit and w/o centrality selections", false); @@ -527,7 +545,7 @@ struct HfCandidateCreator2Prong { TracksWCovExtraPidPiKa const& tracks, aod::BCsWithTimestamps const& bcWithTimeStamps) { - runCreator2ProngWithKFParticle(collisions, rowsTrackIndexProng2, tracks, bcWithTimeStamps); + runCreator2ProngWithKFParticle(collisions, rowsTrackIndexProng2, tracks, bcWithTimeStamps); } PROCESS_SWITCH(HfCandidateCreator2Prong, processNoPvRefitWithKFParticle, "Run candidate creator using KFParticle package w/o PV refit and w/o centrality selections", false); @@ -543,7 +561,7 @@ struct HfCandidateCreator2Prong { TracksWCovExtraPidPiKa const& tracks, aod::BCsWithTimestamps const& bcWithTimeStamps) { - runCreator2ProngWithDCAFitterN(collisions, rowsTrackIndexProng2, tracks, bcWithTimeStamps); + runCreator2ProngWithDCAFitterN(collisions, rowsTrackIndexProng2, tracks, bcWithTimeStamps); } PROCESS_SWITCH(HfCandidateCreator2Prong, processPvRefitWithDCAFitterNCentFT0C, "Run candidate creator using DCA fitter w/ PV refit and w/ centrality selection on FT0C", false); @@ -553,7 +571,7 @@ struct HfCandidateCreator2Prong { TracksWCovExtraPidPiKa const& tracks, aod::BCsWithTimestamps const& bcWithTimeStamps) { - runCreator2ProngWithDCAFitterN(collisions, rowsTrackIndexProng2, tracks, bcWithTimeStamps); + runCreator2ProngWithDCAFitterN(collisions, rowsTrackIndexProng2, tracks, bcWithTimeStamps); } PROCESS_SWITCH(HfCandidateCreator2Prong, processNoPvRefitWithDCAFitterNCentFT0C, "Run candidate creator using DCA fitter w/o PV refit and w/ centrality selection FT0C", false); @@ -563,7 +581,7 @@ struct HfCandidateCreator2Prong { TracksWCovExtraPidPiKa const& tracks, aod::BCsWithTimestamps const& bcWithTimeStamps) { - runCreator2ProngWithKFParticle(collisions, rowsTrackIndexProng2, tracks, bcWithTimeStamps); + runCreator2ProngWithKFParticle(collisions, rowsTrackIndexProng2, tracks, bcWithTimeStamps); } PROCESS_SWITCH(HfCandidateCreator2Prong, processPvRefitWithKFParticleCentFT0C, "Run candidate creator using KFParticle package w/ PV refit and w/ centrality selection on FT0C", false); @@ -573,7 +591,7 @@ struct HfCandidateCreator2Prong { TracksWCovExtraPidPiKa const& tracks, aod::BCsWithTimestamps const& bcWithTimeStamps) { - runCreator2ProngWithKFParticle(collisions, rowsTrackIndexProng2, tracks, bcWithTimeStamps); + runCreator2ProngWithKFParticle(collisions, rowsTrackIndexProng2, tracks, bcWithTimeStamps); } PROCESS_SWITCH(HfCandidateCreator2Prong, processNoPvRefitWithKFParticleCentFT0C, "Run candidate creator using KFParticle package w/o PV refit and w/ centrality selection on FT0C", false); @@ -589,7 +607,7 @@ struct HfCandidateCreator2Prong { TracksWCovExtraPidPiKa const& tracks, aod::BCsWithTimestamps const& bcWithTimeStamps) { - runCreator2ProngWithDCAFitterN(collisions, rowsTrackIndexProng2, tracks, bcWithTimeStamps); + runCreator2ProngWithDCAFitterN(collisions, rowsTrackIndexProng2, tracks, bcWithTimeStamps); } PROCESS_SWITCH(HfCandidateCreator2Prong, processPvRefitWithDCAFitterNCentFT0M, "Run candidate creator using DCA fitter w/ PV refit and w/ centrality selection on FT0M", false); @@ -599,7 +617,7 @@ struct HfCandidateCreator2Prong { TracksWCovExtraPidPiKa const& tracks, aod::BCsWithTimestamps const& bcWithTimeStamps) { - runCreator2ProngWithDCAFitterN(collisions, rowsTrackIndexProng2, tracks, bcWithTimeStamps); + runCreator2ProngWithDCAFitterN(collisions, rowsTrackIndexProng2, tracks, bcWithTimeStamps); } PROCESS_SWITCH(HfCandidateCreator2Prong, processNoPvRefitWithDCAFitterNCentFT0M, "Run candidate creator using DCA fitter w/o PV refit and w/ centrality selection FT0M", false); @@ -609,7 +627,7 @@ struct HfCandidateCreator2Prong { TracksWCovExtraPidPiKa const& tracks, aod::BCsWithTimestamps const& bcWithTimeStamps) { - runCreator2ProngWithKFParticle(collisions, rowsTrackIndexProng2, tracks, bcWithTimeStamps); + runCreator2ProngWithKFParticle(collisions, rowsTrackIndexProng2, tracks, bcWithTimeStamps); } PROCESS_SWITCH(HfCandidateCreator2Prong, processPvRefitWithKFParticleCentFT0M, "Run candidate creator using KFParticle package w/ PV refit and w/ centrality selection on FT0M", false); @@ -619,10 +637,72 @@ struct HfCandidateCreator2Prong { TracksWCovExtraPidPiKa const& tracks, aod::BCsWithTimestamps const& bcWithTimeStamps) { - runCreator2ProngWithKFParticle(collisions, rowsTrackIndexProng2, tracks, bcWithTimeStamps); + runCreator2ProngWithKFParticle(collisions, rowsTrackIndexProng2, tracks, bcWithTimeStamps); } PROCESS_SWITCH(HfCandidateCreator2Prong, processNoPvRefitWithKFParticleCentFT0M, "Run candidate creator using KFParticle package w/o PV refit and w/ centrality selection on FT0M", false); + ///////////////////////////////////////////// + /// /// + /// with centrality selection on UPC /// + /// /// + ///////////////////////////////////////////// + + /// @brief process function using DCA fitter w/ PV refit and w/ centrality selection on UPC + void processPvRefitWithDCAFitterNUpc(soa::Join const& collisions, + soa::Join const& rowsTrackIndexProng2, + TracksWCovExtraPidPiKa const& tracks, + aod::BcFullInfos const& bcWithTimeStamps, + aod::FT0s const& /*ft0s*/, + aod::FV0As const& /*fv0as*/, + aod::FDDs const& /*fdds*/, + aod::Zdcs const& /*zdcs*/) + { + runCreator2ProngWithDCAFitterN(collisions, rowsTrackIndexProng2, tracks, bcWithTimeStamps); + } + PROCESS_SWITCH(HfCandidateCreator2Prong, processPvRefitWithDCAFitterNUpc, "Run candidate creator using DCA fitter w/ PV refit and w/ centrality selection on UltraPeripheral Collision", false); + + /// @brief process function using DCA fitter w/o PV refit and w/ centrality selection UPC + void processNoPvRefitWithDCAFitterNUpc(soa::Join const& collisions, + aod::Hf2Prongs const& rowsTrackIndexProng2, + TracksWCovExtraPidPiKa const& tracks, + aod::BcFullInfos const& bcWithTimeStamps, + aod::FT0s const& /*ft0s*/, + aod::FV0As const& /*fv0as*/, + aod::FDDs const& /*fdds*/, + aod::Zdcs const& /*zdcs*/) + { + runCreator2ProngWithDCAFitterN(collisions, rowsTrackIndexProng2, tracks, bcWithTimeStamps); + } + PROCESS_SWITCH(HfCandidateCreator2Prong, processNoPvRefitWithDCAFitterNUpc, "Run candidate creator using DCA fitter w/o PV refit and w/ centrality selection UltraPeripheral Collision", false); + + /// @brief process function using KFParticle package w/ PV refit and w/ centrality selection on UPC + void processPvRefitWithKFParticleUpc(soa::Join const& collisions, + soa::Join const& rowsTrackIndexProng2, + TracksWCovExtraPidPiKa const& tracks, + aod::BcFullInfos const& bcWithTimeStamps, + aod::FT0s const& /*ft0s*/, + aod::FV0As const& /*fv0as*/, + aod::FDDs const& /*fdds*/, + aod::Zdcs const& /*zdcs*/) + { + runCreator2ProngWithKFParticle(collisions, rowsTrackIndexProng2, tracks, bcWithTimeStamps); + } + PROCESS_SWITCH(HfCandidateCreator2Prong, processPvRefitWithKFParticleUpc, "Run candidate creator using KFParticle package w/ PV refit and w/ centrality selection on UltraPeripheral Collision", false); + + /// @brief process function using KFParticle package w/o PV refit and w/o centrality selections on UPC + void processNoPvRefitWithKFParticleUpc(soa::Join const& collisions, + aod::Hf2Prongs const& rowsTrackIndexProng2, + TracksWCovExtraPidPiKa const& tracks, + aod::BcFullInfos const& bcWithTimeStamps, + aod::FT0s const& /*ft0s*/, + aod::FV0As const& /*fv0as*/, + aod::FDDs const& /*fdds*/, + aod::Zdcs const& /*zdcs*/) + { + runCreator2ProngWithKFParticle(collisions, rowsTrackIndexProng2, tracks, bcWithTimeStamps); + } + PROCESS_SWITCH(HfCandidateCreator2Prong, processNoPvRefitWithKFParticleUpc, "Run candidate creator using KFParticle package w/o PV refit and w/ centrality selection on UltraPeripheral Collision", false); + /////////////////////////////////////////////////////////// /// /// /// Process functions only for collision monitoring /// @@ -682,6 +762,29 @@ struct HfCandidateCreator2Prong { } /// end loop over collisions } PROCESS_SWITCH(HfCandidateCreator2Prong, processCollisionsCentFT0M, "Collision monitoring - FT0M centrality", false); + + /// @brief process function to monitor collisions - UPC collision + void processCollisionsUpc(soa::Join const& collisions, + aod::BcFullInfos const& bcs, + aod::FT0s const& /*ft0s*/, + aod::FV0As const& /*fv0as*/, + aod::FDDs const& /*fdds*/, + aod::Zdcs const& /*zdcs*/) + { + /// loop over collisions + for (const auto& collision : collisions) { + + /// bitmask with event. selection info + float centrality{-1.f}; + float occupancy = getOccupancyColl(collision, OccupancyEstimator::Its); + const auto rejectionMask = hfEvSel.getHfCollisionRejectionMaskWithUpc(collision, centrality, ccdb, registry, bcs); + + /// monitor the satisfied event selections + hfEvSel.fillHistograms(collision, rejectionMask, centrality, occupancy); + + } /// end loop over collisions + } + PROCESS_SWITCH(HfCandidateCreator2Prong, processCollisionsUpc, "Collision monitoring - UPC", false); }; /// Extends the base table with expression columns. diff --git a/PWGHF/TableProducer/candidateCreator3Prong.cxx b/PWGHF/TableProducer/candidateCreator3Prong.cxx index 3460ff0a8a3..40ab5709951 100644 --- a/PWGHF/TableProducer/candidateCreator3Prong.cxx +++ b/PWGHF/TableProducer/candidateCreator3Prong.cxx @@ -136,18 +136,21 @@ struct HfCandidateCreator3Prong { void init(InitContext const&) { - std::array doprocessDF{doprocessPvRefitWithDCAFitterN, doprocessNoPvRefitWithDCAFitterN, + std::array doprocessDF{doprocessPvRefitWithDCAFitterN, doprocessNoPvRefitWithDCAFitterN, doprocessPvRefitWithDCAFitterNCentFT0C, doprocessNoPvRefitWithDCAFitterNCentFT0C, - doprocessPvRefitWithDCAFitterNCentFT0M, doprocessNoPvRefitWithDCAFitterNCentFT0M}; - std::array doprocessKF{doprocessPvRefitWithKFParticle, doprocessNoPvRefitWithKFParticle, + doprocessPvRefitWithDCAFitterNCentFT0M, doprocessNoPvRefitWithDCAFitterNCentFT0M, doprocessPvRefitWithDCAFitterNUpc, doprocessNoPvRefitWithDCAFitterNUpc}; + std::array doprocessKF{doprocessPvRefitWithKFParticle, doprocessNoPvRefitWithKFParticle, doprocessPvRefitWithKFParticleCentFT0C, doprocessNoPvRefitWithKFParticleCentFT0C, - doprocessPvRefitWithKFParticleCentFT0M, doprocessNoPvRefitWithKFParticleCentFT0M}; + doprocessPvRefitWithKFParticleCentFT0M, doprocessNoPvRefitWithKFParticleCentFT0M, doprocessPvRefitWithKFParticleUpc, doprocessNoPvRefitWithKFParticleUpc}; if ((std::accumulate(doprocessDF.begin(), doprocessDF.end(), 0) + std::accumulate(doprocessKF.begin(), doprocessKF.end(), 0)) != 1) { LOGP(fatal, "One and only one process function must be enabled at a time."); } - - std::array processesCollisions = {doprocessCollisions, doprocessCollisionsCentFT0C, doprocessCollisionsCentFT0M}; + std::array processesCollisions = {doprocessCollisions, doprocessCollisionsCentFT0C, doprocessCollisionsCentFT0M, doprocessCollisionsUpc}; const int nProcessesCollisions = std::accumulate(processesCollisions.begin(), processesCollisions.end(), 0); + + std::array processesUpc = {doprocessPvRefitWithDCAFitterNUpc, doprocessNoPvRefitWithDCAFitterNUpc, doprocessPvRefitWithKFParticleUpc, doprocessNoPvRefitWithKFParticleUpc, doprocessCollisionsUpc}; + const int nProcessesUpc = std::accumulate(processesUpc.begin(), processesUpc.end(), 0); + if (nProcessesCollisions > 1) { LOGP(fatal, "At most one process function for collision monitoring can be enabled at a time."); } @@ -161,8 +164,13 @@ struct HfCandidateCreator3Prong { if ((doprocessPvRefitWithDCAFitterNCentFT0M || doprocessNoPvRefitWithDCAFitterNCentFT0M || doprocessPvRefitWithKFParticleCentFT0M || doprocessNoPvRefitWithKFParticleCentFT0M) && !doprocessCollisionsCentFT0M) { LOGP(fatal, "Process function for collision monitoring not correctly enabled. Did you enable \"processCollisionsCentFT0M\"?"); } + if ((doprocessPvRefitWithDCAFitterNUpc || doprocessNoPvRefitWithDCAFitterNUpc || doprocessPvRefitWithKFParticleUpc || doprocessNoPvRefitWithKFParticleUpc) && !doprocessCollisionsUpc) { + LOGP(fatal, "Process function for collision monitoring not correctly enabled. Did you enable \"processCollisionsUpc\"?"); + } + } + if (nProcessesUpc > 0 && isRun2) { + LOGP(fatal, "Process function for UPC is only available in Run 3!"); } - std::array creationFlags = {createDplus, createDs, createLc, createXic}; if (std::accumulate(creationFlags.begin(), creationFlags.end(), 0) == 0) { LOGP(fatal, "At least one particle specie should be enabled for the creation."); @@ -236,11 +244,11 @@ struct HfCandidateCreator3Prong { } } - template + template void runCreator3ProngWithDCAFitterN(Coll const&, Cand const& rowsTrackIndexProng3, TracksWCovExtraPidPiKaPr const&, - aod::BCsWithTimestamps const& /*bcWithTimeStamps*/) + BCsType const& bcs) { // loop over triplets of track indices for (const auto& rowTrackIndexProng3 : rowsTrackIndexProng3) { @@ -248,7 +256,12 @@ struct HfCandidateCreator3Prong { /// reject candidates in collisions not satisfying the event selections auto collision = rowTrackIndexProng3.template collision_as(); float centrality{-1.f}; - const auto rejectionMask = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb, registry); + uint32_t rejectionMask{0}; + if constexpr (applyUpcSel) { + rejectionMask = hfEvSel.getHfCollisionRejectionMaskWithUpc(collision, centrality, ccdb, registry, bcs); + } else { + rejectionMask = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb, registry); + } if (rejectionMask != 0) { /// at least one event selection not satisfied --> reject the candidate continue; @@ -264,7 +277,7 @@ struct HfCandidateCreator3Prong { /// Set the magnetic field from ccdb. /// The static instance of the propagator was already modified in the HFTrackIndexSkimCreator, /// but this is not true when running on Run2 data/MC already converted into AO2Ds. - auto bc = collision.template bc_as(); + auto bc = collision.template bc_as(); if (runNumber != bc.runNumber()) { LOG(info) << ">>>>>>>>>>>> Current run number: " << runNumber; initCCDB(bc, runNumber, ccdb, isRun2 ? ccdbPathGrp : ccdbPathGrpMag, nullptr, isRun2); @@ -404,17 +417,22 @@ struct HfCandidateCreator3Prong { } } - template + template void runCreator3ProngWithKFParticle(Coll const&, Cand const& rowsTrackIndexProng3, TracksWCovExtraPidPiKaPr const&, - aod::BCsWithTimestamps const& /*bcWithTimeStamps*/) + BCsType const& bcs) { for (const auto& rowTrackIndexProng3 : rowsTrackIndexProng3) { /// reject candidates in collisions not satisfying the event selections auto collision = rowTrackIndexProng3.template collision_as(); float centrality{-1.f}; - const auto rejectionMask = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb, registry); + uint32_t rejectionMask{0}; + if constexpr (applyUpcSel) { + rejectionMask = hfEvSel.getHfCollisionRejectionMaskWithUpc(collision, centrality, ccdb, registry, bcs); + } else { + rejectionMask = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb, registry); + } if (rejectionMask != 0) { /// at least one event selection not satisfied --> reject the candidate continue; @@ -654,7 +672,7 @@ struct HfCandidateCreator3Prong { TracksWCovExtraPidPiKaPr const& tracks, aod::BCsWithTimestamps const& bcWithTimeStamps) { - runCreator3ProngWithDCAFitterN(collisions, rowsTrackIndexProng3, tracks, bcWithTimeStamps); + runCreator3ProngWithDCAFitterN(collisions, rowsTrackIndexProng3, tracks, bcWithTimeStamps); } PROCESS_SWITCH(HfCandidateCreator3Prong, processPvRefitWithDCAFitterN, "Run candidate creator using DCA fitter with PV refit and w/o centrality selections", false); @@ -664,7 +682,7 @@ struct HfCandidateCreator3Prong { TracksWCovExtraPidPiKaPr const& tracks, aod::BCsWithTimestamps const& bcWithTimeStamps) { - runCreator3ProngWithDCAFitterN(collisions, rowsTrackIndexProng3, tracks, bcWithTimeStamps); + runCreator3ProngWithDCAFitterN(collisions, rowsTrackIndexProng3, tracks, bcWithTimeStamps); } PROCESS_SWITCH(HfCandidateCreator3Prong, processNoPvRefitWithDCAFitterN, "Run candidate creator using DCA fitter without PV refit and w/o centrality selections", true); @@ -674,7 +692,7 @@ struct HfCandidateCreator3Prong { TracksWCovExtraPidPiKaPr const& tracks, aod::BCsWithTimestamps const& bcWithTimeStamps) { - runCreator3ProngWithKFParticle(collisions, rowsTrackIndexProng3, tracks, bcWithTimeStamps); + runCreator3ProngWithKFParticle(collisions, rowsTrackIndexProng3, tracks, bcWithTimeStamps); } PROCESS_SWITCH(HfCandidateCreator3Prong, processPvRefitWithKFParticle, "Run candidate creator using KFParticle package with PV refit and w/o centrality selections", false); @@ -684,7 +702,7 @@ struct HfCandidateCreator3Prong { TracksWCovExtraPidPiKaPr const& tracks, aod::BCsWithTimestamps const& bcWithTimeStamps) { - runCreator3ProngWithKFParticle(collisions, rowsTrackIndexProng3, tracks, bcWithTimeStamps); + runCreator3ProngWithKFParticle(collisions, rowsTrackIndexProng3, tracks, bcWithTimeStamps); } PROCESS_SWITCH(HfCandidateCreator3Prong, processNoPvRefitWithKFParticle, "Run candidate creator using KFParticle package without PV refit and w/o centrality selections", false); @@ -700,7 +718,7 @@ struct HfCandidateCreator3Prong { TracksWCovExtraPidPiKaPr const& tracks, aod::BCsWithTimestamps const& bcWithTimeStamps) { - runCreator3ProngWithDCAFitterN(collisions, rowsTrackIndexProng3, tracks, bcWithTimeStamps); + runCreator3ProngWithDCAFitterN(collisions, rowsTrackIndexProng3, tracks, bcWithTimeStamps); } PROCESS_SWITCH(HfCandidateCreator3Prong, processPvRefitWithDCAFitterNCentFT0C, "Run candidate creator using DCA fitter with PV refit and w/ centrality selection on FT0C", false); @@ -710,7 +728,7 @@ struct HfCandidateCreator3Prong { TracksWCovExtraPidPiKaPr const& tracks, aod::BCsWithTimestamps const& bcWithTimeStamps) { - runCreator3ProngWithDCAFitterN(collisions, rowsTrackIndexProng3, tracks, bcWithTimeStamps); + runCreator3ProngWithDCAFitterN(collisions, rowsTrackIndexProng3, tracks, bcWithTimeStamps); } PROCESS_SWITCH(HfCandidateCreator3Prong, processNoPvRefitWithDCAFitterNCentFT0C, "Run candidate creator using DCA fitter without PV refit and w/ centrality selection on FT0C", false); @@ -720,7 +738,7 @@ struct HfCandidateCreator3Prong { TracksWCovExtraPidPiKaPr const& tracks, aod::BCsWithTimestamps const& bcWithTimeStamps) { - runCreator3ProngWithKFParticle(collisions, rowsTrackIndexProng3, tracks, bcWithTimeStamps); + runCreator3ProngWithKFParticle(collisions, rowsTrackIndexProng3, tracks, bcWithTimeStamps); } PROCESS_SWITCH(HfCandidateCreator3Prong, processPvRefitWithKFParticleCentFT0C, "Run candidate creator using KFParticle package with PV refit and w/ centrality selection on FT0C", false); @@ -730,7 +748,7 @@ struct HfCandidateCreator3Prong { TracksWCovExtraPidPiKaPr const& tracks, aod::BCsWithTimestamps const& bcWithTimeStamps) { - runCreator3ProngWithKFParticle(collisions, rowsTrackIndexProng3, tracks, bcWithTimeStamps); + runCreator3ProngWithKFParticle(collisions, rowsTrackIndexProng3, tracks, bcWithTimeStamps); } PROCESS_SWITCH(HfCandidateCreator3Prong, processNoPvRefitWithKFParticleCentFT0C, "Run candidate creator using KFParticle package without PV refit and w/ centrality selection on FT0C", false); @@ -746,7 +764,7 @@ struct HfCandidateCreator3Prong { TracksWCovExtraPidPiKaPr const& tracks, aod::BCsWithTimestamps const& bcWithTimeStamps) { - runCreator3ProngWithDCAFitterN(collisions, rowsTrackIndexProng3, tracks, bcWithTimeStamps); + runCreator3ProngWithDCAFitterN(collisions, rowsTrackIndexProng3, tracks, bcWithTimeStamps); } PROCESS_SWITCH(HfCandidateCreator3Prong, processPvRefitWithDCAFitterNCentFT0M, "Run candidate creator using DCA fitter with PV refit and w/ centrality selection on FT0M", false); @@ -756,7 +774,7 @@ struct HfCandidateCreator3Prong { TracksWCovExtraPidPiKaPr const& tracks, aod::BCsWithTimestamps const& bcWithTimeStamps) { - runCreator3ProngWithDCAFitterN(collisions, rowsTrackIndexProng3, tracks, bcWithTimeStamps); + runCreator3ProngWithDCAFitterN(collisions, rowsTrackIndexProng3, tracks, bcWithTimeStamps); } PROCESS_SWITCH(HfCandidateCreator3Prong, processNoPvRefitWithDCAFitterNCentFT0M, "Run candidate creator using DCA fitter without PV refit and w/ centrality selection on FT0M", false); @@ -766,7 +784,7 @@ struct HfCandidateCreator3Prong { TracksWCovExtraPidPiKaPr const& tracks, aod::BCsWithTimestamps const& bcWithTimeStamps) { - runCreator3ProngWithKFParticle(collisions, rowsTrackIndexProng3, tracks, bcWithTimeStamps); + runCreator3ProngWithKFParticle(collisions, rowsTrackIndexProng3, tracks, bcWithTimeStamps); } PROCESS_SWITCH(HfCandidateCreator3Prong, processPvRefitWithKFParticleCentFT0M, "Run candidate creator using KFParticle package with PV refit and w/ centrality selection on FT0M", false); @@ -776,10 +794,72 @@ struct HfCandidateCreator3Prong { TracksWCovExtraPidPiKaPr const& tracks, aod::BCsWithTimestamps const& bcWithTimeStamps) { - runCreator3ProngWithKFParticle(collisions, rowsTrackIndexProng3, tracks, bcWithTimeStamps); + runCreator3ProngWithKFParticle(collisions, rowsTrackIndexProng3, tracks, bcWithTimeStamps); } PROCESS_SWITCH(HfCandidateCreator3Prong, processNoPvRefitWithKFParticleCentFT0M, "Run candidate creator using KFParticle package without PV refit and w/ centrality selection on FT0M", false); + ///////////////////////////////////////////// + /// /// + /// with centrality selection on UPC /// + /// /// + ///////////////////////////////////////////// + + /// @brief process function using DCA fitter w/ PV refit and w/ centrality selection on UPC + void processPvRefitWithDCAFitterNUpc(soa::Join const& collisions, + FilteredPvRefitHf3Prongs const& rowsTrackIndexProng3, + TracksWCovExtraPidPiKaPr const& tracks, + aod::BcFullInfos const& bcWithTimeStamps, + aod::FT0s const& /*ft0s*/, + aod::FV0As const& /*fv0as*/, + aod::FDDs const& /*fdds*/, + aod::Zdcs const& /*zdcs*/) + { + runCreator3ProngWithDCAFitterN(collisions, rowsTrackIndexProng3, tracks, bcWithTimeStamps); + } + PROCESS_SWITCH(HfCandidateCreator3Prong, processPvRefitWithDCAFitterNUpc, "Run candidate creator using DCA fitter with PV refit and w/ centrality selection on UPC", false); + + /// @brief process function using DCA fitter w/o PV refit and w/ centrality selection on UPC + void processNoPvRefitWithDCAFitterNUpc(soa::Join const& collisions, + FilteredHf3Prongs const& rowsTrackIndexProng3, + TracksWCovExtraPidPiKaPr const& tracks, + aod::BcFullInfos const& bcWithTimeStamps, + aod::FT0s const& /*ft0s*/, + aod::FV0As const& /*fv0as*/, + aod::FDDs const& /*fdds*/, + aod::Zdcs const& /*zdcs*/) + { + runCreator3ProngWithDCAFitterN(collisions, rowsTrackIndexProng3, tracks, bcWithTimeStamps); + } + PROCESS_SWITCH(HfCandidateCreator3Prong, processNoPvRefitWithDCAFitterNUpc, "Run candidate creator using DCA fitter without PV refit and w/ centrality selection on UPC", false); + + /// @brief process function using KFParticle package w/ PV refit and w/ centrality selection on UPC + void processPvRefitWithKFParticleUpc(soa::Join const& collisions, + FilteredPvRefitHf3Prongs const& rowsTrackIndexProng3, + TracksWCovExtraPidPiKaPr const& tracks, + aod::BcFullInfos const& bcWithTimeStamps, + aod::FT0s const& /*ft0s*/, + aod::FV0As const& /*fv0as*/, + aod::FDDs const& /*fdds*/, + aod::Zdcs const& /*zdcs*/) + { + runCreator3ProngWithKFParticle(collisions, rowsTrackIndexProng3, tracks, bcWithTimeStamps); + } + PROCESS_SWITCH(HfCandidateCreator3Prong, processPvRefitWithKFParticleUpc, "Run candidate creator using KFParticle package with PV refit and w/ centrality selection on UPC", false); + + /// @brief process function using KFParticle package w/o PV refit and w/ centrality selection on UPC + void processNoPvRefitWithKFParticleUpc(soa::Join const& collisions, + FilteredHf3Prongs const& rowsTrackIndexProng3, + TracksWCovExtraPidPiKaPr const& tracks, + aod::BcFullInfos const& bcWithTimeStamps, + aod::FT0s const& /*ft0s*/, + aod::FV0As const& /*fv0as*/, + aod::FDDs const& /*fdds*/, + aod::Zdcs const& /*zdcs*/) + { + runCreator3ProngWithKFParticle(collisions, rowsTrackIndexProng3, tracks, bcWithTimeStamps); + } + PROCESS_SWITCH(HfCandidateCreator3Prong, processNoPvRefitWithKFParticleUpc, "Run candidate creator using KFParticle package without PV refit and w/ centrality selection on UPC", false); + /////////////////////////////////////////////////////////// /// /// /// Process functions only for collision monitoring /// @@ -839,6 +919,29 @@ struct HfCandidateCreator3Prong { } /// end loop over collisions } PROCESS_SWITCH(HfCandidateCreator3Prong, processCollisionsCentFT0M, "Collision monitoring - FT0M centrality", false); + + /// @brief process function to monitor collisions - UPC + void processCollisionsUpc(soa::Join const& collisions, + aod::BcFullInfos const& bcs, + aod::FT0s const& /*ft0s*/, + aod::FV0As const& /*fv0as*/, + aod::FDDs const& /*fdds*/, + aod::Zdcs const& /*zdcs*/) + { + /// loop over collisions + for (const auto& collision : collisions) { + + /// bitmask with event. selection info + float centrality{-1.f}; + float occupancy = getOccupancyColl(collision, OccupancyEstimator::Its); + const auto rejectionMask = hfEvSel.getHfCollisionRejectionMaskWithUpc(collision, centrality, ccdb, registry, bcs); + + /// monitor the satisfied event selections + hfEvSel.fillHistograms(collision, rejectionMask, centrality, occupancy); + + } /// end loop over collisions + } + PROCESS_SWITCH(HfCandidateCreator3Prong, processCollisionsUpc, "Collision monitoring - UPC", false); }; /// Extends the base table with expression columns. diff --git a/PWGHF/TableProducer/trackIndexSkimCreator.cxx b/PWGHF/TableProducer/trackIndexSkimCreator.cxx index 0f98525ceb1..2c6dfd66343 100644 --- a/PWGHF/TableProducer/trackIndexSkimCreator.cxx +++ b/PWGHF/TableProducer/trackIndexSkimCreator.cxx @@ -108,7 +108,7 @@ struct HfTrackIndexSkimCreatorTagSelCollisions { void init(InitContext const&) { - std::array doProcess = {doprocessTrigAndCentFT0ASel, doprocessTrigAndCentFT0CSel, doprocessTrigAndCentFT0MSel, doprocessTrigAndCentFV0ASel, doprocessTrigSel, doprocessNoTrigSel}; + std::array doProcess = {doprocessTrigAndCentFT0ASel, doprocessTrigAndCentFT0CSel, doprocessTrigAndCentFT0MSel, doprocessTrigAndCentFV0ASel, doprocessTrigSel, doprocessNoTrigSel, doprocessUpcSel}; if (std::accumulate(doProcess.begin(), doProcess.end(), 0) != 1) { LOGP(fatal, "One and only one process function for collision selection can be enabled at a time!"); } @@ -132,11 +132,19 @@ struct HfTrackIndexSkimCreatorTagSelCollisions { /// Collision selection /// \param collision collision table with - template - void selectCollision(const Col& collision, const BCs&) + template + void selectCollision(const Col& collision, const BCsType& bcs) { float centrality = -1.; - const auto rejectionMask = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb, registry); + uint32_t rejectionMask; + + if constexpr (applyUpcSel) { + rejectionMask = hfEvSel.getHfCollisionRejectionMaskWithUpc( + collision, centrality, ccdb, registry, bcs); + } else { + rejectionMask = hfEvSel.getHfCollisionRejectionMask( + collision, centrality, ccdb, registry); + } if (fillHistograms) { hfEvSel.fillHistograms(collision, rejectionMask, centrality); @@ -155,46 +163,69 @@ struct HfTrackIndexSkimCreatorTagSelCollisions { } /// Event selection with trigger and FT0A centrality selection - void processTrigAndCentFT0ASel(soa::Join::iterator const& collision, aod::BCsWithTimestamps const& bcs) + void processTrigAndCentFT0ASel(soa::Join::iterator const& collision, + aod::BcFullInfos const& bcs) { - selectCollision(collision, bcs); + selectCollision(collision, bcs); } PROCESS_SWITCH(HfTrackIndexSkimCreatorTagSelCollisions, processTrigAndCentFT0ASel, "Use trigger and centrality selection with FT0A", false); /// Event selection with trigger and FT0C centrality selection - void processTrigAndCentFT0CSel(soa::Join::iterator const& collision, aod::BCsWithTimestamps const& bcs) + void processTrigAndCentFT0CSel(soa::Join::iterator const& collision, + aod::BcFullInfos const& bcs) { - selectCollision(collision, bcs); + selectCollision(collision, bcs); } PROCESS_SWITCH(HfTrackIndexSkimCreatorTagSelCollisions, processTrigAndCentFT0CSel, "Use trigger and centrality selection with FT0C", false); /// Event selection with trigger and FT0M centrality selection - void processTrigAndCentFT0MSel(soa::Join::iterator const& collision, aod::BCsWithTimestamps const& bcs) + void processTrigAndCentFT0MSel(soa::Join::iterator const& collision, + aod::BcFullInfos const& bcs) { - selectCollision(collision, bcs); + selectCollision(collision, bcs); } PROCESS_SWITCH(HfTrackIndexSkimCreatorTagSelCollisions, processTrigAndCentFT0MSel, "Use trigger and centrality selection with FT0M", false); /// Event selection with trigger and FV0A centrality selection - void processTrigAndCentFV0ASel(soa::Join::iterator const& collision, aod::BCsWithTimestamps const& bcs) + void processTrigAndCentFV0ASel(soa::Join::iterator const& collision, + aod::BcFullInfos const& bcs) { - selectCollision(collision, bcs); + selectCollision(collision, bcs); } PROCESS_SWITCH(HfTrackIndexSkimCreatorTagSelCollisions, processTrigAndCentFV0ASel, "Use trigger and centrality selection with FV0A", false); /// Event selection with trigger selection - void processTrigSel(soa::Join::iterator const& collision, aod::BCsWithTimestamps const& bcs) + void processTrigSel(soa::Join::iterator const& collision, + aod::BcFullInfos const& bcs) { - selectCollision(collision, bcs); + selectCollision(collision, bcs); } PROCESS_SWITCH(HfTrackIndexSkimCreatorTagSelCollisions, processTrigSel, "Use trigger selection", false); /// Event selection without trigger selection - void processNoTrigSel(aod::Collision const& collision, aod::BCsWithTimestamps const& bcs) + void processNoTrigSel(aod::Collision const& collision, + aod::BcFullInfos const& bcs) { - selectCollision(collision, bcs); + selectCollision(collision, bcs); } PROCESS_SWITCH(HfTrackIndexSkimCreatorTagSelCollisions, processNoTrigSel, "Do not use trigger selection", true); + + /// Event selection with UPC + void processUpcSel(soa::Join::iterator const& collision, + aod::BcFullInfos const& bcs, + aod::FT0s const& /*ft0s*/, + aod::FV0As const& /*fv0as*/, + aod::FDDs const& /*fdds*/, + aod::Zdcs const& /*zdcs*/) + { + selectCollision(collision, bcs); + } + PROCESS_SWITCH(HfTrackIndexSkimCreatorTagSelCollisions, processUpcSel, "Use UPC event selection", false); }; /// Track selection @@ -1246,7 +1277,7 @@ struct HfTrackIndexSkimCreator { using FilteredTrackAssocSel = soa::Filtered>; // filter collisions - Filter filterSelectCollisions = (aod::hf_sel_collision::whyRejectColl == static_cast(0)); + Filter filterSelectCollisions = (aod::hf_sel_collision::whyRejectColl == static_cast(0)); // filter track indices Filter filterSelectTrackIds = ((aod::hf_sel_track::isSelProng & static_cast(BIT(CandidateType::Cand2Prong))) != 0u) || ((aod::hf_sel_track::isSelProng & static_cast(BIT(CandidateType::Cand3Prong))) != 0u) || ((aod::hf_sel_track::isSelProng & static_cast(BIT(CandidateType::CandDstar))) != 0u); @@ -3058,7 +3089,7 @@ struct HfTrackIndexSkimCreatorCascades { using SelectedCollisions = soa::Filtered>; using FilteredTrackAssocSel = soa::Filtered>; - Filter filterSelectCollisions = (aod::hf_sel_collision::whyRejectColl == static_cast(0)); + Filter filterSelectCollisions = (aod::hf_sel_collision::whyRejectColl == static_cast(0)); Filter filterSelectTrackIds = (aod::hf_sel_track::isSelProng & static_cast(BIT(CandidateType::CandV0bachelor))) != 0u && (config.applyProtonPid == false || (aod::hf_sel_track::isIdentifiedPid & static_cast(BIT(ChannelsProtonPid::LcToPK0S))) != 0u); Preslice trackIndicesPerCollision = aod::track_association::collisionId; @@ -3337,7 +3368,7 @@ struct HfTrackIndexSkimCreatorLfCascades { using CascFull = soa::Join; using V0Full = soa::Join; - Filter filterSelectCollisions = (aod::hf_sel_collision::whyRejectColl == static_cast(0)); + Filter filterSelectCollisions = (aod::hf_sel_collision::whyRejectColl == static_cast(0)); Filter filterSelectTrackIds = (aod::hf_sel_track::isSelProng & static_cast(BIT(CandidateType::CandCascadeBachelor))) != 0u; Preslice tracksPerCollision = aod::track::collisionId; // needed for PV refit diff --git a/PWGHF/Utils/utilsEvSelHf.h b/PWGHF/Utils/utilsEvSelHf.h index 63e3e72d7e4..4e649f7eddb 100644 --- a/PWGHF/Utils/utilsEvSelHf.h +++ b/PWGHF/Utils/utilsEvSelHf.h @@ -18,11 +18,13 @@ #ifndef PWGHF_UTILS_UTILSEVSELHF_H_ #define PWGHF_UTILS_UTILSEVSELHF_H_ -#include +#include "PWGHF/Core/CentralityEstimation.h" +#include "PWGUD/Core/SGSelector.h" -#include -#include -#include +#include "Common/CCDB/EventSelectionParams.h" +#include "Common/CCDB/RCTSelectionFlags.h" +#include "EventFiltering/Zorro.h" +#include "EventFiltering/ZorroSummary.h" #include #include @@ -30,18 +32,18 @@ #include #include -#include +#include +#include + +#include + +#include + #include +#include #include // std::shared_ptr #include // std::string -#include "Common/CCDB/EventSelectionParams.h" -#include "Common/CCDB/RCTSelectionFlags.h" -#include "EventFiltering/Zorro.h" -#include "EventFiltering/ZorroSummary.h" - -#include "PWGHF/Core/CentralityEstimation.h" - namespace o2::hf_occupancy { // centrality selection estimators @@ -103,15 +105,17 @@ enum EventRejection { NoSameBunchPileup, Occupancy, NContrib, - Chi2, - PositionZ, NoCollInTimeRangeNarrow, NoCollInTimeRangeStandard, NoCollInRofStandard, + UpcEventCut, + Chi2, + PositionZ, NEventRejection }; o2::framework::AxisSpec axisEvents = {EventRejection::NEventRejection, -0.5f, +EventRejection::NEventRejection - 0.5f, ""}; +o2::framework::AxisSpec axisUpcEvents = {o2::aod::sgselector::DoubleGap + 1, -0.5f, +o2::aod::sgselector::DoubleGap + 0.5f, ""}; /// \brief Function to put labels on monitoring histogram /// \param hRejection monitoring histogram @@ -128,6 +132,7 @@ void setEventRejectionLabels(Histo& hRejection, std::string softwareTriggerLabel hRejection->GetXaxis()->SetBinLabel(EventRejection::TvxTrigger + 1, "TVX Trigger"); hRejection->GetXaxis()->SetBinLabel(EventRejection::TimeFrameBorderCut + 1, "TF border"); hRejection->GetXaxis()->SetBinLabel(EventRejection::ItsRofBorderCut + 1, "ITS ROF border"); + hRejection->GetXaxis()->SetBinLabel(EventRejection::UpcEventCut + 1, "UPC event"); hRejection->GetXaxis()->SetBinLabel(EventRejection::IsGoodZvtxFT0vsPV + 1, "PV #it{z} consistency FT0 timing"); hRejection->GetXaxis()->SetBinLabel(EventRejection::NoSameBunchPileup + 1, "No same-bunch pile-up"); // POTENTIALLY BAD FOR BEAUTY ANALYSES hRejection->GetXaxis()->SetBinLabel(EventRejection::Occupancy + 1, "Occupancy"); @@ -172,6 +177,9 @@ struct HfEventSelection : o2::framework::ConfigurableGroup { o2::framework::Configurable rctCheckZDC{"rctCheckZDC", false, "RCT flag to check whether the ZDC is present or not"}; o2::framework::Configurable rctTreatLimitedAcceptanceAsBad{"rctTreatLimitedAcceptanceAsBad", false, "RCT flag to reject events with limited acceptance for selected detectors"}; + // SG selector + SGSelector sgSelector; + // histogram names static constexpr char NameHistCollisions[] = "hCollisions"; static constexpr char NameHistSelCollisionsCent[] = "hSelCollisionsCent"; @@ -181,8 +189,9 @@ struct HfEventSelection : o2::framework::ConfigurableGroup { static constexpr char NameHistPosYAfterEvSel[] = "hPosYAfterEvSel"; static constexpr char NameHistNumPvContributorsAfterSel[] = "hNumPvContributorsAfterSel"; static constexpr char NameHistCollisionsCentOcc[] = "hCollisionsCentOcc"; + static constexpr char NameHistUpCollisions[] = "hUpCollisions"; - std::shared_ptr hCollisions, hSelCollisionsCent, hPosZBeforeEvSel, hPosZAfterEvSel, hPosXAfterEvSel, hPosYAfterEvSel, hNumPvContributorsAfterSel; + std::shared_ptr hCollisions, hSelCollisionsCent, hPosZBeforeEvSel, hPosZAfterEvSel, hPosXAfterEvSel, hPosYAfterEvSel, hNumPvContributorsAfterSel, hUpCollisions; std::shared_ptr hCollisionsCentOcc; // util to retrieve the RCT info from CCDB @@ -193,6 +202,21 @@ struct HfEventSelection : o2::framework::ConfigurableGroup { o2::framework::OutputObj zorroSummary{"zorroSummary"}; int currentRun{-1}; + /// Set standard preselection gap trigger (values taken from UD group) + SGCutParHolder setSgPreselection() + { + SGCutParHolder sgCuts; + sgCuts.SetNDtcoll(1); // Minimum number of sigma around the collision + sgCuts.SetMinNBCs(2); // Minimum number of bunch crossings + sgCuts.SetNTracks(2, 1000); // Minimum and maximum number of PV contributors + sgCuts.SetMaxFITtime(34.f); // Maximum FIT time in ns + + // Set FIT amplitudes: FV0, FT0A, FT0C, FDDA, FDDC + sgCuts.SetFITAmpLimits({-1.f, 150.f, 50.f, -1.f, -1.f}); + + return sgCuts; + } + /// \brief Adds collision monitoring histograms in the histogram registry. /// \param registry reference to the histogram registry void addHistograms(o2::framework::HistogramRegistry& registry) @@ -205,7 +229,7 @@ struct HfEventSelection : o2::framework::ConfigurableGroup { hPosYAfterEvSel = registry.add(NameHistPosYAfterEvSel, "selected events;#it{y}_{prim. vtx.} (cm);entries", {o2::framework::HistType::kTH1D, {{200, -0.5, 0.5}}}); hNumPvContributorsAfterSel = registry.add(NameHistNumPvContributorsAfterSel, "selected events;number of prim. vtx. contributors;entries", {o2::framework::HistType::kTH1D, {{500, -0.5, 499.5}}}); setEventRejectionLabels(hCollisions, softwareTrigger); - + hUpCollisions = registry.add(NameHistUpCollisions, "HF UPC counter;;# of UPC events", {o2::framework::HistType::kTH1D, {axisUpcEvents}}); const o2::framework::AxisSpec th2AxisCent{th2ConfigAxisCent, "Centrality"}; const o2::framework::AxisSpec th2AxisOccupancy{th2ConfigAxisOccupancy, "Occupancy"}; hCollisionsCentOcc = registry.add(NameHistCollisionsCentOcc, "selected events;Centrality; Occupancy", {o2::framework::HistType::kTH2D, {th2AxisCent, th2AxisOccupancy}}); @@ -237,10 +261,10 @@ struct HfEventSelection : o2::framework::ConfigurableGroup { /// \param ccdb ccdb service needed to retrieve the needed info for zorro /// \param registry reference to the histogram registry needed for zorro /// \return bitmask with the event selection criteria not satisfied by the collision - template - uint16_t getHfCollisionRejectionMask(const Coll& collision, float& centrality, o2::framework::Service const& ccdb, o2::framework::HistogramRegistry& registry) + template + uint32_t getHfCollisionRejectionMask(const Coll& collision, float& centrality, o2::framework::Service const& ccdb, o2::framework::HistogramRegistry& registry) { - uint16_t rejectionMask{0}; // 16 bits, in case new ev. selections will be added + uint32_t rejectionMask{0}; // 32 bits, in case new ev. selections will be added if constexpr (centEstimator != o2::hf_centrality::CentralityEstimator::None) { centrality = o2::hf_centrality::getCentralityColl(collision, centEstimator); @@ -316,7 +340,7 @@ struct HfEventSelection : o2::framework::ConfigurableGroup { if (softwareTrigger.value != "") { // we might have to update it from CCDB - auto bc = collision.template bc_as(); + auto bc = collision.template bc_as(); int runNumber = bc.runNumber(); if (runNumber != currentRun) { // We might need to update Zorro from CCDB if the run number changes @@ -341,11 +365,32 @@ struct HfEventSelection : o2::framework::ConfigurableGroup { return rejectionMask; } + template + uint32_t getHfCollisionRejectionMaskWithUpc(const Coll& collision, float& centrality, o2::framework::Service const& ccdb, o2::framework::HistogramRegistry& registry, const BCsType& bcs) + { + auto rejectionMaskWithUpc = getHfCollisionRejectionMask(collision, centrality, ccdb, registry); + + if (useEvSel) { + SGCutParHolder sgCuts = setSgPreselection(); + auto bc = collision.template foundBC_as(); + auto bcRange = udhelpers::compatibleBCs(collision, sgCuts.NDtcoll(), bcs, sgCuts.minNBCs()); + auto sgSelectionResult = sgSelector.IsSelected(sgCuts, collision, bcRange, bc); + int upcEventType = sgSelectionResult.value; + if (upcEventType > o2::aod::sgselector::DoubleGap) { + SETBIT(rejectionMaskWithUpc, EventRejection::UpcEventCut); + } else { + hUpCollisions->Fill(upcEventType); + } + } + + return rejectionMaskWithUpc; + } + /// \brief Fills histograms for monitoring event selections satisfied by the collision. /// \param collision analysed collision /// \param rejectionMask bitmask storing the info about which ev. selections are not satisfied by the collision template - void fillHistograms(Coll const& collision, const uint16_t rejectionMask, float& centrality, float occupancy = -1) + void fillHistograms(Coll const& collision, const uint32_t rejectionMask, float& centrality, float occupancy = -1) { hCollisions->Fill(EventRejection::None); const float posZ = collision.posZ(); @@ -464,9 +509,9 @@ struct HfEventSelectionMc { /// \param centrality centrality variable to be set in this function /// \return a bitmask with the event selections not satisfied by the analysed collision template - uint16_t getHfMcCollisionRejectionMask(TMcColl const& mcCollision, CCs const& collSlice, float& centrality) + uint32_t getHfMcCollisionRejectionMask(TMcColl const& mcCollision, CCs const& collSlice, float& centrality) { - uint16_t rejectionMask{0}; + uint32_t rejectionMask{0}; float zPv = mcCollision.posZ(); auto bc = mcCollision.template bc_as(); @@ -515,7 +560,7 @@ struct HfEventSelectionMc { /// \param collision analysed collision /// \param rejectionMask bitmask storing the info about which ev. selections are not satisfied by the collision template - void fillHistograms(Coll const& mcCollision, const uint16_t rejectionMask, int nSplitColl = 0) + void fillHistograms(Coll const& mcCollision, const uint32_t rejectionMask, int nSplitColl = 0) { hParticles->Fill(EventRejection::None); From 7ba8397e5e5f68ecf4135185c6dd95e568cf5797 Mon Sep 17 00:00:00 2001 From: Oleksii Lubynets Date: Fri, 27 Jun 2025 10:54:52 +0200 Subject: [PATCH 233/871] [PWGHF] runMassFitter: add main() function and missing header, provide Readme (#11611) Co-authored-by: ALICE Action Bot --- .../D2H/Macros/CMakeLists_HFInvMassFitter.txt | 23 ++++++++ PWGHF/D2H/Macros/HFInvMassFitter.cxx | 7 ++- PWGHF/D2H/Macros/HFInvMassFitter.h | 7 ++- PWGHF/D2H/Macros/HFInvMassFitterLinkDef.h | 31 ++++++++++ PWGHF/D2H/Macros/README.md | 59 +++++++++++++++++++ PWGHF/D2H/Macros/runMassFitter.C | 23 ++++++-- 6 files changed, 140 insertions(+), 10 deletions(-) create mode 100644 PWGHF/D2H/Macros/CMakeLists_HFInvMassFitter.txt create mode 100644 PWGHF/D2H/Macros/HFInvMassFitterLinkDef.h create mode 100644 PWGHF/D2H/Macros/README.md diff --git a/PWGHF/D2H/Macros/CMakeLists_HFInvMassFitter.txt b/PWGHF/D2H/Macros/CMakeLists_HFInvMassFitter.txt new file mode 100644 index 00000000000..5a74cec1768 --- /dev/null +++ b/PWGHF/D2H/Macros/CMakeLists_HFInvMassFitter.txt @@ -0,0 +1,23 @@ +cmake_minimum_required(VERSION 3.10) + +project(HFInvMassFitter) + +set(HFFITTER_RAPIDJSON_INCLUDE_DIRS "" CACHE STRING "Location of rapidjson include directories") + +find_package(ROOT REQUIRED COMPONENTS RooFit RooFitCore) + +include_directories(${ROOT_INCLUDE_DIRS} ${CMAKE_SOURCE_DIR} ${HFFITTER_RAPIDJSON_INCLUDE_DIRS}) + +set(SOURCES + HFInvMassFitter.cxx + runMassFitter.C +) + +add_executable(runMassFitter ${SOURCES} "HFInvMassFitter.h") + +ROOT_GENERATE_DICTIONARY(G__HFInvMassFitter + HFInvMassFitter.h LINKDEF HFInvMassFitterLinkDef.h + MODULE runMassFitter +) + +target_link_libraries(runMassFitter PRIVATE ${ROOT_LIBRARIES} ROOT::EG ROOT::RooFit ROOT::RooFitCore) diff --git a/PWGHF/D2H/Macros/HFInvMassFitter.cxx b/PWGHF/D2H/Macros/HFInvMassFitter.cxx index 255de80a079..ba14190be6a 100644 --- a/PWGHF/D2H/Macros/HFInvMassFitter.cxx +++ b/PWGHF/D2H/Macros/HFInvMassFitter.cxx @@ -16,6 +16,7 @@ /// \author Mingyu Zhang /// \author Xinye Peng /// \author Biao Zhang +/// \author Oleksii Lubynets #include "HFInvMassFitter.h" @@ -33,9 +34,6 @@ #include #include #include - -#include -#include #include #include #include @@ -45,6 +43,9 @@ #include #include +#include +#include + #include #include #include diff --git a/PWGHF/D2H/Macros/HFInvMassFitter.h b/PWGHF/D2H/Macros/HFInvMassFitter.h index 8a236412a13..521b83bd465 100644 --- a/PWGHF/D2H/Macros/HFInvMassFitter.h +++ b/PWGHF/D2H/Macros/HFInvMassFitter.h @@ -16,6 +16,7 @@ /// \author Mingyu Zhang /// \author Xinye Peng /// \author Biao Zhang +/// \author Oleksii Lubynets #ifndef PWGHF_D2H_MACROS_HFINVMASSFITTER_H_ #define PWGHF_D2H_MACROS_HFINVMASSFITTER_H_ @@ -23,14 +24,14 @@ #include #include #include -#include -#include - #include #include #include #include +#include +#include + #include class HFInvMassFitter : public TNamed diff --git a/PWGHF/D2H/Macros/HFInvMassFitterLinkDef.h b/PWGHF/D2H/Macros/HFInvMassFitterLinkDef.h new file mode 100644 index 00000000000..cc755de478f --- /dev/null +++ b/PWGHF/D2H/Macros/HFInvMassFitterLinkDef.h @@ -0,0 +1,31 @@ +// 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 HFInvMassFitterLinkDef.h +/// \brief HFInvMassFitter dictionary definition file +/// +/// \author Zhen Zhang +/// \author Mingyu Zhang +/// \author Xinye Peng +/// \author Biao Zhang +/// \author Oleksii Lubynets + +#ifndef PWGHF_D2H_MACROS_HFINVMASSFITTERLINKDEF_H_ +#define PWGHF_D2H_MACROS_HFINVMASSFITTERLINKDEF_H_ + +#ifdef __CINT__ +#pragma link off all globals; +#pragma link off all classes; +#pragma link off all functions; +#pragma link C++ class HFInvMassFitter + ; +#endif + +#endif // PWGHF_D2H_MACROS_HFINVMASSFITTERLINKDEF_H_ diff --git a/PWGHF/D2H/Macros/README.md b/PWGHF/D2H/Macros/README.md new file mode 100644 index 00000000000..f65de110419 --- /dev/null +++ b/PWGHF/D2H/Macros/README.md @@ -0,0 +1,59 @@ +# Invariant-mass fitter +Invariant-mass fitter is implemented in the class `HFInvMassFitter` (`HFInvMassFitter.cxx/h` files), and its run is executed via `runMassFitter.C` macro. +Fitter is configured in `config_massfitter.json`.\ +The fitter is **not** a part of O2Physics source code. + +## Dependencies +1. ROOT +2. RapidJSON. Download the header-only (no compilation needed) RapidJSON library, see the link . + +If you have O2Physics compilation you do not need to fulfill these dependencies explicitly. + +## How to run +### As a ROOT macro +The `runMassFitter.C` can be compiled as ROOT macro. +```bash +cd path-to-o2physics-src/PWGHF/D2H/Macros +source path-to-root-install/bin/thisroot.sh +export ROOT_INCLUDE_PATH=$ROOT_INCLUDE_PATH:path-to-json-include +root -l -x -b -q "HFInvMassFitter.cxx" "runMassFitter.C(\"config_massfitter.json\")" +``` +If you have O2Physics compilation and enter into its environment there is no need to set environment variables (skip lines 2-3 above). + +### As a CMake project +It is also possible to compile the fitter as a CMake project or insert it into existing one if any. +Use the `CMakeLists_HFInvMassFitter.txt` (rename it into `CMakeLists.txt` before usage).\ +Compile the fitter with the following steps: +```bash +cd path-to-o2physics-src/PWGHF/D2H/Macros +mkdir build +cd build +source path-to-root-install/bin/thisroot.sh +cmake -DHFFITTER_RAPIDJSON_INCLUDE_DIRS=path-to-json-include ../ +make +``` +and run the fitter: +```bash +./runMassFitter ../config_massfitter.json +``` +### Directly from the terminal +Compile the fitter with the following steps: +```bash +cd path-to-o2physics-src/PWGHF/D2H/Macros +mkdir build +cd build +source path-to-root-install/bin/thisroot.sh + +# Generate ROOT dictionary: +rootcling -f G__HFInvMassFitter.cxx -c ../HFInvMassFitter.h ../HFInvMassFitterLinkDef.h + +# Compile source code: +g++ -fPIC -I$(root-config --incdir) -I path-to-json-include -c ../HFInvMassFitter.cxx ../runMassFitter.C G__HFInvMassFitter.cxx + +# Link the executable: +g++ -o runMassFitter HFInvMassFitter.o runMassFitter.o G__HFInvMassFitter.o $(root-config --libs) -lRooFit -lRooFitCore -lEG +``` +and run the fitter: +```bash +./runMassFitter ../config_massfitter.json +``` diff --git a/PWGHF/D2H/Macros/runMassFitter.C b/PWGHF/D2H/Macros/runMassFitter.C index 637171248cc..1181c13b814 100644 --- a/PWGHF/D2H/Macros/runMassFitter.C +++ b/PWGHF/D2H/Macros/runMassFitter.C @@ -16,12 +16,18 @@ /// \author Mingyu Zhang /// \author Xinye Peng /// \author Biao Zhang +/// \author Oleksii Lubynets #if !defined(__CINT__) || defined(__CLING__) #include "HFInvMassFitter.h" // if .h file not found, please include your local rapidjson/document.h and rapidjson/filereadstream.h here +#include +#include +#include +#include + #include #include @@ -30,10 +36,6 @@ #include // std::string #include // std::vector -#include -#include -#include - #endif using namespace rapidjson; @@ -672,3 +674,16 @@ void divideCanvas(TCanvas* canvas, int nSliceVarBins) } } } + +int main(int argc, char* argv[]) +{ + if (argc == 1) { + throw std::runtime_error("Not enough arguments. Please use\n./runMassFitter configFileName"); + } + + const std::string configFileName = argv[1]; + + runMassFitter(configFileName); + + return 0; +} From 0ed7e0515fadc3d12566135440abc488ed7babbf Mon Sep 17 00:00:00 2001 From: alcaliva <32872606+alcaliva@users.noreply.github.com> Date: Fri, 27 Jun 2025 12:36:33 +0200 Subject: [PATCH 234/871] [PWGLF] fixed typo in registry name (#11789) --- PWGLF/Tasks/Nuspex/antinucleiInJets.cxx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/PWGLF/Tasks/Nuspex/antinucleiInJets.cxx b/PWGLF/Tasks/Nuspex/antinucleiInJets.cxx index ad51876259b..9b3495484e0 100644 --- a/PWGLF/Tasks/Nuspex/antinucleiInJets.cxx +++ b/PWGLF/Tasks/Nuspex/antinucleiInJets.cxx @@ -280,10 +280,10 @@ struct AntinucleiInJets { registryMC.add("antiproton_incl_ue", "antiproton_incl_ue", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); // DCA Templates - registryData.add("antiproton_prim_dca_jet", "antiproton_prim_dca_jet", HistType::kTH2F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}, {200, -1, 1, "DCA_{xy} (cm)"}}); - registryData.add("antiproton_prim_dca_ue", "antiproton_prim_dca_ue", HistType::kTH2F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}, {200, -1, 1, "DCA_{xy} (cm)"}}); - registryData.add("antiproton_all_dca_jet", "antiproton_all_dca_jet", HistType::kTH2F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}, {200, -1, 1, "DCA_{xy} (cm)"}}); - registryData.add("antiproton_all_dca_ue", "antiproton_all_dca_ue", HistType::kTH2F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}, {200, -1, 1, "DCA_{xy} (cm)"}}); + registryMC.add("antiproton_prim_dca_jet", "antiproton_prim_dca_jet", HistType::kTH2F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}, {200, -1, 1, "DCA_{xy} (cm)"}}); + registryMC.add("antiproton_prim_dca_ue", "antiproton_prim_dca_ue", HistType::kTH2F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}, {200, -1, 1, "DCA_{xy} (cm)"}}); + registryMC.add("antiproton_all_dca_jet", "antiproton_all_dca_jet", HistType::kTH2F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}, {200, -1, 1, "DCA_{xy} (cm)"}}); + registryMC.add("antiproton_all_dca_ue", "antiproton_all_dca_ue", HistType::kTH2F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}, {200, -1, 1, "DCA_{xy} (cm)"}}); // antiproton reweighting registryMC.add("antiproton_eta_pt_pythia", "antiproton_eta_pt_pythia", HistType::kTH2F, {{200, 0.0, 10.0, "#it{p}_{T} (GeV/#it{c})"}, {20, -1.0, 1.0, "#it{#eta}"}}); From 7a5595fe560a9b57370aa7b4d4e226f3f1984c05 Mon Sep 17 00:00:00 2001 From: Samuele Cattaruzzi <124249902+scattaru@users.noreply.github.com> Date: Fri, 27 Jun 2025 15:46:20 +0200 Subject: [PATCH 235/871] [PWGHF] Ds-h correlation - Adding multi-dimensional histogram for efficiency correction (#11779) --- PWGHF/HFC/Tasks/taskCorrelationDsHadrons.cxx | 271 ++++++++++--------- 1 file changed, 141 insertions(+), 130 deletions(-) diff --git a/PWGHF/HFC/Tasks/taskCorrelationDsHadrons.cxx b/PWGHF/HFC/Tasks/taskCorrelationDsHadrons.cxx index 5722e3998f1..9b2b888249c 100644 --- a/PWGHF/HFC/Tasks/taskCorrelationDsHadrons.cxx +++ b/PWGHF/HFC/Tasks/taskCorrelationDsHadrons.cxx @@ -14,22 +14,22 @@ /// \author Grazia Luparello /// \author Samuele Cattaruzzi -#include -#include -#include -#include +#include "PWGHF/Core/HfHelper.h" +#include "PWGHF/Core/SelectorCuts.h" +#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "PWGHF/HFC/DataModel/CorrelationTables.h" +#include "PWGHF/Utils/utilsAnalysis.h" #include "CCDB/BasicCCDBManager.h" #include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" #include "Framework/runDataProcessing.h" -#include "PWGHF/Core/HfHelper.h" -#include "PWGHF/Core/SelectorCuts.h" -#include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" -#include "PWGHF/Utils/utilsAnalysis.h" -#include "PWGHF/HFC/DataModel/CorrelationTables.h" +#include +#include +#include +#include using namespace o2; using namespace o2::constants::physics; @@ -49,6 +49,7 @@ struct HfTaskCorrelationDsHadrons { Configurable removeCollWSplitVtx{"removeCollWSplitVtx", false, "Flag for rejecting the splitted collisions"}; Configurable loadAccXEffFromCCDB{"loadAccXEffFromCCDB", false, "Flag for loading efficiency distributions from CCDB"}; Configurable separateTrackOrigins{"separateTrackOrigins", false, "Flag to enable separation of track origins (from c or b)"}; + Configurable useHighDimHistoForEff{"useHighDimHistoForEff", false, "Flag to create higher dimension histograms in the efficiency processes"}; // Configurable doMcCollisionCheck{"doMcCollisionCheck", false, "Flag for applying the collision check and selection based on MC collision info"}; Configurable selectionFlagDs{"selectionFlagDs", 7, "Selection Flag for Ds (avoid the case of flag = 0, no outputMlScore)"}; Configurable nTpcCrossedRaws{"nTpcCrossedRaws", 70, "Number of crossed TPC Rows"}; @@ -92,23 +93,6 @@ struct HfTaskCorrelationDsHadrons { std::shared_ptr hEfficiencyAssociated = nullptr; const float epsilon = 1.e-8; - enum CandidateStep { - kCandidateStepMcGenDsToKKPi = 0, - kCandidateStepMcCandInAcceptance, - kCandidateStepMcDaughtersInAcceptance, - kCandidateStepMcReco, - kCandidateStepMcRecoInAcceptance, - kCandidateNSteps - }; - - enum AssocTrackStep { kAssocTrackStepMcGen = 0, - kAssocTrackStepMcGenInAcceptance, - kAssocTrackStepRecoAll, - kAssocTrackStepRecoMcMatch, - kAssocTrackStepRecoPrimaries, - kAssocTrackStepRecoSpecies, - kAssocTrackNSteps }; - HfHelper hfHelper; SliceCache cache; @@ -137,6 +121,7 @@ struct HfTaskCorrelationDsHadrons { ConfigurableAxis binsPhi{"binsPhi", {64, -PIHalf, 3. * PIHalf}, "#it{#varphi}"}; ConfigurableAxis binsMultFT0M{"binsMultFT0M", {600, 0., 8000.}, "Multiplicity as FT0M signal amplitude"}; ConfigurableAxis binsPosZ{"binsPosZ", {100, -10., 10.}, "primary vertex z coordinate"}; + ConfigurableAxis binsNumPvContr{"binsNumPvContr", {100, 0., 1000.}, "number PV contributors"}; ConfigurableAxis binsPoolBin{"binsPoolBin", {9, 0., 9.}, "PoolBin"}; HistogramRegistry registry{"registry", {}, OutputObjHandlingPolicy::AnalysisObject}; @@ -153,6 +138,7 @@ struct HfTaskCorrelationDsHadrons { AxisSpec axisBdtScore = {binsBdtScore, "Bdt score"}; AxisSpec axisMultFT0M = {binsMultFT0M, "MultiplicityFT0M"}; AxisSpec axisPosZ = {binsPosZ, "PosZ"}; + AxisSpec axisNumPvContr = {binsNumPvContr, "Num PV contributors"}; AxisSpec axisDsPrompt = {2, -0.5, 1.5, "Prompt Ds"}; // Histograms for data analysis @@ -212,41 +198,51 @@ struct HfTaskCorrelationDsHadrons { } // Histograms for efficiencies if (fillHistoMcEff) { - registry.add("hPtCandMcRecPrompt", "Ds prompt candidates pt", {HistType::kTH1F, {axisPtD}}); - registry.add("hPtCandMcRecNonPrompt", "Ds non prompt candidates pt", {HistType::kTH1F, {axisPtD}}); - registry.add("hPtCandMcGenPrompt", "Ds,Hadron particles prompt - MC Gen", {HistType::kTH1F, {axisPtD}}); - registry.add("hPtCandMcGenNonPrompt", "Ds,Hadron particles non prompt - MC Gen", {HistType::kTH1F, {axisPtD}}); - registry.add("hPtCandMcGenDaughterInAcc", "Ds,Hadron particles non prompt - MC Gen", {HistType::kTH1F, {axisPtD}}); - registry.add("hPtParticleAssocMcRec", "Associated Particle - MC Rec", {HistType::kTH1F, {axisPtHadron}}); - registry.add("hPtParticleAssocSpecieMcRec", "Associated Particle - MC Rec", {HistType::kTH1F, {axisPtHadron}}); - registry.add("hPtMcParticleAssocSpecieMcRec", "Associated Particle - MC Rec", {HistType::kTH1F, {axisPtHadron}}); - registry.add("hPtPrmPionMcRec", "Primary pions - MC Rec", {HistType::kTH1F, {axisPtHadron}}); - registry.add("hPtPrmKaonMcRec", "Primary kaons - MC Rec", {HistType::kTH1F, {axisPtHadron}}); - registry.add("hPtPrmProtonMcRec", "Primary protons - MC Rec", {HistType::kTH1F, {axisPtHadron}}); - registry.add("hPtPrmElectronMcRec", "Primary electrons - MC Rec", {HistType::kTH1F, {axisPtHadron}}); - registry.add("hPtPrmMuonMcRec", "Primary muons - MC Rec", {HistType::kTH1F, {axisPtHadron}}); - registry.add("hPtPrmPromptPartMcRec", "Primary prompt particles - MC Rec", {HistType::kTH1F, {axisPtHadron}}); - registry.add("hPtPrmNonPromptPartMcRec", "Primary non-prompt particles - MC Rec", {HistType::kTH1F, {axisPtHadron}}); - registry.add("hPtParticleAssocMcGen", "Associated Particle - MC Gen", {HistType::kTH1F, {axisPtHadron}}); - registry.add("hPtPrmPionMcGen", "Primary pions - MC Gen", {HistType::kTH1F, {axisPtHadron}}); - registry.add("hPtPrmKaonMcGen", "Primary kaons - MC Gen", {HistType::kTH1F, {axisPtHadron}}); - registry.add("hPtPrmProtonMcGen", "Primary protons - MC Gen", {HistType::kTH1F, {axisPtHadron}}); - registry.add("hPtPrmElectronMcGen", "Primary electrons - MC Gen", {HistType::kTH1F, {axisPtHadron}}); - registry.add("hPtPrmMuonMcGen", "Primary muons - MC Gen", {HistType::kTH1F, {axisPtHadron}}); - registry.add("hPtPrmPromptPartMcGen", "Primary prompt particles - MC Rec", {HistType::kTH1F, {axisPtHadron}}); - registry.add("hPtPrmNonPromptPartMcGen", "Primary non-prompt particles - MC Rec", {HistType::kTH1F, {axisPtHadron}}); registry.add("hFakeCollision", "Fake collision counter", {HistType::kTH1F, {{1, -0.5, 0.5, "n fake coll"}}}); registry.add("hFakeTracks", "Fake tracks counter", {HistType::kTH1F, {{1, -0.5, 0.5, "n fake tracks"}}}); - - auto hCandidates = registry.add("hCandidates", "Candidate count at different steps", {HistType::kStepTHnF, {axisPtD, axisMultFT0M, {RecoDecay::OriginType::NonPrompt + 1, +RecoDecay::OriginType::None - 0.5, +RecoDecay::OriginType::NonPrompt + 0.5}}, kCandidateNSteps}); - hCandidates->GetAxis(0)->SetTitle("#it{p}_{T} (GeV/#it{c})"); - hCandidates->GetAxis(1)->SetTitle("multiplicity"); - hCandidates->GetAxis(2)->SetTitle("Charm hadron origin"); - auto hAssocTracks = registry.add("hAssocTracks", "Associated tracks at different steps", {HistType::kStepTHnF, {axisEta, axisPtHadron, axisMultFT0M, axisPosZ}, kAssocTrackNSteps}); - hAssocTracks->GetAxis(0)->SetTitle("#eta"); - hAssocTracks->GetAxis(1)->SetTitle("#it{p}_{T} (GeV/#it{c})"); - hAssocTracks->GetAxis(2)->SetTitle("multiplicity"); - hAssocTracks->GetAxis(3)->SetTitle("pos z"); + registry.add("hNumPvContrib", "Num PV contributors", {HistType::kTH1F, {axisNumPvContr}}); + registry.add("hPtPrmPromptPartMcGen", "Primary prompt particles - MC Rec", {HistType::kTH1F, {axisPtHadron}}); + registry.add("hPtPrmNonPromptPartMcGen", "Primary non-prompt particles - MC Rec", {HistType::kTH1F, {axisPtHadron}}); + registry.add("hPtPrmPromptPartMcRec", "Primary prompt particles - MC Rec", {HistType::kTH1F, {axisPtHadron}}); + registry.add("hPtPrmNonPromptPartMcRec", "Primary non-prompt particles - MC Rec", {HistType::kTH1F, {axisPtHadron}}); + registry.add("hPtCandMcGenDaughterInAcc", "Ds,Hadron particles non prompt - MC Gen", {HistType::kTH1F, {axisPtD}}); + if (useHighDimHistoForEff) { + registry.add("hPtCandMcRecPrompt", "Ds prompt candidates", {HistType::kTH2F, {{axisPtD}, {axisNumPvContr}}}); + registry.add("hPtCandMcRecNonPrompt", "Ds non prompt candidates pt", {HistType::kTH2F, {{axisPtD}, {axisNumPvContr}}}); + registry.add("hPtCandMcGenPrompt", "Ds,Hadron particles prompt - MC Gen", {HistType::kTH2F, {{axisPtD}, {axisNumPvContr}}}); + registry.add("hPtCandMcGenNonPrompt", "Ds,Hadron particles non prompt - MC Gen", {HistType::kTH2F, {{axisPtD}, {axisNumPvContr}}}); + registry.add("hPtParticleAssocSpecieMcRec", "Associated Particle - MC Rec", {HistType::kTHnSparseF, {axisPtHadron}}); + registry.add("hPtPrmPionMcRec", "Primary pions - MC Rec", {HistType::kTHnSparseF, {{axisPtHadron}, {axisEta}, {axisPosZ}, {axisNumPvContr}}}); + registry.add("hPtPrmKaonMcRec", "Primary kaons - MC Rec", {HistType::kTHnSparseF, {{axisPtHadron}, {axisEta}, {axisPosZ}, {axisNumPvContr}}}); + registry.add("hPtPrmProtonMcRec", "Primary protons - MC Rec", {HistType::kTHnSparseF, {{axisPtHadron}, {axisEta}, {axisPosZ}, {axisNumPvContr}}}); + registry.add("hPtPrmElectronMcRec", "Primary electrons - MC Rec", {HistType::kTHnSparseF, {{axisPtHadron}, {axisEta}, {axisPosZ}, {axisNumPvContr}}}); + registry.add("hPtPrmMuonMcRec", "Primary muons - MC Rec", {HistType::kTHnSparseF, {{axisPtHadron}, {axisEta}, {axisPosZ}, {axisNumPvContr}}}); + registry.add("hPtParticleAssocMcGen", "Associated Particle - MC Gen", {HistType::kTHnSparseF, {{axisPtHadron}, {axisEta}, {axisPosZ}, {axisNumPvContr}}}); + registry.add("hPtPrmPionMcGen", "Primary pions - MC Gen", {HistType::kTHnSparseF, {{axisPtHadron}, {axisEta}, {axisPosZ}, {axisNumPvContr}}}); + registry.add("hPtPrmKaonMcGen", "Primary kaons - MC Gen", {HistType::kTHnSparseF, {{axisPtHadron}, {axisEta}, {axisPosZ}, {axisNumPvContr}}}); + registry.add("hPtPrmProtonMcGen", "Primary protons - MC Gen", {HistType::kTHnSparseF, {{axisPtHadron}, {axisEta}, {axisPosZ}, {axisNumPvContr}}}); + registry.add("hPtPrmElectronMcGen", "Primary electrons - MC Gen", {HistType::kTHnSparseF, {{axisPtHadron}, {axisEta}, {axisPosZ}, {axisNumPvContr}}}); + registry.add("hPtPrmMuonMcGen", "Primary muons - MC Gen", {HistType::kTHnSparseF, {{axisPtHadron}, {axisEta}, {axisPosZ}, {axisNumPvContr}}}); + } else { + registry.add("hPtCandMcRecPrompt", "Ds prompt candidates pt", {HistType::kTH1F, {axisPtD}}); + registry.add("hPtCandMcRecNonPrompt", "Ds non prompt candidates pt", {HistType::kTH1F, {axisPtD}}); + registry.add("hPtCandMcGenPrompt", "Ds,Hadron particles prompt - MC Gen", {HistType::kTH1F, {axisPtD}}); + registry.add("hPtCandMcGenNonPrompt", "Ds,Hadron particles non prompt - MC Gen", {HistType::kTH1F, {axisPtD}}); + registry.add("hPtParticleAssocMcRec", "Associated Particle - MC Rec", {HistType::kTH1F, {axisPtHadron}}); + registry.add("hPtParticleAssocSpecieMcRec", "Associated Particle - MC Rec", {HistType::kTH1F, {axisPtHadron}}); + registry.add("hPtMcParticleAssocSpecieMcRec", "Associated Particle - MC Rec", {HistType::kTH1F, {axisPtHadron}}); + registry.add("hPtPrmPionMcRec", "Primary pions - MC Rec", {HistType::kTH1F, {axisPtHadron}}); + registry.add("hPtPrmKaonMcRec", "Primary kaons - MC Rec", {HistType::kTH1F, {axisPtHadron}}); + registry.add("hPtPrmProtonMcRec", "Primary protons - MC Rec", {HistType::kTH1F, {axisPtHadron}}); + registry.add("hPtPrmElectronMcRec", "Primary electrons - MC Rec", {HistType::kTH1F, {axisPtHadron}}); + registry.add("hPtPrmMuonMcRec", "Primary muons - MC Rec", {HistType::kTH1F, {axisPtHadron}}); + registry.add("hPtParticleAssocMcGen", "Associated Particle - MC Gen", {HistType::kTH1F, {axisPtHadron}}); + registry.add("hPtPrmPionMcGen", "Primary pions - MC Gen", {HistType::kTH1F, {axisPtHadron}}); + registry.add("hPtPrmKaonMcGen", "Primary kaons - MC Gen", {HistType::kTH1F, {axisPtHadron}}); + registry.add("hPtPrmProtonMcGen", "Primary protons - MC Gen", {HistType::kTH1F, {axisPtHadron}}); + registry.add("hPtPrmElectronMcGen", "Primary electrons - MC Gen", {HistType::kTH1F, {axisPtHadron}}); + registry.add("hPtPrmMuonMcGen", "Primary muons - MC Gen", {HistType::kTH1F, {axisPtHadron}}); + } } // Loading efficiency histograms from CCDB @@ -281,7 +277,6 @@ struct HfTaskCorrelationDsHadrons { return (ptBinD != -1 && bdtScorePrompt >= mlOutputPromptMin->at(ptBinD) && bdtScorePrompt <= mlOutputPromptMax->at(ptBinD) && bdtScoreBkg <= mlOutputBkg->at(ptBinD)); } - // template double getEfficiencyWeight(float ptD, std::optional ptAssoc = std::nullopt, EfficiencyMode mode = EfficiencyMode::DsOnly) { if (!applyEfficiency) { @@ -674,8 +669,6 @@ struct HfTaskCorrelationDsHadrons { CandDsMcReco const& candidates, aod::TracksWMc const&) { - auto hCandidates = registry.get(HIST("hCandidates")); - /// loop over generated collisions for (const auto& mcCollision : mcCollisions) { @@ -707,38 +700,42 @@ struct HfTaskCorrelationDsHadrons { continue; } - float multiplicityReco = collision.multFT0M(); - float multiplicityGen = mcCollision.multMCFT0A() + mcCollision.multMCFT0C(); // multFT0M = multFt0A + multFT0C + registry.fill(HIST("hNumPvContrib"), collision.numContrib()); const auto groupedCandidates = candidates.sliceBy(perCollisionCand, collision.globalIndex()); // generated candidate loop for (const auto& mcParticle : groupedMcParticles) { if ((std::abs(mcParticle.flagMcMatchGen()) == hf_decay::hf_cand_3prong::DecayChannelMain::DsToPiKK) && (mcParticle.flagMcDecayChanGen() == decayChannel)) { - hCandidates->Fill(kCandidateStepMcGenDsToKKPi, mcParticle.pt(), multiplicityGen, mcParticle.originMcGen()); auto yDs = RecoDecay::y(mcParticle.pVector(), o2::constants::physics::MassDS); if (std::abs(yDs) <= yCandGenMax) { - hCandidates->Fill(kCandidateStepMcCandInAcceptance, mcParticle.pt(), multiplicityGen, mcParticle.originMcGen()); if (mcParticle.originMcGen() == RecoDecay::OriginType::Prompt) { - registry.fill(HIST("hPtCandMcGenPrompt"), mcParticle.pt()); + if (useHighDimHistoForEff) { + registry.fill(HIST("hPtCandMcGenPrompt"), mcParticle.pt(), collision.numContrib()); + } else { + registry.fill(HIST("hPtCandMcGenPrompt"), mcParticle.pt()); + } + if (mcParticle.originMcGen() == RecoDecay::OriginType::NonPrompt) { + if (useHighDimHistoForEff) { + registry.fill(HIST("hPtCandMcGenNonPrompt"), mcParticle.pt(), collision.numContrib()); + } else { + registry.fill(HIST("hPtCandMcGenNonPrompt"), mcParticle.pt()); + } + } } - if (mcParticle.originMcGen() == RecoDecay::OriginType::NonPrompt) { - registry.fill(HIST("hPtCandMcGenNonPrompt"), mcParticle.pt()); + bool isDaughterInAcceptance = true; + auto daughters = mcParticle.template daughters_as(); + for (const auto& daughter : daughters) { + if (daughter.pt() < ptDaughterMin || std::abs(daughter.eta()) > etaTrackMax) { + isDaughterInAcceptance = false; + } } - } - bool isDaughterInAcceptance = true; - auto daughters = mcParticle.template daughters_as(); - for (const auto& daughter : daughters) { - if (daughter.pt() < ptDaughterMin || std::abs(daughter.eta()) > etaTrackMax) { - isDaughterInAcceptance = false; + if (isDaughterInAcceptance) { + registry.fill(HIST("hPtCandMcGenDaughterInAcc"), mcParticle.pt()); } } - if (isDaughterInAcceptance) { - hCandidates->Fill(kCandidateStepMcDaughtersInAcceptance, mcParticle.pt(), multiplicityGen, mcParticle.originMcGen()); - registry.fill(HIST("hPtCandMcGenDaughterInAcc"), mcParticle.pt()); - } } - } + } // end loop candidate gen // reconstructed candidate loop for (const auto& candidate : groupedCandidates) { @@ -763,20 +760,25 @@ struct HfTaskCorrelationDsHadrons { auto prong0McPart = candidate.template prong0_as().template mcParticle_as(); // DsToKKPi and DsToPiKK division if (((std::abs(prong0McPart.pdgCode()) == kKPlus) && (candidate.isSelDsToKKPi() >= selectionFlagDs)) || ((std::abs(prong0McPart.pdgCode()) == kPiPlus) && (candidate.isSelDsToPiKK() >= selectionFlagDs))) { - hCandidates->Fill(kCandidateStepMcReco, candidate.pt(), multiplicityReco, candidate.originMcRec()); if (std::abs(hfHelper.yDs(candidate)) <= yCandMax) { - hCandidates->Fill(kCandidateStepMcRecoInAcceptance, candidate.pt(), multiplicityReco, candidate.originMcRec()); if (candidate.originMcRec() == RecoDecay::OriginType::Prompt) { - registry.fill(HIST("hPtCandMcRecPrompt"), candidate.pt()); + if (useHighDimHistoForEff) { + registry.fill(HIST("hPtCandMcRecPrompt"), candidate.pt(), collision.numContrib()); + } else { + registry.fill(HIST("hPtCandMcRecPrompt"), candidate.pt()); + } } if (candidate.originMcRec() == RecoDecay::OriginType::NonPrompt) { - registry.fill(HIST("hPtCandMcRecNonPrompt"), candidate.pt()); + if (useHighDimHistoForEff) { + registry.fill(HIST("hPtCandMcRecNonPrompt"), candidate.pt(), collision.numContrib()); + } else { + registry.fill(HIST("hPtCandMcRecNonPrompt"), candidate.pt()); + } } } } } - } - + } // end loop candidate reco } // end loop reconstructed collision } // end loop generated collisions } @@ -788,19 +790,12 @@ struct HfTaskCorrelationDsHadrons { CandDsMcReco const& candidates, aod::TracksWMc const&) { - auto hCandidates = registry.get(HIST("hCandidates")); - /// Gen loop - float multiplicity = -1.; for (const auto& mcParticle : mcParticles) { // generated candidates if ((std::abs(mcParticle.flagMcMatchGen()) == hf_decay::hf_cand_3prong::DecayChannelMain::DsToPiKK) && (mcParticle.flagMcDecayChanGen() == decayChannel)) { - auto mcCollision = mcParticle.template mcCollision_as>(); - multiplicity = mcCollision.multMCFT0A() + mcCollision.multMCFT0C(); // multFT0M = multFt0A + multFT0C - hCandidates->Fill(kCandidateStepMcGenDsToKKPi, mcParticle.pt(), multiplicity, mcParticle.originMcGen()); auto yDs = RecoDecay::y(mcParticle.pVector(), o2::constants::physics::MassDS); if (std::abs(yDs) <= yCandGenMax) { - hCandidates->Fill(kCandidateStepMcCandInAcceptance, mcParticle.pt(), multiplicity, mcParticle.originMcGen()); if (mcParticle.originMcGen() == RecoDecay::OriginType::Prompt) { registry.fill(HIST("hPtCandMcGenPrompt"), mcParticle.pt()); } @@ -816,7 +811,6 @@ struct HfTaskCorrelationDsHadrons { } } if (isDaughterInAcceptance) { - hCandidates->Fill(kCandidateStepMcDaughtersInAcceptance, mcParticle.pt(), multiplicity, mcParticle.originMcGen()); registry.fill(HIST("hPtCandMcGenDaughterInAcc"), mcParticle.pt()); } } @@ -844,14 +838,11 @@ struct HfTaskCorrelationDsHadrons { if (selNoSameBunchPileUpColl && !(collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup))) { continue; } - multiplicity = collision.multFT0M(); if ((std::abs(candidate.flagMcMatchRec()) == hf_decay::hf_cand_3prong::DecayChannelMain::DsToPiKK) && (candidate.flagMcDecayChanRec() == decayChannel)) { auto prong0McPart = candidate.template prong0_as().template mcParticle_as(); // DsToKKPi and DsToPiKK division if (((std::abs(prong0McPart.pdgCode()) == kKPlus) && (candidate.isSelDsToKKPi() >= selectionFlagDs)) || ((std::abs(prong0McPart.pdgCode()) == kPiPlus) && (candidate.isSelDsToPiKK() >= selectionFlagDs))) { - hCandidates->Fill(kCandidateStepMcReco, candidate.pt(), multiplicity, candidate.originMcRec()); if (std::abs(hfHelper.yDs(candidate)) <= yCandMax) { - hCandidates->Fill(kCandidateStepMcRecoInAcceptance, candidate.pt(), multiplicity, candidate.originMcRec()); if (candidate.originMcRec() == RecoDecay::OriginType::Prompt) { registry.fill(HIST("hPtCandMcRecPrompt"), candidate.pt()); } @@ -904,31 +895,39 @@ struct HfTaskCorrelationDsHadrons { continue; } - float multiplicityReco = collision.multFT0M(); - float posZReco = collision.posZ(); - float multiplicityGen = mcCollision.multMCFT0A() + mcCollision.multMCFT0C(); // multFT0M = multFt0A + multFT0C - float posZGen = mcCollision.posZ(); - const auto groupedTracks = tracksData.sliceBy(perCollision, collision.globalIndex()); // generated track loop for (const auto& mcParticle : groupedMcParticles) { if (mcParticle.isPhysicalPrimary() && ((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))) { if (mcParticle.pt() > ptTrackMin && mcParticle.pt() < ptTrackMax) { - hAssocTracks->Fill(kAssocTrackStepMcGen, mcParticle.eta(), mcParticle.pt(), multiplicityGen, posZGen); if (std::abs(mcParticle.eta()) < etaTrackMax) { - hAssocTracks->Fill(kAssocTrackStepMcGenInAcceptance, mcParticle.eta(), mcParticle.pt(), multiplicityGen, posZGen); - registry.fill(HIST("hPtParticleAssocMcGen"), mcParticle.pt()); - if (std::abs(mcParticle.pdgCode()) == kPiPlus) { - registry.fill(HIST("hPtPrmPionMcGen"), mcParticle.pt()); - } else if (std::abs(mcParticle.pdgCode()) == kKPlus) { - registry.fill(HIST("hPtPrmKaonMcGen"), mcParticle.pt()); - } else if (std::abs(mcParticle.pdgCode()) == kProton) { - registry.fill(HIST("hPtPrmProtonMcGen"), mcParticle.pt()); - } else if (std::abs(mcParticle.pdgCode()) == kElectron) { - registry.fill(HIST("hPtPrmElectronMcGen"), mcParticle.pt()); - } else if (std::abs(mcParticle.pdgCode()) == kMuonMinus) { - registry.fill(HIST("hPtPrmMuonMcGen"), mcParticle.pt()); + if (useHighDimHistoForEff) { + registry.fill(HIST("hPtParticleAssocMcGen"), mcParticle.pt(), mcParticle.eta(), collision.posZ(), collision.numContrib()); + if (std::abs(mcParticle.pdgCode()) == kPiPlus) { + registry.fill(HIST("hPtPrmPionMcGen"), mcParticle.pt(), mcParticle.eta(), collision.posZ(), collision.numContrib()); + } else if (std::abs(mcParticle.pdgCode()) == kKPlus) { + registry.fill(HIST("hPtPrmKaonMcGen"), mcParticle.pt(), mcParticle.eta(), collision.posZ(), collision.numContrib()); + } else if (std::abs(mcParticle.pdgCode()) == kProton) { + registry.fill(HIST("hPtPrmProtonMcGen"), mcParticle.pt(), mcParticle.eta(), collision.posZ(), collision.numContrib()); + } else if (std::abs(mcParticle.pdgCode()) == kElectron) { + registry.fill(HIST("hPtPrmElectronMcGen"), mcParticle.pt(), mcParticle.eta(), collision.posZ(), collision.numContrib()); + } else if (std::abs(mcParticle.pdgCode()) == kMuonMinus) { + registry.fill(HIST("hPtPrmMuonMcGen"), mcParticle.pt(), mcParticle.eta(), collision.posZ(), collision.numContrib()); + } + } else { + registry.fill(HIST("hPtParticleAssocMcGen"), mcParticle.pt()); + if (std::abs(mcParticle.pdgCode()) == kPiPlus) { + registry.fill(HIST("hPtPrmPionMcGen"), mcParticle.pt()); + } else if (std::abs(mcParticle.pdgCode()) == kKPlus) { + registry.fill(HIST("hPtPrmKaonMcGen"), mcParticle.pt()); + } else if (std::abs(mcParticle.pdgCode()) == kProton) { + registry.fill(HIST("hPtPrmProtonMcGen"), mcParticle.pt()); + } else if (std::abs(mcParticle.pdgCode()) == kElectron) { + registry.fill(HIST("hPtPrmElectronMcGen"), mcParticle.pt()); + } else if (std::abs(mcParticle.pdgCode()) == kMuonMinus) { + registry.fill(HIST("hPtPrmMuonMcGen"), mcParticle.pt()); + } } if (separateTrackOrigins) { int trackOrigin = RecoDecay::getCharmHadronOrigin(mcParticles, mcParticle, true); @@ -949,26 +948,38 @@ struct HfTaskCorrelationDsHadrons { continue; } if (track.has_mcParticle()) { - hAssocTracks->Fill(kAssocTrackStepRecoMcMatch, track.eta(), track.pt(), multiplicityReco, posZReco); auto mcParticle = track.template mcParticle_as(); if (mcParticle.isPhysicalPrimary()) { - hAssocTracks->Fill(kAssocTrackStepRecoPrimaries, track.eta(), track.pt(), multiplicityReco, posZReco); registry.fill(HIST("hPtParticleAssocMcRec"), track.pt()); 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)) { - hAssocTracks->Fill(kAssocTrackStepRecoSpecies, track.eta(), track.pt(), multiplicityReco, posZReco); - registry.fill(HIST("hPtParticleAssocSpecieMcRec"), track.pt()); // check the pt spectra of mcParticle registry.fill(HIST("hPtMcParticleAssocSpecieMcRec"), mcParticle.pt()); - if (std::abs(mcParticle.pdgCode()) == kPiPlus) { - registry.fill(HIST("hPtPrmPionMcRec"), track.pt()); - } else if (std::abs(mcParticle.pdgCode()) == kKPlus) { - registry.fill(HIST("hPtPrmKaonMcRec"), track.pt()); - } else if (std::abs(mcParticle.pdgCode()) == kProton) { - registry.fill(HIST("hPtPrmProtonMcRec"), track.pt()); - } else if (std::abs(mcParticle.pdgCode()) == kElectron) { - registry.fill(HIST("hPtPrmElectronMcRec"), track.pt()); - } else if (std::abs(mcParticle.pdgCode()) == kMuonMinus) { - registry.fill(HIST("hPtPrmMuonMcRec"), track.pt()); + if (useHighDimHistoForEff) { + registry.fill(HIST("hPtParticleAssocSpecieMcRec"), track.pt()); + if (std::abs(mcParticle.pdgCode()) == kPiPlus) { + registry.fill(HIST("hPtPrmPionMcRec"), track.pt(), track.eta(), collision.posZ(), collision.numContrib()); + } else if (std::abs(mcParticle.pdgCode()) == kKPlus) { + registry.fill(HIST("hPtPrmKaonMcRec"), track.pt(), track.eta(), collision.posZ(), collision.numContrib()); + } else if (std::abs(mcParticle.pdgCode()) == kProton) { + registry.fill(HIST("hPtPrmProtonMcRec"), track.pt(), track.eta(), collision.posZ(), collision.numContrib()); + } else if (std::abs(mcParticle.pdgCode()) == kElectron) { + registry.fill(HIST("hPtPrmElectronMcRec"), track.pt(), track.eta(), collision.posZ(), collision.numContrib()); + } else if (std::abs(mcParticle.pdgCode()) == kMuonMinus) { + registry.fill(HIST("hPtPrmMuonMcRec"), track.pt(), track.eta(), collision.posZ(), collision.numContrib()); + } + } else { + registry.fill(HIST("hPtParticleAssocSpecieMcRec"), track.pt()); + if (std::abs(mcParticle.pdgCode()) == kPiPlus) { + registry.fill(HIST("hPtPrmPionMcRec"), track.pt()); + } else if (std::abs(mcParticle.pdgCode()) == kKPlus) { + registry.fill(HIST("hPtPrmKaonMcRec"), track.pt()); + } else if (std::abs(mcParticle.pdgCode()) == kProton) { + registry.fill(HIST("hPtPrmProtonMcRec"), track.pt()); + } else if (std::abs(mcParticle.pdgCode()) == kElectron) { + registry.fill(HIST("hPtPrmElectronMcRec"), track.pt()); + } else if (std::abs(mcParticle.pdgCode()) == kMuonMinus) { + registry.fill(HIST("hPtPrmMuonMcRec"), track.pt()); + } } // check track origin if (separateTrackOrigins) { From f812e665e4547cc9b5a6a2c568028b7745e4145c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Jacazio?= Date: Fri, 27 Jun 2025 16:00:19 +0200 Subject: [PATCH 236/871] [PWGLF] Init PID ITS in LFNucleiBATask (#11796) --- PWGLF/Tasks/Nuspex/LFNucleiBATask.cxx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/PWGLF/Tasks/Nuspex/LFNucleiBATask.cxx b/PWGLF/Tasks/Nuspex/LFNucleiBATask.cxx index f3f57325bac..407b13fcb77 100644 --- a/PWGLF/Tasks/Nuspex/LFNucleiBATask.cxx +++ b/PWGLF/Tasks/Nuspex/LFNucleiBATask.cxx @@ -112,6 +112,7 @@ struct LFNucleiBATask { } kinemOptions; Configurable isPVContributorCut{"isPVContributorCut", false, "Flag to enable isPVContributor cut."}; + Configurable initITSPID{"initITSPID", false, "Flag to init the ITS PID response"}; struct : ConfigurableGroup { Configurable nsigmaTPCPr{"nsigmaTPCPr", 3.f, "Value of the Nsigma TPC cut for protons"}; @@ -241,8 +242,11 @@ struct LFNucleiBATask { } } - void init(o2::framework::InitContext&) + void init(o2::framework::InitContext& context) { + if (initITSPID) { + o2::aod::ITSResponse::setParameters(context); + } if (skimmingOptions.applySkimming) { zorroSummary.setObject(zorro.getZorroSummary()); } From 1ccb3bdf33f3f8265bb8b931d0c49cbd0bd8a01a Mon Sep 17 00:00:00 2001 From: Anantha Padmanabhan M Nair <82643666+ananthapadmanabhan18@users.noreply.github.com> Date: Fri, 27 Jun 2025 19:30:27 +0530 Subject: [PATCH 237/871] [PWGUD] Added Condition for pass5 data and selection of (cos theta, phi) by larger mass (#11802) --- PWGUD/Tasks/exclusiveRhoTo4Pi.cxx | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/PWGUD/Tasks/exclusiveRhoTo4Pi.cxx b/PWGUD/Tasks/exclusiveRhoTo4Pi.cxx index 153eb19907e..e40ff901666 100644 --- a/PWGUD/Tasks/exclusiveRhoTo4Pi.cxx +++ b/PWGUD/Tasks/exclusiveRhoTo4Pi.cxx @@ -528,6 +528,7 @@ struct ExclusiveRhoTo4Pi { Configurable occupancyCut{"occupancyCut", 20000, "Occupancy Cut"}; Configurable numPVContrib{"numPVContrib", 4, "Number of PV Contributors"}; Configurable checkOneTof{"checkOneTof", 1, " (1 or 0)Check if event has at least 1 TOF"}; + Configurable ifPass5{"ifPass5", true, "If pass 5 data is used"}; // bc selection cuts Configurable sbpCut{"sbpCut", 1, "Sbp"}; @@ -680,6 +681,13 @@ struct ExclusiveRhoTo4Pi { histosData.add("phi_vs_costheta_1", "Phi vs cosTheta; #phi; cos(#theta)", kTH2F, {phiAxis, cosThetaAxis}); histosData.add("phi_vs_costheta_2", "Phi vs cosTheta; #phi; cos(#theta)", kTH2F, {phiAxis, cosThetaAxis}); + histosData.add("collin_soper_phi_small_mass", "#phi Distribution; #phi; Events", kTH1F, {phiAxis}); + histosData.add("collin_soper_phi_large_mass", "#phi Distribution; #phi; Events", kTH1F, {phiAxis}); + histosData.add("collin_soper_costheta_small_mass", "#theta Distribution;cos(#theta); Counts", kTH1F, {cosThetaAxis}); + histosData.add("collin_soper_costheta_large_mass", "#theta Distribution;cos(#theta); Counts", kTH1F, {cosThetaAxis}); + histosData.add("phi_vs_costheta_small_mass", "Phi vs cosTheta for small mass; #phi; cos(#theta)", kTH2F, {phiAxis, cosThetaAxis}); + histosData.add("phi_vs_costheta_large_mass", "Phi vs cosTheta for large mass; #phi; cos(#theta)", kTH2F, {phiAxis, cosThetaAxis}); + // MC Gen Stuff // counts @@ -888,10 +896,12 @@ struct ExclusiveRhoTo4Pi { void processData(UDCollision const& collision, UDtracks const& tracks) { - if (!(collision.sbp() == sbpCut && collision.itsROFb() == itsROFbCut && collision.vtxITSTPC() == vtxITSTPCcut && collision.tfb() == tfbCut)) { + if (ifPass5 && (!(collision.sbp() == sbpCut && collision.itsROFb() == itsROFbCut && collision.vtxITSTPC() == vtxITSTPCcut && collision.tfb() == tfbCut))) { return; } + histosData.fill(HIST("EventsCounts_vs_runNo"), collision.runNumber(), 0); + int gapSide = collision.gapSide(); std::vector parameters = {pvCut, dcaZcut, dcaXYcut, tpcChi2Cut, tpcNClsFindableCut, itsChi2Cut, etaCut, pTcut}; int truegapSide = sgSelector.trueGap(collision, fv0Cut, ft0aCut, ft0cCut, zdcCut); @@ -1124,6 +1134,23 @@ struct ExclusiveRhoTo4Pi { histosData.fill(HIST("collin_soper_costheta_2"), fourPiCosThetaPair2); histosData.fill(HIST("phi_vs_costheta_1"), fourPiPhiPair1, fourPiCosThetaPair1); histosData.fill(HIST("phi_vs_costheta_2"), fourPiPhiPair2, fourPiCosThetaPair2); + + // Small Mass CosTheta and Phi + if ((k13.M() + k24.M()) > (k14.M() + k23.M())) { + histosData.fill(HIST("collin_soper_phi_large_mass"), fourPiPhiPair1); + histosData.fill(HIST("collin_soper_costheta_large_mass"), fourPiCosThetaPair1); + histosData.fill(HIST("phi_vs_costheta_large_mass"), fourPiPhiPair1, fourPiCosThetaPair1); + histosData.fill(HIST("collin_soper_phi_small_mass"), fourPiPhiPair2); + histosData.fill(HIST("collin_soper_costheta_small_mass"), fourPiCosThetaPair2); + histosData.fill(HIST("phi_vs_costheta_small_mass"), fourPiPhiPair2, fourPiCosThetaPair2); + } else { + histosData.fill(HIST("collin_soper_phi_small_mass"), fourPiPhiPair1); + histosData.fill(HIST("collin_soper_costheta_small_mass"), fourPiCosThetaPair1); + histosData.fill(HIST("phi_vs_costheta_small_mass"), fourPiPhiPair1, fourPiCosThetaPair1); + histosData.fill(HIST("collin_soper_phi_large_mass"), fourPiPhiPair2); + histosData.fill(HIST("collin_soper_costheta_large_mass"), fourPiCosThetaPair2); + histosData.fill(HIST("phi_vs_costheta_large_mass"), fourPiPhiPair2, fourPiCosThetaPair2); + } } if (p1234.Pt() > rhoPtCut && p1234.Pt() < zeroPointEight) { histosData.fill(HIST("fourpion_mass_0_charge_domB"), p1234.M()); From 9fc053fc2661acdcb57b48a8ab0fdb11a1fe5cc4 Mon Sep 17 00:00:00 2001 From: tutripat <73981392+tutripat@users.noreply.github.com> Date: Fri, 27 Jun 2025 16:48:50 +0200 Subject: [PATCH 238/871] [PWGLF] Modification in event selection cuts (#11805) Co-authored-by: ALICE Action Bot --- .../GlobalEventProperties/dndeta-mft-pp.cxx | 124 +++++++++--------- 1 file changed, 65 insertions(+), 59 deletions(-) diff --git a/PWGLF/Tasks/GlobalEventProperties/dndeta-mft-pp.cxx b/PWGLF/Tasks/GlobalEventProperties/dndeta-mft-pp.cxx index 452a040d92f..6edb6b9a497 100644 --- a/PWGLF/Tasks/GlobalEventProperties/dndeta-mft-pp.cxx +++ b/PWGLF/Tasks/GlobalEventProperties/dndeta-mft-pp.cxx @@ -15,14 +15,14 @@ // \brief This code loops over MFT tracks and collisions and fills histograms // useful to compute dNdeta -#include -#include -#include -#include -#include -#include -#include +#include "PWGMM/Mult/DataModel/bestCollisionTable.h" + +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "CommonConstants/MathConstants.h" #include "Framework/ASoAHelpers.h" #include "Framework/AnalysisDataModel.h" #include "Framework/AnalysisTask.h" @@ -30,19 +30,18 @@ #include "Framework/O2DatabasePDGPlugin.h" #include "Framework/RuntimeError.h" #include "Framework/runDataProcessing.h" - -#include "Common/DataModel/Centrality.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "CommonConstants/MathConstants.h" #include "MathUtils/Utils.h" #include "ReconstructionDataFormats/GlobalTrackID.h" -#include "TDatabasePDG.h" -#include "PWGMM/Mult/DataModel/bestCollisionTable.h" #include "TFile.h" +#include +#include +#include +#include +#include +#include + using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; @@ -51,7 +50,7 @@ using namespace o2::aod::track; AxisSpec PtAxis = {1001, -0.005, 10.005}; AxisSpec DeltaZAxis = {61, -6.1, 6.1}; AxisSpec ZAxis = {301, -30.1, 30.1}; -AxisSpec PhiAxis = {629, 0, 2 * M_PI, "Rad", "phi axis"}; +AxisSpec PhiAxis = {629, 0, o2::constants::math::TwoPI, "Rad", "phi axis"}; // AxisSpec EtaAxis = {18, -4.6, -1.}; AxisSpec DCAxyAxis = {100, -1, 10}; AxisSpec CentAxis = {{0, 10, 20, 30, 40, 50, 60, 70, 80, 100}}; @@ -82,6 +81,7 @@ struct PseudorapidityDensityMFT { "eta range for INEL>0 sample definition"}; Configurable useEvSel{"useEvSel", true, "use event selection"}; + Configurable disableITSROFCut{"disableITSROFCut", false, "Disable ITS ROC cut for event selection"}; ConfigurableAxis multBinning{"multBinning", {701, -0.5, 700.5}, ""}; ConfigurableAxis EtaAxis = {"etaBinning", {18, -4.6, -1.}, ""}; @@ -145,15 +145,15 @@ struct PseudorapidityDensityMFT { auto hstat = registry.get(HIST("EventSelection")); auto* x = hstat->GetXaxis(); x->SetBinLabel(1, "All"); - x->SetBinLabel(2, "Selected"); - x->SetBinLabel(3, "Selected Vz Cut"); - x->SetBinLabel(4, "Sel8+Vz+INEL>0"); - x->SetBinLabel(5, "Sel INEL,INEL_fwd>0"); - x->SetBinLabel(6, "Rejected"); - x->SetBinLabel(7, "Good BCs"); - x->SetBinLabel(8, "BCs with collisions"); - x->SetBinLabel(9, "BCs with pile-up/splitting"); - x->SetBinLabel(10, "midtracks>0"); + x->SetBinLabel(2, "Vz"); + x->SetBinLabel(3, "Vz+ITSRof"); + x->SetBinLabel(4, "Vz+Selected"); + x->SetBinLabel(5, "Sel8+Vz+INEL>0"); + x->SetBinLabel(6, "Sel INEL,INEL_fwd>0"); + x->SetBinLabel(7, "Rejected"); + x->SetBinLabel(8, "Good BCs"); + x->SetBinLabel(9, "BCs with collisions"); + x->SetBinLabel(10, "BCs with pile-up/splitting"); x->SetBinLabel(11, "percollisionSample>0"); x->SetBinLabel(12, "midtracks+percollisionSample>0"); registry.add({"EventsNtrkZvtx", @@ -446,13 +446,13 @@ struct PseudorapidityDensityMFT { { std::vector::iterator> cols; - for (auto& bc : bcs) { + for (const auto& bc : bcs) { if (!useEvSel || (useEvSel && ((bc.selection_bit(aod::evsel::kIsBBT0A) && bc.selection_bit(aod::evsel::kIsBBT0C)) != 0))) { - registry.fill(HIST("EventSelection"), 7); // added 5->12 + registry.fill(HIST("EventSelection"), 8); // added 5->12 cols.clear(); - for (auto& collision : collisions) { + for (const auto& collision : collisions) { if (collision.has_foundBC()) { if (collision.foundBCId() == bc.globalIndex()) { cols.emplace_back(collision); @@ -463,9 +463,9 @@ struct PseudorapidityDensityMFT { } LOGP(debug, "BC {} has {} collisions", bc.globalBC(), cols.size()); if (!cols.empty()) { - registry.fill(HIST("EventSelection"), 8); // added 6->13 + registry.fill(HIST("EventSelection"), 9); // added 6->13 if (cols.size() > 1) { - registry.fill(HIST("EventSelection"), 9); // added 7->14 + registry.fill(HIST("EventSelection"), 10); // added 7->14 } } } @@ -522,17 +522,17 @@ struct PseudorapidityDensityMFT { } if (tracks.size() > 0) { - for (auto& track : tracks) { + for (const auto& track : tracks) { float phi = track.phi(); o2::math_utils::bringTo02Pi(phi); if (usePhiCut) { if ((phi < cfgPhiCut) || - ((phi > M_PI - cfgPhiCut) && (phi < M_PI + cfgPhiCut)) || - (phi > 2. * M_PI - cfgPhiCut) || - ((phi > ((M_PI / 2. - 0.1) * M_PI) - cfgPhiCut) && - (phi < ((M_PI / 2. - 0.1) * M_PI) + cfgPhiCut))) + ((phi > o2::constants::math::PI - cfgPhiCut) && (phi < o2::constants::math::PI + cfgPhiCut)) || + (phi > o2::constants::math::TwoPI - cfgPhiCut) || + ((phi > ((o2::constants::math::PIHalf - 0.1) * o2::constants::math::PI) - cfgPhiCut) && + (phi < ((o2::constants::math::PIHalf - 0.1) * o2::constants::math::PI) + cfgPhiCut))) continue; } @@ -569,16 +569,20 @@ struct PseudorapidityDensityMFT { registry.fill(HIST("EventsNtrkZvtx"), Ntrk, z); if ((z >= cfgVzCut1) && (z <= cfgVzCut2)) { registry.fill(HIST("Tracks/2Danalysis/EventsNtrkZvtx_all"), Ntrk, z); - for (auto& retrack : retracks) { + registry.fill(HIST("EventSelection"), 2.); + for (const auto& retrack : retracks) { auto track = retrack.mfttrack(); if ((cfgnEta1 < track.eta()) && (track.eta() < cfgnEta2) && track.nClusters() >= cfgnCluster && retrack.ambDegree() > 0) { registry.fill(HIST("Tracks/2Danalysis/EtaZvtx"), track.eta(), z); } } - if (!useEvSel || (useEvSel && collision.sel8())) { - registry.fill(HIST("EventSelection"), 2.); + if (!disableITSROFCut && !collision.selection_bit(aod::evsel::kNoITSROFrameBorder)) { + return; + } + registry.fill(HIST("EventSelection"), 3.); + if (!useEvSel || (useEvSel && collision.selection_bit(aod::evsel::kIsTriggerTVX) && collision.selection_bit(aod::evsel::kNoTimeFrameBorder))) { + registry.fill(HIST("EventSelection"), 4.); registry.fill(HIST("Tracks/2Danalysis/EventsNtrkZvtx_sel8"), Ntrk, z); - registry.fill(HIST("EventSelection"), 3.); std::unordered_set uniqueEvents; std::unordered_set uniqueEventsAmb; std::unordered_set uniqueCollisions; @@ -586,8 +590,7 @@ struct PseudorapidityDensityMFT { std::unordered_set eventsInelMFT; std::unordered_set eventsInel; if (midtracks.size() > 0) { - registry.fill(HIST("EventSelection"), 4.); - registry.fill(HIST("EventSelection"), 10.); + registry.fill(HIST("EventSelection"), 5.); registry.fill(HIST("EventsNtrkZvtx_gt0"), Ntrk, z); registry.fill(HIST("Tracks/2Danalysis/EventsNtrkZvtx_sel8_inelgt0"), Ntrk, z); eventsInel.insert(collision.globalIndex()); @@ -599,7 +602,7 @@ struct PseudorapidityDensityMFT { registry.fill(HIST("EventSelection"), 12.); } int64_t i = 0.0, j = 0.0, k = 0.0; - for (auto& retrack : retracks) { + for (const auto& retrack : retracks) { auto track = retrack.mfttrack(); if ((cfgnEta1 < track.eta()) && (track.eta() < cfgnEta2) && track.nClusters() >= cfgnCluster && retrack.ambDegree() > 0) { registry.fill(HIST("Tracks/2Danalysis/EtaZvtx_sel8"), track.eta(), z); @@ -609,11 +612,11 @@ struct PseudorapidityDensityMFT { } } if (retracks.size() > 0) { - registry.fill(HIST("EventSelection"), 5.); + registry.fill(HIST("EventSelection"), 6.); if (midtracks.size() > 0) { registry.fill(HIST("Tracks/2Danalysis/EventsNtrkZvtx_sel8_inelfwdgt0"), Ntrk, z); } - for (auto& retrack : retracks) { + for (const auto& retrack : retracks) { auto track = retrack.mfttrack(); if ((cfgnEta1 < track.eta()) && (track.eta() < cfgnEta2) && track.nClusters() >= cfgnCluster) { @@ -736,7 +739,7 @@ struct PseudorapidityDensityMFT { registry.fill(HIST("hNumCollisions_Inel"), 1, eventsInel.size()); } } else { - registry.fill(HIST("EventSelection"), 6); + registry.fill(HIST("EventSelection"), 7); } } PROCESS_SWITCH(PseudorapidityDensityMFT, processMultReassoc, @@ -759,17 +762,17 @@ struct PseudorapidityDensityMFT { registry.fill(HIST("Events/Centrality/NtrkZvtx"), Ntrk, z, c); - for (auto& track : tracks) { + for (const auto& track : tracks) { float phi = track.phi(); o2::math_utils::bringTo02Pi(phi); if (usePhiCut) { if ((phi < cfgPhiCut) || - ((phi > M_PI - cfgPhiCut) && (phi < M_PI + cfgPhiCut)) || - (phi > 2. * M_PI - cfgPhiCut) || - ((phi > ((M_PI / 2. - 0.1) * M_PI) - cfgPhiCut) && - (phi < ((M_PI / 2. - 0.1) * M_PI) + cfgPhiCut))) + ((phi > o2::constants::math::PI - cfgPhiCut) && (phi < o2::constants::math::PI + cfgPhiCut)) || + (phi > o2::constants::math::TwoPI - cfgPhiCut) || + ((phi > ((o2::constants::math::PIHalf - 0.1) * o2::constants::math::PI) - cfgPhiCut) && + (phi < ((o2::constants::math::PIHalf - 0.1) * o2::constants::math::PI) + cfgPhiCut))) continue; } @@ -807,7 +810,7 @@ struct PseudorapidityDensityMFT { auto perCollisionMCSample = mcSample->sliceByCached( aod::mcparticle::mcCollisionId, mcCollision.globalIndex(), cache); auto nCharged = 0; - for (auto& particle : perCollisionMCSample) { + for (const auto& particle : perCollisionMCSample) { auto charge = 0.; auto p = pdg->GetParticle(particle.pdgCode()); if (p != nullptr) { @@ -824,7 +827,7 @@ struct PseudorapidityDensityMFT { auto perCollisionMCSampleCentral = mcSampleCentral->sliceByCached( aod::mcparticle::mcCollisionId, mcCollision.globalIndex(), cache); auto nChargedCentral = 0; - for (auto& particle : perCollisionMCSampleCentral) { + for (const auto& particle : perCollisionMCSample) { auto charge = 0.; auto p = pdg->GetParticle(particle.pdgCode()); if (p != nullptr) { @@ -849,9 +852,12 @@ struct PseudorapidityDensityMFT { LOGP(debug, "MC col {} has {} reco cols", mcCollision.globalIndex(), collisions.size()); - for (auto& collision : collisions) { + for (const auto& collision : collisions) { registry.fill(HIST("EventEfficiency"), 3.); - if (!useEvSel || (useEvSel && collision.sel8())) { + if (!disableITSROFCut && !collision.selection_bit(aod::evsel::kNoITSROFrameBorder)) { + return; + } + if (!useEvSel || (useEvSel && collision.selection_bit(aod::evsel::kIsTriggerTVX) && collision.selection_bit(aod::evsel::kNoTimeFrameBorder))) { atLeastOne = true; auto perCollisionSample = sample->sliceByCached( o2::aod::fwdtrack::collisionId, collision.globalIndex(), cache); @@ -888,7 +894,7 @@ struct PseudorapidityDensityMFT { registry.fill(HIST("EventsSplitMult"), nCharged); } if ((mcCollision.posZ() >= cfgVzCut1) && (mcCollision.posZ() <= cfgVzCut2)) { - for (auto& particle : particles) { + for (const auto& particle : particles) { auto p = pdg->GetParticle(particle.pdgCode()); auto charge = 0; if (p != nullptr) { @@ -943,7 +949,7 @@ struct PseudorapidityDensityMFT { float c_gen = -1; bool atLeastOne = false; - for (auto& collision : collisions) { + for (const auto& collision : collisions) { float c_rec = -1; if constexpr (ExColsGenCent::template contains()) { c_rec = collision.centFT0C(); @@ -972,7 +978,7 @@ struct PseudorapidityDensityMFT { aod::mcparticle::mcCollisionId, mcCollision.globalIndex(), cache); auto nCharged = 0; - for (auto& particle : perCollisionMCSample) { + for (const auto& particle : perCollisionMCSample) { auto p = pdg->GetParticle(particle.pdgCode()); auto charge = 0; if (p != nullptr) { @@ -989,7 +995,7 @@ struct PseudorapidityDensityMFT { mcCollision.posZ(), c_gen); } - for (auto& particle : particles) { + for (const auto& particle : particles) { auto p = pdg->GetParticle(particle.pdgCode()); auto charge = 0; if (p != nullptr) { @@ -1025,7 +1031,7 @@ struct PseudorapidityDensityMFT { MFTTracksLabeled const& tracks, aod::McParticles const&) { if (!useEvSel || (useEvSel && collision.sel8())) { - for (auto& track : tracks) { + for (const auto& track : tracks) { if (!track.has_mcParticle()) { continue; } From df4c5ed4b805fa7623b843097ef50dcdf541356a Mon Sep 17 00:00:00 2001 From: Preet-Bhanjan Date: Fri, 27 Jun 2025 17:23:43 +0200 Subject: [PATCH 239/871] [PWGCF] Addition of extra event & track selections and configurable correlators (#11790) Co-authored-by: Preet Pati Co-authored-by: ALICE Action Bot --- PWGCF/Flow/Tasks/resonancesGfwFlow.cxx | 1155 ++++++++++++++---------- 1 file changed, 684 insertions(+), 471 deletions(-) diff --git a/PWGCF/Flow/Tasks/resonancesGfwFlow.cxx b/PWGCF/Flow/Tasks/resonancesGfwFlow.cxx index 8f6db97fde8..8a2c634e31f 100644 --- a/PWGCF/Flow/Tasks/resonancesGfwFlow.cxx +++ b/PWGCF/Flow/Tasks/resonancesGfwFlow.cxx @@ -13,50 +13,49 @@ /// \brief PID flow for resonances using the generic framework /// \author Preet Bhanjan Pati -#include -#include -#include -#include -#include -#include -#include - -#include "Math/Vector4D.h" - -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/RunningWorkflowInfo.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/StepTHn.h" - -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "Common/DataModel/Centrality.h" -#include "Common/DataModel/PIDResponse.h" -#include "Common/DataModel/Multiplicity.h" -#include "Common/Core/TrackSelection.h" -#include "Common/Core/trackUtilities.h" -#include "Common/Core/RecoDecay.h" -#include "CommonConstants/PhysicsConstants.h" - -#include "PWGLF/DataModel/EPCalibrationTables.h" -#include "PWGLF/DataModel/LFStrangenessTables.h" - -#include "PWGCF/GenericFramework/Core/GFWPowerArray.h" +#include "PWGCF/GenericFramework/Core/FlowContainer.h" #include "PWGCF/GenericFramework/Core/GFW.h" +#include "PWGCF/GenericFramework/Core/GFWConfig.h" #include "PWGCF/GenericFramework/Core/GFWCumulant.h" -#include "PWGCF/GenericFramework/Core/FlowContainer.h" +#include "PWGCF/GenericFramework/Core/GFWPowerArray.h" #include "PWGCF/GenericFramework/Core/GFWWeights.h" #include "PWGCF/GenericFramework/Core/GFWWeightsList.h" +#include "PWGLF/DataModel/EPCalibrationTables.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" -#include "ReconstructionDataFormats/Track.h" +#include "Common/Core/RecoDecay.h" +#include "Common/Core/TrackSelection.h" +#include "Common/Core/trackUtilities.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/PIDResponseITS.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include "CommonConstants/PhysicsConstants.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/RunningWorkflowInfo.h" +#include "Framework/StepTHn.h" +#include "Framework/runDataProcessing.h" #include "ReconstructionDataFormats/PID.h" +#include "ReconstructionDataFormats/Track.h" +#include +#include "Math/Vector4D.h" +#include #include #include -#include + +#include +#include +#include +#include +#include +#include using namespace o2; using namespace o2::framework; @@ -65,37 +64,118 @@ using namespace std; namespace { -std::shared_ptr refC22Boot[10]; -std::shared_ptr refC24Boot[10]; - -std::shared_ptr phiD22FPtBoot[10]; -std::shared_ptr phiD22BPtBoot[10]; -std::shared_ptr phiD24FPtBoot[10]; -std::shared_ptr phiD24BPtBoot[10]; - -std::shared_ptr k0D22FPtBoot[10]; -std::shared_ptr k0D22BPtBoot[10]; -std::shared_ptr k0D24FPtBoot[10]; -std::shared_ptr k0D24BPtBoot[10]; - -std::shared_ptr lambdaD22FPtBoot[10]; -std::shared_ptr lambdaD22BPtBoot[10]; -std::shared_ptr lambdaD24FPtBoot[10]; -std::shared_ptr lambdaD24BPtBoot[10]; - -std::shared_ptr anLambdaD22FPtBoot[10]; -std::shared_ptr anLambdaD22BPtBoot[10]; -std::shared_ptr anLambdaD24FPtBoot[10]; -std::shared_ptr anLambdaD24BPtBoot[10]; +std::vector> refV2; +std::vector> phiV2; +std::vector> k0V2; +std::vector> lambdaV2; + +std::vector>> refBoot; +std::vector>> phiBoot; +std::vector>> k0Boot; +std::vector>> lambdaBoot; } // namespace #define O2_DEFINE_CONFIGURABLE(NAME, TYPE, DEFAULT, HELP) Configurable NAME{#NAME, DEFAULT, HELP}; +namespace o2::analysis::genericframework +{ +GFWRegions regions; +GFWCorrConfigs configs; +} // namespace o2::analysis::genericframework + +template +auto projectMatrix(Array2D const& mat, std::array& array1, std::array& array2, std::array& array3) +{ + for (auto j = 0; j < static_cast(mat.cols); ++j) { + array1[j] = mat(0, j); + array2[j] = mat(1, j); + array3[j] = mat(2, j); + } + return; +} +template +auto readMatrix(Array2D const& mat, P& array) +{ + for (auto i = 0; i < static_cast(mat.rows); ++i) { + for (auto j = 0; j < static_cast(mat.cols); ++j) { + array[i][j] = mat(i, j); + } + } + + return; +} + +using namespace o2::analysis::genericframework; + +static constexpr float LongArrayFloat[3][20] = {{1.1, 1.2, 1.3, -1.1, -1.2, -1.3, 1.1, 1.2, 1.3, -1.1, -1.2, -1.3, 1.1, 1.2, 1.3, -1.1, -1.2, -1.3, 1.1, 1.2}, {2.1, 2.2, 2.3, -2.1, -2.2, -2.3, 1.1, 1.2, 1.3, -1.1, -1.2, -1.3, 1.1, 1.2, 1.3, -1.1, -1.2, -1.3, 1.1, 1.2}, {3.1, 3.2, 3.3, -3.1, -3.2, -3.3, 1.1, 1.2, 1.3, -1.1, -1.2, -1.3, 1.1, 1.2, 1.3, -1.1, -1.2, -1.3, 1.1, 1.2}}; +static constexpr int LongArrayInt[3][20] = {{1, 1, 1, -1, -1, -1, 1, 1, 1, -1, -1, -1, 1, 1, 1, -1, -1, -1, 1, 1}, {2, 2, 2, -2, -2, -2, 1, 1, 1, -1, -1, -1, 1, 1, 1, -1, -1, -1, 1, 1}, {3, 3, 3, -3, -3, -3, 1, 1, 1, -1, -1, -1, 1, 1, 1, -1, -1, -1, 1, 1}}; + struct ResonancesGfwFlow { + o2::aod::ITSResponse itsResponse; Service ccdb; - Configurable noLaterThan{"noLaterThan", std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(), "latest acceptable timestamp of creation for the object"}; Configurable ccdbUrl{"ccdbUrl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + enum OutputSpecies { + K0 = 0, + LAMBDA = 1, + PHI = 2, + ANLAMBDA = 3, + REF = 4, + kCount_OutputSpecies + }; + enum Particles { + PIONS, + KAONS, + PROTONS + }; + enum ParticleCuts { + kCosPA = 0, + kMassMin, + kMassMax, + kPosTrackPt, + kNegTrackPt, + kDCAPosToPVMin, + kDCANegToPVMin, + kLifeTime, + kRadiusMin, + kRadiusMax, + kRapidity + }; + enum ParticleSwitches { + kUseParticle = 0, + kUseCosPA, + kMassBins, + kDCABetDaug, + kUseProperLifetime, + kUseV0Radius + }; + enum EventCutTypes { + kFilteredEvents = 0, + kAfterSel8, + kUseNoTimeFrameBorder, + kUseNoITSROFrameBorder, + kUseNoSameBunchPileup, + kUseGoodZvtxFT0vsPV, + kUseNoCollInTimeRangeStandard, + kUseGoodITSLayersAll, + kUseNoCollInRofStandard, + kUseNoHighMultCollInPrevRof, + kUseOccupancy, + kUseMultCorrCut, + kUseT0AV0ACut, + kUseVertexITSTPC, + kUseTVXinTRD + }; + enum TrackCutTypes { + kFilteredTracks = 0, + kUseGlobalTracks, + kUsePvContributor, + kItsClustersCut, + kHasTpcSignal, + kTpcClustersCut, + kTpcCrossedRowsCut + }; + O2_DEFINE_CONFIGURABLE(cfgCutVertex, float, 10.0f, "Accepted z-vertex range") O2_DEFINE_CONFIGURABLE(cfgCutPtPOIMin, float, 0.2f, "Minimal pT for poi tracks") O2_DEFINE_CONFIGURABLE(cfgCutPtPOIMax, float, 10.0f, "Maximal pT for poi tracks") @@ -103,32 +183,17 @@ struct ResonancesGfwFlow { O2_DEFINE_CONFIGURABLE(cfgCutPtMax, float, 3.0f, "Maximal pT for ref tracks") O2_DEFINE_CONFIGURABLE(cfgCutEta, float, 0.8f, "Eta range for tracks") O2_DEFINE_CONFIGURABLE(cfgCutChi2prTPCcls, float, 2.5, "Chi2 per TPC clusters") - O2_DEFINE_CONFIGURABLE(cfgTpcCluster, int, 70, "Number of TPC clusters") - O2_DEFINE_CONFIGURABLE(cfgTpcNsigmaCut, float, 3.0f, "TPC N-sigma cut for pions, kaons, protons") - O2_DEFINE_CONFIGURABLE(cfgTofNsigmaCut, float, 3.0f, "TOF N-sigma cut for pions, kaons, protons") + O2_DEFINE_CONFIGURABLE(cfgTpcCluster, int, 50, "Number of TPC clusters") + O2_DEFINE_CONFIGURABLE(cfgTpcCrossRows, int, 70, "Number of TPC clusters") + O2_DEFINE_CONFIGURABLE(cfgTpcCut, float, 3.0f, "TPC N-sigma cut for pions, kaons, protons") O2_DEFINE_CONFIGURABLE(cfgTofPtCut, float, 0.5f, "Minimum pt to use TOF N-sigma") - O2_DEFINE_CONFIGURABLE(cfgITScluster, int, 0, "Number of ITS cluster") - O2_DEFINE_CONFIGURABLE(cfgCutOccupancy, int, 3000, "Occupancy cut") + O2_DEFINE_CONFIGURABLE(cfgITScluster, int, 5, "Number of ITS cluster") + O2_DEFINE_CONFIGURABLE(cfgCutOccupancyMin, int, 0, "Minimum occupancy cut") + O2_DEFINE_CONFIGURABLE(cfgCutOccupancyMax, int, 2000, "Maximum occupancy cut") O2_DEFINE_CONFIGURABLE(cfgUseGlobalTrack, bool, true, "use Global track") O2_DEFINE_CONFIGURABLE(cfgFakeKaonCut, float, 0.1f, "Maximum difference in measured momentum and TPC inner ring momentum of particle") - O2_DEFINE_CONFIGURABLE(cfgRapidityCut, float, 0.5, "Rapidity cut for the reconstructed particles") - O2_DEFINE_CONFIGURABLE(cfgUseCosPA, bool, false, "Use Pointing angle for resonances") - O2_DEFINE_CONFIGURABLE(cfgUseV0Radius, bool, true, "Use V0 radius for particle identification") - O2_DEFINE_CONFIGURABLE(cfgLambdaRadiusMin, float, 0.5f, "Minimum Lambda radius in cm") - O2_DEFINE_CONFIGURABLE(cfgLambdaRadiusMax, float, 200.0f, "Maximum Lambda radius in cm") - O2_DEFINE_CONFIGURABLE(cfgK0RadiusMin, float, 0.5f, "Minimum K0 radius in cm") - O2_DEFINE_CONFIGURABLE(cfgK0RadiusMax, float, 200.0f, "Maximum K0 radius in cm") - O2_DEFINE_CONFIGURABLE(cfgUseProperLifetime, bool, false, "Use proper lifetime for particle identification") - O2_DEFINE_CONFIGURABLE(cfgK0LifeTime, float, 20.0f, "Maximum lifetime for K0 in cm") - O2_DEFINE_CONFIGURABLE(cfgLambdaLifeTime, float, 30.0f, "Maximum lifetime for Lambda in cm") O2_DEFINE_CONFIGURABLE(cfgCutDCAxy, float, 2.0f, "DCAxy range for tracks") O2_DEFINE_CONFIGURABLE(cfgCutDCAz, float, 2.0f, "DCAz range for tracks") - O2_DEFINE_CONFIGURABLE(cfgDCALambdaPosToPVMin, float, 0.1f, "minimum DCA to PV for Lambda positive track") - O2_DEFINE_CONFIGURABLE(cfgDCALambdaNegToPVMin, float, 0.25f, "minimum DCA to PV for Lambda negative track") - O2_DEFINE_CONFIGURABLE(cfgDCAK0PosToPVMin, float, 0.06f, "minimum DCA to PV for K0 positive track") - O2_DEFINE_CONFIGURABLE(cfgDCAK0NegToPVMin, float, 0.06f, "minimum DCA to PV for K0 negative track") - O2_DEFINE_CONFIGURABLE(cfgUseMCCLambda, bool, false, "Use mass cross check for lambda") - O2_DEFINE_CONFIGURABLE(cfgUseMCCK0, bool, false, "Use mass cross check for K0") O2_DEFINE_CONFIGURABLE(cfgOutputNUAWeights, bool, true, "Fill and output NUA weights") O2_DEFINE_CONFIGURABLE(cfgAcceptance, std::string, "", "CCDB path to acceptance object") O2_DEFINE_CONFIGURABLE(cfgUseWeightPhiEtaVtxz, bool, true, "Use Phi, Eta, VertexZ dependent NUA weights") @@ -137,42 +202,22 @@ struct ResonancesGfwFlow { O2_DEFINE_CONFIGURABLE(cfgNbootstrap, int, 10, "Number of subsamples") O2_DEFINE_CONFIGURABLE(cfgUseBootStrap, bool, true, "Use bootstrap for error estimation") O2_DEFINE_CONFIGURABLE(cfgTrackDensityCorrUse, bool, true, "Use track density efficiency correction") - O2_DEFINE_CONFIGURABLE(cfgUsePhi, bool, true, "Analyze Phi") - O2_DEFINE_CONFIGURABLE(cfgUseK0, bool, true, "Analyze K0") - O2_DEFINE_CONFIGURABLE(cfgUseLambda, bool, true, "Analyze Lambda") + O2_DEFINE_CONFIGURABLE(cfgV0AT0Acut, int, 5, "V0AT0A cut") - enum OutputSpecies { - Ref = 0, - K0 = 1, - Lambda = 2, - AnLambda = 3, - Phi = 4, - kCount_OutputSpecies - }; - - struct : ConfigurableGroup { - Configurable> cfgCosPAs{"cfgCosPAs", std::vector{0.97f, 0.995f, 0.04f}, "Minimum Pointing angle for resonances [K0, Lambda, Phi]"}; - Configurable> cfgDCABetDaug{"cfgDCABetDaug", std::vector{1, 1, 1}, "Maximum DCA between resonance daughters [K0, Lambda, Phi]"}; - Configurable> cfgMassMin{"cfgMassMin", std::vector{0.44f, 1.1f, 0.99f}, "Minimum mass for resonances [K0, Lambda, Phi]"}; - Configurable> cfgMassMax{"cfgMassMax", std::vector{0.56f, 1.16f, 1.06f}, "Maximum mass for resonances [K0, Lambda, Phi]"}; - Configurable> cfgNMassBins{"cfgNMassBins", std::vector{70, 70, 70}, "Invariant mass bins for resonances [K0, Lambda, Phi]"}; - Configurable> cfgMccCut{"cfgMccCut", std::vector{0.005f, 0.01f, 0.0f}, "MCC cut for resonances [K0, Lambda, Phi]"}; - Configurable> cfgPosTrackPt{"cfgPosTrackPt", std::vector{0.15f, 0.15f, 0.15f}, "Pt cut for positive track of resonances [K0, Lambda, Phi]"}; - Configurable> cfgNegTrackPt{"cfgNegTrackPt", std::vector{0.15f, 0.15f, 0.15f}, "Pt cut for negative track of resonances [K0, Lambda, Phi]"}; - } resoCuts; + O2_DEFINE_CONFIGURABLE(cfgUseOnlyTPC, bool, true, "Use only TPC PID for daughter selection") + O2_DEFINE_CONFIGURABLE(cfgUseStrictPID, bool, true, "Use strict PID cuts for TPC") + O2_DEFINE_CONFIGURABLE(cfgUseAsymmetricPID, bool, false, "Use asymmetric PID cuts") + O2_DEFINE_CONFIGURABLE(cfgUseItsPID, bool, true, "Use ITS PID for particle identification") Configurable> cfgTrackDensityP0{"cfgTrackDensityP0", std::vector{0.7217476707, 0.7384792571, 0.7542625668, 0.7640680200, 0.7701951667, 0.7755299053, 0.7805901710, 0.7849446786, 0.7957356586, 0.8113039262, 0.8211968966, 0.8280558878, 0.8329342135}, "parameter 0 for track density efficiency correction"}; Configurable> cfgTrackDensityP1{"cfgTrackDensityP1", std::vector{-2.169488e-05, -2.191913e-05, -2.295484e-05, -2.556538e-05, -2.754463e-05, -2.816832e-05, -2.846502e-05, -2.843857e-05, -2.705974e-05, -2.477018e-05, -2.321730e-05, -2.203315e-05, -2.109474e-05}, "parameter 1 for track density efficiency correction"}; + Configurable> cfgUseEventCuts{"cfgUseEventCuts", std::vector{1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0}, "Switch for various event cuts [Filtered Events, Sel8, kNoTimeFrameBorder, kNoITSROFrameBorder, kNoSameBunchPileup, kIsGoodZvtxFT0vsPV, kNoCollInTimeRangeStandard, kIsGoodITSLayersAll, kNoCollInRofStandard, kNoHighMultCollInPrevRof, Occupancy, Multiplicity correlation, T0AV0A 3 sigma cut, kIsVertexITSTPC, kTVXinTRD]"}; + Configurable> nSigmas{"nSigmas", {LongArrayFloat[0], 3, 6, {"TPC", "TOF", "ITS"}, {"pos_pi", "pos_ka", "pos_pr", "neg_pi", "neg_ka", "neg_pr"}}, "Labeled array for n-sigma values for TPC, TOF, ITS for pions, kaons, protons (positive and negative)"}; + Configurable> resonanceCuts{"resonanceCuts", {LongArrayFloat[0], 3, 11, {"K0", "Lambda", "Phi"}, {"cos_PAs", "massMin", "massMax", "PosTrackPt", "NegTrackPt", "DCAPosToPVMin", "DCANegToPVMin", "Lifetime", "RadiusMin", "RadiusMax", "Rapidity"}}, "Labeled array (float) for various cuts on resonances"}; + Configurable> resonanceSwitches{"resonanceSwitches", {LongArrayInt[0], 3, 6, {"K0", "Lambda", "Phi"}, {"UseParticle", "UseCosPA", "NMassBins", "DCABetDaug", "UseProperLifetime", "UseV0Radius"}}, "Labeled array (int) for various cuts on resonances"}; - // Reading in the configurables - std::vector vMassMin = resoCuts.cfgMassMin; - std::vector vMassMax = resoCuts.cfgMassMax; - std::vector vMassBins = resoCuts.cfgNMassBins; - std::vector vCosPAs = resoCuts.cfgCosPAs; - std::vector vDCABetDaug = resoCuts.cfgDCABetDaug; - std::vector vMccCut = resoCuts.cfgMccCut; - std::vector vPosTrackPt = resoCuts.cfgPosTrackPt; - std::vector vNegTrackPt = resoCuts.cfgNegTrackPt; + Configurable cfgRegions{"cfgRegions", {{"refN08", "refP08", "refFull", "poiNphi", "poiPphi", "poifullphi", "olNphi", "olPphi", "olfullphi", "poiNk0", "poiPk0", "poifullk0", "olNk0", "olPk0", "olfullk0", "poiNlam", "poiPlam", "poifulllam", "olNlam", "olPlam", "olfulllam", "poiNantilam", "poiPantilam", "poifullantilam", "olNantilam", "olPantilam", "olfullantilam"}, {-0.8, 0.4, -0.8, -0.8, 0.4, -0.8, -0.8, 0.4, -0.8, -0.8, 0.4, -0.8, -0.8, 0.4, -0.8, -0.8, 0.4, -0.8, -0.8, 0.4, -0.8, -0.8, 0.4, -0.8, -0.8, 0.4, -0.8}, {-0.4, 0.8, 0.8, -0.4, 0.8, 0.8, -0.4, 0.8, 0.8, -0.4, 0.8, 0.8, -0.4, 0.8, 0.8, -0.4, 0.8, 0.8, -0.4, 0.8, 0.8, -0.4, 0.8, 0.8, -0.4, 0.8, 0.8}, {0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, {1, 1, 1, 2, 2, 2, 32, 32, 32, 4, 4, 4, 64, 64, 64, 8, 8, 8, 128, 128, 128, 16, 16, 16, 256, 256, 256}}, "Configurations for GFW regions"}; + Configurable cfgCorrConfig{"cfgCorrConfig", {{"refN08 {2} refP08 {-2}", "refN08 {2 2} refP08 {-2 -2}", "poiNphi refN08 | olNphi {2} refP08 {-2}", "poiNphi refN08 | olNphi {2 2} refP08 {-2 -2}", "poiPphi refP08 | olPphi {2} refN08 {-2}", "poiPphi refP08 | olPphi {2 2} refN08 {-2 -2}", "poiNk0 refN08 | olNk0 {2} refP08 {-2}", "poiNk0 refN08 | olNk0 {2 2} refP08 {-2 -2}", "poiPk0 refP08 | olPk0 {2} refN08 {-2}", "poiPk0 refP08 | olPk0 {2 2} refN08 {-2 -2}", "poiNlam refN08 | olNlam {2} refP08 {-2}", "poiNlam refN08 | olNlam {2 2} refP08 {-2 -2}", "poiPlam refP08 | olPlam {2} refN08 {-2}", "poiPlam refP08 | olPlam {2 2} refN08 {-2 -2}", "poiNantilam refN08 | olNantilam {2} refP08 {-2}", "poiNantilam refN08 | olNantilam {2 2} refP08 {-2 -2}", "poiPantilam refP08 | olPantilam {2} refN08 {-2}", "poiPantilam refP08 | olPantilam {2 2} refN08 {-2 -2}"}, {"Ref08Gap22", "Ref08Gap24", "PhiF08Gap22", "PhiF08Gap24", "PhiB08Gap22", "PhiB08Gap24", "K0F08Gap22", "K0F08Gap24", "K0B08Gap22", "K0B08Gap24", "LamF08Gap22", "LamF08Gap24", "LamB08Gap22", "LamB08Gap24", "AnLamF08Gap22", "AnLamF08Gap24", "AnLamB08Gap22", "AnLamB08Gap24"}, {0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, "Configurations for each correlation to calculate"}; // Defining configurable axis ConfigurableAxis axisVertex{"axisVertex", {20, -10, 10}, "vertex axis for histograms"}; @@ -183,11 +228,6 @@ struct ResonancesGfwFlow { ConfigurableAxis axisNsigmaTPC{"axisNsigmaTPC", {80, -5, 5}, "nsigmaTPC axis"}; ConfigurableAxis axisNsigmaTOF{"axisNsigmaTOF", {80, -5, 5}, "nsigmaTOF axis"}; ConfigurableAxis axisParticles{"axisParticles", {3, 0, 3}, "axis for different hadrons"}; - ConfigurableAxis axisPhiMass{"axisPhiMass", {vMassBins[Phi - 2], vMassMin[Phi - 2], vMassMax[Phi - 2]}, "axis for invariant mass distibution for Phi"}; - ConfigurableAxis axisK0Mass{"axisK0Mass", {vMassBins[K0 - 1], vMassMin[K0 - 1], vMassMax[K0 - 1]}, "axis for invariant mass distibution for K0"}; - ConfigurableAxis axisLambdaMass{"axisLambdaMass", {vMassBins[Lambda - 1], vMassMin[Lambda - 1], vMassMax[Lambda - 1]}, "axis for invariant mass distibution for Lambda"}; - ConfigurableAxis axisTPCsignal{"axisTPCsignal", {10000, 0, 1000}, "axis for TPC signal"}; - ConfigurableAxis axisTOFsignal{"axisTOFsignal", {10000, 0, 1000}, "axis for TOF signal"}; Filter collisionFilter = nabs(aod::collision::posZ) < cfgCutVertex; Filter trackFilter = (nabs(aod::track::dcaXY) < cfgCutDCAxy) && (nabs(aod::track::dcaZ) < cfgCutDCAz) && (nabs(aod::track::eta) < cfgCutEta) && (aod::track::pt > cfgCutPtPOIMin) && (aod::track::pt < cfgCutPtPOIMax) && ((requireGlobalTrackInFilter()) || (aod::track::isGlobalTrackSDD == (uint8_t) true)) && (aod::track::tpcChi2NCl < cfgCutChi2prTPCcls); @@ -202,6 +242,13 @@ struct ResonancesGfwFlow { HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + std::array, 3> resoCutVals; + std::array, 3> resoSwitchVals; + std::array tofNsigmaCut; + std::array itsNsigmaCut; + std::array tpcNsigmaCut; + std::vector eventCuts; + GFW* fGFW = new GFW(); std::vector corrconfigs; TAxis* fPtAxis; @@ -220,52 +267,123 @@ struct ResonancesGfwFlow { TF1* funcV3; TF1* funcV4; + // Additional Event selection cuts - Copy from flowGenericFramework.cxx + TF1* fMultPVCutLow = nullptr; + TF1* fMultPVCutHigh = nullptr; + TF1* fMultCutLow = nullptr; + TF1* fMultCutHigh = nullptr; + TF1* fMultMultPVCut = nullptr; + TF1* fT0AV0AMean = nullptr; + TF1* fT0AV0ASigma = nullptr; + void init(InitContext const&) { + int64_t noLaterThan = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); + // Initilizing ccdb ccdb->setURL(ccdbUrl.value); ccdb->setCaching(true); - ccdb->setCreatedNotAfter(noLaterThan.value); + ccdb->setCreatedNotAfter(noLaterThan); + + LOGF(info, "flowGenericFramework::init()"); + regions.SetNames(cfgRegions->GetNames()); + regions.SetEtaMin(cfgRegions->GetEtaMin()); + regions.SetEtaMax(cfgRegions->GetEtaMax()); + regions.SetpTDifs(cfgRegions->GetpTDifs()); + regions.SetBitmasks(cfgRegions->GetBitmasks()); + configs.SetCorrs(cfgCorrConfig->GetCorrs()); + configs.SetHeads(cfgCorrConfig->GetHeads()); + configs.SetpTDifs(cfgCorrConfig->GetpTDifs()); + configs.SetpTCorrMasks(cfgCorrConfig->GetpTCorrMasks()); + regions.Print(); + configs.Print(); + + projectMatrix(nSigmas->getData(), tpcNsigmaCut, tofNsigmaCut, itsNsigmaCut); + readMatrix(resonanceCuts->getData(), resoCutVals); + readMatrix(resonanceSwitches->getData(), resoSwitchVals); + eventCuts = cfgUseEventCuts; AxisSpec singleCount = {1, 0, 1}; + AxisSpec axisK0Mass = {resoSwitchVals[K0][kMassBins], resoCutVals[K0][kMassMin], resoCutVals[K0][kMassMax]}; + AxisSpec axisLambdaMass = {resoSwitchVals[LAMBDA][kMassBins], resoCutVals[LAMBDA][kMassMin], resoCutVals[LAMBDA][kMassMax]}; + AxisSpec axisPhiMass = {resoSwitchVals[PHI][kMassBins], resoCutVals[PHI][kMassMin], resoCutVals[PHI][kMassMax]}; histos.add("hVtxZ", "", {HistType::kTH1D, {axisVertex}}); histos.add("hMult", "", {HistType::kTH1D, {{3000, 0.5, 3000.5}}}); histos.add("hCent", "", {HistType::kTH1D, {{90, 0, 90}}}); - histos.add("Refc22", "", {HistType::kTProfile, {axisMultiplicity}}); - histos.add("Refc24", "", {HistType::kTProfile, {axisMultiplicity}}); + refBoot.resize(cfgNbootstrap); + phiBoot.resize(cfgNbootstrap); + k0Boot.resize(cfgNbootstrap); + lambdaBoot.resize(cfgNbootstrap); + + // Defining histograms to store correlations + for (auto i = 0; i < configs.GetSize(); ++i) { + if (resoSwitchVals[PHI][kUseParticle] && configs.GetHeads()[i].starts_with("Phi")) { + phiV2.push_back(histos.add(Form("h%spt", configs.GetHeads()[i].c_str()), "", {HistType::kTProfile3D, {axisPt, axisPhiMass, axisMultiplicity}})); + if (cfgUseBootStrap) { + for (int j = 0; j < cfgNbootstrap; ++j) { + phiBoot[j].push_back(histos.add(Form("BootStrap/h%spt_boot_%d", configs.GetHeads()[i].c_str(), j), "", {HistType::kTProfile3D, {axisPt, axisPhiMass, axisMultiplicity}})); + } + } // end of bootstrap condition + } // end of phi loop + + if (resoSwitchVals[K0][kUseParticle] && configs.GetHeads()[i].starts_with("K0")) { + k0V2.push_back(histos.add(Form("h%spt", configs.GetHeads()[i].c_str()), "", {HistType::kTProfile3D, {axisPt, axisK0Mass, axisMultiplicity}})); + if (cfgUseBootStrap) { + for (int j = 0; j < cfgNbootstrap; ++j) { + k0Boot[j].push_back(histos.add(Form("BootStrap/h%spt_boot_%d", configs.GetHeads()[i].c_str(), j), "", {HistType::kTProfile3D, {axisPt, axisK0Mass, axisMultiplicity}})); + } + } // end of bootstrap condition + } // end of K0 loop + + if (resoSwitchVals[LAMBDA][kUseParticle] && (configs.GetHeads()[i].starts_with("Lam") || configs.GetHeads()[i].starts_with("AnLam"))) { + lambdaV2.push_back(histos.add(Form("h%spt", configs.GetHeads()[i].c_str()), "", {HistType::kTProfile3D, {axisPt, axisLambdaMass, axisMultiplicity}})); + if (cfgUseBootStrap) { + for (int j = 0; j < cfgNbootstrap; ++j) { + lambdaBoot[j].push_back(histos.add(Form("BootStrap/h%spt_boot_%d", configs.GetHeads()[i].c_str(), j), "", {HistType::kTProfile3D, {axisPt, axisLambdaMass, axisMultiplicity}})); + } + } // end of bootstrap condition + } // end of lambda loop + + if (configs.GetHeads()[i].starts_with("Ref")) { + refV2.push_back(histos.add(Form("h%s", configs.GetHeads()[i].c_str()), "", {HistType::kTProfile, {axisMultiplicity}})); + if (cfgUseBootStrap) { + for (int j = 0; j < cfgNbootstrap; ++j) { + refBoot[j].push_back(histos.add(Form("BootStrap/h%s_boot_%d", configs.GetHeads()[i].c_str(), j), "", {HistType::kTProfile, {axisMultiplicity}})); + } + } // end of bootstrap condition + } // end of ref loop - if (cfgUsePhi) { - histos.add("KaplusTPC", "", {HistType::kTH2D, {{axisPt, axisTPCsignal}}}); - histos.add("KaminusTPC", "", {HistType::kTH2D, {{axisPt, axisTPCsignal}}}); - histos.add("KaplusTOF", "", {HistType::kTH2D, {{axisPt, axisTOFsignal}}}); - histos.add("KaminusTOF", "", {HistType::kTH2D, {{axisPt, axisTOFsignal}}}); + } // end of configs loop + + if (resoSwitchVals[PHI][kUseParticle]) { + histos.add("KaPlusTPC", "", {HistType::kTH2D, {{axisPt, axisNsigmaTPC}}}); + histos.add("KaMinusTPC", "", {HistType::kTH2D, {{axisPt, axisNsigmaTPC}}}); + histos.add("KaPlusTOF", "", {HistType::kTH2D, {{axisPt, axisNsigmaTOF}}}); + histos.add("KaMinusTOF", "", {HistType::kTH2D, {{axisPt, axisNsigmaTOF}}}); histos.add("hPhiPhi", "", {HistType::kTH1D, {axisPhi}}); histos.add("hPhiEta", "", {HistType::kTH1D, {axisEta}}); histos.add("hPhiMass_sparse", "", {HistType::kTHnSparseD, {{axisPhiMass, axisPt, axisMultiplicity}}}); histos.add("hPhimassSparse_RD", "", {HistType::kTHnSparseD, {{axisPhiMass, axisPt, axisMultiplicity}}}); - histos.add("Phid22Fpt", "", {HistType::kTProfile3D, {axisPt, axisPhiMass, axisMultiplicity}}); - histos.add("Phid24Fpt", "", {HistType::kTProfile3D, {axisPt, axisPhiMass, axisMultiplicity}}); - histos.add("Phid22Bpt", "", {HistType::kTProfile3D, {axisPt, axisPhiMass, axisMultiplicity}}); - histos.add("Phid24Bpt", "", {HistType::kTProfile3D, {axisPt, axisPhiMass, axisMultiplicity}}); + histos.add("hPhiCount", "Number of Phi;; Count", {HistType::kTH1D, {{5, 0, 5}}}); + histos.get(HIST("hPhiCount"))->GetXaxis()->SetBinLabel(1, "Phi candidates"); + histos.get(HIST("hPhiCount"))->GetXaxis()->SetBinLabel(2, "Daughter track selection"); + histos.get(HIST("hPhiCount"))->GetXaxis()->SetBinLabel(3, "Fake Kaon"); + histos.get(HIST("hPhiCount"))->GetXaxis()->SetBinLabel(4, "CosPA"); + histos.get(HIST("hPhiCount"))->GetXaxis()->SetBinLabel(5, "Rapidity cut"); } - if (cfgUseK0) { - histos.add("PlusTPC_K0", "", {HistType::kTH2D, {{axisPt, axisTPCsignal}}}); - histos.add("MinusTPC_K0", "", {HistType::kTH2D, {{axisPt, axisTPCsignal}}}); - histos.add("PlusTOF_K0", "", {HistType::kTH2D, {{axisPt, axisTOFsignal}}}); - histos.add("MinusTOF_K0", "", {HistType::kTH2D, {{axisPt, axisTOFsignal}}}); + if (resoSwitchVals[K0][kUseParticle]) { + histos.add("PiPlusTPC_K0", "", {HistType::kTH2D, {{axisPt, axisNsigmaTPC}}}); + histos.add("PiMinusTPC_K0", "", {HistType::kTH2D, {{axisPt, axisNsigmaTPC}}}); + histos.add("PiPlusTOF_K0", "", {HistType::kTH2D, {{axisPt, axisNsigmaTOF}}}); + histos.add("PiMinusTOF_K0", "", {HistType::kTH2D, {{axisPt, axisNsigmaTOF}}}); histos.add("hK0Phi", "", {HistType::kTH1D, {axisPhi}}); histos.add("hK0Eta", "", {HistType::kTH1D, {axisEta}}); histos.add("hK0Mass_sparse", "", {HistType::kTHnSparseF, {{axisK0Mass, axisPt, axisMultiplicity}}}); histos.add("hK0s", "", {HistType::kTH1D, {singleCount}}); - histos.add("K0d22Fpt", "", {HistType::kTProfile3D, {axisPt, axisK0Mass, axisMultiplicity}}); - histos.add("K0d24Fpt", "", {HistType::kTProfile3D, {axisPt, axisK0Mass, axisMultiplicity}}); - histos.add("K0d22Bpt", "", {HistType::kTProfile3D, {axisPt, axisK0Mass, axisMultiplicity}}); - histos.add("K0d24Bpt", "", {HistType::kTProfile3D, {axisPt, axisK0Mass, axisMultiplicity}}); - histos.add("hK0Count", "Number of K0;; Count", {HistType::kTH1D, {{10, 0, 10}}}); histos.get(HIST("hK0Count"))->GetXaxis()->SetBinLabel(1, "K0 candidates"); histos.get(HIST("hK0Count"))->GetXaxis()->SetBinLabel(2, "Daughter pt"); @@ -278,33 +396,23 @@ struct ResonancesGfwFlow { histos.get(HIST("hK0Count"))->GetXaxis()->SetBinLabel(9, "Proper lifetime"); histos.get(HIST("hK0Count"))->GetXaxis()->SetBinLabel(10, "Daughter track selection"); } - if (cfgUseLambda) { - histos.add("PlusTPC_L", "", {HistType::kTH2D, {{axisPt, axisTPCsignal}}}); - histos.add("MinusTPC_L", "", {HistType::kTH2D, {{axisPt, axisTPCsignal}}}); - histos.add("PlusTOF_L", "", {HistType::kTH2D, {{axisPt, axisTOFsignal}}}); - histos.add("MinusTOF_L", "", {HistType::kTH2D, {{axisPt, axisTOFsignal}}}); + if (resoSwitchVals[LAMBDA][kUseParticle]) { + histos.add("PrPlusTPC_L", "", {HistType::kTH2D, {{axisPt, axisNsigmaTPC}}}); + histos.add("PiMinusTPC_L", "", {HistType::kTH2D, {{axisPt, axisNsigmaTPC}}}); + histos.add("PrPlusTOF_L", "", {HistType::kTH2D, {{axisPt, axisNsigmaTOF}}}); + histos.add("PiMinusTOF_L", "", {HistType::kTH2D, {{axisPt, axisNsigmaTOF}}}); histos.add("hLambdaPhi", "", {HistType::kTH1D, {axisPhi}}); histos.add("hLambdaEta", "", {HistType::kTH1D, {axisEta}}); histos.add("hLambdaMass_sparse", "", {HistType::kTHnSparseF, {{axisLambdaMass, axisPt, axisMultiplicity}}}); - histos.add("PlusTPC_AL", "", {HistType::kTH2D, {{axisPt, axisTPCsignal}}}); - histos.add("MinusTPC_AL", "", {HistType::kTH2D, {{axisPt, axisTPCsignal}}}); - histos.add("PlusTOF_AL", "", {HistType::kTH2D, {{axisPt, axisTOFsignal}}}); - histos.add("MinusTOF_AL", "", {HistType::kTH2D, {{axisPt, axisTOFsignal}}}); + histos.add("PiPlusTPC_AL", "", {HistType::kTH2D, {{axisPt, axisNsigmaTPC}}}); + histos.add("PrMinusTPC_AL", "", {HistType::kTH2D, {{axisPt, axisNsigmaTPC}}}); + histos.add("PiPlusTOF_AL", "", {HistType::kTH2D, {{axisPt, axisNsigmaTOF}}}); + histos.add("PrMinusTOF_AL", "", {HistType::kTH2D, {{axisPt, axisNsigmaTOF}}}); histos.add("hAntiLambdaPhi", "", {HistType::kTH1D, {axisPhi}}); histos.add("hAntiLambdaEta", "", {HistType::kTH1D, {axisEta}}); histos.add("hAntiLambdaMass_sparse", "", {HistType::kTHnSparseF, {{axisLambdaMass, axisPt, axisMultiplicity}}}); histos.add("hLambdas", "", {HistType::kTH1D, {singleCount}}); - histos.add("Lambdad22Fpt", "", {HistType::kTProfile3D, {axisPt, axisLambdaMass, axisMultiplicity}}); - histos.add("Lambdad24Fpt", "", {HistType::kTProfile3D, {axisPt, axisLambdaMass, axisMultiplicity}}); - histos.add("Lambdad22Bpt", "", {HistType::kTProfile3D, {axisPt, axisLambdaMass, axisMultiplicity}}); - histos.add("Lambdad24Bpt", "", {HistType::kTProfile3D, {axisPt, axisLambdaMass, axisMultiplicity}}); - - histos.add("AnLambdad22Fpt", "", {HistType::kTProfile3D, {axisPt, axisLambdaMass, axisMultiplicity}}); - histos.add("AnLambdad24Fpt", "", {HistType::kTProfile3D, {axisPt, axisLambdaMass, axisMultiplicity}}); - histos.add("AnLambdad22Bpt", "", {HistType::kTProfile3D, {axisPt, axisLambdaMass, axisMultiplicity}}); - histos.add("AnLambdad24Bpt", "", {HistType::kTProfile3D, {axisPt, axisLambdaMass, axisMultiplicity}}); - histos.add("hLambdaCount", "Number of Lambda;; Count", {HistType::kTH1D, {{10, 0, 10}}}); histos.get(HIST("hLambdaCount"))->GetXaxis()->SetBinLabel(1, "Lambda candidates"); histos.get(HIST("hLambdaCount"))->GetXaxis()->SetBinLabel(2, "Daughter pt"); @@ -318,15 +426,31 @@ struct ResonancesGfwFlow { histos.get(HIST("hLambdaCount"))->GetXaxis()->SetBinLabel(10, "Daughter track selection"); } - histos.add("hEventCount", "Number of Event;; Count", {HistType::kTH1D, {{8, 0, 8}}}); - histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(1, "Filtered event"); - histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(2, "After sel8"); - histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(3, "kNoTimeFrameBorder"); - histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(4, "kNoITSROFrameBorder"); - histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(5, "kNoSameBunchPileup"); - histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(6, "kIsGoodZvtxFT0vsPV"); - histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(7, "kNoCollInTimeRangeStandard"); - histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(8, "After Occupancy"); + histos.add("hEventCount", "Number of Events;; Count", {HistType::kTH1D, {{15, -0.5, 14.5}}}); + histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(kFilteredEvents + 1, "Filtered event"); + histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(kAfterSel8 + 1, "After sel8"); + histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(kUseNoTimeFrameBorder + 1, "kNoTimeFrameBorder"); + histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(kUseNoITSROFrameBorder + 1, "kNoITSROFrameBorder"); + histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(kUseNoSameBunchPileup + 1, "kNoSameBunchPileup"); + histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(kUseGoodZvtxFT0vsPV + 1, "kIsGoodZvtxFT0vsPV"); + histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(kUseNoCollInRofStandard + 1, "kNoCollInTimeRangeStandard"); + histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(kUseGoodITSLayersAll + 1, "kIsGoodITSLayersAll"); + histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(kUseNoCollInRofStandard + 1, "kNoCollInRofStandard"); + histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(kUseNoHighMultCollInPrevRof + 1, "kNoHighMultCollInPrevRof"); + histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(kUseOccupancy + 1, "Occupancy Cut"); + histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(kUseMultCorrCut + 1, "Multiplicity correlation Cut"); + histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(kUseT0AV0ACut + 1, "T0AV0A cut"); + histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(kUseVertexITSTPC + 1, "kIsVertexITSTPC"); + histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(kUseTVXinTRD + 1, "kTVXinTRD"); + + histos.add("hTrackCount", "Number of Tracks;; Count", {HistType::kTH1D, {{7, -0.5, 6.5}}}); + histos.get(HIST("hTrackCount"))->GetXaxis()->SetBinLabel(kFilteredTracks + 1, "Filtered track"); + histos.get(HIST("hTrackCount"))->GetXaxis()->SetBinLabel(kUseGlobalTracks + 1, "Global tracks"); + histos.get(HIST("hTrackCount"))->GetXaxis()->SetBinLabel(kUsePvContributor + 1, "PV contributor"); + histos.get(HIST("hTrackCount"))->GetXaxis()->SetBinLabel(kItsClustersCut + 1, "ITS clusters"); + histos.get(HIST("hTrackCount"))->GetXaxis()->SetBinLabel(kHasTpcSignal + 1, "TPC signal"); + histos.get(HIST("hTrackCount"))->GetXaxis()->SetBinLabel(kTpcClustersCut + 1, "TPC clusters"); + histos.get(HIST("hTrackCount"))->GetXaxis()->SetBinLabel(kTpcCrossedRowsCut + 1, "TPC crossed rows"); if (cfgOutputNUAWeights) { histos.add("NUA/hPhiEtaVtxz_ref", ";#varphi;#eta;v_{z}", {HistType::kTH3D, {axisPhi, {64, -1.6, 1.6}, {40, -10, 10}}}); @@ -348,115 +472,62 @@ struct ResonancesGfwFlow { histos.add("NUA/hPhiEtaPt_phi", ";#varphi;#eta;p_{T}", {HistType::kTH3D, {axisPhi, {64, -1.6, 1.6}, axisPt}}); } - if (cfgUseBootStrap) { - for (int i = 0; i < cfgNbootstrap; i++) { - refC22Boot[i] = histos.add(Form("BootStrap/Refc22_bootstrap_%d", i), "", {HistType::kTProfile, {axisMultiplicity}}); - refC24Boot[i] = histos.add(Form("BootStrap/Refc24_bootstrap_%d", i), "", {HistType::kTProfile, {axisMultiplicity}}); - if (cfgUsePhi) { - phiD22FPtBoot[i] = histos.add(Form("BootStrap/phid22Fpt_bootstrap_%d", i), "", {HistType::kTProfile3D, {axisPt, axisPhiMass, axisMultiplicity}}); - phiD24FPtBoot[i] = histos.add(Form("BootStrap/phid24Fpt_bootstrap_%d", i), "", {HistType::kTProfile3D, {axisPt, axisPhiMass, axisMultiplicity}}); - phiD22BPtBoot[i] = histos.add(Form("BootStrap/phid22Bpt_bootstrap_%d", i), "", {HistType::kTProfile3D, {axisPt, axisPhiMass, axisMultiplicity}}); - phiD24BPtBoot[i] = histos.add(Form("BootStrap/phid24Bpt_bootstrap_%d", i), "", {HistType::kTProfile3D, {axisPt, axisPhiMass, axisMultiplicity}}); - } - if (cfgUseK0) { - k0D22FPtBoot[i] = histos.add(Form("BootStrap/k0d22Fpt_bootstrap_%d", i), "", {HistType::kTProfile3D, {axisPt, axisK0Mass, axisMultiplicity}}); - k0D24FPtBoot[i] = histos.add(Form("BootStrap/k0d24Fpt_bootstrap_%d", i), "", {HistType::kTProfile3D, {axisPt, axisK0Mass, axisMultiplicity}}); - k0D22BPtBoot[i] = histos.add(Form("BootStrap/k0d22Bpt_bootstrap_%d", i), "", {HistType::kTProfile3D, {axisPt, axisK0Mass, axisMultiplicity}}); - k0D24BPtBoot[i] = histos.add(Form("BootStrap/k0d24Bpt_bootstrap_%d", i), "", {HistType::kTProfile3D, {axisPt, axisK0Mass, axisMultiplicity}}); - } - if (cfgUseLambda) { - lambdaD22FPtBoot[i] = histos.add(Form("BootStrap/lambdad22Fpt_bootstrap_%d", i), "", {HistType::kTProfile3D, {axisPt, axisLambdaMass, axisMultiplicity}}); - lambdaD24FPtBoot[i] = histos.add(Form("BootStrap/lambdad24Fpt_bootstrap_%d", i), "", {HistType::kTProfile3D, {axisPt, axisLambdaMass, axisMultiplicity}}); - lambdaD22BPtBoot[i] = histos.add(Form("BootStrap/lambdad22Bpt_bootstrap_%d", i), "", {HistType::kTProfile3D, {axisPt, axisLambdaMass, axisMultiplicity}}); - lambdaD24BPtBoot[i] = histos.add(Form("BootStrap/lambdad24Bpt_bootstrap_%d", i), "", {HistType::kTProfile3D, {axisPt, axisLambdaMass, axisMultiplicity}}); - - anLambdaD22FPtBoot[i] = histos.add(Form("BootStrap/anlambdad22Fpt_bootstrap_%d", i), "", {HistType::kTProfile3D, {axisPt, axisLambdaMass, axisMultiplicity}}); - anLambdaD24FPtBoot[i] = histos.add(Form("BootStrap/anlambdad24Fpt_bootstrap_%d", i), "", {HistType::kTProfile3D, {axisPt, axisLambdaMass, axisMultiplicity}}); - anLambdaD22BPtBoot[i] = histos.add(Form("BootStrap/anlambdad22Bpt_bootstrap_%d", i), "", {HistType::kTProfile3D, {axisPt, axisLambdaMass, axisMultiplicity}}); - anLambdaD24BPtBoot[i] = histos.add(Form("BootStrap/anlambdad24Bpt_bootstrap_%d", i), "", {HistType::kTProfile3D, {axisPt, axisLambdaMass, axisMultiplicity}}); - } - } // end of bootstrap loop - } // end of bootstrap condition - o2::framework::AxisSpec axis = axisPt; int nPtBins = axis.binEdges.size() - 1; double* ptBins = &(axis.binEdges)[0]; fPtAxis = new TAxis(nPtBins, ptBins); - fPhiMassAxis = new TAxis(vMassBins[Phi - 2], vMassMin[Phi - 2], vMassMax[Phi - 2]); - fK0MassAxis = new TAxis(vMassBins[K0 - 1], vMassMin[K0 - 1], vMassMax[K0 - 1]); - fLambdaMassAxis = new TAxis(vMassBins[Lambda - 1], vMassMin[Lambda - 1], vMassMax[Lambda - 1]); + fPhiMassAxis = new TAxis(resoSwitchVals[PHI][kMassBins], resoCutVals[PHI][kMassMin], resoCutVals[PHI][kMassMax]); + fK0MassAxis = new TAxis(resoSwitchVals[K0][kMassBins], resoCutVals[K0][kMassMin], resoCutVals[K0][kMassMax]); + fLambdaMassAxis = new TAxis(resoSwitchVals[LAMBDA][kMassBins], resoCutVals[LAMBDA][kMassMin], resoCutVals[LAMBDA][kMassMax]); - int nPhisPtMassBins = nPtBins * vMassBins[Phi - 2]; - int nK0sPtMassBins = nPtBins * vMassBins[K0 - 1]; - int nLambdasPtMassBins = nPtBins * vMassBins[Lambda - 1]; + int nPhisPtMassBins = nPtBins * resoSwitchVals[PHI][kMassBins]; + int nK0sPtMassBins = nPtBins * resoSwitchVals[K0][kMassBins]; + int nLambdasPtMassBins = nPtBins * resoSwitchVals[LAMBDA][kMassBins]; + int nPtMassBins; //********** Defining the regions ********** - // reference particles - fGFW->AddRegion("refN08", -0.8, -0.4, 1, 1); - fGFW->AddRegion("refP08", 0.4, 0.8, 1, 1); - - // phi - fGFW->AddRegion("poiNphi", -0.8, -0.4, 1 + nPhisPtMassBins, 2); - fGFW->AddRegion("poiPphi", -0.8, -0.4, 1 + nPhisPtMassBins, 2); - fGFW->AddRegion("olNphi", -0.8, -0.4, 1 + nPhisPtMassBins, 32); - fGFW->AddRegion("olPphi", -0.8, -0.4, 1 + nPhisPtMassBins, 32); - - // kshort - fGFW->AddRegion("poiNk0", -0.8, -0.4, 1 + nK0sPtMassBins, 4); - fGFW->AddRegion("poiPk0", -0.8, -0.4, 1 + nK0sPtMassBins, 4); - fGFW->AddRegion("olNk0", -0.8, -0.4, 1 + nK0sPtMassBins, 64); - fGFW->AddRegion("olPk0", -0.8, -0.4, 1 + nK0sPtMassBins, 64); - - // lambda - fGFW->AddRegion("poiNlam", -0.8, -0.4, 1 + nLambdasPtMassBins, 8); - fGFW->AddRegion("poiPlam", -0.8, -0.4, 1 + nLambdasPtMassBins, 8); - fGFW->AddRegion("olNlam", -0.8, -0.4, 1 + nLambdasPtMassBins, 128); - fGFW->AddRegion("olPlam", -0.8, -0.4, 1 + nLambdasPtMassBins, 128); - - // antilambda - fGFW->AddRegion("poiNantilam", -0.8, -0.4, 1 + nLambdasPtMassBins, 16); - fGFW->AddRegion("poiPantilam", -0.8, -0.4, 1 + nLambdasPtMassBins, 16); - fGFW->AddRegion("olNantilam", -0.8, -0.4, 1 + nLambdasPtMassBins, 256); - fGFW->AddRegion("olPantilam", -0.8, -0.4, 1 + nLambdasPtMassBins, 256); + for (auto i(0); i < regions.GetSize(); ++i) { + if (regions.GetNames()[i].ends_with("phi")) { + nPtMassBins = nPhisPtMassBins; + } else if (regions.GetNames()[i].ends_with("k0")) { + nPtMassBins = nK0sPtMassBins; + } else if (regions.GetNames()[i].ends_with("lam") || regions.GetNames()[i].ends_with("antilam")) { + nPtMassBins = nLambdasPtMassBins; + } else { + nPtMassBins = nPtBins; + } + fGFW->AddRegion(regions.GetNames()[i], regions.GetEtaMin()[i], regions.GetEtaMax()[i], (regions.GetpTDifs()[i]) ? nPtMassBins + 1 : 1, regions.GetBitmasks()[i]); + } //********** Defining the correlations ************ - // NAMING CONVENTION: - // F: Forward --> REF from negative eta + POI from negative eta correlated to REF from positive eta - // B: Backward --> REF from negative eta correlated to REF from positive eta + POI from positive eta - - //--------- reference particles - // Forward and Backward correlations are the same for reference particles - corrconfigs.push_back(fGFW->GetCorrelatorConfig("refN08 {2} refP08 {-2}", "Ref08Gap22", kFALSE)); - corrconfigs.push_back(fGFW->GetCorrelatorConfig("refN08 {2 2} refP08 {-2 -2}", "Ref08Gap24", kFALSE)); - - //--------- pt differential pois - // Phi - corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiNphi refN08 | olNphi {2} refP08 {-2}", "PhiF08Gap22", kTRUE)); - corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiNphi refN08 | olNphi {2 2} refP08 {-2 -2}", "PhiF08Gap24", kTRUE)); - corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiPphi refP08 | olPphi {2} refN08 {-2}", "PhiB08Gap22", kTRUE)); - corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiPphi refP08 | olPphi {2 2} refN08 {-2 -2}", "PhiB08Gap24", kTRUE)); - - // K0 - corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiNk0 refN08 | olNk0 {2} refP08 {-2}", "KsF08Gap22", kTRUE)); - corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiNk0 refN08 | olNk0 {2 2} refP08 {-2 -2}", "KsF08Gap24", kTRUE)); - corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiPk0 refP08 | olPk0 {2} refN08 {-2}", "KsB08Gap22", kTRUE)); - corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiPk0 refP08 | olPk0 {2 2} refN08 {-2 -2}", "KsB08Gap24", kTRUE)); - - // Lambda - corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiNlam refN08 | olNlam {2} refP08 {-2}", "LamF08Gap22", kTRUE)); - corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiNlam refN08 | olNlam {2 2} refP08 {-2 -2}", "LamF08Gap24", kTRUE)); - corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiPlam refP08 | olPlam {2} refN08 {-2}", "LamB08Gap22", kTRUE)); - corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiPlam refP08 | olPlam {2 2} refN08 {-2 -2}", "LamB08Gap24", kTRUE)); - - // Antilambda - corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiNantilam refN08 | olNantilam {2} refP08 {-2}", "AnLamF08Gap22", kTRUE)); - corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiNantilam refN08 | olNantilam {2 2} refP08 {-2 -2}", "AnLamF08Gap24", kTRUE)); - corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiPantilam refP08 | olPantilam {2} refN08 {-2}", "AnLamB08Gap22", kTRUE)); - corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiPantilam refP08 | olPantilam {2 2} refN08 {-2 -2}", "AnLamB08Gap24", kTRUE)); - + for (auto i = 0; i < configs.GetSize(); ++i) { + corrconfigs.push_back(fGFW->GetCorrelatorConfig(configs.GetCorrs()[i], configs.GetHeads()[i], configs.GetpTDifs()[i])); + } + if (corrconfigs.empty()) + LOGF(error, "Configuration contains vectors of different size - check the GFWCorrConfig configurable"); fGFW->CreateRegions(); + // Multiplicity correlation cuts + if (eventCuts[kUseMultCorrCut]) { + 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); + fMultPVCutLow->SetParameters(3257.29, -121.848, 1.98492, -0.0172128, 6.47528e-05, 154.756, -1.86072, -0.0274713, 0.000633499, -3.37757e-06); + 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); + fMultPVCutHigh->SetParameters(3257.29, -121.848, 1.98492, -0.0172128, 6.47528e-05, 154.756, -1.86072, -0.0274713, 0.000633499, -3.37757e-06); + + 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); + fMultCutLow->SetParameters(1654.46, -47.2379, 0.449833, -0.0014125, 150.773, -3.67334, 0.0530503, -0.000614061, 3.15956e-06); + 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); + fMultCutHigh->SetParameters(1654.46, -47.2379, 0.449833, -0.0014125, 150.773, -3.67334, 0.0530503, -0.000614061, 3.15956e-06); + } + if (eventCuts[kUseT0AV0ACut]) { + fT0AV0AMean = new TF1("fT0AV0AMean", "[0]+[1]*x", 0, 200000); + fT0AV0AMean->SetParameters(-1601.0581, 9.417652e-01); + fT0AV0ASigma = new TF1("fT0AV0ASigma", "[0]+[1]*x+[2]*x*x+[3]*x*x*x+[4]*x*x*x*x", 0, 200000); + fT0AV0ASigma->SetParameters(463.4144, 6.796509e-02, -9.097136e-07, 7.971088e-12, -2.600581e-17); + } + + // Track density correction 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]); @@ -477,30 +548,17 @@ struct ResonancesGfwFlow { } } - template - void fillResoProfile(const GFW::CorrConfig& corrconf, const ConstStr& tarName, const double cent, TAxis* partaxis) + template + int findComponent(std::vector>& ptr, const std::string& name) { - double dnx, val; - if (!corrconf.pTDif) { - dnx = fGFW->Calculate(corrconf, 0, kTRUE).real(); - if (dnx == 0) - return; - val = fGFW->Calculate(corrconf, 0, kFALSE).real() / dnx; - if (std::fabs(val) < 1) - histos.fill(tarName, cent, val, dnx); - return; - } - for (int i = 1; i <= fPtAxis->GetNbins(); i++) { - for (int j = 1; j <= partaxis->GetNbins(); j++) { - dnx = fGFW->Calculate(corrconf, ((i - 1) * partaxis->GetNbins()) + (j - 1), kTRUE).real(); - if (dnx == 0) - continue; - val = fGFW->Calculate(corrconf, ((i - 1) * partaxis->GetNbins()) + (j - 1), kFALSE).real() / dnx; - if (std::fabs(val) < 1) - histos.fill(tarName, fPtAxis->GetBinCenter(i), partaxis->GetBinCenter(j), cent, val, dnx); + int nIndex = -1; + for (int i = 0; i < static_cast(ptr.size()); i++) { + if (ptr[i]->GetName() == name) { + nIndex = i; } } - return; + + return nIndex; } void fillProfileBoot(const GFW::CorrConfig& corrconf, std::shared_ptr profile, const double& cent) @@ -533,9 +591,10 @@ struct ResonancesGfwFlow { } return; } + // Cosine pointing angle cut template - bool selectionPair(const TTrack1& track1, const TTrack2& track2) + double cosinePointingAngle(const TTrack1& track1, const TTrack2& track2) { double pt1, pt2, pz1, pz2, p1, p2, angle; pt1 = track1.pt(); @@ -545,10 +604,8 @@ struct ResonancesGfwFlow { p1 = track1.p(); p2 = track2.p(); angle = std::acos((pt1 * pt2 + pz1 * pz2) / (p1 * p2)); - if (cfgUseCosPA && angle < vCosPAs[Phi - 2]) { - return false; - } - return true; + + return angle; } template @@ -563,39 +620,120 @@ struct ResonancesGfwFlow { } template - bool selectionTrack(const TTrack& track) + bool isGoodTrack(const TTrack& track) { - if (cfgUseGlobalTrack && !(track.isGlobalTrack() && track.isPVContributor() && track.itsNCls() > cfgITScluster && track.tpcNClsFound() > cfgTpcCluster && track.hasTPC())) { - return false; + histos.fill(HIST("hTrackCount"), kFilteredTracks); // Filtered tracks + + if (cfgUseGlobalTrack && !(track.isGlobalTrack())) { + return 0; } - if (!cfgUseGlobalTrack && !(track.isPVContributor() && track.itsNCls() > cfgITScluster && track.hasTPC())) { - return false; + histos.fill(HIST("hTrackCount"), kUseGlobalTracks); // After global track selection + + if (!(track.isPVContributor())) { + return 0; } - return true; + histos.fill(HIST("hTrackCount"), kUsePvContributor); // After PV contributor selection + + if (!(track.itsNCls() > cfgITScluster)) { + return 0; + } + histos.fill(HIST("hTrackCount"), kItsClustersCut); // After ITS cluster selection + + if (!(track.hasTPC())) { + return 0; + } + histos.fill(HIST("hTrackCount"), kHasTpcSignal); // If track has TPC signal + + if (!(track.tpcNClsFound() > cfgTpcCluster)) { + return 0; + } + histos.fill(HIST("hTrackCount"), kTpcClustersCut); // After TPC cluster selection + + if (!(track.tpcNClsCrossedRows() > cfgTpcCrossRows)) { + return 0; + } + histos.fill(HIST("hTrackCount"), kTpcCrossedRowsCut); // After TPC crossed rows selection + + return 1; } template - int getNsigmaPID(TTrack track) + int getNsigmaPIDTpcTof(TTrack track) { // Computing Nsigma arrays for pion, kaon, and protons std::array nSigmaTPC = {track.tpcNSigmaPi(), track.tpcNSigmaKa(), track.tpcNSigmaPr()}; std::array nSigmaCombined = {std::hypot(track.tpcNSigmaPi(), track.tofNSigmaPi()), std::hypot(track.tpcNSigmaKa(), track.tofNSigmaKa()), std::hypot(track.tpcNSigmaPr(), track.tofNSigmaPr())}; int pid = -1; - float nsigma = cfgTpcNsigmaCut; + float nsigma = cfgTpcCut; // Choose which nSigma to use - std::array nSigmaToUse = (track.pt() >= cfgTofPtCut && track.hasTOF()) ? nSigmaCombined : nSigmaTPC; - if (track.pt() >= cfgTofPtCut && !track.hasTOF()) - return -1; + std::array nSigmaToUse = (track.pt() > cfgTofPtCut && track.hasTOF()) ? nSigmaCombined : nSigmaTPC; + if (track.pt() > cfgTofPtCut && !track.hasTOF()) + return 0; const int numSpecies = 3; + int pidCount = 0; // Select particle with the lowest nsigma for (int i = 0; i < numSpecies; ++i) { if (std::abs(nSigmaToUse[i]) < nsigma) { + if (pidCount > 0 && cfgUseStrictPID) + return 0; // more than one particle with low nsigma + + pidCount++; pid = i; - nsigma = std::abs(nSigmaToUse[i]); + if (!cfgUseStrictPID) + nsigma = std::abs(nSigmaToUse[i]); } } + return pid + 1; // shift the pid by 1, 1 = pion, 2 = kaon, 3 = proton + } + + template + int getNsigmaPIDAssymmetric(TTrack track) + { + // Computing Nsigma arrays for pion, kaon, and protons + std::array nSigmaTPC = {track.tpcNSigmaPi(), track.tpcNSigmaKa(), track.tpcNSigmaPr()}; + std::array nSigmaTOF = {track.tofNSigmaPi(), track.tofNSigmaKa(), track.tofNSigmaPr()}; + std::array nSigmaITS = {itsResponse.nSigmaITS(track), itsResponse.nSigmaITS(track), itsResponse.nSigmaITS(track)}; + int pid = -1; + + std::array nSigmaToUse = cfgUseItsPID ? nSigmaITS : nSigmaTPC; // Choose which nSigma to use: TPC or ITS + std::array detectorNsigmaCut = cfgUseItsPID ? itsNsigmaCut : tpcNsigmaCut; // Choose which nSigma to use: TPC or ITS + + bool isPion, isKaon, isProton; + bool isDetectedPion = nSigmaToUse[0] < detectorNsigmaCut[0] && nSigmaToUse[0] > detectorNsigmaCut[0 + 3]; + bool isDetectedKaon = nSigmaToUse[1] < detectorNsigmaCut[1] && nSigmaToUse[1] > detectorNsigmaCut[1 + 3]; + bool isDetectedProton = nSigmaToUse[2] < detectorNsigmaCut[2] && nSigmaToUse[2] > detectorNsigmaCut[2 + 3]; + + bool isTofPion = nSigmaTOF[0] < tofNsigmaCut[0] && nSigmaTOF[0] > tofNsigmaCut[0 + 3]; + bool isTofKaon = nSigmaTOF[1] < tofNsigmaCut[1] && nSigmaTOF[1] > tofNsigmaCut[1 + 3]; + bool isTofProton = nSigmaTOF[2] < tofNsigmaCut[2] && nSigmaTOF[2] > tofNsigmaCut[2 + 3]; + + if (track.pt() > cfgTofPtCut && !track.hasTOF()) { + return 0; + } else if (track.pt() > cfgTofPtCut && track.hasTOF()) { + isPion = isTofPion && isDetectedPion; + isKaon = isTofKaon && isDetectedKaon; + isProton = isTofProton && isDetectedProton; + } else { + isPion = isDetectedPion; + isKaon = isDetectedKaon; + isProton = isDetectedProton; + } + + if ((isPion && isKaon) || (isPion && isProton) || (isKaon && isProton)) { + return 0; // more than one particle satisfy the criteria + } + + if (isPion) { + pid = PIONS; + } else if (isKaon) { + pid = KAONS; + } else if (isProton) { + pid = PROTONS; + } else { + return 0; // no particle satisfies the criteria + } return pid + 1; // shift the pid by 1, 1 = pion, 2 = kaon, 3 = proton } @@ -609,35 +747,35 @@ struct ResonancesGfwFlow { mAcceptance.clear(); mAcceptance.resize(kCount_OutputSpecies); - mAcceptance[Ref] = ccdb->getForTimeStamp(cfgAcceptance.value + "_ref", timestamp); - if (mAcceptance[Ref]) - LOGF(info, "Loaded acceptance weights from %s_ref (%p)", cfgAcceptance.value.c_str(), (void*)mAcceptance[Ref]); - else - LOGF(fatal, "Could not load acceptance weights from %s_ref (%p)", cfgAcceptance.value.c_str(), (void*)mAcceptance[Ref]); - mAcceptance[K0] = ccdb->getForTimeStamp(cfgAcceptance.value + "_k0", timestamp); if (mAcceptance[K0]) LOGF(info, "Loaded acceptance weights from %s_k0 (%p)", cfgAcceptance.value.c_str(), (void*)mAcceptance[K0]); else LOGF(fatal, "Could not load acceptance weights from %s_k0 (%p)", cfgAcceptance.value.c_str(), (void*)mAcceptance[K0]); - mAcceptance[Lambda] = ccdb->getForTimeStamp(cfgAcceptance.value + "_lambda", timestamp); - if (mAcceptance[Lambda]) - LOGF(info, "Loaded acceptance weights from %s_lambda (%p)", cfgAcceptance.value.c_str(), (void*)mAcceptance[Lambda]); + mAcceptance[LAMBDA] = ccdb->getForTimeStamp(cfgAcceptance.value + "_lambda", timestamp); + if (mAcceptance[LAMBDA]) + LOGF(info, "Loaded acceptance weights from %s_lambda (%p)", cfgAcceptance.value.c_str(), (void*)mAcceptance[LAMBDA]); + else + LOGF(fatal, "Could not load acceptance weights from %s_lambda (%p)", cfgAcceptance.value.c_str(), (void*)mAcceptance[LAMBDA]); + + mAcceptance[PHI] = ccdb->getForTimeStamp(cfgAcceptance.value + "_phi", timestamp); + if (mAcceptance[PHI]) + LOGF(info, "Loaded acceptance weights from %s_phi (%p)", cfgAcceptance.value.c_str(), (void*)mAcceptance[PHI]); else - LOGF(fatal, "Could not load acceptance weights from %s_lambda (%p)", cfgAcceptance.value.c_str(), (void*)mAcceptance[Lambda]); + LOGF(fatal, "Could not load acceptance weights from %s_phi (%p)", cfgAcceptance.value.c_str(), (void*)mAcceptance[PHI]); - mAcceptance[AnLambda] = ccdb->getForTimeStamp(cfgAcceptance.value + "_AnLambda", timestamp); - if (mAcceptance[AnLambda]) - LOGF(info, "Loaded acceptance weights from %s_anlambda (%p)", cfgAcceptance.value.c_str(), (void*)mAcceptance[AnLambda]); + mAcceptance[ANLAMBDA] = ccdb->getForTimeStamp(cfgAcceptance.value + "_anlambda", timestamp); + if (mAcceptance[ANLAMBDA]) + LOGF(info, "Loaded acceptance weights from %s_anlambda (%p)", cfgAcceptance.value.c_str(), (void*)mAcceptance[ANLAMBDA]); else - LOGF(fatal, "Could not load acceptance weights from %s_anlambda (%p)", cfgAcceptance.value.c_str(), (void*)mAcceptance[AnLambda]); + LOGF(fatal, "Could not load acceptance weights from %s_anlambda (%p)", cfgAcceptance.value.c_str(), (void*)mAcceptance[ANLAMBDA]); - mAcceptance[Phi] = ccdb->getForTimeStamp(cfgAcceptance.value + "_phi", timestamp); - if (mAcceptance[Phi]) - LOGF(info, "Loaded acceptance weights from %s_phi (%p)", cfgAcceptance.value.c_str(), (void*)mAcceptance[Phi]); + mAcceptance[REF] = ccdb->getForTimeStamp(cfgAcceptance.value + "_ref", timestamp); + if (mAcceptance[REF]) + LOGF(info, "Loaded acceptance weights from %s_ref (%p)", cfgAcceptance.value.c_str(), (void*)mAcceptance[REF]); else - LOGF(fatal, "Could not load acceptance weights from %s_phi (%p)", cfgAcceptance.value.c_str(), (void*)mAcceptance[Phi]); + LOGF(fatal, "Could not load acceptance weights from %s_ref (%p)", cfgAcceptance.value.c_str(), (void*)mAcceptance[REF]); } correctionsLoaded = true; @@ -645,7 +783,7 @@ struct ResonancesGfwFlow { template double getAcceptance(TTrack track, const TCollision collision, int pid_index_reso) - { // 0 = ref, 1 = k0, 2 = lambda, 3 = anti-lambda, 4 = phi + { // 0 = k0, 1 = lambda, 2 = phi, 3 = anti-lambda, 4 = ref if (pid_index_reso < 0 || pid_index_reso >= kCount_OutputSpecies) { return 1; } @@ -674,7 +812,7 @@ struct ResonancesGfwFlow { template double getAcceptancePhi(vector mom, const TCollision collision, int pid_index_reso) - { // 0 = ref, 1 = k0, 2 = lambda, 3 = anti-lambda, 4 = phi + { // 0 = k0, 1 = lambda, 2 = phi, 3 = anti-lambda, 4 = ref if (pid_index_reso < 0 || pid_index_reso >= kCount_OutputSpecies) { return 1; } @@ -712,7 +850,7 @@ struct ResonancesGfwFlow { bool withinPtPOI = (cfgCutPtPOIMin < pt) && (pt < cfgCutPtPOIMax); // within POI pT range bool withinPtRef = (cfgCutPtMin < pt) && (pt < cfgCutPtMax); // within RF pT range - if (withinPtRef && !pid_index_reso) { + if (withinPtRef && pid_index_reso == REF) { histos.fill(HIST("NUA/hPhiEtaVtxz_ref"), track.phi(), track.eta(), vtxz); // pt-subset of charged particles for ref flow histos.fill(HIST("NUA/hPhiPtCent_ref"), track.phi(), track.pt(), cent); histos.fill(HIST("NUA/hPhiEtaPt_ref"), track.phi(), track.eta(), track.pt()); @@ -725,12 +863,12 @@ struct ResonancesGfwFlow { histos.fill(HIST("NUA/hPhiPtCent_k0"), track.phi(), track.pt(), cent); histos.fill(HIST("NUA/hPhiEtaPt_k0"), track.phi(), track.eta(), track.pt()); break; - case Lambda: + case LAMBDA: histos.fill(HIST("NUA/hPhiEtaVtxz_lambda"), track.phi(), track.eta(), vtxz); // Lambda weights histos.fill(HIST("NUA/hPhiPtCent_lambda"), track.phi(), track.pt(), cent); histos.fill(HIST("NUA/hPhiEtaPt_lambda"), track.phi(), track.eta(), track.pt()); break; - case AnLambda: + case ANLAMBDA: histos.fill(HIST("NUA/hPhiEtaVtxz_anlambda"), track.phi(), track.eta(), vtxz); // Anti-Lambda weights histos.fill(HIST("NUA/hPhiPtCent_anlambda"), track.phi(), track.pt(), cent); histos.fill(HIST("NUA/hPhiEtaPt_anlambda"), track.phi(), track.eta(), track.pt()); @@ -743,23 +881,24 @@ struct ResonancesGfwFlow { template void resurrectPhi(TTrack trackplus, TTrack trackminus, const TCollision collision, vector plusdaug, vector minusdaug, vector mom, double plusmass, const ConstStr& hist) { - const int nKaon = 2; for (auto const& [partplus, partminus] : o2::soa::combinations(o2::soa::CombinationsFullIndexPolicy(trackplus, trackminus))) { - if (getNsigmaPID(partplus) != nKaon) - continue; - if (getNsigmaPID(partminus) != nKaon) + histos.fill(HIST("hPhiCount"), 0.5); + if (!selectionV0Daughter(partplus, KAONS) || !selectionV0Daughter(partminus, KAONS)) // 0 = pion, 1 = kaon, 2 = proton continue; + histos.fill(HIST("hPhiCount"), 1.5); + if (isFakeKaon(partplus) || isFakeKaon(partminus)) continue; - if (!selectionPair(partplus, partminus)) - continue; - if (!selectionTrack(partplus) || !selectionTrack(partminus)) + histos.fill(HIST("hPhiCount"), 2.5); + + if (resoSwitchVals[PHI][kUseCosPA] && cosinePointingAngle(partplus, partminus) < resoCutVals[PHI][kCosPA]) continue; + histos.fill(HIST("hPhiCount"), 3.5); - histos.fill(HIST("KaplusTPC"), partplus.pt(), partplus.tpcNSigmaKa()); - histos.fill(HIST("KaplusTOF"), partplus.pt(), partplus.tofNSigmaKa()); - histos.fill(HIST("KaminusTPC"), partminus.pt(), partminus.tpcNSigmaKa()); - histos.fill(HIST("KaminusTOF"), partminus.pt(), partminus.tofNSigmaKa()); + histos.fill(HIST("KaPlusTPC"), partplus.pt(), partplus.tpcNSigmaKa()); + histos.fill(HIST("KaPlusTOF"), partplus.pt(), partplus.tofNSigmaKa()); + histos.fill(HIST("KaMinusTPC"), partminus.pt(), partminus.tpcNSigmaKa()); + histos.fill(HIST("KaMinusTOF"), partminus.pt(), partminus.tofNSigmaKa()); std::array, 2> ptarr = {{{partplus.px(), partplus.py(), partplus.pz()}, {partminus.px(), partminus.py(), partminus.pz()}}}; std::array massarr = {plusmass, plusmass}; @@ -781,7 +920,9 @@ struct ResonancesGfwFlow { phi = RecoDecay::constrainAngle(phi, 0.0, 1); // constrain azimuthal angle to [0,2pi] - if (std::abs(mom.Rapidity()) < cfgRapidityCut) { + if (std::abs(mom.Rapidity()) < resoCutVals[PHI][kRapidity]) { + histos.fill(HIST("hPhiCount"), 4.5); + histos.fill(hist, invMass, pt, collision.centFT0C()); histos.fill(HIST("hPhiPhi"), phi); histos.fill(HIST("hPhiEta"), mom.Eta()); @@ -794,7 +935,7 @@ struct ResonancesGfwFlow { histos.fill(HIST("NUA/hPhiEtaPt_phi"), phi, mom.Eta(), pt); } double weff = 1; - double waccPOI = getAcceptancePhi(mom, collision, Phi); + double waccPOI = getAcceptancePhi(mom, collision, PHI); if (withinPtPOI) fGFW->Fill(mom.Eta(), ((fPtAxis->FindBin(pt) - 1) * fPhiMassAxis->GetNbins()) + (fPhiMassAxis->FindBin(invMass) - 1), phi, weff * waccPOI, 2); @@ -806,16 +947,30 @@ struct ResonancesGfwFlow { } template - bool selectionV0Daughter(TTrack const& track, int pid) // pid 1: proton, pid 0: pion + bool selectionV0Daughter(TTrack const& track, int pid) { - if (track.tpcNClsFound() < cfgTpcCluster) - return false; + if (!(track.itsNCls() > cfgITScluster)) + return 0; if (!track.hasTPC()) return false; - if (pid == 1 && std::abs(track.tpcNSigmaPr()) > cfgTpcNsigmaCut) - return false; - if (pid == 0 && std::abs(track.tpcNSigmaPi()) > cfgTpcNsigmaCut) + if (track.tpcNClsFound() < cfgTpcCluster) return false; + if (!(track.tpcNClsCrossedRows() > cfgTpcCrossRows)) + return 0; + + if (cfgUseOnlyTPC) { + if (pid == PIONS && std::abs(track.tpcNSigmaPi()) > cfgTpcCut) + return false; + if (pid == KAONS && std::abs(track.tpcNSigmaKa()) > cfgTpcCut) + return false; + if (pid == PROTONS && std::abs(track.tpcNSigmaPr()) > cfgTpcCut) + return false; + } else { + int partIndex = cfgUseAsymmetricPID ? getNsigmaPIDAssymmetric(track) : getNsigmaPIDTpcTof(track); + int pidIndex = partIndex - 1; // 0 = pion, 1 = kaon, 2 = proton + if (pidIndex != pid) + return false; + } return true; } @@ -834,13 +989,13 @@ struct ResonancesGfwFlow { auto negtrack = candidate.template negTrack_as(); histos.fill(HIST("hLambdaCount"), 0.5); - if (postrack.pt() < vPosTrackPt[Lambda - 1] || negtrack.pt() < vNegTrackPt[Lambda - 1]) + if (postrack.pt() < resoCutVals[LAMBDA][kPosTrackPt] || negtrack.pt() < resoCutVals[LAMBDA][kNegTrackPt]) return false; histos.fill(HIST("hLambdaCount"), 1.5); - if (mlambda > vMassMin[Lambda - 1] && mlambda < vMassMax[Lambda - 1]) + if (mlambda > resoCutVals[LAMBDA][kMassMin] && mlambda < resoCutVals[LAMBDA][kMassMax]) isL = true; - if (mantilambda > vMassMin[Lambda - 1] && mantilambda < vMassMax[Lambda - 1]) + if (mantilambda > resoCutVals[LAMBDA][kMassMin] && mantilambda < resoCutVals[LAMBDA][kMassMax]) isAL = true; if (!isL && !isAL) { @@ -849,40 +1004,40 @@ struct ResonancesGfwFlow { histos.fill(HIST("hLambdaCount"), 2.5); // Rapidity correction - if (candidate.yLambda() > cfgRapidityCut) + if (candidate.yLambda() > resoCutVals[LAMBDA][kRapidity]) return false; histos.fill(HIST("hLambdaCount"), 3.5); // DCA cuts for lambda and antilambda if (isL) { - if (std::abs(candidate.dcapostopv()) < cfgDCALambdaPosToPVMin || std::abs(candidate.dcanegtopv()) < cfgDCALambdaNegToPVMin) + if (std::abs(candidate.dcapostopv()) < resoCutVals[LAMBDA][kDCAPosToPVMin] || std::abs(candidate.dcanegtopv()) < resoCutVals[LAMBDA][kDCANegToPVMin]) return false; } if (isAL) { - if (std::abs(candidate.dcapostopv()) < cfgDCALambdaNegToPVMin || std::abs(candidate.dcanegtopv()) < cfgDCALambdaPosToPVMin) + if (std::abs(candidate.dcapostopv()) < resoCutVals[LAMBDA][kDCANegToPVMin] || std::abs(candidate.dcanegtopv()) < resoCutVals[LAMBDA][kDCAPosToPVMin]) return false; } histos.fill(HIST("hLambdaCount"), 4.5); - if (std::abs(candidate.dcaV0daughters()) > vDCABetDaug[Lambda - 1]) + if (std::abs(candidate.dcaV0daughters()) > resoSwitchVals[LAMBDA][kDCABetDaug]) return false; histos.fill(HIST("hLambdaCount"), 5.5); // v0 radius cuts - if (cfgUseV0Radius && (candidate.v0radius() < cfgLambdaRadiusMin || candidate.v0radius() > cfgLambdaRadiusMax)) + if (resoSwitchVals[LAMBDA][kUseV0Radius] && (candidate.v0radius() < resoCutVals[LAMBDA][kRadiusMin] || candidate.v0radius() > resoCutVals[LAMBDA][kRadiusMax])) return false; histos.fill(HIST("hLambdaCount"), 6.5); // cosine pointing angle cuts - if (candidate.v0cosPA() < vCosPAs[Lambda - 1]) + if (candidate.v0cosPA() < resoCutVals[LAMBDA][kCosPA]) return false; histos.fill(HIST("hLambdaCount"), 7.5); // Proper lifetime - if (cfgUseProperLifetime && candidate.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * massLambda > cfgLambdaLifeTime) + if (resoSwitchVals[LAMBDA][kUseProperLifetime] && candidate.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * massLambda > resoCutVals[LAMBDA][kLifeTime]) return false; histos.fill(HIST("hLambdaCount"), 8.5); if (isL) { - if (!selectionV0Daughter(postrack, 1) || !selectionV0Daughter(negtrack, 0)) + if (!selectionV0Daughter(postrack, PROTONS) || !selectionV0Daughter(negtrack, PIONS)) return false; } if (isAL) { - if (!selectionV0Daughter(postrack, 0) || !selectionV0Daughter(negtrack, 1)) + if (!selectionV0Daughter(postrack, PIONS) || !selectionV0Daughter(negtrack, PROTONS)) return false; } histos.fill(HIST("hLambdaCount"), 9.5); @@ -893,9 +1048,9 @@ struct ResonancesGfwFlow { if (isL) { if (cfgOutputNUAWeights) - fillWeights(candidate, collision, Lambda); + fillWeights(candidate, collision, LAMBDA); - double waccPOI = getAcceptance(candidate, collision, Lambda); + double waccPOI = getAcceptance(candidate, collision, LAMBDA); if (withinPtPOI) fGFW->Fill(candidate.eta(), ((fPtAxis->FindBin(candidate.pt()) - 1) * fLambdaMassAxis->GetNbins()) + (fLambdaMassAxis->FindBin(mlambda) - 1), candidate.phi(), waccPOI * weff, 8); if (withinPtPOI && withinPtRef) @@ -904,16 +1059,16 @@ struct ResonancesGfwFlow { histos.fill(HIST("hLambdaMass_sparse"), mlambda, candidate.pt(), collision.centFT0C()); histos.fill(HIST("hLambdaPhi"), candidate.phi()); histos.fill(HIST("hLambdaEta"), candidate.eta()); - histos.fill(HIST("PlusTPC_L"), postrack.pt(), postrack.tpcNSigmaKa()); - histos.fill(HIST("PlusTOF_L"), postrack.pt(), postrack.tofNSigmaKa()); - histos.fill(HIST("MinusTPC_L"), negtrack.pt(), negtrack.tpcNSigmaKa()); - histos.fill(HIST("MinusTOF_L"), negtrack.pt(), negtrack.tofNSigmaKa()); + histos.fill(HIST("PrPlusTPC_L"), postrack.pt(), postrack.tpcNSigmaKa()); + histos.fill(HIST("PrPlusTOF_L"), postrack.pt(), postrack.tofNSigmaKa()); + histos.fill(HIST("PiMinusTPC_L"), negtrack.pt(), negtrack.tpcNSigmaKa()); + histos.fill(HIST("PiMinusTOF_L"), negtrack.pt(), negtrack.tofNSigmaKa()); } if (isAL) { if (cfgOutputNUAWeights) - fillWeights(candidate, collision, AnLambda); + fillWeights(candidate, collision, ANLAMBDA); - double waccPOI = getAcceptance(candidate, collision, AnLambda); + double waccPOI = getAcceptance(candidate, collision, ANLAMBDA); if (withinPtPOI) fGFW->Fill(candidate.eta(), ((fPtAxis->FindBin(candidate.pt()) - 1) * fLambdaMassAxis->GetNbins()) + (fLambdaMassAxis->FindBin(mantilambda) - 1), candidate.phi(), waccPOI * weff, 16); if (withinPtPOI && withinPtRef) @@ -922,10 +1077,10 @@ struct ResonancesGfwFlow { histos.fill(HIST("hAntiLambdaMass_sparse"), mantilambda, candidate.pt(), collision.centFT0C()); histos.fill(HIST("hAntiLambdaPhi"), candidate.phi()); histos.fill(HIST("hAntiLambdaEta"), candidate.eta()); - histos.fill(HIST("PlusTPC_AL"), postrack.pt(), postrack.tpcNSigmaKa()); - histos.fill(HIST("PlusTOF_AL"), postrack.pt(), postrack.tofNSigmaKa()); - histos.fill(HIST("MinusTPC_AL"), negtrack.pt(), negtrack.tpcNSigmaKa()); - histos.fill(HIST("MinusTOF_AL"), negtrack.pt(), negtrack.tofNSigmaKa()); + histos.fill(HIST("PiPlusTPC_AL"), postrack.pt(), postrack.tpcNSigmaKa()); + histos.fill(HIST("PiPlusTOF_AL"), postrack.pt(), postrack.tofNSigmaKa()); + histos.fill(HIST("PrMinusTPC_AL"), negtrack.pt(), negtrack.tpcNSigmaKa()); + histos.fill(HIST("PrMinusTOF_AL"), negtrack.pt(), negtrack.tofNSigmaKa()); } return true; } @@ -940,36 +1095,36 @@ struct ResonancesGfwFlow { auto negtrack = candidate.template negTrack_as(); histos.fill(HIST("hK0Count"), 0.5); - if (postrack.pt() < vPosTrackPt[K0 - 1] || negtrack.pt() < vNegTrackPt[K0 - 1]) + if (postrack.pt() < resoCutVals[K0][kPosTrackPt] || negtrack.pt() < resoCutVals[K0][kNegTrackPt]) return false; histos.fill(HIST("hK0Count"), 1.5); - if (mk0 < vMassMin[K0 - 1] && mk0 > vMassMax[K0 - 1]) + if (mk0 < resoCutVals[K0][kMassMin] && mk0 > resoCutVals[K0][kMassMax]) return false; histos.fill(HIST("hK0Count"), 2.5); // Rapidity correction - if (candidate.yK0Short() > cfgRapidityCut) + if (candidate.yK0Short() > resoCutVals[K0][kRapidity]) return false; histos.fill(HIST("hK0Count"), 3.5); // DCA cuts for K0short - if (std::abs(candidate.dcapostopv()) < cfgDCAK0PosToPVMin || std::abs(candidate.dcanegtopv()) < cfgDCAK0NegToPVMin) + if (std::abs(candidate.dcapostopv()) < resoCutVals[K0][kDCAPosToPVMin] || std::abs(candidate.dcanegtopv()) < resoCutVals[K0][kDCANegToPVMin]) return false; histos.fill(HIST("hK0Count"), 4.5); - if (std::abs(candidate.dcaV0daughters()) > vDCABetDaug[K0 - 1]) + if (std::abs(candidate.dcaV0daughters()) > resoSwitchVals[K0][kDCABetDaug]) return false; histos.fill(HIST("hK0Count"), 5.5); // v0 radius cuts - if (cfgUseV0Radius && (candidate.v0radius() < cfgK0RadiusMin || candidate.v0radius() > cfgK0RadiusMax)) + if (resoSwitchVals[K0][kUseV0Radius] && (candidate.v0radius() < resoCutVals[K0][kRadiusMin] || candidate.v0radius() > resoCutVals[K0][kRadiusMax])) return false; histos.fill(HIST("hK0Count"), 6.5); // cosine pointing angle cuts - if (candidate.v0cosPA() < vCosPAs[K0 - 1]) + if (candidate.v0cosPA() < resoCutVals[K0][kCosPA]) return false; histos.fill(HIST("hK0Count"), 7.5); // Proper lifetime - if (cfgUseProperLifetime && candidate.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * massK0Short > cfgK0LifeTime) + if (resoSwitchVals[K0][kUseProperLifetime] && candidate.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * massK0Short > resoCutVals[K0][kLifeTime]) return false; histos.fill(HIST("hK0Count"), 8.5); - if (!selectionV0Daughter(postrack, 0) || !selectionV0Daughter(negtrack, 0)) + if (!selectionV0Daughter(postrack, PIONS) || !selectionV0Daughter(negtrack, PIONS)) return false; histos.fill(HIST("hK0Count"), 9.5); bool withinPtPOI = (cfgCutPtPOIMin < candidate.pt()) && (candidate.pt() < cfgCutPtPOIMax); // within POI pT range @@ -989,15 +1144,114 @@ struct ResonancesGfwFlow { histos.fill(HIST("hK0Mass_sparse"), mk0, candidate.pt(), collision.centFT0C()); histos.fill(HIST("hK0Phi"), candidate.phi()); histos.fill(HIST("hK0Eta"), candidate.eta()); - histos.fill(HIST("PlusTPC_K0"), postrack.pt(), postrack.tpcNSigmaKa()); - histos.fill(HIST("PlusTOF_K0"), postrack.pt(), postrack.tofNSigmaKa()); - histos.fill(HIST("MinusTPC_K0"), negtrack.pt(), negtrack.tpcNSigmaKa()); - histos.fill(HIST("MinusTOF_K0"), negtrack.pt(), negtrack.tofNSigmaKa()); + histos.fill(HIST("PiPlusTPC_K0"), postrack.pt(), postrack.tpcNSigmaKa()); + histos.fill(HIST("PiPlusTOF_K0"), postrack.pt(), postrack.tofNSigmaKa()); + histos.fill(HIST("PiMinusTPC_K0"), negtrack.pt(), negtrack.tpcNSigmaKa()); + histos.fill(HIST("PiMinusTOF_K0"), negtrack.pt(), negtrack.tofNSigmaKa()); return true; } - using BinningTypeVertexContributor = ColumnBinningPolicy; + template + bool selectionEvent(TCollision collision, const int mult, const float cent) + { + histos.fill(HIST("hEventCount"), kFilteredEvents); + if (!collision.sel8()) { + return 0; + } + histos.fill(HIST("hEventCount"), kAfterSel8); + + if (eventCuts[kUseNoTimeFrameBorder] && !collision.selection_bit(aod::evsel::kNoTimeFrameBorder)) { + return 0; + } + if (eventCuts[kUseNoTimeFrameBorder]) + histos.fill(HIST("hEventCount"), kUseNoTimeFrameBorder); + + if (eventCuts[kUseNoITSROFrameBorder] && !collision.selection_bit(aod::evsel::kNoITSROFrameBorder)) { + return 0; + } + if (eventCuts[kUseNoITSROFrameBorder]) + histos.fill(HIST("hEventCount"), kUseNoITSROFrameBorder); + + if (eventCuts[kUseNoSameBunchPileup] && !collision.selection_bit(aod::evsel::kNoSameBunchPileup)) { + return 0; + } + if (eventCuts[kUseNoSameBunchPileup]) + histos.fill(HIST("hEventCount"), kUseNoSameBunchPileup); + + if (eventCuts[kUseGoodZvtxFT0vsPV] && !collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { + return 0; + } + if (eventCuts[kUseGoodZvtxFT0vsPV]) + histos.fill(HIST("hEventCount"), kUseGoodZvtxFT0vsPV); + + if (eventCuts[kUseNoCollInTimeRangeStandard] && !collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { + return 0; + } + if (eventCuts[kUseNoCollInTimeRangeStandard]) + histos.fill(HIST("hEventCount"), kUseNoCollInTimeRangeStandard); + + if (eventCuts[kUseGoodITSLayersAll] && !collision.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { + return 0; + } + if (eventCuts[kUseGoodITSLayersAll]) + histos.fill(HIST("hEventCount"), kUseGoodITSLayersAll); + + if (eventCuts[kUseNoCollInRofStandard] && !collision.selection_bit(o2::aod::evsel::kNoCollInRofStandard)) { + return 0; + } + if (eventCuts[kUseNoCollInRofStandard]) + histos.fill(HIST("hEventCount"), kUseNoCollInRofStandard); + + if (eventCuts[kUseNoHighMultCollInPrevRof] && !collision.selection_bit(o2::aod::evsel::kNoHighMultCollInPrevRof)) { + return 0; + } + if (eventCuts[kUseNoHighMultCollInPrevRof]) + histos.fill(HIST("hEventCount"), kUseNoHighMultCollInPrevRof); + + auto multNTracksPV = collision.multNTracksPV(); + auto occupancy = collision.trackOccupancyInTimeRange(); + + if (eventCuts[kUseOccupancy] && (occupancy < cfgCutOccupancyMin || occupancy > cfgCutOccupancyMax)) { + return 0; + } + if (eventCuts[kUseOccupancy]) + histos.fill(HIST("hEventCount"), kUseOccupancy); + + if (eventCuts[kUseMultCorrCut]) { + if (multNTracksPV < fMultPVCutLow->Eval(cent)) + return 0; + if (multNTracksPV > fMultPVCutHigh->Eval(cent)) + return 0; + if (mult < fMultCutLow->Eval(cent)) + return 0; + if (mult > fMultCutHigh->Eval(cent)) + return 0; + } + if (eventCuts[kUseMultCorrCut]) + histos.fill(HIST("hEventCount"), kUseMultCorrCut); + + // V0A T0A 5 sigma cut + if (eventCuts[kUseT0AV0ACut] && (std::fabs(collision.multFV0A() - fT0AV0AMean->Eval(collision.multFT0A())) > cfgV0AT0Acut * fT0AV0ASigma->Eval(collision.multFT0A()))) + return 0; + if (eventCuts[kUseT0AV0ACut]) + histos.fill(HIST("hEventCount"), kUseT0AV0ACut); + + if (eventCuts[kUseVertexITSTPC] && !collision.selection_bit(o2::aod::evsel::kIsVertexITSTPC)) + return 0; + if (eventCuts[kUseVertexITSTPC]) + histos.fill(HIST("hEventCount"), kUseVertexITSTPC); + + if (eventCuts[kUseTVXinTRD] && collision.alias_bit(kTVXinTRD)) { + return 0; + } + if (eventCuts[kUseTVXinTRD]) + histos.fill(HIST("hEventCount"), kUseTVXinTRD); + + return 1; + } + + // using BinningTypeVertexContributor = ColumnBinningPolicy; ROOT::Math::PxPyPzMVector phiMom, kaonPlus, kaonMinus; double massKaPlus = o2::constants::physics::MassKPlus; double massLambda = o2::constants::physics::MassLambda; @@ -1005,42 +1259,16 @@ struct ResonancesGfwFlow { void process(AodCollisions::iterator const& collision, aod::BCsWithTimestamps const&, AodTracksWithoutBayes const& tracks, aod::V0Datas const& V0s) { - histos.fill(HIST("hEventCount"), 0.5); int nTot = tracks.size(); if (nTot < 1) return; - if (!collision.sel8()) - return; - histos.fill(HIST("hEventCount"), 1.5); - - if (!collision.selection_bit(aod::evsel::kNoTimeFrameBorder)) - return; - histos.fill(HIST("hEventCount"), 2.5); - - if (!collision.selection_bit(aod::evsel::kNoITSROFrameBorder)) - return; - histos.fill(HIST("hEventCount"), 3.5); - - if (!collision.selection_bit(aod::evsel::kNoSameBunchPileup)) - return; - histos.fill(HIST("hEventCount"), 4.5); - - if (!collision.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV)) - return; - histos.fill(HIST("hEventCount"), 5.5); - - if (!collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) - return; - histos.fill(HIST("hEventCount"), 6.5); + float vtxz = collision.posZ(); + const auto cent = collision.centFT0C(); - int occupancy = collision.trackOccupancyInTimeRange(); - if (occupancy > cfgCutOccupancy) + if (!selectionEvent(collision, nTot, cent)) return; - histos.fill(HIST("hEventCount"), 7.5); - const auto cent = collision.centFT0C(); - float vtxz = collision.posZ(); auto bc = collision.bc_as(); histos.fill(HIST("hVtxZ"), vtxz); @@ -1083,8 +1311,9 @@ struct ResonancesGfwFlow { // Actual track loop for (auto const& track : tracks) { - if (!selectionTrack(track)) + if (!isGoodTrack(track)) continue; + double pt = track.pt(); bool withinPtRef = (cfgCutPtMin < pt) && (pt < cfgCutPtMax); @@ -1092,9 +1321,9 @@ struct ResonancesGfwFlow { if (withinPtRef) if (cfgOutputNUAWeights) - fillWeights(track, collision, Ref); + fillWeights(track, collision, REF); - double waccRef = getAcceptance(track, collision, 0); + double waccRef = getAcceptance(track, collision, REF); if (cfgTrackDensityCorrUse && withinPtRef) { double fphi = v2 * std::cos(2 * (track.phi() - psi2Est)) + v3 * std::cos(3 * (track.phi() - psi3Est)) + v4 * std::cos(4 * (track.phi() - psi4Est)); @@ -1115,80 +1344,64 @@ struct ResonancesGfwFlow { auto posSlicedTracks = posTracks->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); auto negSlicedTracks = negTracks->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); - if (cfgUsePhi) { + if (resoSwitchVals[PHI][kUseParticle]) { resurrectPhi(posSlicedTracks, negSlicedTracks, collision, kaonPlus, kaonMinus, phiMom, massKaPlus, HIST("hPhiMass_sparse")); } + // ---------------------- Analyzing the V0s for (auto const& v0s : V0s) { - if (cfgUseK0) { + if (resoSwitchVals[K0][kUseParticle]) { if (selectionK0(collision, v0s) == true) histos.fill(HIST("hK0s"), 1); } - if (cfgUseLambda) { + if (resoSwitchVals[LAMBDA][kUseParticle]) { if (selectionLambda(collision, v0s) == true) histos.fill(HIST("hLambdas"), 1); } } // End of v0 loop - fillResoProfile(corrconfigs.at(0), HIST("Refc22"), cent, fPhiMassAxis); - fillResoProfile(corrconfigs.at(1), HIST("Refc24"), cent, fPhiMassAxis); - if (cfgUsePhi) { - fillResoProfile(corrconfigs.at(2), HIST("Phid22Fpt"), cent, fPhiMassAxis); - fillResoProfile(corrconfigs.at(3), HIST("Phid24Fpt"), cent, fPhiMassAxis); - fillResoProfile(corrconfigs.at(4), HIST("Phid22Bpt"), cent, fPhiMassAxis); - fillResoProfile(corrconfigs.at(5), HIST("Phid24Bpt"), cent, fPhiMassAxis); - } - if (cfgUseK0) { - fillResoProfile(corrconfigs.at(6), HIST("K0d22Fpt"), cent, fK0MassAxis); - fillResoProfile(corrconfigs.at(7), HIST("K0d24Fpt"), cent, fK0MassAxis); - fillResoProfile(corrconfigs.at(8), HIST("K0d22Bpt"), cent, fK0MassAxis); - fillResoProfile(corrconfigs.at(9), HIST("K0d24Bpt"), cent, fK0MassAxis); - } - if (cfgUseLambda) { - fillResoProfile(corrconfigs.at(10), HIST("Lambdad22Fpt"), cent, fLambdaMassAxis); - fillResoProfile(corrconfigs.at(11), HIST("Lambdad24Fpt"), cent, fLambdaMassAxis); - fillResoProfile(corrconfigs.at(12), HIST("Lambdad22Bpt"), cent, fLambdaMassAxis); - fillResoProfile(corrconfigs.at(13), HIST("Lambdad24Bpt"), cent, fLambdaMassAxis); - - fillResoProfile(corrconfigs.at(14), HIST("AnLambdad22Fpt"), cent, fLambdaMassAxis); - fillResoProfile(corrconfigs.at(15), HIST("AnLambdad24Fpt"), cent, fLambdaMassAxis); - fillResoProfile(corrconfigs.at(16), HIST("AnLambdad22Bpt"), cent, fLambdaMassAxis); - fillResoProfile(corrconfigs.at(17), HIST("AnLambdad24Bpt"), cent, fLambdaMassAxis); - } + // Filling the cumulant profiles + double r = fRndm->Rndm(); + int bootId = static_cast(r * 10); + + for (auto i = 0; i < static_cast(corrconfigs.size()); ++i) { + if (resoSwitchVals[PHI][kUseParticle] && corrconfigs.at(i).Head.starts_with("Phi")) { + int pIndex = findComponent(phiV2, Form("h%spt", corrconfigs.at(i).Head.c_str())); + fillProfileBoot3D(corrconfigs.at(i), phiV2[pIndex], cent, fPhiMassAxis); - // bootstraping - if (cfgUseBootStrap) { - double r = fRndm->Rndm(); - int bootId = static_cast(r * 10); + if (cfgUseBootStrap) { + fillProfileBoot3D(corrconfigs.at(i), phiBoot[bootId][pIndex], cent, fPhiMassAxis); + } + } // end of phi condition - fillProfileBoot(corrconfigs.at(0), refC22Boot[bootId], cent); - fillProfileBoot(corrconfigs.at(1), refC24Boot[bootId], cent); + if (resoSwitchVals[K0][kUseParticle] && corrconfigs.at(i).Head.starts_with("K0")) { + int pIndex = findComponent(k0V2, Form("h%spt", corrconfigs.at(i).Head.c_str())); + fillProfileBoot3D(corrconfigs.at(i), k0V2[pIndex], cent, fK0MassAxis); - if (cfgUsePhi) { - fillProfileBoot3D(corrconfigs.at(2), phiD22FPtBoot[bootId], cent, fPhiMassAxis); - fillProfileBoot3D(corrconfigs.at(3), phiD24FPtBoot[bootId], cent, fPhiMassAxis); - fillProfileBoot3D(corrconfigs.at(4), phiD22BPtBoot[bootId], cent, fPhiMassAxis); - fillProfileBoot3D(corrconfigs.at(5), phiD24BPtBoot[bootId], cent, fPhiMassAxis); - } - if (cfgUseK0) { - fillProfileBoot3D(corrconfigs.at(6), k0D22FPtBoot[bootId], cent, fK0MassAxis); - fillProfileBoot3D(corrconfigs.at(7), k0D24FPtBoot[bootId], cent, fK0MassAxis); - fillProfileBoot3D(corrconfigs.at(8), k0D22BPtBoot[bootId], cent, fK0MassAxis); - fillProfileBoot3D(corrconfigs.at(9), k0D24BPtBoot[bootId], cent, fK0MassAxis); - } - if (cfgUseLambda) { - fillProfileBoot3D(corrconfigs.at(10), lambdaD22FPtBoot[bootId], cent, fLambdaMassAxis); - fillProfileBoot3D(corrconfigs.at(11), lambdaD24FPtBoot[bootId], cent, fLambdaMassAxis); - fillProfileBoot3D(corrconfigs.at(12), lambdaD22BPtBoot[bootId], cent, fLambdaMassAxis); - fillProfileBoot3D(corrconfigs.at(13), lambdaD24BPtBoot[bootId], cent, fLambdaMassAxis); - - fillProfileBoot3D(corrconfigs.at(14), anLambdaD22FPtBoot[bootId], cent, fLambdaMassAxis); - fillProfileBoot3D(corrconfigs.at(15), anLambdaD24FPtBoot[bootId], cent, fLambdaMassAxis); - fillProfileBoot3D(corrconfigs.at(16), anLambdaD22BPtBoot[bootId], cent, fLambdaMassAxis); - fillProfileBoot3D(corrconfigs.at(17), anLambdaD24BPtBoot[bootId], cent, fLambdaMassAxis); - } - } // end of bootstrap condition - } // end of process + if (cfgUseBootStrap) { + fillProfileBoot3D(corrconfigs.at(i), k0Boot[bootId][pIndex], cent, fK0MassAxis); + } + } // end of K0 condition + + if (resoSwitchVals[LAMBDA][kUseParticle] && (corrconfigs.at(i).Head.starts_with("Lam") || corrconfigs.at(i).Head.starts_with("AnLam"))) { + int pIndex = findComponent(lambdaV2, Form("h%spt", corrconfigs.at(i).Head.c_str())); + fillProfileBoot3D(corrconfigs.at(i), lambdaV2[pIndex], cent, fLambdaMassAxis); + + if (cfgUseBootStrap) { + fillProfileBoot3D(corrconfigs.at(i), lambdaBoot[bootId][pIndex], cent, fLambdaMassAxis); + } + } // end of lambda condition + + if (configs.GetHeads()[i].starts_with("Ref")) { + int pIndex = findComponent(refV2, Form("h%s", corrconfigs.at(i).Head.c_str())); + fillProfileBoot(corrconfigs.at(i), refV2[pIndex], cent); + + if (cfgUseBootStrap) { + fillProfileBoot(corrconfigs.at(i), refBoot[bootId][pIndex], cent); + } + } // end of ref condition + } // end of loop over correlation configurations + } // end of processReso }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) From 0882ed52c194504c30aea83b48ca377ac8fdba65 Mon Sep 17 00:00:00 2001 From: Paola Vargas Torres <88360333+PaolaVT@users.noreply.github.com> Date: Fri, 27 Jun 2025 09:29:19 -0600 Subject: [PATCH 240/871] [PWGLF] Ncl cut value was modified (#11794) --- PWGMM/UE/Tasks/dedxAnalysis.cxx | 43 +++++++++++++++++++++++++++++++-- 1 file changed, 41 insertions(+), 2 deletions(-) diff --git a/PWGMM/UE/Tasks/dedxAnalysis.cxx b/PWGMM/UE/Tasks/dedxAnalysis.cxx index af5cfcefd8a..b87e9c30478 100644 --- a/PWGMM/UE/Tasks/dedxAnalysis.cxx +++ b/PWGMM/UE/Tasks/dedxAnalysis.cxx @@ -64,7 +64,6 @@ struct DedxAnalysis { float invMassCutGamma = 0.0015; float magField = 1; float pTcut = 2.0; - float nclCut = 120.0; // Configurable Parameters // Tracks cuts @@ -100,6 +99,8 @@ struct DedxAnalysis { "Minimum Mass Gamma"}; Configurable maxMassGamma{"maxMassGamma", 0.002022f, "Maximum Mass Gamma"}; + Configurable nclCut{"nclCut", 135.0f, + "ncl Cut"}; Configurable calibrationMode{"calibrationMode", false, "calibration mode"}; Configurable additionalCuts{"additionalCuts", true, "additional cuts"}; // Histograms names @@ -555,6 +556,38 @@ struct DedxAnalysis { return true; } + // Phi cut Secondaries + template + bool passedPhiCutSecondaries(const T& trk, float magField, const TF1& fphiCutLow, const TF1& fphiCutHigh) + { + float pt = trk.pt(); + float phi = trk.phi(); + int charge = trk.sign(); + auto nTPCCl = trk.tpcNClsFindable() - trk.tpcNClsFindableMinusFound(); + + if (pt < pTcut) + return true; + + if (magField < 0) // for negatve polarity field + phi = o2::constants::math::TwoPI - phi; + if (charge < 0) // for negatve charge + phi = o2::constants::math::TwoPI - phi; + + // to center gap in the middle + phi += o2::constants::math::PI / 18.0f; + phi = std::fmod(phi, o2::constants::math::PI / 9.0f); + + // cut phi + if (phi < fphiCutHigh.Eval(pt) && phi > fphiCutLow.Eval(pt)) + return false; // reject track + + // cut Ncl + if (nTPCCl < nclCut) + return false; + + return true; + } + // Process Data void process(SelectedCollisions::iterator const& collision, aod::V0Datas const& fullV0s, PIDTracks const& tracks) @@ -590,7 +623,7 @@ struct DedxAnalysis { if (!mySelectionPrim.IsSelected(trk)) continue; - // phi cut + // phi and Ncl cut if (!passedPhiCut(trk, magField, *fphiCutLow, *fphiCutHigh)) continue; @@ -702,6 +735,12 @@ struct DedxAnalysis { continue; if (!negTrack.passedTPCRefit()) continue; + // phi and Ncl cut + if (!passedPhiCutSecondaries(posTrack, magField, *fphiCutLow, *fphiCutHigh)) + continue; + + if (!passedPhiCutSecondaries(negTrack, magField, *fphiCutLow, *fphiCutHigh)) + continue; float signedPpos = posTrack.sign() * posTrack.tpcInnerParam(); float signedPneg = negTrack.sign() * negTrack.tpcInnerParam(); From 4f198e3341696f3640b5c2ee60d1bee43aa069e8 Mon Sep 17 00:00:00 2001 From: Rik Spijkers <78484875+rspijkers@users.noreply.github.com> Date: Fri, 27 Jun 2025 19:27:40 +0200 Subject: [PATCH 241/871] [PWGLF] fix bug in filling inv mass histograms (#11812) --- PWGLF/Tasks/Strangeness/cascadecorrelations.cxx | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/PWGLF/Tasks/Strangeness/cascadecorrelations.cxx b/PWGLF/Tasks/Strangeness/cascadecorrelations.cxx index 13d45dd198b..8adfd81d430 100644 --- a/PWGLF/Tasks/Strangeness/cascadecorrelations.cxx +++ b/PWGLF/Tasks/Strangeness/cascadecorrelations.cxx @@ -574,8 +574,8 @@ struct CascadeCorrelations { ConfigurableAxis multiplicityAxis{"multiplicityAxis", {100, 0, 100}, "Multiplicity (MultFT0M?)"}; ConfigurableAxis invLambdaMassAxis{"invLambdaMassAxis", {100, 1.07f, 1.17f}, "Inv. Mass (GeV/c^{2})"}; AxisSpec signAxis{3, -1.5, 1.5, "sign of cascade"}; - AxisSpec deltaYAxis{40, -2 * maxRapidity, 2 * maxRapidity, "#Delta y"}; - AxisSpec rapidityAxis{100, -maxRapidity, maxRapidity, "y"}; + AxisSpec deltaYAxis{40, -2.f, 2.f, "#Delta y"}; + AxisSpec rapidityAxis{100, -1.f, 1.f, "y"}; AxisSpec selectionFlagAxis{4, -0.5f, 3.5f, "Selection flag of casc candidate"}; AxisSpec itsClustersAxis{8, -0.5, 7.5, "number of ITS clusters"}; AxisSpec tpcRowsAxis{160, -0.5, 159.5, "TPC crossed rows"}; @@ -751,7 +751,7 @@ struct CascadeCorrelations { weight = getEfficiency(hEffXiPlus, casc.pt()); } // LOGF(info, "casc pt %f, weight %f", casc.pt(), weight); - registry.fill(HIST("hMassXiEffCorrected"), casc.mXi(), casc.pt(), casc.yXi(), collision.posZ(), collision.multFT0M(), weight); + registry.fill(HIST("hMassXiEffCorrected"), casc.mXi(), casc.sign(), casc.pt(), casc.yXi(), collision.posZ(), collision.multFT0M(), weight); registry.fill(HIST("hRapidityXi"), casc.yXi()); } if (casc.isSelected() >= 2) { // consistent with Omega or both @@ -762,7 +762,7 @@ struct CascadeCorrelations { registry.fill(HIST("hMassOmegaPlus"), casc.mOmega(), casc.pt()); weight = getEfficiency(hEffOmegaPlus, casc.pt()); } - registry.fill(HIST("hMassOmegaEffCorrected"), casc.mOmega(), casc.pt(), casc.yOmega(), collision.posZ(), collision.multFT0M(), weight); + registry.fill(HIST("hMassOmegaEffCorrected"), casc.mOmega(), casc.sign(), casc.pt(), casc.yOmega(), collision.posZ(), collision.multFT0M(), weight); registry.fill(HIST("hRapidityOmega"), casc.yOmega()); } registry.fill(HIST("hV0Radius"), casc.v0radius()); @@ -868,7 +868,6 @@ struct CascadeCorrelations { registry.fill(HIST("hMEQA"), 0.5); continue; } - registry.fill(HIST("MixedEvents/hMEVz1"), col1.posZ()); registry.fill(HIST("MixedEvents/hMEVz2"), col2.posZ()); From 53931f43f1b40d878bc1a7e1d140c260f1d93425 Mon Sep 17 00:00:00 2001 From: Marcello Di Costanzo <96481191+Marcellocosti@users.noreply.github.com> Date: Fri, 27 Jun 2025 19:42:04 +0200 Subject: [PATCH 242/871] [PWGHF] Remove hardcoded values in centrality axis for Ds task (#11781) --- PWGHF/D2H/Tasks/taskDplus.cxx | 4 ++-- PWGHF/D2H/Tasks/taskDs.cxx | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/PWGHF/D2H/Tasks/taskDplus.cxx b/PWGHF/D2H/Tasks/taskDplus.cxx index cbf6118ce68..7f851263341 100644 --- a/PWGHF/D2H/Tasks/taskDplus.cxx +++ b/PWGHF/D2H/Tasks/taskDplus.cxx @@ -82,8 +82,8 @@ struct HfTaskDplus { Partition recoBkgCandidatesWithMl = nabs(aod::hf_cand_3prong::flagMcMatchRec) != static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi) && aod::hf_sel_candidate_dplus::isSelDplusToPiKPi >= selectionFlagDplus; ConfigurableAxis thnConfigAxisY{"thnConfigAxisY", {40, -1, 1}, "Cand. rapidity bins"}; - ConfigurableAxis thnConfigAxisCent{"thnConfigAxisCent", {110, 0., 110.}, ""}; - ConfigurableAxis thnConfigAxisOccupancy{"thnConfigAxisOccupancy", {14, 0, 14000}, "axis for centrality"}; + ConfigurableAxis thnConfigAxisCent{"thnConfigAxisCent", {110, 0., 110.}, "axis for centrality"}; + ConfigurableAxis thnConfigAxisOccupancy{"thnConfigAxisOccupancy", {14, 0, 14000}, "axis for occupancy"}; ConfigurableAxis thnConfigAxisPtBHad{"thnConfigAxisPtBHad", {25, 0., 50}, "axis for pt of B hadron decayed into D candidate"}; ConfigurableAxis thnConfigAxisFlagBHad{"thnConfigAxisFlagBHad", {5, 0., 5}, "axis for PDG of B hadron"}; ConfigurableAxis thnConfigAxisMlScore0{"thnConfigAxisMlScore0", {100, 0., 1.}, "axis for ML output score 0"}; diff --git a/PWGHF/D2H/Tasks/taskDs.cxx b/PWGHF/D2H/Tasks/taskDs.cxx index 2b94c93f6b8..95ecfb6c2c9 100644 --- a/PWGHF/D2H/Tasks/taskDs.cxx +++ b/PWGHF/D2H/Tasks/taskDs.cxx @@ -138,7 +138,7 @@ struct HfTaskDs { ConfigurableAxis axisMlScore0{"axisMlScore0", {100, 0., 1.}, "axis for ML output score 0"}; ConfigurableAxis axisMlScore1{"axisMlScore1", {100, 0., 1.}, "axis for ML output score 1"}; ConfigurableAxis axisMlScore2{"axisMlScore2", {100, 0., 1.}, "axis for ML output score 2"}; - ConfigurableAxis axisCentrality{"axisCentrality", {100, 0., 1.}, "axis for centrality/multiplicity"}; + ConfigurableAxis axisCentrality{"axisCentrality", {100, 0, 100}, "axis for centrality/multiplicity"}; ConfigurableAxis axisOccupancy{"axisOccupancy", {14, 0., 14000.}, "axis for occupancy"}; int mRunNumber{0}; @@ -183,7 +183,7 @@ struct HfTaskDs { AxisSpec flagBHad{axisFlagBHad, "B Hadron flag"}; AxisSpec ybins = {100, -5., 5, "#it{y}"}; AxisSpec massbins = {600, 1.67, 2.27, "inv. mass (KK#pi) (GeV/#it{c}^{2})"}; - AxisSpec centralitybins = {100, 0., 100., "Centrality"}; + AxisSpec centralitybins = {axisCentrality, "Centrality"}; AxisSpec npvcontributorsbins = {axisNPvContributors, "NPvContributors"}; AxisSpec mlscore0bins = {axisMlScore0, "Score 0"}; AxisSpec mlscore1bins = {axisMlScore1, "Score 1"}; From 7d10012137806edda44b83294db2fac4e20a1dbb Mon Sep 17 00:00:00 2001 From: Mattia Faggin Date: Fri, 27 Jun 2025 19:45:42 +0200 Subject: [PATCH 243/871] [PWGHF] add correlated bkg to Lc tree creator. (#11807) Co-authored-by: Mattia Faggin --- PWGHF/TableProducer/treeCreatorLcToPKPi.cxx | 25 ++++++++++++--------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/PWGHF/TableProducer/treeCreatorLcToPKPi.cxx b/PWGHF/TableProducer/treeCreatorLcToPKPi.cxx index 3f53966a973..abb9b3c220b 100644 --- a/PWGHF/TableProducer/treeCreatorLcToPKPi.cxx +++ b/PWGHF/TableProducer/treeCreatorLcToPKPi.cxx @@ -17,20 +17,20 @@ /// \author Nicolo' Jacazio , CERN /// \author Luigi Dello Stritto , CERN -#include -#include -#include +#include "PWGHF/Core/HfHelper.h" +#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "PWGHF/DataModel/CandidateSelectionTables.h" + +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/Multiplicity.h" #include "CommonConstants/PhysicsConstants.h" #include "Framework/AnalysisTask.h" #include "Framework/runDataProcessing.h" -#include "Common/DataModel/Centrality.h" -#include "Common/DataModel/Multiplicity.h" - -#include "PWGHF/Core/HfHelper.h" -#include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" +#include +#include +#include using namespace o2; using namespace o2::framework; @@ -388,6 +388,7 @@ struct HfTreeCreatorLcToPKPi { Configurable applyMl{"applyMl", false, "Whether ML was used in candidateSelectorLc"}; Configurable keepOnlySignalMc{"keepOnlySignalMc", false, "Fill MC tree only with signal candidates"}; Configurable keepOnlyBkg{"keepOnlyBkg", false, "Fill MC tree only with background candidates"}; + Configurable keepCorrBkgMC{"keepCorrBkgMC", false, "Flag to keep correlated background sources (Λc+ -> p K− π+ π0, p π− π+, p K− K+ and other charm hadrons)"}; Configurable downSampleBkgFactor{"downSampleBkgFactor", 1., "Fraction of candidates to store in the tree"}; Configurable downSampleBkgPtMax{"downSampleBkgPtMax", 100.f, "Max. pt for background downsampling"}; @@ -927,9 +928,11 @@ struct HfTreeCreatorLcToPKPi { const int sigbgstatus = determineSignalBgStatus(candidate, candFlag); const bool isMcCandidateSignal = (sigbgstatus == Prompt) || (sigbgstatus == NonPrompt); const bool passSelection = functionSelection >= selectionFlagLc; - const bool keepAll = !keepOnlySignalMc && !keepOnlyBkg; + const bool keepAll = !keepOnlySignalMc && !keepOnlyBkg && !keepCorrBkgMC; + const int flag = candidate.flagMcMatchRec(); + const bool isCorrBkg = (std::abs(flag) != 0 && std::abs(flag) != o2::hf_decay::hf_cand_3prong::DecayChannelMain::LcToPKPi); const bool notSkippedBkg = isMcCandidateSignal || candidate.pt() > downSampleBkgPtMax || pseudoRndm < downSampleBkgFactor; - if (passSelection && notSkippedBkg && (keepAll || (keepOnlySignalMc && isMcCandidateSignal) || (keepOnlyBkg && !isMcCandidateSignal))) { + if (passSelection && notSkippedBkg && (keepAll || (keepOnlySignalMc && isMcCandidateSignal) || (keepOnlyBkg && !isMcCandidateSignal) || (keepCorrBkgMC && isCorrBkg))) { if (fillCandidateLiteTable) { fillLiteTable(candidate, candidateMlScore, candFlag); } else { From 3bb98736e1146706980f9c112c6e24df94e2c4d8 Mon Sep 17 00:00:00 2001 From: Daiki Sekihata Date: Fri, 27 Jun 2025 20:41:45 +0200 Subject: [PATCH 244/871] [PWGEM/Dilepton] reduce data size of tree ML DDA (#11798) --- PWGEM/Dilepton/DataModel/lmeeMLTables.h | 2 +- PWGEM/Dilepton/TableProducer/treeCreatorElectronMLDDA.cxx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/PWGEM/Dilepton/DataModel/lmeeMLTables.h b/PWGEM/Dilepton/DataModel/lmeeMLTables.h index a18978a5dda..bf90ace9b7b 100644 --- a/PWGEM/Dilepton/DataModel/lmeeMLTables.h +++ b/PWGEM/Dilepton/DataModel/lmeeMLTables.h @@ -86,7 +86,7 @@ DECLARE_SOA_DYNAMIC_COLUMN(MeanClusterSizeITSob, meanClusterSizeITSob, [](uint32 // reconstructed track information DECLARE_SOA_TABLE(EMPrimaryTracks, "AOD", "EMPTRACK", //! - o2::soa::Index<>, collision::PosZ, collision::NumContrib, evsel::NumTracksInTimeRange, evsel::SumAmpFT0CInTimeRange, + o2::soa::Index<>, collision::NumContrib, evsel::NumTracksInTimeRange, evsel::SumAmpFT0CInTimeRange, track::Pt, track::Eta, track::Phi, track::Tgl, emprimarytrack::Sign, track::DcaXY, track::DcaZ, track::CYY, track::CZZ, track::CZY, track::TPCNClsFindable, emprimarytrack::TPCNClsFound, emprimarytrack::TPCNClsCrossedRows, diff --git a/PWGEM/Dilepton/TableProducer/treeCreatorElectronMLDDA.cxx b/PWGEM/Dilepton/TableProducer/treeCreatorElectronMLDDA.cxx index 13d7e8c6b6d..cb88ec1f45a 100644 --- a/PWGEM/Dilepton/TableProducer/treeCreatorElectronMLDDA.cxx +++ b/PWGEM/Dilepton/TableProducer/treeCreatorElectronMLDDA.cxx @@ -594,7 +594,7 @@ struct TreeCreatorElectronMLDDA { float dcaXY = mDcaInfoCov.getY(); float dcaZ = mDcaInfoCov.getZ(); - emprimarytracks(collision.posZ(), collision.numContrib(), collision.trackOccupancyInTimeRange(), collision.ft0cOccupancyInTimeRange(), + emprimarytracks(collision.numContrib(), collision.trackOccupancyInTimeRange(), collision.ft0cOccupancyInTimeRange(), trackParCov.getPt(), trackParCov.getEta(), trackParCov.getPhi() > 0.f ? trackParCov.getPhi() : trackParCov.getPhi() + 2 * M_PI, trackParCov.getTgl(), track.sign(), dcaXY, dcaZ, trackParCov.getSigmaY2(), trackParCov.getSigmaZ2(), trackParCov.getSigmaZY(), track.tpcNClsFindable(), track.tpcNClsFound(), track.tpcNClsCrossedRows(), From 14c70d94b9ebf3b851fe2bfd795224327ff4604e Mon Sep 17 00:00:00 2001 From: Phil Stahlhut <138057549+pstahlhu@users.noreply.github.com> Date: Fri, 27 Jun 2025 21:56:21 +0200 Subject: [PATCH 245/871] [PWGHF] Update candidate selector in XicToXiPiPi workflow (#11816) --- PWGHF/Core/SelectorCuts.h | 43 ++- PWGHF/DataModel/CandidateSelectionTables.h | 8 + .../candidateSelectorXicToXiPiPi.cxx | 305 ++++++++++++------ 3 files changed, 241 insertions(+), 115 deletions(-) diff --git a/PWGHF/Core/SelectorCuts.h b/PWGHF/Core/SelectorCuts.h index 7fbd324f8c3..18aab0bad6f 100644 --- a/PWGHF/Core/SelectorCuts.h +++ b/PWGHF/Core/SelectorCuts.h @@ -753,8 +753,8 @@ static const std::vector labelsCutVar = {"m", "pT p", "pT K", "pT P namespace hf_cuts_xic_to_xi_pi_pi { -static constexpr int NBinsPt = 10; -static constexpr int NCutVars = 12; +static constexpr int NBinsPt = 13; +static constexpr int NCutVars = 11; // 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] = { @@ -765,23 +765,29 @@ constexpr double BinsPt[NBinsPt + 1] = { 4., 5., 6., + 7., 8., + 9., + 10., + 11., 12., - 24., - 36.}; + 20.}; auto vecBinsPt = std::vector{BinsPt, BinsPt + NBinsPt + 1}; -// default values for the cuts m ptXi ptPi0 ptPi1 chi2PCA dL dLXY cosp cospXY impParXY Xi Pi0 Pi1 -constexpr double Cuts[NBinsPt][NCutVars] = {{0.4, 0.4, 0.4, 0.4, 1e-5, 0.5, 0.5, 0.9, 0.9, 0.1, 0.1, 0.1}, /* 0 < pT < 1 */ - {0.4, 0.4, 0.4, 0.4, 1e-5, 0.5, 0.5, 0.9, 0.9, 0.1, 0.1, 0.1}, /* 1 < pT < 2 */ - {0.4, 0.4, 0.4, 0.4, 1e-5, 0.5, 0.5, 0.9, 0.9, 0.1, 0.1, 0.1}, /* 2 < pT < 3 */ - {0.4, 0.4, 0.4, 0.4, 1e-5, 0.5, 0.5, 0.9, 0.9, 0.1, 0.1, 0.1}, /* 3 < pT < 4 */ - {0.4, 0.4, 0.4, 0.4, 1e-5, 0.5, 0.5, 0.9, 0.9, 0.1, 0.1, 0.1}, /* 4 < pT < 5 */ - {0.4, 0.4, 0.4, 0.4, 1e-5, 0.5, 0.5, 0.9, 0.9, 0.1, 0.1, 0.1}, /* 5 < pT < 6 */ - {0.4, 0.4, 0.4, 0.4, 1e-5, 0.5, 0.5, 0.9, 0.9, 0.1, 0.1, 0.1}, /* 6 < pT < 8 */ - {0.4, 0.4, 0.4, 0.4, 1e-5, 0.5, 0.5, 0.9, 0.9, 0.1, 0.1, 0.1}, /* 8 < pT < 10 */ - {0.4, 0.4, 0.4, 0.4, 1e-5, 0.5, 0.5, 0.9, 0.9, 0.1, 0.1, 0.1}, /* 12 < pT < 24 */ - {0.4, 0.4, 0.4, 0.4, 1e-5, 0.5, 0.5, 0.9, 0.9, 0.1, 0.1, 0.1}}; /* 24 < pT < 36 */ +// default values for the cuts m Y Eta EtaDau ptPi0 ptPi1 chi2SV dL dLXY invMass Xi-Pi pairs +constexpr double Cuts[NBinsPt][NCutVars] = {{0.4, 0.8, 0.8, 0.8, 0.4, 0.4, 100, 0.0, 0.0, 2.4, 2.4}, /* 0 < pT < 1 */ + {0.4, 0.8, 0.8, 0.8, 0.4, 0.4, 100, 0.0, 0.0, 2.4, 2.4}, /* 1 < pT < 2 */ + {0.4, 0.8, 0.8, 0.8, 0.4, 0.4, 100, 0.0, 0.0, 2.4, 2.4}, /* 2 < pT < 3 */ + {0.4, 0.8, 0.8, 0.8, 0.4, 0.4, 100, 0.0, 0.0, 2.4, 2.4}, /* 3 < pT < 4 */ + {0.4, 0.8, 0.8, 0.8, 0.4, 0.4, 100, 0.0, 0.0, 2.4, 2.4}, /* 4 < pT < 5 */ + {0.4, 0.8, 0.8, 0.8, 0.4, 0.4, 100, 0.0, 0.0, 2.4, 2.4}, /* 5 < pT < 6 */ + {0.4, 0.8, 0.8, 0.8, 0.4, 0.4, 100, 0.0, 0.0, 2.4, 2.4}, /* 6 < pT < 7 */ + {0.4, 0.8, 0.8, 0.8, 0.4, 0.4, 100, 0.0, 0.0, 2.4, 2.4}, /* 7 < pT < 8 */ + {0.4, 0.8, 0.8, 0.8, 0.4, 0.4, 100, 0.0, 0.0, 2.4, 2.4}, /* 8 < pT < 9 */ + {0.4, 0.8, 0.8, 0.8, 0.4, 0.4, 100, 0.0, 0.0, 2.4, 2.4}, /* 9 < pT < 10 */ + {0.4, 0.8, 0.8, 0.8, 0.4, 0.4, 100, 0.0, 0.0, 2.4, 2.4}, /* 10 < pT < 11 */ + {0.4, 0.8, 0.8, 0.8, 0.4, 0.4, 100, 0.0, 0.0, 2.4, 2.4}, /* 11 < pT < 12 */ + {0.4, 0.8, 0.8, 0.8, 0.4, 0.4, 100, 0.0, 0.0, 2.4, 2.4}}; /* 12 < pT < 20 */ // row labels static const std::vector labelsPt = { @@ -794,10 +800,13 @@ static const std::vector labelsPt = { "pT bin 6", "pT bin 7", "pT bin 8", - "pT bin 9"}; + "pT bin 9", + "pT bin 10", + "pT bin 11", + "pT bin 12"}; // column labels -static const std::vector labelsCutVar = {"m", "pT Xi", "pT Pi0", "pT Pi1", "chi2PCA", "max decay length", "max decay length XY", "cos pointing angle", "cos pointing angle XY", "max impParXY Xi", "max impParXY Pi0", "max impParXY Pi1"}; +static const std::vector labelsCutVar = {"m", "y", "eta", "eta Daughters", "pT Pi0", "pT Pi1", "chi2SV", "min decay length", "min decay length XY", "max inv mass Xi-Pi0", "max inv mass Xi-Pi1"}; } // namespace hf_cuts_xic_to_xi_pi_pi namespace hf_cuts_xicc_to_p_k_pi_pi diff --git a/PWGHF/DataModel/CandidateSelectionTables.h b/PWGHF/DataModel/CandidateSelectionTables.h index 0ac6ffa1a98..150419752f1 100644 --- a/PWGHF/DataModel/CandidateSelectionTables.h +++ b/PWGHF/DataModel/CandidateSelectionTables.h @@ -317,6 +317,14 @@ DECLARE_SOA_COLUMN(MlProbXicToPiKP, mlProbXicToPiKP, std::vector); //! // XicPlus to Xi Pi Pi DECLARE_SOA_COLUMN(IsSelXicToXiPiPi, isSelXicToXiPiPi, int); //! DECLARE_SOA_COLUMN(MlProbXicToXiPiPi, mlProbXicToXiPiPi, std::vector); //! +enum XicToXiPiPiSelectionStep { + RecoTotal = 0, + RecoKinTopol, + RecoTrackQuality, + RecoPID, + RecoMl, + NSelectionSteps +}; } // namespace hf_sel_candidate_xic DECLARE_SOA_TABLE(HfSelXicToPKPi, "AOD", "HFSELXIC", //! diff --git a/PWGHF/TableProducer/candidateSelectorXicToXiPiPi.cxx b/PWGHF/TableProducer/candidateSelectorXicToXiPiPi.cxx index ae3256fcd48..fc52551630d 100644 --- a/PWGHF/TableProducer/candidateSelectorXicToXiPiPi.cxx +++ b/PWGHF/TableProducer/candidateSelectorXicToXiPiPi.cxx @@ -19,10 +19,11 @@ #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" -#include "PWGHF/Utils/utilsAnalysis.h" // findBin function +#include "PWGHF/Utils/utilsAnalysis.h" #include "Common/Core/TrackSelectorPID.h" +#include "CommonConstants/PhysicsConstants.h" #include "Framework/AnalysisTask.h" #include "Framework/runDataProcessing.h" @@ -38,16 +39,12 @@ struct HfCandidateSelectorXicToXiPiPi { Produces hfSelXicToXiPiPiCandidate; Produces hfMlXicToXiPiPiCandidate; - Configurable ptCandMin{"ptCandMin", 0., "Lower bound of candidate pT"}; - Configurable ptCandMax{"ptCandMax", 36., "Upper bound of candidate pT"}; - // topological cuts Configurable> binsPt{"binsPt", std::vector{hf_cuts_xic_to_xi_pi_pi::vecBinsPt}, "pT bin limits"}; Configurable> cuts{"cuts", {hf_cuts_xic_to_xi_pi_pi::Cuts[0], hf_cuts_xic_to_xi_pi_pi::NBinsPt, hf_cuts_xic_to_xi_pi_pi::NCutVars, hf_cuts_xic_to_xi_pi_pi::labelsPt, hf_cuts_xic_to_xi_pi_pi::labelsCutVar}, "Xicplus candidate selection per pT bin"}; - // QA switch - Configurable activateQA{"activateQA", false, "Flag to enable QA histogram"}; + Configurable fillHistogram{"fillHistogram", false, "Flag to filling of counter histogram"}; // Enable PID Configurable usePid{"usePid", true, "Switch for PID selection at track level"}; - Configurable acceptPIDNotApplicable{"acceptPIDNotApplicable", true, "Switch to accept Status::NotApplicable [(NotApplicable for one detector) and (NotApplicable or Conditional for the other)] in PID selection"}; + Configurable useTpcPidOnly{"useTpcPidOnly", false, "Switch to use TPC PID only instead of TPC OR TOF)"}; // TPC PID Configurable ptPidTpcMin{"ptPidTpcMin", 0.15, "Lower bound of track pT for TPC PID"}; Configurable ptPidTpcMax{"ptPidTpcMax", 20., "Upper bound of track pT for TPC PID"}; @@ -58,6 +55,15 @@ struct HfCandidateSelectorXicToXiPiPi { Configurable ptPidTofMax{"ptPidTofMax", 20., "Upper bound of track pT for TOF PID"}; Configurable nSigmaTofMax{"nSigmaTofMax", 5., "Nsigma cut on TOF only"}; Configurable nSigmaTofCombinedMax{"nSigmaTofCombinedMax", 5., "Nsigma cut on TOF combined with TPC"}; + // TrackQualitySelection + Configurable doTrackQualitySelection{"doTrackQualitySelection", true, "Switch to apply track quality selections on final state daughter particles"}; + Configurable nClustersTpcMin{"nClustersTpcMin", 70, "Minimum number of TPC clusters requirement"}; + Configurable nTpcCrossedRowsMin{"nTpcCrossedRowsMin", 70, "Minimum number of TPC crossed rows requirement"}; + Configurable tpcCrossedRowsOverFindableClustersRatioMin{"tpcCrossedRowsOverFindableClustersRatioMin", 0.8, "Minimum ratio TPC crossed rows over findable clusters requirement"}; + Configurable tpcChi2PerClusterMax{"tpcChi2PerClusterMax", 4, "Maximum value of chi2 fit over TPC clusters"}; + Configurable nClustersItsMin{"nClustersItsMin", 3, "Minimum number of ITS clusters requirement for pi <- charm baryon"}; + Configurable nClustersItsInnBarrMin{"nClustersItsInnBarrMin", 1, "Minimum number of ITS clusters in inner barrel requirement for pi <- charm baryon"}; + Configurable itsChi2PerClusterMax{"itsChi2PerClusterMax", 36, "Maximum value of chi2 fit over ITS clusters for pi <- charm baryon"}; // ML inference Configurable applyMl{"applyMl", false, "Flag to apply ML selections"}; Configurable> binsPtMl{"binsPtMl", std::vector{hf_cuts_ml::vecBinsPt}, "pT bin limits for ML application"}; @@ -77,8 +83,23 @@ struct HfCandidateSelectorXicToXiPiPi { o2::ccdb::CcdbApi ccdbApi; TrackSelectorPi selectorPion; TrackSelectorPr selectorProton; - - using TracksPidWithSel = soa::Join; + enum XicSelCriteria { All = 0, + Pt, + Mass, + Rapidity, + Eta, + EtaDaughters, + PtPionFromXicPlus, + Chi2SV, + MinDecayLength, + MaxInvMassXiPiPairs, + TpcTrackQualityXiDaughters, + TpcTrackQualityPiFromCharm, + ItsTrackQualityPiFromCharm, + PidSelected, + BdtSelected }; + + using TracksExtraWPid = soa::Join; HistogramRegistry registry{"registry"}; @@ -101,19 +122,23 @@ struct HfCandidateSelectorXicToXiPiPi { selectorProton.setRangeNSigmaTofCondTpc(-nSigmaTofCombinedMax, nSigmaTofCombinedMax); } - if (activateQA) { - constexpr int kNBinsSelections = 1 + SelectionStep::NSelectionSteps; - std::string labels[kNBinsSelections]; - labels[0] = "No selection"; - labels[1 + SelectionStep::RecoSkims] = "Skims selection"; - labels[1 + SelectionStep::RecoTopol] = "Skims & Topological selections"; - labels[1 + SelectionStep::RecoPID] = "Skims & Topological & PID selections"; - labels[1 + SelectionStep::RecoMl] = "Skims & Topological & PID & ML selections"; - static const AxisSpec axisSelections = {kNBinsSelections, 0.5, kNBinsSelections + 0.5, ""}; - registry.add("hSelections", "Selections;;#it{p}_{T} (GeV/#it{c})", {HistType::kTH2F, {axisSelections, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); - for (int iBin = 0; iBin < kNBinsSelections; ++iBin) { - registry.get(HIST("hSelections"))->GetXaxis()->SetBinLabel(iBin + 1, labels[iBin].data()); - } + if (fillHistogram) { + registry.add("hSelCandidates", ";;entries", {HistType::kTH1F, {{15, -0.5, 14.5}}}); + registry.get(HIST("hSelCandidates"))->GetXaxis()->SetBinLabel(1 + All, "All"); + registry.get(HIST("hSelCandidates"))->GetXaxis()->SetBinLabel(1 + Pt, "#it{p}_{T}"); + registry.get(HIST("hSelCandidates"))->GetXaxis()->SetBinLabel(1 + Mass, "#Delta M"); + registry.get(HIST("hSelCandidates"))->GetXaxis()->SetBinLabel(1 + Rapidity, "y"); + registry.get(HIST("hSelCandidates"))->GetXaxis()->SetBinLabel(1 + Eta, "#eta"); + registry.get(HIST("hSelCandidates"))->GetXaxis()->SetBinLabel(1 + EtaDaughters, "#eta final state daughters"); + registry.get(HIST("hSelCandidates"))->GetXaxis()->SetBinLabel(1 + PtPionFromXicPlus, "#it{p}_{T} (#pi #leftarrow #Xi_{c}^{+})"); + registry.get(HIST("hSelCandidates"))->GetXaxis()->SetBinLabel(1 + Chi2SV, "#chi^{2}_{SV}"); + registry.get(HIST("hSelCandidates"))->GetXaxis()->SetBinLabel(1 + MinDecayLength, "Decay length"); + registry.get(HIST("hSelCandidates"))->GetXaxis()->SetBinLabel(1 + MaxInvMassXiPiPairs, "M_{#Xi #pi}"); + registry.get(HIST("hSelCandidates"))->GetXaxis()->SetBinLabel(1 + TpcTrackQualityXiDaughters, "TPC track quality selection on #Xi daughters"); + registry.get(HIST("hSelCandidates"))->GetXaxis()->SetBinLabel(1 + TpcTrackQualityPiFromCharm, "TPC track quality selection on #pi #leftarrow #Xi_{c}^{+}"); + registry.get(HIST("hSelCandidates"))->GetXaxis()->SetBinLabel(1 + ItsTrackQualityPiFromCharm, "ITS track quality selection on #pi #leftarrow #Xi_{c}^{+}"); + registry.get(HIST("hSelCandidates"))->GetXaxis()->SetBinLabel(1 + PidSelected, "PID selection"); + registry.get(HIST("hSelCandidates"))->GetXaxis()->SetBinLabel(1 + BdtSelected, "BDT selection"); } if (applyMl) { @@ -133,130 +158,200 @@ struct HfCandidateSelectorXicToXiPiPi { /// \param candidate is candidate /// \return true if candidate passes all cuts template - bool selectionTopol(const T1& hfCandXic) + bool isSelectedXic(const T1& hfCandXic, + const float& etaPi0, + const float& etaPi1, + const float& etaPiFromXi, + const float& etaV0PosDau, + const float& etaV0NegDau) { auto candpT = hfCandXic.pt(); int pTBin = findBin(binsPt, candpT); if (pTBin == -1) { return false; } - - // check that the candidate pT is within the analysis range - if (candpT < ptCandMin || candpT >= ptCandMax) { - return false; + if (fillHistogram) { + registry.fill(HIST("hSelCandidates"), Pt); } - // check candidate mass is within a defined mass window + // check whether candidate mass is within a defined mass window if (std::abs(hfCandXic.invMassXicPlus() - o2::constants::physics::MassXiCPlus) > cuts->get(pTBin, "m")) { return false; } + if (fillHistogram) { + registry.fill(HIST("hSelCandidates"), Mass); + } - // cosine of pointing angle - if (hfCandXic.cpa() <= cuts->get(pTBin, "cos pointing angle")) { + // cut on candidate rapidity + if (std::abs(hfCandXic.y(o2::constants::physics::MassXiCPlus)) > cuts->get(pTBin, "y")) { return false; } + if (fillHistogram) { + registry.fill(HIST("hSelCandidates"), Rapidity); + } - // cosine of pointing angle XY - if (hfCandXic.cpaXY() <= cuts->get(pTBin, "cos pointing angle XY")) { + // cut on candidate pseudorapidity + if (std::abs(hfCandXic.eta()) > cuts->get(pTBin, "eta")) { return false; } + if (fillHistogram) { + registry.fill(HIST("hSelCandidates"), Eta); + } - // candidate maximum decay length - if (hfCandXic.decayLength() > cuts->get(pTBin, "max decay length")) { + // cut on pseudorapidity of final state daughters + if (std::abs(etaPi0) > cuts->get(pTBin, "eta Daughters") || std::abs(etaPi1) > cuts->get(pTBin, "eta Daughters") || std::abs(etaPiFromXi) > cuts->get(pTBin, "eta Daughters") || std::abs(etaV0PosDau) > cuts->get(pTBin, "eta Daughters") || std::abs(etaV0NegDau) > cuts->get(pTBin, "eta Daughters")) { return false; } + if (fillHistogram) { + registry.fill(HIST("hSelCandidates"), EtaDaughters); + } - // candidate maximum decay length XY - if (hfCandXic.decayLengthXY() > cuts->get(pTBin, "max decay length XY")) { + // cut on pion pT + if (hfCandXic.ptProng1() < cuts->get(pTBin, "pT Pi0") || hfCandXic.ptProng2() < cuts->get(pTBin, "pT Pi1")) { return false; } + if (fillHistogram) { + registry.fill(HIST("hSelCandidates"), PtPionFromXicPlus); + } - // candidate chi2PC - if (hfCandXic.chi2PCA() > cuts->get(pTBin, "chi2PCA")) { + // cut on chi2 of secondary vertex + if (hfCandXic.chi2PCA() > cuts->get(pTBin, "chi2SV")) { return false; } + if (fillHistogram) { + registry.fill(HIST("hSelCandidates"), Chi2SV); + } - // maximum DCA of daughters - if ((std::abs(hfCandXic.impactParameter0()) > cuts->get(pTBin, "max impParXY Xi")) || - (std::abs(hfCandXic.impactParameter1()) > cuts->get(pTBin, "max impParXY Pi0")) || - (std::abs(hfCandXic.impactParameter2()) > cuts->get(pTBin, "max impParXY Pi1"))) { + // cut on candidate decay length + if (hfCandXic.decayLength() < cuts->get(pTBin, "min decay length") || hfCandXic.decayLengthXY() < cuts->get(pTBin, "min decay length XY")) { return false; } + if (fillHistogram) { + registry.fill(HIST("hSelCandidates"), MinDecayLength); + } - // cut on daughter pT - if (hfCandXic.ptProng0() < cuts->get(pTBin, "pT Xi") || - hfCandXic.ptProng1() < cuts->get(pTBin, "pT Pi0") || - hfCandXic.ptProng2() < cuts->get(pTBin, "pT Pi1")) { + // cut on invariant mass of Xi-pion pairs + if (hfCandXic.invMassXiPi0() > cuts->get(pTBin, "max inv mass Xi-Pi0") || hfCandXic.invMassXiPi1() > cuts->get(pTBin, "max inv mass Xi-Pi1")) { return false; } + if (fillHistogram) { + registry.fill(HIST("hSelCandidates"), MaxInvMassXiPiPairs); + } return true; } /// Apply PID selection - /// \param pidTrackPi0 PID status of trackPi0 (prong1 of Xic candidate) - /// \param pidTrackPi1 PID status of trackPi1 (prong2 of Xic candidate) - /// \param pidTrackPr PID status of trackPr (positive daughter of V0 candidate) - /// \param pidTrackPiLam PID status of trackPiLam (negative daughter of V0 candidate) - /// \param pidTrackPiXi PID status of trackPiXi (Bachelor of cascade candidate) - /// \param acceptPIDNotApplicable switch to accept Status::NotApplicable + /// \param statusPidPi0 PID status of trackPi0 (prong1 of Xic candidate) + /// \param statusPidPi1 PID status of trackPi1 (prong2 of Xic candidate) + /// \param statusPidPiXi PID status of trackPiXi (Bachelor of cascade candidate) + /// \param statusPidPrLam PID status of trackPr (positive daughter of V0 candidate) + /// \param statusPidPiLam PID status of trackPiLam (negative daughter of V0 candidate) + /// \param usePidTpcOnly switch to check only TPC status /// \return true if prongs of Xic candidate pass all selections - bool selectionPid(TrackSelectorPID::Status const pidTrackPi0, - TrackSelectorPID::Status const pidTrackPi1, - TrackSelectorPID::Status const pidTrackPr, - TrackSelectorPID::Status const pidTrackPiLam, - TrackSelectorPID::Status const pidTrackPiXi, - bool const acceptPIDNotApplicable) + bool selectionPid(TrackSelectorPID::Status const statusPidPi0, + TrackSelectorPID::Status const statusPidPi1, + TrackSelectorPID::Status const statusPidPiXi, + TrackSelectorPID::Status const statusPidPrLam, + TrackSelectorPID::Status const statusPidPiLam, + bool const useTpcPidOnly) { - if (!acceptPIDNotApplicable && (pidTrackPi0 != TrackSelectorPID::Accepted || pidTrackPi1 != TrackSelectorPID::Accepted || pidTrackPr != TrackSelectorPID::Accepted || pidTrackPiLam != TrackSelectorPID::Accepted || pidTrackPiXi != TrackSelectorPID::Accepted)) { - return false; + if (useTpcPidOnly) { + if ((statusPidPi0 != TrackSelectorPID::Accepted && statusPidPi0 != TrackSelectorPID::NotApplicable) || (statusPidPi1 != TrackSelectorPID::Accepted && statusPidPi1 != TrackSelectorPID::NotApplicable) || (statusPidPiXi != TrackSelectorPID::Accepted && statusPidPiXi != TrackSelectorPID::NotApplicable) || (statusPidPrLam != TrackSelectorPID::Accepted && statusPidPrLam != TrackSelectorPID::NotApplicable) || (statusPidPiLam != TrackSelectorPID::Accepted && statusPidPiLam != TrackSelectorPID::NotApplicable)) { + return false; + } + return true; } - if (acceptPIDNotApplicable && (pidTrackPi0 == TrackSelectorPID::Rejected || pidTrackPi1 == TrackSelectorPID::Rejected || pidTrackPr == TrackSelectorPID::Rejected || pidTrackPiLam == TrackSelectorPID::Rejected || pidTrackPiXi == TrackSelectorPID::Rejected)) { + if (statusPidPi0 == TrackSelectorPID::Rejected || statusPidPi1 == TrackSelectorPID::Rejected || statusPidPiXi == TrackSelectorPID::Rejected || statusPidPrLam == TrackSelectorPID::Rejected || statusPidPiLam == TrackSelectorPID::Rejected) { return false; } return true; } void process(aod::HfCandXic const& hfCandsXic, - TracksPidWithSel const&) + TracksExtraWPid const&) { for (const auto& hfCandXic : hfCandsXic) { int statusXicToXiPiPi = 0; - - outputMlXicToXiPiPi.clear(); - - auto ptCandXic = hfCandXic.pt(); - - if (activateQA) { - registry.fill(HIST("hSelections"), 1, ptCandXic); + if (applyMl) { + outputMlXicToXiPiPi.clear(); } - // No hfflag -> by default skim selected - SETBIT(statusXicToXiPiPi, SelectionStep::RecoSkims); // RecoSkims = 0 --> statusXicToXiPiPi = 1 - if (activateQA) { - registry.fill(HIST("hSelections"), 2 + SelectionStep::RecoSkims, ptCandXic); - } + float ptCandXic = hfCandXic.pt(); + auto trackPi0 = hfCandXic.pi0_as(); + auto trackPi1 = hfCandXic.pi1_as(); + auto trackPiFromXi = hfCandXic.bachelor_as(); + auto trackV0PosDau = hfCandXic.posTrack_as(); + auto trackV0NegDau = hfCandXic.negTrack_as(); + + // Succesful reconstruction + SETBIT(statusXicToXiPiPi, hf_sel_candidate_xic::XicToXiPiPiSelectionStep::RecoTotal); // RecoTotal = 0 --> statusXicToXiPiPi += 1 - // topological cuts - if (!selectionTopol(hfCandXic)) { + // kinematic and topological selection + if (!isSelectedXic(hfCandXic, trackPi0.eta(), trackPi1.eta(), trackPiFromXi.eta(), trackV0PosDau.eta(), trackV0NegDau.eta())) { hfSelXicToXiPiPiCandidate(statusXicToXiPiPi); if (applyMl) { hfMlXicToXiPiPiCandidate(outputMlXicToXiPiPi); } continue; } - SETBIT(statusXicToXiPiPi, SelectionStep::RecoTopol); // RecoTopol = 1 --> statusXicToXiPiPi = 3 - if (activateQA) { - registry.fill(HIST("hSelections"), 2 + SelectionStep::RecoTopol, ptCandXic); + SETBIT(statusXicToXiPiPi, hf_sel_candidate_xic::XicToXiPiPiSelectionStep::RecoKinTopol); // RecoKinTopol = 1 --> statusXicToXiPiPi += 2 + + // track quality selection + if (doTrackQualitySelection) { + if (!isSelectedTrackTpcQuality(trackPiFromXi, nClustersTpcMin, nTpcCrossedRowsMin, tpcCrossedRowsOverFindableClustersRatioMin, tpcChi2PerClusterMax) || + !isSelectedTrackTpcQuality(trackV0PosDau, nClustersTpcMin, nTpcCrossedRowsMin, tpcCrossedRowsOverFindableClustersRatioMin, tpcChi2PerClusterMax) || + !isSelectedTrackTpcQuality(trackV0NegDau, nClustersTpcMin, nTpcCrossedRowsMin, tpcCrossedRowsOverFindableClustersRatioMin, tpcChi2PerClusterMax)) { + hfSelXicToXiPiPiCandidate(statusXicToXiPiPi); + if (applyMl) { + hfMlXicToXiPiPiCandidate(outputMlXicToXiPiPi); + } + continue; + } + if (fillHistogram) { + registry.fill(HIST("hSelCandidates"), TpcTrackQualityXiDaughters); + } + + if (!isSelectedTrackTpcQuality(trackPi0, nClustersTpcMin, nTpcCrossedRowsMin, tpcCrossedRowsOverFindableClustersRatioMin, tpcChi2PerClusterMax) || + !isSelectedTrackTpcQuality(trackPi1, nClustersTpcMin, nTpcCrossedRowsMin, tpcCrossedRowsOverFindableClustersRatioMin, tpcChi2PerClusterMax)) { + hfSelXicToXiPiPiCandidate(statusXicToXiPiPi); + if (applyMl) { + hfMlXicToXiPiPiCandidate(outputMlXicToXiPiPi); + } + continue; + } + if (fillHistogram) { + registry.fill(HIST("hSelCandidates"), TpcTrackQualityPiFromCharm); + } + + if ((!isSelectedTrackItsQuality(trackPi0, nClustersItsMin, itsChi2PerClusterMax) || trackPi0.itsNClsInnerBarrel() < nClustersItsInnBarrMin) || + (!isSelectedTrackItsQuality(trackPi0, nClustersItsMin, itsChi2PerClusterMax) || trackPi1.itsNClsInnerBarrel() < nClustersItsInnBarrMin)) { + hfSelXicToXiPiPiCandidate(statusXicToXiPiPi); + if (applyMl) { + hfMlXicToXiPiPiCandidate(outputMlXicToXiPiPi); + } + continue; + } + if (fillHistogram) { + registry.fill(HIST("hSelCandidates"), ItsTrackQualityPiFromCharm); + } + + SETBIT(statusXicToXiPiPi, hf_sel_candidate_xic::XicToXiPiPiSelectionStep::RecoTrackQuality); // RecoTrackQuality = 2 --> statusXicToXiPiPi += 4 + } + if (!doTrackQualitySelection && fillHistogram) { + registry.fill(HIST("hSelCandidates"), TpcTrackQualityXiDaughters); + registry.fill(HIST("hSelCandidates"), TpcTrackQualityPiFromCharm); + registry.fill(HIST("hSelCandidates"), ItsTrackQualityPiFromCharm); } // track-level PID selection if (usePid) { - auto trackPi0 = hfCandXic.pi0_as(); - auto trackPi1 = hfCandXic.pi1_as(); - auto trackV0PosDau = hfCandXic.posTrack_as(); - auto trackV0NegDau = hfCandXic.negTrack_as(); - auto trackPiFromXi = hfCandXic.bachelor_as(); + TrackSelectorPID::Status statusPidPi0 = TrackSelectorPID::NotApplicable; + TrackSelectorPID::Status statusPidPi1 = TrackSelectorPID::NotApplicable; + TrackSelectorPID::Status statusPidPiXi = TrackSelectorPID::NotApplicable; + TrackSelectorPID::Status statusPidPrLam = TrackSelectorPID::NotApplicable; + TrackSelectorPID::Status statusPidPiLam = TrackSelectorPID::NotApplicable; + // assign proton and pion hypothesis to V0 daughters auto trackPr = trackV0PosDau; auto trackPiFromLam = trackV0NegDau; @@ -264,25 +359,36 @@ struct HfCandidateSelectorXicToXiPiPi { trackPr = trackV0NegDau; trackPiFromLam = trackV0PosDau; } - // PID info - TrackSelectorPID::Status pidTrackPi0 = selectorPion.statusTpcAndTof(trackPi0); - TrackSelectorPID::Status pidTrackPi1 = selectorPion.statusTpcAndTof(trackPi1); - TrackSelectorPID::Status pidTrackPr = selectorProton.statusTpcAndTof(trackPr); - TrackSelectorPID::Status pidTrackPiLam = selectorPion.statusTpcAndTof(trackPiFromLam); - TrackSelectorPID::Status pidTrackPiXi = selectorPion.statusTpcAndTof(trackPiFromXi); - - if (!selectionPid(pidTrackPi0, pidTrackPi1, pidTrackPr, pidTrackPiLam, pidTrackPiXi, acceptPIDNotApplicable.value)) { + + if (useTpcPidOnly) { + statusPidPi0 = selectorPion.statusTpc(trackPi0); + statusPidPi1 = selectorPion.statusTpc(trackPi1); + statusPidPiXi = selectorPion.statusTpc(trackPiFromXi); + statusPidPrLam = selectorProton.statusTpc(trackPr); + statusPidPiLam = selectorPion.statusTpc(trackPiFromLam); + } else { + statusPidPi0 = selectorPion.statusTpcOrTof(trackPi0); + statusPidPi1 = selectorPion.statusTpcOrTof(trackPi1); + statusPidPiXi = selectorPion.statusTpcOrTof(trackPiFromXi); + statusPidPrLam = selectorProton.statusTpcOrTof(trackPr); + statusPidPiLam = selectorPion.statusTpcOrTof(trackPiFromLam); + } + + if (!selectionPid(statusPidPi0, statusPidPi1, statusPidPiXi, statusPidPrLam, statusPidPiLam, useTpcPidOnly.value)) { hfSelXicToXiPiPiCandidate(statusXicToXiPiPi); if (applyMl) { hfMlXicToXiPiPiCandidate(outputMlXicToXiPiPi); } continue; } - SETBIT(statusXicToXiPiPi, SelectionStep::RecoPID); // RecoPID = 2 --> statusXicToXiPiPi = 7 - if (activateQA) { - registry.fill(HIST("hSelections"), 2 + SelectionStep::RecoPID, ptCandXic); + SETBIT(statusXicToXiPiPi, hf_sel_candidate_xic::XicToXiPiPiSelectionStep::RecoPID); // RecoPID = 3 --> statusXicToXiPiPi += 8 + if (fillHistogram) { + registry.fill(HIST("hSelCandidates"), PidSelected); } } + if (!usePid && fillHistogram) { + registry.fill(HIST("hSelCandidates"), PidSelected); + } // ML selection if (applyMl) { @@ -297,11 +403,14 @@ struct HfCandidateSelectorXicToXiPiPi { hfSelXicToXiPiPiCandidate(statusXicToXiPiPi); continue; } - SETBIT(statusXicToXiPiPi, aod::SelectionStep::RecoMl); - if (activateQA) { - registry.fill(HIST("hSelections"), 2 + SelectionStep::RecoMl, ptCandXic); + SETBIT(statusXicToXiPiPi, hf_sel_candidate_xic::XicToXiPiPiSelectionStep::RecoMl); // RecoPID = 4 --> statusXicToXiPiPi += 16 + if (fillHistogram) { + registry.fill(HIST("hSelCandidates"), BdtSelected); } } + if (!applyMl && fillHistogram) { + registry.fill(HIST("hSelCandidates"), BdtSelected); + } hfSelXicToXiPiPiCandidate(statusXicToXiPiPi); } From fd579277928573102a62dcfcfedc8e5ef2e7b0f0 Mon Sep 17 00:00:00 2001 From: Fabrizio Chinu <91954233+fchinu@users.noreply.github.com> Date: Fri, 27 Jun 2025 22:21:53 +0200 Subject: [PATCH 246/871] [PWGHF] Make mass axis configurable in candidateCreator2Prong (#11799) --- PWGHF/TableProducer/candidateCreator2Prong.cxx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/PWGHF/TableProducer/candidateCreator2Prong.cxx b/PWGHF/TableProducer/candidateCreator2Prong.cxx index 851fa76c33d..afaffc09700 100644 --- a/PWGHF/TableProducer/candidateCreator2Prong.cxx +++ b/PWGHF/TableProducer/candidateCreator2Prong.cxx @@ -108,6 +108,9 @@ struct HfCandidateCreator2Prong { double bz{0.}; std::shared_ptr hCandidates; + + ConfigurableAxis axisMass{"axisMass", {500, 1.6, 2.1}, "axis for mass (GeV/c^2)"}; + HistogramRegistry registry{"registry"}; void init(InitContext const&) @@ -148,7 +151,7 @@ struct HfCandidateCreator2Prong { } // histograms - registry.add("hMass2", "2-prong candidates;inv. mass (#pi K) (GeV/#it{c}^{2});entries", {HistType::kTH1F, {{500, 1.6, 2.1}}}); + registry.add("hMass2", "2-prong candidates;inv. mass (#pi K) (GeV/#it{c}^{2});entries", {HistType::kTH1F, {axisMass}}); registry.add("hCovPVXX", "2-prong candidates;XX element of cov. matrix of prim. vtx. position (cm^{2});entries", {HistType::kTH1F, {{100, 0., 1.e-4}}}); registry.add("hCovSVXX", "2-prong candidates;XX element of cov. matrix of sec. vtx. position (cm^{2});entries", {HistType::kTH1F, {{100, 0., 0.2}}}); registry.add("hCovPVYY", "2-prong candidates;YY element of cov. matrix of prim. vtx. position (cm^{2});entries", {HistType::kTH1F, {{100, 0., 1.e-4}}}); From e861d505531783ac57c22cee74e9dfd73866eaf5 Mon Sep 17 00:00:00 2001 From: Gyula Bencedi Date: Sat, 28 Jun 2025 00:22:52 +0200 Subject: [PATCH 247/871] [PWGLF] Add task spectra pi/k/p vs flattenicity (#11787) --- .../GlobalEventProperties/CMakeLists.txt | 5 + .../GlobalEventProperties/flattenictyPikp.cxx | 1939 +++++++++++++++++ 2 files changed, 1944 insertions(+) create mode 100644 PWGLF/Tasks/GlobalEventProperties/flattenictyPikp.cxx diff --git a/PWGLF/Tasks/GlobalEventProperties/CMakeLists.txt b/PWGLF/Tasks/GlobalEventProperties/CMakeLists.txt index ed61c203672..258a43a91d0 100644 --- a/PWGLF/Tasks/GlobalEventProperties/CMakeLists.txt +++ b/PWGLF/Tasks/GlobalEventProperties/CMakeLists.txt @@ -23,3 +23,8 @@ o2physics_add_dpl_workflow(dndeta-mft-pp SOURCES dndeta-mft-pp.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(flattenicty-pikp + SOURCES flattenictyPikp.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::AnalysisCCDB + COMPONENT_NAME Analysis) diff --git a/PWGLF/Tasks/GlobalEventProperties/flattenictyPikp.cxx b/PWGLF/Tasks/GlobalEventProperties/flattenictyPikp.cxx new file mode 100644 index 00000000000..df99f8b7a6f --- /dev/null +++ b/PWGLF/Tasks/GlobalEventProperties/flattenictyPikp.cxx @@ -0,0 +1,1939 @@ +// Copyright 2020-2022 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 flattenictyPikp.cxx +/// \author Gyula Bencedi, gyula.bencedi@cern.ch +/// \brief Task to produce pion, kaon, proton high-pT +/// distributions as a function of charged-particle flattenicity +/// \since 26 June 2025 + +#include "PWGLF/DataModel/LFParticleIdentification.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" +#include "PWGLF/DataModel/mcCentrality.h" +#include "PWGLF/Utils/inelGt.h" + +#include "Common/Core/TrackSelection.h" +#include "Common/Core/TrackSelectionDefaults.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/FT0Corrected.h" +#include "Common/DataModel/McCollisionExtra.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include "CommonConstants/MathConstants.h" +#include "DataFormatsFIT/Triggers.h" +#include "DetectorsCommonDataFormats/AlignParam.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/Configurable.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/O2DatabasePDGPlugin.h" +#include "Framework/StaticFor.h" +#include "Framework/runDataProcessing.h" +#include "ReconstructionDataFormats/PID.h" +#include "ReconstructionDataFormats/Track.h" +#include +#include +#include + +#include "TEfficiency.h" +#include "THashList.h" +#include "TPDGCode.h" +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace o2; +using namespace o2::framework; +using namespace o2::constants::math; + +auto static constexpr kMinCharge = 3.f; +// FV0 specific constants +static constexpr int kMaxRingsFV0 = 5; +static constexpr int kNCellsFV0 = 48; +static constexpr int kInnerFV0 = 32; +static constexpr float kFV0IndexPhi[5] = {0., 8., 16., 24., 32.}; +static constexpr float kEtaMaxFV0 = 5.1; +static constexpr float kEtaMinFV0 = 2.2; +static constexpr float kDEtaFV0 = (kEtaMaxFV0 - kEtaMinFV0) / kMaxRingsFV0; +// PID names +static constexpr int kProcessIdWeak = 4; +static constexpr int Ncharges = 2; +static constexpr o2::track::PID::ID Npart = 5; +static constexpr o2::track::PID::ID NpartChrg = Npart * Ncharges; +static constexpr int PDGs[] = {11, 13, 211, 321, 2212}; +static constexpr int PidSgn[NpartChrg] = {11, 13, 211, 321, 2212, -11, -13, -211, -321, -2212}; +static constexpr const char* Pid[Npart] = {"el", "mu", "pi", "ka", "pr"}; +static constexpr const char* PidChrg[NpartChrg] = {"e^{-}", "#mu^{-}", "#pi^{+}", "K^{+}", "p", "e^{+}", "#mu^{+}", "#pi^{-}", "K^{-}", "#bar{p}"}; +static constexpr std::string_view kSpecies[NpartChrg] = {"Elminus", "Muplus", "PiPlus", "KaPlus", "Pr", "ElPlus", "MuMinus", "PiMinus", "KaMinus", "PrBar"}; +static constexpr std::string_view kSpeciesAll[Npart] = {"El", "Mu", "Pi", "Ka", "Pr"}; +// histogram naming +static constexpr std::string_view kCharge[] = {"all/", "pos/", "neg/"}; +static constexpr std::string_view kPrefix = "Tracks/"; +static constexpr std::string_view kQA = "QA/"; +static constexpr std::string_view kPrefixCleanTof = "Tracks/CleanTof/"; +static constexpr std::string_view kPrefixCleanV0 = "Tracks/CleanV0/"; +static constexpr std::string_view kStatus[] = {"preSel/", "postSel/"}; +static constexpr std::string_view kStatCalib[] = {"preCalib/", "postCalib/"}; +static constexpr std::string_view kPtGenPrimSgn = "/hPtGenPrimSgn"; +static constexpr std::string_view kPtGenPrimSgnF = "Tracks/{}/hPtGenPrimSgn"; +static constexpr std::string_view kPtGenPrimSgnINEL = "/hPtGenPrimSgnINEL"; +static constexpr std::string_view kPtGenPrimSgnINELF = "Tracks/{}/hPtGenPrimSgnINEL"; +static constexpr std::string_view kPtRecCollPrimSgn = "/hPtRecCollPrimSgn"; +static constexpr std::string_view kPtRecCollPrimSgnF = "Tracks/{}/hPtRecCollPrimSgn"; +static constexpr std::string_view kPtRecCollPrimSgnINEL = "/hPtRecCollPrimSgnINEL"; +static constexpr std::string_view kPtRecCollPrimSgnINELF = "Tracks/{}/hPtRecCollPrimSgnINEL"; +static constexpr std::string_view kPtGenRecCollPrimSgn = "/hPtGenRecCollPrimSgn"; +static constexpr std::string_view kPtGenRecCollPrimSgnF = "Tracks/{}/hPtGenRecCollPrimSgn"; +static constexpr std::string_view kPtGenRecCollPrimSgnINEL = "/hPtGenRecCollPrimSgnINEL"; +static constexpr std::string_view kPtGenRecCollPrimSgnINELF = "Tracks/{}/hPtGenRecCollPrimSgnINEL"; +static constexpr std::string_view kPtMCclosurePrim = "/hPtMCclosurePrim"; +static constexpr std::string_view kPtMCclosurePrimF = "Tracks/{}/hPtMCclosurePrim"; + +enum V0sSel { + kNaN = -1, + kGa = 0, + kKz = 1, + kLam = 2, + kaLam = 3 +}; + +enum TrkSelNoFilt { + trkSelEta, + trkSelPt, + trkSelDCA, + trkSelNCls, + trkSelTPCBndr, + nTrkSel +}; + +enum EvtSel { + evtSelAll, + evtSelSel8, + evtSelNoITSROFrameBorder, + evtSelkNoTimeFrameBorder, + evtSelkNoSameBunchPileup, + evtSelkIsGoodZvtxFT0vsPV, + evtSelkIsVertexITSTPC, + evtSelkIsVertexTOFmatched, + evtSelVtxZ, + evtSelINELgt0, + nEvtSel +}; + +enum FillType { + kBefore, + kAfter +}; + +enum ChargeType { + kAll, + kPos, + kNeg +}; + +struct MultE { + static constexpr int kNoMult = 0; + static constexpr int kMultFT0M = 1; + static constexpr int kMultTPC = 2; +}; + +std::array rhoLatticeFV0{0}; +std::array fv0AmplitudeWoCalib{0}; + +std::array, NpartChrg> hPtEffRecPrim{}; +std::array, NpartChrg> hPtEffRecWeak{}; +std::array, NpartChrg> hPtEffRecMat{}; +std::array, NpartChrg> hPtEffRec{}; +std::array, NpartChrg> hPtEffGen{}; +std::array, NpartChrg> hPtGenRecEvt{}; +std::array, NpartChrg> hPtGenPrimRecEvt{}; +std::array, NpartChrg> hPtEffGenPrim{}; +std::array, NpartChrg> hPtEffGenWeak{}; +std::array, NpartChrg> hPtEffGenMat{}; +std::array, NpartChrg> hPtVsDCAxyPrim{}; +std::array, NpartChrg> hPtVsDCAxyWeak{}; +std::array, NpartChrg> hPtVsDCAxyMat{}; +std::array, NpartChrg> hDCAxyBadCollPrim{}; +std::array, NpartChrg> hDCAxyBadCollWeak{}; +std::array, NpartChrg> hDCAxyBadCollMat{}; +std::array, NpartChrg> hPtNsigmaTPC{}; +std::array, NpartChrg> hThPtNsigmaTPC{}; +std::array, NpartChrg> hPtNsigmaTOF{}; +std::array, NpartChrg> hPtNsigmaTPCTOF{}; + +struct FlattenictyPikp { + + HistogramRegistry flatchrg{"flatchrg", {}, OutputObjHandlingPolicy::AnalysisObject, true, false}; + OutputObj listEfficiency{"Efficiency"}; + Service pdg; + + std::vector fv0AmplCorr{}; + TProfile2D* zVtxMap = nullptr; + int runNumber{-1}; + + Configurable multEst{"multEst", 1, "0: without multiplicity; 1: MultFT0M; 2: MultTPC"}; + Configurable applyCalibGain{"applyCalibGain", true, "equalize detector amplitudes"}; + Configurable applyCalibVtx{"applyCalibVtx", false, "equalize Amp vs vtx"}; + Configurable applyCalibDeDx{"applyCalibDeDx", true, "calibration of dedx signal"}; + Configurable cfgFillQAHisto{"cfgFillQAHisto", true, "fill QA histograms"}; + Configurable cfgFillChrgType{"cfgFillChrgType", true, "fill histograms per charge types"}; + Configurable> paramsFuncMIPposEta{"paramsFuncMIPposEta", std::vector{-1.f}, "parameters of pol2"}; + Configurable> paramsFuncMIPnegEta{"paramsFuncMIPnegEta", std::vector{-1.f}, "parameters of pol2"}; + Configurable> paramsFuncPlateuPosEta{"paramsFuncPlateuPosEta", std::vector{-1.f}, "parameters of pol2"}; + Configurable> paramsFuncPlateuNegEta{"paramsFuncPlateuNegEta", std::vector{-1.f}, "parameters of pol2"}; + Configurable cfgGainEqCcdbPath{"cfgGainEqCcdbPath", "Users/g/gbencedi/flattenicity/GainEq", "CCDB path for gain equalization constants"}; + Configurable cfgVtxEqCcdbPath{"cfgVtxEqCcdbPath", "Users/g/gbencedi/flattenicity/ZvtxEq", "CCDB path for z-vertex equalization constants"}; + Configurable cfgUseCcdbForRun{"cfgUseCcdbForRun", true, "Get ccdb object based on run number instead of timestamp"}; + Configurable cfgStoreThnSparse{"cfgStoreThnSparse", false, "Store histograms as THnSparse"}; + + struct : ConfigurableGroup { + Configurable cfgCustomTVX{"cfgCustomTVX", false, "Ask for custom TVX instead of sel8"}; + Configurable cfgRemoveNoTimeFrameBorder{"cfgRemoveNoTimeFrameBorder", true, "Bunch crossing is far from Time Frame borders"}; + Configurable cfgRemoveITSROFrameBorder{"cfgRemoveITSROFrameBorder", true, "Bunch crossing is far from ITS RO Frame border"}; + Configurable cfgCutVtxZ{"cfgCutVtxZ", 10.0f, "Accepted z-vertex range"}; + Configurable cfgINELCut{"cfgINELCut", true, "INEL event selection"}; + Configurable cfgRemoveNoSameBunchPileup{"cfgRemoveNoSameBunchPileup", false, "Reject collisions in case of pileup with another collision in the same foundBC"}; + Configurable cfgRequireIsGoodZvtxFT0vsPV{"cfgRequireIsGoodZvtxFT0vsPV", false, "Small difference between z-vertex from PV and from FT0"}; + Configurable cfgRequireIsVertexITSTPC{"cfgRequireIsVertexITSTPC", false, "At least one ITS-TPC track (reject vertices built from ITS-only tracks)"}; + Configurable cfgRequirekIsVertexTOFmatched{"cfgRequirekIsVertexTOFmatched", false, "Require kIsVertexTOFmatched: at least one of vertex contributors is matched to TOF"}; + } evtSelOpt; + + struct : ConfigurableGroup { + Configurable useFlatData{"useFlatData", true, "use flattenicity from rec collisions"}; + } flatSelOpt; + + struct : ConfigurableGroup { + ConfigurableAxis axisPt{"axisPt", {VARIABLE_WIDTH, 0.0, 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.2, 2.4, 2.6, 2.8, 3.0, 3.2, 3.4, 3.6, 3.8, 4.0, 4.2, 4.4, 4.6, 4.8, 5.0}, "pT binning"}; + ConfigurableAxis axisMultPerc{"axisMultPerc", {100, 0, 100}, "Multiplicity percentiles binning"}; + ConfigurableAxis axisVertexZ{"axisVertexZ", {60, -15., 15.}, "Vertex z binning"}; + ConfigurableAxis axisMult{"axisMult", {301, -0.5, 300.5}, "Multiplicity binning"}; + ConfigurableAxis axisDCAxy{"axisDCAxy", {200, -5, 5}, "DCAxy binning"}; + ConfigurableAxis axisDCAz{"axisDCAz", {200, -5, 5}, "DCAz binning"}; + ConfigurableAxis axisPhi = {"axisPhi", {60, 0, constants::math::TwoPI}, "#varphi binning"}; + ConfigurableAxis axisPhiMod = {"axisPhiMod", {100, 0, constants::math::PI / 9}, "fmod(#varphi,#pi/9)"}; + ConfigurableAxis axisEta = {"axisEta", {8, -0.8, 0.8}, "#eta binning"}; + ConfigurableAxis axisDedx{"axisDedx", {1000, 0, 1000}, "dE/dx binning"}; + ConfigurableAxis axisNsigmaTPC{"axisNsigmaTPC", {200, -10, 10}, "nsigmaTPC binning"}; + ConfigurableAxis axisNsigmaTOF{"axisNsigmaTOF", {200, -10, 10}, "nsigmaTOF binning"}; + } binOpt; + + struct : ConfigurableGroup { + Configurable cfgTrkEtaMax{"cfgTrkEtaMax", 0.8f, "Eta range for tracks"}; + Configurable cfgRapMax{"cfgRapMax", 0.5f, "Maximum range of rapidity for tracks"}; + Configurable cfgTrkPtMin{"cfgTrkPtMin", 0.15f, "Minimum pT of tracks"}; + Configurable cfgPhiCutPtMin{"cfgPhiCutPtMin", 2.0f, "Minimum pT for phi cut"}; + Configurable cfgTOFBetaPion{"cfgTOFBetaPion", 1.0f, "Minimum beta for TOF pions"}; + Configurable cfgUseExtraTrkCut{"cfgUseExtraTrkCut", true, "Use extra track cut"}; + Configurable cfgMomMIPMax{"cfgMomMIPMax", 0.6f, "Maximum momentum of MIP pions"}; + Configurable cfgMomMIPMin{"cfgMomMIPMin", 0.4f, "Minimum momentum of MIP pions"}; + Configurable cfgDeDxMIPMax{"cfgDeDxMIPMax", 60.0f, "Maximum range of MIP dedx"}; + Configurable cfgDeDxMIPMin{"cfgDeDxMIPMin", 40.0f, "Maximum range of MIP dedx"}; + Configurable cfgNsigmaMax{"cfgNsigmaMax", 100.0f, "Maximum range of nsgima for tracks"}; + Configurable cfgMomSelPiTOF{"cfgMomSelPiTOF", 0.7f, "Momentum cut for TOF pions"}; + Configurable cfgNsigSelKaTOF{"cfgNsigSelKaTOF", 3.0f, "Nsigma cut for TOF kaons"}; + Configurable cfgBetaPlateuMax{"cfgBetaPlateuMax", 0.1f, "Beta max for Plateau electrons"}; + } trkSelOpt; + + struct : ConfigurableGroup { + Configurable cfgDCAv0daughter{"cfgDCAv0daughter", 0.3, "DCA of V0 daughter tracks"}; + Configurable cfgV0etamax{"cfgV0etamax", 0.9f, "max eta of V0s"}; + Configurable cfgV0DaughterTpcMomMax{"cfgV0DaughterTpcMomMax", 0.6f, "Maximum momentum of V0 daughter tracks in TPC"}; + Configurable cfgTPCnClsmin{"cfgTPCnClsmin", 50.0f, "cfgTPCnClsmin"}; + Configurable cfgDCAposToPV{"cfgDCAposToPV", 0.05f, "cfgDCAposToPV"}; + Configurable cfgv0cospa{"cfgv0cospa", 0.998, "V0 CosPA"}; + Configurable cfgv0Rmin{"cfgv0Rmin", 0.0, "cfgv0Rmin"}; + Configurable cfgv0Rmax{"cfgv0Rmax", 90.0, "cfgv0Rmax"}; + Configurable cfgdmassG{"cfgdmassG", 0.1, "max mass for photon"}; + Configurable cfgdmassK{"cfgdmassK", 0.1, "max mass for K0s"}; + Configurable cfgdmassL{"cfgdmassL", 0.1, "max mass for Lambda"}; + Configurable cfgdmassAL{"cfgdmassAL", 0.1, "max mass for anti Lambda"}; + Configurable cfgNsigmaElTPC{"cfgNsigmaElTPC", 5.0, "max nsigma of TPC for electorn"}; + Configurable cfgNsigmaPiTPC{"cfgNsigmaPiTPC", 5.0, "max nsigma of TPC for pion"}; + Configurable cfgNsigmaPrTPC{"cfgNsigmaPrTPC", 5.0, "max nsigma of TPC for proton"}; + Configurable cfgNsigmaElTOF{"cfgNsigmaElTOF", 3.0, "max nsigma of TOF for electorn"}; + Configurable cfgNsigmaPiTOF{"cfgNsigmaPiTOF", 3.0, "max nsigma of TOF for pion"}; + Configurable cfgNsigmaPrTOF{"cfgNsigmaPrTOF", 3.0, "max nsigma of TOF for proton"}; + } v0SelOpt; + + Service ccdb; + struct : ConfigurableGroup { + Configurable cfgMagField{"cfgMagField", 99999, "Configurable magnetic field;default CCDB will be queried"}; + Configurable ccdbUrl{"ccdbUrl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable grpmagPath{"grpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; + Configurable grpPath{"grpPath", "GLO/GRP/GRP", "Path of the grp file"}; + } ccdbConf; + + TrackSelection mTrackSelector; + Configurable isCustomTracks{"isCustomTracks", false, "Use custom track cuts"}; + Configurable requirePt{"requirePt", 0.15f, "Set minimum pT of tracks"}; + Configurable requireEta{"requireEta", 0.8f, "Set eta range of tracks"}; + Configurable setITSreq{"setITSreq", 1, "0 = Run3ITSibAny, 1 = Run3ITSallAny, 2 = Run3ITSall7Layers, 3 = Run3ITSibTwo"}; + Configurable requireITS{"requireITS", true, "Additional cut on the ITS requirement"}; + Configurable requireTPC{"requireTPC", true, "Additional cut on the TPC requirement"}; + Configurable requireGoldenChi2{"requireGoldenChi2", true, "Additional cut on the GoldenChi2"}; + Configurable minNCrossedRowsTPC{"minNCrossedRowsTPC", 70.f, "Additional cut on the minimum number of crossed rows in the TPC"}; + Configurable minNCrossedRowsOverFindableClustersTPC{"minNCrossedRowsOverFindableClustersTPC", 0.8f, "Additional cut on the minimum value of the ratio between crossed rows and findable clusters in the TPC"}; + Configurable maxChi2PerClusterTPC{"maxChi2PerClusterTPC", 4.f, "Additional cut on the maximum value of the chi2 per cluster in the TPC"}; + Configurable maxChi2PerClusterITS{"maxChi2PerClusterITS", 36.f, "Additional cut on the maximum value of the chi2 per cluster in the ITS"}; + Configurable minITSnClusters{"minITSnClusters", 5, "minimum number of found ITS clusters"}; + Configurable maxDcaXYFactor{"maxDcaXYFactor", 1.f, "Multiplicative factor on the maximum value of the DCA xy"}; + Configurable maxDcaZ{"maxDcaZ", 2.f, "Additional cut on the maximum value of the DCA z"}; + Configurable minTPCNClsFound{"minTPCNClsFound", 0.f, "Additional cut on the minimum value of the number of found clusters in the TPC"}; + + TF1* fPhiCutLow = nullptr; + TF1* fPhiCutHigh = nullptr; + + std::unique_ptr fDeDxVsEtaPos = nullptr; + std::unique_ptr fDeDxVsEtaNeg = nullptr; + std::unique_ptr fEDeDxVsEtaPos = nullptr; + std::unique_ptr fEDeDxVsEtaNeg = nullptr; + + void init(InitContext&) + { + auto vecParamsMIPposEta = (std::vector)paramsFuncMIPposEta; + auto vecParamsMIPnegEta = (std::vector)paramsFuncMIPnegEta; + auto vecParamsPlateuPosEta = (std::vector)paramsFuncPlateuPosEta; + auto vecParamsPlateuNegEta = (std::vector)paramsFuncPlateuNegEta; + + fDeDxVsEtaPos = setFuncPars(vecParamsMIPposEta); + fDeDxVsEtaNeg = setFuncPars(vecParamsMIPnegEta); + fEDeDxVsEtaPos = setFuncPars(vecParamsPlateuPosEta); + fEDeDxVsEtaNeg = setFuncPars(vecParamsPlateuNegEta); + + ccdb->setURL(ccdbConf.ccdbUrl.value); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + ccdb->setCreatedNotAfter(std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count()); + ccdb->setFatalWhenNull(false); + + if (isCustomTracks.value) { + mTrackSelector = getGlobalTrackSelectionRun3ITSMatch(setITSreq.value); + mTrackSelector.SetPtRange(requirePt.value, 1e10f); + mTrackSelector.SetEtaRange(-requireEta.value, requireEta.value); + mTrackSelector.SetRequireITSRefit(requireITS.value); + mTrackSelector.SetRequireTPCRefit(requireTPC.value); + mTrackSelector.SetRequireGoldenChi2(requireGoldenChi2.value); + mTrackSelector.SetMaxChi2PerClusterTPC(maxChi2PerClusterTPC.value); + mTrackSelector.SetMaxChi2PerClusterITS(maxChi2PerClusterITS.value); + mTrackSelector.SetMinNClustersITS(minITSnClusters.value); + mTrackSelector.SetMinNCrossedRowsTPC(minNCrossedRowsTPC.value); + mTrackSelector.SetMinNClustersTPC(minTPCNClsFound.value); + mTrackSelector.SetMinNCrossedRowsOverFindableClustersTPC(minNCrossedRowsOverFindableClustersTPC.value); + // // mTrackSelector.SetMaxDcaXYPtDep([](float pt) { return 0.0105f + 0.0350f / pow(pt, 1.1f); }); + mTrackSelector.SetMaxDcaXYPtDep([](float /*pt*/) { return 10000.f; }); + mTrackSelector.SetMaxDcaZ(maxDcaZ.value); + mTrackSelector.print(); + } + + const AxisSpec chargeAxis{2, -2.f, 2.f, "Charge"}; + const AxisSpec dEdxAxis{binOpt.axisDedx, "TPC dEdx (a.u.)"}; + const AxisSpec vtxzAxis{100, -20, 20, "Z_{vtx} (cm)"}; + const AxisSpec flatAxis{102, -0.01, 1.01, "Flat FV0"}; + const AxisSpec etaAxis{binOpt.axisEta, "#eta"}; + const AxisSpec phiAxis{binOpt.axisPhi, "#varphi"}; + const AxisSpec phiAxisMod{binOpt.axisPhiMod, "fmod(#varphi,#pi/9)"}; + const AxisSpec pAxis{binOpt.axisPt, "#it{p} (GeV/#it{c})"}; + const AxisSpec ptAxis{binOpt.axisPt, "#it{p}_{T} (GeV/#it{c})"}; + const AxisSpec dcaXYAxis{binOpt.axisDCAxy, "DCA_{xy} (cm)"}; + const AxisSpec dcaZAxis{binOpt.axisDCAz, "DCA_{z} (cm)"}; + const AxisSpec shCluserAxis{200, 0, 1, "Fraction of shared TPC clusters"}; + const AxisSpec clTpcAxis{160, 0, 160, "Number of clusters in TPC"}; + const AxisSpec nSigmaTPCAxis{binOpt.axisNsigmaTPC, "n#sigma_{TPC}"}; + const AxisSpec nSigmaTOFAxis{binOpt.axisNsigmaTOF, "n#sigma_{TOF}"}; + const AxisSpec amplitudeFT0 = {5000, 0, 10000, "FT0 amplitude"}; + const AxisSpec channelFT0Axis = {220, 0.0, 220.0, "FT0 channel"}; + + AxisSpec multAxis{binOpt.axisMultPerc, "multiplicity estimator"}; + + switch (multEst) { + case MultE::kNoMult: + break; + case MultE::kMultFT0M: + multAxis.name = "multFT0M"; + break; + case MultE::kMultTPC: + multAxis.name = "multTPC"; + break; + default: + LOG(fatal) << "No valid option for mult estimator " << multEst; + } + + // Event counter + flatchrg.add("Events/hEvtSel", "Number of events; Cut; #Events Passed Cut", {HistType::kTH1D, {{nEvtSel, 0, nEvtSel}}}); + flatchrg.get(HIST("Events/hEvtSel"))->GetXaxis()->SetBinLabel(evtSelAll + 1, "Events read"); + flatchrg.get(HIST("Events/hEvtSel"))->GetXaxis()->SetBinLabel(evtSelSel8 + 1, "Evt. sel8"); + flatchrg.get(HIST("Events/hEvtSel"))->GetXaxis()->SetBinLabel(evtSelNoITSROFrameBorder + 1, "NoITSROFrameBorder"); + flatchrg.get(HIST("Events/hEvtSel"))->GetXaxis()->SetBinLabel(evtSelkNoTimeFrameBorder + 1, "NoTimeFrameBorder"); + flatchrg.get(HIST("Events/hEvtSel"))->GetXaxis()->SetBinLabel(evtSelkNoSameBunchPileup + 1, "NoSameBunchPileup"); + flatchrg.get(HIST("Events/hEvtSel"))->GetXaxis()->SetBinLabel(evtSelkIsGoodZvtxFT0vsPV + 1, "IsGoodZvtxFT0vsPV"); + flatchrg.get(HIST("Events/hEvtSel"))->GetXaxis()->SetBinLabel(evtSelkIsVertexITSTPC + 1, "IsVertexITSTPC"); + flatchrg.get(HIST("Events/hEvtSel"))->GetXaxis()->SetBinLabel(evtSelkIsVertexTOFmatched + 1, "IsVertexTOFmatched"); + flatchrg.get(HIST("Events/hEvtSel"))->GetXaxis()->SetBinLabel(evtSelVtxZ + 1, "Vtx-z pos"); + flatchrg.get(HIST("Events/hEvtSel"))->GetXaxis()->SetBinLabel(evtSelINELgt0 + 1, "INEL>0"); + // Track counter + flatchrg.add("Tracks/hTrkSel", "Number of tracks; Cut; #Tracks Passed Cut", {HistType::kTH1D, {{nTrkSel, 0, nTrkSel}}}); + flatchrg.get(HIST("Tracks/hTrkSel"))->GetXaxis()->SetBinLabel(trkSelEta + 1, "Eta"); + flatchrg.get(HIST("Tracks/hTrkSel"))->GetXaxis()->SetBinLabel(trkSelPt + 1, "Pt"); + flatchrg.get(HIST("Tracks/hTrkSel"))->GetXaxis()->SetBinLabel(trkSelDCA + 1, "DCA"); + flatchrg.get(HIST("Tracks/hTrkSel"))->GetXaxis()->SetBinLabel(trkSelNCls + 1, "NCls"); + flatchrg.get(HIST("Tracks/hTrkSel"))->GetXaxis()->SetBinLabel(trkSelTPCBndr + 1, "TPC Boundary"); + + if (trkSelOpt.cfgUseExtraTrkCut) { + 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); + } + + if (doprocessFlat) { + flatchrg.add("Events/hVtxZ", "Measured vertex z position", HistType::kTH1D, {vtxzAxis}); + flatchrg.add("Events/hFlatVsMultEst", "hFlatVsMultEst", HistType::kTH2D, {flatAxis, multAxis}); + + if (cfgFillQAHisto) { + flatchrg.add("Tracks/postSel/hPtPhi", "; #it{p}_{T} (GeV/#it{c}); fmod(#varphi,#pi/9)", {HistType::kTH2D, {ptAxis, phiAxisMod}}); + // P vs PT vs ETA + flatchrg.add("Tracks/postSel/hPVsPtEta", "; #it{p} (GeV/#it{c}); #it{p}_{T} (GeV/#it{c}); #eta;", {HistType::kTH3D, {pAxis, ptAxis, etaAxis}}); + flatchrg.addClone("Tracks/postSel/", "Tracks/preSel/"); + // dEdx MIP, Plateau + flatchrg.add("Tracks/postCalib/all/hMIP", "; mult; flat; #eta; #LT dE/dx #GT_{MIP, primary tracks};", {HistType::kTHnSparseD, {multAxis, flatAxis, etaAxis, dEdxAxis}}); + flatchrg.add("Tracks/postCalib/all/hPlateau", "; mult; flat; #eta; #LT dE/dx #GT_{Plateau, primary tracks};", {HistType::kTHnSparseD, {multAxis, flatAxis, etaAxis, dEdxAxis}}); + flatchrg.add("Tracks/postCalib/all/hMIPVsEta", "; #eta; #LT dE/dx #GT_{MIP, primary tracks};", {HistType::kTH2D, {etaAxis, dEdxAxis}}); + flatchrg.add("Tracks/postCalib/all/pMIPVsEta", "; #eta; #LT dE/dx #GT_{MIP, primary tracks};", {HistType::kTProfile, {etaAxis}}); + flatchrg.add("Tracks/postCalib/all/hMIPVsPhi", "; #varphi; #LT dE/dx #GT_{MIP, primary tracks};", {HistType::kTH2D, {phiAxis, dEdxAxis}}); + flatchrg.add("Tracks/postCalib/all/pMIPVsPhi", "; #varphi; #LT dE/dx #GT_{MIP, primary tracks};", {HistType::kTProfile, {phiAxis}}); + flatchrg.add("Tracks/postCalib/all/hMIPVsPhiVsEta", "; #varphi; #LT dE/dx #GT_{MIP, primary tracks}; #eta;", {HistType::kTH3D, {phiAxis, dEdxAxis, etaAxis}}); + flatchrg.add("Tracks/postCalib/all/hPlateauVsEta", "; #eta; #LT dE/dx #GT_{Plateau, primary tracks};", {HistType::kTH2D, {etaAxis, dEdxAxis}}); + flatchrg.add("Tracks/postCalib/all/pPlateauVsEta", "; #eta; #LT dE/dx #GT_{Plateau, primary tracks};", {HistType::kTProfile, {etaAxis}}); + flatchrg.add("Tracks/postCalib/all/hPlateauVsPhi", "; #varphi; #LT dE/dx #GT_{Plateau, primary tracks};", {HistType::kTH2D, {phiAxis, dEdxAxis}}); + flatchrg.add("Tracks/postCalib/all/pPlateauVsPhi", "; #varphi; #LT dE/dx #GT_{Plateau, primary tracks};", {HistType::kTProfile, {phiAxis}}); + flatchrg.add("Tracks/postCalib/all/hPlateauVsPhiVsEta", "; #varphi; #LT dE/dx #GT_{Plateau, primary tracks}; #eta;", {HistType::kTH3D, {phiAxis, dEdxAxis, etaAxis}}); + if (cfgFillChrgType) { + flatchrg.addClone("Tracks/postCalib/all/", "Tracks/postCalib/pos/"); + flatchrg.addClone("Tracks/postCalib/all/", "Tracks/postCalib/neg/"); + flatchrg.addClone("Tracks/postCalib/all/", "Tracks/preCalib/all/"); + flatchrg.addClone("Tracks/preCalib/all/", "Tracks/preCalib/pos/"); + flatchrg.addClone("Tracks/preCalib/all/", "Tracks/preCalib/neg/"); + } + // fillTrackQA + flatchrg.add("Tracks/QA/hPtVsWOcutDCA", "hPtVsWOcutDCA", HistType::kTH2D, {ptAxis, dcaXYAxis}); + flatchrg.add("Tracks/QA/hPt", "", HistType::kTH1D, {ptAxis}); + flatchrg.add("Tracks/QA/hPhi", "", HistType::kTH1D, {phiAxis}); + flatchrg.add("Tracks/QA/hEta", "", HistType::kTH1D, {etaAxis}); + flatchrg.add("Tracks/QA/hDCAXYvsPt", "", HistType::kTH2D, {ptAxis, dcaXYAxis}); + flatchrg.add("Tracks/QA/hDCAZvsPt", "", HistType::kTH2D, {ptAxis, dcaZAxis}); + // tpc + flatchrg.add("Tracks/QA/hShTpcClvsPt", "", {HistType::kTH2D, {ptAxis, shCluserAxis}}); + flatchrg.add("Tracks/QA/hCrossTPCvsPt", "", {HistType::kTH2D, {ptAxis, clTpcAxis}}); + flatchrg.add("Tracks/QA/hTPCCluster", "N_{cluster}", HistType::kTH1D, {{200, -0.5, 199.5}}); + flatchrg.add("Tracks/QA/tpcNClsShared", " ; # shared TPC clusters TPC", HistType::kTH1D, {{165, -0.5, 164.5}}); + flatchrg.add("Tracks/QA/tpcCrossedRows", " ; # crossed TPC rows", HistType::kTH1D, {{165, -0.5, 164.5}}); + flatchrg.add("Tracks/QA/tpcCrossedRowsOverFindableCls", " ; crossed rows / findable TPC clusters", HistType::kTH1D, {{60, 0.7, 1.3}}); + // its + flatchrg.add("Tracks/QA/itsNCls", " ; # ITS clusters", HistType::kTH1D, {{8, -0.5, 7.5}}); + flatchrg.add("Tracks/QA/hChi2ITSTrkSegment", "chi2ITS", HistType::kTH1D, {{100, -0.5, 99.5}}); + // tof + flatchrg.add("Tracks/QA/hTOFPvsBeta", "Beta from TOF; #it{p} (GeV/#it{c}); #beta", {HistType::kTH2D, {pAxis, {120, 0.0, 1.2}}}); + flatchrg.add("Tracks/QA/hTOFpi", "Primary Pions from TOF; #eta; #it{p} (GeV/#it{c}); dEdx", {HistType::kTHnSparseD, {etaAxis, pAxis, dEdxAxis}}); + // nsigma + for (int i = 0; i < NpartChrg; i++) { + const std::string strID = Form("/%s/%s", (i < Npart) ? "pos" : "neg", Pid[i % Npart]); + hPtNsigmaTPC[i] = flatchrg.add("Tracks/hPtNsigmaTPC" + strID, " ; p_{T} (GeV/c)", HistType::kTH2D, {ptAxis, nSigmaTPCAxis}); + if (cfgStoreThnSparse) { + hThPtNsigmaTPC[i] = flatchrg.add("Tracks/hThPtNsigmaTPC" + strID, " ; p_{T} (GeV/c)", HistType::kTHnSparseD, {ptAxis, nSigmaTPCAxis, multAxis, flatAxis}); + } + hPtNsigmaTOF[i] = flatchrg.add("Tracks/hPtNsigmaTOF" + strID, " ; p_{T} (GeV/c)", HistType::kTH2D, {ptAxis, nSigmaTOFAxis}); + hPtNsigmaTPCTOF[i] = flatchrg.add("Tracks/hPtNsigmaTPCTOF" + strID, PidChrg[i], HistType::kTH2D, {nSigmaTPCAxis, nSigmaTOFAxis}); + } + } + // FV0 QA + flatchrg.add("FV0/hFV0AmplWCalib", "", HistType::kTH2D, {{48, -0.5, 47.5, "channel"}, {500, -0.5, +19999.5, "FV0 amplitude"}}); + flatchrg.add("FV0/hFV0AmplvsVtxzWoCalib", "", HistType::kTH2D, {{30, -15.0, +15.0, "z vtx (cm)"}, {1000, -0.5, +39999.5, "FV0 amplitude"}}); + flatchrg.add("FV0/hFV0AmplvsVtxzCalib", "", HistType::kTH2D, {{30, -15.0, +15.0, "z vtx (cm)"}, {1000, -0.5, +39999.5, "FV0 amplitude"}}); + flatchrg.add("FV0/hFV0amp", "", {HistType::kTH2D, {channelFT0Axis, amplitudeFT0}}); + flatchrg.add("FV0/pFV0amp", "", HistType::kTProfile, {channelFT0Axis}); + flatchrg.add("FV0/hFV0ampCorr", "", {HistType::kTH2D, {channelFT0Axis, amplitudeFT0}}); + // V0's QA + flatchrg.add("Tracks/V0qa/hV0Pt", "pT", HistType::kTH1D, {{100, 0.0f, 10}}); + flatchrg.add("Tracks/V0qa/hV0ArmPod", ";#alpha; #it{q}_T", HistType::kTH2D, {{200, -1.0f, +1.0f}, {250, 0.0f, 0.25f}}); + // dEdx PID + flatchrg.add({"Tracks/all/hdEdx", "; #eta; mult; flat; #it{p} (GeV/#it{c}); dEdx", {HistType::kTHnSparseD, {etaAxis, multAxis, flatAxis, pAxis, dEdxAxis}}}); + // Clean samples + flatchrg.add({"Tracks/CleanTof/all/hPiTof", "; #eta; mult; flat; #it{p} (GeV/#it{c}); dEdx", {HistType::kTHnSparseD, {etaAxis, multAxis, flatAxis, pAxis, dEdxAxis}}}); + flatchrg.add({"Tracks/CleanV0/pos/hEV0", "; #eta; mult; flat; #it{p} (GeV/#it{c}); dEdx", {HistType::kTHnSparseD, {etaAxis, multAxis, flatAxis, pAxis, dEdxAxis}}}); + flatchrg.add({"Tracks/CleanV0/pos/hPiV0", "; #eta; mult; flat; #it{p} (GeV/#it{c}); dEdx", {HistType::kTHnSparseD, {etaAxis, multAxis, flatAxis, pAxis, dEdxAxis}}}); + flatchrg.add({"Tracks/CleanV0/pos/hPV0", "; #eta; mult; flat; #it{p} (GeV/#it{c}); dEdx", {HistType::kTHnSparseD, {etaAxis, multAxis, flatAxis, pAxis, dEdxAxis}}}); + flatchrg.addClone("Tracks/CleanV0/pos/", "Tracks/CleanV0/neg/"); + if (cfgFillChrgType) { + flatchrg.addClone("Tracks/all/", "Tracks/pos/"); + flatchrg.addClone("Tracks/all/", "Tracks/neg/"); + flatchrg.addClone("Tracks/CleanTof/all/", "Tracks/CleanTof/pos/"); + flatchrg.addClone("Tracks/CleanTof/all/", "Tracks/CleanTof/neg/"); + } + } + + if (doprocessMC) { + auto h = flatchrg.add("hEvtGenRec", "Generated and Reconstructed MC Collisions", kTH1D, {{3, 0.5, 3.5}}); + h->GetXaxis()->SetBinLabel(1, "Gen coll"); + h->GetXaxis()->SetBinLabel(2, "Rec coll"); + h->GetXaxis()->SetBinLabel(3, "INEL>0"); + + flatchrg.add("hEvtMcGenColls", "Number of events; Cut; #Events Passed Cut", {HistType::kTH1D, {{5, 0.5, 5.5}}}); + flatchrg.get(HIST("hEvtMcGenColls"))->GetXaxis()->SetBinLabel(1, "Gen. coll"); + flatchrg.get(HIST("hEvtMcGenColls"))->GetXaxis()->SetBinLabel(2, "At least 1 reco"); + flatchrg.get(HIST("hEvtMcGenColls"))->GetXaxis()->SetBinLabel(3, "Reco. coll."); + flatchrg.get(HIST("hEvtMcGenColls"))->GetXaxis()->SetBinLabel(4, "Reco. good coll."); + + for (int i = 0; i < NpartChrg; i++) { + const std::string strID = Form("/%s/%s", (i < Npart) ? "pos" : "neg", Pid[i % Npart]); + hPtGenRecEvt[i] = flatchrg.add("Tracks/hPtGenRecEvt" + strID, " ; p_{T} (GeV/c)", HistType::kTH1D, {ptAxis}); + hPtGenPrimRecEvt[i] = flatchrg.add("Tracks/hPtGenPrimRecEvt" + strID, " ; p_{T} (GeV/c)", HistType::kTH1D, {ptAxis}); + hPtEffGenPrim[i] = flatchrg.add("Tracks/hPtEffGenPrim" + strID, " ; p_{T} (GeV/c)", HistType::kTH3D, {multAxis, flatAxis, ptAxis}); + hPtEffGenWeak[i] = flatchrg.add("Tracks/hPtEffGenWeak" + strID, " ; p_{T} (GeV/c)", HistType::kTH3D, {multAxis, flatAxis, ptAxis}); + hPtEffGenMat[i] = flatchrg.add("Tracks/hPtEffGenMat" + strID, " ; p_{T} (GeV/c)", HistType::kTH3D, {multAxis, flatAxis, ptAxis}); + hPtEffRecPrim[i] = flatchrg.add("Tracks/hPtEffRecPrim" + strID, " ; p_{T} (GeV/c)", HistType::kTH3D, {multAxis, flatAxis, ptAxis}); + hPtEffRecWeak[i] = flatchrg.add("Tracks/hPtEffRecWeak" + strID, " ; p_{T} (GeV/c)", HistType::kTH3D, {multAxis, flatAxis, ptAxis}); + hPtEffRecMat[i] = flatchrg.add("Tracks/hPtEffRecMat" + strID, " ; p_{T} (GeV/c)", HistType::kTH3D, {multAxis, flatAxis, ptAxis}); + hDCAxyBadCollPrim[i] = flatchrg.add("Tracks/hDCAxyBadCollPrim" + strID, " ; p_{T} (GeV/c)", HistType::kTH2D, {ptAxis, dcaXYAxis}); + hDCAxyBadCollWeak[i] = flatchrg.add("Tracks/hDCAxyBadCollWeak" + strID, " ; p_{T} (GeV/c)", HistType::kTH2D, {ptAxis, dcaXYAxis}); + hDCAxyBadCollMat[i] = flatchrg.add("Tracks/hDCAxyBadCollMat" + strID, " ; p_{T} (GeV/c)", HistType::kTH2D, {ptAxis, dcaXYAxis}); + hPtVsDCAxyPrim[i] = flatchrg.add("Tracks/hPtVsDCAxyPrim" + strID, " ; p_{T} (GeV/c)", HistType::kTH2D, {ptAxis, dcaXYAxis}); + hPtVsDCAxyWeak[i] = flatchrg.add("Tracks/hPtVsDCAxyWeak" + strID, " ; p_{T} (GeV/c)", HistType::kTH2D, {ptAxis, dcaXYAxis}); + hPtVsDCAxyMat[i] = flatchrg.add("Tracks/hPtVsDCAxyMat" + strID, " ; p_{T} (GeV/c)", HistType::kTH2D, {ptAxis, dcaXYAxis}); + } + + flatchrg.add({"hPtOut", " ; p_{T} (GeV/c)", {HistType::kTH1D, {ptAxis}}}); + flatchrg.add({"hPtOutPrim", " ; p_{T} (GeV/c)", {HistType::kTH1D, {ptAxis}}}); + flatchrg.add({"hPtOutNoEtaCut", " ; p_{T} (GeV/c)", {HistType::kTH1D, {ptAxis}}}); + flatchrg.add({"PtOutFakes", " ; p_{T} (GeV/c)", {HistType::kTH1D, {ptAxis}}}); + flatchrg.add("hPtVsDCAxyPrimAll", "hPtVsDCAxyPrimAll", HistType::kTH2D, {ptAxis, dcaXYAxis}); + flatchrg.add("hPtVsDCAxyWeakAll", "hPtVsDCAxyWeakAll", HistType::kTH2D, {ptAxis, dcaXYAxis}); + flatchrg.add("hPtVsDCAxyMatAll", "hPtVsDCAxyMatAll", HistType::kTH2D, {ptAxis, dcaXYAxis}); + flatchrg.add("hPtVsDCAxyAll", "hPtVsDCAxyAll", HistType::kTH2D, {ptAxis, dcaXYAxis}); + flatchrg.add({"ResponseGen", " ; N_{part}; F_{FV0};", {HistType::kTHnSparseD, {multAxis, flatAxis}}}); + flatchrg.add("h1flatencityFV0MCGen", "", HistType::kTH1D, {{102, -0.01, 1.01, "1-flatencityFV0"}}); + } + + if (doprocessMCclosure) { + for (int i = 0; i < Npart; i++) { + flatchrg.add({fmt::format(kPtMCclosurePrimF.data(), kSpeciesAll[i]).c_str(), " ; p_{T} (GeV/c)", {HistType::kTH3D, {multAxis, flatAxis, ptAxis}}}); + } + } + + if (doprocessSgnLoss) { + flatchrg.add("hFlatMCGenRecColl", "hFlatMCGenRecColl", {HistType::kTH1D, {flatAxis}}); + flatchrg.add("hFlatMCGen", "hFlatMCGen", {HistType::kTH1D, {flatAxis}}); + // Event counter + flatchrg.add("hEvtMcGen", "hEvtMcGen", {HistType::kTH1D, {{4, 0.f, 4.f}}}); + flatchrg.get(HIST("hEvtMcGen"))->GetXaxis()->SetBinLabel(1, "all"); + flatchrg.get(HIST("hEvtMcGen"))->GetXaxis()->SetBinLabel(2, "z-vtx"); + flatchrg.get(HIST("hEvtMcGen"))->GetXaxis()->SetBinLabel(3, "INELgt0"); + flatchrg.add("hEvtMCRec", "hEvtMCRec", {HistType::kTH1D, {{4, 0.f, 4.f}}}); + flatchrg.get(HIST("hEvtMCRec"))->GetXaxis()->SetBinLabel(1, "all"); + flatchrg.get(HIST("hEvtMCRec"))->GetXaxis()->SetBinLabel(2, "evt sel"); + flatchrg.get(HIST("hEvtMCRec"))->GetXaxis()->SetBinLabel(3, "INELgt0"); + flatchrg.add("hEvtMcGenRecColl", "hEvtMcGenRecColl", {HistType::kTH1D, {{2, 0.f, 2.f}}}); + flatchrg.get(HIST("hEvtMcGenRecColl"))->GetXaxis()->SetBinLabel(1, "INEL"); + flatchrg.get(HIST("hEvtMcGenRecColl"))->GetXaxis()->SetBinLabel(2, "INELgt0"); + + flatchrg.add("hFlatGenINELgt0", "hFlatGenINELgt0", {HistType::kTH1D, {flatAxis}}); + + for (int i = 0; i < NpartChrg; ++i) { + flatchrg.add({fmt::format(kPtGenPrimSgnF.data(), kSpecies[i]).c_str(), " ; p_{T} (GeV/c)", {HistType::kTH3D, {multAxis, flatAxis, ptAxis}}}); + flatchrg.add({fmt::format(kPtGenPrimSgnINELF.data(), kSpecies[i]).c_str(), " ; p_{T} (GeV/c)", {HistType::kTH3D, {multAxis, flatAxis, ptAxis}}}); + flatchrg.add({fmt::format(kPtRecCollPrimSgnF.data(), kSpecies[i]).c_str(), " ; p_{T} (GeV/c)", {HistType::kTH3D, {multAxis, flatAxis, ptAxis}}}); + flatchrg.add({fmt::format(kPtRecCollPrimSgnINELF.data(), kSpecies[i]).c_str(), " ; p_{T} (GeV/c)", {HistType::kTH3D, {multAxis, flatAxis, ptAxis}}}); + flatchrg.add({fmt::format(kPtGenRecCollPrimSgnF.data(), kSpecies[i]).c_str(), " ; p_{T} (GeV/c)", {HistType::kTH3D, {multAxis, flatAxis, ptAxis}}}); + flatchrg.add({fmt::format(kPtGenRecCollPrimSgnINELF.data(), kSpecies[i]).c_str(), " ; p_{T} (GeV/c)", {HistType::kTH3D, {multAxis, flatAxis, ptAxis}}}); + } + } + + // Hash list for efficiency + listEfficiency.setObject(new THashList); + static_for<0, 1>([&](auto pidSgn) { + bookMcHist(); + bookMcHist(); + bookMcHist(); + initEfficiency(); + initEfficiency(); + initEfficiency(); + }); + } + + void initCCDB(aod::BCsWithTimestamps::iterator const& bc) + { + fv0AmplCorr.clear(); + fv0AmplCorr = {}; + std::string fullPathCalibGain; + std::string fullPathCalibVtx; + auto timestamp = bc.timestamp(); + auto runnumber = bc.runNumber(); + + if (applyCalibGain) { + fullPathCalibGain = cfgGainEqCcdbPath; + fullPathCalibGain += "/FV0"; + auto objfv0Gain = getForTsOrRun>(fullPathCalibGain, timestamp, runnumber); + if (!objfv0Gain) { + for (auto i{0u}; i < kNCellsFV0; i++) { + fv0AmplCorr.push_back(1.); + LOGF(warning, "Setting FV0 calibration object values to 1"); + } + } else { + fv0AmplCorr = *(objfv0Gain); + } + } + + if (applyCalibVtx) { + fullPathCalibVtx = cfgVtxEqCcdbPath; + fullPathCalibVtx += "/FV0"; + zVtxMap = getForTsOrRun(fullPathCalibVtx, timestamp, runnumber); + } + } + + using MyCollisions = soa::Join; + using Colls = soa::Join; + using CollsGen = soa::Join; + using MCColls = soa::Join; + using CollsGenSgn = soa::SmallGroups>; + using MyPIDTracks = soa::Join; + using MyLabeledTracks = soa::Join; + using MyFiltLabeledTracks = soa::Filtered; + using MyLabeledPIDTracks = soa::Join; + + template + std::unique_ptr setFuncPars(T const& vecPars) + { + std::unique_ptr fCalibFunc(new TF1("fCalibFunc", "pol2", -1., 1.)); + if (vecPars.size() >= 1) { + for (typename T::size_type i = 0; i < vecPars.size(); i++) { + fCalibFunc->SetParameter(i, vecPars[i]); + } + } + return fCalibFunc; + } + + template + bool isPID(const P& mcParticle) + { + static_assert(pidSgn == 0 || pidSgn == 1); + static_assert(id > 0 || id < Npart); + constexpr int kIdx = id + pidSgn * Npart; + return mcParticle.pdgCode() == PidSgn[kIdx]; + } + + template + bool selTPCtrack(T const& track) + { + return (track.hasTPC() && + track.passedTPCCrossedRowsOverNCls() && + track.passedTPCChi2NDF() && + track.passedTPCNCls() && + track.passedTPCCrossedRows() && + track.passedTPCRefit()); + } + + template + bool selTOFPi(T const& track) + { + if (track.p() < trkSelOpt.cfgMomSelPiTOF) { + if (track.hasTOF()) { + if (std::abs(track.tpcNSigmaPi()) < v0SelOpt.cfgNsigmaPiTPC && std::abs(track.tofNSigmaPi()) < v0SelOpt.cfgNsigmaPiTOF) { + return true; + } + } + } + return false; + } + + template + void fillNsigma(T const& tracks, const C& collision) + { + const float mult = getMult(collision); + const float flat = fillFlat(collision); + for (const auto& track : tracks) { + checkNsigma(track, mult, flat); + } + } + + template + void filldEdx(T const& tracks, V const& v0s, const C& collision, aod::BCsWithTimestamps const& /*bcs*/) + { + auto bc = collision.template bc_as(); + auto magField = (ccdbConf.cfgMagField == 0) ? getMagneticField(bc.timestamp()) : ccdbConf.cfgMagField; + + if (applyCalibGain || applyCalibVtx) { + int currentRun = bc.runNumber(); + if (runNumber != currentRun) { + initCCDB(bc); + runNumber = currentRun; + } + } + + const float mult = getMult(collision); + const float flat = fillFlat(collision); + flatchrg.fill(HIST("Events/hFlatVsMultEst"), flat, mult); + + for (const auto& track : tracks) { + float dEdx = track.tpcSignal(); + bool posP = (track.sign() * track.tpcInnerParam() > 0) ? true : false; + if (cfgFillQAHisto) { + fillTrackQA(track); + } + if (!isGoodTrack(track, magField)) { + continue; + } + if (cfgFillQAHisto) { + fillTrackQA(track); + filldEdxQA(track, collision); + if (posP) { + filldEdxQA(track, collision); + } else { + filldEdxQA(track, collision); + } + } + if (applyCalibDeDx) { + dEdx *= (50.0 / getCalibration(true, track.eta())); + } + if (cfgFillQAHisto) { + filldEdxQA(track, collision); + if (posP) { + filldEdxQA(track, collision); + } else { + filldEdxQA(track, collision); + } + } + + // PID TPC dEdx + flatchrg.fill(HIST(kPrefix) + HIST(kCharge[kAll]) + HIST("hdEdx"), track.eta(), mult, flat, track.tpcInnerParam(), dEdx); + if (posP) { + flatchrg.fill(HIST(kPrefix) + HIST(kCharge[kPos]) + HIST("hdEdx"), track.eta(), mult, flat, track.tpcInnerParam(), dEdx); + } else { + flatchrg.fill(HIST(kPrefix) + HIST(kCharge[kNeg]) + HIST("hdEdx"), track.eta(), mult, flat, track.tpcInnerParam(), dEdx); + } + + // TOF pions + if (track.hasTOF() && track.beta() > 1.) { + if (selTOFPi(track)) { + flatchrg.fill(HIST(kPrefixCleanTof) + HIST(kCharge[kAll]) + HIST("hPiTof"), track.eta(), mult, flat, track.tpcInnerParam(), dEdx); + if (posP) { + flatchrg.fill(HIST(kPrefixCleanTof) + HIST(kCharge[kPos]) + HIST("hPiTof"), track.eta(), mult, flat, track.tpcInnerParam(), dEdx); + } else { + flatchrg.fill(HIST(kPrefixCleanTof) + HIST(kCharge[kNeg]) + HIST("hPiTof"), track.eta(), mult, flat, track.tpcInnerParam(), dEdx); + } + } + } + } + + // V0s + for (const auto& v0 : v0s) { + if (!isGoodV0Track(v0, tracks)) { + continue; + } + + const auto& posTrack = v0.template posTrack_as(); + const auto& negTrack = v0.template negTrack_as(); + float dEdxPos = posTrack.tpcSignal(); + float dEdxNeg = negTrack.tpcSignal(); + + if (applyCalibDeDx) { + dEdxPos *= (50.0 / getCalibration(true, posTrack.eta())); + dEdxNeg *= (50.0 / getCalibration(true, negTrack.eta())); + } + + if (selectTypeV0s(v0, posTrack, negTrack) == kGa) { // Gamma selection + flatchrg.fill(HIST(kPrefixCleanV0) + HIST(kCharge[kPos]) + HIST("hEV0"), posTrack.eta(), mult, flat, posTrack.sign() * posTrack.tpcInnerParam(), dEdxPos); + flatchrg.fill(HIST(kPrefixCleanV0) + HIST(kCharge[kNeg]) + HIST("hEV0"), negTrack.eta(), mult, flat, negTrack.sign() * negTrack.tpcInnerParam(), dEdxNeg); + } + if (selectTypeV0s(v0, posTrack, negTrack) == kKz) { // K0S -> pi + pi + flatchrg.fill(HIST(kPrefixCleanV0) + HIST(kCharge[kPos]) + HIST("hPiV0"), posTrack.eta(), mult, flat, posTrack.sign() * posTrack.tpcInnerParam(), dEdxPos); + flatchrg.fill(HIST(kPrefixCleanV0) + HIST(kCharge[kNeg]) + HIST("hPiV0"), negTrack.eta(), mult, flat, negTrack.sign() * negTrack.tpcInnerParam(), dEdxNeg); + } + if (selectTypeV0s(v0, posTrack, negTrack) == kLam) { // L -> p + pi- + flatchrg.fill(HIST(kPrefixCleanV0) + HIST(kCharge[kPos]) + HIST("hPV0"), posTrack.eta(), mult, flat, posTrack.sign() * posTrack.tpcInnerParam(), dEdxPos); + flatchrg.fill(HIST(kPrefixCleanV0) + HIST(kCharge[kNeg]) + HIST("hPV0"), negTrack.eta(), mult, flat, negTrack.sign() * negTrack.tpcInnerParam(), dEdxNeg); + } + if (selectTypeV0s(v0, posTrack, negTrack) == kaLam) { // L -> p + pi- + flatchrg.fill(HIST(kPrefixCleanV0) + HIST(kCharge[kPos]) + HIST("hPiV0"), posTrack.eta(), mult, flat, posTrack.sign() * posTrack.tpcInnerParam(), dEdxPos); + flatchrg.fill(HIST(kPrefixCleanV0) + HIST(kCharge[kNeg]) + HIST("hPiV0"), negTrack.eta(), mult, flat, negTrack.sign() * negTrack.tpcInnerParam(), dEdxNeg); + } + } + } + + float getCalibration(bool isMIP, const float& eta) + { + double valCalib = 999.0; + if (eta < 0.) { + if (isMIP) { + valCalib = fDeDxVsEtaNeg->Eval(eta); + } else { + valCalib = fEDeDxVsEtaNeg->Eval(eta); + } + } else { + if (isMIP) { + valCalib = fDeDxVsEtaPos->Eval(eta); + } else { + valCalib = fEDeDxVsEtaPos->Eval(eta); + } + } + return valCalib; + } + + bool isChrgParticle(int code) + { + auto p = pdg->GetParticle(code); + auto charge = 0.; + if (p != nullptr) { + charge = p->Charge(); + } + return std::abs(charge) >= kMinCharge; + } + + template + bool phiCut(T const& track, float mag, TF1* fphiCutLow, TF1* fphiCutHigh) + { + if (track.pt() < trkSelOpt.cfgPhiCutPtMin) + return true; + // cut to remove tracks at TPC boundaries + double phimodn = track.phi(); + if (mag < 0) // for negative polarity field + phimodn = o2::constants::math::TwoPI - phimodn; + if (track.sign() < 0) // for negative charge + phimodn = o2::constants::math::TwoPI - phimodn; + if (phimodn < 0) + LOGF(warning, "phi < 0: %g", phimodn); + + phimodn += o2::constants::math::PI / 18.0; // to center gap in the middle + phimodn = std::fmod(phimodn, o2::constants::math::PI / 9.0); + + if (cfgFillQAHisto) { + flatchrg.fill(HIST("Tracks/preSel/hPtPhi"), track.pt(), phimodn); + } + if (phimodn < fphiCutHigh->Eval(track.pt()) && phimodn > fphiCutLow->Eval(track.pt())) { + return false; + } + if (cfgFillQAHisto) { + flatchrg.fill(HIST("Tracks/postSel/hPtPhi"), track.pt(), phimodn); + } + return true; + } + + template + bool isGoodTrack(T const& track, int const magfield) + { + if (std::abs(track.eta()) > trkSelOpt.cfgTrkEtaMax) { + return false; + } + flatchrg.fill(HIST("Tracks/hTrkSel"), trkSelEta); + if (track.pt() < trkSelOpt.cfgTrkPtMin) { + return false; + } + flatchrg.fill(HIST("Tracks/hTrkSel"), trkSelPt); + if (!isDCAxyCut(track)) { + return false; + } + flatchrg.fill(HIST("Tracks/hTrkSel"), trkSelDCA); + if (track.tpcNClsCrossedRows() < minNCrossedRowsTPC) { + return false; + } + flatchrg.fill(HIST("Tracks/hTrkSel"), trkSelNCls); + if (trkSelOpt.cfgUseExtraTrkCut && !phiCut(track, magfield, fPhiCutLow, fPhiCutHigh)) { + return false; + } + flatchrg.fill(HIST("Tracks/hTrkSel"), trkSelTPCBndr); + return true; + } + + template + int selectTypeV0s(T1 const& v0, T2 const& postrk, T2 const& negtrk) + { + // Gamma selection + if (v0.mGamma() < v0SelOpt.cfgdmassG) { + if (postrk.tpcInnerParam() < v0SelOpt.cfgV0DaughterTpcMomMax && postrk.hasTPC() && std::abs(postrk.tpcNSigmaEl()) < v0SelOpt.cfgNsigmaElTPC) { + if (postrk.hasTOF() && std::abs(postrk.tofNSigmaEl()) < v0SelOpt.cfgNsigmaElTOF) { + return kGa; + } + } + if (negtrk.tpcInnerParam() < v0SelOpt.cfgV0DaughterTpcMomMax && negtrk.hasTPC() && std::abs(negtrk.tpcNSigmaEl()) < v0SelOpt.cfgNsigmaElTPC) { + if (negtrk.hasTOF() && std::abs(negtrk.tofNSigmaEl()) < v0SelOpt.cfgNsigmaElTOF) { + return kGa; + } + } + } + // K0S selection, K0S -> pi + pi + if (std::abs(v0.mK0Short() - o2::constants::physics::MassK0Short) < v0SelOpt.cfgdmassK) { + if (postrk.tpcInnerParam() < v0SelOpt.cfgV0DaughterTpcMomMax && postrk.hasTPC() && std::abs(postrk.tpcNSigmaPi()) < v0SelOpt.cfgNsigmaPiTPC) { + if (postrk.hasTOF() && std::abs(postrk.tofNSigmaPi()) < v0SelOpt.cfgNsigmaElTOF) { + return kKz; + } + } + if (negtrk.tpcInnerParam() < v0SelOpt.cfgV0DaughterTpcMomMax && negtrk.hasTPC() && std::abs(negtrk.tpcNSigmaPi()) < v0SelOpt.cfgNsigmaPiTPC) { + if (negtrk.hasTOF() && std::abs(negtrk.tofNSigmaPi()) < v0SelOpt.cfgNsigmaPiTOF) { + return kKz; + } + } + } + // Lambda selection, L -> p + pi- + if (std::abs(v0.mLambda() - o2::constants::physics::MassLambda0) < v0SelOpt.cfgdmassL) { + if (postrk.tpcInnerParam() < v0SelOpt.cfgV0DaughterTpcMomMax && postrk.hasTPC() && std::abs(postrk.tpcNSigmaPr()) < v0SelOpt.cfgNsigmaPrTPC && negtrk.hasTPC() && std::abs(negtrk.tpcNSigmaPi()) < v0SelOpt.cfgNsigmaPiTPC) { + if (postrk.hasTOF() && std::abs(postrk.tofNSigmaPr()) < v0SelOpt.cfgNsigmaPrTOF && negtrk.hasTOF() && std::abs(negtrk.tofNSigmaPi()) < v0SelOpt.cfgNsigmaPiTOF) { + return kLam; + } + } + } + // antiLambda -> pbar + pi+ + if (std::abs(v0.mAntiLambda() - o2::constants::physics::MassLambda0) < v0SelOpt.cfgdmassL) { + if (postrk.tpcInnerParam() < v0SelOpt.cfgV0DaughterTpcMomMax && postrk.hasTPC() && std::abs(postrk.tpcNSigmaPi()) < v0SelOpt.cfgNsigmaPiTPC && negtrk.hasTPC() && std::abs(negtrk.tpcNSigmaPr()) < v0SelOpt.cfgNsigmaPrTPC) { + if (postrk.hasTOF() && std::abs(postrk.tofNSigmaPi()) < v0SelOpt.cfgNsigmaPiTOF && negtrk.hasTOF() && std::abs(negtrk.tofNSigmaPr()) < v0SelOpt.cfgNsigmaPrTOF) { + return kaLam; + } + } + } + return kNaN; + } + + template + bool isGoodV0Track(T1 const& v0, T2 const& /*track*/) + { + const auto& posTrack = v0.template posTrack_as(); + const auto& negTrack = v0.template negTrack_as(); + + if (std::abs(posTrack.eta()) > v0SelOpt.cfgV0etamax || std::abs(negTrack.eta()) > v0SelOpt.cfgV0etamax) { + return false; + } + if (posTrack.tpcNClsFound() < v0SelOpt.cfgTPCnClsmin || negTrack.tpcNClsFound() < v0SelOpt.cfgTPCnClsmin) { + return false; + } + if (posTrack.sign() * negTrack.sign() > 0) { // reject same sign pair + return false; + } + if (v0.dcaV0daughters() > v0SelOpt.cfgDCAv0daughter) { + return false; + } + if (v0.v0cosPA() < v0SelOpt.cfgv0cospa) { + return false; + } + if (v0.v0radius() < v0SelOpt.cfgv0Rmin || v0.v0radius() > v0SelOpt.cfgv0Rmax) { + return false; + } + if (std::abs(v0.dcapostopv()) < v0SelOpt.cfgDCAposToPV || std::abs(v0.dcanegtopv()) < v0SelOpt.cfgDCAposToPV) { + return false; + } + if constexpr (fillHist) { + flatchrg.fill(HIST("Tracks/V0qa/hV0Pt"), v0.pt()); + flatchrg.fill(HIST("Tracks/V0qa/hV0ArmPod"), v0.alpha(), v0.qtarm()); + } + return true; + } + + template + void checkNsigma(const T& track, const float mult, const float flat) + { + if (std::abs(track.rapidity(o2::track::PID::getMass(pid))) > trkSelOpt.cfgRapMax) { + return; + } + + float valTPCnsigma = -999, valTOFnsigma = -999; + switch (pid) { + case o2::track::PID::Pion: + valTPCnsigma = track.tpcNSigmaPi(); + valTOFnsigma = track.tofNSigmaPi(); + break; + case o2::track::PID::Kaon: + valTPCnsigma = track.tpcNSigmaKa(); + valTOFnsigma = track.tofNSigmaKa(); + break; + case o2::track::PID::Proton: + valTPCnsigma = track.tpcNSigmaPr(); + valTOFnsigma = track.tofNSigmaPr(); + break; + case o2::track::PID::Electron: + valTPCnsigma = track.tpcNSigmaEl(); + valTOFnsigma = track.tofNSigmaEl(); + break; + case o2::track::PID::Muon: + valTPCnsigma = track.tpcNSigmaMu(); + valTOFnsigma = track.tofNSigmaMu(); + break; + default: + valTPCnsigma = -999, valTOFnsigma = -999; + break; + } + + if (track.sign() > 0) { + hPtNsigmaTPC[pid]->Fill(track.pt(), valTPCnsigma); + if (cfgStoreThnSparse) { + hThPtNsigmaTPC[pid]->Fill(track.pt(), valTPCnsigma, mult, flat); + } + } else { + hPtNsigmaTPC[pid + Npart]->Fill(track.pt(), valTPCnsigma); + if (cfgStoreThnSparse) { + hThPtNsigmaTPC[pid + Npart]->Fill(track.pt(), valTPCnsigma, mult, flat); + } + } + if (!track.hasTOF()) { + return; + } + if (track.sign() > 0) { + hPtNsigmaTOF[pid]->Fill(track.pt(), valTOFnsigma); + hPtNsigmaTPCTOF[pid]->Fill(valTPCnsigma, valTOFnsigma); + } else { + hPtNsigmaTOF[pid + Npart]->Fill(track.pt(), valTOFnsigma); + hPtNsigmaTPCTOF[pid + Npart]->Fill(valTPCnsigma, valTOFnsigma); + } + } + + template + inline void fillTrackQA(T const& track) + { + if constexpr (fillHist) { + flatchrg.fill(HIST(kPrefix) + HIST(kQA) + HIST("hPt"), track.pt()); + flatchrg.fill(HIST(kPrefix) + HIST(kQA) + HIST("hPhi"), track.phi()); + flatchrg.fill(HIST(kPrefix) + HIST(kQA) + HIST("hEta"), track.eta()); + flatchrg.fill(HIST(kPrefix) + HIST(kQA) + HIST("hDCAXYvsPt"), track.pt(), track.dcaXY()); + flatchrg.fill(HIST(kPrefix) + HIST(kQA) + HIST("hDCAZvsPt"), track.pt(), track.dcaZ()); + + if (track.hasTPC() && track.hasITS()) { + int nFindable = track.tpcNClsFindable(); + int nMinusFound = track.tpcNClsFindableMinusFound(); + int nCluster = nFindable - nMinusFound; + flatchrg.fill(HIST(kPrefix) + HIST(kQA) + HIST("hTPCCluster"), nCluster); + flatchrg.fill(HIST(kPrefix) + HIST(kQA) + HIST("hShTpcClvsPt"), track.pt(), track.tpcFractionSharedCls()); + flatchrg.fill(HIST(kPrefix) + HIST(kQA) + HIST("hCrossTPCvsPt"), track.pt(), track.tpcNClsFound()); + flatchrg.fill(HIST(kPrefix) + HIST(kQA) + HIST("tpcNClsShared"), track.tpcNClsShared()); + flatchrg.fill(HIST(kPrefix) + HIST(kQA) + HIST("tpcCrossedRows"), track.tpcNClsCrossedRows()); + flatchrg.fill(HIST(kPrefix) + HIST(kQA) + HIST("tpcCrossedRowsOverFindableCls"), track.tpcCrossedRowsOverFindableCls()); + flatchrg.fill(HIST(kPrefix) + HIST(kQA) + HIST("hChi2ITSTrkSegment"), track.itsChi2NCl()); + flatchrg.fill(HIST(kPrefix) + HIST(kQA) + HIST("itsNCls"), track.itsNCls()); + } + + flatchrg.fill(HIST(kPrefix) + HIST(kQA) + HIST("hTOFPvsBeta"), track.tpcInnerParam(), track.beta()); + if (track.beta() > trkSelOpt.cfgTOFBetaPion && track.beta() < trkSelOpt.cfgTOFBetaPion + 0.05) { // TOF pions + flatchrg.fill(HIST(kPrefix) + HIST(kQA) + HIST("hTOFpi"), track.eta(), track.tpcInnerParam(), track.tpcSignal()); + } + + if (std::abs(track.eta()) < trkSelOpt.cfgTrkEtaMax) { + if (isDCAxyWoCut(track)) { + flatchrg.fill(HIST(kPrefix) + HIST(kQA) + HIST("hPtVsWOcutDCA"), track.pt(), track.dcaXY()); + } + } + } + + flatchrg.fill(HIST(kPrefix) + HIST(kStatus[ft]) + HIST("hPVsPtEta"), track.tpcInnerParam(), track.pt(), track.eta()); + } + + template + inline void filldEdxQA(T const& track, C const& collision) + { + const float mult = getMult(collision); + const float flat = fillFlat(collision); + float dEdx = track.tpcSignal(); + if constexpr (fillHist) { + if (track.tpcInnerParam() >= trkSelOpt.cfgMomMIPMin && track.tpcInnerParam() <= trkSelOpt.cfgMomMIPMax) { + if (dEdx > trkSelOpt.cfgDeDxMIPMin && dEdx < trkSelOpt.cfgDeDxMIPMax) { // MIP pions + flatchrg.fill(HIST(kPrefix) + HIST(kStatCalib[ft]) + HIST(kCharge[chrg]) + HIST("hMIP"), mult, flat, track.eta(), dEdx); + flatchrg.fill(HIST(kPrefix) + HIST(kStatCalib[ft]) + HIST(kCharge[chrg]) + HIST("hMIPVsEta"), track.eta(), dEdx); + flatchrg.fill(HIST(kPrefix) + HIST(kStatCalib[ft]) + HIST(kCharge[chrg]) + HIST("pMIPVsEta"), track.eta(), dEdx); + flatchrg.fill(HIST(kPrefix) + HIST(kStatCalib[ft]) + HIST(kCharge[chrg]) + HIST("hMIPVsPhi"), track.phi(), dEdx); + flatchrg.fill(HIST(kPrefix) + HIST(kStatCalib[ft]) + HIST(kCharge[chrg]) + HIST("hMIPVsPhiVsEta"), track.phi(), dEdx, track.eta()); + flatchrg.fill(HIST(kPrefix) + HIST(kStatCalib[ft]) + HIST(kCharge[chrg]) + HIST("pMIPVsPhi"), track.phi(), dEdx); + } + if (dEdx > trkSelOpt.cfgDeDxMIPMax + 10. && dEdx < trkSelOpt.cfgDeDxMIPMax + 30.) { // Plateau electrons + if (std::abs(track.beta() - 1) < trkSelOpt.cfgBetaPlateuMax) { + flatchrg.fill(HIST(kPrefix) + HIST(kStatCalib[ft]) + HIST(kCharge[chrg]) + HIST("hPlateau"), mult, flat, track.eta(), dEdx); + flatchrg.fill(HIST(kPrefix) + HIST(kStatCalib[ft]) + HIST(kCharge[chrg]) + HIST("hPlateauVsEta"), track.eta(), dEdx); + flatchrg.fill(HIST(kPrefix) + HIST(kStatCalib[ft]) + HIST(kCharge[chrg]) + HIST("pPlateauVsEta"), track.eta(), dEdx); + flatchrg.fill(HIST(kPrefix) + HIST(kStatCalib[ft]) + HIST(kCharge[chrg]) + HIST("hPlateauVsPhi"), track.phi(), dEdx); + flatchrg.fill(HIST(kPrefix) + HIST(kStatCalib[ft]) + HIST(kCharge[chrg]) + HIST("hPlateauVsPhiVsEta"), track.phi(), dEdx, track.eta()); + flatchrg.fill(HIST(kPrefix) + HIST(kStatCalib[ft]) + HIST(kCharge[chrg]) + HIST("pPlateauVsPhi"), track.phi(), dEdx); + } + } + } + } + } + + template + bool isGoodEvent(C const& collision) + { + if constexpr (fillHist) { + flatchrg.fill(HIST("Events/hEvtSel"), evtSelAll); + } + if (evtSelOpt.cfgCustomTVX) { + if (!collision.selection_bit(aod::evsel::kIsTriggerTVX)) { + return false; + } + } else { + if (!collision.sel8()) { + return false; + } + } + if constexpr (fillHist) { + flatchrg.fill(HIST("Events/hEvtSel"), evtSelSel8); + } + if (evtSelOpt.cfgRemoveITSROFrameBorder && !collision.selection_bit(aod::evsel::kNoITSROFrameBorder)) { + return false; + } + if constexpr (fillHist) { + flatchrg.fill(HIST("Events/hEvtSel"), evtSelNoITSROFrameBorder); + } + if (evtSelOpt.cfgRemoveNoTimeFrameBorder && !collision.selection_bit(aod::evsel::kNoTimeFrameBorder)) { + return false; + } + if constexpr (fillHist) { + flatchrg.fill(HIST("Events/hEvtSel"), evtSelkNoTimeFrameBorder); + } + if (evtSelOpt.cfgRemoveNoSameBunchPileup && !collision.selection_bit(aod::evsel::kNoSameBunchPileup)) { + return false; + } + if constexpr (fillHist) { + flatchrg.fill(HIST("Events/hEvtSel"), evtSelkNoSameBunchPileup); + } + if (evtSelOpt.cfgRequireIsGoodZvtxFT0vsPV && !collision.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV)) { + return false; + } + if constexpr (fillHist) { + flatchrg.fill(HIST("Events/hEvtSel"), evtSelkIsGoodZvtxFT0vsPV); + } + if (evtSelOpt.cfgRequireIsVertexITSTPC && !collision.selection_bit(aod::evsel::kIsVertexITSTPC)) { + return false; + } + if constexpr (fillHist) { + flatchrg.fill(HIST("Events/hEvtSel"), evtSelkIsVertexITSTPC); + } + if (evtSelOpt.cfgRequirekIsVertexTOFmatched && !collision.selection_bit(aod::evsel::kIsVertexTOFmatched)) { + return false; + } + if constexpr (fillHist) { + flatchrg.fill(HIST("Events/hEvtSel"), evtSelkIsVertexTOFmatched); + } + if (std::abs(collision.posZ()) > evtSelOpt.cfgCutVtxZ) { + return false; + } + if constexpr (fillHist) { + flatchrg.fill(HIST("Events/hEvtSel"), evtSelVtxZ); + flatchrg.fill(HIST("Events/hVtxZ"), collision.posZ()); + } + if (evtSelOpt.cfgINELCut && !collision.isInelGt0()) { + return false; + } + if constexpr (fillHist) { + flatchrg.fill(HIST("Events/hEvtSel"), evtSelINELgt0); + } + return true; + } + + int getFV0IndexPhi(int i_ch) + { + int iRing = -1; + + if (i_ch >= kFV0IndexPhi[0] && i_ch < kFV0IndexPhi[1]) { + if (i_ch < kFV0IndexPhi[0] + 4) { + iRing = i_ch; + } else { + if (i_ch == kFV0IndexPhi[1] - 1) { + iRing = i_ch - 3; // 4; + } else if (i_ch == kFV0IndexPhi[1] - 2) { + iRing = i_ch - 1; // 5; + } else if (i_ch == kFV0IndexPhi[1] - 3) { + iRing = i_ch + 1; // 6; + } else if (i_ch == kFV0IndexPhi[1] - 4) { + iRing = i_ch + 3; // 7; + } + } + } else if (i_ch >= kFV0IndexPhi[1] && i_ch < kFV0IndexPhi[2]) { + if (i_ch < kFV0IndexPhi[2] - 4) { + iRing = i_ch; + } else { + if (i_ch == kFV0IndexPhi[2] - 1) { + iRing = i_ch - 3; // 12; + } else if (i_ch == kFV0IndexPhi[2] - 2) { + iRing = i_ch - 1; // 13; + } else if (i_ch == kFV0IndexPhi[2] - 3) { + iRing = i_ch + 1; // 14; + } else if (i_ch == kFV0IndexPhi[2] - 4) { + iRing = i_ch + 3; // 15; + } + } + } else if (i_ch >= kFV0IndexPhi[2] && i_ch < kFV0IndexPhi[3]) { + if (i_ch < kFV0IndexPhi[3] - 4) { + iRing = i_ch; + } else { + if (i_ch == kFV0IndexPhi[3] - 1) { + iRing = i_ch - 3; // 20; + } else if (i_ch == kFV0IndexPhi[3] - 2) { + iRing = i_ch - 1; // 21; + } else if (i_ch == kFV0IndexPhi[3] - 3) { + iRing = i_ch + 1; // 22; + } else if (i_ch == kFV0IndexPhi[3] - 4) { + iRing = i_ch + 3; // 23; + } + } + } else if (i_ch >= kFV0IndexPhi[3] && i_ch < kFV0IndexPhi[4]) { + if (i_ch < kFV0IndexPhi[3] + 4) { + iRing = i_ch; + } else { + if (i_ch == kFV0IndexPhi[4] - 5) { + iRing = i_ch - 3; // 28; + } else if (i_ch == kFV0IndexPhi[4] - 6) { + iRing = i_ch - 1; // 29; + } else if (i_ch == kFV0IndexPhi[4] - 7) { + iRing = i_ch + 1; // 30; + } else if (i_ch == kFV0IndexPhi[4] - 8) { + iRing = i_ch + 3; // 31; + } + } + } else if (i_ch == kFV0IndexPhi[4]) { + iRing = kFV0IndexPhi[4]; + } else if (i_ch == kFV0IndexPhi[4] + 8) { + iRing = i_ch - 7; // 33; + } else if (i_ch == kFV0IndexPhi[4] - 3) { + iRing = i_ch + 1; // 34; + } else if (i_ch == kFV0IndexPhi[4] + 5) { + iRing = i_ch - 6; // 35; + } else if (i_ch == kFV0IndexPhi[4] - 2) { + iRing = i_ch + 2; // 36; + } else if (i_ch == kFV0IndexPhi[4] + 6) { + iRing = i_ch - 5; // 37; + } else if (i_ch == kFV0IndexPhi[4] - 1) { + iRing = i_ch + 3; // 38; + } else if (i_ch == kFV0IndexPhi[4] + 7) { + iRing = i_ch - 4; // 39; + } else if (i_ch == kFV0IndexPhi[4] + 11) { + iRing = i_ch + 7; // 40; + } else if (i_ch == kFV0IndexPhi[4] + 3) { + iRing = i_ch + 2; // 41; + } else if (i_ch == kFV0IndexPhi[4] + 10) { + iRing = i_ch - 4; // 42; + } else if (i_ch == kFV0IndexPhi[4] + 1) { + iRing = i_ch + 5; // 43; + } else if (i_ch == kFV0IndexPhi[4] + 9) { + iRing = i_ch - 1; // 44; + } else if (i_ch == kFV0IndexPhi[4] + 1) { + iRing = i_ch + 8; // 45; + } else if (i_ch == kFV0IndexPhi[4] + 8) { + iRing = i_ch + 2; // 46; + } else if (i_ch == kFV0IndexPhi[4]) { + iRing = i_ch + 11; // 47; + } + return iRing; + } + + int getMagneticField(uint64_t timestamp) + { + o2::parameters::GRPMagField* grpmag = nullptr; + grpmag = ccdb->getForTimeStamp(ccdbConf.grpmagPath, timestamp); + if (!grpmag) { + return 0; + } + return grpmag->getNominalL3Field(); + } + + template + float getMult(C const& collision) + { + float val = -999.0; + switch (multEst) { + case MultE::kNoMult: + return val; + break; + case MultE::kMultFT0M: + return collision.centFT0M(); + break; + case MultE::kMultTPC: + if constexpr (!isMC) { + return collision.multTPC(); + } else { + LOG(fatal) << "No valid multiplicity estimator: " << multEst; + return val; + } + break; + default: + return collision.centFT0M(); + break; + } + } + + float getMultMC(MCColls::iterator const& collision) + { + return getMult(collision); + } + + template + float calcFlatenicity(std::array const& signals) + { + static_assert(S != 0); + + int entries = signals.size(); + float flat{-1}; + float mRho{0}; + for (int iCell = 0; iCell < entries; ++iCell) { + if (signals[iCell] > 0.) { + mRho += 1.0 * signals[iCell]; + } + } + // average activity per cell + mRho /= (1.0 * entries); + if (mRho <= 0) { + return -1; + } + // get sigma + float sRhoTmp{0}; + float sRho{0}; + for (int iCell = 0; iCell < entries; ++iCell) { + if (signals[iCell] > 0.) { + sRhoTmp += std::pow(1.0 * signals[iCell] - mRho, 2); + } + } + sRhoTmp /= (1.0 * entries * entries); + sRho = std::sqrt(sRhoTmp); + if (mRho > 0.) { + flat = sRho / mRho; + } else { + flat = -1; + } + return flat; + } + + template + float fillFlat(C const& collision) + { + rhoLatticeFV0.fill(0); + fv0AmplitudeWoCalib.fill(0); + bool isOkFV0OrA = false; + if (collision.has_foundFV0()) { + auto fv0 = collision.foundFV0(); + std::bitset<8> fV0Triggers = fv0.triggerMask(); + isOkFV0OrA = fV0Triggers[o2::fit::Triggers::bitA]; + if (isOkFV0OrA) { + for (std::size_t ich = 0; ich < fv0.channel().size(); ich++) { + float amplCh = fv0.amplitude()[ich]; + int chv0 = fv0.channel()[ich]; + int chv0phi = getFV0IndexPhi(chv0); + if constexpr (fillHist) { + flatchrg.fill(HIST("FV0/hFV0amp"), chv0, amplCh); + flatchrg.fill(HIST("FV0/pFV0amp"), chv0, amplCh); + if (applyCalibGain) { + flatchrg.fill(HIST("FV0/hFV0ampCorr"), chv0, amplCh / fv0AmplCorr[chv0]); + } + } + if (amplCh > 0.) { + if (applyCalibGain) { // equalize gain channel-by-channel + amplCh /= fv0AmplCorr[chv0]; + } + if (chv0phi > 0) { + fv0AmplitudeWoCalib[chv0phi] = amplCh; + if constexpr (fillHist) { + flatchrg.fill(HIST("FV0/hFV0AmplWCalib"), ich, fv0AmplitudeWoCalib[ich]); + } + if (chv0 < kInnerFV0) { + rhoLatticeFV0[chv0phi] += amplCh; + } else { // two channels per bin + rhoLatticeFV0[chv0phi] += amplCh / 2.; + } + if constexpr (fillHist) { + flatchrg.fill(HIST("FV0/hFV0AmplvsVtxzWoCalib"), collision.posZ(), rhoLatticeFV0[chv0phi]); + } + if (applyCalibVtx) { + rhoLatticeFV0[chv0phi] *= zVtxMap->GetBinContent(zVtxMap->GetXaxis()->FindBin(chv0phi), zVtxMap->GetYaxis()->FindBin(collision.posZ())); + if constexpr (fillHist) { + flatchrg.fill(HIST("FV0/hFV0AmplvsVtxzCalib"), collision.posZ(), rhoLatticeFV0[chv0phi]); + } + } + } + } + } + float flattenicityFV0 = calcFlatenicity(rhoLatticeFV0); + return 1. - flattenicityFV0; + } else { + return 9999; + } + } else { + return 9999; + } + } + + template + bool isDCAxyCut(T const& track) const + { + if (isCustomTracks.value) { + for (int i = 0; i < static_cast(TrackSelection::TrackCuts::kNCuts); i++) { + if (i == static_cast(TrackSelection::TrackCuts::kDCAxy)) { + continue; + } + if (!mTrackSelector.IsSelected(track, static_cast(i))) { + return false; + } + } + return (std::abs(track.dcaXY()) <= (maxDcaXYFactor.value * (0.0105f + 0.0350f / std::pow(track.pt(), 1.1f)))); + } + return track.isGlobalTrack(); + } + + template + bool isDCAxyWoCut(T const& track) const + { + if (isCustomTracks.value) { + for (int i = 0; i < static_cast(TrackSelection::TrackCuts::kNCuts); i++) { + if (i == static_cast(TrackSelection::TrackCuts::kDCAxy)) { + continue; + } + if (i == static_cast(TrackSelection::TrackCuts::kDCAz)) { + continue; + } + if (!mTrackSelector.IsSelected(track, static_cast(i))) { + return false; + } + } + return true; + } + return track.isGlobalTrackWoDCA(); + } + + Preslice perCol = aod::track::collisionId; + Preslice perColV0s = aod::v0::collisionId; + + template + void processData(C const& collisions, + MyPIDTracks const& tracks, + aod::V0Datas const& v0s, + aod::BCsWithTimestamps const& bcs) + { + for (const auto& collision : collisions) { + if (!isGoodEvent(collision)) { + continue; + } + auto tracksPerCollision = tracks.sliceBy(perCol, collision.globalIndex()); + auto v0sPerCollision = v0s.sliceBy(perColV0s, collision.globalIndex()); + v0sPerCollision.bindExternalIndices(&tracks); + filldEdx(tracksPerCollision, v0sPerCollision, collision, bcs); + if (cfgFillQAHisto) { + fillNsigma(tracksPerCollision, collision); + fillNsigma(tracksPerCollision, collision); + fillNsigma(tracksPerCollision, collision); + } + } + } + + void processFlat( + Colls const& collisions, + MyPIDTracks const& tracks, + aod::V0Datas const& v0s, + aod::BCsWithTimestamps const& bcs, + aod::FT0s const&, aod::FV0As const&) + { + processData(collisions, tracks, v0s, bcs); + } + PROCESS_SWITCH(FlattenictyPikp, processFlat, "process Flat data inclusive", true); + + template + float fillFlatMC(McPart const& mcparts) + { + int nFV0sectors = 0; + float minPhi = 0; + float maxPhi = 0; + float dPhi = 0; + + double etaMinFV0bins[kMaxRingsFV0] = {0.0}; + double etaMaxFV0bins[kMaxRingsFV0] = {0.0}; + for (int i = 0; i < kMaxRingsFV0; ++i) { + etaMaxFV0bins[i] = kEtaMaxFV0 - i * kDEtaFV0; + if (i < kMaxRingsFV0 - 1) { + etaMinFV0bins[i] = kEtaMaxFV0 - (i + 1) * kDEtaFV0; + } else { + etaMinFV0bins[i] = kEtaMinFV0; + } + } + + rhoLatticeFV0.fill(0); + std::vector vNch; + float nCharged{0}; + for (const auto& mcPart : mcparts) { + if (!isChrgParticle(mcPart.pdgCode())) { + continue; + } + auto etaMc = mcPart.eta(); + auto phiMc = mcPart.phi(); + + int isegment = 0; + for (int ieta = 0; ieta < kMaxRingsFV0; ieta++) { + + nFV0sectors = kNCellsFV0 / 6.; + if (ieta == kMaxRingsFV0 - 1) { + nFV0sectors = kNCellsFV0 / 3.; + } + + for (int iphi = 0; iphi < nFV0sectors; iphi++) { + + minPhi = iphi * TwoPI / nFV0sectors; + maxPhi = (iphi + 1) * TwoPI / nFV0sectors; + dPhi = std::abs(maxPhi - minPhi); + + if (etaMc >= etaMinFV0bins[ieta] && etaMc < etaMaxFV0bins[ieta] && phiMc >= minPhi && phiMc < maxPhi) { + rhoLatticeFV0[isegment] += 1. / std::abs(kDEtaFV0 * dPhi); + } + isegment++; + } + } + nCharged++; + } + + vNch.push_back(nCharged); + auto flatFV0 = calcFlatenicity(rhoLatticeFV0); + + if constexpr (fillHist) { + flatchrg.fill(HIST("ResponseGen"), vNch[0], 1. - flatFV0); + flatchrg.fill(HIST("h1flatencityFV0MCGen"), 1. - flatFV0); + } + vNch.clear(); + return 1. - flatFV0; + } + + template + void bookMcHist() + { + AxisSpec ptAxis{binOpt.axisPt, "#it{p}_{T} (GeV/#it{c})"}; + constexpr int kHistIdx = id + pidSgn * Npart; + auto kIdx = static_cast(id); + const std::string strID = Form("/%s/%s", (pidSgn == 0 && id < Npart) ? "pos" : "neg", Pid[kIdx]); + hPtEffRec[kHistIdx] = flatchrg.add("Tracks/hPtEffRec" + strID, " ; p_{T} (GeV/c)", HistType::kTH1D, {ptAxis}); + hPtEffGen[kHistIdx] = flatchrg.add("Tracks/hPtEffGen" + strID, " ; p_{T} (GeV/c)", HistType::kTH1D, {ptAxis}); + } + + template + void initEfficiency() + { + static_assert(pidSgn == 0 || pidSgn == 1); + static_assert(id > 0 || id < Npart); + constexpr int kIdx = id + pidSgn * Npart; + const TString partName = PidChrg[kIdx]; + THashList* lhash = new THashList(); + lhash->SetName(partName); + listEfficiency->Add(lhash); + + auto bookEff = [&](const TString eName, auto h) { + const TAxis* axis = h->GetXaxis(); + TString eTitle = h->GetTitle(); + eTitle.ReplaceAll("Numerator", "").Strip(TString::kBoth); + eTitle = Form("%s;%s;Efficiency", eTitle.Data(), axis->GetTitle()); + lhash->Add(new TEfficiency(eName, eTitle, axis->GetNbins(), axis->GetXbins()->GetArray())); + }; + + const int kHistIdx = id + pidSgn * Npart; + bookEff("hEffvsPt", hPtEffRec[kHistIdx]); + } + + template + void fillEfficiency() + { + static_assert(pidSgn == 0 || pidSgn == 1); + constexpr int kHistIdx = id + pidSgn * Npart; + const char* partName = PidChrg[kHistIdx]; + THashList* lhash = static_cast(listEfficiency->FindObject(partName)); + if (!lhash) { + LOG(warning) << "No efficiency object found for particle " << partName; + return; + } + + auto fillEff = [&](const TString eName, auto num, auto den) { + TEfficiency* eff = static_cast(lhash->FindObject(eName)); + if (!eff) { + LOG(warning) << "Cannot find TEfficiency " << eName; + return; + } + eff->SetTotalHistogram(*den, "f"); + eff->SetPassedHistogram(*num, "f"); + }; + fillEff("hEffvsPt", hPtEffRec[kHistIdx], hPtEffGen[kHistIdx]); + } + + template + void fillMCRecTrack(MyLabeledPIDTracks::iterator const& track, const float mult, const float flat) + { + static_assert(pidSgn == 0 || pidSgn == 1); + constexpr int kHistIdx = id + pidSgn * Npart; + const aod::McParticles::iterator& mcParticle = track.mcParticle(); + const CollsGen::iterator& collision = track.collision_as(); + + if (!isPID(mcParticle)) { + return; + } + flatchrg.fill(HIST("hPtOutNoEtaCut"), track.pt()); + if (std::abs(track.eta()) > trkSelOpt.cfgTrkEtaMax) { + return; + } + if (std::abs(mcParticle.y()) > trkSelOpt.cfgRapMax) { + return; + } + + if ((collision.has_mcCollision() && (mcParticle.mcCollisionId() != collision.mcCollisionId())) || !collision.has_mcCollision()) { + if (!mcParticle.isPhysicalPrimary()) { + if (mcParticle.getProcess() == kProcessIdWeak) { + hDCAxyBadCollWeak[kHistIdx]->Fill(track.pt(), track.dcaXY()); + } else { + hDCAxyBadCollMat[kHistIdx]->Fill(track.pt(), track.dcaXY()); + } + } else { + hDCAxyBadCollPrim[kHistIdx]->Fill(track.pt(), track.dcaXY()); + } + } + + if (!isDCAxyCut(track)) { + return; + } + flatchrg.fill(HIST("hPtVsDCAxyAll"), track.pt(), track.dcaXY()); + + if (selTPCtrack(track)) { + hPtEffRec[kHistIdx]->Fill(mcParticle.pt()); + } + + if (!mcParticle.isPhysicalPrimary()) { + if (mcParticle.getProcess() == kProcessIdWeak) { + hPtEffRecWeak[kHistIdx]->Fill(mult, flat, track.pt()); + hPtVsDCAxyWeak[kHistIdx]->Fill(track.pt(), track.dcaXY()); + flatchrg.fill(HIST("hPtVsDCAxyWeakAll"), track.pt(), track.dcaXY()); + } else { + hPtEffRecMat[kHistIdx]->Fill(mult, flat, track.pt()); + hPtVsDCAxyMat[kHistIdx]->Fill(track.pt(), track.dcaXY()); + flatchrg.fill(HIST("hPtVsDCAxyMatAll"), track.pt(), track.dcaXY()); + } + } else { + hPtEffRecPrim[kHistIdx]->Fill(mult, flat, track.pt()); + hPtVsDCAxyPrim[kHistIdx]->Fill(track.pt(), track.dcaXY()); + flatchrg.fill(HIST("hPtVsDCAxyPrimAll"), track.pt(), track.dcaXY()); + } + } + + template + void fillMCGen(aod::McParticles::iterator const& mcParticle, const float mult, const float flat) + { + static_assert(pidSgn == 0 || pidSgn == 1); + constexpr int kHistIdx = id + pidSgn * Npart; + + if (!isPID(mcParticle)) { + return; + } + + if constexpr (recoEvt) { + hPtGenRecEvt[kHistIdx]->Fill(mcParticle.pt()); + if (mcParticle.isPhysicalPrimary()) { + hPtGenPrimRecEvt[kHistIdx]->Fill(mcParticle.pt()); + } + return; + } + + if (!mcParticle.isPhysicalPrimary()) { + if (mcParticle.getProcess() == kProcessIdWeak) { + hPtEffGenWeak[kHistIdx]->Fill(mult, flat, mcParticle.pt()); + } else { + hPtEffGenMat[kHistIdx]->Fill(mult, flat, mcParticle.pt()); + } + } else { + hPtEffGenPrim[kHistIdx]->Fill(mult, flat, mcParticle.pt()); + hPtEffGen[kHistIdx]->Fill(mcParticle.pt()); + } + } + + void processSgnLoss(MCColls::iterator const& mcCollision, + CollsGenSgn const& collisions, + aod::FV0As const& /*fv0s*/, + aod::McParticles const& particles) + { + float flat; + float mult; + if (flatSelOpt.useFlatData) { + float flatRec = 999.0; + float multRec = 999.0; + for (const auto& collision : collisions) { + multRec = getMult(collision); + flatRec = fillFlat(collision); + } + flat = flatRec; + mult = multRec; + flatchrg.fill(HIST("hFlatMCGenRecColl"), flatRec); + } else { + float flatGen = fillFlatMC(particles); + flat = flatGen; + flatchrg.fill(HIST("hFlatMCGen"), flatGen); + float multGen = getMultMC(mcCollision); + mult = multGen; + } + + // Evt loss den + flatchrg.fill(HIST("hEvtMcGen"), 0.5); + if (std::abs(mcCollision.posZ()) > evtSelOpt.cfgCutVtxZ) { + return; + } + flatchrg.fill(HIST("hEvtMcGen"), 1.5); + + bool isINELgt0mc = false; + if (pwglf::isINELgtNmc(particles, 0, pdg)) { + isINELgt0mc = true; + flatchrg.fill(HIST("hEvtMcGen"), 2.5); + flatchrg.fill(HIST("hFlatGenINELgt0"), flat); + } + + // Sgn loss den + for (const auto& particle : particles) { + if (!particle.isPhysicalPrimary()) { + continue; + } + if (std::abs(particle.y()) > trkSelOpt.cfgRapMax) { + continue; + } + static_for<0, 5>([&](auto i) { + constexpr int kIdx = i.value; + if (particle.pdgCode() == PidSgn[kIdx]) { + flatchrg.fill(HIST(kPrefix) + HIST(kSpecies[kIdx]) + HIST(kPtGenPrimSgn), mult, flat, particle.pt()); + if (isINELgt0mc) { + flatchrg.fill(HIST(kPrefix) + HIST(kSpecies[kIdx]) + HIST(kPtGenPrimSgnINEL), mult, flat, particle.pt()); + } + } + }); + } + + int nRecCollINEL = 0; + int nRecCollINELgt0 = 0; + for (const auto& collision : collisions) { + // Evt split num + flatchrg.fill(HIST("hEvtMCRec"), 0.5); + if (!isGoodEvent(collision)) { + continue; + } + flatchrg.fill(HIST("hEvtMCRec"), 1.5); + + nRecCollINEL++; + + if (collision.isInelGt0() && isINELgt0mc) { + flatchrg.fill(HIST("hEvtMCRec"), 2.5); + nRecCollINELgt0++; + } + // Sgn split num + for (const auto& particle : particles) { + if (!particle.isPhysicalPrimary()) { + continue; + } + if (std::abs(particle.y()) > trkSelOpt.cfgRapMax) { + continue; + } + static_for<0, 5>([&](auto i) { + constexpr int kIdx = i.value; + if (particle.pdgCode() == PidSgn[kIdx]) { + flatchrg.fill(HIST(kPrefix) + HIST(kSpecies[kIdx]) + HIST(kPtRecCollPrimSgn), mult, flat, particle.pt()); + if (nRecCollINELgt0) { + flatchrg.fill(HIST(kPrefix) + HIST(kSpecies[kIdx]) + HIST(kPtRecCollPrimSgnINEL), mult, flat, particle.pt()); + } + } + }); + } + } + + if (nRecCollINEL < 1) { + return; + } + // Evt loss num + flatchrg.fill(HIST("hEvtMcGenRecColl"), 0.5); + if (nRecCollINELgt0 > 0) { + flatchrg.fill(HIST("hEvtMcGenRecColl"), 1.5); + } + + // Sgn loss num + for (const auto& particle : particles) { + if (!particle.isPhysicalPrimary()) { + continue; + } + if (std::abs(particle.y()) > trkSelOpt.cfgRapMax) { + continue; + } + static_for<0, 5>([&](auto i) { + constexpr int kIdx = i.value; + if (particle.pdgCode() == PidSgn[kIdx]) { + flatchrg.fill(HIST(kPrefix) + HIST(kSpecies[kIdx]) + HIST(kPtGenRecCollPrimSgn), mult, flat, particle.pt()); + if (nRecCollINELgt0) { + flatchrg.fill(HIST(kPrefix) + HIST(kSpecies[kIdx]) + HIST(kPtGenRecCollPrimSgnINEL), mult, flat, particle.pt()); + } + } + }); + } + } + PROCESS_SWITCH(FlattenictyPikp, processSgnLoss, "process to calcuate signal/event lossses", false); + + // using Particles = soa::Filtered; + // expressions::Filter primaries = (aod::mcparticle::flags & (uint8_t)o2::aod::mcparticle::enums::PhysicalPrimary) == (uint8_t)o2::aod::mcparticle::enums::PhysicalPrimary; + + void processMCclosure(Colls::iterator const& collision, + MyPIDTracks const& tracks, + MyLabeledTracks const& mcTrackLabels, + aod::McParticles const& particles, + // Particles const& particles, + aod::FV0As const& /*fv0s*/, + aod::BCsWithTimestamps const& /*bcs*/) + { + const float multRec = getMult(collision); + const float flatRec = fillFlat(collision); + for (const auto& track : tracks) { + if (!track.has_collision()) { + continue; + } + const auto& coll = track.collision_as(); + auto bc = coll.template bc_as(); + auto magField = (ccdbConf.cfgMagField == 0) ? getMagneticField(bc.timestamp()) : ccdbConf.cfgMagField; + + if (!isGoodEvent(coll)) { + continue; + } + if (!isGoodTrack(track, magField)) { + continue; + } + if (!isDCAxyCut(track)) { + continue; + } + const auto& mcLabel = mcTrackLabels.iteratorAt(track.globalIndex()); + const auto& mcParticle = particles.iteratorAt(mcLabel.mcParticleId()); + + static_for<0, 4>([&](auto i) { + constexpr int kIdx = i.value; + if ((std::abs(o2::aod::pidutils::tpcNSigma(track)) < trkSelOpt.cfgNsigmaMax) && std::abs(track.rapidity(o2::track::PID::getMass(kIdx))) <= trkSelOpt.cfgRapMax) { + if (std::fabs(mcParticle.pdgCode()) == PDGs[kIdx]) { + flatchrg.fill(HIST(kPrefix) + HIST(kSpeciesAll[kIdx]) + HIST(kPtMCclosurePrim), multRec, flatRec, track.pt()); + } + } + }); + } + } + PROCESS_SWITCH(FlattenictyPikp, processMCclosure, "process MC closure test", false); + + Preslice perCollTrk = aod::track::collisionId; + PresliceUnsorted perCollMcLabel = aod::mccollisionlabel::mcCollisionId; + Preslice perCollMcPart = aod::mcparticle::mcCollisionId; + + void processMC(MCColls const& mcCollisions, + CollsGen const& collisions, + MyLabeledPIDTracks const& tracks, + aod::McParticles const& mcparticles) + { + flatchrg.fill(HIST("hEvtGenRec"), 1.f, mcCollisions.size()); + flatchrg.fill(HIST("hEvtGenRec"), 2.f, collisions.size()); + + for (const auto& mcCollision : mcCollisions) { + if (mcCollision.isInelGt0()) { + flatchrg.fill(HIST("hEvtGenRec"), 3.f); + } + flatchrg.fill(HIST("hEvtMcGenColls"), 1); + const auto groupedColls = collisions.sliceBy(perCollMcLabel, mcCollision.globalIndex()); + const auto groupedParts = mcparticles.sliceBy(perCollMcPart, mcCollision.globalIndex()); + const float flatMC = fillFlatMC(groupedParts); + const float multMC = getMultMC(mcCollision); + if (groupedColls.size() < 1) { // if MC events have no rec collisions + continue; + } + flatchrg.fill(HIST("hEvtMcGenColls"), 2); + for (const auto& collision : groupedColls) { + flatchrg.fill(HIST("hEvtMcGenColls"), 3); + if (!isGoodEvent(collision)) { + continue; + } + flatchrg.fill(HIST("hEvtMcGenColls"), 4); + const auto groupedTrks = tracks.sliceBy(perCollTrk, collision.globalIndex()); + for (const auto& track : groupedTrks) { + if (!isDCAxyWoCut(track)) { + continue; + } + if (!track.has_mcParticle()) { + flatchrg.fill(HIST("PtOutFakes"), track.pt()); + continue; + } + const auto& mcParticle = track.mcParticle(); + if (std::abs(mcParticle.y()) > trkSelOpt.cfgRapMax) { + continue; + } + if (!track.has_collision()) { + continue; + } + static_for<0, 1>([&](auto pidSgn) { + fillMCRecTrack(track, multMC, flatMC); + fillMCRecTrack(track, multMC, flatMC); + fillMCRecTrack(track, multMC, flatMC); + }); + } + + if (std::abs(mcCollision.posZ()) > evtSelOpt.cfgCutVtxZ) { + continue; + } + + if (evtSelOpt.cfgINELCut.value) { + if (!o2::pwglf::isINELgt0mc(groupedParts, pdg)) { + continue; + } + } + + for (const auto& particle : groupedParts) { + if (std::abs(particle.y()) > trkSelOpt.cfgRapMax) { + continue; + } + static_for<0, 1>([&](auto pidSgn) { + fillMCGen(particle, multMC, flatMC); + fillMCGen(particle, multMC, flatMC); + fillMCGen(particle, multMC, flatMC); + }); + } + } // reco collisions + + if (evtSelOpt.cfgINELCut.value) { + if (!o2::pwglf::isINELgt0mc(groupedParts, pdg)) { + continue; + } + } + + for (const auto& mcParticle : groupedParts) { + if (std::abs(mcParticle.y()) > trkSelOpt.cfgRapMax) { + continue; + } + static_for<0, 1>([&](auto pidSgn) { + fillMCGen(mcParticle, multMC, flatMC); + fillMCGen(mcParticle, multMC, flatMC); + fillMCGen(mcParticle, multMC, flatMC); + }); + } + + static_for<0, 1>([&](auto pidSgn) { + fillEfficiency(); + fillEfficiency(); + fillEfficiency(); + }); + + } // gen collisions + } + PROCESS_SWITCH(FlattenictyPikp, processMC, "process MC", false); + + template + ObjType* getForTsOrRun(std::string const& fullPath, int64_t timestamp, int runNumber) + { + if (cfgUseCcdbForRun) { + return ccdb->getForRun(fullPath, runNumber); + } else { + return ccdb->getForTimeStamp(fullPath, timestamp); + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} From 910f19240bd6a925926a26005bead796d285b497 Mon Sep 17 00:00:00 2001 From: yuanzhe <90246048+wang-yuanzhe@users.noreply.github.com> Date: Sat, 28 Jun 2025 04:54:06 +0200 Subject: [PATCH 248/871] [PWGLF] Update datamodel of hyphe4s analysis (#11811) --- PWGLF/DataModel/LFHyperhelium4sigmaTables.h | 15 +++- .../Nuspex/hyperhelium4sigmaRecoTask.cxx | 71 ++++++++++++++----- 2 files changed, 67 insertions(+), 19 deletions(-) diff --git a/PWGLF/DataModel/LFHyperhelium4sigmaTables.h b/PWGLF/DataModel/LFHyperhelium4sigmaTables.h index 5d50a007f66..4e6d28085a3 100644 --- a/PWGLF/DataModel/LFHyperhelium4sigmaTables.h +++ b/PWGLF/DataModel/LFHyperhelium4sigmaTables.h @@ -30,6 +30,9 @@ DECLARE_SOA_COLUMN(ZPrimVtx, zPrimVtx, float); // Pri DECLARE_SOA_COLUMN(XDecVtx, xDecVtx, float); // Decay vertex of the candidate (x direction) DECLARE_SOA_COLUMN(YDecVtx, yDecVtx, float); // Decay vertex of the candidate (y direction) DECLARE_SOA_COLUMN(ZDecVtx, zDecVtx, float); // Decay vertex of the candidate (z direction) +DECLARE_SOA_COLUMN(XMoth, xMoth, float); // X of the mother track at the radii of ITS layer which has the outermost update +DECLARE_SOA_COLUMN(YMoth, yMoth, float); // Y of the mother track at the radii of ITS layer which has the outermost update +DECLARE_SOA_COLUMN(ZMoth, zMoth, float); // Z of the mother track at the radii of ITS layer which has the outermost update DECLARE_SOA_COLUMN(PxMoth, pxMoth, float); //! Px of the mother track at the decay vertex DECLARE_SOA_COLUMN(PyMoth, pyMoth, float); //! Py of the mother track at the decay vertex DECLARE_SOA_COLUMN(PzMoth, pzMoth, float); //! Pz of the mother track at the decay vertex @@ -56,6 +59,9 @@ DECLARE_SOA_COLUMN(TrueZDecVtx, trueZDecVtx, float); // true z decay DECLARE_SOA_COLUMN(GenPxMoth, genPxMoth, float); // Generated px of the mother track DECLARE_SOA_COLUMN(GenPyMoth, genPyMoth, float); // Generated py of the mother track DECLARE_SOA_COLUMN(GenPzMoth, genPzMoth, float); // Generated pz of the mother track +DECLARE_SOA_COLUMN(TruePxMoth, truePxMoth, float); // true px of the mother track at the decay vertex +DECLARE_SOA_COLUMN(TruePyMoth, truePyMoth, float); // true py of the mother track at the decay vertex +DECLARE_SOA_COLUMN(TruePzMoth, truePzMoth, float); // true pz of the mother track at the decay vertex DECLARE_SOA_COLUMN(GenPxAlpha, genPxAlpha, float); // true px of the daughter alpha track DECLARE_SOA_COLUMN(GenPyAlpha, genPyAlpha, float); // true py of the daughter alpha track DECLARE_SOA_COLUMN(GenPzAlpha, genPzAlpha, float); // true pz of the daughter alpha track @@ -68,7 +74,9 @@ DECLARE_SOA_TABLE(He4S2BCands, "AOD", "HE4S2BCANDS", o2::soa::Index<>, he4scand::XPrimVtx, he4scand::YPrimVtx, he4scand::ZPrimVtx, he4scand::XDecVtx, he4scand::YDecVtx, he4scand::ZDecVtx, - he4scand::IsMatter, he4scand::PxMoth, he4scand::PyMoth, he4scand::PzMoth, + he4scand::IsMatter, + he4scand::XMoth, he4scand::YMoth, he4scand::ZMoth, + he4scand::PxMoth, he4scand::PyMoth, he4scand::PzMoth, he4scand::PxAlpha, he4scand::PyAlpha, he4scand::PzAlpha, he4scand::DcaMothPv, he4scand::DcaAlphaPv, he4scand::DcaKinkTopo, he4scand::ItsChi2Moth, he4scand::ItsClusterSizesMoth, he4scand::ItsClusterSizesAlpha, @@ -78,7 +86,9 @@ DECLARE_SOA_TABLE(MCHe4S2BCands, "AOD", "MCHE4S2BCANDS", o2::soa::Index<>, he4scand::XPrimVtx, he4scand::YPrimVtx, he4scand::ZPrimVtx, he4scand::XDecVtx, he4scand::YDecVtx, he4scand::ZDecVtx, - he4scand::IsMatter, he4scand::PxMoth, he4scand::PyMoth, he4scand::PzMoth, + he4scand::IsMatter, + he4scand::XMoth, he4scand::YMoth, he4scand::ZMoth, + he4scand::PxMoth, he4scand::PyMoth, he4scand::PzMoth, he4scand::PxAlpha, he4scand::PyAlpha, he4scand::PzAlpha, he4scand::DcaMothPv, he4scand::DcaAlphaPv, he4scand::DcaKinkTopo, he4scand::ItsChi2Moth, he4scand::ItsClusterSizesMoth, he4scand::ItsClusterSizesAlpha, @@ -86,6 +96,7 @@ DECLARE_SOA_TABLE(MCHe4S2BCands, "AOD", "MCHE4S2BCANDS", he4scand::IsSignal, he4scand::IsSignalReco, he4scand::IsCollReco, he4scand::IsSurvEvSelection, he4scand::TrueXDecVtx, he4scand::TrueYDecVtx, he4scand::TrueZDecVtx, he4scand::GenPxMoth, he4scand::GenPyMoth, he4scand::GenPzMoth, + he4scand::TruePxMoth, he4scand::TruePyMoth, he4scand::TruePzMoth, he4scand::GenPxAlpha, he4scand::GenPyAlpha, he4scand::GenPzAlpha, he4scand::IsMothReco, he4scand::RecoPtMoth, he4scand::RecoPzMoth); diff --git a/PWGLF/TableProducer/Nuspex/hyperhelium4sigmaRecoTask.cxx b/PWGLF/TableProducer/Nuspex/hyperhelium4sigmaRecoTask.cxx index 3e35c99e2df..92859fe0ae7 100644 --- a/PWGLF/TableProducer/Nuspex/hyperhelium4sigmaRecoTask.cxx +++ b/PWGLF/TableProducer/Nuspex/hyperhelium4sigmaRecoTask.cxx @@ -68,7 +68,7 @@ enum DaughterType { namespace { -// constexpr std::array LayerRadii{2.33959f, 3.14076f, 3.91924f, 19.6213f, 24.5597f, 34.388f, 39.3329f}; +constexpr std::array LayerRadii{2.33959f, 3.14076f, 3.91924f, 19.6213f, 24.5597f, 34.388f, 39.3329f}; constexpr int kITSLayers = 7; constexpr int kITSInnerBarrelLayers = 3; // constexpr int kITSOuterBarrelLayers = 4; @@ -231,6 +231,7 @@ struct Hyphe4sCandidate { std::array primVtx = {0.0f, 0.0f, 0.0f}; std::array decVtx = {0.0f, 0.0f, 0.0f}; + std::array lastPosMoth = {0.0f, 0.0f, 0.0f}; // last position of mother track at the radii of ITS layer which has the outermost update std::array momMoth = {0.0f, 0.0f, 0.0f}; std::array momDaug = {0.0f, 0.0f, 0.0f}; @@ -251,7 +252,8 @@ struct Hyphe4sCandidate { bool isSurvEvSelection = false; std::array trueDecVtx = {0.0f, 0.0f, 0.0f}; - std::array gMomMoth = {0.0f, 0.0f, 0.0f}; + std::array gMomMoth = {0.0f, 0.0f, 0.0f}; // generated mother momentum + std::array trueMomMoth = {0.0f, 0.0f, 0.0f}; // true mother momentum at decay vertex std::array gMomDau = {0.0f, 0.0f, 0.0f}; bool isMothReco = false; @@ -322,8 +324,8 @@ struct Hyperhelium4sigmaRecoTask { registry.add("h2TrueMotherDiffPyVsRecSVR", ";Reconstruced SV R (cm);#Delta #it{p}_{T} (GeV/#it{c});", HistType::kTH2F, {radiusAxis, diffPyAxis}); registry.add("h2TrueMotherDiffPtVsRecSVR", ";Reconstruced SV R (cm);#Delta #it{p}_{T} (GeV/#it{c});", HistType::kTH2F, {radiusAxis, diffPtAxis}); registry.add("h2TrueMotherDiffPzVsRecSVR", ";Reconstruced SV R (cm);#Delta #it{p}_{z} (GeV/#it{c});", HistType::kTH2F, {radiusAxis, diffPzAxis}); - registry.add("h2TrueMotherDiffTglVsRecSVR", ";Reconstruced SV R (cm);#Delta tan#lambda;", HistType::kTH2F, {radiusAxis, {200, -1.f, 1.f}}); - registry.add("h2TrueMotherDiffEtaVsRecSVR", ";Reconstruced SV R (cm);#Delta #eta;", HistType::kTH2F, {radiusAxis, {200, -1.f, 1.f}}); + registry.add("h2TrueMotherDiffTglVsRecSVR", ";Reconstruced SV R (cm);#Delta tan#lambda;", HistType::kTH2F, {radiusAxis, {200, -0.1, 0.1}}); + registry.add("h2TrueMotherDiffEtaVsRecSVR", ";Reconstruced SV R (cm);#Delta #eta;", HistType::kTH2F, {radiusAxis, {200, -0.1, 0.1}}); registry.add("hDiffDauPx", ";#Delta p_{x} (GeV/#it{c}); ", HistType::kTH1D, {{200, -10, 10}}); registry.add("hDiffDauPy", ";#Delta p_{y} (GeV/#it{c}); ", HistType::kTH1D, {{200, -10, 10}}); registry.add("hDiffDauPz", ";#Delta p_{z} (GeV/#it{c}); ", HistType::kTH1D, {{200, -10, 10}}); @@ -394,6 +396,22 @@ struct Hyperhelium4sigmaRecoTask { hyphe4sCand.itsClusterSizeDau = trackDau.itsClusterSizes(); hyphe4sCand.nSigmaTPCDau = trackDau.tpcNSigmaAl(); hyphe4sCand.nSigmaITSDau = itsResponse.nSigmaITS(trackDau); + + int lastLayerMoth = 0; + for (int i = 6; i >= 0; i--) { + if (trackMoth.itsClusterMap() & (1 << i)) { + lastLayerMoth = i; + break; + } + } + auto trackparMother = getTrackParCov(trackMoth); + o2::base::Propagator::Instance()->PropagateToXBxByBz(trackparMother, LayerRadii[lastLayerMoth]); + std::array vecLab{0.f}; + if (trackparMother.getPosDirGlo(vecLab)) { + hyphe4sCand.lastPosMoth[0] = vecLab[0]; + hyphe4sCand.lastPosMoth[1] = vecLab[1]; + hyphe4sCand.lastPosMoth[2] = vecLab[2]; + } } template @@ -407,7 +425,7 @@ struct Hyperhelium4sigmaRecoTask { } template - void fillCandidateMCInfo(Hyphe4sCandidate& hyphe4sCand, TMCParticle const& mcMothTrack, TMCParticle const& mcDauTrack) + void fillCandidateMCInfo(Hyphe4sCandidate& hyphe4sCand, TMCParticle const& mcMothTrack, TMCParticle const& mcDauTrack, TMCParticle const& mcNeutDauTrack) { hyphe4sCand.trueDecVtx[0] = mcDauTrack.vx(); hyphe4sCand.trueDecVtx[1] = mcDauTrack.vy(); @@ -415,12 +433,15 @@ struct Hyperhelium4sigmaRecoTask { hyphe4sCand.gMomMoth[0] = mcMothTrack.px(); hyphe4sCand.gMomMoth[1] = mcMothTrack.py(); hyphe4sCand.gMomMoth[2] = mcMothTrack.pz(); + hyphe4sCand.trueMomMoth[0] = mcDauTrack.px() + mcNeutDauTrack.px(); + hyphe4sCand.trueMomMoth[1] = mcDauTrack.py() + mcNeutDauTrack.py(); + hyphe4sCand.trueMomMoth[2] = mcDauTrack.pz() + mcNeutDauTrack.pz(); hyphe4sCand.gMomDau[0] = mcDauTrack.px(); hyphe4sCand.gMomDau[1] = mcDauTrack.py(); hyphe4sCand.gMomDau[2] = mcDauTrack.pz(); } - void processData(CollisionsFull const& collisions, aod::KinkCands const& KinkCands, FullTracksExtIU const&) + void processData(CollisionsFull const& collisions, aod::KinkCands const& KinkCands, FullTracksExtIU const&, aod::BCs const&) { for (const auto& collision : collisions) { registry.fill(HIST("hEventCounter"), 0); @@ -448,6 +469,8 @@ struct Hyperhelium4sigmaRecoTask { registry.fill(HIST("h2MassHyperhelium4sigmaPt"), kinkCand.mothSign() * kinkCand.ptMoth(), invMass); registry.fill(HIST("h2NSigmaAlPt"), kinkCand.mothSign() * kinkCand.ptDaug(), dauTrack.tpcNSigmaAl()); + auto bc = collision.bc_as(); + initCCDB(bc); auto motherTrack = kinkCand.trackMoth_as(); Hyphe4sCandidate hyphe4sCand; fillCandidate(hyphe4sCand, collision, kinkCand, motherTrack, dauTrack); @@ -455,7 +478,9 @@ struct Hyperhelium4sigmaRecoTask { outputDataTable( hyphe4sCand.primVtx[0], hyphe4sCand.primVtx[1], hyphe4sCand.primVtx[2], hyphe4sCand.decVtx[0], hyphe4sCand.decVtx[1], hyphe4sCand.decVtx[2], - hyphe4sCand.isMatter, hyphe4sCand.momMoth[0], hyphe4sCand.momMoth[1], hyphe4sCand.momMoth[2], + hyphe4sCand.isMatter, + hyphe4sCand.lastPosMoth[0], hyphe4sCand.lastPosMoth[1], hyphe4sCand.lastPosMoth[2], + hyphe4sCand.momMoth[0], hyphe4sCand.momMoth[1], hyphe4sCand.momMoth[2], hyphe4sCand.momDaug[0], hyphe4sCand.momDaug[1], hyphe4sCand.momDaug[2], hyphe4sCand.dcaXYMothPv, hyphe4sCand.dcaXYDauPv, hyphe4sCand.dcaKinkTopo, hyphe4sCand.chi2ITSMoth, hyphe4sCand.itsClusterSizeMoth, hyphe4sCand.itsClusterSizeDau, @@ -524,6 +549,8 @@ struct Hyperhelium4sigmaRecoTask { registry.fill(HIST("h2MassHyperhelium4sigmaPt"), kinkCand.mothSign() * kinkCand.ptMoth(), invMass); registry.fill(HIST("h2NSigmaAlPt"), kinkCand.mothSign() * kinkCand.ptDaug(), dauTrack.tpcNSigmaAl()); + auto bc = collision.bc_as(); + initCCDB(bc); Hyphe4sCandidate hyphe4sCand; fillCandidate(hyphe4sCand, collision, kinkCand, motherTrack, dauTrack); @@ -531,6 +558,7 @@ struct Hyperhelium4sigmaRecoTask { if (isTrueSignal) { auto mcMotherTrack = motherTrack.mcParticle_as(); auto mcDauTrack = dauTrack.mcParticle_as(); + auto mcNeutTrack = particlesMC.rawIteratorAt(dauIDList[2]); float posDecVtx[3] = {kinkCand.xDecVtx() + collision.posX(), kinkCand.yDecVtx() + collision.posY(), kinkCand.zDecVtx() + collision.posZ()}; float recSVR = std::sqrt(posDecVtx[0] * posDecVtx[0] + posDecVtx[1] * posDecVtx[1]); registry.fill(HIST("hDiffSVx"), posDecVtx[0] - mcDauTrack.vx()); @@ -551,11 +579,9 @@ struct Hyperhelium4sigmaRecoTask { hyphe4sCand.isSignalReco = true; hyphe4sCand.isCollReco = true; hyphe4sCand.isSurvEvSelection = true; - fillCandidateMCInfo(hyphe4sCand, mcMotherTrack, mcDauTrack); + fillCandidateMCInfo(hyphe4sCand, mcMotherTrack, mcDauTrack, mcNeutTrack); mcHe4sIndices.push_back(mcMotherTrack.globalIndex()); - auto bc = collision.bc_as(); - initCCDB(bc); std::array dcaInfo; auto mcMotherTrackPar = getTrackParFromMC(mcMotherTrack); o2::base::Propagator::Instance()->propagateToDCABxByBz({posDecVtx[0], posDecVtx[1], posDecVtx[2]}, mcMotherTrackPar, 2.f, matCorr, &dcaInfo); @@ -591,7 +617,9 @@ struct Hyperhelium4sigmaRecoTask { outputMCTable( hyphe4sCand.primVtx[0], hyphe4sCand.primVtx[1], hyphe4sCand.primVtx[2], hyphe4sCand.decVtx[0], hyphe4sCand.decVtx[1], hyphe4sCand.decVtx[2], - hyphe4sCand.isMatter, hyphe4sCand.momMoth[0], hyphe4sCand.momMoth[1], hyphe4sCand.momMoth[2], + hyphe4sCand.isMatter, + hyphe4sCand.lastPosMoth[0], hyphe4sCand.lastPosMoth[1], hyphe4sCand.lastPosMoth[2], + hyphe4sCand.momMoth[0], hyphe4sCand.momMoth[1], hyphe4sCand.momMoth[2], hyphe4sCand.momDaug[0], hyphe4sCand.momDaug[1], hyphe4sCand.momDaug[2], hyphe4sCand.dcaXYMothPv, hyphe4sCand.dcaXYDauPv, hyphe4sCand.dcaKinkTopo, hyphe4sCand.chi2ITSMoth, hyphe4sCand.itsClusterSizeMoth, hyphe4sCand.itsClusterSizeDau, @@ -599,6 +627,7 @@ struct Hyperhelium4sigmaRecoTask { hyphe4sCand.isSignal, hyphe4sCand.isSignalReco, hyphe4sCand.isCollReco, hyphe4sCand.isSurvEvSelection, hyphe4sCand.trueDecVtx[0], hyphe4sCand.trueDecVtx[1], hyphe4sCand.trueDecVtx[2], hyphe4sCand.gMomMoth[0], hyphe4sCand.gMomMoth[1], hyphe4sCand.gMomMoth[2], + hyphe4sCand.trueMomMoth[0], hyphe4sCand.trueMomMoth[1], hyphe4sCand.trueMomMoth[2], hyphe4sCand.gMomDau[0], hyphe4sCand.gMomDau[1], hyphe4sCand.gMomDau[2], hyphe4sCand.isMothReco, hyphe4sCand.ptMoth, hyphe4sCand.pzMoth); } @@ -615,7 +644,8 @@ struct Hyperhelium4sigmaRecoTask { Hyphe4sCandidate hyphe4sCand; auto mcDauTrack = particlesMC.rawIteratorAt(dauIDList[0]); - fillCandidateMCInfo(hyphe4sCand, mcparticle, mcDauTrack); + auto mcNeutTrack = particlesMC.rawIteratorAt(dauIDList[2]); + fillCandidateMCInfo(hyphe4sCand, mcparticle, mcDauTrack, mcNeutTrack); if (mcPartIndices[mcparticle.globalIndex()] != -1) { auto mothTrack = tracks.rawIteratorAt(mcPartIndices[mcparticle.globalIndex()]); @@ -625,7 +655,9 @@ struct Hyperhelium4sigmaRecoTask { outputMCTable( -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, + -1, + -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, @@ -633,6 +665,7 @@ struct Hyperhelium4sigmaRecoTask { true, false, isReconstructedMCCollisions[mcparticle.mcCollisionId()], isSelectedMCCollisions[mcparticle.mcCollisionId()], hyphe4sCand.trueDecVtx[0], hyphe4sCand.trueDecVtx[1], hyphe4sCand.trueDecVtx[2], hyphe4sCand.gMomMoth[0], hyphe4sCand.gMomMoth[1], hyphe4sCand.gMomMoth[2], + hyphe4sCand.trueMomMoth[0], hyphe4sCand.trueMomMoth[1], hyphe4sCand.trueMomMoth[2], hyphe4sCand.gMomDau[0], hyphe4sCand.gMomDau[1], hyphe4sCand.gMomDau[2], hyphe4sCand.isMothReco, hyphe4sCand.ptMoth, hyphe4sCand.pzMoth); } @@ -731,6 +764,7 @@ struct Hyperhelium4sigmaQa { hDauTPCNSigma[kDauTriton] = recoQAHist.add("hDauTritonTPCNSigma", "", HistType::kTH2F, {rigidityAxis, nsigmaAxis}); hDauTPCNSigma[kDauProton] = recoQAHist.add("hDauProtonTPCNSigma", "", HistType::kTH2F, {rigidityAxis, nsigmaAxis}); hDauTPCNSigma[kDauChargedPion] = recoQAHist.add("hDauPionTPCNSigma", "", HistType::kTH2F, {rigidityAxis, nsigmaAxis}); + recoQAHist.add("hDauAlphaITSNSigmaCheck", "", HistType::kTH2F, {rigidityAxis, itsnsigmaAxis}); hRecoMotherCounter = recoQAHist.add("hRecoMotherCounter", "", HistType::kTH1F, {{9, 0.f, 9.f}}); hRecoDauAlphaCounter = recoQAHist.add("hRecoDauAlphaCounter", "", HistType::kTH1F, {{9, 0.f, 9.f}}); @@ -750,8 +784,8 @@ struct Hyperhelium4sigmaQa { recoQAHist.add("hMotherITSCls", "", HistType::kTH1F, {{8, 0.f, 8.f}}); recoQAHist.add("hDauAlphaIsPVContributer", "", HistType::kTH1F, {{2, 0.f, 2.f}}); recoQAHist.add("hDauAlphaITSCls", "", HistType::kTH1F, {{8, 0.f, 8.f}}); - recoQAHist.add("hDauAlphaPVsITSNSigma", "", HistType::kTH2F, {rigidityAxis, itsnsigmaAxis}); - recoQAHist.add("h2BCandDauAlphaPVsITSNSigma", "", HistType::kTH2F, {rigidityAxis, nsigmaAxis}); + recoQAHist.add("hDauAlphaITSNSigma", "", HistType::kTH2F, {rigidityAxis, itsnsigmaAxis}); + recoQAHist.add("hReco2BDauAlphaPVsITSNSigma", "", HistType::kTH2F, {rigidityAxis, itsnsigmaAxis}); recoQAHist.add("hReco2BCandidateCount", "", HistType::kTH1F, {{4, 0.f, 4.f}}); } } @@ -950,6 +984,9 @@ struct Hyperhelium4sigmaQa { if (track.hasTPC()) { hDauTPCNSigma[type]->Fill(track.p() * track.sign(), tpcNSigma); } + if (type == kDauAlpha && track.itsNCls() > kITSLayers - 2) { + recoQAHist.fill(HIST("hDauAlphaITSNSigmaCheck"), track.p() * track.sign(), itsResponse.nSigmaITS(track)); + } } } } @@ -1000,7 +1037,7 @@ struct Hyperhelium4sigmaQa { float itsNSigma = itsResponse.nSigmaITS(daughterTrack); if (daughterTrack.hasITS()) { - recoQAHist.fill(HIST("hDauAlphaPVsITSNSigma"), daughterTrack.sign() * daughterTrack.p(), itsNSigma); + recoQAHist.fill(HIST("hDauAlphaITSNSigma"), daughterTrack.sign() * daughterTrack.p(), itsNSigma); recoQAHist.fill(HIST("hDauAlphaITSCls"), daughterTrack.itsNCls()); } @@ -1013,7 +1050,7 @@ struct Hyperhelium4sigmaQa { if (isMoth && isDaug) { recoQAHist.fill(HIST("hReco2BCandidateCount"), 3.5); - recoQAHist.fill(HIST("h2BCandDauAlphaPVsITSNSigma"), daughterTrack.sign() * daughterTrack.p(), itsNSigma); + recoQAHist.fill(HIST("hReco2BDauAlphaPVsITSNSigma"), daughterTrack.sign() * daughterTrack.p(), itsNSigma); } } } From ea858cc64a8c84a11e5d760b56051386c504b9d3 Mon Sep 17 00:00:00 2001 From: alicja-pp <101565842+alicja-pp@users.noreply.github.com> Date: Sat, 28 Jun 2025 07:10:41 +0200 Subject: [PATCH 249/871] [PWGCF] FemtoUniverse: Add efficiency calculation with EfficiencyCorrection class to V0 task (#11814) --- .../Core/FemtoUniverseEfficiencyCorrection.h | 31 ++++----- .../femtoUniversePairTaskTrackV0Extended.cxx | 65 ++++++++++++------- 2 files changed, 56 insertions(+), 40 deletions(-) diff --git a/PWGCF/FemtoUniverse/Core/FemtoUniverseEfficiencyCorrection.h b/PWGCF/FemtoUniverse/Core/FemtoUniverseEfficiencyCorrection.h index 9936a5430d6..71abd4e12d9 100644 --- a/PWGCF/FemtoUniverse/Core/FemtoUniverseEfficiencyCorrection.h +++ b/PWGCF/FemtoUniverse/Core/FemtoUniverseEfficiencyCorrection.h @@ -16,22 +16,22 @@ #ifndef PWGCF_FEMTOUNIVERSE_CORE_FEMTOUNIVERSEEFFICIENCYCORRECTION_H_ #define PWGCF_FEMTOUNIVERSE_CORE_FEMTOUNIVERSEEFFICIENCYCORRECTION_H_ +#include "PWGCF/FemtoUniverse/DataModel/FemtoDerived.h" + #include #include #include #include #include - #include + #include #include -#include -#include #include #include - -#include "PWGCF/FemtoUniverse/DataModel/FemtoDerived.h" +#include +#include namespace o2::analysis::femto_universe::efficiency_correction { @@ -115,7 +115,7 @@ class EfficiencyCorrection } } - template + template requires IsOneOrTwo void fillTruthHist(auto particle) { @@ -126,10 +126,10 @@ class EfficiencyCorrection histRegistry->fill(HIST(histDirectory) + HIST("/") + HIST(histSuffix[N - 1]) + HIST("/hMCTruth"), particle.pt(), particle.eta(), - particle.fdCollision().multV0M()); + particle.template fdCollision_as().multV0M()); } - template + template requires IsOneOrTwo void fillRecoHist(auto particle, int particlePDG) { @@ -149,7 +149,7 @@ class EfficiencyCorrection histRegistry->fill(HIST(histDirectory) + HIST("/") + HIST(histSuffix[N - 1]) + HIST("/hPrimary"), mcParticle.pt(), mcParticle.eta(), - particle.fdCollision().multV0M()); + particle.template fdCollision_as().multV0M()); break; case (o2::aod::femtouniverse_mc_particle::kDaughter): @@ -158,33 +158,34 @@ class EfficiencyCorrection histRegistry->fill(HIST(histDirectory) + HIST("/") + HIST(histSuffix[N - 1]) + HIST("/hSecondary"), mcParticle.pt(), mcParticle.eta(), - particle.fdCollision().multV0M()); + particle.template fdCollision_as().multV0M()); break; case (o2::aod::femtouniverse_mc_particle::kMaterial): histRegistry->fill(HIST(histDirectory) + HIST("/") + HIST(histSuffix[N - 1]) + HIST("/hMaterial"), mcParticle.pt(), mcParticle.eta(), - particle.fdCollision().multV0M()); + particle.template fdCollision_as().multV0M()); break; case (o2::aod::femtouniverse_mc_particle::kFake): histRegistry->fill(HIST(histDirectory) + HIST("/") + HIST(histSuffix[N - 1]) + HIST("/hFake"), mcParticle.pt(), mcParticle.eta(), - particle.fdCollision().multV0M()); + particle.template fdCollision_as().multV0M()); break; default: histRegistry->fill(HIST(histDirectory) + HIST("/") + HIST(histSuffix[N - 1]) + HIST("/hOther"), mcParticle.pt(), mcParticle.eta(), - particle.fdCollision().multV0M()); + particle.template fdCollision_as().multV0M()); break; } } } + template auto getWeight(ParticleNo partNo, auto particle) -> float { auto weight = 1.0f; @@ -203,9 +204,9 @@ class EfficiencyCorrection } else if (config->confEffCorVariables.value == "pt,eta") { bin = hWeights->FindBin(particle.pt(), particle.eta()); } else if (config->confEffCorVariables.value == "pt,mult") { - bin = hWeights->FindBin(particle.pt(), particle.fdCollision().multV0M()); + bin = hWeights->FindBin(particle.pt(), particle.template fdCollision_as().multV0M()); } else if (config->confEffCorVariables.value == "pt,eta,mult") { - bin = hWeights->FindBin(particle.pt(), particle.eta(), particle.fdCollision().multV0M()); + bin = hWeights->FindBin(particle.pt(), particle.eta(), particle.template fdCollision_as().multV0M()); } else { LOGF(fatal, notify("Unknown configuration for efficiency variables")); return weight; diff --git a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackV0Extended.cxx b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackV0Extended.cxx index cd8506ced21..cd7cf167027 100644 --- a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackV0Extended.cxx +++ b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackV0Extended.cxx @@ -15,24 +15,27 @@ /// \author Zuzanna Chochulska, WUT Warsaw & CTU Prague, zchochul@cern.ch /// \author Shirajum Monira, WUT Warsaw, shirajum.monira.dokt@pw.edu.pl -#include -#include -#include -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/ASoAHelpers.h" -#include "PWGCF/FemtoUniverse/DataModel/FemtoDerived.h" -#include "PWGCF/FemtoUniverse/Core/FemtoUniverseParticleHisto.h" -#include "PWGCF/FemtoUniverse/Core/FemtoUniverseEventHisto.h" -#include "PWGCF/FemtoUniverse/Core/FemtoUniversePairCleaner.h" #include "PWGCF/FemtoUniverse/Core/FemtoUniverseContainer.h" #include "PWGCF/FemtoUniverse/Core/FemtoUniverseDetaDphiStar.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseEfficiencyCorrection.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseEventHisto.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniversePairCleaner.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseParticleHisto.h" + +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" #include "Framework/O2DatabasePDGPlugin.h" +#include "Framework/runDataProcessing.h" + #include #include #include +#include +#include +#include + using namespace o2; using namespace o2::soa; using namespace o2::framework; @@ -40,6 +43,7 @@ using namespace o2::framework::expressions; using namespace o2::analysis::femto_universe; using namespace o2::aod::pidutils; using namespace o2::track; +using namespace o2::analysis::femto_universe::efficiency_correction; struct FemtoUniversePairTaskTrackV0Extended { @@ -140,6 +144,9 @@ struct FemtoUniversePairTaskTrackV0Extended { // Efficiency Configurable confLocalEfficiency{"confLocalEfficiency", "", "Local path to efficiency .root file"}; + EffCorConfigurableGroup effCorConfGroup; + EfficiencyCorrection effCorrection{&effCorConfGroup}; + static constexpr unsigned int V0ChildTable[][2] = {{0, 1}, {1, 0}, {1, 1}}; // Table to select the V0 children FemtoUniverseContainer sameEventCont; @@ -154,8 +161,6 @@ struct FemtoUniversePairTaskTrackV0Extended { HistogramRegistry registryMCtruth{"MCtruthHistos", {}, OutputObjHandlingPolicy::AnalysisObject, false, true}; HistogramRegistry registryMCreco{"MCrecoHistos", {}, OutputObjHandlingPolicy::AnalysisObject, false, true}; - HistogramRegistry mixQaRegistry{"mixQaRegistry", {}, OutputObjHandlingPolicy::AnalysisObject}; - std::unique_ptr plocalEffFile; std::unique_ptr plocalEffp1; std::unique_ptr plocalEffp2; @@ -228,7 +233,7 @@ struct FemtoUniversePairTaskTrackV0Extended { posChildV0Type2.init(&qaRegistry, confChildTempFitVarpTBins, confChildTempFitVarBins, false, 0, true, "posChildV0Type2"); negChildV0Type2.init(&qaRegistry, confChildTempFitVarpTBins, confChildTempFitVarBins, false, 0, true, "negChildV0Type2"); - mixQaRegistry.add("MixingQA/hMECollisionBins", ";bin;Entries", kTH1F, {{120, -0.5, 119.5}}); + qaRegistry.add("MixingQA/hMECollisionBins", ";bin;Entries", kTH1F, {{120, -0.5, 119.5}}); // 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}}}); @@ -300,6 +305,8 @@ struct FemtoUniversePairTaskTrackV0Extended { LOGF(info, "Loaded efficiency histograms for V0-V0."); } } + + effCorrection.init(&qaRegistry, {static_cast(confV0TempFitVarpTBins), {confEtaBins, -2, 2}, confMultBins}); } /// This function processes the same event for track - V0 template @@ -379,7 +386,7 @@ struct FemtoUniversePairTaskTrackV0Extended { } /// This function processes the same event for V0 - V0 - template + template void doSameEventV0(FilteredFDCollision const& col, PartType const& parts, PartitionType& groupPartsTwo, [[maybe_unused]] MCParticles mcParts = nullptr) { const auto& magFieldTesla = col.magField(); @@ -402,6 +409,9 @@ struct FemtoUniversePairTaskTrackV0Extended { negChildV0Type1.fillQABase(negChild, HIST("negChildV0Type1")); qaRegistry.fill(HIST("V0Type1/hInvMassLambdaVsCent"), multCol, part.mLambda()); qaRegistry.fill(HIST("V0Type1/hInvMassAntiLambdaVsCent"), multCol, part.mAntiLambda()); + if constexpr (isMC) { + effCorrection.fillRecoHist(part, kLambda0); + } } /// Check daughters of second V0 particle if (isParticleTPC(posChild, V0ChildTable[confV0Type2][0]) && isParticleTPC(negChild, V0ChildTable[confV0Type2][1])) { @@ -410,6 +420,9 @@ struct FemtoUniversePairTaskTrackV0Extended { negChildV0Type2.fillQABase(negChild, HIST("negChildV0Type2")); qaRegistry.fill(HIST("V0Type2/hInvMassLambdaVsCent"), multCol, part.mLambda()); qaRegistry.fill(HIST("V0Type2/hInvMassAntiLambdaVsCent"), multCol, part.mAntiLambda()); + if constexpr (isMC) { + effCorrection.fillRecoHist(part, kLambda0Bar); + } } } @@ -481,14 +494,14 @@ struct FemtoUniversePairTaskTrackV0Extended { void processSameEventV0(FilteredFDCollision const& col, FemtoFullParticles const& parts) { auto groupPartsTwo = partsTwo->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); - doSameEventV0(col, parts, groupPartsTwo); + doSameEventV0(col, parts, groupPartsTwo); } PROCESS_SWITCH(FemtoUniversePairTaskTrackV0Extended, processSameEventV0, "Enable processing same event for V0 - V0", false); void processSameEventV0MCReco(FilteredFDCollision const& col, FemtoRecoParticles const& parts, aod::FdMCParticles const& mcparts) { auto groupPartsTwo = partsTwoMCReco->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); - doSameEventV0(col, parts, groupPartsTwo, mcparts); + doSameEventV0(col, parts, groupPartsTwo, mcparts); } PROCESS_SWITCH(FemtoUniversePairTaskTrackV0Extended, processSameEventV0MCReco, "Enable processing same event for V0 - V0 MC Reco", false); @@ -565,6 +578,7 @@ struct FemtoUniversePairTaskTrackV0Extended { negChildV0Type1.fillQABase(negChild, HIST("negChildV0Type1")); qaRegistry.fill(HIST("V0Type1/hInvMassLambdaVsCent"), multCol, part.mLambda()); qaRegistry.fill(HIST("V0Type1/hInvMassAntiLambdaVsCent"), multCol, part.mAntiLambda()); + effCorrection.fillTruthHist(part); } if ((confV0Type2 == 0 && pdgCode == kLambda0) || (confV0Type2 == 1 && pdgCode == kLambda0Bar)) { trackHistoV0Type2.fillQABase(part, HIST("V0Type2")); @@ -572,6 +586,7 @@ struct FemtoUniversePairTaskTrackV0Extended { negChildV0Type2.fillQABase(negChild, HIST("negChildV0Type2")); qaRegistry.fill(HIST("V0Type2/hInvMassLambdaVsCent"), multCol, part.mLambda()); qaRegistry.fill(HIST("V0Type2/hInvMassAntiLambdaVsCent"), multCol, part.mAntiLambda()); + effCorrection.fillTruthHist(part); } } @@ -657,12 +672,12 @@ struct FemtoUniversePairTaskTrackV0Extended { if (confUseCent) { for (const auto& [collision1, collision2] : soa::selfCombinations(colBinningCent, confNEventsMix, -1, cols, cols)) { mixedCollProcessFunc(collision1, collision2); - mixQaRegistry.fill(HIST("MixingQA/hMECollisionBins"), colBinningCent.getBin({collision1.posZ(), collision1.multV0M()})); + qaRegistry.fill(HIST("MixingQA/hMECollisionBins"), colBinningCent.getBin({collision1.posZ(), collision1.multV0M()})); } } else { for (const auto& [collision1, collision2] : soa::selfCombinations(colBinningMult, confNEventsMix, -1, cols, cols)) { mixedCollProcessFunc(collision1, collision2); - mixQaRegistry.fill(HIST("MixingQA/hMECollisionBins"), colBinningMult.getBin({collision1.posZ(), collision1.multNtr()})); + qaRegistry.fill(HIST("MixingQA/hMECollisionBins"), colBinningMult.getBin({collision1.posZ(), collision1.multNtr()})); } } } @@ -729,12 +744,12 @@ struct FemtoUniversePairTaskTrackV0Extended { if (confUseCent) { for (const auto& [collision1, collision2] : soa::selfCombinations(colBinningCent, confNEventsMix, -1, cols, cols)) { mixedCollProcessFunc(collision1, collision2); - mixQaRegistry.fill(HIST("MixingQA/hMECollisionBins"), colBinningCent.getBin({collision1.posZ(), collision1.multV0M()})); + qaRegistry.fill(HIST("MixingQA/hMECollisionBins"), colBinningCent.getBin({collision1.posZ(), collision1.multV0M()})); } } else { for (const auto& [collision1, collision2] : soa::selfCombinations(colBinningMult, confNEventsMix, -1, cols, cols)) { mixedCollProcessFunc(collision1, collision2); - mixQaRegistry.fill(HIST("MixingQA/hMECollisionBins"), colBinningMult.getBin({collision1.posZ(), collision1.multNtr()})); + qaRegistry.fill(HIST("MixingQA/hMECollisionBins"), colBinningMult.getBin({collision1.posZ(), collision1.multNtr()})); } } } @@ -799,12 +814,12 @@ struct FemtoUniversePairTaskTrackV0Extended { if (confUseCent) { for (const auto& [collision1, collision2] : soa::selfCombinations(colBinningCent, confNEventsMix, -1, cols, cols)) { mixedCollProcessFunc(collision1, collision2); - mixQaRegistry.fill(HIST("MixingQA/hMECollisionBins"), colBinningCent.getBin({collision1.posZ(), collision1.multV0M()})); + qaRegistry.fill(HIST("MixingQA/hMECollisionBins"), colBinningCent.getBin({collision1.posZ(), collision1.multV0M()})); } } else { for (const auto& [collision1, collision2] : soa::selfCombinations(colBinningMult, confNEventsMix, -1, cols, cols)) { mixedCollProcessFunc(collision1, collision2); - mixQaRegistry.fill(HIST("MixingQA/hMECollisionBins"), colBinningMult.getBin({collision1.posZ(), collision1.multNtr()})); + qaRegistry.fill(HIST("MixingQA/hMECollisionBins"), colBinningMult.getBin({collision1.posZ(), collision1.multNtr()})); } } } @@ -837,12 +852,12 @@ struct FemtoUniversePairTaskTrackV0Extended { if (confUseCent) { for (const auto& [collision1, collision2] : soa::selfCombinations(colBinningCent, confNEventsMix, -1, cols, cols)) { mixedCollProcessFunc(collision1, collision2); - mixQaRegistry.fill(HIST("MixingQA/hMECollisionBins"), colBinningCent.getBin({collision1.posZ(), collision1.multV0M()})); + qaRegistry.fill(HIST("MixingQA/hMECollisionBins"), colBinningCent.getBin({collision1.posZ(), collision1.multV0M()})); } } else { for (const auto& [collision1, collision2] : soa::selfCombinations(colBinningMult, confNEventsMix, -1, cols, cols)) { mixedCollProcessFunc(collision1, collision2); - mixQaRegistry.fill(HIST("MixingQA/hMECollisionBins"), colBinningMult.getBin({collision1.posZ(), collision1.multNtr()})); + qaRegistry.fill(HIST("MixingQA/hMECollisionBins"), colBinningMult.getBin({collision1.posZ(), collision1.multNtr()})); } } } From d38032a8f25b1d69a90eb0a8672c836b591aa155 Mon Sep 17 00:00:00 2001 From: Giovanni Malfattore <89481844+giovannimalfattore@users.noreply.github.com> Date: Sat, 28 Jun 2025 08:10:41 +0200 Subject: [PATCH 250/871] [PWGLF] NucleiTask - Add MC multiplicity (#11823) --- PWGLF/Tasks/Nuspex/LFNucleiBATask.cxx | 68 +++++++++++++++------------ 1 file changed, 37 insertions(+), 31 deletions(-) diff --git a/PWGLF/Tasks/Nuspex/LFNucleiBATask.cxx b/PWGLF/Tasks/Nuspex/LFNucleiBATask.cxx index 407b13fcb77..2f018baca7d 100644 --- a/PWGLF/Tasks/Nuspex/LFNucleiBATask.cxx +++ b/PWGLF/Tasks/Nuspex/LFNucleiBATask.cxx @@ -18,30 +18,33 @@ /// #include "PWGLF/DataModel/LFNucleiTables.h" +#include "PWGLF/DataModel/LFParticleIdentification.h" +#include "PWGLF/DataModel/mcCentrality.h" +#include "Common/CCDB/EventSelectionParams.h" +#include "Common/Core/trackUtilities.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/PIDResponseITS.h" +#include "Common/DataModel/TrackSelectionTables.h" #include "EventFiltering/Zorro.h" #include "EventFiltering/ZorroSummary.h" + #include "CCDB/BasicCCDBManager.h" -#include -#include -#include -#include "ReconstructionDataFormats/Track.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" #include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" - -#include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/PIDResponse.h" -#include "Common/DataModel/PIDResponseITS.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/Centrality.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "Common/Core/trackUtilities.h" -#include "Common/CCDB/EventSelectionParams.h" -#include "PWGLF/DataModel/LFParticleIdentification.h" +#include "Framework/runDataProcessing.h" #include "ReconstructionDataFormats/PID.h" +#include "ReconstructionDataFormats/Track.h" + +#include +#include + +#include using namespace o2; using namespace o2::framework; @@ -328,7 +331,7 @@ struct LFNucleiBATask { hSkim->GetXaxis()->SetBinLabel(1, "Total"); hSkim->GetXaxis()->SetBinLabel(2, "Skimmed events"); - histos.add("event/eventSelection", "eventSelection", HistType::kTH1D, {{7, -0.5, 6.5}}); + histos.add("event/eventSelection", "eventSelection", HistType::kTH1D, {{8, -0.5, 7.5}}); auto h = histos.get(HIST("event/eventSelection")); if (skimmingOptions.applySkimming) h->GetXaxis()->SetBinLabel(1, "Skimmed events"); @@ -340,6 +343,7 @@ struct LFNucleiBATask { h->GetXaxis()->SetBinLabel(5, "TVX + TF + ITS ROF"); h->GetXaxis()->SetBinLabel(6, "Sel8 cut"); h->GetXaxis()->SetBinLabel(7, "Z-vert Cut"); + h->GetXaxis()->SetBinLabel(8, "Multiplicity cut"); histos.add("event/h1VtxZ", "V_{z};V_{z} (in cm); counts", HistType::kTH1F, {{1500, -15, 15}}); if (enablePIDplot) { @@ -1597,9 +1601,6 @@ struct LFNucleiBATask { } } if (enableTr) { - // histos.add("tracks/triton/h2TritonVspTNSigmaITS", "NSigmaITS(t) vs pT; #it{p}_{T} (GeV/#it{c}); NSigmaITS", HistType::kTH2F, {{ptAxis}, {sigmaITSAxis}}); - // histos.add("tracks/triton/h2antiTritonVspTNSigmaITS", "NSigmaITS(#bar{t}) vs pT; #it{p}_{T} (GeV/#it{c}); NSigmaITS", HistType::kTH2F, {{ptAxis}, {sigmaITSAxis}}); - histos.add("tracks/triton/h2TritonVspTNSigmaTPC", "NSigmaTPC(t) vs pT; #it{p}_{T} (GeV/#it{c}); NSigmaTPC", HistType::kTH2F, {{ptAxis}, {sigmaTPCAxis}}); histos.add("tracks/triton/h2antiTritonVspTNSigmaTPC", "NSigmaTPC(#bar{t}) vs pT; #it{p}_{T} (GeV/#it{c}); NSigmaTPC", HistType::kTH2F, {{ptAxis}, {sigmaTPCAxis}}); } @@ -2140,14 +2141,6 @@ struct LFNucleiBATask { if (enableDebug) debugHistos.fill(HIST("qa/h1VtxZ_sel8"), event.posZ()); - if (enableCentrality) { - if (event.centFT0M() < cfgLowMultCut || event.centFT0M() > cfgHighMultCut) { - return; - } - if (enableDebug) - debugHistos.fill(HIST("event/h1VtxZ_Centrality"), event.posZ()); - } - if (event.posZ() < cfgLowCutVertex || event.posZ() > cfgHighCutVertex) return; histos.fill(HIST("event/eventSelection"), 6); @@ -2159,6 +2152,15 @@ struct LFNucleiBATask { return; } + if (event.centFT0M() < cfgLowMultCut || event.centFT0M() > cfgHighMultCut) { + return; + } + histos.fill(HIST("event/eventSelection"), 7); + + if (enableCentrality && enableDebug) { + debugHistos.fill(HIST("event/h1VtxZ_Centrality"), event.posZ()); + } + 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; bool prRapCut = false; @@ -5763,6 +5765,7 @@ struct LFNucleiBATask { // Process function that runs on the original AO2D (for the MC) void processMCReco(EventCandidatesMC::iterator const& event, + soa::Join const&, soa::Join const& tracks, aod::McParticles const& mcParticles, o2::aod::BCsWithTimestamps const&) @@ -5773,6 +5776,7 @@ struct LFNucleiBATask { // Process function that runs on the original AO2D (for the MC) with the LfPIDcalibration void processMCRecoLfPid(EventCandidatesMC::iterator const& event, + soa::Join const&, soa::Join const& tracks, aod::McParticles const& mcParticles, o2::aod::BCsWithTimestamps const&) @@ -5916,10 +5920,12 @@ struct LFNucleiBATask { //////////// // LOOP OVER GENERATED MC PARTICLES - void processMCGen(aod::McCollision const& mcCollision, + void processMCGen(soa::Join::iterator const& mcCollision, aod::McParticles& mcParticles) { spectraGen.fill(HIST("histGenVetxZ"), mcCollision.posZ()); + if (mcCollision.centFT0M() > cfgHighMultCut || mcCollision.centFT0M() < cfgLowMultCut) + return; for (auto& mcParticleGen : mcParticles) { if (mcParticleGen.y() > kinemOptions.yHighCut || mcParticleGen.y() < kinemOptions.yLowCut) { continue; @@ -6151,7 +6157,7 @@ struct LFNucleiBATask { } } // Close processMCGen PROCESS_SWITCH(LFNucleiBATask, processMCGen, "process MC Generated", true); - void processEvSgLossMC(aod::McCollision const& mcCollision, + void processEvSgLossMC(soa::Join::iterator const& mcCollision, aod::McParticles const& mcParticles, const soa::SmallGroups& recoColls) { From 3f137bcb70b18a0d77ce0635325985649b16daa5 Mon Sep 17 00:00:00 2001 From: Hadi Hassan Date: Sat, 28 Jun 2025 09:27:36 +0300 Subject: [PATCH 251/871] [PWGJE] Adding a process functions withou event weight (#11740) --- .../secondaryVertexReconstruction.cxx | 3 +- PWGJE/Tasks/bjetTaggingML.cxx | 309 +++++++++++------- 2 files changed, 198 insertions(+), 114 deletions(-) diff --git a/PWGJE/TableProducer/secondaryVertexReconstruction.cxx b/PWGJE/TableProducer/secondaryVertexReconstruction.cxx index f86371a5d67..8bab0ea0c05 100644 --- a/PWGJE/TableProducer/secondaryVertexReconstruction.cxx +++ b/PWGJE/TableProducer/secondaryVertexReconstruction.cxx @@ -210,8 +210,6 @@ struct SecondaryVertexReconstruction { auto chi2PCA = df.getChi2AtPCACandidate(); auto covMatrixPCA = df.calcPCACovMatrixFlat(); - registry.fill(HIST("hDispersion"), dispersion, numProngs); - // get track impact parameters // This modifies track momenta! auto primaryVertex = getPrimaryVertex(collision); @@ -288,6 +286,7 @@ struct SecondaryVertexReconstruction { double decayLengthNormalised = RecoDecay::distance(std::array{primaryVertex.getX(), primaryVertex.getY(), primaryVertex.getZ()}, std::array{secondaryVertex[0], secondaryVertex[1], secondaryVertex[2]}) / errorDecayLength; double decayLengthXYNormalised = RecoDecay::distanceXY(std::array{primaryVertex.getX(), primaryVertex.getY()}, std::array{secondaryVertex[0], secondaryVertex[1]}) / errorDecayLengthXY; + registry.fill(HIST("hDispersion"), dispersion, numProngs); registry.fill(HIST("hMassNProngs"), massSV, numProngs); registry.fill(HIST("hLxySNProngs"), decayLengthXYNormalised, numProngs); registry.fill(HIST("hLSNProngs"), decayLengthNormalised, numProngs); diff --git a/PWGJE/Tasks/bjetTaggingML.cxx b/PWGJE/Tasks/bjetTaggingML.cxx index 4f89b482677..64536cb0c15 100644 --- a/PWGJE/Tasks/bjetTaggingML.cxx +++ b/PWGJE/Tasks/bjetTaggingML.cxx @@ -51,7 +51,6 @@ struct BJetTaggingML { // event level configurables Configurable vertexZCut{"vertexZCut", 10.0f, "Accepted z-vertex range"}; 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"}; @@ -75,6 +74,7 @@ struct BJetTaggingML { Configurable jetEtaMax{"jetEtaMax", 99.0, "maximum jet pseudorapidity"}; Configurable nJetConst{"nJetConst", 10, "maximum number of jet consistuents to be used for ML evaluation"}; Configurable useDb{"useDb", false, "Flag whether to use the Db instead of the score for tagging"}; + Configurable callSumw2{"callSumw2", false, "Flag whether to use sum weight squared for THnSparse error calculation"}; Configurable doDataDriven{"doDataDriven", false, "Flag whether to use fill THnSpase for data driven methods"}; @@ -113,15 +113,15 @@ struct BJetTaggingML { registry.add("h2_SVMass_jetpT", "Secondary vertex mass;#it{p}_{T,jet} (GeV/#it{c});#it{m}_{SV} (GeV/#it{c}^{2})", {HistType::kTH2F, {{200, 0., 200.}, {50, 0, 10}}}); if (doDataDriven) { - registry.add("hSparse_Incljets", "Inclusive jets Info;#it{p}_{T,jet} (GeV/#it{c});Score;-log(1-score);#it{m}_{jet} (GeV/#it{c}^{2});-log(JP);#it{m}_{SV} (GeV/#it{c}^{2});SVfE;", {HistType::kTHnSparseF, {{200, 0., 200.}, useDb ? axisDb : axisScore, axisLogScore, {50, 0, 50}, {375, 0, 30}, {50, 0, 10}, {50, 0, 1}}}); - if (doprocessMCJets) { - registry.add("hSparse_bjets", "Tagged b-jets Info;#it{p}_{T,jet} (GeV/#it{c});Score;-log(1-score);#it{m}_{jet} (GeV/#it{c}^{2});-log(JP);#it{m}_{SV} (GeV/#it{c}^{2});SVfE;", {HistType::kTHnSparseF, {{200, 0., 200.}, useDb ? axisDb : axisScore, axisLogScore, {50, 0, 50}, {375, 0, 30}, {50, 0, 10}, {50, 0, 1}}}); - registry.add("hSparse_cjets", "Tagged c-jets Info;#it{p}_{T,jet} (GeV/#it{c});Score;-log(1-score);#it{m}_{jet} (GeV/#it{c}^{2});-log(JP);#it{m}_{SV} (GeV/#it{c}^{2});SVfE;", {HistType::kTHnSparseF, {{200, 0., 200.}, useDb ? axisDb : axisScore, axisLogScore, {50, 0, 50}, {375, 0, 30}, {50, 0, 10}, {50, 0, 1}}}); - registry.add("hSparse_lfjets", "Tagged lf-jets Info;#it{p}_{T,jet} (GeV/#it{c});Score;-log(1-score);#it{m}_{jet} (GeV/#it{c}^{2});-log(JP);#it{m}_{SV} (GeV/#it{c}^{2});SVfE;", {HistType::kTHnSparseF, {{200, 0., 200.}, useDb ? axisDb : axisScore, axisLogScore, {50, 0, 50}, {375, 0, 30}, {50, 0, 10}, {50, 0, 1}}}); + registry.add("hSparse_Incljets", "Inclusive jets Info;#it{p}_{T,jet} (GeV/#it{c});Score;-log(1-score);#it{m}_{jet} (GeV/#it{c}^{2});-log(JP);#it{m}_{SV} (GeV/#it{c}^{2});SVfE;", {HistType::kTHnSparseF, {{200, 0., 200.}, useDb ? axisDb : axisScore, axisLogScore, {50, 0, 50}, {375, 0, 30}, {50, 0, 10}, {50, 0, 1}}}, callSumw2); + if (doprocessMCJets || doprocessMCJetsWeighted) { + registry.add("hSparse_bjets", "Tagged b-jets Info;#it{p}_{T,jet} (GeV/#it{c});Score;-log(1-score);#it{m}_{jet} (GeV/#it{c}^{2});-log(JP);#it{m}_{SV} (GeV/#it{c}^{2});SVfE;", {HistType::kTHnSparseF, {{200, 0., 200.}, useDb ? axisDb : axisScore, axisLogScore, {50, 0, 50}, {375, 0, 30}, {50, 0, 10}, {50, 0, 1}}}, callSumw2); + registry.add("hSparse_cjets", "Tagged c-jets Info;#it{p}_{T,jet} (GeV/#it{c});Score;-log(1-score);#it{m}_{jet} (GeV/#it{c}^{2});-log(JP);#it{m}_{SV} (GeV/#it{c}^{2});SVfE;", {HistType::kTHnSparseF, {{200, 0., 200.}, useDb ? axisDb : axisScore, axisLogScore, {50, 0, 50}, {375, 0, 30}, {50, 0, 10}, {50, 0, 1}}}, callSumw2); + registry.add("hSparse_lfjets", "Tagged lf-jets Info;#it{p}_{T,jet} (GeV/#it{c});Score;-log(1-score);#it{m}_{jet} (GeV/#it{c}^{2});-log(JP);#it{m}_{SV} (GeV/#it{c}^{2});SVfE;", {HistType::kTHnSparseF, {{200, 0., 200.}, useDb ? axisDb : axisScore, axisLogScore, {50, 0, 50}, {375, 0, 30}, {50, 0, 10}, {50, 0, 1}}}, callSumw2); } } - if (doprocessMCJets) { + if (doprocessMCJets || doprocessMCJetsWeighted || doprocessMCTruthJets || doprocessMCTruthJetsWeighted) { registry.add("h2_score_jetpT_bjet", "ML scores for b-jets;#it{p}_{T,jet} (GeV/#it{c});Score", {HistType::kTH2F, {{200, 0., 200.}, useDb ? axisDb : axisScore}}); registry.add("h2_logscore_jetpT_bjet", "ML scores for b-jets;#it{p}_{T,jet} (GeV/#it{c});- log(1 - Score)", {HistType::kTH2F, {{200, 0., 200.}, axisLogScore}}); @@ -163,9 +163,9 @@ struct BJetTaggingML { registry.add("h_jetpT_particle_cjet", "Jet transverse momentum particle level c-jets;#it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH1F, {{200, 0., 200.0}}}); registry.add("h_jetpT_particle_lfjet", "Jet transverse momentum particle level lf-jet;#it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH1F, {{200, 0., 200.0}}}); - registry.add("h2_Response_DetjetpT_PartjetpT_bjet", "Response matrix b-jets;#it{p}_{T,jet}^{det} (GeV/#it{c});#it{p}_{T,jet}^{part} (GeV/#it{c})", {HistType::kTH2F, {{200, 0., 200.}, {200, 0., 200.}}}); - registry.add("h2_Response_DetjetpT_PartjetpT_cjet", "Response matrix c-jets;#it{p}_{T,jet}^{det} (GeV/#it{c});#it{p}_{T,jet}^{part} (GeV/#it{c})", {HistType::kTH2F, {{200, 0., 200.}, {200, 0., 200.}}}); - registry.add("h2_Response_DetjetpT_PartjetpT_lfjet", "Response matrix lf-jet;#it{p}_{T,jet}^{det} (GeV/#it{c});#it{p}_{T,jet}^{part} (GeV/#it{c})", {HistType::kTH2F, {{200, 0., 200.}, {200, 0., 200.}}}); + registry.add("h2_Response_DetjetpT_PartjetpT_bjet", "Response matrix b-jets;#it{p}_{T,jet}^{det} (GeV/#it{c});#it{p}_{T,jet}^{part} (GeV/#it{c})", {HistType::kTH2F, {{200, 0., 200.}, {200, 0., 200.}}}, callSumw2); + registry.add("h2_Response_DetjetpT_PartjetpT_cjet", "Response matrix c-jets;#it{p}_{T,jet}^{det} (GeV/#it{c});#it{p}_{T,jet}^{part} (GeV/#it{c})", {HistType::kTH2F, {{200, 0., 200.}, {200, 0., 200.}}}, callSumw2); + registry.add("h2_Response_DetjetpT_PartjetpT_lfjet", "Response matrix lf-jet;#it{p}_{T,jet}^{det} (GeV/#it{c});#it{p}_{T,jet}^{part} (GeV/#it{c})", {HistType::kTH2F, {{200, 0., 200.}, {200, 0., 200.}}}, callSumw2); } } @@ -215,7 +215,7 @@ struct BJetTaggingML { registry.fill(HIST("h2_Dispersion_jetpT"), myJet.pt(), candSV.dispersion(), eventweight); registry.fill(HIST("h2_SVMass_jetpT"), myJet.pt(), massSV, eventweight); - if (doprocessMCJets) { + if (doprocessMCJets || doprocessMCJetsWeighted) { if (jetFlavor == JetTaggingSpecies::beauty) { registry.fill(HIST("h2_LxyS_jetpT_bjet"), myJet.pt(), candSV.decayLengthXY() / candSV.errorDecayLengthXY(), eventweight); registry.fill(HIST("h2_Dispersion_jetpT_bjet"), myJet.pt(), candSV.dispersion(), eventweight); @@ -253,7 +253,7 @@ struct BJetTaggingML { registry.fill(HIST("h2_SIPs2D_jetpT"), analysisJet.pt(), sign * std::abs(constituent.dcaXY()) / constituent.sigmadcaXY(), eventweight); registry.fill(HIST("h2_SIPs3D_jetpT"), analysisJet.pt(), sign * std::abs(constituent.dcaXYZ()) / constituent.sigmadcaXYZ(), eventweight); - if (doprocessMCJets) { + if (doprocessMCJets || doprocessMCJetsWeighted) { if (jetFlavor == JetTaggingSpecies::beauty) { registry.fill(HIST("h2_SIPs2D_jetpT_bjet"), analysisJet.pt(), sign * std::abs(constituent.dcaXY()) / constituent.sigmadcaXY(), eventweight); registry.fill(HIST("h2_SIPs3D_jetpT_bjet"), analysisJet.pt(), sign * std::abs(constituent.dcaXYZ()) / constituent.sigmadcaXYZ(), eventweight); @@ -278,6 +278,94 @@ struct BJetTaggingML { tracksParams.resize(nJetConst); } + template + void processJetInfo(AnalysisJet const& myJet, AnyTracks const& allTracks, SecondaryVertices const& allSVs, int8_t jetFlavor = 0, double eventWeight = 1.0) + { + std::vector tracksParams; + std::vector svsParams; + + analyzeJetSVInfo(myJet, allSVs, svsParams, jetFlavor, eventWeight); + analyzeJetTrackInfo(myJet, allTracks, tracksParams, jetFlavor, eventWeight); + + int nSVs = myJet.template secondaryVertices_as().size(); + int nTracks = myJet.template tracks_as().size(); + + registry.fill(HIST("h2_nTracks_jetpT"), myJet.pt(), nTracks); + registry.fill(HIST("h2_nSV_jetpT"), myJet.pt(), nSVs < 250 ? nSVs : 249); + + registry.fill(HIST("h2_score_jetpT"), myJet.pt(), myJet.scoreML(), eventWeight); + if (!useDb) { + registry.fill(HIST("h2_logscore_jetpT"), myJet.pt(), -1 * std::log(1 - myJet.scoreML()), eventWeight); + } + registry.fill(HIST("h2_jetMass_jetpT"), myJet.pt(), myJet.mass(), eventWeight); + + if (doDataDriven) { + registry.fill(HIST("hSparse_Incljets"), myJet.pt(), myJet.scoreML(), useDb ? 0 : -1 * std::log(1 - myJet.scoreML()), myJet.mass(), -1 * std::log(myJet.jetProb()), svsParams[0].svMass, svsParams[0].svfE, eventWeight); + if (doprocessMCJets || doprocessMCJetsWeighted) { + if (jetFlavor == JetTaggingSpecies::beauty) { + registry.fill(HIST("hSparse_bjets"), myJet.pt(), myJet.scoreML(), useDb ? 0 : -1 * std::log(1 - myJet.scoreML()), myJet.mass(), -1 * std::log(myJet.jetProb()), svsParams[0].svMass, svsParams[0].svfE, eventWeight); + } else if (jetFlavor == JetTaggingSpecies::charm) { + registry.fill(HIST("hSparse_cjets"), myJet.pt(), myJet.scoreML(), useDb ? 0 : -1 * std::log(1 - myJet.scoreML()), myJet.mass(), -1 * std::log(myJet.jetProb()), svsParams[0].svMass, svsParams[0].svfE, eventWeight); + } else { + registry.fill(HIST("hSparse_lfjets"), myJet.pt(), myJet.scoreML(), useDb ? 0 : -1 * std::log(1 - myJet.scoreML()), myJet.mass(), -1 * std::log(myJet.jetProb()), svsParams[0].svMass, svsParams[0].svfE, eventWeight); + } + } + } + + if (doprocessMCJets || doprocessMCJetsWeighted) { + if (jetFlavor == JetTaggingSpecies::beauty) { + registry.fill(HIST("h2_score_jetpT_bjet"), myJet.pt(), myJet.scoreML(), eventWeight); + if (!useDb) { + registry.fill(HIST("h2_logscore_jetpT_bjet"), myJet.pt(), -1 * std::log(1 - myJet.scoreML()), eventWeight); + } + registry.fill(HIST("h2_jetMass_jetpT_bjet"), myJet.pt(), myJet.mass(), eventWeight); + registry.fill(HIST("h_jetpT_detector_bjet"), myJet.pt(), eventWeight); + } else if (jetFlavor == JetTaggingSpecies::charm) { + registry.fill(HIST("h2_score_jetpT_cjet"), myJet.pt(), myJet.scoreML(), eventWeight); + if (!useDb) { + registry.fill(HIST("h2_logscore_jetpT_cjet"), myJet.pt(), -1 * std::log(1 - myJet.scoreML()), eventWeight); + } + registry.fill(HIST("h2_jetMass_jetpT_cjet"), myJet.pt(), myJet.mass(), eventWeight); + registry.fill(HIST("h_jetpT_detector_cjet"), myJet.pt(), eventWeight); + } else { + registry.fill(HIST("h2_score_jetpT_lfjet"), myJet.pt(), myJet.scoreML(), eventWeight); + if (!useDb) { + registry.fill(HIST("h2_logscore_jetpT_lfjet"), myJet.pt(), -1 * std::log(1 - myJet.scoreML()), eventWeight); + } + registry.fill(HIST("h2_jetMass_jetpT_lfjet"), myJet.pt(), myJet.mass(), eventWeight); + registry.fill(HIST("h_jetpT_detector_lfjet"), myJet.pt(), eventWeight); + } + } + } + + template + void fillMCPHistograms(AnalysisJetMCP const& mcpjet, bool detColl = false, double eventWeight = 1.0) + { + int8_t jetFlavor = mcpjet.origin(); + + if (detColl) { + + registry.fill(HIST("h_jetpT_particle_DetColl"), mcpjet.pt(), eventWeight); + + if (jetFlavor == JetTaggingSpecies::beauty) { + registry.fill(HIST("h_jetpT_particle_DetColl_bjet"), mcpjet.pt(), eventWeight); + } else if (jetFlavor == JetTaggingSpecies::charm) { + registry.fill(HIST("h_jetpT_particle_DetColl_cjet"), mcpjet.pt(), eventWeight); + } else { + registry.fill(HIST("h_jetpT_particle_DetColl_lfjet"), mcpjet.pt(), eventWeight); + } + } else { + + if (jetFlavor == JetTaggingSpecies::beauty) { + registry.fill(HIST("h_jetpT_particle_bjet"), mcpjet.pt(), eventWeight); + } else if (jetFlavor == JetTaggingSpecies::charm) { + registry.fill(HIST("h_jetpT_particle_cjet"), mcpjet.pt(), eventWeight); + } else { + registry.fill(HIST("h_jetpT_particle_lfjet"), mcpjet.pt(), eventWeight); + } + } + } + void processDummy(FilteredCollision::iterator const& /*collision*/) { } @@ -305,39 +393,18 @@ struct BJetTaggingML { continue; } - std::vector tracksParams; - std::vector svsParams; - - analyzeJetSVInfo(analysisJet, allSVs, svsParams); - analyzeJetTrackInfo(analysisJet, allTracks, tracksParams); - - int nSVs = analysisJet.template secondaryVertices_as().size(); - int nTracks = analysisJet.template tracks_as().size(); - - registry.fill(HIST("h2_nTracks_jetpT"), analysisJet.pt(), nTracks); - registry.fill(HIST("h2_nSV_jetpT"), analysisJet.pt(), nSVs < 250 ? nSVs : 249); - - registry.fill(HIST("h2_score_jetpT"), analysisJet.pt(), analysisJet.scoreML()); - if (!useDb) { - registry.fill(HIST("h2_logscore_jetpT"), analysisJet.pt(), -1 * std::log(1 - analysisJet.scoreML())); - } - - registry.fill(HIST("h2_jetMass_jetpT"), analysisJet.pt(), analysisJet.mass()); - - if (doDataDriven) { - registry.fill(HIST("hSparse_Incljets"), analysisJet.pt(), analysisJet.scoreML(), useDb ? 0 : -1 * std::log(1 - analysisJet.scoreML()), analysisJet.mass(), -1 * std::log(analysisJet.jetProb()), svsParams[0].svMass, svsParams[0].svfE); - } + processJetInfo(analysisJet, allTracks, allSVs); } } PROCESS_SWITCH(BJetTaggingML, processDataJets, "jet information in Data", false); - using MCDJetTable = soa::Filtered>; - using MCPJetTable = soa::Filtered>; + using MCDJetTableWeighted = soa::Filtered>; + using MCPJetTableWeighted = soa::Filtered>; using FilteredCollisionMCD = soa::Filtered>; - Preslice mcpJetsPerCollision = aod::jet::mcCollisionId; + Preslice mcpJetsPerCollisionWeighted = aod::jet::mcCollisionId; - void processMCJets(FilteredCollisionMCD::iterator const& collision, MCDJetTable const& MCDjets, MCPJetTable const& MCPjets, JetTracksMCDwID const& allTracks, aod::JetParticles const& /*MCParticles*/, aod::MCDSecondaryVertex3Prongs const& allSVs) + void processMCJetsWeighted(FilteredCollisionMCD::iterator const& collision, MCDJetTableWeighted const& MCDjets, MCPJetTableWeighted const& MCPjets, JetTracksMCDwID const& allTracks, aod::JetParticles const& /*MCParticles*/, aod::MCDSecondaryVertex3Prongs const& allSVs) { if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits)) { return; @@ -345,7 +412,7 @@ struct BJetTaggingML { registry.fill(HIST("h_vertexZ"), collision.posZ()); - auto const mcPJetsPerColl = MCPjets.sliceBy(mcpJetsPerCollision, collision.mcCollisionId()); + auto const mcPJetsPerColl = MCPjets.sliceBy(mcpJetsPerCollisionWeighted, collision.mcCollisionId()); for (const auto& analysisJet : MCDjets) { @@ -361,67 +428,17 @@ struct BJetTaggingML { continue; } - float eventWeight = useEventWeight ? analysisJet.eventWeight() : 1.0; + float eventWeight = analysisJet.eventWeight(); float pTHat = 10. / (std::pow(eventWeight, 1.0 / pTHatExponent)); if (analysisJet.pt() > pTHatMaxMCD * pTHat) { continue; } - std::vector tracksParams; - std::vector svsParams; - int jetFlavor = analysisJet.origin(); - analyzeJetSVInfo(analysisJet, allSVs, svsParams, jetFlavor, eventWeight); - analyzeJetTrackInfo(analysisJet, allTracks, tracksParams, jetFlavor, eventWeight); - - int nSVs = analysisJet.template secondaryVertices_as().size(); - int nTracks = analysisJet.template tracks_as().size(); + processJetInfo(analysisJet, allTracks, allSVs, jetFlavor, eventWeight); - registry.fill(HIST("h2_nTracks_jetpT"), analysisJet.pt(), nTracks); - registry.fill(HIST("h2_nSV_jetpT"), analysisJet.pt(), nSVs < 250 ? nSVs : 249); - - registry.fill(HIST("h2_score_jetpT"), analysisJet.pt(), analysisJet.scoreML(), eventWeight); - if (!useDb) { - registry.fill(HIST("h2_logscore_jetpT"), analysisJet.pt(), -1 * std::log(1 - analysisJet.scoreML()), eventWeight); - } - registry.fill(HIST("h2_jetMass_jetpT"), analysisJet.pt(), analysisJet.mass(), eventWeight); - - if (doDataDriven) { - registry.fill(HIST("hSparse_Incljets"), analysisJet.pt(), analysisJet.scoreML(), useDb ? 0 : -1 * std::log(1 - analysisJet.scoreML()), analysisJet.mass(), -1 * std::log(analysisJet.jetProb()), svsParams[0].svMass, svsParams[0].svfE, eventWeight); - if (jetFlavor == JetTaggingSpecies::beauty) { - registry.fill(HIST("hSparse_bjets"), analysisJet.pt(), analysisJet.scoreML(), useDb ? 0 : -1 * std::log(1 - analysisJet.scoreML()), analysisJet.mass(), -1 * std::log(analysisJet.jetProb()), svsParams[0].svMass, svsParams[0].svfE, eventWeight); - } else if (jetFlavor == JetTaggingSpecies::charm) { - registry.fill(HIST("hSparse_cjets"), analysisJet.pt(), analysisJet.scoreML(), useDb ? 0 : -1 * std::log(1 - analysisJet.scoreML()), analysisJet.mass(), -1 * std::log(analysisJet.jetProb()), svsParams[0].svMass, svsParams[0].svfE, eventWeight); - } else { - registry.fill(HIST("hSparse_lfjets"), analysisJet.pt(), analysisJet.scoreML(), useDb ? 0 : -1 * std::log(1 - analysisJet.scoreML()), analysisJet.mass(), -1 * std::log(analysisJet.jetProb()), svsParams[0].svMass, svsParams[0].svfE, eventWeight); - } - } - - if (jetFlavor == JetTaggingSpecies::beauty) { - registry.fill(HIST("h2_score_jetpT_bjet"), analysisJet.pt(), analysisJet.scoreML(), eventWeight); - if (!useDb) { - registry.fill(HIST("h2_logscore_jetpT_bjet"), analysisJet.pt(), -1 * std::log(1 - analysisJet.scoreML()), eventWeight); - } - registry.fill(HIST("h2_jetMass_jetpT_bjet"), analysisJet.pt(), analysisJet.mass(), eventWeight); - registry.fill(HIST("h_jetpT_detector_bjet"), analysisJet.pt(), eventWeight); - } else if (jetFlavor == JetTaggingSpecies::charm) { - registry.fill(HIST("h2_score_jetpT_cjet"), analysisJet.pt(), analysisJet.scoreML(), eventWeight); - if (!useDb) { - registry.fill(HIST("h2_logscore_jetpT_cjet"), analysisJet.pt(), -1 * std::log(1 - analysisJet.scoreML()), eventWeight); - } - registry.fill(HIST("h2_jetMass_jetpT_cjet"), analysisJet.pt(), analysisJet.mass(), eventWeight); - registry.fill(HIST("h_jetpT_detector_cjet"), analysisJet.pt(), eventWeight); - } else { - registry.fill(HIST("h2_score_jetpT_lfjet"), analysisJet.pt(), analysisJet.scoreML(), eventWeight); - if (!useDb) { - registry.fill(HIST("h2_logscore_jetpT_lfjet"), analysisJet.pt(), -1 * std::log(1 - analysisJet.scoreML()), eventWeight); - } - registry.fill(HIST("h2_jetMass_jetpT_lfjet"), analysisJet.pt(), analysisJet.mass(), eventWeight); - registry.fill(HIST("h_jetpT_detector_lfjet"), analysisJet.pt(), eventWeight); - } - - for (const auto& mcpjet : analysisJet.template matchedJetGeo_as()) { + for (const auto& mcpjet : analysisJet.template matchedJetGeo_as()) { if (mcpjet.pt() > pTHatMaxMCP * pTHat) { continue; } @@ -451,31 +468,85 @@ struct BJetTaggingML { continue; } - float eventWeight = useEventWeight ? mcpjet.eventWeight() : 1.0; + float eventWeight = mcpjet.eventWeight(); float pTHat = 10. / (std::pow(eventWeight, 1.0 / pTHatExponent)); if (mcpjet.pt() > pTHatMaxMCP * pTHat) { continue; } - int8_t jetFlavor = mcpjet.origin(); + fillMCPHistograms(mcpjet, true, eventWeight); + } + } + PROCESS_SWITCH(BJetTaggingML, processMCJetsWeighted, "jet information in MC with event weight", false); - registry.fill(HIST("h_jetpT_particle_DetColl"), mcpjet.pt(), eventWeight); + using MCDJetTable = soa::Filtered>; + using MCPJetTable = soa::Filtered>; - if (jetFlavor == JetTaggingSpecies::beauty) { - registry.fill(HIST("h_jetpT_particle_DetColl_bjet"), mcpjet.pt(), eventWeight); - } else if (jetFlavor == JetTaggingSpecies::charm) { - registry.fill(HIST("h_jetpT_particle_DetColl_cjet"), mcpjet.pt(), eventWeight); - } else { - registry.fill(HIST("h_jetpT_particle_DetColl_lfjet"), mcpjet.pt(), eventWeight); + Preslice mcpJetsPerCollision = aod::jet::mcCollisionId; + + void processMCJets(FilteredCollisionMCD::iterator const& collision, MCDJetTable const& MCDjets, MCPJetTable const& MCPjets, JetTracksMCDwID const& allTracks, aod::JetParticles const& /*MCParticles*/, aod::MCDSecondaryVertex3Prongs const& allSVs) + { + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits)) { + return; + } + + registry.fill(HIST("h_vertexZ"), collision.posZ()); + + auto const mcPJetsPerColl = MCPjets.sliceBy(mcpJetsPerCollision, collision.mcCollisionId()); + + for (const auto& analysisJet : MCDjets) { + + bool jetIncluded = false; + for (const auto& jetR : jetRadiiValues) { + if (analysisJet.r() == static_cast(jetR * 100)) { + jetIncluded = true; + break; + } + } + + if (!jetIncluded) { + continue; + } + + int jetFlavor = analysisJet.origin(); + + processJetInfo(analysisJet, allTracks, allSVs, jetFlavor); + + for (const auto& mcpjet : analysisJet.template matchedJetGeo_as()) { + if (jetFlavor == JetTaggingSpecies::beauty) { + registry.fill(HIST("h2_Response_DetjetpT_PartjetpT_bjet"), analysisJet.pt(), mcpjet.pt()); + } else if (jetFlavor == JetTaggingSpecies::charm) { + registry.fill(HIST("h2_Response_DetjetpT_PartjetpT_cjet"), analysisJet.pt(), mcpjet.pt()); + } else { + registry.fill(HIST("h2_Response_DetjetpT_PartjetpT_lfjet"), analysisJet.pt(), mcpjet.pt()); + } } } + + // For filling histograms used for the jet matching efficiency + for (const auto& mcpjet : mcPJetsPerColl) { + + bool jetIncluded = false; + for (const auto& jetR : jetRadiiValues) { + if (mcpjet.r() == static_cast(jetR * 100)) { + jetIncluded = true; + break; + } + } + + if (!jetIncluded) { + continue; + } + + fillMCPHistograms(mcpjet, true); + } } - PROCESS_SWITCH(BJetTaggingML, processMCJets, "jet information in MC", false); + PROCESS_SWITCH(BJetTaggingML, processMCJets, "jet information in MC without event weight", false); Filter mccollisionFilter = nabs(aod::jmccollision::posZ) < vertexZCut; using FilteredCollisionMCP = soa::Filtered; - void processMCTruthJets(FilteredCollisionMCP::iterator const& /*collision*/, MCPJetTable const& MCPjets, aod::JetParticles const& /*MCParticles*/) + void processMCTruthJetsWeighted(FilteredCollisionMCP::iterator const& /*collision*/, MCPJetTableWeighted const& MCPjets, aod::JetParticles const& /*MCParticles*/) { for (const auto& mcpjet : MCPjets) { @@ -492,24 +563,38 @@ struct BJetTaggingML { continue; } - float eventWeight = useEventWeight ? mcpjet.eventWeight() : 1.0; + float eventWeight = mcpjet.eventWeight(); float pTHat = 10. / (std::pow(eventWeight, 1.0 / pTHatExponent)); if (mcpjet.pt() > pTHatMaxMCP * pTHat) { continue; } - int8_t jetFlavor = mcpjet.origin(); + fillMCPHistograms(mcpjet, false, eventWeight); + } + } + PROCESS_SWITCH(BJetTaggingML, processMCTruthJetsWeighted, "truth jet information with event weight", false); - if (jetFlavor == JetTaggingSpecies::beauty) { - registry.fill(HIST("h_jetpT_particle_bjet"), mcpjet.pt(), eventWeight); - } else if (jetFlavor == JetTaggingSpecies::charm) { - registry.fill(HIST("h_jetpT_particle_cjet"), mcpjet.pt(), eventWeight); - } else { - registry.fill(HIST("h_jetpT_particle_lfjet"), mcpjet.pt(), eventWeight); + void processMCTruthJets(FilteredCollisionMCP::iterator const& /*collision*/, MCPJetTable const& MCPjets, aod::JetParticles const& /*MCParticles*/) + { + + for (const auto& mcpjet : MCPjets) { + + bool jetIncluded = false; + for (const auto& jetR : jetRadiiValues) { + if (mcpjet.r() == static_cast(jetR * 100)) { + jetIncluded = true; + break; + } } + + if (!jetIncluded) { + continue; + } + + fillMCPHistograms(mcpjet); } } - PROCESS_SWITCH(BJetTaggingML, processMCTruthJets, "truth jet information", false); + PROCESS_SWITCH(BJetTaggingML, processMCTruthJets, "truth jet information without event weight", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) From 68d23d834fdf1021f7f4123d5583cf1b0ca9f89a Mon Sep 17 00:00:00 2001 From: GijsvWeelden <55794847+GijsvWeelden@users.noreply.github.com> Date: Sat, 28 Jun 2025 08:28:44 +0200 Subject: [PATCH 252/871] [PWGJE] Jet Fragmentation & V0 QA (#11750) --- PWGJE/Tasks/jetFragmentation.cxx | 4 +- PWGJE/Tasks/v0QA.cxx | 144 +++++++++++++++++++++++++++++++ 2 files changed, 146 insertions(+), 2 deletions(-) diff --git a/PWGJE/Tasks/jetFragmentation.cxx b/PWGJE/Tasks/jetFragmentation.cxx index eae04024d08..6d84df3fb04 100644 --- a/PWGJE/Tasks/jetFragmentation.cxx +++ b/PWGJE/Tasks/jetFragmentation.cxx @@ -2658,9 +2658,9 @@ struct JetFragmentation { std::vector state = convertState(M, nV0inJet, nV0Classes); std::vector corrected; if (doCorrectionWithTracks) - corrected = correctedValues(state, values); - else corrected = correctedValuesPlusTracks(state, jet); + else + corrected = correctedValues(state, values); double ws = stateWeight(state, weights); double jetpt = corrected[nV0inJet]; diff --git a/PWGJE/Tasks/v0QA.cxx b/PWGJE/Tasks/v0QA.cxx index 0f6793ef4ae..2ad01dd572b 100644 --- a/PWGJE/Tasks/v0QA.cxx +++ b/PWGJE/Tasks/v0QA.cxx @@ -70,11 +70,13 @@ struct V0QA { Configurable lifetimeLambdaMax{"lifetimeLambdaMax", 30.0, "Maximum lifetime of Lambda (cm)"}; Configurable yPartMax{"yPartMax", 0.5, "Maximum rapidity of particles"}; Configurable vertexZCut{"vertexZCut", 10.0, "Vertex Z cut"}; + Configurable v0Fraction{"v0Fraction", 0.5, "Fraction of V0s to accept randomly"}; Filter jetCollisionFilter = nabs(aod::jcollision::posZ) < vertexZCut; ConfigurableAxis binPtJet{"ptJet", {100., 0.0f, 50.0f}, ""}; ConfigurableAxis binPtV0{"ptV0", {100., 0.0f, 50.0f}, ""}; + ConfigurableAxis binZV0{"zV0", {100., 1e-3f, 1 + 1e-3f}, ""}; ConfigurableAxis binEta{"binEta", {100, -1.0f, 1.0f}, ""}; ConfigurableAxis binPhi{"binPhi", {constants::math::PI * 10 / 2, 0.0f, constants::math::TwoPI}, ""}; @@ -103,6 +105,7 @@ struct V0QA { const AxisSpec axisJetPt{binPtJet, "Jet Pt (GeV/c)"}; const AxisSpec axisV0Pt{binPtV0, "V0 Pt (GeV/c)"}; + const AxisSpec axisV0Z{binZV0, "z_{V0} = #it{p}_{T, V0} / #it{p}_{T, jet}"}; const AxisSpec axisEta{binEta, "Eta"}; const AxisSpec axisPhi{binPhi, "Phi"}; const AxisSpec axisV0Radius{binV0Radius, "V0 Radius (cm)"}; @@ -225,6 +228,38 @@ struct V0QA { registry.add("feeddown/JetsPtXiMinusPtLambdaPt", "Jets Pt, #Xi^{-} Pt, #Lambda Pt", HistType::kTHnSparseD, {axisJetPt, axisJetPt, axisV0Pt, axisV0Pt}); registry.add("feeddown/JetsPtXiPlusPtAntiLambdaPt", "Jets Pt, #Xi^{+} Pt, #bar{#Lambda} Pt", HistType::kTHnSparseD, {axisJetPt, axisJetPt, axisV0Pt, axisV0Pt}); } + if (doprocessTestWeightedJetFinder) { + registry.add("tests/weighted/JetPtEtaPhi", "Jet Pt, Eta, Phi", HistType::kTH3D, {axisJetPt, axisEta, axisPhi}); + registry.add("tests/weighted/JetPtEtaV0Pt", "Jet Pt, Eta, V0 Pt", HistType::kTH3D, {axisJetPt, axisEta, axisV0Pt}); + registry.add("tests/weighted/JetPtEtaV0Z", "Jet Pt, Eta, V0 Z", HistType::kTH3D, {axisJetPt, axisEta, axisV0Z}); + registry.add("tests/weighted/JetPtEtaK0SPt", "Jet Pt, Eta, K0S Pt", HistType::kTH3D, {axisJetPt, axisEta, axisV0Pt}); + registry.add("tests/weighted/JetPtEtaK0SZ", "Jet Pt, Eta, K0S Z", HistType::kTH3D, {axisJetPt, axisEta, axisV0Z}); + registry.add("tests/weighted/JetPtEtaLambdaPt", "Jet Pt, Eta, Lambda Pt", HistType::kTH3D, {axisJetPt, axisEta, axisV0Pt}); + registry.add("tests/weighted/JetPtEtaLambdaZ", "Jet Pt, Eta, Lambda Z", HistType::kTH3D, {axisJetPt, axisEta, axisV0Z}); + registry.add("tests/weighted/JetPtEtaAntiLambdaPt", "Jet Pt, Eta, AntiLambda Pt", HistType::kTH3D, {axisJetPt, axisEta, axisV0Pt}); + registry.add("tests/weighted/JetPtEtaAntiLambdaZ", "Jet Pt, Eta, AntiLambda Z", HistType::kTH3D, {axisJetPt, axisEta, axisV0Z}); + } + if (doprocessTestSubtractedJetFinder) { + registry.add("tests/nosub/JetPtEtaPhi", "Jet Pt, Eta, Phi", HistType::kTH3D, {axisJetPt, axisEta, axisPhi}); + registry.add("tests/nosub/JetPtEtaV0Pt", "Jet Pt, Eta, V0 Pt", HistType::kTH3D, {axisJetPt, axisEta, axisV0Pt}); + registry.add("tests/nosub/JetPtEtaV0Z", "Jet Pt, Eta, V0 Z", HistType::kTH3D, {axisJetPt, axisEta, axisV0Z}); + registry.add("tests/nosub/JetPtEtaK0SPt", "Jet Pt, Eta, K0S Pt", HistType::kTH3D, {axisJetPt, axisEta, axisV0Pt}); + registry.add("tests/nosub/JetPtEtaK0SZ", "Jet Pt, Eta, K0S Z", HistType::kTH3D, {axisJetPt, axisEta, axisV0Z}); + registry.add("tests/nosub/JetPtEtaLambdaPt", "Jet Pt, Eta, Lambda Pt", HistType::kTH3D, {axisJetPt, axisEta, axisV0Pt}); + registry.add("tests/nosub/JetPtEtaLambdaZ", "Jet Pt, Eta, Lambda Z", HistType::kTH3D, {axisJetPt, axisEta, axisV0Z}); + registry.add("tests/nosub/JetPtEtaAntiLambdaPt", "Jet Pt, Eta, AntiLambda Pt", HistType::kTH3D, {axisJetPt, axisEta, axisV0Pt}); + registry.add("tests/nosub/JetPtEtaAntiLambdaZ", "Jet Pt, Eta, AntiLambda Z", HistType::kTH3D, {axisJetPt, axisEta, axisV0Z}); + + registry.add("tests/sub/JetPtEtaPhi", "Jet Pt, Eta, Phi", HistType::kTH3D, {axisJetPt, axisEta, axisPhi}); + registry.add("tests/sub/JetPtEtaV0Pt", "Jet Pt, Eta, V0 Pt", HistType::kTH3D, {axisJetPt, axisEta, axisV0Pt}); + registry.add("tests/sub/JetPtEtaV0Z", "Jet Pt, Eta, V0 Z", HistType::kTH3D, {axisJetPt, axisEta, axisV0Z}); + registry.add("tests/sub/JetPtEtaK0SPt", "Jet Pt, Eta, K0S Pt", HistType::kTH3D, {axisJetPt, axisEta, axisV0Pt}); + registry.add("tests/sub/JetPtEtaK0SZ", "Jet Pt, Eta, K0S Z", HistType::kTH3D, {axisJetPt, axisEta, axisV0Z}); + registry.add("tests/sub/JetPtEtaLambdaPt", "Jet Pt, Eta, Lambda Pt", HistType::kTH3D, {axisJetPt, axisEta, axisV0Pt}); + registry.add("tests/sub/JetPtEtaLambdaZ", "Jet Pt, Eta, Lambda Z", HistType::kTH3D, {axisJetPt, axisEta, axisV0Z}); + registry.add("tests/sub/JetPtEtaAntiLambdaPt", "Jet Pt, Eta, AntiLambda Pt", HistType::kTH3D, {axisJetPt, axisEta, axisV0Pt}); + registry.add("tests/sub/JetPtEtaAntiLambdaZ", "Jet Pt, Eta, AntiLambda Z", HistType::kTH3D, {axisJetPt, axisEta, axisV0Z}); + } if (doprocessV0TrackQA) { registry.add("tracks/Pos", "pos", HistType::kTHnSparseD, {axisV0Pt, axisV0Pt, axisEta, axisPhi}); registry.add("tracks/Neg", "neg", HistType::kTHnSparseD, {axisV0Pt, axisV0Pt, axisEta, axisPhi}); @@ -1220,6 +1255,115 @@ struct V0QA { } PROCESS_SWITCH(V0QA, processFeeddownMatchedJets, "Jets feeddown", false); + // Test the difference between excluding V0s from jet finding and subtracting V0s from jets afterwards + void processTestWeightedJetFinder(soa::Filtered::iterator const& jcoll, soa::Join const& jets, aod::CandidatesV0Data const&) + { + if (!jetderiveddatautilities::selectCollision(jcoll, eventSelectionBits)) + return; + + for (const auto& jet : jets) { + registry.fill(HIST("tests/weighted/JetPtEtaPhi"), jet.pt(), jet.eta(), jet.phi()); + + for (const auto& v0 : jet.template candidates_as()) { + if (v0.isRejectedCandidate()) + continue; + + double z = v0.pt() / jet.pt(); + + registry.fill(HIST("tests/weighted/JetPtEtaV0Pt"), jet.pt(), jet.eta(), v0.pt()); + registry.fill(HIST("tests/weighted/JetPtEtaV0Z"), jet.pt(), jet.eta(), z); + + if (v0.isK0SCandidate()) { + registry.fill(HIST("tests/weighted/JetPtEtaK0SPt"), jet.pt(), jet.eta(), v0.pt()); + registry.fill(HIST("tests/weighted/JetPtEtaK0SZ"), jet.pt(), jet.eta(), z); + } + if (v0.isLambdaCandidate()) { + registry.fill(HIST("tests/weighted/JetPtEtaLambdaPt"), jet.pt(), jet.eta(), v0.pt()); + registry.fill(HIST("tests/weighted/JetPtEtaLambdaZ"), jet.pt(), jet.eta(), z); + } + if (v0.isAntiLambdaCandidate()) { + registry.fill(HIST("tests/weighted/JetPtEtaAntiLambdaPt"), jet.pt(), jet.eta(), v0.pt()); + registry.fill(HIST("tests/weighted/JetPtEtaAntiLambdaZ"), jet.pt(), jet.eta(), z); + } + } + } + } + PROCESS_SWITCH(V0QA, processTestWeightedJetFinder, "Test weighted jet finder", false); + + void processTestSubtractedJetFinder(soa::Filtered::iterator const& jcoll, soa::Join const& jets, aod::CandidatesV0Data const&) + { + if (!jetderiveddatautilities::selectCollision(jcoll, eventSelectionBits)) + return; + + for (const auto& jet : jets) { + registry.fill(HIST("tests/nosub/JetPtEtaPhi"), jet.pt(), jet.eta(), jet.phi()); + + std::vector v0Pt; + std::vector v0Type; // 0: K0S, 1: Lambda, 2: AntiLambda + double ptjetsub = jet.pt(); + + for (const auto& v0 : jet.template candidates_as()) { + if (v0.isRejectedCandidate()) + continue; + + double z = v0.pt() / jet.pt(); + + registry.fill(HIST("tests/nosub/JetPtEtaV0Pt"), jet.pt(), jet.eta(), v0.pt()); + registry.fill(HIST("tests/nosub/JetPtEtaV0Z"), jet.pt(), jet.eta(), z); + + if (v0.isK0SCandidate()) { + registry.fill(HIST("tests/nosub/JetPtEtaK0SPt"), jet.pt(), jet.eta(), v0.pt()); + registry.fill(HIST("tests/nosub/JetPtEtaK0SZ"), jet.pt(), jet.eta(), z); + } + if (v0.isLambdaCandidate()) { + registry.fill(HIST("tests/nosub/JetPtEtaLambdaPt"), jet.pt(), jet.eta(), v0.pt()); + registry.fill(HIST("tests/nosub/JetPtEtaLambdaZ"), jet.pt(), jet.eta(), z); + } + if (v0.isAntiLambdaCandidate()) { + registry.fill(HIST("tests/nosub/JetPtEtaAntiLambdaPt"), jet.pt(), jet.eta(), v0.pt()); + registry.fill(HIST("tests/nosub/JetPtEtaAntiLambdaZ"), jet.pt(), jet.eta(), z); + } + + double r = gRandom->Uniform(); + if (r < v0Fraction) { // Accepted + v0Pt.push_back(v0.pt()); + if (v0.isK0SCandidate()) { + v0Type.push_back(0); + } else if (v0.isLambdaCandidate()) { + v0Type.push_back(1); + } else if (v0.isAntiLambdaCandidate()) { + v0Type.push_back(2); + } + } else { // Subtracted + ptjetsub -= v0.pt(); + } + } + + for (unsigned int i = 0; i < v0Pt.size(); ++i) { + registry.fill(HIST("tests/sub/JetPtEtaPhi"), ptjetsub, jet.eta(), jet.phi()); + + int type = v0Type[i]; + double pt = v0Pt[i]; + double z = pt / ptjetsub; + + registry.fill(HIST("tests/sub/JetPtEtaV0Pt"), ptjetsub, jet.eta(), pt); + registry.fill(HIST("tests/sub/JetPtEtaV0Z"), ptjetsub, jet.eta(), z); + + if (type == 0) { // K0S + registry.fill(HIST("tests/sub/JetPtEtaK0SPt"), ptjetsub, jet.eta(), pt); + registry.fill(HIST("tests/sub/JetPtEtaK0SZ"), ptjetsub, jet.eta(), z); + } else if (type == 1) { // Lambda + registry.fill(HIST("tests/sub/JetPtEtaLambdaPt"), ptjetsub, jet.eta(), pt); + registry.fill(HIST("tests/sub/JetPtEtaLambdaZ"), ptjetsub, jet.eta(), z); + } else if (type == 2) { // AntiLambda + registry.fill(HIST("tests/sub/JetPtEtaAntiLambdaPt"), ptjetsub, jet.eta(), pt); + registry.fill(HIST("tests/sub/JetPtEtaAntiLambdaZ"), ptjetsub, jet.eta(), z); + } + } + } + } + PROCESS_SWITCH(V0QA, processTestSubtractedJetFinder, "Test subtracted jet finder", false); + using DaughterJTracks = soa::Join; using DaughterTracks = soa::Join; void processV0TrackQA(aod::JetCollision const& /*jcoll*/, aod::CandidatesV0Data const& v0s, DaughterJTracks const&, DaughterTracks const&) From 9d38580d1310b880d4060112e247b049e16255b5 Mon Sep 17 00:00:00 2001 From: Florian Jonas Date: Sat, 28 Jun 2025 08:29:20 +0200 Subject: [PATCH 253/871] [PWGJE] GammaJetTree MC capabilities & perf improvements (#11776) Co-authored-by: ALICE Action Bot --- PWGJE/DataModel/GammaJetAnalysisTree.h | 98 +- PWGJE/Tasks/gammaJetTreeProducer.cxx | 1148 ++++++++++++++++++++++-- 2 files changed, 1146 insertions(+), 100 deletions(-) diff --git a/PWGJE/DataModel/GammaJetAnalysisTree.h b/PWGJE/DataModel/GammaJetAnalysisTree.h index 655fcdfbc37..02a9602ec6e 100644 --- a/PWGJE/DataModel/GammaJetAnalysisTree.h +++ b/PWGJE/DataModel/GammaJetAnalysisTree.h @@ -17,17 +17,45 @@ #ifndef PWGJE_DATAMODEL_GAMMAJETANALYSISTREE_H_ #define PWGJE_DATAMODEL_GAMMAJETANALYSISTREE_H_ -#include +#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include "PWGJE/DataModel/EMCALClusters.h" +#include "PWGJE/DataModel/Jet.h" -#include - -#include +#include "Framework/AnalysisDataModel.h" +namespace o2::aod::gjanalysis +{ +enum class ClusterOrigin { + kUnknown = 0, + kPhoton, // dominant amount of energy from the cluster is from a photon + kPromptPhoton, + kDirectPromptPhoton, + kFragmentationPhoton, + kDecayPhoton, // the particle that produced the cluster is a decay product + kDecayPhotonPi0, // the cluster was produced by a pi0 decay + kDecayPhotonEta, // the cluster was produced by a eta decay + kMergedPi0, // the cluster was produced by a merged pi0, i.e. two photons contribute to the cluster that both come from pi0 decay + kMergedEta, // the cluster was produced by a merged eta, i.e. two photons contribute to the cluster that both come from eta decay + kConvertedPhoton, // the cluster was produced by a converted photon, i.e. a photon that converted to an electron-positron pair and one of the electrons was detected in the cluster +}; +enum class ParticleOrigin { + kUnknown = 0, + kPromptPhoton, + kDirectPromptPhoton, + kFragmentationPhoton, + kDecayPhoton, + kDecayPhotonPi0, + kDecayPhotonEta, + kDecayPhotonOther, + kPi0 +}; +} // namespace o2::aod::gjanalysis namespace o2::aod { +// Collision level information namespace gjevent -{ // TODO add rho //! event index +{ //! event index DECLARE_SOA_COLUMN(Multiplicity, multiplicity, float); DECLARE_SOA_COLUMN(Centrality, centrality, float); DECLARE_SOA_COLUMN(Rho, rho, float); @@ -39,6 +67,16 @@ DECLARE_SOA_TABLE(GjEvents, "AOD", "GJEVENT", o2::soa::Index<>, gjevent::Multipl using GjEvent = GjEvents::iterator; +// Information about the MC collision that was matched to the reconstructed collision +namespace gjmcevent +{ +DECLARE_SOA_INDEX_COLUMN(GjEvent, gjevent); +DECLARE_SOA_COLUMN(Weight, weight, double); +DECLARE_SOA_COLUMN(Rho, rho, float); // gen level rho +DECLARE_SOA_COLUMN(IsMultipleAssigned, isMultipleAssigned, bool); // if the corresponding MC collision matched to this rec collision was also matched to other rec collisions (allows to skip those on analysis level ) +} // namespace gjmcevent +DECLARE_SOA_TABLE(GjMCEvents, "AOD", "GJMCEVENT", gjmcevent::GjEventId, gjmcevent::Weight, gjmcevent::Rho, gjmcevent::IsMultipleAssigned) +// Information about EMCal clusters namespace gjgamma { DECLARE_SOA_INDEX_COLUMN(GjEvent, gjevent); //! event index @@ -61,9 +99,32 @@ DECLARE_SOA_COLUMN(TMtrackP, tmtrackp, float); //! track } // namespace gjgamma DECLARE_SOA_TABLE(GjGammas, "AOD", "GJGAMMA", gjgamma::GjEventId, gjgamma::Energy, gjgamma::Definition, gjgamma::Eta, gjgamma::Phi, gjgamma::M02, gjgamma::M20, gjgamma::NCells, gjgamma::Time, gjgamma::IsExotic, gjgamma::DistanceToBadChannel, gjgamma::NLM, gjgamma::IsoRaw, gjgamma::PerpConeRho, gjgamma::TMdeltaPhi, gjgamma::TMdeltaEta, gjgamma::TMtrackP) -namespace gjchjet + +// MC information for reconstructed EMCal clusters +namespace gjgammamcinfo +{ +DECLARE_SOA_COLUMN(Origin, origin, uint16_t); +DECLARE_SOA_COLUMN(LeadingEnergyFraction, leadingEnergyFraction, float); // fraction of energy from the leading MC particle +} // namespace gjgammamcinfo +DECLARE_SOA_TABLE(GjGammaMCInfos, "AOD", "GJGAMMAMCINFO", gjgamma::GjEventId, gjgammamcinfo::Origin, gjgammamcinfo::LeadingEnergyFraction) + +// Generator level particle information from the MC collision that was matched to the reconstructed collision +namespace gjmcparticle { DECLARE_SOA_INDEX_COLUMN(GjEvent, gjevent); +DECLARE_SOA_COLUMN(Energy, energy, float); +DECLARE_SOA_COLUMN(Eta, eta, float); +DECLARE_SOA_COLUMN(Phi, phi, float); +DECLARE_SOA_COLUMN(Pt, pt, float); +DECLARE_SOA_COLUMN(PdgCode, pdgCode, ushort); // TODO also add smoe origin of particle? maybe only save original pi0 and eta and photon (not decay photons) +DECLARE_SOA_COLUMN(MCIsolation, mcIsolation, float); // isolation in cone on mc gen level +DECLARE_SOA_COLUMN(Origin, origin, uint16_t); // origin of particle +} // namespace gjmcparticle +DECLARE_SOA_TABLE(GjMCParticles, "AOD", "GJMCPARTICLE", gjmcparticle::GjEventId, gjmcparticle::Energy, gjmcparticle::Eta, gjmcparticle::Phi, gjmcparticle::Pt, gjmcparticle::PdgCode, gjmcparticle::MCIsolation, gjmcparticle::Origin) + +// Reconstructed charged jet information +namespace gjchjet +{ DECLARE_SOA_COLUMN(Pt, pt, float); DECLARE_SOA_COLUMN(Eta, eta, float); DECLARE_SOA_COLUMN(Phi, phi, float); @@ -75,7 +136,30 @@ DECLARE_SOA_COLUMN(LeadingTrackPt, leadingtrackpt, float); DECLARE_SOA_COLUMN(PerpConeRho, perpconerho, float); DECLARE_SOA_COLUMN(NConstituents, nConstituents, ushort); } // namespace gjchjet -DECLARE_SOA_TABLE(GjChargedJets, "AOD", "GJCHJET", gjchjet::GjEventId, gjchjet::Pt, gjchjet::Eta, gjchjet::Phi, gjchjet::Radius, gjchjet::Energy, gjchjet::Mass, gjchjet::Area, gjchjet::LeadingTrackPt, gjchjet::PerpConeRho, gjchjet::NConstituents) +DECLARE_SOA_TABLE(GjChargedJets, "AOD", "GJCHJET", gjgamma::GjEventId, gjchjet::Pt, gjchjet::Eta, gjchjet::Phi, gjchjet::Radius, gjchjet::Energy, gjchjet::Mass, gjchjet::Area, gjchjet::LeadingTrackPt, gjchjet::PerpConeRho, gjchjet::NConstituents) + +// MC information for reconstructed charged jet +namespace gjchjetmcinfo +{ +DECLARE_SOA_COLUMN(MatchedJetIndexGeo, matchedJetIndexGeo, int); +DECLARE_SOA_COLUMN(MatchedJetIndexPt, matchedJetIndexPt, int); +} // namespace gjchjetmcinfo +DECLARE_SOA_TABLE(GjChJetMCInfos, "AOD", "GJCHJETMCINFO", gjgamma::GjEventId, gjchjetmcinfo::MatchedJetIndexGeo, gjchjetmcinfo::MatchedJetIndexPt) + +// MC information for generator level jets of associated MC collision +namespace gjmcjet +{ +DECLARE_SOA_COLUMN(Pt, pt, float); +DECLARE_SOA_COLUMN(Eta, eta, float); +DECLARE_SOA_COLUMN(Phi, phi, float); +DECLARE_SOA_COLUMN(Radius, radius, float); +DECLARE_SOA_COLUMN(Energy, energy, float); +DECLARE_SOA_COLUMN(Mass, mass, float); +DECLARE_SOA_COLUMN(Area, area, float); +DECLARE_SOA_COLUMN(PerpConeRho, perpconerho, float); +} // namespace gjmcjet +DECLARE_SOA_TABLE(GjMCJets, "AOD", "GJMCJET", gjgamma::GjEventId, gjmcjet::Pt, gjmcjet::Eta, gjmcjet::Phi, gjmcjet::Radius, gjmcjet::Energy, gjmcjet::Mass, gjmcjet::Area, gjmcjet::PerpConeRho) + } // namespace o2::aod #endif // PWGJE_DATAMODEL_GAMMAJETANALYSISTREE_H_ diff --git a/PWGJE/Tasks/gammaJetTreeProducer.cxx b/PWGJE/Tasks/gammaJetTreeProducer.cxx index 42dbfa869ef..df20989b93a 100644 --- a/PWGJE/Tasks/gammaJetTreeProducer.cxx +++ b/PWGJE/Tasks/gammaJetTreeProducer.cxx @@ -1,4 +1,4 @@ -// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// 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. // @@ -9,59 +9,78 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -/// \struct GammaJetTreeProducer -/// \brief Task to produce a tree for gamma-jet analysis, including photons (and information of isolation) and charged and full jets +/// \file gammaJetTreeProducer.cxx +/// \brief Task to produce a tree for gamma-jet analysis, including photons (and information of isolation) and charged jets /// \author Florian Jonas , UC Berkeley/LBNL /// \since 02.08.2024 -/// +// C++ system headers first +#include + +#include +#include +#include + +// Framework and other headers after +#include "PWGJE/Core/FastJetUtilities.h" #include "PWGJE/Core/JetDerivedDataUtilities.h" #include "PWGJE/Core/JetUtilities.h" +#include "PWGJE/DataModel/EMCALClusters.h" #include "PWGJE/DataModel/GammaJetAnalysisTree.h" #include "PWGJE/DataModel/Jet.h" -#include "PWGJE/DataModel/JetReducedData.h" -#include "PWGJE/DataModel/JetSubtraction.h" #include "Common/Core/RecoDecay.h" +#include "Common/Core/TrackSelection.h" +#include "Common/Core/TrackSelectionDefaults.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "EventFiltering/filterTables.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include "CommonDataFormat/InteractionRecord.h" +#include "DataFormatsEMCAL/AnalysisCluster.h" +#include "DataFormatsEMCAL/Cell.h" +#include "DataFormatsEMCAL/Constants.h" +#include "EMCALBase/Geometry.h" +#include "EMCALCalib/BadChannelMap.h" +#include "Framework/ASoA.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/O2DatabasePDGPlugin.h" #include "TVector2.h" -#include - -#include - -#include -#include -#include -#include - -#include +// \struct GammaJetTreeProducer +/// \brief Task to produce a tree for gamma-jet analysis, including photons (and information of isolation) and charged and full jets +/// \author Florian Jonas , UC Berkeley/LBNL +/// \since 02.08.2024 +/// using namespace o2; using namespace o2::aod; using namespace o2::framework; using namespace o2::framework::expressions; using emcClusters = o2::soa::Join; +using emcMCClusters = o2::soa::Join; + +#include "Framework/runDataProcessing.h" struct GammaJetTreeProducer { // analysis tree // charged jets // photon candidates - Produces chargedJetsTable; - Produces eventsTable; - Produces gammasTable; + Produces chargedJetsTable; // detector level jets + Produces eventsTable; // rec events + Produces gammasTable; // detector level clusters + Produces mcEventsTable; // mc collisions information + Produces mcParticlesTable; // gen level particles (photons and pi0) + Produces gammaMCInfosTable; // detector level clusters MC information + Produces chJetMCInfosTable; // detector level charged jets MC information + Produces mcJetsTable; // gen level jets HistogramRegistry mHistograms{"GammaJetTreeProducerHisto"}; + Service pdg; + // --------------- // Configureables // --------------- @@ -78,13 +97,27 @@ struct GammaJetTreeProducer { Configurable perpConeJetR{"perpConeJetR", 0.4, "perpendicular cone radius used to calculate perp cone rho for jet"}; Configurable trackMatchingEoverP{"trackMatchingEoverP", 2.0, "closest track is required to have E/p < value"}; Configurable minClusterETrigger{"minClusterETrigger", 0.0, "minimum cluster energy to trigger"}; + Configurable minMCGenPt{"minMCGenPt", 0.0, "minimum pt of mc gen particles to store"}; int mRunNumber = 0; std::vector eventSelectionBits; int trackSelection = -1; + const int kMaxRecursionDepth = 100; std::unordered_map collisionMapping; + std::unordered_map mcJetIndexMapping; // maps the global index to the index in the mc jets table (per event). This is because later we want to later construct all trees on a per event level, and we need to know at what position in the table per event this is stored std::vector triggerMaskBits; + std::vector mcCollisionsMultiRecCollisions; // used for MC. global index of MC collisions that have multiple matched rec collisions + + // kd tree for tracks and mc particles (used for fast isolation calculation) + std::vector trackEta; + std::vector trackPhi; + std::vector trackPt; + std::vector mcParticleEta; + std::vector mcParticlePhi; + std::vector mcParticlePt; + TKDTree* trackTree = nullptr; + TKDTree* mcParticleTree = nullptr; void init(InitContext const&) { @@ -99,25 +132,152 @@ struct GammaJetTreeProducer { LOG(info) << "Creating histograms"; const o2Axis ptAxis{100, 0, 200, "p_{T} (GeV/c)"}; + const o2Axis ptRecAxis{100, 0, 200, "p_{T}^{rec} (GeV/c)"}; + const o2Axis ptGenAxis{100, 0, 200, "p_{T}^{gen} (GeV/c)"}; const o2Axis energyAxis{100, 0, 100, "E (GeV)"}; const o2Axis m02Axis{100, 0, 3, "m02"}; const o2Axis etaAxis{100, -1, 1, "#eta"}; - const o2Axis phiAxis{100, 0, 2 * TMath::Pi(), "#phi"}; + const o2Axis phiAxis{100, 0, o2::constants::math::TwoPI, "#phi"}; + const o2Axis dRAxis{100, 0, 1, "dR"}; const o2Axis occupancyAxis{300, 0, 30000, "occupancy"}; + const o2Axis nCollisionsAxis{10, -0.5, 9.5, "nCollisions"}; mHistograms.add("clusterE", "Energy of cluster", o2HistType::kTH1F, {energyAxis}); mHistograms.add("trackPt", "pT of track", o2HistType::kTH1F, {ptAxis}); mHistograms.add("chjetPt", "pT of charged jet", o2HistType::kTH1F, {ptAxis}); mHistograms.add("chjetPtEtaPhi", "pT of charged jet", o2HistType::kTHnSparseF, {ptAxis, etaAxis, phiAxis}); - mHistograms.add("chjetpt_vs_constpt", "pT of charged jet vs pT of constituents", o2HistType::kTH2F, {ptAxis, ptAxis}); + mHistograms.add("chjetpt_vs_constpt", "pT of charged jet vs pT of constituents", o2HistType::kTH2F, {ptRecAxis, ptGenAxis}); // track QA THnSparse mHistograms.add("trackPtEtaPhi", "Track QA", o2HistType::kTHnSparseF, {ptAxis, etaAxis, phiAxis}); mHistograms.add("trackPtEtaOccupancy", "Track QA vs occupancy", o2HistType::kTHnSparseF, {ptAxis, etaAxis, occupancyAxis}); + + // QA for MC collisions to rec collision matching + // number of reconstructed and matched collisions for each MC collision vs mc gen photon energy + mHistograms.add("numberRecCollisionsVsPhotonPt", "Number of rec collisions vs photon energy", o2HistType::kTH2F, {nCollisionsAxis, energyAxis}); + + // Cluster MC histograms + mHistograms.add("clusterMC_E_All", "Cluster energy for photons", o2HistType::kTH1F, {energyAxis}); + mHistograms.add("clusterMC_E_Photon", "Cluster energy for photons", o2HistType::kTH1F, {energyAxis}); + mHistograms.add("clusterMC_E_PromptPhoton", "Cluster energy for prompt photons", o2HistType::kTH1F, {energyAxis}); + mHistograms.add("clusterMC_E_DirectPromptPhoton", "Cluster energy for direct prompt photons", o2HistType::kTH1F, {energyAxis}); + mHistograms.add("clusterMC_E_FragmentationPhoton", "Cluster energy for fragmentation photons", o2HistType::kTH1F, {energyAxis}); + mHistograms.add("clusterMC_E_DecayPhoton", "Cluster energy for decay photons", o2HistType::kTH1F, {energyAxis}); + mHistograms.add("clusterMC_E_DecayPhotonPi0", "Cluster energy for decay photons from pi0", o2HistType::kTH1F, {energyAxis}); + mHistograms.add("clusterMC_E_DecayPhotonEta", "Cluster energy for decay photons from eta", o2HistType::kTH1F, {energyAxis}); + mHistograms.add("clusterMC_E_MergedPi0", "Cluster energy for merged pi0s", o2HistType::kTH1F, {energyAxis}); + mHistograms.add("clusterMC_E_MergedEta", "Cluster energy for merged etas", o2HistType::kTH1F, {energyAxis}); + mHistograms.add("clusterMC_E_ConvertedPhoton", "Cluster energy for converted photons", o2HistType::kTH1F, {energyAxis}); + mHistograms.add("clusterMC_m02_Photon", "M02 for photons", o2HistType::kTH1F, {m02Axis}); + mHistograms.add("clusterMC_m02_PromptPhoton", "M02 for prompt photons", o2HistType::kTH1F, {m02Axis}); + mHistograms.add("clusterMC_m02_DirectPromptPhoton", "M02 for direct prompt photons", o2HistType::kTH1F, {m02Axis}); + mHistograms.add("clusterMC_m02_FragmentationPhoton", "M02 for fragmentation photons", o2HistType::kTH1F, {m02Axis}); + mHistograms.add("clusterMC_m02_DecayPhoton", "M02 for decay photons", o2HistType::kTH1F, {m02Axis}); + mHistograms.add("clusterMC_m02_DecayPhotonPi0", "M02 for decay photons from pi0", o2HistType::kTH1F, {m02Axis}); + mHistograms.add("clusterMC_m02_DecayPhotonEta", "M02 for decay photons from eta", o2HistType::kTH1F, {m02Axis}); + mHistograms.add("clusterMC_m02_MergedPi0", "M02 for merged pi0s", o2HistType::kTH1F, {m02Axis}); + mHistograms.add("clusterMC_m02_MergedEta", "M02 for merged etas", o2HistType::kTH1F, {m02Axis}); + mHistograms.add("clusterMC_m02_ConvertedPhoton", "M02 for converted photons", o2HistType::kTH1F, {m02Axis}); + + // MC Gen trigger particle histograms + mHistograms.add("mcGenTrigger_Eta", "eta of mc gen trigger particle", o2HistType::kTH1F, {etaAxis}); + mHistograms.add("mcGenTrigger_Phi", "phi of mc gen trigger particle", o2HistType::kTH1F, {phiAxis}); + mHistograms.add("mcGenTrigger_Pt", "pT of mc gen trigger particle", o2HistType::kTH1F, {ptAxis}); + mHistograms.add("mcGenTrigger_E", "E of mc gen trigger particle", o2HistType::kTH1F, {energyAxis}); + mHistograms.add("mcGenTrigger_E_PromptPhoton", "E of mc gen trigger prompt photon", o2HistType::kTH1F, {energyAxis}); + mHistograms.add("mcGenTrigger_E_DirectPromptPhoton", "E of mc gen trigger direct prompt photon", o2HistType::kTH1F, {energyAxis}); + mHistograms.add("mcGenTrigger_E_FragmentationPhoton", "E of mc gen trigger fragmentation photon", o2HistType::kTH1F, {energyAxis}); + mHistograms.add("mcGenTrigger_E_DecayPhoton", "E of mc gen trigger decay photon", o2HistType::kTH1F, {energyAxis}); + mHistograms.add("mcGenTrigger_E_DecayPhotonPi0", "E of mc gen trigger decay photon from pi0", o2HistType::kTH1F, {energyAxis}); + mHistograms.add("mcGenTrigger_E_DecayPhotonEta", "E of mc gen trigger decay photon from eta", o2HistType::kTH1F, {energyAxis}); + mHistograms.add("mcGenTrigger_E_DecayPhotonOther", "E of mc gen trigger decay photon from other", o2HistType::kTH1F, {energyAxis}); + mHistograms.add("mcGenTrigger_E_Pi0", "E of mc gen trigger pi0", o2HistType::kTH1F, {energyAxis}); + + // MC Particle level jet histograms + mHistograms.add("mcpJetPt", "pT of mc particle level jet", o2HistType::kTH1F, {ptAxis}); + + // MC Detector level jet matching jet histograms + mHistograms.add("mcdJetPtVsTrueJetPtMatchingGeo", "pT rec (x-axis) of detector level jets vs pT true (y-axis) of mc particle level jet (geo matching)", o2HistType::kTH2F, {ptRecAxis, ptGenAxis}); + mHistograms.add("mcdJetPtVsTrueJetPtMatchingPt", "pT rec (x-axis) of detector level jets vs pT true (y-axis) of mc particle level jet (pt matching)", o2HistType::kTH2F, {ptRecAxis, ptGenAxis}); + + // Event QA histogram + const int nEventBins = 8; + const TString eventLabels[nEventBins] = {"All", "AfterVertexCut", "AfterCollisionSelection", "AfterTriggerSelection", "AfterEMCALSelection", "AfterClusterESelection", "Has MC collision", "is not MB Gap"}; + mHistograms.add("eventQA", "Event QA", o2HistType::kTH1F, {{nEventBins, -0.5, 7.5}}); + for (int iBin = 0; iBin < nEventBins; iBin++) { + mHistograms.get(HIST("eventQA"))->GetXaxis()->SetBinLabel(iBin + 1, eventLabels[iBin]); + } + + // MC collisions QA histograms) + const int nRecCollisionBins = 4; + const TString recCollisionLabels[nRecCollisionBins] = {"All", "1 Rec collision", "More than 1 rec collisions", "No rec collisions"}; + mHistograms.add("mcCollisionsWithRecCollisions", "MC collisions with rec collisions", o2HistType::kTH1F, {{nRecCollisionBins, -0.5, 3.5}}); + for (int iBin = 0; iBin < nRecCollisionBins; iBin++) { + mHistograms.get(HIST("mcCollisionsWithRecCollisions"))->GetXaxis()->SetBinLabel(iBin + 1, recCollisionLabels[iBin]); + } } // --------------------- // Helper functions // --------------------- + + /// \brief Builds the kd tree for the tracks or mc particles (used for fast isolation calculation) + /// \param objects The objects to build the kd tree for (tracks or mc particles) + template + void buildKdTree(const T& objects) + { + 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>) { + for (const auto& track : objects) { + if (!isTrackSelected(track)) { + continue; + } + trackEta.push_back(track.eta()); + trackPhi.push_back(track.phi()); + trackPt.push_back(track.pt()); + } + if (trackEta.size() > 0) { + delete trackTree; + trackTree = new TKDTree(trackEta.size(), 2, 1); + trackTree->SetData(0, trackEta.data()); + trackTree->SetData(1, trackPhi.data()); + trackTree->Build(); + } + } + // 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>) { + for (const auto& particle : objects) { + if (!particle.isPhysicalPrimary()) { + continue; + } + if (!isCharged(particle)) { + continue; + } + if (particle.pt() < trackMinPt) { + continue; + } + mcParticleEta.push_back(particle.eta()); + mcParticlePhi.push_back(particle.phi()); + mcParticlePt.push_back(particle.pt()); + } + if (mcParticleEta.size() > 0) { + delete mcParticleTree; + mcParticleTree = new TKDTree(mcParticleEta.size(), 2, 1); + mcParticleTree->SetData(0, mcParticleEta.data()); + mcParticleTree->SetData(1, mcParticlePhi.data()); + mcParticleTree->Build(); + } + } + } + /// \brief Checks if a track passes the selection criteria + /// \param track The track to be checked + /// \return true if track passes all selection criteria, false otherwise bool isTrackSelected(const auto& track) { if (!jetderiveddatautilities::selectTrack(track, trackSelection)) { @@ -130,6 +290,9 @@ struct GammaJetTreeProducer { return true; } + /// \brief Gets the stored collision index from the collision mapping + /// \param collision The collision to look up + /// \return The stored collision index, or -1 if not found int getStoredColIndex(const auto& collision) { int32_t storedColIndex = -1; @@ -139,50 +302,149 @@ struct GammaJetTreeProducer { return storedColIndex; } + /// \brief Checks if an event passes all selection criteria + /// \param collision The collision to check + /// \param clusters The EMCAL clusters in the event + /// \return true if event passes all selection criteria, false otherwise bool isEventAccepted(const auto& collision, const auto& clusters) { + mHistograms.fill(HIST("eventQA"), 0); if (collision.posZ() > mVertexCut) { return false; } + mHistograms.fill(HIST("eventQA"), 1); if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits)) { return false; } + mHistograms.fill(HIST("eventQA"), 2); if (!jetderiveddatautilities::selectTrigger(collision, triggerMaskBits)) { return false; } + mHistograms.fill(HIST("eventQA"), 3); if (!jetderiveddatautilities::eventEMCAL(collision)) { return false; } + mHistograms.fill(HIST("eventQA"), 4); // Check if event contains a cluster with energy > minClusterETrigger - for (auto cluster : clusters) { + for (const auto& cluster : clusters) { if (cluster.energy() > minClusterETrigger) { + mHistograms.fill(HIST("eventQA"), 5); return true; } } return false; } - double ch_iso_in_cone(const auto& cluster, aod::JetTracks const& tracks, float radius = 0.4) + /// \brief Checks if a particle is charged + /// \param particle The MC particle to check + /// \return true if particle has non-zero charge, false otherwise + bool isCharged(const auto& particle) + { + return std::abs(pdg->GetParticle(particle.pdgCode())->Charge()) >= 1.; + } + + /// \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 + /// \param mcGenIso Whether to use the mc gen particle tree (if false, use the track tree) + /// \return The charged particle isolation + template + double ch_iso_in_cone(const T& particle, float radius = 0.4, bool mcGenIso = false) { double iso = 0; - for (auto track : tracks) { - if (!isTrackSelected(track)) { - continue; + float point[2] = {particle.eta(), particle.phi()}; + std::vector indices; + + if (!mcGenIso) { + if (trackTree) { + trackTree->FindInRange(point, radius, indices); + for (const auto& index : indices) { + iso += trackPt[index]; + } + } else { + LOG(error) << "Track tree not found"; + return 0; } - // make dR function live somwhere else - float dR = jetutilities::deltaR(cluster, track); - if (dR < radius) { - iso += track.pt(); + } else { + if (mcParticleTree) { + mcParticleTree->FindInRange(point, radius, indices); + for (const auto& index : indices) { + iso += mcParticlePt[index]; + } + } else { + LOG(error) << "MC particle tree not found"; + return 0; } } return iso; } + /// \brief Calculates the charged particle density in perpendicular cones + /// \param object The reference object (cluster or jet) + /// \param tracks The tracks to check + /// \param radius The cone radius for density calculation + /// \return The average charged particle density in the perpendicular cones + template + double ch_perp_cone_rho(const T& object, float radius = 0.4, bool mcGenIso = false) + { + double ptSumLeft = 0; + double ptSumRight = 0; + + 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 pointLeft[2] = {object.eta(), cPhiLeft}; + float pointRight[2] = {object.eta(), cPhiRight}; + + std::vector indicesLeft; + std::vector indicesRight; + + if (!mcGenIso) { + if (trackTree) { + trackTree->FindInRange(pointLeft, radius, indicesLeft); + trackTree->FindInRange(pointRight, radius, indicesRight); + } else { + LOG(error) << "Track tree not found"; + return 0; + } + + for (const auto& index : indicesLeft) { + ptSumLeft += trackPt[index]; + } + for (const auto& index : indicesRight) { + ptSumRight += trackPt[index]; + } + } else { + if (mcParticleTree) { + mcParticleTree->FindInRange(pointLeft, radius, indicesLeft); + mcParticleTree->FindInRange(pointRight, radius, indicesRight); + } else { + 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]; + } + } + + float rho = (ptSumLeft + ptSumRight) / (o2::constants::math::TwoPI * radius * radius); + return rho; + } + + /// \brief Fills track QA histograms for a given collision + /// \param collision The collision containing the tracks + /// \param tracks The tracks to analyze void runTrackQA(const auto& collision, aod::JetTracks const& tracks) { - for (auto track : tracks) { + for (const auto& track : tracks) { if (!isTrackSelected(track)) { continue; } @@ -192,50 +454,489 @@ struct GammaJetTreeProducer { } } - double ch_perp_cone_rho(const auto& object, aod::JetTracks const& tracks, float radius = 0.4) + /// \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 + template + T iTopCopy(const T& particle) const { - double ptSumLeft = 0; - double ptSumRight = 0; + int iUp = particle.globalIndex(); + 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]; + mothers = currentParticle.template mothers_as(); + } + return currentParticle; + } - double cPhi = TVector2::Phi_0_2pi(object.phi()); + /// \brief Checks if a particle is a prompt photon + /// \param particle The MC particle to check + /// \return true if particle is a prompt photon, false otherwise + bool isPromptPhoton(const auto& particle) + { + if (particle.pdgCode() == PDG_t::kGamma && particle.isPhysicalPrimary() && std::abs(particle.getGenStatusCode()) < 90) { + return true; + } + return false; + } + /// \brief Checks if a particle is a direct prompt photon + /// \param particle The particle to check + /// \return true if particle is a direct prompt photon, false otherwise + bool isDirectPromptPhoton(const auto& particle) + { + // check if particle isa prompt photon + if (particle.pdgCode() == PDG_t::kGamma && particle.isPhysicalPrimary() && std::abs(particle.getGenStatusCode()) < 90) { + // find the top carbon copy + auto topCopy = iTopCopy(particle); + if (topCopy.pdgCode() == PDG_t::kGamma && std::abs(topCopy.getGenStatusCode()) < 40) { // < 40 is particle directly produced in hard scattering + return true; + } + } + return false; + } + /// \brief Checks if a particle is a fragmentation photon + /// \param particle The particle to check + /// \return true if particle is a fragmentation photon, false otherwise + bool isFragmentationPhoton(const auto& particle) + { + if (particle.pdgCode() == PDG_t::kGamma && particle.isPhysicalPrimary() && std::abs(particle.getGenStatusCode()) < 90) { + // find the top carbon copy + auto topCopy = iTopCopy(particle); + if (topCopy.pdgCode() == PDG_t::kGamma && std::abs(topCopy.getGenStatusCode()) >= 40) { // frag photon + return true; + } + } + return false; + } + /// \brief Checks if a particle is a decay photon + /// \param particle The particle to check + /// \return true if particle is a decay photon, false otherwise + bool isDecayPhoton(const auto& particle) + { + if (particle.pdgCode() == PDG_t::kGamma && particle.isPhysicalPrimary() && std::abs(particle.getGenStatusCode()) >= 90) { + return true; + } + return false; + } + /// \brief Checks if a particle is a decay photon from pi0 + /// \param particle The particle to check + /// \return true if particle is a decay photon from pi0, false otherwise + template + bool isDecayPhotonPi0(const T& particle) + { + if (particle.pdgCode() == PDG_t::kGamma && particle.isPhysicalPrimary() && std::abs(particle.getGenStatusCode()) >= 90) { + // check if it has mothers that are pi0s + const auto& mothers = particle.template mothers_as(); + for (const auto& mother : mothers) { + if (mother.pdgCode() == PDG_t::kPi0) { + return true; + } + } + } + return false; + } + /// \brief Checks if a particle is a decay photon from eta + /// \param particle The particle to check + /// \return true if particle is a decay photon from eta, false otherwise + template + bool isDecayPhotonEta(const T& particle) + { + if (particle.pdgCode() == PDG_t::kGamma && particle.isPhysicalPrimary() && std::abs(particle.getGenStatusCode()) >= 90) { + // check if it has mothers that are etas + const auto& mothers = particle.template mothers_as(); + for (const auto& mother : mothers) { + if (mother.pdgCode() == 221) { + return true; + } + } + } + return false; + } + /// \brief Checks if a particle is a decay photon from other sources + /// \param particle The particle to check + /// \return true if particle is a decay photon from other sources, false otherwise + template + bool isDecayPhotonOther(const T& particle) + { + if (particle.pdgCode() == PDG_t::kGamma && particle.isPhysicalPrimary() && std::abs(particle.getGenStatusCode()) >= 90) { + // check if you find a pi0 mother or a eta mother + const auto& mothers = particle.template mothers_as(); + for (const auto& mother : mothers) { + if (mother.pdgCode() == PDG_t::kPi0 || mother.pdgCode() == 221) { + return false; + } + } + return true; + } + return false; + } + /// \brief Checks if a particle is a pi0 + /// \param particle The particle to check + /// \return true if particle is a pi0, false otherwise + bool isPi0(const auto& particle) + { + if (particle.pdgCode() == PDG_t::kPi0) { + return true; + } + return false; + } - // rotate cone left by 90 degrees - float cPhiLeft = cPhi - TMath::Pi() / 2; - float cPhiRight = cPhi + TMath::Pi() / 2; + /// \brief Gets the bitmap for a MC particle that indicated what type of particle it is + /// \param particle The particle to check + /// \return A bitmap indicating the particle's origin + uint16_t getMCParticleOrigin(const auto& particle) + { + uint16_t origin = 0; + if (isPromptPhoton(particle)) { + SETBIT(origin, static_cast(gjanalysis::ParticleOrigin::kPromptPhoton)); + } + if (isDirectPromptPhoton(particle)) { + SETBIT(origin, static_cast(gjanalysis::ParticleOrigin::kDirectPromptPhoton)); + } + if (isFragmentationPhoton(particle)) { + SETBIT(origin, static_cast(gjanalysis::ParticleOrigin::kFragmentationPhoton)); + } + if (isDecayPhoton(particle)) { + SETBIT(origin, static_cast(gjanalysis::ParticleOrigin::kDecayPhoton)); + } + if (isDecayPhotonPi0(particle)) { + SETBIT(origin, static_cast(gjanalysis::ParticleOrigin::kDecayPhotonPi0)); + } + if (isDecayPhotonEta(particle)) { + SETBIT(origin, static_cast(gjanalysis::ParticleOrigin::kDecayPhotonEta)); + } + if (isDecayPhotonOther(particle)) { + SETBIT(origin, static_cast(gjanalysis::ParticleOrigin::kDecayPhotonOther)); + } + if (isPi0(particle)) { + SETBIT(origin, static_cast(gjanalysis::ParticleOrigin::kPi0)); + } + return origin; + } - // loop over tracks - float dRLeft, dRRight; - for (auto track : tracks) { - if (!isTrackSelected(track)) { - continue; + /// \brief Gets the index of a mother particle with specific PDG code in the decay chain (upwards) + /// \param particle The particle to start from + /// \param mcParticles The MC particles collection + /// \param pdgCode The PDG code to search for + /// \return The index of the mother particle, or -1 if not found + template + int getIndexMotherChain(const T& particle, aod::JMcParticles const& mcParticles, int pdgCode, int depth = 0) + { + // Limit recursion depth to avoid infinite loops + if (depth > kMaxRecursionDepth) { // 100 generations should be more than enough + return -1; + } + const auto& mothers = particle.template mothers_as(); + for (const auto& mother : mothers) { + if (mother.pdgCode() == pdgCode) { + return mother.globalIndex(); + } else { + return getIndexMotherChain(mother, mcParticles, pdgCode, depth + 1); } - dRLeft = jetutilities::deltaR(object.eta(), cPhiLeft, track.eta(), track.phi()); - dRRight = jetutilities::deltaR(object.eta(), cPhiRight, track.eta(), track.phi()); + } + return -1; + } + // return recursive list of all daughter IDs + /// \brief Gets all daughter particle IDs in the decay chain + /// \param particle The particle to start from + /// \return Vector of daughter particle IDs + template + std::vector getDaughtersInChain(const T& particle, int depth = 0) + { + std::vector daughters; + // Limit recursion depth to avoid infinite loops + if (depth > kMaxRecursionDepth) { // 100 generations should be more than enough + return daughters; + } + T currentParticle = particle; + while (currentParticle.has_daughters()) { + const auto& daughtersIDs = currentParticle.template daughters_as(); + for (const auto& daughter : daughtersIDs) { + daughters.push_back(daughter.globalIndex()); + } + currentParticle = daughtersIDs.iteratorAt(0); + depth++; + if (depth > kMaxRecursionDepth) { + break; + } + } + return daughters; + } + /// \brief Finds the first physical primary particle in the decay chain (upwards) + /// \param particle The particle to start from + /// \return The index of the first physical primary particle, or -1 if not found + template + int findPhysicalPrimaryInChain(const T& particle, int depth = 0) + { + // Limit recursion depth to avoid infinite loops + if (depth > kMaxRecursionDepth) { // 100 generations should be more than enough + return -1; + } - if (dRLeft < radius) { - ptSumLeft += track.pt(); + // first check if current particle is physical primary + if (particle.isPhysicalPrimary()) { + return particle.globalIndex(); + } + + // check if the particle has mothers + if (!particle.has_mothers()) + return -1; + + // now get mothers + const auto mothers = particle.template mothers_as(); + if (mothers.size() == 0) + return -1; + + // get first mother + for (const auto& mother : mothers) { + int primaryIndex = findPhysicalPrimaryInChain(mother, depth + 1); + if (primaryIndex >= 0) { + return primaryIndex; } - if (dRRight < radius) { - ptSumRight += track.pt(); + break; // only check first mother + } + + return -1; + } + + /// \brief Checks if a cluster is merged from particles of a specific PDG decay to two gammas. A cluster is considered merged if the leading and subleading contribution to a cluster come from two photons that are part of a pi0 decay + /// \param cluster The cluster to check + /// \param mcParticles The MC particles collection + /// \param pdgCode The PDG code to check for + /// \return true if cluster is merged from the specified decay, false otherwise + template + bool isMergedFromPDGDecay(const T& cluster, U const& mcParticles, int pdgCode) + { + auto inducerIDs = cluster.mcParticlesIds(); + if (inducerIDs.size() < 2) { // it can not me "merged" if it has less than 2 inducers + return false; + } + + bool isMerged = false; + int motherIndex = getIndexMotherChain(mcParticles.iteratorAt(inducerIDs[0]), mcParticles, pdgCode); + if (motherIndex != -1) { + const auto& mother = mcParticles.iteratorAt(motherIndex); + + // get daughters of pi0 mother + auto daughtersMother = mother.template daughters_as(); + // check if there are two daughters that are both photons + if (daughtersMother.size() == 2) { + const auto& daughter1 = daughtersMother.iteratorAt(0); + const auto& daughter2 = daughtersMother.iteratorAt(1); + if (daughter1.pdgCode() == PDG_t::kGamma && daughter2.pdgCode() == PDG_t::kGamma) { + // get the full stack of particles that these daughters create + auto fullDecayChain1 = getDaughtersInChain(daughter1); + auto fullDecayChain2 = getDaughtersInChain(daughter2); + bool photon1Found = false; + bool photon2Found = false; + + // check if any of the particles in the fullDecayChain are leading or subleading in the cluster + for (const auto& particleID : fullDecayChain1) { + if (particleID == inducerIDs[0] || particleID == inducerIDs[1]) { + photon1Found = true; + } + } + for (const auto& particleID : fullDecayChain2) { + if (particleID == inducerIDs[0] || particleID == inducerIDs[1]) { + photon2Found = true; + } + } + if (photon1Found && photon2Found) { + isMerged = true; + } + } } } + return isMerged; + } - float rho = (ptSumLeft + ptSumRight) / (2 * TMath::Pi() * radius * radius); - return rho; + // determine cluster origin + /// \brief Gets the origin bitmap for a cluster + /// \param cluster The cluster to check + /// \param mcParticles The MC particles collection + /// \return A bitmap indicating the cluster's origin + template + uint16_t getClusterOrigin(const T& cluster, U const& mcParticles) + { + uint16_t origin = 0; + auto inducerIDs = cluster.mcParticlesIds(); + if (inducerIDs.size() == 0) { + SETBIT(origin, static_cast(gjanalysis::ClusterOrigin::kUnknown)); + return origin; + } + + // loop over all inducers and print their energy + LOG(debug) << "Cluster with energy: " << cluster.energy() << " and nInducers: " << inducerIDs.size(); + LOG(debug) << "Number of stored amplitudes: " << cluster.amplitudeA().size(); + int aCounter = 0; + for (const auto& inducerID : inducerIDs) { + const auto& inducer = mcParticles.iteratorAt(inducerID); + int motherPDG = -1; + if (inducer.has_mothers()) { + motherPDG = inducer.template mothers_as()[0].pdgCode(); + } + LOG(debug) << "Inducer energy: " << inducer.energy() << " amplitude: " << cluster.amplitudeA()[aCounter] << " and PDG: " << inducer.pdgCode() << " isPhysicalPrimary: " << inducer.isPhysicalPrimary() << " motherPDG: " << motherPDG; + aCounter++; + } + + // check if leading energy contribution is from a photon + const auto& leadingParticle = mcParticles.iteratorAt(inducerIDs[0]); + LOG(debug) << "Leading particle: PDG" << leadingParticle.pdgCode(); + // leading particle primary ID + int leadingParticlePrimaryID = findPhysicalPrimaryInChain(leadingParticle); + LOG(debug) << "Leading particle primary ID: " << leadingParticlePrimaryID; + if (leadingParticlePrimaryID == -1) { + SETBIT(origin, static_cast(gjanalysis::ClusterOrigin::kUnknown)); + return origin; + } + const auto& leadingParticlePrimary = mcParticles.iteratorAt(leadingParticlePrimaryID); + LOG(debug) << "Leading particle primary PDG: " << leadingParticlePrimary.pdgCode(); + if (leadingParticlePrimary.pdgCode() == PDG_t::kGamma) { + LOG(debug) << "Leading particle primary is a photon"; + SETBIT(origin, static_cast(gjanalysis::ClusterOrigin::kPhoton)); + } + if (isPromptPhoton(leadingParticlePrimary)) { + SETBIT(origin, static_cast(gjanalysis::ClusterOrigin::kPromptPhoton)); + LOG(debug) << "Leading particle primary is a prompt photon"; + } + if (isDirectPromptPhoton(leadingParticlePrimary)) { + SETBIT(origin, static_cast(gjanalysis::ClusterOrigin::kDirectPromptPhoton)); + LOG(debug) << "Leading particle primary is a direct prompt photon"; + } + if (isFragmentationPhoton(leadingParticlePrimary)) { + SETBIT(origin, static_cast(gjanalysis::ClusterOrigin::kFragmentationPhoton)); + LOG(debug) << "Leading particle primary is a fragmentation photon"; + } + if (isDecayPhoton(leadingParticlePrimary)) { + SETBIT(origin, static_cast(gjanalysis::ClusterOrigin::kDecayPhoton)); + LOG(debug) << "Leading particle primary is a decay photon"; + } + if (isDecayPhotonPi0(leadingParticlePrimary)) { + SETBIT(origin, static_cast(gjanalysis::ClusterOrigin::kDecayPhotonPi0)); + LOG(debug) << "Leading particle primary is a decay photon from pi0"; + } + if (isDecayPhotonEta(leadingParticlePrimary)) { + SETBIT(origin, static_cast(gjanalysis::ClusterOrigin::kDecayPhotonEta)); + LOG(debug) << "Leading particle primary is a decay photon from eta"; + } + + // Do checks if a cluster is a merged pi0 decay + // we classify a cluster as merged pi0 if the leading and subleading contribution to a cluster come from two photons that are part of a pi0 decay + if (isMergedFromPDGDecay(cluster, mcParticles, PDG_t::kPi0)) { + SETBIT(origin, static_cast(gjanalysis::ClusterOrigin::kMergedPi0)); + LOG(debug) << "Cluster is a merged pi0"; + } + if (isMergedFromPDGDecay(cluster, mcParticles, 221)) { + SETBIT(origin, static_cast(gjanalysis::ClusterOrigin::kMergedEta)); + LOG(debug) << "Cluster is a merged eta"; + } + + // check if photon conversion + // check that leading contribution is an electron or positron + LOG(debug) << "Checking if cluster is a converted photon"; + if (std::abs(leadingParticle.pdgCode()) == PDG_t::kElectron) { + // make sure this electron is not a physicsl primary and has mothers + if (!leadingParticle.isPhysicalPrimary() && leadingParticle.has_mothers()) { + const auto mothers = leadingParticle.template mothers_as(); + if (mothers.size() > 0) { + LOG(debug) << "Got the mother"; + const auto& mother = mothers[0]; + if (mother.pdgCode() == PDG_t::kGamma && mother.has_daughters()) { + LOG(debug) << "Got the mother with PDG 22 and daughters"; + const auto& daughters = mother.template daughters_as(); + // 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)) { + SETBIT(origin, static_cast(gjanalysis::ClusterOrigin::kConvertedPhoton)); + LOG(debug) << "Cluster is a converted photon"; + } + } + } + } + } + } + // display bit origin + LOG(debug) << "Origin bits: " << std::bitset<16>(origin); + return origin; } // --------------------- // Processing functions // --------------------- // WARNING: This function always has to run first in the processing chain + /// \brief Clears collision mapping at the start of each dataframe + /// \param collisions The collisions collection void processClearMaps(aod::JetCollisions const&) { collisionMapping.clear(); + mcCollisionsMultiRecCollisions.clear(); + mcJetIndexMapping.clear(); } PROCESS_SWITCH(GammaJetTreeProducer, processClearMaps, "process function that clears all the maps in each dataframe", true); // WARNING: This function always has to run second in the processing chain - void processEvent(soa::Join::iterator const& collision, emcClusters const& clusters) + /// \brief Processes MC event matching QA + /// \param mcCollision The MC collision to process + /// \param collisions The rec collisions collection + /// \param mcgenparticles The MC particles collection + void processMCCollisionsMatching(aod::JetMcCollision const& mcCollision, soa::SmallGroups const& collisions, aod::JetParticles const& mcgenparticles) + { + if (mcCollision.weight() == 0) { + return; + } + + // determine number of rec collisions + int nRecCollisions = 0; + mHistograms.fill(HIST("mcCollisionsWithRecCollisions"), 0); + for (auto const& collision : collisions) { + if (collision.posZ() > mVertexCut) { + continue; + } + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits)) { + continue; + } + if (!jetderiveddatautilities::selectTrigger(collision, triggerMaskBits)) { + continue; + } + if (!jetderiveddatautilities::eventEMCAL(collision)) { + continue; + } + nRecCollisions++; + } + if (nRecCollisions == 0) { + mHistograms.fill(HIST("mcCollisionsWithRecCollisions"), 3); + } + if (nRecCollisions == 1) { + mHistograms.fill(HIST("mcCollisionsWithRecCollisions"), 1); + } + if (nRecCollisions > 1) { + mHistograms.fill(HIST("mcCollisionsWithRecCollisions"), 2); + } + if (nRecCollisions > 1) { + mcCollisionsMultiRecCollisions.push_back(mcCollision.globalIndex()); + } + + // loop over mcgenparticles + for (auto const& particle : mcgenparticles) { + if (!particle.isPhysicalPrimary()) { + continue; + } + if (particle.pdgCode() != PDG_t::kGamma) { + continue; + } + mHistograms.fill(HIST("numberRecCollisionsVsPhotonPt"), nRecCollisions, particle.pt()); + } + } + PROCESS_SWITCH(GammaJetTreeProducer, processMCCollisionsMatching, "Process MC event matching QA", false); + + /// \brief Processes data events in data fill event table + /// \param collision The collision to process + /// \param clusters The EMCAL clusters in the event + void processEventData(soa::Join::iterator const& collision, emcClusters const& clusters) { if (!isEventAccepted(collision, clusters)) { return; @@ -244,7 +945,48 @@ struct GammaJetTreeProducer { eventsTable(collision.multiplicity(), collision.centrality(), collision.rho(), collision.eventSel(), collision.trackOccupancyInTimeRange(), collision.alias_raw()); collisionMapping[collision.globalIndex()] = eventsTable.lastIndex(); } - PROCESS_SWITCH(GammaJetTreeProducer, processEvent, "Process event", true); + PROCESS_SWITCH(GammaJetTreeProducer, processEventData, "Process event data", true); + + using MCCol = o2::soa::Join; + + /// \brief Processes MC events and fills rec and MC event tables (disable processEventData) + /// \param collision The collision to process + /// \param clusters The EMCAL clusters in the event + /// \param mcCollisions The MC collisions collection + void processEventMC(soa::Join::iterator const& collision, emcClusters const& clusters, MCCol const&) + { + if (!isEventAccepted(collision, clusters)) { + return; + } + + // check that this event has a MC collision + if (!collision.has_mcCollision()) { + return; + } + mHistograms.fill(HIST("eventQA"), 6); + + // check if this event is not MB gap event + if (collision.subGeneratorId() == jetderiveddatautilities::JCollisionSubGeneratorId::mbGap) { + return; + } + mHistograms.fill(HIST("eventQA"), 7); + + // fill rec collision table + eventsTable(collision.multiplicity(), collision.centrality(), collision.rho(), collision.eventSel(), collision.trackOccupancyInTimeRange(), collision.alias_raw()); + + // fill collision mapping + collisionMapping[collision.globalIndex()] = eventsTable.lastIndex(); + + auto mcCollision = collision.mcCollision_as(); + + bool isMultipleAssigned = false; + // check if we are dealing with a rec collision matched to a MC collision that was matched to multiple rec collisions + if (std::find(mcCollisionsMultiRecCollisions.begin(), mcCollisionsMultiRecCollisions.end(), mcCollision.globalIndex()) != mcCollisionsMultiRecCollisions.end()) { + isMultipleAssigned = true; + } + mcEventsTable(eventsTable.lastIndex(), mcCollision.weight(), mcCollision.rho(), isMultipleAssigned); + } + PROCESS_SWITCH(GammaJetTreeProducer, processEventMC, "Process MC event MC", false); // --------------------- // Processing functions can be safely added below this line @@ -255,6 +997,11 @@ struct GammaJetTreeProducer { // an integer instead PresliceUnsorted EMCTrackPerTrack = aod::jemctrack::trackId; // Process clusters + /// \brief Processes clusters and fills cluster table + /// \param collision The collision to process + /// \param clusters The EMCAL clusters to process + /// \param tracks The tracks collection + /// \param emctracks The EMCAL tracks collection from track matching void processClusters(soa::Join::iterator const& collision, emcClusters const& clusters, aod::JetTracks const& tracks, aod::JEMCTracks const& emctracks) { // event selection @@ -262,20 +1009,20 @@ struct GammaJetTreeProducer { if (storedColIndex == -1) return; - // eventsTable(collision.multiplicity(), collision.centrality(), collision.rho(), collision.eventSel(), collision.trackOccupancyInTimeRange(), collision.alias_raw()); - // collisionMapping[collision.globalIndex()] = eventsTable.lastIndex(); - // loop over tracks one time for QA runTrackQA(collision, tracks); + // build kd tree for tracks and mc particles + buildKdTree(tracks); + // loop over clusters - for (auto cluster : clusters) { + for (const auto& cluster : clusters) { // fill histograms mHistograms.fill(HIST("clusterE"), cluster.energy()); - double isoraw = ch_iso_in_cone(cluster, tracks, isoR); - double perpconerho = ch_perp_cone_rho(cluster, tracks, isoR); + double isoraw = ch_iso_in_cone(cluster, isoR, false); + double perpconerho = ch_perp_cone_rho(cluster, isoR, false); // find closest matched track double dEta = 0; @@ -285,7 +1032,7 @@ struct GammaJetTreeProducer { // do track matching auto tracksofcluster = cluster.matchedTracks_as(); - for (auto track : tracksofcluster) { + for (const auto& track : tracksofcluster) { if (!isTrackSelected(track)) { continue; } @@ -296,7 +1043,7 @@ struct GammaJetTreeProducer { continue; } else { dEta = cluster.eta() - emcTrack.etaEmcal(); - dPhi = RecoDecay::constrainAngle(RecoDecay::constrainAngle(emcTrack.phiEmcal(), -M_PI) - RecoDecay::constrainAngle(cluster.phi(), -M_PI), -M_PI); + dPhi = RecoDecay::constrainAngle(RecoDecay::constrainAngle(emcTrack.phiEmcal(), -o2::constants::math::PI) - RecoDecay::constrainAngle(cluster.phi(), -o2::constants::math::PI), -o2::constants::math::PI); p = track.p(); break; } @@ -305,47 +1052,262 @@ struct GammaJetTreeProducer { } // dummy loop over tracks - for (auto track : tracks) { + for (const auto& track : tracks) { mHistograms.fill(HIST("trackPt"), track.pt()); } } PROCESS_SWITCH(GammaJetTreeProducer, processClusters, "Process EMCal clusters", true); - Filter jetCuts = aod::jet::pt > jetPtMin; - // Process charged jets - void processChargedJets(soa::Join::iterator const& collision, soa::Filtered> const& chargedJets, aod::JetTracks const& tracks) + /// \brief Processes MC cluster information (rec level) + /// \param collision The collision to process + /// \param mcClusters The MC clusters to process + /// \param mcParticles The MC particles collection + void processClustersMCInfo(soa::Join::iterator const& collision, emcMCClusters const& mcClusters, aod::JMcParticles const& mcParticles) { // event selection int32_t storedColIndex = getStoredColIndex(collision); if (storedColIndex == -1) return; - float leadingTrackPt = 0; + // loop over mcClusters + // TODO: add weights + for (const auto& mcCluster : mcClusters) { + mHistograms.fill(HIST("clusterMC_E_All"), mcCluster.energy()); + uint16_t origin = getClusterOrigin(mcCluster, mcParticles); + float leadingEnergyFraction = mcCluster.amplitudeA()[0] / mcCluster.energy(); + // Fill MC origin QA histograms + if (origin & (1 << static_cast(gjanalysis::ClusterOrigin::kPhoton))) { + mHistograms.fill(HIST("clusterMC_E_Photon"), mcCluster.energy()); + mHistograms.fill(HIST("clusterMC_m02_Photon"), mcCluster.m02()); + } + if (origin & (1 << static_cast(gjanalysis::ClusterOrigin::kPromptPhoton))) { + mHistograms.fill(HIST("clusterMC_E_PromptPhoton"), mcCluster.energy()); + mHistograms.fill(HIST("clusterMC_m02_PromptPhoton"), mcCluster.m02()); + } + if (origin & (1 << static_cast(gjanalysis::ClusterOrigin::kDirectPromptPhoton))) { + mHistograms.fill(HIST("clusterMC_E_DirectPromptPhoton"), mcCluster.energy()); + mHistograms.fill(HIST("clusterMC_m02_DirectPromptPhoton"), mcCluster.m02()); + } + if (origin & (1 << static_cast(gjanalysis::ClusterOrigin::kFragmentationPhoton))) { + mHistograms.fill(HIST("clusterMC_E_FragmentationPhoton"), mcCluster.energy()); + mHistograms.fill(HIST("clusterMC_m02_FragmentationPhoton"), mcCluster.m02()); + } + if (origin & (1 << static_cast(gjanalysis::ClusterOrigin::kDecayPhoton))) { + mHistograms.fill(HIST("clusterMC_E_DecayPhoton"), mcCluster.energy()); + mHistograms.fill(HIST("clusterMC_m02_DecayPhoton"), mcCluster.m02()); + } + if (origin & (1 << static_cast(gjanalysis::ClusterOrigin::kDecayPhotonPi0))) { + mHistograms.fill(HIST("clusterMC_E_DecayPhotonPi0"), mcCluster.energy()); + mHistograms.fill(HIST("clusterMC_m02_DecayPhotonPi0"), mcCluster.m02()); + } + if (origin & (1 << static_cast(gjanalysis::ClusterOrigin::kDecayPhotonEta))) { + mHistograms.fill(HIST("clusterMC_E_DecayPhotonEta"), mcCluster.energy()); + mHistograms.fill(HIST("clusterMC_m02_DecayPhotonEta"), mcCluster.m02()); + } + if (origin & (1 << static_cast(gjanalysis::ClusterOrigin::kMergedPi0))) { + mHistograms.fill(HIST("clusterMC_E_MergedPi0"), mcCluster.energy()); + mHistograms.fill(HIST("clusterMC_m02_MergedPi0"), mcCluster.m02()); + } + if (origin & (1 << static_cast(gjanalysis::ClusterOrigin::kMergedEta))) { + mHistograms.fill(HIST("clusterMC_E_MergedEta"), mcCluster.energy()); + mHistograms.fill(HIST("clusterMC_m02_MergedEta"), mcCluster.m02()); + } + if (origin & (1 << static_cast(gjanalysis::ClusterOrigin::kConvertedPhoton))) { + mHistograms.fill(HIST("clusterMC_E_ConvertedPhoton"), mcCluster.energy()); + mHistograms.fill(HIST("clusterMC_m02_ConvertedPhoton"), mcCluster.m02()); + } + // fill table + gammaMCInfosTable(storedColIndex, origin, leadingEnergyFraction); + } + } + PROCESS_SWITCH(GammaJetTreeProducer, processClustersMCInfo, "Process MC cluster information", false); + + /// \brief Fills the charged jet table with jet information and calculates jet properties + /// \param storedColIndex The stored collision index + /// \param jet The jet to process + /// \param tracks The tracks collection + template + void fillChargedJetTable(int32_t storedColIndex, T const& jet, U const& /*tracks*/) + { + if (jet.pt() < jetPtMin) { + return; + } ushort nconst = 0; + float leadingTrackPt = 0; + for (const auto& constituent : jet.template tracks_as()) { + mHistograms.fill(HIST("chjetpt_vs_constpt"), jet.pt(), constituent.pt()); + nconst++; + if (constituent.pt() > leadingTrackPt) { + leadingTrackPt = constituent.pt(); + } + } + double perpconerho = ch_perp_cone_rho(jet, perpConeJetR, false); + chargedJetsTable(storedColIndex, jet.pt(), jet.eta(), jet.phi(), jet.r(), jet.energy(), jet.mass(), jet.area(), leadingTrackPt, perpconerho, nconst); + mHistograms.fill(HIST("chjetPtEtaPhi"), jet.pt(), jet.eta(), jet.phi()); + mHistograms.fill(HIST("chjetPt"), jet.pt()); + } + + Filter jetCuts = aod::jet::pt > jetPtMin; + /// \brief Processes charged jets and fills jet table + /// \param collision The collision to process + /// \param chargedJets The charged jets to process + /// \param tracks The tracks collection + void processChargedJetsData(soa::Join::iterator const& collision, soa::Filtered> const& chargedJets, aod::JetTracks const& tracks) + { + // event selection + int32_t storedColIndex = getStoredColIndex(collision); + if (storedColIndex == -1) + return; // loop over charged jets - for (auto jet : chargedJets) { - if (jet.pt() < jetPtMin) + for (const auto& jet : chargedJets) { + fillChargedJetTable(storedColIndex, jet, tracks); + } + } + PROCESS_SWITCH(GammaJetTreeProducer, processChargedJetsData, "Process charged jets", true); + + Preslice ParticlesPerMCCollisions = aod::jmcparticle::mcCollisionId; + /// \brief Processes MC particles and fills MC particle table + /// \param collision The collision to process + /// \param mcgenparticles The MC particles to process + void processMCParticles(soa::Join::iterator const& collision, aod::JetParticles const& mcgenparticles, MCCol const&) + { + // event selection + int32_t storedColIndex = getStoredColIndex(collision); + if (storedColIndex == -1) + return; + + if (!collision.has_mcCollision()) { + return; + } + + // only storing MC particles if we found a reconstructed collision + auto particlesPerMcCollision = mcgenparticles.sliceBy(ParticlesPerMCCollisions, collision.mcCollisionId()); + + // build kd tree for mc particles + buildKdTree(particlesPerMcCollision); + + // Now we want to store every pi0 and every prompt photon that we find on generator level + for (const auto& particle : particlesPerMcCollision) { + // only store particles above a given threshold + if (particle.pt() < minMCGenPt) { + continue; + } + // Test if a particle is a physical primary according to the following definition: + // Particles produced in the collision including products of strong and + // electromagnetic decay and excluding feed-down from weak decays of strange + // particles. + if (!(particle.isPhysicalPrimary() || particle.pdgCode() == PDG_t::kPi0)) { continue; - nconst = 0; - leadingTrackPt = 0; - // loop over constituents - for (auto& constituent : jet.template tracks_as()) { - mHistograms.fill(HIST("chjetpt_vs_constpt"), jet.pt(), constituent.pt()); - nconst++; - if (constituent.pt() > leadingTrackPt) { - leadingTrackPt = constituent.pt(); - } } - // calculate perp cone rho - double perpconerho = ch_perp_cone_rho(jet, tracks, perpConeJetR); - mHistograms.fill(HIST("chjetPtEtaPhi"), jet.pt(), jet.eta(), jet.phi()); - chargedJetsTable(storedColIndex, jet.pt(), jet.eta(), jet.phi(), jet.r(), jet.energy(), jet.mass(), jet.area(), leadingTrackPt, perpconerho, nconst); - // fill histograms - mHistograms.fill(HIST("chjetPt"), jet.pt()); + // only store photons and pi0s in mcgen stack + 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); + + // fill mc gen trigger particle histograms + mHistograms.fill(HIST("mcGenTrigger_E"), particle.energy()); + mHistograms.fill(HIST("mcGenTrigger_Eta"), particle.eta()); + mHistograms.fill(HIST("mcGenTrigger_Phi"), particle.phi()); + mHistograms.fill(HIST("mcGenTrigger_Pt"), particle.pt()); + if (origin & (1 << static_cast(gjanalysis::ParticleOrigin::kPromptPhoton))) { + mHistograms.fill(HIST("mcGenTrigger_E_PromptPhoton"), particle.energy()); + } + if (origin & (1 << static_cast(gjanalysis::ParticleOrigin::kDirectPromptPhoton))) { + mHistograms.fill(HIST("mcGenTrigger_E_DirectPromptPhoton"), particle.energy()); + } + if (origin & (1 << static_cast(gjanalysis::ParticleOrigin::kFragmentationPhoton))) { + mHistograms.fill(HIST("mcGenTrigger_E_FragmentationPhoton"), particle.energy()); + } + if (origin & (1 << static_cast(gjanalysis::ParticleOrigin::kDecayPhoton))) { + mHistograms.fill(HIST("mcGenTrigger_E_DecayPhoton"), particle.energy()); + } + if (origin & (1 << static_cast(gjanalysis::ParticleOrigin::kDecayPhotonPi0))) { + mHistograms.fill(HIST("mcGenTrigger_E_DecayPhotonPi0"), particle.energy()); + } + if (origin & (1 << static_cast(gjanalysis::ParticleOrigin::kDecayPhotonEta))) { + mHistograms.fill(HIST("mcGenTrigger_E_DecayPhotonEta"), particle.energy()); + } + if (origin & (1 << static_cast(gjanalysis::ParticleOrigin::kDecayPhotonOther))) { + mHistograms.fill(HIST("mcGenTrigger_E_DecayPhotonOther"), particle.energy()); + } + if (origin & (1 << static_cast(gjanalysis::ParticleOrigin::kPi0))) { + mHistograms.fill(HIST("mcGenTrigger_E_Pi0"), particle.energy()); + } } } - PROCESS_SWITCH(GammaJetTreeProducer, processChargedJets, "Process charged jets", true); + PROCESS_SWITCH(GammaJetTreeProducer, processMCParticles, "Process MC particles", false); + + // NOTE: It is important that this function runs after the processMCParticles function (where the isolation tree is built ) + Preslice PJetsPerMCCollisions = aod::jmcparticle::mcCollisionId; + /// \brief Processes MC particle level charged jets and fills MC jet table + /// \param collision The collision to process + /// \param chargedJets The MC particle level charged jets to process + /// \param mcCollisions The MC collisions collection + void processChargedJetsMCP(soa::Join::iterator const& collision, soa::Filtered> const& chargedJets, MCCol const&) + { + // event selection + int32_t storedColIndex = getStoredColIndex(collision); + if (storedColIndex == -1) + return; + // loop over charged jets + if (!collision.has_mcCollision()) { + return; + } + int localIndex = 0; + auto pjetsPerMcCollision = chargedJets.sliceBy(PJetsPerMCCollisions, collision.mcCollisionId()); + for (const auto& pjet : pjetsPerMcCollision) { + // fill MC particle level jet table + float perpconerho = ch_perp_cone_rho(pjet, perpConeJetR, true); + mcJetsTable(storedColIndex, pjet.pt(), pjet.eta(), pjet.phi(), pjet.r(), pjet.energy(), pjet.mass(), pjet.area(), perpconerho); + mcJetIndexMapping[pjet.globalIndex()] = localIndex; + localIndex++; + mHistograms.fill(HIST("mcpJetPt"), pjet.pt()); + } + } + PROCESS_SWITCH(GammaJetTreeProducer, processChargedJetsMCP, "Process MC particle level jets", false); + + // NOTE: It is important that this function runs after the processChargedJetsMCP function (where the mc jet index mapping is built) + using JetMCPTable = soa::Filtered>; + Filter jetCutsMCD = aod::jet::pt > jetPtMin; + /// \brief Processes MC detector level charged jets and fills jet matching information + /// \param collision The collision to process + /// \param chargedJets The MC detector level charged jets to process + /// \param tracks The tracks collection + /// \param pjets The MC particle level jets collection (just loaded to have subscription to the table) + void processChargedJetsMCD(soa::Join::iterator const& collision, soa::Filtered> const& chargedJets, aod::JetTracks const& tracks, JetMCPTable const& /*pjets*/) + { + // event selection + int32_t storedColIndex = getStoredColIndex(collision); + if (storedColIndex == -1) + return; + // loop over charged jets + for (const auto& jet : chargedJets) { + fillChargedJetTable(storedColIndex, jet, tracks); + + // Fill Matching information + int iLocalIndexGeo = -1; + int iLocalIndexPt = -1; + // We will always store the information for both in our tree + if (jet.has_matchedJetGeo()) { + const auto& pjet = jet.template matchedJetGeo_first_as(); + iLocalIndexGeo = mcJetIndexMapping[pjet.globalIndex()]; + mHistograms.fill(HIST("mcdJetPtVsTrueJetPtMatchingGeo"), jet.pt(), pjet.pt()); + } + if (jet.has_matchedJetPt()) { + const auto& pjet = jet.template matchedJetPt_first_as(); + iLocalIndexPt = mcJetIndexMapping[pjet.globalIndex()]; + mHistograms.fill(HIST("mcdJetPtVsTrueJetPtMatchingPt"), jet.pt(), pjet.pt()); + } + chJetMCInfosTable(storedColIndex, iLocalIndexGeo, iLocalIndexPt); + } + } + PROCESS_SWITCH(GammaJetTreeProducer, processChargedJetsMCD, "Process MC detector level jets", false); }; + WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { WorkflowSpec workflow{ From f01d1b105eafbf2c7d255ca5f48bd21c148e2b27 Mon Sep 17 00:00:00 2001 From: aimeric-landou <46970521+aimeric-landou@users.noreply.github.com> Date: Sat, 28 Jun 2025 08:30:02 +0200 Subject: [PATCH 254/871] [PWGJE] trackEfficiency workflow additions (#11793) --- PWGJE/Tasks/trackEfficiency.cxx | 318 +++++++++++++++++++++++++------- 1 file changed, 251 insertions(+), 67 deletions(-) diff --git a/PWGJE/Tasks/trackEfficiency.cxx b/PWGJE/Tasks/trackEfficiency.cxx index ae7344c0876..c984ea86d43 100644 --- a/PWGJE/Tasks/trackEfficiency.cxx +++ b/PWGJE/Tasks/trackEfficiency.cxx @@ -80,7 +80,8 @@ struct TrackEfficiency { Configurable pTHatExponent{"pTHatExponent", 6.0, "exponent of the event weight for the calculation of pTHat"}; Configurable pTHatMaxFractionMCD{"pTHatMaxFractionMCD", 999.0, "maximum fraction of hard scattering for reconstructed track acceptance in MC"}; - Configurable useTrueTrackWeight{"useTrueTrackWeight", 1, "test configurable, to be removed"}; + Configurable getPtHatFromHepMCXSection{"getPtHatFromHepMCXSection", true, "test configurable, configurable should be removed once well tested"}; + Configurable useTrueTrackWeight{"useTrueTrackWeight", true, "test configurable, should be set to 1 then config removed once well tested"}; std::vector eventSelectionBits; int trackSelection = -1; @@ -102,8 +103,8 @@ struct TrackEfficiency { return std::abs(charge) >= chargeUnit; } - template - void fillTrackHistograms(T const& collision, U const& tracks, float weight = 1.0) + template + void fillTrackHistograms(TCollision const& collision, TTracks const& tracks, float weight = 1.0) { for (auto const& track : tracks) { if (!(jetderiveddatautilities::selectTrack(track, trackSelection) && jetderiveddatautilities::selectTrackDcaZ(track, trackDcaZmax))) { @@ -128,8 +129,8 @@ struct TrackEfficiency { } } - template - void fillParticlesHistograms(T const& collision, U const& mcparticles, float weight = 1.0) + template + void fillParticlesHistograms(TCollision const& collision, TParticles const& mcparticles, TTracks tracks, float weight = 1.0) { for (auto const& mcparticle : mcparticles) { registry.fill(HIST("h2_centrality_particle_pt"), collision.centrality(), mcparticle.pt(), weight); @@ -137,6 +138,10 @@ struct TrackEfficiency { registry.fill(HIST("h2_centrality_particle_phi"), collision.centrality(), mcparticle.phi(), weight); registry.fill(HIST("h2_centrality_particle_energy"), collision.centrality(), mcparticle.energy(), weight); registry.fill(HIST("h3_intrate_centrality_particle_pt"), collision.hadronicRate(), collision.centrality(), mcparticle.pt(), weight); + for (auto const& track : tracks) { + registry.fill(HIST("h2_particle_pt_track_pt_deltapt"), mcparticle.pt(), mcparticle.pt() - track.pt(), weight); + registry.fill(HIST("h2_particle_pt_track_pt_deltaptoverparticlept"), mcparticle.pt(), (mcparticle.pt() - track.pt()) / mcparticle.pt(), weight); + } } } @@ -220,7 +225,7 @@ struct TrackEfficiency { registry.add("h2_particle_pt_high_track_pt_high_residual_associatedtrack_primary", "(#it{p}_{T, mcpart} - #it{p}_{T, track}) / #it{p}_{T, mcpart}; #it{p}_{T, mcpart} (GeV/#it{c})", {HistType::kTH2F, {ptAxisHighEff, {200, -1., 1.}}}); } - if (doprocessTracks || doprocessTracksMc || doprocessTracksMcWeighted) { + if (doprocessTracksFromData || doprocessTracksFromMc || doprocessTracksFromMcWeighted) { AxisSpec centAxis = {centralityBinning, "centrality (%)"}; AxisSpec intRateAxis = {intRateNBins, 0., intRateMax, "int. rate (kHz)"}; registry.add("h2_centrality_track_pt", "centrality vs track pT; centrality; #it{p}_{T,track} (GeV/#it{c})", {HistType::kTH2F, {centAxis, {200, 0., 200.}}}); @@ -232,9 +237,6 @@ struct TrackEfficiency { registry.add("h2_track_pt_track_sigma1overpt", "#sigma(1/#it{p}_{T}); #it{p}_{T,track} (GeV/#it{c})", {HistType::kTH2F, {{100, 0., 10.}, {1000, 0.0, 10.0}}}); registry.add("h2_track_pt_high_track_sigma1overpt", "#sigma(1/#it{p}_{T}); #it{p}_{T,track} (GeV/#it{c})", {HistType::kTH2F, {{90, 10., 100.}, {1000, 0.0, 10.0}}}); registry.add("h3_intrate_centrality_track_pt", "interaction rate vs centrality vs track pT; int. rate; centrality; #it{p}_{T,track} (GeV/#it{c})", {HistType::kTH3F, {intRateAxis, centAxis, {200, 0., 200.}}}); - - registry.add("h_collisions", "event status;event status;entries", {HistType::kTH1F, {{4, 0.0, 4.0}}}); - registry.add("h2_centrality_collisions", "centrality vs collisions; centrality; collisions", {HistType::kTH2F, {centAxis, {4, 0.0, 4.0}}}); } if (doprocessParticles || doprocessParticlesWeighted) { @@ -245,20 +247,33 @@ struct TrackEfficiency { registry.add("h2_centrality_particle_phi", "centrality vs particle #varphi; centrality; #varphi_{part}", {HistType::kTH2F, {centAxis, {160, -1.0, 7.}}}); registry.add("h2_centrality_particle_energy", "centrality vs particle energy; centrality; Energy GeV", {HistType::kTH2F, {centAxis, {100, 0.0, 100.0}}}); registry.add("h3_intrate_centrality_particle_pt", "interaction rate vs centrality vs particle pT; int. rate; centrality; #it{p}_{T,part} (GeV/#it{c})", {HistType::kTH3F, {intRateAxis, centAxis, {200, 0., 200.}}}); + } + if (doprocessCollisionsFromData || doprocessCollisionsFromMc || doprocessCollisionsFromMcWeighted) { + AxisSpec centAxis = {centralityBinning, "centrality (%)"}; + registry.add("h_collisions", "event status;event status;entries", {HistType::kTH1F, {{4, 0.0, 4.0}}}); + registry.add("h2_centrality_collisions", "centrality vs collisions; centrality; collisions", {HistType::kTH2F, {centAxis, {4, 0.0, 4.0}}}); + } + if (doprocessMcCollisions || doprocessMcCollisionsWeighted) { + AxisSpec centAxis = {centralityBinning, "centrality (%)"}; registry.add("h_mccollisions", "event status;event status;entries", {HistType::kTH1F, {{4, 0.0, 4.0}}}); registry.add("h2_centrality_mccollisions", "centrality vs mccollisions; centrality; collisions", {HistType::kTH2F, {centAxis, {4, 0.0, 4.0}}}); + registry.add("h2_mccollision_pthardfromweight_pthardfromhepmcxsection", "ptHard from weight vs ptHard from HepMCXSections; ptHard_weight; ptHard_hepmcxsections", {HistType::kTH2F, {{200, 0.0, 200.0}, {200, 0.0, 200.0}}}); } - if (doprocessTracksMc || doprocessTracksMcWeighted) { - AxisSpec centAxis = {centralityBinning, "centrality (%)"}; + if (doprocessCollisionsFromMc || doprocessCollisionsFromMcWeighted) { registry.add("h_fakecollisions", "event status;event status;entries", {HistType::kTH1F, {{4, 0.0, 4.0}}}); } - if (doprocessTracksMcWeighted) { + if (doprocessCollisionsFromMcWeighted) { + AxisSpec centAxis = {centralityBinning, "centrality (%)"}; registry.add("h_collisions_weighted", "event status;event status;entries", {HistType::kTH1F, {{4, 0.0, 4.0}}}); + registry.add("h2_centrality_collisions_weighted", "centrality vs mccollisions; centrality; collisions", {HistType::kTH2F, {centAxis, {4, 0.0, 4.0}}}); } - if (doprocessParticlesWeighted) { + if (doprocessMcCollisionsWeighted) { + AxisSpec centAxis = {centralityBinning, "centrality (%)"}; registry.add("h_mccollisions_weighted", "event status;event status;entries", {HistType::kTH1F, {{4, 0.0, 4.0}}}); + registry.add("h2_centrality_mccollisions_weighted", "centrality vs mccollisions; centrality; collisions", {HistType::kTH2F, {centAxis, {4, 0.0, 4.0}}}); + registry.add("h2_mccollision_pthardfromweight_pthardfromhepmcxsection_weighted", "ptHard from weight vs ptHard from HepMCXSections; ptHard_weight; ptHard_hepmcxsections", {HistType::kTH2F, {{200, 0.0, 200.0}, {200, 0.0, 200.0}}}); } } @@ -269,7 +284,8 @@ struct TrackEfficiency { Filter particleCuts = (aod::jmcparticle::pt >= trackQAPtMin && aod::jmcparticle::pt < trackQAPtMax && aod::jmcparticle::eta > trackQAEtaMin && aod::jmcparticle::eta < trackQAEtaMax); Filter eventCuts = (nabs(aod::jcollision::posZ) < vertexZCut && aod::jcollision::centrality >= centralityMin && aod::jcollision::centrality < centralityMax); - void processEFficiencyPurity(aod::JetMcCollision const& mcCollision, + void processEFficiencyPurity(soa::Join::iterator const& mcCollision, + soa::Join const&, soa::SmallGroups const& collisions, // smallgroups gives only the collisions associated to the current mccollision, thanks to the mccollisionlabel pre-integrated in jetcollisionsmcd soa::Join const& jetTracks, JetParticlesWithOriginal const& jMcParticles) @@ -326,7 +342,7 @@ struct TrackEfficiency { } registry.fill(HIST("hMcCollCutsCounts"), 5.5); // at least one of the reconstructed collisions associated with this mcCollision is selected with regard to centrality - float pTHat = 10. / (std::pow(mcCollision.weight(), 1.0 / pTHatExponent)); + float pTHat = getPtHatFromHepMCXSection ? mcCollision.mcCollision_as>().ptHard() : 10. / (std::pow(mcCollision.weight(), 1.0 / pTHatExponent)); if (pTHat < ptHatMin || pTHat > ptHatMax) { // only allows mcCollisions with weight in between min and max return; } @@ -435,7 +451,8 @@ struct TrackEfficiency { } PROCESS_SWITCH(TrackEfficiency, processEFficiencyPurity, "Histograms for efficiency and purity quantities", true); - void processEFficiencyPurityWeighted(aod::JetMcCollision const& mcCollision, + void processEFficiencyPurityWeighted(soa::Join::iterator const& mcCollision, + soa::Join const&, soa::SmallGroups const& collisions, // smallgroups gives only the collisions associated to the current mccollision, thanks to the mccollisionlabel pre-integrated in jetcollisionsmcd soa::Join const& jetTracks, JetParticlesWithOriginal const& jMcParticles) @@ -446,22 +463,22 @@ struct TrackEfficiency { // * dividing in centrality bins // I should maybe introduce the sel8 cuts on the collisoins (reco, but what about mccoll? maybe not htat way included in efficiency) - registry.fill(HIST("hMcCollCutsCounts"), 0.5); // all mcCollisions + registry.fill(HIST("hMcCollCutsCounts"), 0.5, mcCollision.weight()); // all mcCollisions if (!(std::abs(mcCollision.posZ()) < vertexZCut)) { return; } - registry.fill(HIST("hMcCollCutsCounts"), 1.5); // mcCollision.posZ() condition + registry.fill(HIST("hMcCollCutsCounts"), 1.5, mcCollision.weight()); // mcCollision.posZ() condition if (collisions.size() < 1) { return; } - registry.fill(HIST("hMcCollCutsCounts"), 2.5); // mcCollisions with at least one reconstructed collision + registry.fill(HIST("hMcCollCutsCounts"), 2.5, mcCollision.weight()); // mcCollisions with at least one reconstructed collision if (acceptSplitCollisions == NonSplitOnly && collisions.size() > 1) { return; } - registry.fill(HIST("hMcCollCutsCounts"), 3.5); // split mcCollisions condition + registry.fill(HIST("hMcCollCutsCounts"), 3.5, mcCollision.weight()); // split mcCollisions condition bool hasSel8Coll = false; bool centralityCheck = false; @@ -485,12 +502,12 @@ struct TrackEfficiency { if (!hasSel8Coll) { return; } - registry.fill(HIST("hMcCollCutsCounts"), 4.5); // at least one of the reconstructed collisions associated with this mcCollision is selected + registry.fill(HIST("hMcCollCutsCounts"), 4.5, mcCollision.weight()); // at least one of the reconstructed collisions associated with this mcCollision is selected if (!centralityCheck) { return; } - registry.fill(HIST("hMcCollCutsCounts"), 5.5); // at least one of the reconstructed collisions associated with this mcCollision is selected with regard to centrality + registry.fill(HIST("hMcCollCutsCounts"), 5.5, mcCollision.weight()); // at least one of the reconstructed collisions associated with this mcCollision is selected with regard to centrality float simPtRef = 10.; float mcCollEventWeight = mcCollision.weight(); @@ -498,29 +515,29 @@ struct TrackEfficiency { if (pTHat < ptHatMin || pTHat > ptHatMax) { // only allows mcCollisions with weight in between min and max return; } - registry.fill(HIST("hMcCollCutsCounts"), 6.5); // ptHat condition + registry.fill(HIST("hMcCollCutsCounts"), 6.5, mcCollision.weight()); // ptHat condition for (auto const& jMcParticle : jMcParticles) { - registry.fill(HIST("hMcPartCutsCounts"), 0.5); // allPartsInSelMcColl + registry.fill(HIST("hMcPartCutsCounts"), 0.5, mcCollision.weight()); // allPartsInSelMcColl if (!isChargedParticle(jMcParticle.pdgCode())) { continue; } - registry.fill(HIST("hMcPartCutsCounts"), 1.5); // isCharged + registry.fill(HIST("hMcPartCutsCounts"), 1.5, mcCollision.weight()); // isCharged registry.fill(HIST("h3_particle_pt_particle_eta_particle_phi_mcpart_nonprimary"), jMcParticle.pt(), jMcParticle.eta(), jMcParticle.phi(), mcCollEventWeight); if (checkPrimaryPart && !jMcParticle.isPhysicalPrimary()) { // global tracks should be mostly primaries continue; } - registry.fill(HIST("hMcPartCutsCounts"), 2.5); // isPrimary + registry.fill(HIST("hMcPartCutsCounts"), 2.5, mcCollision.weight()); // isPrimary registry.fill(HIST("h3_particle_pt_particle_eta_particle_phi_mcpartofinterest"), jMcParticle.pt(), jMcParticle.eta(), jMcParticle.phi(), mcCollEventWeight); registry.fill(HIST("h3_particle_pt_high_particle_eta_particle_phi_mcpartofinterest"), jMcParticle.pt(), jMcParticle.eta(), jMcParticle.phi(), mcCollEventWeight); if ((std::abs(jMcParticle.eta()) < trackEtaAcceptanceCountQA)) { // removed from actual cuts for now because all the histograms have an eta axis - registry.fill(HIST("hMcPartCutsCounts"), 3.5); // etaAccept // not actually applied here but it will give an idea of what will be done in the post processing + registry.fill(HIST("hMcPartCutsCounts"), 3.5, mcCollision.weight()); // etaAccept // not actually applied here but it will give an idea of what will be done in the post processing } } @@ -539,12 +556,12 @@ struct TrackEfficiency { auto collTracks = jetTracks.sliceBy(tracksPerJCollision, collision.globalIndex()); for (auto const& track : collTracks) { - registry.fill(HIST("hTrackCutsCounts"), 0.5); + registry.fill(HIST("hTrackCutsCounts"), 0.5, mcCollision.weight()); if (!(jetderiveddatautilities::selectTrack(track, trackSelection) && jetderiveddatautilities::selectTrackDcaZ(track, trackDcaZmax))) { // if track selection is uniformTrack, dcaZ cuts need to be added as they aren't in the selection so that they can be studied here continue; } - registry.fill(HIST("hTrackCutsCounts"), 1.5); + registry.fill(HIST("hTrackCutsCounts"), 1.5, mcCollision.weight()); if (!track.has_mcParticle()) { registry.fill(HIST("h3_track_pt_track_eta_track_phi_nonassociatedtrack"), track.pt(), track.eta(), track.phi(), mcCollEventWeight); // weight attribution here not trivial; I use the one of the current mcCollision, but track belongs to no collision; what should be its weight? could be a moot point but algo has complained about invalid index for mcParticle if I put th etrueTrackCollEventWeight before this cut @@ -552,12 +569,12 @@ struct TrackEfficiency { registry.fill(HIST("h3_track_pt_high_track_eta_track_phi_nonassociatedtrack"), track.pt(), track.eta(), track.phi(), mcCollEventWeight); continue; } - registry.fill(HIST("hTrackCutsCounts"), 2.5); + registry.fill(HIST("hTrackCutsCounts"), 2.5, mcCollision.weight()); if (track.pt() > pTHatMaxFractionMCD * pTHat) { continue; } - registry.fill(HIST("hTrackCutsCounts"), 3.5); + registry.fill(HIST("hTrackCutsCounts"), 3.5, mcCollision.weight()); auto mcParticle = track.mcParticle_as(); auto trueTrackMcCollision = mcParticle.mcCollision_as(); @@ -584,7 +601,7 @@ struct TrackEfficiency { continue; } - registry.fill(HIST("hTrackCutsCounts"), 4.5); + registry.fill(HIST("hTrackCutsCounts"), 4.5, mcCollision.weight()); registry.fill(HIST("h3_track_pt_track_eta_track_phi_associatedtrack_primary"), track.pt(), track.eta(), track.phi(), trueTrackCollEventWeight); registry.fill(HIST("h3_particle_pt_particle_eta_particle_phi_associatedtrack_primary"), jMcParticleFromTrack.pt(), jMcParticleFromTrack.eta(), jMcParticleFromTrack.phi(), trueTrackCollEventWeight); @@ -605,15 +622,186 @@ struct TrackEfficiency { } if (std::abs(jMcParticleFromTrack.eta()) < trackEtaAcceptanceCountQA) { // not actually applied here but it will give an idea of what will be done in the post processing - registry.fill(HIST("hTrackCutsCounts"), 5.5); + registry.fill(HIST("hTrackCutsCounts"), 5.5, mcCollision.weight()); } } } } PROCESS_SWITCH(TrackEfficiency, processEFficiencyPurityWeighted, "Histograms for efficiency and purity quantities for weighted simulations", false); - void processTracks(soa::Filtered::iterator const& collision, - soa::Filtered> const& tracks) + void processTracksFromData(soa::Filtered::iterator const& collision, + soa::Filtered> const& tracks) + { + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents)) { + return; + } + if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { + return; + } + + fillTrackHistograms(collision, tracks); + } + PROCESS_SWITCH(TrackEfficiency, processTracksFromData, "QA for charged tracks in data", false); + + void processTracksFromMc(soa::Join::iterator const& collision, + soa::Join const&, + soa::Join const&, + soa::Filtered> const& tracks) + { + if (!collision.has_mcCollision()) { // the collision is fake and has no associated mc coll; skip as .mccollision() cannot be called + return; + } + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents)) { + return; + } + if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { + return; + } + + float pTHat = getPtHatFromHepMCXSection ? collision.mcCollision_as>().mcCollision_as>().ptHard() : 10. / (std::pow(collision.mcCollision().weight(), 1.0 / pTHatExponent)); + if (pTHat < ptHatMin || pTHat > ptHatMax) { // only allows mcCollisions with weight in between min and max + return; + } + + fillTrackHistograms(collision, tracks); + } + PROCESS_SWITCH(TrackEfficiency, processTracksFromMc, "QA for charged tracks in MC without weights", false); + + void processTracksFromMcWeighted(soa::Join::iterator const& collision, + soa::Join const&, + soa::Join const&, + soa::Filtered> const& tracks) + { + if (!collision.has_mcCollision()) { // the collision is fake and has no associated mc coll; skip as .mccollision() cannot be called + return; + } + float eventWeight = collision.mcCollision().weight(); + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents)) { + return; + } + if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { + return; + } + + float pTHat = getPtHatFromHepMCXSection ? collision.mcCollision_as>().mcCollision_as>().ptHard() : 10. / (std::pow(eventWeight, 1.0 / pTHatExponent)); + if (pTHat < ptHatMin || pTHat > ptHatMax) { // only allows mcCollisions with weight in between min and max + return; + } + + fillTrackHistograms(collision, tracks, eventWeight); + } + PROCESS_SWITCH(TrackEfficiency, processTracksFromMcWeighted, "QA for charged tracks in weighted MC", false); + + void processParticles(soa::Join::iterator const& mcCollision, + soa::Join const&, + soa::SmallGroups const& collisions, + soa::Filtered const& mcparticles, + soa::Filtered const& tracks) + { + + if (!(std::abs(mcCollision.posZ()) < vertexZCut)) { + return; + } + if (collisions.size() < 1) { + return; + } + if (acceptSplitCollisions == NonSplitOnly && collisions.size() > 1) { + return; + } + + float pTHat = getPtHatFromHepMCXSection ? mcCollision.mcCollision_as>().ptHard() : 10. / (std::pow(mcCollision.weight(), 1.0 / pTHatExponent)); + if (pTHat < ptHatMin || pTHat > ptHatMax) { // only allows mcCollisions with weight in between min and max + return; + } + + bool hasSel8Coll = false; + bool centralityCheck = false; + if (acceptSplitCollisions == SplitOkCheckFirstAssocCollOnly || acceptSplitCollisions == NonSplitOnly) { // check only that the first reconstructed collision passes the check (for the NonSplitOnly case, there's only one associated collision) + if (jetderiveddatautilities::selectCollision(collisions.begin(), eventSelectionBits, skipMBGapEvents)) { // Skipping MC events that have not a single selected reconstructed collision ; effect unclear if mcColl is split + hasSel8Coll = true; + } + if (!checkCentrality || ((centralityMin < collisions.begin().centrality()) && (collisions.begin().centrality() < centralityMax))) { // effect unclear if mcColl is split + centralityCheck = true; + } + } else if (acceptSplitCollisions == SplitOkCheckAnyAssocColl) { // check that at least one of the reconstructed collisions passes the checks + for (auto const& collision : collisions) { + if (jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents)) { // Skipping MC events that have not a single selected reconstructed collision ; effect unclear if mcColl is split + hasSel8Coll = true; + } + if (!checkCentrality || ((centralityMin < collision.centrality()) && (collision.centrality() < centralityMax))) { // effect unclear if mcColl is split + centralityCheck = true; + } + } + } + if (!hasSel8Coll) { + return; + } + if (!centralityCheck) { + return; + } + + fillParticlesHistograms(collisions.begin(), mcparticles, tracks); + } + PROCESS_SWITCH(TrackEfficiency, processParticles, "QA for charged particles", false); + + void processParticlesWeighted(soa::Join::iterator const& mcCollision, + soa::Join const&, + soa::SmallGroups const& collisions, + soa::Filtered const& mcparticles, + soa::Filtered const& tracks) + { + if (skipMBGapEvents && mcCollision.subGeneratorId() == jetderiveddatautilities::JCollisionSubGeneratorId::mbGap) { + return; + } + + float eventWeight = mcCollision.weight(); + + if (!(std::abs(mcCollision.posZ()) < vertexZCut)) { + return; + } + if (collisions.size() < 1) { + return; + } + if (acceptSplitCollisions == NonSplitOnly && collisions.size() > 1) { + return; + } + + float pTHat = getPtHatFromHepMCXSection ? mcCollision.mcCollision_as>().ptHard() : 10. / (std::pow(eventWeight, 1.0 / pTHatExponent)); + if (pTHat < ptHatMin || pTHat > ptHatMax) { // only allows mcCollisions with weight in between min and max + return; + } + + bool hasSel8Coll = false; + bool centralityCheck = false; + if (acceptSplitCollisions == SplitOkCheckFirstAssocCollOnly || acceptSplitCollisions == NonSplitOnly) { // check only that the first reconstructed collision passes the check (for the NonSplitOnly case, there's only one associated collision) + if (jetderiveddatautilities::selectCollision(collisions.begin(), eventSelectionBits, skipMBGapEvents)) { // Skipping MC events that have not a single selected reconstructed collision ; effect unclear if mcColl is split + hasSel8Coll = true; + } + if (!checkCentrality || ((centralityMin < collisions.begin().centrality()) && (collisions.begin().centrality() < centralityMax))) { // effect unclear if mcColl is split + centralityCheck = true; + } + } else if (acceptSplitCollisions == SplitOkCheckAnyAssocColl) { // check that at least one of the reconstructed collisions passes the checks + for (auto const& collision : collisions) { + if (jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents)) { // Skipping MC events that have not a single selected reconstructed collision ; effect unclear if mcColl is split + hasSel8Coll = true; + } + if (!checkCentrality || ((centralityMin < collision.centrality()) && (collision.centrality() < centralityMax))) { // effect unclear if mcColl is split + centralityCheck = true; + } + } + } + if (!hasSel8Coll) { + return; + } + if (!centralityCheck) { + return; + } + + fillParticlesHistograms(collisions.begin(), mcparticles, tracks, eventWeight); + } + PROCESS_SWITCH(TrackEfficiency, processParticlesWeighted, "QA for charged particles weighted", false); + + void processCollisionsFromData(soa::Filtered::iterator const& collision) { registry.fill(HIST("h_collisions"), 0.5); registry.fill(HIST("h2_centrality_collisions"), collision.centrality(), 0.5); @@ -627,14 +815,12 @@ struct TrackEfficiency { } registry.fill(HIST("h_collisions"), 2.5); registry.fill(HIST("h2_centrality_collisions"), collision.centrality(), 2.5); - - fillTrackHistograms(collision, tracks); } - PROCESS_SWITCH(TrackEfficiency, processTracks, "QA for charged tracks in data", false); + PROCESS_SWITCH(TrackEfficiency, processCollisionsFromData, "QA for reconstructed collisions in data", false); - void processTracksMc(soa::Join::iterator const& collision, - aod::JetMcCollisions const&, - soa::Filtered> const& tracks) + void processCollisionsFromMc(soa::Join::iterator const& collision, + soa::Join const&, + soa::Join const&) { if (!collision.has_mcCollision()) { // the collision is fake and has no associated mc coll; skip as .mccollision() cannot be called registry.fill(HIST("h_fakecollisions"), 0.5); @@ -653,20 +839,18 @@ struct TrackEfficiency { registry.fill(HIST("h_collisions"), 2.5); registry.fill(HIST("h2_centrality_collisions"), collision.centrality(), 2.5); - float pTHat = 10. / (std::pow(collision.mcCollision().weight(), 1.0 / pTHatExponent)); + float pTHat = getPtHatFromHepMCXSection ? collision.mcCollision_as>().mcCollision_as>().ptHard() : 10. / (std::pow(collision.mcCollision().weight(), 1.0 / pTHatExponent)); if (pTHat < ptHatMin || pTHat > ptHatMax) { // only allows mcCollisions with weight in between min and max return; } registry.fill(HIST("h_collisions"), 3.5); registry.fill(HIST("h2_centrality_collisions"), collision.centrality(), 3.5); - - fillTrackHistograms(collision, tracks); } - PROCESS_SWITCH(TrackEfficiency, processTracksMc, "QA for charged tracks in MC without weights", false); + PROCESS_SWITCH(TrackEfficiency, processCollisionsFromMc, "QA for reconstructed collisions in MC without weights", false); - void processTracksMcWeighted(soa::Join::iterator const& collision, - aod::JetMcCollisions const&, - soa::Filtered> const& tracks) + void processCollisionsFromMcWeighted(soa::Join::iterator const& collision, + soa::Join const&, + soa::Join const&) { if (!collision.has_mcCollision()) { // the collision is fake and has no associated mc coll; skip as .mccollision() cannot be called registry.fill(HIST("h_fakecollisions"), 0.5); @@ -686,21 +870,23 @@ struct TrackEfficiency { registry.fill(HIST("h_collisions"), 2.5); registry.fill(HIST("h_collisions_weighted"), 2.5, eventWeight); - float pTHat = 10. / (std::pow(eventWeight, 1.0 / pTHatExponent)); + float pTHat = getPtHatFromHepMCXSection ? collision.mcCollision_as>().mcCollision_as>().ptHard() : 10. / (std::pow(eventWeight, 1.0 / pTHatExponent)); if (pTHat < ptHatMin || pTHat > ptHatMax) { // only allows mcCollisions with weight in between min and max return; } registry.fill(HIST("h_collisions"), 3.5); - registry.fill(HIST("h2_centrality_collisions"), collision.centrality(), 3.5); - - fillTrackHistograms(collision, tracks, eventWeight); + registry.fill(HIST("h2_centrality_collisions"), collision.centrality(), 3.5, eventWeight); } - PROCESS_SWITCH(TrackEfficiency, processTracksMcWeighted, "QA for charged tracks in weighted MC", false); + PROCESS_SWITCH(TrackEfficiency, processCollisionsFromMcWeighted, "QA for reconstructed collisions in weighted MC", false); - void processParticles(aod::JetMcCollision const& mcCollision, - soa::SmallGroups const& collisions, - soa::Filtered const& mcparticles) + void processMcCollisions(soa::Join::iterator const& mcCollision, + soa::Join const&, + soa::SmallGroups const& collisions) { + float eventWeight = mcCollision.weight(); + float pTHat = getPtHatFromHepMCXSection ? mcCollision.mcCollision_as>().ptHard() : 10. / (std::pow(eventWeight, 1.0 / pTHatExponent)); + registry.fill(HIST("h2_mccollision_pthardfromweight_pthardfromhepmcxsection"), 10. / (std::pow(eventWeight, 1.0 / pTHatExponent)), mcCollision.mcCollision_as>().ptHard()); + registry.fill(HIST("h_mccollisions"), 0.5); registry.fill(HIST("h2_centrality_mccollisions"), collisions.begin().centrality(), 0.5); @@ -714,7 +900,6 @@ struct TrackEfficiency { return; } - float pTHat = 10. / (std::pow(mcCollision.weight(), 1.0 / pTHatExponent)); if (pTHat < ptHatMin || pTHat > ptHatMax) { // only allows mcCollisions with weight in between min and max return; } @@ -748,20 +933,22 @@ struct TrackEfficiency { } registry.fill(HIST("h_mccollisions"), 2.5); registry.fill(HIST("h2_centrality_mccollisions"), collisions.begin().centrality(), 2.5); - - fillParticlesHistograms(collisions.begin(), mcparticles); } - PROCESS_SWITCH(TrackEfficiency, processParticles, "QA for charged particles", false); + PROCESS_SWITCH(TrackEfficiency, processMcCollisions, "QA for McCollisions in MC without weights", false); - void processParticlesWeighted(aod::JetMcCollision const& mcCollision, - soa::SmallGroups const& collisions, - soa::Filtered const& mcparticles) + void processMcCollisionsWeighted(soa::Join::iterator const& mcCollision, + soa::Join const&, + soa::SmallGroups const& collisions) { if (skipMBGapEvents && mcCollision.subGeneratorId() == jetderiveddatautilities::JCollisionSubGeneratorId::mbGap) { return; } float eventWeight = mcCollision.weight(); + float pTHat = getPtHatFromHepMCXSection ? mcCollision.mcCollision_as>().ptHard() : 10. / (std::pow(eventWeight, 1.0 / pTHatExponent)); + registry.fill(HIST("h2_mccollision_pthardfromweight_pthardfromhepmcxsection"), 10. / (std::pow(eventWeight, 1.0 / pTHatExponent)), mcCollision.mcCollision_as>().ptHard()); + registry.fill(HIST("h2_mccollision_pthardfromweight_pthardfromhepmcxsection_weighted"), 10. / (std::pow(eventWeight, 1.0 / pTHatExponent)), mcCollision.mcCollision_as>().ptHard(), eventWeight); + registry.fill(HIST("h_mccollisions"), 0.5); registry.fill(HIST("h_mccollisions_weighted"), 0.5, eventWeight); @@ -775,7 +962,6 @@ struct TrackEfficiency { return; } - float pTHat = 10. / (std::pow(eventWeight, 1.0 / pTHatExponent)); if (pTHat < ptHatMin || pTHat > ptHatMax) { // only allows mcCollisions with weight in between min and max return; } @@ -809,10 +995,8 @@ struct TrackEfficiency { } registry.fill(HIST("h_mccollisions"), 2.5); registry.fill(HIST("h_mccollisions_weighted"), 2.5, eventWeight); - - fillParticlesHistograms(collisions.begin(), mcparticles, eventWeight); } - PROCESS_SWITCH(TrackEfficiency, processParticlesWeighted, "QA for charged particles weighted", false); + PROCESS_SWITCH(TrackEfficiency, processMcCollisionsWeighted, "QA for McCollisions in weighted MC", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) From 35de7b86dd0fc1776612708c639b0c299fad1a98 Mon Sep 17 00:00:00 2001 From: sawan <124118453+sawankumawat@users.noreply.github.com> Date: Sat, 28 Jun 2025 15:35:57 +0530 Subject: [PATCH 255/871] [PWGLF] Helicity angle in MC (#11819) Co-authored-by: Sawan Sawan --- .../Tasks/Resonances/higherMassResonances.cxx | 58 +++++++++++-------- 1 file changed, 33 insertions(+), 25 deletions(-) diff --git a/PWGLF/Tasks/Resonances/higherMassResonances.cxx b/PWGLF/Tasks/Resonances/higherMassResonances.cxx index 81f26d94dc6..4c8f8658230 100644 --- a/PWGLF/Tasks/Resonances/higherMassResonances.cxx +++ b/PWGLF/Tasks/Resonances/higherMassResonances.cxx @@ -310,20 +310,22 @@ struct HigherMassResonances { if (config.isMC) { hMChists.add("events_check", "No. of events in the generated MC", kTH1I, {{20, 0, 20}}); hMChists.add("events_checkrec", "No. of events in the reconstructed MC", kTH1I, {{20, 0, 20}}); - hMChists.add("Genf1710", "Gen f_{0}(1710)", kTHnSparseF, {multiplicityAxis, ptAxis, glueballMassAxis, thnAxisPOL}); + hMChists.add("Genf1710", "Gen f_{0}(1710)", kTHnSparseF, {multiplicityAxis, ptAxis, thnAxisPOL}); hMChists.add("Recf1710_pt1", "Rec f_{0}(1710) p_{T}", kTHnSparseF, {multiplicityAxis, ptAxis, glueballMassAxis, thnAxisPOL}); hMChists.add("Recf1710_pt2", "Rec f_{0}(1710) p_{T}", kTHnSparseF, {multiplicityAxis, ptAxis, glueballMassAxis, thnAxisPOL}); // hMChists.add("Recf1710_p", "Rec f_{0}(1710) p", kTH1F, {ptAxis}); hMChists.add("h1Recsplit", "Rec p_{T}2", kTH1F, {ptAxis}); // hMChists.add("Recf1710_mass", "Rec f_{0}(1710) mass", kTH1F, {glueballMassAxis}); - // hMChists.add("Genf1710_mass", "Gen f_{0}(1710) mass", kTH1F, {glueballMassAxis}); + hMChists.add("Genf1710_mass", "Gen f_{0}(1710) mass", kTH1F, {glueballMassAxis}); + hMChists.add("Genf1710_mass2", "Gen f_{0}(1710) mass", kTH1F, {glueballMassAxis}); + hMChists.add("Genf1710_pt2", "Gen f_{0}(1710) mass", kTH1F, {glueballMassAxis}); hMChists.add("GenEta", "Gen Eta", kTHnSparseF, {ptAxis, {100, -1.0f, 1.0f}}); hMChists.add("GenPhi", "Gen Phi", kTH1F, {{70, -3.5f, 3.5f}}); hMChists.add("GenRapidity", "Gen Rapidity", kTHnSparseF, {ptAxis, {100, -1.0f, 1.0f}}); hMChists.add("RecEta", "Rec Eta", kTH1F, {{100, -1.0f, 1.0f}}); hMChists.add("RecPhi", "Rec Phi", kTH1F, {{70, 0.0f, 7.0f}}); hMChists.add("RecRapidity", "Rec Rapidity", kTH1F, {{100, -1.0f, 1.0f}}); - hMChists.add("MC_mult", "Multiplicity in MC", kTH1F, {multiplicityAxis}); + hMChists.add("Rec_Multiplicity", "Multiplicity in MC", kTH1F, {multiplicityAxis}); hMChists.add("MC_mult_after_event_sel", "Multiplicity in MC", kTH1F, {multiplicityAxis}); // hMChists.add("GenPx", "Gen Px", kTH1F, {{100, -10.0f, 10.0f}}); // hMChists.add("GenPy", "Gen Py", kTH1F, {{100, -10.0f, 10.0f}}); @@ -982,12 +984,14 @@ struct HigherMassResonances { int counter = 0; float multiplicityGen = 0.0; + std::vector passKs; + ROOT::Math::PxPyPzMVector lResonance_gen, lResonance_gen2; + void processGen(aod::McCollision const& mcCollision, aod::McParticles const& mcParticles, const soa::SmallGroups& collisions) { if (config.isMC == false) { return; } - ROOT::Math::PxPyPzMVector lResonance_gen; hMChists.fill(HIST("events_check"), 0.5); if (std::abs(mcCollision.posZ()) < config.cutzvertex) { hMChists.fill(HIST("events_check"), 1.5); @@ -1039,6 +1043,11 @@ struct HigherMassResonances { } hMChists.fill(HIST("events_check"), 5.5); + if (config.apply_rapidityMC && std::abs(mcParticle.y()) >= 0.5) { + continue; + } + hMChists.fill(HIST("events_check"), 6.5); + // if (counter < 1e3) // std::cout << "px " << mcParticle.px() << " py " << mcParticle.py() << " pz " << mcParticle.pz() << " y " << mcParticle.y() << std::endl; // counter++; @@ -1050,18 +1059,12 @@ struct HigherMassResonances { // hMChists.fill(HIST("GenPy"), mcParticle.py()); // hMChists.fill(HIST("GenPz"), mcParticle.pz()); - if (config.apply_rapidityMC && std::abs(mcParticle.y()) >= 0.5) { - continue; - } - hMChists.fill(HIST("events_check"), 6.5); - auto kDaughters = mcParticle.daughters_as(); if (kDaughters.size() != 2) { continue; } hMChists.fill(HIST("events_check"), 7.5); - auto passKs = false; for (const auto& kCurrentDaughter : kDaughters) { // int daupdg = std::abs(kCurrentDaughter.pdgCode()); @@ -1069,24 +1072,31 @@ struct HigherMassResonances { continue; } hMChists.fill(HIST("events_check"), 8.5); - if (std::abs(kCurrentDaughter.pdgCode()) == 310) { - passKs = true; + passKs.push_back(true); hMChists.fill(HIST("events_check"), 9.5); - daughter1 = ROOT::Math::PxPyPzMVector(kCurrentDaughter.px(), kCurrentDaughter.py(), kCurrentDaughter.pz(), o2::constants::physics::MassK0Short); + if (passKs.size() == 1) { + daughter1 = ROOT::Math::PxPyPzMVector(kCurrentDaughter.px(), kCurrentDaughter.py(), kCurrentDaughter.pz(), o2::constants::physics::MassK0Short); + } else if (passKs.size() == 2) { + daughter2 = ROOT::Math::PxPyPzMVector(kCurrentDaughter.px(), kCurrentDaughter.py(), kCurrentDaughter.pz(), o2::constants::physics::MassK0Short); + } } } - if (passKs) { + if (passKs.size() == 2) { lResonance_gen = ROOT::Math::PxPyPzMVector(mcParticle.pt(), mcParticle.eta(), mcParticle.phi(), mcParticle.e()); - mother = ROOT::Math::PxPyPzMVector(lResonance_gen.Px(), lResonance_gen.Py(), lResonance_gen.Pz(), lResonance_gen.M()); - ROOT::Math::Boost boost{mother.BoostToCM()}; + lResonance_gen2 = daughter1 + daughter2; // invariant mass of Kshort pair + + ROOT::Math::Boost boost{lResonance_gen.BoostToCM()}; fourVecDauCM = boost(daughter1); // boost the frame of daughter to the center of mass frame - auto helicity_gen = daughter1.Vect().Dot(fourVecDauCM.Vect()) / (std::sqrt(fourVecDauCM.Vect().Mag2()) * std::sqrt(daughter1.Vect().Mag2())); + auto helicity_gen = lResonance_gen.Vect().Dot(fourVecDauCM.Vect()) / (std::sqrt(fourVecDauCM.Vect().Mag2()) * std::sqrt(lResonance_gen.Vect().Mag2())); - hMChists.fill(HIST("Genf1710"), multiplicityGen, mcParticle.pt(), lResonance_gen.M(), helicity_gen); - // hMChists.fill(HIST("Genf1710_mass"), lResonance_gen.M()); + hMChists.fill(HIST("Genf1710"), multiplicityGen, mcParticle.pt(), helicity_gen); + hMChists.fill(HIST("Genf1710_mass"), lResonance_gen.M()); + hMChists.fill(HIST("Genf1710_mass2"), lResonance_gen2.M()); + hMChists.fill(HIST("Genf1710_pt2"), lResonance_gen2.Pt()); } + passKs.clear(); // clear the vector for the next iteration } } PROCESS_SWITCH(HigherMassResonances, processGen, "Process Generated", false); @@ -1102,7 +1112,7 @@ struct HigherMassResonances { ROOT::Math::PxPyPzMVector lDecayDaughter1, lDecayDaughter2, lResonance; auto multiplicity = collision.centFT0C(); - hMChists.fill(HIST("MC_mult"), multiplicity); + hMChists.fill(HIST("Rec_Multiplicity"), multiplicity); hMChists.fill(HIST("events_checkrec"), 0.5); if (!collision.has_mcCollision()) { @@ -1270,11 +1280,9 @@ struct HigherMassResonances { continue; } // daughter1, mother, fourVecDauCM - mother = ROOT::Math::PxPyPzMVector(lResonance.Px(), lResonance.Py(), lResonance.Pz(), lResonance.M()); - daughter1 = ROOT::Math::PxPyPzMVector(lDecayDaughter1.Px(), lDecayDaughter1.Py(), lDecayDaughter1.Pz(), o2::constants::physics::MassK0Short); - ROOT::Math::Boost boost{mother.BoostToCM()}; - fourVecDauCM = boost(daughter1); // boost the frame of daughter to the center of mass frame - auto helicity_rec = daughter1.Vect().Dot(fourVecDauCM.Vect()) / (std::sqrt(fourVecDauCM.Vect().Mag2()) * std::sqrt(daughter1.Vect().Mag2())); + ROOT::Math::Boost boost{lResonance.BoostToCM()}; + fourVecDauCM = boost(lDecayDaughter1); // boost the frame of daughter to the center of mass frame + auto helicity_rec = lResonance.Vect().Dot(fourVecDauCM.Vect()) / (std::sqrt(fourVecDauCM.Vect().Mag2()) * std::sqrt(lResonance.Vect().Mag2())); // hMChists.fill(HIST("Recf1710_p"), motherP); // hMChists.fill(HIST("Recf1710_mass"), recMass); From 2ad62b3c1c4164fe32855e7db09271965f4570e6 Mon Sep 17 00:00:00 2001 From: skundu692 <86804743+skundu692@users.noreply.github.com> Date: Sat, 28 Jun 2025 13:42:45 +0200 Subject: [PATCH 256/871] [PWGLF] Avoid pair repeat in mixing (#11820) --- PWGLF/Tasks/Strangeness/lambdaspincorrderived.cxx | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/PWGLF/Tasks/Strangeness/lambdaspincorrderived.cxx b/PWGLF/Tasks/Strangeness/lambdaspincorrderived.cxx index 0dd9b2ac542..78bc5c5fa5e 100644 --- a/PWGLF/Tasks/Strangeness/lambdaspincorrderived.cxx +++ b/PWGLF/Tasks/Strangeness/lambdaspincorrderived.cxx @@ -259,13 +259,22 @@ struct lambdaspincorrderived { Preslice tracksPerCollisionV0 = aod::lambdapair::lambdaeventId; void processME(EventCandidates const& collisions, AllTrackCandidates const& V0s) { + auto collOldIndex = -999; + std::vector t1Used; for (auto& [collision1, collision2] : selfCombinations(colBinning, nEvtMixing, -1, collisions, collisions)) { // LOGF(info, "Mixed event collisions: (%d, %d)", collision1.index(), collision2.index()); auto centrality = collision1.cent(); auto groupV01 = V0s.sliceBy(tracksPerCollisionV0, collision1.globalIndex()); auto groupV02 = V0s.sliceBy(tracksPerCollisionV0, collision1.globalIndex()); auto groupV03 = V0s.sliceBy(tracksPerCollisionV0, collision2.globalIndex()); - std::vector t1Used(groupV01.size(), false); // <-- reset here + auto collNewIndex = collision1.index(); + // LOGF(info, "Mixed event collisions: (%d, %d)", collNewIndex, collOldIndex); + if (collOldIndex != collNewIndex) { + t1Used.resize(groupV01.size(), false); + // std::fill(t1Used.begin(), t1Used.end(), false); + // std::vector t1Used(groupV01.size(), false); // <-- reset here + collOldIndex = collNewIndex; + } for (auto& [t1, t3] : soa::combinations(o2::soa::CombinationsFullIndexPolicy(groupV01, groupV03))) { if (t1Used[t1.index()]) { continue; From 3d737049aea7b779575168af16dcfe18bf0bea8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADt=20Ku=C4=8Dera?= Date: Sat, 28 Jun 2025 16:53:23 +0200 Subject: [PATCH 257/871] [PWGHF] Include What You Use (#11549) --- PWGHF/Core/CentralityEstimation.h | 2 +- PWGHF/Core/HfHelper.h | 1 + PWGHF/Core/HfMlResponseB0ToDPi.h | 9 ++- PWGHF/Core/HfMlResponseBplusToD0Pi.h | 9 ++- PWGHF/Core/HfMlResponseBplusToD0PiReduced.h | 9 ++- PWGHF/Core/HfMlResponseBplusToJpsiKReduced.h | 3 + PWGHF/Core/HfMlResponseBsToDsPi.h | 9 ++- PWGHF/Core/HfMlResponseBsToJpsiPhiReduced.h | 3 + PWGHF/Core/HfMlResponseD0ToKPi.h | 13 +-- PWGHF/Core/HfMlResponseDplusToPiKPi.h | 9 ++- PWGHF/Core/HfMlResponseDsToKKPi.h | 13 +-- PWGHF/Core/HfMlResponseDstarToD0Pi.h | 18 +++-- PWGHF/Core/HfMlResponseLbToLcPi.h | 9 ++- PWGHF/Core/HfMlResponseLcToK0sP.h | 15 ++-- PWGHF/Core/HfMlResponseLcToPKPi.h | 10 ++- PWGHF/Core/HfMlResponseOmegacToOmegaPi.h | 11 ++- PWGHF/Core/HfMlResponseXic0ToXiPiKf.h | 7 +- PWGHF/Core/HfMlResponseXicToPKPi.h | 15 ++-- PWGHF/Core/HfMlResponseXicToXiPiPi.h | 5 +- PWGHF/D2H/DataModel/ReducedDataModel.h | 7 +- .../candidateCreatorB0Reduced.cxx | 28 +++++-- .../candidateCreatorBToJpsiReduced.cxx | 3 +- .../candidateCreatorBplusReduced.cxx | 29 ++++--- .../candidateCreatorBsReduced.cxx | 28 +++++-- .../candidateCreatorCharmResoReduced.cxx | 42 +++++++--- .../candidateCreatorLbReduced.cxx | 38 ++++++--- .../candidateSelectorB0ToDPiReduced.cxx | 35 +++++--- .../candidateSelectorBplusToD0PiReduced.cxx | 35 +++++--- .../candidateSelectorBsToDsPiReduced.cxx | 35 +++++--- .../candidateSelectorLbToLcPiReduced.cxx | 35 +++++--- .../converterReduced3ProngsMl.cxx | 8 +- .../converterReducedHadronDausPid.cxx | 12 +-- .../dataCreatorCharmHadPiReduced.cxx | 45 +++++++++-- .../dataCreatorCharmResoReduced.cxx | 64 ++++++++++----- .../dataCreatorJpsiHadReduced.cxx | 3 +- PWGHF/D2H/Tasks/taskB0.cxx | 36 ++++++--- PWGHF/D2H/Tasks/taskB0Reduced.cxx | 8 +- PWGHF/D2H/Tasks/taskBplus.cxx | 32 +++++--- PWGHF/D2H/Tasks/taskBplusReduced.cxx | 31 +++++-- PWGHF/D2H/Tasks/taskBplusToJpsiKReduced.cxx | 3 +- PWGHF/D2H/Tasks/taskBs.cxx | 36 ++++++--- PWGHF/D2H/Tasks/taskBsReduced.cxx | 8 +- PWGHF/D2H/Tasks/taskBsToJpsiPhiReduced.cxx | 3 +- PWGHF/D2H/Tasks/taskCharmPolarisation.cxx | 49 +++++++---- PWGHF/D2H/Tasks/taskCharmResoReduced.cxx | 22 +++-- PWGHF/D2H/Tasks/taskD0.cxx | 33 +++++--- .../Tasks/taskDirectedFlowCharmHadrons.cxx | 42 ++++++---- PWGHF/D2H/Tasks/taskDplus.cxx | 32 ++++++-- PWGHF/D2H/Tasks/taskDs.cxx | 54 +++++++++---- PWGHF/D2H/Tasks/taskDstarToD0Pi.cxx | 31 ++++--- PWGHF/D2H/Tasks/taskFlowCharmHadrons.cxx | 42 +++++++--- PWGHF/D2H/Tasks/taskLb.cxx | 41 +++++++--- PWGHF/D2H/Tasks/taskLbReduced.cxx | 29 +++++-- PWGHF/D2H/Tasks/taskLc.cxx | 30 +++++-- PWGHF/D2H/Tasks/taskLcToK0sP.cxx | 21 +++-- PWGHF/D2H/Tasks/taskOmegac0ToOmegapi.cxx | 32 +++++--- PWGHF/D2H/Tasks/taskSigmac.cxx | 29 +++++-- PWGHF/D2H/Tasks/taskSigmacToCascade.cxx | 23 +++--- PWGHF/D2H/Tasks/taskXic.cxx | 28 +++++-- PWGHF/D2H/Tasks/taskXicToXiPiPi.cxx | 31 +++++-- PWGHF/D2H/Tasks/taskXicc.cxx | 23 ++++-- PWGHF/D2H/Utils/utilsRedDataFormat.h | 4 +- .../DataModel/CandidateReconstructionTables.h | 10 +-- PWGHF/DataModel/DerivedTables.h | 15 ++-- PWGHF/HFC/DataModel/CorrelationTables.h | 10 +-- PWGHF/HFC/Macros/DhCorrelationExtraction.cxx | 10 +++ PWGHF/HFC/Macros/DhCorrelationFitter.cxx | 36 ++++----- PWGHF/HFC/TableProducer/correlatorD0D0bar.cxx | 30 ++++--- .../correlatorD0D0barBarrelFullPid.cxx | 30 ++++--- .../HFC/TableProducer/correlatorD0Hadrons.cxx | 46 ++++++++--- .../TableProducer/correlatorDMesonPairs.cxx | 36 ++++++--- .../TableProducer/correlatorDplusDminus.cxx | 31 ++++--- .../TableProducer/correlatorDplusHadrons.cxx | 43 +++++++--- .../HFC/TableProducer/correlatorDsHadrons.cxx | 31 +++++-- .../correlatorDsHadronsReduced.cxx | 29 ++++--- .../TableProducer/correlatorDstarHadrons.cxx | 38 ++++++--- .../TableProducer/correlatorHfeHadrons.cxx | 32 +++++--- .../HFC/TableProducer/correlatorLcHadrons.cxx | 51 ++++++++---- .../TableProducer/correlatorLcScHadrons.cxx | 54 +++++++++---- .../HFC/TableProducer/femtoDreamProducer.cxx | 64 +++++++++------ .../HFC/Tasks/taskCharmHadronsFemtoDream.cxx | 39 +++++---- PWGHF/HFC/Tasks/taskCorrelationD0Hadrons.cxx | 34 ++++++-- PWGHF/HFC/Tasks/taskCorrelationDDbar.cxx | 27 ++++--- .../HFC/Tasks/taskCorrelationDMesonPairs.cxx | 20 +++-- .../HFC/Tasks/taskCorrelationDplusHadrons.cxx | 47 ++++++++--- PWGHF/HFC/Tasks/taskCorrelationDsHadrons.cxx | 35 ++++++-- .../HFC/Tasks/taskCorrelationDstarHadrons.cxx | 21 +++-- PWGHF/HFC/Tasks/taskCorrelationHfeHadrons.cxx | 13 +-- PWGHF/HFC/Tasks/taskCorrelationLcHadrons.cxx | 47 ++++++++--- PWGHF/HFC/Tasks/taskFlow.cxx | 62 +++++++------- PWGHF/HFC/Utils/utilsCorrelations.h | 17 ++-- PWGHF/HFL/DataModel/ElectronSelectionTable.h | 2 +- .../electronSelectionWithTpcEmcal.cxx | 44 ++++++---- .../TableProducer/treeCreatorElectronDCA.cxx | 29 ++++--- PWGHF/HFL/Tasks/taskElectronWeakBoson.cxx | 55 +++++++------ .../Tasks/taskMuonCharmBeautySeparation.cxx | 15 ++-- PWGHF/HFL/Tasks/taskSingleMuon.cxx | 20 +++-- PWGHF/HFL/Tasks/taskSingleMuonMult.cxx | 28 ++++--- PWGHF/HFL/Tasks/taskSingleMuonReader.cxx | 21 ++--- PWGHF/HFL/Tasks/taskSingleMuonReaderAssoc.cxx | 18 ++--- PWGHF/HFL/Tasks/taskSingleMuonSource.cxx | 28 ++++--- .../computeFonllPlusPythiaPredictions.C | 32 ++++---- .../TableProducer/candidateCreator2Prong.cxx | 41 +++++++--- .../TableProducer/candidateCreator3Prong.cxx | 40 ++++++--- PWGHF/TableProducer/candidateCreatorB0.cxx | 51 ++++++++---- PWGHF/TableProducer/candidateCreatorBplus.cxx | 51 ++++++++---- PWGHF/TableProducer/candidateCreatorBs.cxx | 51 ++++++++---- .../TableProducer/candidateCreatorCascade.cxx | 59 +++++++++----- PWGHF/TableProducer/candidateCreatorDstar.cxx | 58 ++++++++----- PWGHF/TableProducer/candidateCreatorLb.cxx | 40 ++++++--- PWGHF/TableProducer/candidateCreatorMcGen.cxx | 23 +++--- .../candidateCreatorSigmac0plusplus.cxx | 44 +++++++--- ...candidateCreatorSigmac0plusplusCascade.cxx | 26 +++--- .../candidateCreatorXic0Omegac0.cxx | 81 ++++++++++--------- .../candidateCreatorXicToXiPiPi.cxx | 40 ++++++--- PWGHF/TableProducer/candidateCreatorXicc.cxx | 34 +++++--- .../candidateSelectorB0ToDPi.cxx | 37 ++++++--- .../candidateSelectorBplusToD0Pi.cxx | 38 ++++++--- .../candidateSelectorBsToDsPi.cxx | 34 +++++--- PWGHF/TableProducer/candidateSelectorD0.cxx | 31 ++++--- .../candidateSelectorDplusToPiKPi.cxx | 31 ++++--- .../candidateSelectorDsToKKPi.cxx | 31 ++++--- .../candidateSelectorDstarToD0Pi.cxx | 35 +++++--- .../candidateSelectorLbToLcPi.cxx | 23 ++++-- PWGHF/TableProducer/candidateSelectorLc.cxx | 33 +++++--- .../candidateSelectorLcPidMl.cxx | 41 +++++++--- .../candidateSelectorLcToK0sP.cxx | 35 +++++--- .../candidateSelectorOmegac0ToOmegaKa.cxx | 29 +++++-- .../candidateSelectorOmegac0ToOmegaPi.cxx | 39 ++++++--- .../TableProducer/candidateSelectorToXiPi.cxx | 29 +++++-- .../candidateSelectorXic0ToXiPiKf.cxx | 37 ++++++--- .../candidateSelectorXicToPKPi.cxx | 33 +++++--- .../candidateSelectorXicToXiPiPi.cxx | 21 ++++- .../candidateSelectorXiccToPKPiPi.cxx | 22 +++-- PWGHF/TableProducer/converterDstarIndices.cxx | 8 +- .../derivedDataCreatorB0ToDPi.cxx | 39 +++++---- .../derivedDataCreatorBplusToD0Pi.cxx | 40 +++++---- .../derivedDataCreatorD0ToKPi.cxx | 40 +++++---- .../derivedDataCreatorDplusToPiKPi.cxx | 39 ++++++--- .../derivedDataCreatorDstarToD0Pi.cxx | 38 ++++++--- .../derivedDataCreatorLcToPKPi.cxx | 39 ++++++--- PWGHF/TableProducer/mcPidTof.cxx | 32 ++++++-- PWGHF/TableProducer/pidCreator.cxx | 18 +++-- PWGHF/TableProducer/refitPvDummy.cxx | 11 +-- PWGHF/TableProducer/trackIndexSkimCreator.cxx | 72 +++++++++++------ PWGHF/TableProducer/treeCreatorB0ToDPi.cxx | 20 ++++- .../TableProducer/treeCreatorBplusToD0Pi.cxx | 21 ++++- PWGHF/TableProducer/treeCreatorBsToDsPi.cxx | 20 ++++- PWGHF/TableProducer/treeCreatorD0ToKPi.cxx | 22 ++++- .../TableProducer/treeCreatorDplusToPiKPi.cxx | 24 ++++-- PWGHF/TableProducer/treeCreatorDsToKKPi.cxx | 26 ++++-- .../TableProducer/treeCreatorDstarToD0Pi.cxx | 18 ++++- PWGHF/TableProducer/treeCreatorLbToLcPi.cxx | 15 +++- PWGHF/TableProducer/treeCreatorLcToK0sP.cxx | 19 ++++- PWGHF/TableProducer/treeCreatorLcToPKPi.cxx | 20 ++++- .../treeCreatorOmegac0ToOmegaKa.cxx | 17 +++- .../treeCreatorOmegac0ToOmegaPi.cxx | 19 ++++- PWGHF/TableProducer/treeCreatorOmegacSt.cxx | 49 +++++++---- .../TableProducer/treeCreatorTccToD0D0Pi.cxx | 65 +++++++++------ PWGHF/TableProducer/treeCreatorToXiPi.cxx | 22 +++-- .../TableProducer/treeCreatorXic0ToXiPiKf.cxx | 22 +++-- PWGHF/TableProducer/treeCreatorXicToPKPi.cxx | 18 ++++- .../TableProducer/treeCreatorXicToXiPiPi.cxx | 18 ++++- .../TableProducer/treeCreatorXiccToPKPiPi.cxx | 18 ++++- PWGHF/Tasks/taskCharmHadImpactPar.cxx | 32 +++++--- PWGHF/Tasks/taskLcCentrality.cxx | 27 ++++--- PWGHF/Tasks/taskMcEfficiency.cxx | 47 +++++++---- PWGHF/Tasks/taskMcEfficiencyToXiPi.cxx | 31 ++++--- PWGHF/Tasks/taskMcGenPtRapShapes.cxx | 26 ++++-- PWGHF/Tasks/taskMcValidation.cxx | 64 ++++++++++----- .../taskMultiplicityEstimatorCorrelation.cxx | 28 +++++-- PWGHF/Tasks/taskPidStudies.cxx | 41 ++++++---- PWGHF/Tasks/taskSelOptimisation.cxx | 29 +++++-- PWGHF/Utils/utilsBfieldCCDB.h | 3 +- PWGHF/Utils/utilsDerivedData.h | 7 +- PWGHF/Utils/utilsEvSelHf.h | 5 +- PWGHF/Utils/utilsMcGen.h | 2 + PWGHF/Utils/utilsPid.h | 8 +- 178 files changed, 3424 insertions(+), 1593 deletions(-) diff --git a/PWGHF/Core/CentralityEstimation.h b/PWGHF/Core/CentralityEstimation.h index e575e11aa57..bd1746c4604 100644 --- a/PWGHF/Core/CentralityEstimation.h +++ b/PWGHF/Core/CentralityEstimation.h @@ -16,7 +16,7 @@ #ifndef PWGHF_CORE_CENTRALITYESTIMATION_H_ #define PWGHF_CORE_CENTRALITYESTIMATION_H_ -#include +#include namespace o2::hf_centrality { diff --git a/PWGHF/Core/HfHelper.h b/PWGHF/Core/HfHelper.h index 933557eaa29..078b68ac8e8 100644 --- a/PWGHF/Core/HfHelper.h +++ b/PWGHF/Core/HfHelper.h @@ -27,6 +27,7 @@ #include #include // IWYU pragma: keep (do not replace with Math/Vector4Dfwd.h) +#include #include #include diff --git a/PWGHF/Core/HfMlResponseB0ToDPi.h b/PWGHF/Core/HfMlResponseB0ToDPi.h index 7f6c1c80cc5..1f6d4940b7f 100644 --- a/PWGHF/Core/HfMlResponseB0ToDPi.h +++ b/PWGHF/Core/HfMlResponseB0ToDPi.h @@ -17,13 +17,14 @@ #ifndef PWGHF_CORE_HFMLRESPONSEB0TODPI_H_ #define PWGHF_CORE_HFMLRESPONSEB0TODPI_H_ -#include -#include -#include - #include "PWGHF/Core/HfMlResponse.h" #include "PWGHF/D2H/Utils/utilsRedDataFormat.h" +#include "Tools/ML/MlResponse.h" + +#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 diff --git a/PWGHF/Core/HfMlResponseBplusToD0Pi.h b/PWGHF/Core/HfMlResponseBplusToD0Pi.h index 90fb0669675..427e90fd16d 100644 --- a/PWGHF/Core/HfMlResponseBplusToD0Pi.h +++ b/PWGHF/Core/HfMlResponseBplusToD0Pi.h @@ -16,13 +16,14 @@ #ifndef PWGHF_CORE_HFMLRESPONSEBPLUSTOD0PI_H_ #define PWGHF_CORE_HFMLRESPONSEBPLUSTOD0PI_H_ -#include -#include -#include - #include "PWGHF/Core/HfMlResponse.h" #include "PWGHF/D2H/Utils/utilsRedDataFormat.h" +#include "Tools/ML/MlResponse.h" + +#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 diff --git a/PWGHF/Core/HfMlResponseBplusToD0PiReduced.h b/PWGHF/Core/HfMlResponseBplusToD0PiReduced.h index 6f56cbce245..93e2ea67eb4 100644 --- a/PWGHF/Core/HfMlResponseBplusToD0PiReduced.h +++ b/PWGHF/Core/HfMlResponseBplusToD0PiReduced.h @@ -16,13 +16,14 @@ #ifndef PWGHF_CORE_HFMLRESPONSEBPLUSTOD0PIREDUCED_H_ #define PWGHF_CORE_HFMLRESPONSEBPLUSTOD0PIREDUCED_H_ -#include -#include -#include - #include "PWGHF/Core/HfMlResponse.h" #include "PWGHF/D2H/Utils/utilsRedDataFormat.h" +#include "Tools/ML/MlResponse.h" + +#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 diff --git a/PWGHF/Core/HfMlResponseBplusToJpsiKReduced.h b/PWGHF/Core/HfMlResponseBplusToJpsiKReduced.h index 5f218ec6259..ebf77e7effe 100644 --- a/PWGHF/Core/HfMlResponseBplusToJpsiKReduced.h +++ b/PWGHF/Core/HfMlResponseBplusToJpsiKReduced.h @@ -19,6 +19,9 @@ #include "PWGHF/Core/HfMlResponse.h" #include "PWGHF/D2H/Utils/utilsRedDataFormat.h" +#include "Tools/ML/MlResponse.h" + +#include #include // Fill the map of available input features diff --git a/PWGHF/Core/HfMlResponseBsToDsPi.h b/PWGHF/Core/HfMlResponseBsToDsPi.h index 111a76b1227..4c472034f71 100644 --- a/PWGHF/Core/HfMlResponseBsToDsPi.h +++ b/PWGHF/Core/HfMlResponseBsToDsPi.h @@ -16,13 +16,14 @@ #ifndef PWGHF_CORE_HFMLRESPONSEBSTODSPI_H_ #define PWGHF_CORE_HFMLRESPONSEBSTODSPI_H_ -#include -#include -#include - #include "PWGHF/Core/HfMlResponse.h" #include "PWGHF/D2H/Utils/utilsRedDataFormat.h" +#include "Tools/ML/MlResponse.h" + +#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 diff --git a/PWGHF/Core/HfMlResponseBsToJpsiPhiReduced.h b/PWGHF/Core/HfMlResponseBsToJpsiPhiReduced.h index 71e19567a2b..2af47921132 100644 --- a/PWGHF/Core/HfMlResponseBsToJpsiPhiReduced.h +++ b/PWGHF/Core/HfMlResponseBsToJpsiPhiReduced.h @@ -19,6 +19,9 @@ #include "PWGHF/Core/HfMlResponse.h" #include "PWGHF/D2H/Utils/utilsRedDataFormat.h" +#include "Tools/ML/MlResponse.h" + +#include #include // Fill the map of available input features diff --git a/PWGHF/Core/HfMlResponseD0ToKPi.h b/PWGHF/Core/HfMlResponseD0ToKPi.h index fbca4f8319e..8a1128bd65f 100644 --- a/PWGHF/Core/HfMlResponseD0ToKPi.h +++ b/PWGHF/Core/HfMlResponseD0ToKPi.h @@ -17,15 +17,16 @@ #ifndef PWGHF_CORE_HFMLRESPONSED0TOKPI_H_ #define PWGHF_CORE_HFMLRESPONSED0TOKPI_H_ -#include -#include -#include - -#include "CommonConstants/PhysicsConstants.h" - #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/HfMlResponse.h" +#include "Tools/ML/MlResponse.h" + +#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 diff --git a/PWGHF/Core/HfMlResponseDplusToPiKPi.h b/PWGHF/Core/HfMlResponseDplusToPiKPi.h index 42dde77eda7..fd6085b5ce9 100644 --- a/PWGHF/Core/HfMlResponseDplusToPiKPi.h +++ b/PWGHF/Core/HfMlResponseDplusToPiKPi.h @@ -16,12 +16,13 @@ #ifndef PWGHF_CORE_HFMLRESPONSEDPLUSTOPIKPI_H_ #define PWGHF_CORE_HFMLRESPONSEDPLUSTOPIKPI_H_ -#include -#include -#include - #include "PWGHF/Core/HfMlResponse.h" +#include "Tools/ML/MlResponse.h" + +#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 diff --git a/PWGHF/Core/HfMlResponseDsToKKPi.h b/PWGHF/Core/HfMlResponseDsToKKPi.h index ccb6a99e371..0c166e55e51 100644 --- a/PWGHF/Core/HfMlResponseDsToKKPi.h +++ b/PWGHF/Core/HfMlResponseDsToKKPi.h @@ -16,17 +16,20 @@ #ifndef PWGHF_CORE_HFMLRESPONSEDSTOKKPI_H_ #define PWGHF_CORE_HFMLRESPONSEDSTOKKPI_H_ -#include - #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/HfMlResponse.h" +#include "Tools/ML/MlResponse.h" + +#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_DS(FEATURE) \ - { \ -#FEATURE, static_cast < uint8_t>(InputFeaturesDsToKKPi::FEATURE) \ +#define FILL_MAP_DS(FEATURE) \ + { \ + #FEATURE, static_cast(InputFeaturesDsToKKPi::FEATURE) \ } // Check if the index of mCachedIndices (index associated to a FEATURE) diff --git a/PWGHF/Core/HfMlResponseDstarToD0Pi.h b/PWGHF/Core/HfMlResponseDstarToD0Pi.h index be309743893..4d9e2bff488 100644 --- a/PWGHF/Core/HfMlResponseDstarToD0Pi.h +++ b/PWGHF/Core/HfMlResponseDstarToD0Pi.h @@ -16,19 +16,21 @@ #ifndef PWGHF_CORE_HFMLRESPONSEDSTARTOD0PI_H_ #define PWGHF_CORE_HFMLRESPONSEDSTARTOD0PI_H_ -#include -#include -#include - #include "PWGHF/Core/HfMlResponse.h" -#include "CommonConstants/PhysicsConstants.h" + +#include "Tools/ML/MlResponse.h" + +#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_DSTAR(FEATURE) \ - { \ -#FEATURE, static_cast < uint8_t>(InputFeaturesDstarToD0Pi::FEATURE) \ +#define FILL_MAP_DSTAR(FEATURE) \ + { \ + #FEATURE, static_cast(InputFeaturesDstarToD0Pi::FEATURE) \ } // Check if the index of mCachedIndices (index associated to a FEATURE) diff --git a/PWGHF/Core/HfMlResponseLbToLcPi.h b/PWGHF/Core/HfMlResponseLbToLcPi.h index a421f9019d4..8375e8cf5ea 100644 --- a/PWGHF/Core/HfMlResponseLbToLcPi.h +++ b/PWGHF/Core/HfMlResponseLbToLcPi.h @@ -16,13 +16,14 @@ #ifndef PWGHF_CORE_HFMLRESPONSELBTOLCPI_H_ #define PWGHF_CORE_HFMLRESPONSELBTOLCPI_H_ -#include -#include -#include - #include "PWGHF/Core/HfMlResponse.h" #include "PWGHF/D2H/Utils/utilsRedDataFormat.h" +#include "Tools/ML/MlResponse.h" + +#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 diff --git a/PWGHF/Core/HfMlResponseLcToK0sP.h b/PWGHF/Core/HfMlResponseLcToK0sP.h index 2dc78cb19d1..a3484c029cb 100644 --- a/PWGHF/Core/HfMlResponseLcToK0sP.h +++ b/PWGHF/Core/HfMlResponseLcToK0sP.h @@ -17,19 +17,20 @@ #ifndef PWGHF_CORE_HFMLRESPONSELCTOK0SP_H_ #define PWGHF_CORE_HFMLRESPONSELCTOK0SP_H_ -#include -#include -#include - #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/HfMlResponse.h" +#include "Tools/ML/MlResponse.h" + +#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_LC(FEATURE) \ - { \ -#FEATURE, static_cast < uint8_t>(InputFeaturesLcToK0sP::FEATURE) \ +#define FILL_MAP_LC(FEATURE) \ + { \ + #FEATURE, static_cast(InputFeaturesLcToK0sP::FEATURE) \ } // Check if the index of mCachedIndices (index associated to a FEATURE) diff --git a/PWGHF/Core/HfMlResponseLcToPKPi.h b/PWGHF/Core/HfMlResponseLcToPKPi.h index ae797f32acd..6c09afdbe8f 100644 --- a/PWGHF/Core/HfMlResponseLcToPKPi.h +++ b/PWGHF/Core/HfMlResponseLcToPKPi.h @@ -16,14 +16,16 @@ #ifndef PWGHF_CORE_HFMLRESPONSELCTOPKPI_H_ #define PWGHF_CORE_HFMLRESPONSELCTOPKPI_H_ +#include "PWGHF/Core/HfMlResponse.h" +#include "PWGHF/DataModel/CandidateReconstructionTables.h" + +#include "Tools/ML/MlResponse.h" + +#include #include #include #include -#include "PWGHF/DataModel/CandidateReconstructionTables.h" - -#include "PWGHF/Core/HfMlResponse.h" - // Fill the map of available input features // the key is the feature's name (std::string) // the value is the corresponding value in EnumInputFeatures diff --git a/PWGHF/Core/HfMlResponseOmegacToOmegaPi.h b/PWGHF/Core/HfMlResponseOmegacToOmegaPi.h index 53b40330e04..c61616cc9d4 100644 --- a/PWGHF/Core/HfMlResponseOmegacToOmegaPi.h +++ b/PWGHF/Core/HfMlResponseOmegacToOmegaPi.h @@ -16,15 +16,14 @@ #ifndef PWGHF_CORE_HFMLRESPONSEOMEGACTOOMEGAPI_H_ #define PWGHF_CORE_HFMLRESPONSEOMEGACTOOMEGAPI_H_ -#include -#include -#include - -#include "CommonConstants/PhysicsConstants.h" - #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/HfMlResponse.h" +#include "Tools/ML/MlResponse.h" + +#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 diff --git a/PWGHF/Core/HfMlResponseXic0ToXiPiKf.h b/PWGHF/Core/HfMlResponseXic0ToXiPiKf.h index d75bdcc4c10..3fbb6cf4052 100644 --- a/PWGHF/Core/HfMlResponseXic0ToXiPiKf.h +++ b/PWGHF/Core/HfMlResponseXic0ToXiPiKf.h @@ -16,10 +16,13 @@ #ifndef PWGHF_CORE_HFMLRESPONSEXIC0TOXIPIKF_H_ #define PWGHF_CORE_HFMLRESPONSEXIC0TOXIPIKF_H_ -#include - #include "PWGHF/Core/HfMlResponse.h" +#include "Tools/ML/MlResponse.h" + +#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 diff --git a/PWGHF/Core/HfMlResponseXicToPKPi.h b/PWGHF/Core/HfMlResponseXicToPKPi.h index d533c7fb8ab..f433d29bd5d 100644 --- a/PWGHF/Core/HfMlResponseXicToPKPi.h +++ b/PWGHF/Core/HfMlResponseXicToPKPi.h @@ -16,18 +16,19 @@ #ifndef PWGHF_CORE_HFMLRESPONSEXICTOPKPI_H_ #define PWGHF_CORE_HFMLRESPONSEXICTOPKPI_H_ -#include -#include -#include - #include "PWGHF/Core/HfMlResponse.h" +#include "Tools/ML/MlResponse.h" + +#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_XIC(FEATURE) \ - { \ -#FEATURE, static_cast < uint8_t>(InputFeaturesXicToPKPi::FEATURE) \ +#define FILL_MAP_XIC(FEATURE) \ + { \ + #FEATURE, static_cast(InputFeaturesXicToPKPi::FEATURE) \ } // Check if the index of mCachedIndices (index associated to a FEATURE) diff --git a/PWGHF/Core/HfMlResponseXicToXiPiPi.h b/PWGHF/Core/HfMlResponseXicToXiPiPi.h index 64a3241485b..4bb4a4d023f 100644 --- a/PWGHF/Core/HfMlResponseXicToXiPiPi.h +++ b/PWGHF/Core/HfMlResponseXicToXiPiPi.h @@ -18,8 +18,9 @@ #include "PWGHF/Core/HfMlResponse.h" -#include -#include +#include "Tools/ML/MlResponse.h" + +#include #include // Fill the map of available input features diff --git a/PWGHF/D2H/DataModel/ReducedDataModel.h b/PWGHF/D2H/DataModel/ReducedDataModel.h index 10e997f7ed4..c23a22efcad 100644 --- a/PWGHF/D2H/DataModel/ReducedDataModel.h +++ b/PWGHF/D2H/DataModel/ReducedDataModel.h @@ -34,9 +34,10 @@ #include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/Qvectors.h" -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/ASoA.h" -#include "Framework/AnalysisDataModel.h" +#include +#include +#include +#include #include #include diff --git a/PWGHF/D2H/TableProducer/candidateCreatorB0Reduced.cxx b/PWGHF/D2H/TableProducer/candidateCreatorB0Reduced.cxx index 6434b88e024..a5815359f4b 100644 --- a/PWGHF/D2H/TableProducer/candidateCreatorB0Reduced.cxx +++ b/PWGHF/D2H/TableProducer/candidateCreatorB0Reduced.cxx @@ -17,19 +17,31 @@ #include "PWGHF/D2H/DataModel/ReducedDataModel.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" #include "PWGHF/Utils/utilsTrkCandHf.h" +#include "Common/Core/RecoDecay.h" #include "Common/Core/trackUtilities.h" -#include "Common/DataModel/CollisionAssociationTables.h" - -#include "CommonConstants/PhysicsConstants.h" -#include "DCAFitter/DCAFitterN.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/DCA.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::aod; diff --git a/PWGHF/D2H/TableProducer/candidateCreatorBToJpsiReduced.cxx b/PWGHF/D2H/TableProducer/candidateCreatorBToJpsiReduced.cxx index 3fe788035af..39b54c2e13c 100644 --- a/PWGHF/D2H/TableProducer/candidateCreatorBToJpsiReduced.cxx +++ b/PWGHF/D2H/TableProducer/candidateCreatorBToJpsiReduced.cxx @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -40,8 +41,6 @@ #include -#include - #include #include #include diff --git a/PWGHF/D2H/TableProducer/candidateCreatorBplusReduced.cxx b/PWGHF/D2H/TableProducer/candidateCreatorBplusReduced.cxx index bbd8f9df356..1bcff8ae7ae 100644 --- a/PWGHF/D2H/TableProducer/candidateCreatorBplusReduced.cxx +++ b/PWGHF/D2H/TableProducer/candidateCreatorBplusReduced.cxx @@ -16,20 +16,31 @@ #include "PWGHF/D2H/DataModel/ReducedDataModel.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" #include "PWGHF/Utils/utilsTrkCandHf.h" +#include "Common/Core/RecoDecay.h" #include "Common/Core/trackUtilities.h" -#include "Common/DataModel/CollisionAssociationTables.h" - -#include "CommonConstants/PhysicsConstants.h" -#include "DCAFitter/DCAFitterN.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/DCA.h" -#include "ReconstructionDataFormats/V0.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::aod; diff --git a/PWGHF/D2H/TableProducer/candidateCreatorBsReduced.cxx b/PWGHF/D2H/TableProducer/candidateCreatorBsReduced.cxx index a20adc78f7e..4a9ee3a9c57 100644 --- a/PWGHF/D2H/TableProducer/candidateCreatorBsReduced.cxx +++ b/PWGHF/D2H/TableProducer/candidateCreatorBsReduced.cxx @@ -16,19 +16,31 @@ #include "PWGHF/D2H/DataModel/ReducedDataModel.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" #include "PWGHF/Utils/utilsTrkCandHf.h" +#include "Common/Core/RecoDecay.h" #include "Common/Core/trackUtilities.h" -#include "Common/DataModel/CollisionAssociationTables.h" - -#include "CommonConstants/PhysicsConstants.h" -#include "DCAFitter/DCAFitterN.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/DCA.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::aod; diff --git a/PWGHF/D2H/TableProducer/candidateCreatorCharmResoReduced.cxx b/PWGHF/D2H/TableProducer/candidateCreatorCharmResoReduced.cxx index 1055c891092..7911f206d61 100644 --- a/PWGHF/D2H/TableProducer/candidateCreatorCharmResoReduced.cxx +++ b/PWGHF/D2H/TableProducer/candidateCreatorCharmResoReduced.cxx @@ -13,22 +13,38 @@ /// \brief Reconstruction of Resonance candidates /// /// \author Luca Aglietta , Università degli Studi di Torino -#include -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/DCA.h" -#include "ReconstructionDataFormats/V0.h" - -#include "Common/Core/trackUtilities.h" -#include "Common/DataModel/CollisionAssociationTables.h" - -#include "PWGHF/D2H/DataModel/ReducedDataModel.h" #include "PWGHF/D2H/Core/SelectorCutsRedDataFormat.h" +#include "PWGHF/D2H/DataModel/ReducedDataModel.h" #include "PWGHF/Utils/utilsAnalysis.h" +#include "Common/Core/RecoDecay.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::aod; using namespace o2::analysis; diff --git a/PWGHF/D2H/TableProducer/candidateCreatorLbReduced.cxx b/PWGHF/D2H/TableProducer/candidateCreatorLbReduced.cxx index 9246748ab48..8ccb879719e 100644 --- a/PWGHF/D2H/TableProducer/candidateCreatorLbReduced.cxx +++ b/PWGHF/D2H/TableProducer/candidateCreatorLbReduced.cxx @@ -14,22 +14,34 @@ /// /// \author Biao Zhang , Heidelberg University -#include -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "DCAFitter/DCAFitterN.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/DCA.h" +#include "PWGHF/D2H/DataModel/ReducedDataModel.h" +#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "PWGHF/Utils/utilsTrkCandHf.h" +#include "Common/Core/RecoDecay.h" #include "Common/Core/trackUtilities.h" -#include "Common/DataModel/CollisionAssociationTables.h" -#include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" -#include "PWGHF/D2H/DataModel/ReducedDataModel.h" -#include "PWGHF/Utils/utilsTrkCandHf.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::aod; diff --git a/PWGHF/D2H/TableProducer/candidateSelectorB0ToDPiReduced.cxx b/PWGHF/D2H/TableProducer/candidateSelectorB0ToDPiReduced.cxx index 5ddf1bcd1a8..53609fc66c9 100644 --- a/PWGHF/D2H/TableProducer/candidateSelectorB0ToDPiReduced.cxx +++ b/PWGHF/D2H/TableProducer/candidateSelectorB0ToDPiReduced.cxx @@ -15,22 +15,37 @@ /// \author Alexandre Bigot , IPHC Strasbourg /// \author Fabrizio Grosa , CERN -#include -#include - -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - -#include "Common/Core/TrackSelectorPID.h" - #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/HfMlResponseB0ToDPi.h" #include "PWGHF/Core/SelectorCuts.h" -#include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" #include "PWGHF/D2H/DataModel/ReducedDataModel.h" +#include "PWGHF/DataModel/CandidateSelectionTables.h" #include "PWGHF/Utils/utilsPid.h" +#include "Common/Core/TrackSelectorPID.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::aod; using namespace o2::framework; diff --git a/PWGHF/D2H/TableProducer/candidateSelectorBplusToD0PiReduced.cxx b/PWGHF/D2H/TableProducer/candidateSelectorBplusToD0PiReduced.cxx index b11b65a39fb..3e1554fdb2e 100644 --- a/PWGHF/D2H/TableProducer/candidateSelectorBplusToD0PiReduced.cxx +++ b/PWGHF/D2H/TableProducer/candidateSelectorBplusToD0PiReduced.cxx @@ -14,22 +14,37 @@ /// /// \author Antonio Palasciano , Università degli Studi di Bari -#include -#include - -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - -#include "Common/Core/TrackSelectorPID.h" - #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/HfMlResponseBplusToD0PiReduced.h" #include "PWGHF/Core/SelectorCuts.h" -#include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" #include "PWGHF/D2H/DataModel/ReducedDataModel.h" +#include "PWGHF/DataModel/CandidateSelectionTables.h" #include "PWGHF/Utils/utilsPid.h" +#include "Common/Core/TrackSelectorPID.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::aod; using namespace o2::framework; diff --git a/PWGHF/D2H/TableProducer/candidateSelectorBsToDsPiReduced.cxx b/PWGHF/D2H/TableProducer/candidateSelectorBsToDsPiReduced.cxx index 7864ee493b7..99e71e34acd 100644 --- a/PWGHF/D2H/TableProducer/candidateSelectorBsToDsPiReduced.cxx +++ b/PWGHF/D2H/TableProducer/candidateSelectorBsToDsPiReduced.cxx @@ -14,22 +14,37 @@ /// /// \author Fabio Catalano , CERN -#include -#include - -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - -#include "Common/Core/TrackSelectorPID.h" - #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/HfMlResponseBsToDsPi.h" #include "PWGHF/Core/SelectorCuts.h" -#include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" #include "PWGHF/D2H/DataModel/ReducedDataModel.h" +#include "PWGHF/DataModel/CandidateSelectionTables.h" #include "PWGHF/Utils/utilsPid.h" +#include "Common/Core/TrackSelectorPID.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::aod; using namespace o2::framework; diff --git a/PWGHF/D2H/TableProducer/candidateSelectorLbToLcPiReduced.cxx b/PWGHF/D2H/TableProducer/candidateSelectorLbToLcPiReduced.cxx index a4093a9340a..dbe86c4905d 100644 --- a/PWGHF/D2H/TableProducer/candidateSelectorLbToLcPiReduced.cxx +++ b/PWGHF/D2H/TableProducer/candidateSelectorLbToLcPiReduced.cxx @@ -14,22 +14,37 @@ /// /// \author Biao Zhang , Heidelberg University -#include -#include - -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - -#include "Common/Core/TrackSelectorPID.h" - #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/HfMlResponseLbToLcPi.h" #include "PWGHF/Core/SelectorCuts.h" -#include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" #include "PWGHF/D2H/DataModel/ReducedDataModel.h" +#include "PWGHF/DataModel/CandidateSelectionTables.h" #include "PWGHF/Utils/utilsPid.h" +#include "Common/Core/TrackSelectorPID.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::aod; using namespace o2::framework; diff --git a/PWGHF/D2H/TableProducer/converterReduced3ProngsMl.cxx b/PWGHF/D2H/TableProducer/converterReduced3ProngsMl.cxx index ea9450eca08..90360a29cc0 100644 --- a/PWGHF/D2H/TableProducer/converterReduced3ProngsMl.cxx +++ b/PWGHF/D2H/TableProducer/converterReduced3ProngsMl.cxx @@ -14,12 +14,12 @@ /// /// \author Fabrizio Grosa , CERN -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" - #include "PWGHF/D2H/DataModel/ReducedDataModel.h" +#include +#include +#include + using namespace o2; using namespace o2::framework; diff --git a/PWGHF/D2H/TableProducer/converterReducedHadronDausPid.cxx b/PWGHF/D2H/TableProducer/converterReducedHadronDausPid.cxx index 2d4036247f5..3acc4f222cc 100644 --- a/PWGHF/D2H/TableProducer/converterReducedHadronDausPid.cxx +++ b/PWGHF/D2H/TableProducer/converterReducedHadronDausPid.cxx @@ -14,12 +14,14 @@ /// /// \author Biao Zhang , Heidelberg University -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" - #include "PWGHF/D2H/DataModel/ReducedDataModel.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "PWGHF/DataModel/CandidateReconstructionTables.h" + +#include +#include +#include +#include +#include using namespace o2; using namespace o2::framework; diff --git a/PWGHF/D2H/TableProducer/dataCreatorCharmHadPiReduced.cxx b/PWGHF/D2H/TableProducer/dataCreatorCharmHadPiReduced.cxx index 5470de035b0..9f3f1e6fb6d 100644 --- a/PWGHF/D2H/TableProducer/dataCreatorCharmHadPiReduced.cxx +++ b/PWGHF/D2H/TableProducer/dataCreatorCharmHadPiReduced.cxx @@ -18,31 +18,60 @@ /// \author Fabio Catalano , CERN /// \author Biao Zhang , Heidelberg University +#include "PWGHF/Core/CentralityEstimation.h" #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/D2H/DataModel/ReducedDataModel.h" #include "PWGHF/D2H/Utils/utilsRedDataFormat.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" -#include "PWGHF/Utils/utilsBfieldCCDB.h" #include "PWGHF/Utils/utilsEvSelHf.h" #include "PWGHF/Utils/utilsTrkCandHf.h" +#include "Common/Core/RecoDecay.h" #include "Common/Core/trackUtilities.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/Qvectors.h" - -#include "CommonConstants/PhysicsConstants.h" -#include "DCAFitter/DCAFitterN.h" -#include "Framework/AnalysisTask.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/DCA.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 diff --git a/PWGHF/D2H/TableProducer/dataCreatorCharmResoReduced.cxx b/PWGHF/D2H/TableProducer/dataCreatorCharmResoReduced.cxx index 36deb224116..8a75fa5a486 100644 --- a/PWGHF/D2H/TableProducer/dataCreatorCharmResoReduced.cxx +++ b/PWGHF/D2H/TableProducer/dataCreatorCharmResoReduced.cxx @@ -15,34 +15,54 @@ /// \author Luca Aglietta , UniTO Turin /// \author Fabrizio Grosa , CERN -#include -#include -#include -#include -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "DCAFitter/DCAFitterN.h" -#include "DetectorsBase/Propagator.h" -#include "Framework/AnalysisTask.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/DCA.h" - -#include "Common/Core/trackUtilities.h" -#include "Common/DataModel/CollisionAssociationTables.h" -#include "Common/DataModel/TrackSelectionTables.h" - -#include "PWGLF/DataModel/LFStrangenessTables.h" - +#include "PWGHF/Core/CentralityEstimation.h" #include "PWGHF/Core/HfHelper.h" +#include "PWGHF/D2H/DataModel/ReducedDataModel.h" +#include "PWGHF/D2H/Utils/utilsRedDataFormat.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" #include "PWGHF/Utils/utilsBfieldCCDB.h" #include "PWGHF/Utils/utilsEvSelHf.h" -#include "PWGHF/D2H/DataModel/ReducedDataModel.h" -#include "PWGHF/D2H/Utils/utilsRedDataFormat.h" +#include "Common/Core/RecoDecay.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 + +#include + +#include +#include +#include +#include +#include +#include +#include +#include using namespace o2; using namespace o2::analysis; diff --git a/PWGHF/D2H/TableProducer/dataCreatorJpsiHadReduced.cxx b/PWGHF/D2H/TableProducer/dataCreatorJpsiHadReduced.cxx index 3a382d62dcf..ed6321fe4ba 100644 --- a/PWGHF/D2H/TableProducer/dataCreatorJpsiHadReduced.cxx +++ b/PWGHF/D2H/TableProducer/dataCreatorJpsiHadReduced.cxx @@ -48,6 +48,7 @@ #include #include #include +#include #include #include #include @@ -58,8 +59,6 @@ #include #include -#include - #include #include #include diff --git a/PWGHF/D2H/Tasks/taskB0.cxx b/PWGHF/D2H/Tasks/taskB0.cxx index c1076cab906..f42a9c0bf3d 100644 --- a/PWGHF/D2H/Tasks/taskB0.cxx +++ b/PWGHF/D2H/Tasks/taskB0.cxx @@ -14,19 +14,35 @@ /// /// \author Alexandre Bigot , IPHC Strasbourg -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "Framework/runDataProcessing.h" - #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "Common/Core/RecoDecay.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; using namespace o2::aod; using namespace o2::analysis; @@ -186,7 +202,7 @@ struct HfTaskB0 { registry.fill(HIST("hDecLenXYErr"), candidate.errorDecayLengthXY(), ptCandB0); registry.fill(HIST("hInvMassD"), hfHelper.invMassDplusToPiKPi(candD), ptCandB0); } // candidate loop - } // process + } // process /// B0 MC analysis and fill histograms void processMc(soa::Filtered> const& candidates, @@ -308,7 +324,7 @@ struct HfTaskB0 { registry.fill(HIST("hEtaGenWithProngsInAcceptance"), particle.eta(), ptParticle); } } // gen - } // process + } // process PROCESS_SWITCH(HfTaskB0, processMc, "Process MC", false); }; // struct diff --git a/PWGHF/D2H/Tasks/taskB0Reduced.cxx b/PWGHF/D2H/Tasks/taskB0Reduced.cxx index c917abb8776..e1e30490f18 100644 --- a/PWGHF/D2H/Tasks/taskB0Reduced.cxx +++ b/PWGHF/D2H/Tasks/taskB0Reduced.cxx @@ -22,15 +22,15 @@ #include "Common/Core/RecoDecay.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" #include #include +#include #include -#include +#include #include #include +#include +#include #include #include diff --git a/PWGHF/D2H/Tasks/taskBplus.cxx b/PWGHF/D2H/Tasks/taskBplus.cxx index b98a2930258..9d306bea7de 100644 --- a/PWGHF/D2H/Tasks/taskBplus.cxx +++ b/PWGHF/D2H/Tasks/taskBplus.cxx @@ -18,19 +18,31 @@ /// \author Antonio Palasciano , Università degli Studi di Bari & INFN, Sezione di Bari /// \author Deepa Thomas , UT Austin -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "Framework/runDataProcessing.h" - #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "Common/Core/RecoDecay.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include + using namespace o2; using namespace o2::aod; using namespace o2::analysis; @@ -198,7 +210,7 @@ struct HfTaskBplus { registry.fill(HIST("hCPAFinerBinning"), candidate.cpa(), ptCandBplus); registry.fill(HIST("hCPAxyFinerBinning"), candidate.cpaXY(), ptCandBplus); } // candidate loop - } // process + } // process void processMc(soa::Join const&, soa::Join const& mcParticles, @@ -299,7 +311,7 @@ struct HfTaskBplus { registry.fill(HIST("hEtaGenWithProngsInAcceptance"), particle.eta(), ptParticle); } } // gen - } // processMc + } // processMc PROCESS_SWITCH(HfTaskBplus, processMc, "Process MC", false); }; diff --git a/PWGHF/D2H/Tasks/taskBplusReduced.cxx b/PWGHF/D2H/Tasks/taskBplusReduced.cxx index e319692b0c2..e7a9a8f93db 100644 --- a/PWGHF/D2H/Tasks/taskBplusReduced.cxx +++ b/PWGHF/D2H/Tasks/taskBplusReduced.cxx @@ -14,18 +14,33 @@ /// /// \author Antonio Palasciano , Università degli Studi di Bari & INFN, Sezione di Bari -#include - -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" -#include "Common/Core/RecoDecay.h" - #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/SelectorCuts.h" +#include "PWGHF/D2H/DataModel/ReducedDataModel.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" -#include "PWGHF/D2H/DataModel/ReducedDataModel.h" + +#include "Common/Core/RecoDecay.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include +#include +#include +#include using namespace o2; using namespace o2::aod; diff --git a/PWGHF/D2H/Tasks/taskBplusToJpsiKReduced.cxx b/PWGHF/D2H/Tasks/taskBplusToJpsiKReduced.cxx index a3d4cf2dc71..efac09291f3 100644 --- a/PWGHF/D2H/Tasks/taskBplusToJpsiKReduced.cxx +++ b/PWGHF/D2H/Tasks/taskBplusToJpsiKReduced.cxx @@ -36,13 +36,12 @@ #include #include #include +#include #include #include #include -#include - #include #include diff --git a/PWGHF/D2H/Tasks/taskBs.cxx b/PWGHF/D2H/Tasks/taskBs.cxx index c394db35d1d..98bc8dee0aa 100644 --- a/PWGHF/D2H/Tasks/taskBs.cxx +++ b/PWGHF/D2H/Tasks/taskBs.cxx @@ -15,19 +15,35 @@ /// /// \author Phil Stahlhut -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "Framework/runDataProcessing.h" - #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "Common/Core/RecoDecay.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; using namespace o2::aod; using namespace o2::analysis; @@ -183,7 +199,7 @@ struct HfTaskBs { registry.fill(HIST("hIPProd"), candidate.impactParameterProduct(), ptCandBs); registry.fill(HIST("hInvMassDs"), hfHelper.invMassDsToKKPi(candDs), ptCandBs); } // candidate loop - } // process + } // process /// Bs MC analysis and fill histograms void processMc(soa::Filtered> const& candidates, @@ -304,7 +320,7 @@ struct HfTaskBs { registry.fill(HIST("hYGenWithProngsInAcceptance"), yParticle, ptParticle); } } // gen - } // process + } // process PROCESS_SWITCH(HfTaskBs, processMc, "Process MC", false); }; // struct diff --git a/PWGHF/D2H/Tasks/taskBsReduced.cxx b/PWGHF/D2H/Tasks/taskBsReduced.cxx index 9a41a7a40d2..a5a89e241cf 100644 --- a/PWGHF/D2H/Tasks/taskBsReduced.cxx +++ b/PWGHF/D2H/Tasks/taskBsReduced.cxx @@ -21,15 +21,15 @@ #include "Common/Core/RecoDecay.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" #include #include +#include #include -#include +#include #include #include +#include +#include #include #include diff --git a/PWGHF/D2H/Tasks/taskBsToJpsiPhiReduced.cxx b/PWGHF/D2H/Tasks/taskBsToJpsiPhiReduced.cxx index ce140114298..fda743b4628 100644 --- a/PWGHF/D2H/Tasks/taskBsToJpsiPhiReduced.cxx +++ b/PWGHF/D2H/Tasks/taskBsToJpsiPhiReduced.cxx @@ -37,13 +37,12 @@ #include #include #include +#include #include #include #include -#include - #include #include diff --git a/PWGHF/D2H/Tasks/taskCharmPolarisation.cxx b/PWGHF/D2H/Tasks/taskCharmPolarisation.cxx index 95cefe1ff0f..53667bba5ee 100644 --- a/PWGHF/D2H/Tasks/taskCharmPolarisation.cxx +++ b/PWGHF/D2H/Tasks/taskCharmPolarisation.cxx @@ -16,23 +16,42 @@ /// \author S. Kundu (CERN) sourav.kundu@cern.ch /// \author M. Faggin (CERN) mattia.faggin@cern.ch -#include - -#include "TRandom3.h" -#include "Math/Vector3D.h" -#include "Math/Vector4D.h" -#include "Math/GenVector/Boost.h" - -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" - -// #include "Common/Core/EventPlaneHelper.h" -// #include "Common/DataModel/Qvectors.h" - +#include "PWGHF/Core/DecayChannels.h" #include "PWGHF/Core/HfHelper.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "PWGHF/DataModel/CandidateSelectionTables.h" + +#include "Common/Core/RecoDecay.h" + +#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 +#include using namespace o2; using namespace o2::aod; diff --git a/PWGHF/D2H/Tasks/taskCharmResoReduced.cxx b/PWGHF/D2H/Tasks/taskCharmResoReduced.cxx index 37aef67937a..feb872262b3 100644 --- a/PWGHF/D2H/Tasks/taskCharmResoReduced.cxx +++ b/PWGHF/D2H/Tasks/taskCharmResoReduced.cxx @@ -14,20 +14,26 @@ /// /// \author Luca Aglietta , University and INFN Torino -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" +#include "PWGHF/D2H/DataModel/ReducedDataModel.h" #include "Common/Core/RecoDecay.h" -// #include "PWGHF/Core/HfHelper.h" -#include "PWGHF/Core/SelectorCuts.h" -#include "PWGHF/D2H/DataModel/ReducedDataModel.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include using namespace o2; using namespace o2::soa; -using namespace o2::analysis; using namespace o2::framework; using namespace o2::framework::expressions; using namespace o2::constants::physics; diff --git a/PWGHF/D2H/Tasks/taskD0.cxx b/PWGHF/D2H/Tasks/taskD0.cxx index b650e5bd4f0..b40c546650e 100644 --- a/PWGHF/D2H/Tasks/taskD0.cxx +++ b/PWGHF/D2H/Tasks/taskD0.cxx @@ -15,22 +15,37 @@ /// \author Gian Michele Innocenti , CERN /// \author Vít Kučera , CERN -#include -#include // std::min - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" - #include "PWGHF/Core/CentralityEstimation.h" #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" -#include "PWGHF/Utils/utilsAnalysis.h" #include "PWGHF/Utils/utilsEvSelHf.h" +#include "Common/Core/RecoDecay.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include // std::min +#include +#include +#include + using namespace o2; using namespace o2::analysis; using namespace o2::framework; diff --git a/PWGHF/D2H/Tasks/taskDirectedFlowCharmHadrons.cxx b/PWGHF/D2H/Tasks/taskDirectedFlowCharmHadrons.cxx index db2300126f2..bc4d3308c18 100644 --- a/PWGHF/D2H/Tasks/taskDirectedFlowCharmHadrons.cxx +++ b/PWGHF/D2H/Tasks/taskDirectedFlowCharmHadrons.cxx @@ -15,24 +15,36 @@ /// \author Prottay Das, prottay.das@cern.ch /// \author Biao Zhang, biao.zhanng@cern.ch -#include -#include -#include -#include - -#include "CCDB/BasicCCDBManager.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" - -#include "Common/Core/EventPlaneHelper.h" -#include "PWGLF/DataModel/SPCalibrationTables.h" - -#include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/CentralityEstimation.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "PWGHF/Core/HfHelper.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "PWGHF/DataModel/CandidateSelectionTables.h" #include "PWGHF/Utils/utilsEvSelHf.h" +#include "PWGLF/DataModel/SPCalibrationTables.h" + +#include "Common/Core/EventPlaneHelper.h" +#include "Common/DataModel/Centrality.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::aod; diff --git a/PWGHF/D2H/Tasks/taskDplus.cxx b/PWGHF/D2H/Tasks/taskDplus.cxx index 7f851263341..30734322e9d 100644 --- a/PWGHF/D2H/Tasks/taskDplus.cxx +++ b/PWGHF/D2H/Tasks/taskDplus.cxx @@ -17,14 +17,8 @@ /// \author Vít Kučera , CERN /// \author Luca Aglietta , University and INFN Torino -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" - #include "PWGHF/Core/CentralityEstimation.h" +#include "PWGHF/Core/DecayChannels.h" #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" @@ -32,6 +26,30 @@ #include "PWGHF/Utils/utilsAnalysis.h" #include "PWGHF/Utils/utilsEvSelHf.h" +#include "Common/Core/RecoDecay.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + using namespace o2; using namespace o2::analysis; using namespace o2::framework; diff --git a/PWGHF/D2H/Tasks/taskDs.cxx b/PWGHF/D2H/Tasks/taskDs.cxx index 95ecfb6c2c9..0305d004e0c 100644 --- a/PWGHF/D2H/Tasks/taskDs.cxx +++ b/PWGHF/D2H/Tasks/taskDs.cxx @@ -17,25 +17,49 @@ /// \author Stefano Politanò , Politecnico & INFN Torino /// \author Fabrizio Chinu , Universita and INFN Torino -#include -#include -#include -#include -#include - -#include "CCDB/BasicCCDBManager.h" -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" -#include "MetadataHelper.h" - -#include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/CentralityEstimation.h" +#include "PWGHF/Core/DecayChannels.h" +#include "PWGHF/Core/HfHelper.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" -#include "PWGHF/Utils/utilsEvSelHf.h" #include "PWGHF/Utils/utilsAnalysis.h" +#include "PWGHF/Utils/utilsEvSelHf.h" + +#include "Common/Core/MetadataHelper.h" +#include "Common/Core/RecoDecay.h" +#include "Common/DataModel/Centrality.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 +#include +#include +#include +#include +#include +#include using namespace o2; using namespace o2::analysis; diff --git a/PWGHF/D2H/Tasks/taskDstarToD0Pi.cxx b/PWGHF/D2H/Tasks/taskDstarToD0Pi.cxx index 0682c0584aa..3175b472a0c 100644 --- a/PWGHF/D2H/Tasks/taskDstarToD0Pi.cxx +++ b/PWGHF/D2H/Tasks/taskDstarToD0Pi.cxx @@ -17,19 +17,32 @@ /// \brief Dstar production analysis task (With and Without ML) -#include -#include -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/runDataProcessing.h" - +#include "PWGHF/Core/DecayChannels.h" #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "Common/Core/RecoDecay.h" +#include "Common/DataModel/Centrality.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + using namespace o2; using namespace o2::analysis; using namespace o2::framework; diff --git a/PWGHF/D2H/Tasks/taskFlowCharmHadrons.cxx b/PWGHF/D2H/Tasks/taskFlowCharmHadrons.cxx index 65608d34ffe..ee401849761 100644 --- a/PWGHF/D2H/Tasks/taskFlowCharmHadrons.cxx +++ b/PWGHF/D2H/Tasks/taskFlowCharmHadrons.cxx @@ -16,22 +16,40 @@ /// \author Wu Chuntai, CUG, China /// \author Ran Tu, Fudan University, China -#include -#include - -#include "CCDB/BasicCCDBManager.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" +#include "PWGHF/Core/CentralityEstimation.h" +#include "PWGHF/Core/HfHelper.h" +#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "PWGHF/Utils/utilsEvSelHf.h" #include "Common/Core/EventPlaneHelper.h" +#include "Common/Core/RecoDecay.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" #include "Common/DataModel/Qvectors.h" -#include "PWGHF/Core/HfHelper.h" -#include "PWGHF/Core/CentralityEstimation.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" -#include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/Utils/utilsEvSelHf.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::aod; diff --git a/PWGHF/D2H/Tasks/taskLb.cxx b/PWGHF/D2H/Tasks/taskLb.cxx index e934a37b554..aba513b2fd3 100644 --- a/PWGHF/D2H/Tasks/taskLb.cxx +++ b/PWGHF/D2H/Tasks/taskLb.cxx @@ -15,30 +15,45 @@ /// \author Panos Christakoglou , Nikhef /// \author Martin Voelkl , University of Birmingham -#include -#include -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/O2DatabasePDGPlugin.h" - -#include "Common/DataModel/Centrality.h" - #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "Common/Core/RecoDecay.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 + using namespace o2; using namespace o2::aod; using namespace o2::analysis; using namespace o2::framework; using namespace o2::framework::expressions; -#include "Framework/runDataProcessing.h" - /// Λb0 analysis task struct HfTaskLb { Configurable selectionFlagLb{"selectionFlagLb", 0, "Selection Flag for Lb"}; diff --git a/PWGHF/D2H/Tasks/taskLbReduced.cxx b/PWGHF/D2H/Tasks/taskLbReduced.cxx index 6ca71f85a55..f756d9abc62 100644 --- a/PWGHF/D2H/Tasks/taskLbReduced.cxx +++ b/PWGHF/D2H/Tasks/taskLbReduced.cxx @@ -14,16 +14,31 @@ /// /// \author Biao Zhang , Heidelberg University -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" -#include "Common/Core/RecoDecay.h" - #include "PWGHF/Core/HfHelper.h" -#include "PWGHF/Core/SelectorCuts.h" +#include "PWGHF/D2H/DataModel/ReducedDataModel.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" -#include "PWGHF/D2H/DataModel/ReducedDataModel.h" + +#include "Common/Core/RecoDecay.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include +#include +#include using namespace o2; using namespace o2::aod; diff --git a/PWGHF/D2H/Tasks/taskLc.cxx b/PWGHF/D2H/Tasks/taskLc.cxx index cf3c070e6b7..85eee1bb213 100644 --- a/PWGHF/D2H/Tasks/taskLc.cxx +++ b/PWGHF/D2H/Tasks/taskLc.cxx @@ -18,20 +18,36 @@ /// \author Annalena Kalteyer , GSI Darmstadt /// \author Biao Zhang , Heidelberg University -#include // std::vector - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" - #include "PWGHF/Core/CentralityEstimation.h" +#include "PWGHF/Core/DecayChannels.h" #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" #include "PWGHF/Utils/utilsEvSelHf.h" +#include "Common/Core/RecoDecay.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" + +#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; diff --git a/PWGHF/D2H/Tasks/taskLcToK0sP.cxx b/PWGHF/D2H/Tasks/taskLcToK0sP.cxx index 5b379e9e759..088c88c2629 100644 --- a/PWGHF/D2H/Tasks/taskLcToK0sP.cxx +++ b/PWGHF/D2H/Tasks/taskLcToK0sP.cxx @@ -17,17 +17,26 @@ /// /// \note based on taskD0.cxx, taskLc.cxx -#include - -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" - #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "Common/Core/RecoDecay.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + using namespace o2; using namespace o2::analysis; using namespace o2::framework; diff --git a/PWGHF/D2H/Tasks/taskOmegac0ToOmegapi.cxx b/PWGHF/D2H/Tasks/taskOmegac0ToOmegapi.cxx index 2550d41c386..4e9c3ccc412 100644 --- a/PWGHF/D2H/Tasks/taskOmegac0ToOmegapi.cxx +++ b/PWGHF/D2H/Tasks/taskOmegac0ToOmegapi.cxx @@ -14,19 +14,33 @@ /// \author Yunfan Liu , China University of Geosciences /// \author Fabio Catalano , University of Houston -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" - #include "PWGHF/Core/CentralityEstimation.h" #include "PWGHF/Core/HfHelper.h" -#include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" -#include "PWGHF/Utils/utilsEvSelHf.h" + +#include "Common/Core/RecoDecay.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include +#include +#include using namespace o2; using namespace o2::analysis; diff --git a/PWGHF/D2H/Tasks/taskSigmac.cxx b/PWGHF/D2H/Tasks/taskSigmac.cxx index 0a259ea6347..b60f1927ba5 100644 --- a/PWGHF/D2H/Tasks/taskSigmac.cxx +++ b/PWGHF/D2H/Tasks/taskSigmac.cxx @@ -15,15 +15,34 @@ /// /// \author Mattia Faggin , University and INFN PADOVA +#include "PWGHF/Core/DecayChannels.h" #include "PWGHF/Core/HfHelper.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" - +#include "Common/Core/RecoDecay.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include +#include +#include +#include #include using namespace o2; diff --git a/PWGHF/D2H/Tasks/taskSigmacToCascade.cxx b/PWGHF/D2H/Tasks/taskSigmacToCascade.cxx index dbdd51410ce..fc527254dac 100644 --- a/PWGHF/D2H/Tasks/taskSigmacToCascade.cxx +++ b/PWGHF/D2H/Tasks/taskSigmacToCascade.cxx @@ -15,21 +15,24 @@ /// \author Rutuparna Rath , INFN BOLOGNA and GSI Darmstadt /// In collaboration with Andrea Alici , INFN BOLOGNA -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" - -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectionDefaults.h" - #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + using namespace o2; using namespace o2::analysis; using namespace o2::framework; diff --git a/PWGHF/D2H/Tasks/taskXic.cxx b/PWGHF/D2H/Tasks/taskXic.cxx index ab5bf69738c..24d63b71650 100644 --- a/PWGHF/D2H/Tasks/taskXic.cxx +++ b/PWGHF/D2H/Tasks/taskXic.cxx @@ -19,17 +19,33 @@ /// \author Himanshu Sharma , University and INFN Padova /// \author Cristina Terrevoli , INFN Bari +#include "PWGHF/Core/DecayChannels.h" #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "Framework/runDataProcessing.h" - +#include "Common/Core/RecoDecay.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include #include using namespace o2; diff --git a/PWGHF/D2H/Tasks/taskXicToXiPiPi.cxx b/PWGHF/D2H/Tasks/taskXicToXiPiPi.cxx index 9c42b24c133..b52fc6ab780 100644 --- a/PWGHF/D2H/Tasks/taskXicToXiPiPi.cxx +++ b/PWGHF/D2H/Tasks/taskXicToXiPiPi.cxx @@ -21,12 +21,31 @@ #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "Framework/runDataProcessing.h" - +#include "Common/Core/RecoDecay.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; diff --git a/PWGHF/D2H/Tasks/taskXicc.cxx b/PWGHF/D2H/Tasks/taskXicc.cxx index 1e49bb8649b..90f4c5da24d 100644 --- a/PWGHF/D2H/Tasks/taskXicc.cxx +++ b/PWGHF/D2H/Tasks/taskXicc.cxx @@ -16,17 +16,26 @@ /// \author Gian Michele Innocenti , CERN /// \author Jinjoo Seo , Inha University -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" - #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "Common/Core/RecoDecay.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + using namespace o2; using namespace o2::analysis; using namespace o2::framework; @@ -38,7 +47,7 @@ void customize(std::vector& workflowOptions) workflowOptions.push_back(optionDoMC); } -#include "Framework/runDataProcessing.h" +#include /// Ξcc±± analysis task struct HfTaskXicc { diff --git a/PWGHF/D2H/Utils/utilsRedDataFormat.h b/PWGHF/D2H/Utils/utilsRedDataFormat.h index 513f2a998fc..0cd519074bc 100644 --- a/PWGHF/D2H/Utils/utilsRedDataFormat.h +++ b/PWGHF/D2H/Utils/utilsRedDataFormat.h @@ -19,9 +19,9 @@ #include "PWGHF/Core/CentralityEstimation.h" #include "PWGHF/Utils/utilsEvSelHf.h" -#include "CCDB/BasicCCDBManager.h" #include "Framework/AnalysisHelpers.h" -#include "Framework/HistogramRegistry.h" +#include +#include #include diff --git a/PWGHF/DataModel/CandidateReconstructionTables.h b/PWGHF/DataModel/CandidateReconstructionTables.h index dd6f2f53367..5df712115b9 100644 --- a/PWGHF/DataModel/CandidateReconstructionTables.h +++ b/PWGHF/DataModel/CandidateReconstructionTables.h @@ -18,12 +18,12 @@ #ifndef PWGHF_DATAMODEL_CANDIDATERECONSTRUCTIONTABLES_H_ #define PWGHF_DATAMODEL_CANDIDATERECONSTRUCTIONTABLES_H_ -#include "PWGHF/Core/DecayChannels.h" // FIXME: temporary until propagated where needed #include "PWGHF/Utils/utilsPid.h" #include "PWGLF/DataModel/LFStrangenessTables.h" #include "ALICE3/DataModel/ECAL.h" #include "Common/Core/RecoDecay.h" +#include "Common/DataModel/EventSelection.h" #include "Common/DataModel/PIDResponseTOF.h" #include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/TrackSelectionTables.h" @@ -638,10 +638,10 @@ DECLARE_SOA_DYNAMIC_COLUMN(MaxNormalisedDeltaIP, maxNormalisedDeltaIP, //! DECLARE_SOA_DYNAMIC_COLUMN(CtXY, ctXY, //! [](float px0, float py0, float pz0, float px1, float py1, float pz1, float xVtxP, float yVtxP, float xVtxS, float yVtxS, const std::array& m) -> float { return RecoDecay::ctXY(std::array{xVtxP, yVtxP}, std::array{xVtxS, yVtxS}, std::array{std::array{px0, py0, pz0}, std::array{px1, py1, pz1}}, m); }); // MC matching result: -DECLARE_SOA_COLUMN(FlagMcMatchRec, flagMcMatchRec, int8_t); //! reconstruction level -DECLARE_SOA_COLUMN(FlagMcMatchGen, flagMcMatchGen, int8_t); //! generator level -DECLARE_SOA_COLUMN(OriginMcRec, originMcRec, int8_t); //! particle origin, reconstruction level -DECLARE_SOA_COLUMN(OriginMcGen, originMcGen, int8_t); //! particle origin, generator level +DECLARE_SOA_COLUMN(FlagMcMatchRec, flagMcMatchRec, int8_t); //! reconstruction level +DECLARE_SOA_COLUMN(FlagMcMatchGen, flagMcMatchGen, int8_t); //! generator level +DECLARE_SOA_COLUMN(OriginMcRec, originMcRec, int8_t); //! particle origin, reconstruction level +DECLARE_SOA_COLUMN(OriginMcGen, originMcGen, int8_t); //! particle origin, generator level DECLARE_SOA_COLUMN(FlagMcDecayChanRec, flagMcDecayChanRec, int8_t); //! resonant decay channel flag, reconstruction level DECLARE_SOA_COLUMN(FlagMcDecayChanGen, flagMcDecayChanGen, int8_t); //! resonant decay channel flag, reconstruction level diff --git a/PWGHF/DataModel/DerivedTables.h b/PWGHF/DataModel/DerivedTables.h index 337abce14e0..61c85b9fd63 100644 --- a/PWGHF/DataModel/DerivedTables.h +++ b/PWGHF/DataModel/DerivedTables.h @@ -16,17 +16,18 @@ #ifndef PWGHF_DATAMODEL_DERIVEDTABLES_H_ #define PWGHF_DATAMODEL_DERIVEDTABLES_H_ -#include -#include - -#include -#include -#include +#include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "Common/Core/RecoDecay.h" #include "Common/DataModel/Centrality.h" -#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include +#include + +#include + +#include +#include namespace o2::aod { diff --git a/PWGHF/HFC/DataModel/CorrelationTables.h b/PWGHF/HFC/DataModel/CorrelationTables.h index eaf0b4f3c4a..a77035b7f3f 100644 --- a/PWGHF/HFC/DataModel/CorrelationTables.h +++ b/PWGHF/HFC/DataModel/CorrelationTables.h @@ -16,16 +16,16 @@ #ifndef PWGHF_HFC_DATAMODEL_CORRELATIONTABLES_H_ #define PWGHF_HFC_DATAMODEL_CORRELATIONTABLES_H_ +#include "PWGHF/DataModel/CandidateReconstructionTables.h" // IWYU pragma: keep + +#include "Common/Core/RecoDecay.h" + #include -#include // NOLINT #include +#include #include -#include "Common/Core/RecoDecay.h" - -#include "PWGHF/DataModel/CandidateReconstructionTables.h" // NOLINT - namespace o2::aod { // definition of columns and tables for D-Dbar correlation pairs diff --git a/PWGHF/HFC/Macros/DhCorrelationExtraction.cxx b/PWGHF/HFC/Macros/DhCorrelationExtraction.cxx index 446dcfbe4a0..c4faa289abb 100644 --- a/PWGHF/HFC/Macros/DhCorrelationExtraction.cxx +++ b/PWGHF/HFC/Macros/DhCorrelationExtraction.cxx @@ -16,6 +16,16 @@ #include "DhCorrelationExtraction.h" +#include +#include +#include +#include +#include +#include +#include + +#include + #include #include diff --git a/PWGHF/HFC/Macros/DhCorrelationFitter.cxx b/PWGHF/HFC/Macros/DhCorrelationFitter.cxx index 7e5157bb752..8882c567535 100644 --- a/PWGHF/HFC/Macros/DhCorrelationFitter.cxx +++ b/PWGHF/HFC/Macros/DhCorrelationFitter.cxx @@ -16,32 +16,26 @@ #include "DhCorrelationFitter.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 // IWYU pragma: keep (do not replace with TMatrixDfwd.h) +#include #include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include using namespace std; diff --git a/PWGHF/HFC/TableProducer/correlatorD0D0bar.cxx b/PWGHF/HFC/TableProducer/correlatorD0D0bar.cxx index cffe8b898c2..a59e95bd7e0 100644 --- a/PWGHF/HFC/TableProducer/correlatorD0D0bar.cxx +++ b/PWGHF/HFC/TableProducer/correlatorD0D0bar.cxx @@ -14,21 +14,31 @@ /// /// \author Fabio Colamaria , INFN Bari -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" - -#include "Common/Core/TrackSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" - #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" #include "PWGHF/HFC/DataModel/CorrelationTables.h" +#include "PWGHF/Utils/utilsAnalysis.h" + +#include "Common/Core/RecoDecay.h" + +#include "Framework/HistogramRegistry.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include using namespace o2; using namespace o2::analysis; diff --git a/PWGHF/HFC/TableProducer/correlatorD0D0barBarrelFullPid.cxx b/PWGHF/HFC/TableProducer/correlatorD0D0barBarrelFullPid.cxx index 9e090a49c57..c51912e5e40 100644 --- a/PWGHF/HFC/TableProducer/correlatorD0D0barBarrelFullPid.cxx +++ b/PWGHF/HFC/TableProducer/correlatorD0D0barBarrelFullPid.cxx @@ -14,21 +14,31 @@ /// /// \author Fabio Colamaria , INFN Bari -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" - -#include "Common/Core/TrackSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" - #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" #include "PWGHF/HFC/DataModel/CorrelationTables.h" +#include "PWGHF/Utils/utilsAnalysis.h" + +#include "Common/Core/RecoDecay.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include using namespace o2; using namespace o2::analysis; diff --git a/PWGHF/HFC/TableProducer/correlatorD0Hadrons.cxx b/PWGHF/HFC/TableProducer/correlatorD0Hadrons.cxx index f2a7afc6bdc..30df8b9a57e 100644 --- a/PWGHF/HFC/TableProducer/correlatorD0Hadrons.cxx +++ b/PWGHF/HFC/TableProducer/correlatorD0Hadrons.cxx @@ -15,25 +15,45 @@ /// \author Samrangy Sadhu , INFN Bari /// \author Swapnesh Santosh Khade , IIT Indore -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" - -#include "Common/Core/TrackSelection.h" -#include "Common/DataModel/Centrality.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/TrackSelectionTables.h" - #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" #include "PWGHF/HFC/DataModel/CorrelationTables.h" #include "PWGHF/HFC/Utils/utilsCorrelations.h" +#include "PWGHF/Utils/utilsAnalysis.h" + +#include "Common/CCDB/EventSelectionParams.h" +#include "Common/Core/RecoDecay.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Multiplicity.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::analysis; diff --git a/PWGHF/HFC/TableProducer/correlatorDMesonPairs.cxx b/PWGHF/HFC/TableProducer/correlatorDMesonPairs.cxx index 96aa7514a40..8885893e696 100644 --- a/PWGHF/HFC/TableProducer/correlatorDMesonPairs.cxx +++ b/PWGHF/HFC/TableProducer/correlatorDMesonPairs.cxx @@ -14,24 +14,38 @@ /// /// \author Andrea Tavira García , IJCLab Orsay -#include -#include - -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" - -#include "Common/Core/TrackSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" - #include "PWGHF/Core/HfHelper.h" -#include "PWGHF/Core/HfMlResponse.h" #include "PWGHF/Core/HfMlResponseD0ToKPi.h" #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" #include "PWGHF/HFC/DataModel/DMesonPairsTables.h" +#include "Common/Core/RecoDecay.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::analysis; using namespace o2::constants::physics; diff --git a/PWGHF/HFC/TableProducer/correlatorDplusDminus.cxx b/PWGHF/HFC/TableProducer/correlatorDplusDminus.cxx index 3cbee2b072a..e4c2e0fe6bb 100644 --- a/PWGHF/HFC/TableProducer/correlatorDplusDminus.cxx +++ b/PWGHF/HFC/TableProducer/correlatorDplusDminus.cxx @@ -14,21 +14,32 @@ /// /// \author Fabio Colamaria , INFN Bari -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" - -#include "Common/Core/TrackSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" - +#include "PWGHF/Core/DecayChannels.h" #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" #include "PWGHF/HFC/DataModel/CorrelationTables.h" +#include "PWGHF/Utils/utilsAnalysis.h" + +#include "Common/Core/RecoDecay.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include using namespace o2; using namespace o2::analysis; diff --git a/PWGHF/HFC/TableProducer/correlatorDplusHadrons.cxx b/PWGHF/HFC/TableProducer/correlatorDplusHadrons.cxx index a1a8941779b..c10865e21d2 100644 --- a/PWGHF/HFC/TableProducer/correlatorDplusHadrons.cxx +++ b/PWGHF/HFC/TableProducer/correlatorDplusHadrons.cxx @@ -13,24 +13,41 @@ /// \brief D+-Hadrons correlator task - data-like, MC-reco and MC-Gen analyses /// \author Shyam Kumar -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" - -#include "Common/Core/TrackSelection.h" -#include "Common/DataModel/Centrality.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/TrackSelectionTables.h" - +#include "PWGHF/Core/DecayChannels.h" #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" #include "PWGHF/HFC/DataModel/CorrelationTables.h" +#include "PWGHF/Utils/utilsAnalysis.h" + +#include "Common/CCDB/EventSelectionParams.h" +#include "Common/Core/RecoDecay.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Multiplicity.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::analysis; diff --git a/PWGHF/HFC/TableProducer/correlatorDsHadrons.cxx b/PWGHF/HFC/TableProducer/correlatorDsHadrons.cxx index 4a6c458b7e9..95bb9e07e1a 100644 --- a/PWGHF/HFC/TableProducer/correlatorDsHadrons.cxx +++ b/PWGHF/HFC/TableProducer/correlatorDsHadrons.cxx @@ -14,24 +14,41 @@ /// \author Grazia Luparello /// \author Samuele Cattaruzzi +#include "PWGHF/Core/DecayChannels.h" #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" #include "PWGHF/HFC/DataModel/CorrelationTables.h" #include "PWGHF/HFC/DataModel/DerivedDataCorrelationTables.h" +#include "PWGHF/Utils/utilsAnalysis.h" -#include "Common/Core/TrackSelection.h" -#include "Common/DataModel/Centrality.h" +#include "Common/CCDB/EventSelectionParams.h" +#include "Common/Core/RecoDecay.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.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 diff --git a/PWGHF/HFC/TableProducer/correlatorDsHadronsReduced.cxx b/PWGHF/HFC/TableProducer/correlatorDsHadronsReduced.cxx index d005659cc69..5684619dd3f 100644 --- a/PWGHF/HFC/TableProducer/correlatorDsHadronsReduced.cxx +++ b/PWGHF/HFC/TableProducer/correlatorDsHadronsReduced.cxx @@ -13,19 +13,30 @@ /// \brief Ds-Hadrons correlator task for offline analysis /// \author Samuele Cattaruzzi -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" - -#include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/HFC/DataModel/CorrelationTables.h" #include "PWGHF/HFC/DataModel/DerivedDataCorrelationTables.h" +#include "Common/Core/RecoDecay.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + using namespace o2; -using namespace o2::analysis; using namespace o2::constants::physics; using namespace o2::constants::math; using namespace o2::framework; diff --git a/PWGHF/HFC/TableProducer/correlatorDstarHadrons.cxx b/PWGHF/HFC/TableProducer/correlatorDstarHadrons.cxx index 849d15e9013..1a4cafe02ac 100644 --- a/PWGHF/HFC/TableProducer/correlatorDstarHadrons.cxx +++ b/PWGHF/HFC/TableProducer/correlatorDstarHadrons.cxx @@ -15,24 +15,36 @@ /// \brief Correlator for D* and hadrons. This task is used to produce table for D* and hadron pairs. -// c++ -#include - -// O2 -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - -// O2Physics -#include "Common/DataModel/Multiplicity.h" - -// PWGHF #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" #include "PWGHF/HFC/DataModel/CorrelationTables.h" #include "PWGHF/Utils/utilsAnalysis.h" +#include "Common/DataModel/Multiplicity.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 + using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; diff --git a/PWGHF/HFC/TableProducer/correlatorHfeHadrons.cxx b/PWGHF/HFC/TableProducer/correlatorHfeHadrons.cxx index 277111d8817..d88daf5c4a3 100644 --- a/PWGHF/HFC/TableProducer/correlatorHfeHadrons.cxx +++ b/PWGHF/HFC/TableProducer/correlatorHfeHadrons.cxx @@ -14,37 +14,45 @@ /// \author Rashi Gupta , IIT Indore /// \author Ravindra Singh , IIT Indore -#include - -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" +#include "PWGHF/HFC/DataModel/CorrelationTables.h" +#include "PWGHF/HFL/DataModel/ElectronSelectionTable.h" -#include "Common/Core/PID/TPCPIDResponse.h" +#include "Common/CCDB/TriggerAliases.h" #include "Common/Core/RecoDecay.h" -#include "Common/Core/TrackSelection.h" -#include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/PIDResponse.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "PWGHF/HFC/DataModel/CorrelationTables.h" -#include "PWGHF/HFL/DataModel/ElectronSelectionTable.h" +#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::soa; using namespace o2::aod::hf_sel_electron; + std::vector zBins{VARIABLE_WIDTH, -10.0, -2.5, 2.5, 10.0}; std::vector multBins{VARIABLE_WIDTH, 0., 200., 500.0, 5000.}; std::vector multBinsMcGen{VARIABLE_WIDTH, 0., 20., 50.0, 500.}; // In MCGen multiplicity is defined by counting primaries using BinningType = ColumnBinningPolicy>; BinningType corrBinning{{zBins, multBins}, true}; using BinningTypeMcGen = ColumnBinningPolicy; -struct HfCorrelatorHfeHadrons { +struct HfCorrelatorHfeHadrons { Produces entryElectronHadronPair; Produces entryElectronHadronPairmcGen; Produces entryElectron; diff --git a/PWGHF/HFC/TableProducer/correlatorLcHadrons.cxx b/PWGHF/HFC/TableProducer/correlatorLcHadrons.cxx index 7dc6d877a8b..22770502878 100644 --- a/PWGHF/HFC/TableProducer/correlatorLcHadrons.cxx +++ b/PWGHF/HFC/TableProducer/correlatorLcHadrons.cxx @@ -16,27 +16,47 @@ /// \author Zhen Zhang /// \author Ravindra Singh -#include -#include "TRandom3.h" - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "Framework/runDataProcessing.h" - -#include "Common/Core/TrackSelection.h" -#include "Common/DataModel/Centrality.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/TrackSelectionTables.h" - +#include "PWGHF/Core/DecayChannels.h" #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" #include "PWGHF/HFC/DataModel/CorrelationTables.h" #include "PWGHF/HFC/Utils/utilsCorrelations.h" +#include "PWGHF/Utils/utilsAnalysis.h" + +#include "Common/CCDB/EventSelectionParams.h" +#include "Common/Core/RecoDecay.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" + +#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::analysis; @@ -45,6 +65,7 @@ using namespace o2::constants::math; using namespace o2::framework; using namespace o2::framework::expressions; using namespace o2::analysis::hf_correlations; + /// /// Returns deltaPhi values in range [-pi/2., 3.*pi/2.], typically used for correlation studies /// diff --git a/PWGHF/HFC/TableProducer/correlatorLcScHadrons.cxx b/PWGHF/HFC/TableProducer/correlatorLcScHadrons.cxx index 21d3b4b6458..db357dcc51a 100644 --- a/PWGHF/HFC/TableProducer/correlatorLcScHadrons.cxx +++ b/PWGHF/HFC/TableProducer/correlatorLcScHadrons.cxx @@ -16,28 +16,50 @@ /// \author Zhen Zhang /// \author Ravindra Singh -#include -#include "TRandom3.h" - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "Framework/runDataProcessing.h" - -#include "Common/Core/TrackSelection.h" -#include "Common/DataModel/Centrality.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "CommonConstants/MathConstants.h" - #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" #include "PWGHF/HFC/DataModel/CorrelationTables.h" #include "PWGHF/HFC/Utils/utilsCorrelations.h" +#include "PWGHF/Utils/utilsAnalysis.h" + +#include "Common/CCDB/EventSelectionParams.h" +#include "Common/Core/RecoDecay.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" + +#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::analysis; diff --git a/PWGHF/HFC/TableProducer/femtoDreamProducer.cxx b/PWGHF/HFC/TableProducer/femtoDreamProducer.cxx index ee8ec8aaa26..a605bc74f6c 100644 --- a/PWGHF/HFC/TableProducer/femtoDreamProducer.cxx +++ b/PWGHF/HFC/TableProducer/femtoDreamProducer.cxx @@ -14,39 +14,53 @@ /// \author Ravindra Singh, GSI, ravindra.singh@cern.ch /// \author Biao Zhang, Heidelberg University, biao.zhang@cern.ch -#include -#include - -#include "TMCProcess.h" - -#include "CCDB/BasicCCDBManager.h" - -#include "Common/Core/trackUtilities.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/Centrality.h" - -#include "DataFormatsParameters/GRPMagField.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DetectorsBase/Propagator.h" - -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" - -#include "PWGCF/FemtoDream/Core/femtoDreamCollisionSelection.h" +#include "PWGCF/DataModel/FemtoDerived.h" +#include "PWGCF/FemtoDream/Core/femtoDreamSelection.h" #include "PWGCF/FemtoDream/Core/femtoDreamTrackSelection.h" #include "PWGCF/FemtoDream/Core/femtoDreamUtils.h" - +#include "PWGHF/Core/CentralityEstimation.h" +#include "PWGHF/Core/DecayChannels.h" #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/HfMlResponseLcToPKPi.h" +#include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" #include "PWGHF/Utils/utilsBfieldCCDB.h" #include "PWGHF/Utils/utilsEvSelHf.h" -#include "PWGHF/Core/CentralityEstimation.h" -#include "PWGHF/Core/SelectorCuts.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/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 using namespace o2; using namespace o2::framework; diff --git a/PWGHF/HFC/Tasks/taskCharmHadronsFemtoDream.cxx b/PWGHF/HFC/Tasks/taskCharmHadronsFemtoDream.cxx index b8a0005e6ac..c386b3932e0 100644 --- a/PWGHF/HFC/Tasks/taskCharmHadronsFemtoDream.cxx +++ b/PWGHF/HFC/Tasks/taskCharmHadronsFemtoDream.cxx @@ -14,25 +14,36 @@ /// \author Ravindra SIngh, GSI, ravindra.singh@cern.ch /// \author Biao Zhang, Heidelberg University, biao.zhang@cern.ch -#include -#include - -#include "Framework/Expressions.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/RunningWorkflowInfo.h" -#include "Framework/StepTHn.h" - #include "PWGCF/DataModel/FemtoDerived.h" -#include "PWGCF/FemtoDream/Core/femtoDreamParticleHisto.h" -#include "PWGCF/FemtoDream/Core/femtoDreamEventHisto.h" -#include "PWGCF/FemtoDream/Core/femtoDreamPairCleaner.h" #include "PWGCF/FemtoDream/Core/femtoDreamContainer.h" #include "PWGCF/FemtoDream/Core/femtoDreamDetaDphiStar.h" +#include "PWGCF/FemtoDream/Core/femtoDreamEventHisto.h" +#include "PWGCF/FemtoDream/Core/femtoDreamMath.h" +#include "PWGCF/FemtoDream/Core/femtoDreamPairCleaner.h" +#include "PWGCF/FemtoDream/Core/femtoDreamParticleHisto.h" #include "PWGCF/FemtoDream/Core/femtoDreamUtils.h" +#include "Framework/Expressions.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + using namespace o2; using namespace o2::aod; using namespace o2::soa; diff --git a/PWGHF/HFC/Tasks/taskCorrelationD0Hadrons.cxx b/PWGHF/HFC/Tasks/taskCorrelationD0Hadrons.cxx index 93c0fecd90d..94a4ab37270 100644 --- a/PWGHF/HFC/Tasks/taskCorrelationD0Hadrons.cxx +++ b/PWGHF/HFC/Tasks/taskCorrelationD0Hadrons.cxx @@ -16,19 +16,39 @@ /// \author Samrangy Sadhu , INFN Bari /// \author Swapnesh Santosh Khade , IIT Indore -#include - -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" - #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" -#include "PWGHF/Utils/utilsAnalysis.h" #include "PWGHF/HFC/DataModel/CorrelationTables.h" #include "PWGHF/HFC/Utils/utilsCorrelations.h" +#include "PWGHF/Utils/utilsAnalysis.h" + +#include "Common/CCDB/EventSelectionParams.h" +#include "Common/Core/RecoDecay.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include using namespace o2; using namespace o2::constants::physics; diff --git a/PWGHF/HFC/Tasks/taskCorrelationDDbar.cxx b/PWGHF/HFC/Tasks/taskCorrelationDDbar.cxx index f7b50def0a4..21321f51f21 100644 --- a/PWGHF/HFC/Tasks/taskCorrelationDDbar.cxx +++ b/PWGHF/HFC/Tasks/taskCorrelationDDbar.cxx @@ -14,17 +14,26 @@ /// /// \author Fabio Colamaria , INFN Bari -#include - -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" - #include "PWGHF/Core/SelectorCuts.h" -#include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" -#include "PWGHF/Utils/utilsAnalysis.h" #include "PWGHF/HFC/DataModel/CorrelationTables.h" +#include "PWGHF/Utils/utilsAnalysis.h" + +#include "Common/Core/RecoDecay.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include using namespace o2; using namespace o2::framework; diff --git a/PWGHF/HFC/Tasks/taskCorrelationDMesonPairs.cxx b/PWGHF/HFC/Tasks/taskCorrelationDMesonPairs.cxx index 41a1f77836f..31082ef795a 100644 --- a/PWGHF/HFC/Tasks/taskCorrelationDMesonPairs.cxx +++ b/PWGHF/HFC/Tasks/taskCorrelationDMesonPairs.cxx @@ -14,15 +14,21 @@ /// /// \author Andrea Tavira García , IJCLab Orsay -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" - -#include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" -#include "PWGHF/Utils/utilsAnalysis.h" #include "PWGHF/HFC/DataModel/DMesonPairsTables.h" +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include + using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; diff --git a/PWGHF/HFC/Tasks/taskCorrelationDplusHadrons.cxx b/PWGHF/HFC/Tasks/taskCorrelationDplusHadrons.cxx index 834bf4d217c..ebdbab469df 100644 --- a/PWGHF/HFC/Tasks/taskCorrelationDplusHadrons.cxx +++ b/PWGHF/HFC/Tasks/taskCorrelationDplusHadrons.cxx @@ -13,21 +13,48 @@ /// \brief D+-Hadrons azimuthal correlations analysis task - data-like, MC-reco and MC-Gen analyses /// \author Shyam Kumar -#include // std::shared_ptr -#include -#include - -#include "CCDB/BasicCCDBManager.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" - +#include "PWGHF/Core/DecayChannels.h" #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" -#include "PWGHF/Utils/utilsAnalysis.h" #include "PWGHF/HFC/DataModel/CorrelationTables.h" +#include "PWGHF/Utils/utilsAnalysis.h" + +#include "Common/CCDB/EventSelectionParams.h" +#include "Common/Core/RecoDecay.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Multiplicity.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 // std::shared_ptr +#include +#include using namespace o2; using namespace o2::constants::math; diff --git a/PWGHF/HFC/Tasks/taskCorrelationDsHadrons.cxx b/PWGHF/HFC/Tasks/taskCorrelationDsHadrons.cxx index 9b2b888249c..999c5b0016c 100644 --- a/PWGHF/HFC/Tasks/taskCorrelationDsHadrons.cxx +++ b/PWGHF/HFC/Tasks/taskCorrelationDsHadrons.cxx @@ -14,6 +14,7 @@ /// \author Grazia Luparello /// \author Samuele Cattaruzzi +#include "PWGHF/Core/DecayChannels.h" #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" @@ -21,11 +22,35 @@ #include "PWGHF/HFC/DataModel/CorrelationTables.h" #include "PWGHF/Utils/utilsAnalysis.h" -#include "CCDB/BasicCCDBManager.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" - +#include "Common/CCDB/EventSelectionParams.h" +#include "Common/Core/RecoDecay.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Multiplicity.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 diff --git a/PWGHF/HFC/Tasks/taskCorrelationDstarHadrons.cxx b/PWGHF/HFC/Tasks/taskCorrelationDstarHadrons.cxx index 1e002d9118d..eb450cc7e61 100644 --- a/PWGHF/HFC/Tasks/taskCorrelationDstarHadrons.cxx +++ b/PWGHF/HFC/Tasks/taskCorrelationDstarHadrons.cxx @@ -14,18 +14,23 @@ /// \author Fabrizio Grosa , CERN /// \author Shyam Kumar -#include - -// Framework -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" - -// PWGHF #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/HFC/DataModel/CorrelationTables.h" #include "PWGHF/Utils/utilsAnalysis.h" +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; diff --git a/PWGHF/HFC/Tasks/taskCorrelationHfeHadrons.cxx b/PWGHF/HFC/Tasks/taskCorrelationHfeHadrons.cxx index 94786e27372..00202c55122 100644 --- a/PWGHF/HFC/Tasks/taskCorrelationHfeHadrons.cxx +++ b/PWGHF/HFC/Tasks/taskCorrelationHfeHadrons.cxx @@ -14,13 +14,16 @@ /// \author Rashi Gupta , IIT Indore /// \author Ravindra Singh , IIT Indore -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" - -#include "Common/Core/RecoDecay.h" #include "PWGHF/HFC/DataModel/CorrelationTables.h" +#include +#include +#include +#include +#include +#include +#include + using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; diff --git a/PWGHF/HFC/Tasks/taskCorrelationLcHadrons.cxx b/PWGHF/HFC/Tasks/taskCorrelationLcHadrons.cxx index 791dd045f99..84386ab9794 100644 --- a/PWGHF/HFC/Tasks/taskCorrelationLcHadrons.cxx +++ b/PWGHF/HFC/Tasks/taskCorrelationLcHadrons.cxx @@ -14,22 +14,49 @@ /// \author Marianna Mazzilli /// \author Zhen Zhang -#include // std::shared_ptr -#include -#include - -#include "CCDB/BasicCCDBManager.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" - +#include "PWGHF/Core/DecayChannels.h" #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" -#include "PWGHF/Utils/utilsAnalysis.h" #include "PWGHF/HFC/DataModel/CorrelationTables.h" #include "PWGHF/HFC/Utils/utilsCorrelations.h" +#include "PWGHF/Utils/utilsAnalysis.h" + +#include "Common/CCDB/EventSelectionParams.h" +#include "Common/Core/RecoDecay.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Multiplicity.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 // std::shared_ptr +#include +#include using namespace o2; using namespace o2::constants::math; diff --git a/PWGHF/HFC/Tasks/taskFlow.cxx b/PWGHF/HFC/Tasks/taskFlow.cxx index 981ce78e7ca..2e4ed8d210b 100644 --- a/PWGHF/HFC/Tasks/taskFlow.cxx +++ b/PWGHF/HFC/Tasks/taskFlow.cxx @@ -15,42 +15,46 @@ /// \author Katarina Krizkova Gajdosova , CERN /// \author Maja Kabus , CERN -#include -#include - -#include -#include -#include +#include "PWGCF/Core/CorrelationContainer.h" +#include "PWGHF/Core/DecayChannels.h" +#include "PWGHF/Core/HfHelper.h" +#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "PWGHF/Utils/utilsPid.h" +#include "PWGMM/Mult/DataModel/bestCollisionTable.h" -#include "CCDB/BasicCCDBManager.h" -#include "DataFormatsParameters/GRPObject.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/Logger.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "Framework/runDataProcessing.h" -#include "Framework/RunningWorkflowInfo.h" -#include "Framework/StepTHn.h" -#include "ReconstructionDataFormats/GlobalTrackID.h" - -#include "Common/DataModel/CollisionAssociationTables.h" +#include "Common/Core/RecoDecay.h" #include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/McCollisionExtra.h" #include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "CommonConstants/MathConstants.h" -#include "PWGMM/Mult/DataModel/Index.h" -#include "PWGMM/Mult/DataModel/bestCollisionTable.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include -#include "PWGCF/Core/CorrelationContainer.h" -#include "PWGCF/Core/PairCuts.h" +#include +#include +#include -#include "PWGHF/Core/HfHelper.h" -#include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" -#include "PWGHF/Utils/utilsPid.h" +#include +#include +#include +#include using namespace o2; using namespace o2::analysis; diff --git a/PWGHF/HFC/Utils/utilsCorrelations.h b/PWGHF/HFC/Utils/utilsCorrelations.h index b830eedcfef..56fc5e435e2 100644 --- a/PWGHF/HFC/Utils/utilsCorrelations.h +++ b/PWGHF/HFC/Utils/utilsCorrelations.h @@ -16,18 +16,23 @@ #ifndef PWGHF_HFC_UTILS_UTILSCORRELATIONS_H_ #define PWGHF_HFC_UTILS_UTILSCORRELATIONS_H_ +#include "PWGHF/Core/DecayChannels.h" +#include "PWGHF/DataModel/CandidateReconstructionTables.h" + +#include "Common/DataModel/PIDResponseTOF.h" +#include "Common/DataModel/PIDResponseTPC.h" + +#include +#include +#include + #include -#include +#include #include #include -#include "CommonConstants/MathConstants.h" - -#include "Common/DataModel/PIDResponseTPC.h" -#include "Common/DataModel/PIDResponseTOF.h" - namespace o2::analysis::hf_correlations { enum Region { diff --git a/PWGHF/HFL/DataModel/ElectronSelectionTable.h b/PWGHF/HFL/DataModel/ElectronSelectionTable.h index 477011950e2..cae859d08f1 100644 --- a/PWGHF/HFL/DataModel/ElectronSelectionTable.h +++ b/PWGHF/HFL/DataModel/ElectronSelectionTable.h @@ -18,8 +18,8 @@ #ifndef PWGHF_HFL_DATAMODEL_ELECTRONSELECTIONTABLE_H_ #define PWGHF_HFL_DATAMODEL_ELECTRONSELECTIONTABLE_H_ -#include // NOLINT #include +#include #include diff --git a/PWGHF/HFL/TableProducer/electronSelectionWithTpcEmcal.cxx b/PWGHF/HFL/TableProducer/electronSelectionWithTpcEmcal.cxx index 24ebae0ea8a..5d2d3d9e0c0 100644 --- a/PWGHF/HFL/TableProducer/electronSelectionWithTpcEmcal.cxx +++ b/PWGHF/HFL/TableProducer/electronSelectionWithTpcEmcal.cxx @@ -14,28 +14,38 @@ /// \author Rashi Gupta , IIT Indore /// \author Ravindra Singh , IIT Indore -#include "THnSparse.h" -#include "TPDGCode.h" - -#include "DataFormatsEMCAL/AnalysisCluster.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" - -#include "Common/Core/PID/TPCPIDResponse.h" -#include "Common/Core/trackUtilities.h" -#include "Common/Core/TrackSelection.h" -#include "Common/DataModel/Centrality.h" +#include "PWGHF/HFL/DataModel/ElectronSelectionTable.h" +#include "PWGJE/DataModel/EMCALClusters.h" + +#include "Common/CCDB/TriggerAliases.h" +#include "Common/Core/RecoDecay.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/PIDResponseTOF.h" +#include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/TrackSelectionTables.h" - #include "Tools/KFparticle/KFUtilities.h" -#include "PWGJE/DataModel/EMCALClusters.h" - -#include "PWGHF/HFL/DataModel/ElectronSelectionTable.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include +#include +#include using namespace o2; using namespace o2::constants::physics; diff --git a/PWGHF/HFL/TableProducer/treeCreatorElectronDCA.cxx b/PWGHF/HFL/TableProducer/treeCreatorElectronDCA.cxx index b8faca73bf7..1b32608a310 100644 --- a/PWGHF/HFL/TableProducer/treeCreatorElectronDCA.cxx +++ b/PWGHF/HFL/TableProducer/treeCreatorElectronDCA.cxx @@ -14,18 +14,27 @@ /// /// \author Martin Voelkl , University of Birmingham -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "Framework/runDataProcessing.h" - -#include "Common/DataModel/Centrality.h" - #include "PWGHF/Core/HfHelper.h" -#include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" + +#include "Common/Core/RecoDecay.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include using namespace o2; using namespace o2::aod; diff --git a/PWGHF/HFL/Tasks/taskElectronWeakBoson.cxx b/PWGHF/HFL/Tasks/taskElectronWeakBoson.cxx index f740814eedb..4539149c69d 100644 --- a/PWGHF/HFL/Tasks/taskElectronWeakBoson.cxx +++ b/PWGHF/HFL/Tasks/taskElectronWeakBoson.cxx @@ -12,44 +12,47 @@ /// \file taskElectronWeakBoson.cxx /// \brief task for WeakBoson (W/Z) based on electron in mid-rapidity /// \author S. Sakai & S. Ito (Univ. of Tsukuba) + #ifndef HomogeneousField #define HomogeneousField // o2-linter: disable=name/macro (required by KFParticle) #endif -#include "PWGHF/Core/HfHelper.h" #include "PWGJE/DataModel/EMCALClusters.h" #include "Common/Core/RecoDecay.h" -#include "Common/Core/TrackSelection.h" -#include "Common/Core/trackUtilities.h" #include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/TrackSelectionTables.h" #include "EventFiltering/Zorro.h" +#include "EventFiltering/ZorroSummary.h" #include "Tools/KFparticle/KFUtilities.h" -#include "CCDB/BasicCCDBManager.h" -#include "DataFormatsEMCAL/AnalysisCluster.h" -#include "DataFormatsEMCAL/Cell.h" -#include "DataFormatsEMCAL/Constants.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DetectorsBase/GeometryManager.h" -#include "DetectorsBase/Propagator.h" -#include "EMCALBase/Geometry.h" -#include "EMCALCalib/BadChannelMap.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - -#include "TPDGCode.h" - -#include "KFPTrack.h" -#include "KFPVertex.h" -#include "KFParticle.h" -#include "KFParticleBase.h" -#include "KFVertex.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 diff --git a/PWGHF/HFL/Tasks/taskMuonCharmBeautySeparation.cxx b/PWGHF/HFL/Tasks/taskMuonCharmBeautySeparation.cxx index cc2637cedc3..5fca08870fa 100644 --- a/PWGHF/HFL/Tasks/taskMuonCharmBeautySeparation.cxx +++ b/PWGHF/HFL/Tasks/taskMuonCharmBeautySeparation.cxx @@ -14,13 +14,18 @@ /// \brief Task to estimate HF->mu in the forward direction and use DCA observable to separate b-> mu, c-> mu. /// \author Shreyasi Acharya , LPC, France -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/TrackFwd.h" - #include "Common/DataModel/TrackSelectionTables.h" +#include +#include +#include +#include +#include +#include +#include + +#include + using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; diff --git a/PWGHF/HFL/Tasks/taskSingleMuon.cxx b/PWGHF/HFL/Tasks/taskSingleMuon.cxx index 73445124ae9..9b38f3f45a6 100644 --- a/PWGHF/HFL/Tasks/taskSingleMuon.cxx +++ b/PWGHF/HFL/Tasks/taskSingleMuon.cxx @@ -13,17 +13,23 @@ /// \brief Task used to extract the observables on single muons needed for the HF-muon analysis. /// \author Maolin Zhang , CCNU -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/TrackFwd.h" - #include "Common/Core/RecoDecay.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/TrackSelectionTables.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + using namespace o2; using namespace o2::aod; using namespace o2::framework; diff --git a/PWGHF/HFL/Tasks/taskSingleMuonMult.cxx b/PWGHF/HFL/Tasks/taskSingleMuonMult.cxx index 48cc13b74c4..b51635dda6b 100644 --- a/PWGHF/HFL/Tasks/taskSingleMuonMult.cxx +++ b/PWGHF/HFL/Tasks/taskSingleMuonMult.cxx @@ -13,22 +13,28 @@ /// \brief Task used to study the Open heavy flavour decay muon production as a function of multiplicity. /// \author Md Samsul Islam , IITB -#include - -#include "CommonConstants/MathConstants.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/TrackFwd.h" - -#include "Common/Core/TrackSelection.h" -#include "Common/Core/trackUtilities.h" +#include "Common/Core/RecoDecay.h" #include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/TrackSelectionTables.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + using namespace o2; using namespace o2::aod; using namespace o2::framework; diff --git a/PWGHF/HFL/Tasks/taskSingleMuonReader.cxx b/PWGHF/HFL/Tasks/taskSingleMuonReader.cxx index 7d04bead362..52cb12b6f41 100644 --- a/PWGHF/HFL/Tasks/taskSingleMuonReader.cxx +++ b/PWGHF/HFL/Tasks/taskSingleMuonReader.cxx @@ -12,17 +12,20 @@ /// \file taskSingleMuonReader.cxx /// \brief Task used to read the derived table produced by the tableMaker of DQ framework and extract observables on single muons needed for the HF-muon analysis. /// \author Maolin Zhang , CCNU -#include -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/TrackFwd.h" + #include "PWGDQ/DataModel/ReducedInfoTables.h" + #include "Common/Core/RecoDecay.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include using namespace o2; using namespace o2::aod; diff --git a/PWGHF/HFL/Tasks/taskSingleMuonReaderAssoc.cxx b/PWGHF/HFL/Tasks/taskSingleMuonReaderAssoc.cxx index 03fa6efb5a5..2b43e9ab14f 100644 --- a/PWGHF/HFL/Tasks/taskSingleMuonReaderAssoc.cxx +++ b/PWGHF/HFL/Tasks/taskSingleMuonReaderAssoc.cxx @@ -13,18 +13,18 @@ /// \brief Task used to read the derived table produced by the tableMaker-association of DQ framework and extract observables on single muons needed for the HF-muon analysis. /// \author Maolin Zhang , CCNU -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/TrackFwd.h" +#include "PWGDQ/DataModel/ReducedInfoTables.h" #include "Common/Core/RecoDecay.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "PWGDQ/DataModel/ReducedInfoTables.h" +#include +#include +#include +#include +#include +#include +#include +#include using namespace o2; using namespace o2::aod; diff --git a/PWGHF/HFL/Tasks/taskSingleMuonSource.cxx b/PWGHF/HFL/Tasks/taskSingleMuonSource.cxx index d60a04f80d0..58f6654ee68 100644 --- a/PWGHF/HFL/Tasks/taskSingleMuonSource.cxx +++ b/PWGHF/HFL/Tasks/taskSingleMuonSource.cxx @@ -13,20 +13,30 @@ // \brief Task used to seperate single muons source in Monte Carlo simulation. // \author Maolin Zhang , CCNU +#include "Common/Core/RecoDecay.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + #include #include #include -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/TrackFwd.h" +#include -#include "Common/Core/RecoDecay.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" +#include +#include +#include using namespace o2; using namespace o2::aod; diff --git a/PWGHF/Macros/computeFonllPlusPythiaPredictions.C b/PWGHF/Macros/computeFonllPlusPythiaPredictions.C index bdd8f1ca7e2..c112f7f5d24 100644 --- a/PWGHF/Macros/computeFonllPlusPythiaPredictions.C +++ b/PWGHF/Macros/computeFonllPlusPythiaPredictions.C @@ -16,27 +16,27 @@ #if !defined(__CINT__) || defined(__CLING__) -#include -#include -#include -#include -#include +#include +#include -#include -#include -#include #include -#include -#include +#include #include +#include +#include +#include +#include +#include -#include "Math/Vector3D.h" -#include "Math/Vector4D.h" - -#include "CommonConstants/MathConstants.h" -#include "Framework/Logger.h" +#include -#include "Pythia8/Pythia.h" +#include +#include +#include +#include +#include +#include +#include #endif diff --git a/PWGHF/TableProducer/candidateCreator2Prong.cxx b/PWGHF/TableProducer/candidateCreator2Prong.cxx index afaffc09700..895b8804cb9 100644 --- a/PWGHF/TableProducer/candidateCreator2Prong.cxx +++ b/PWGHF/TableProducer/candidateCreator2Prong.cxx @@ -21,8 +21,6 @@ #endif #include "PWGHF/Core/CentralityEstimation.h" -#include "PWGHF/Core/DecayChannels.h" -#include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/Utils/utilsBfieldCCDB.h" #include "PWGHF/Utils/utilsEvSelHf.h" @@ -32,26 +30,45 @@ #include "PWGHF/Utils/utilsTrkCandHf.h" #include "PWGLF/DataModel/mcCentrality.h" +#include "Common/Core/RecoDecay.h" #include "Common/Core/trackUtilities.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" #include "Tools/KFparticle/KFUtilities.h" -#include "CommonConstants/PhysicsConstants.h" -#include "DCAFitter/DCAFitterN.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/RunningWorkflowInfo.h" -#include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/DCA.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 diff --git a/PWGHF/TableProducer/candidateCreator3Prong.cxx b/PWGHF/TableProducer/candidateCreator3Prong.cxx index 40ab5709951..38c9bc0a30f 100644 --- a/PWGHF/TableProducer/candidateCreator3Prong.cxx +++ b/PWGHF/TableProducer/candidateCreator3Prong.cxx @@ -30,26 +30,46 @@ #include "PWGHF/Utils/utilsTrkCandHf.h" #include "PWGLF/DataModel/mcCentrality.h" +#include "Common/Core/RecoDecay.h" #include "Common/Core/trackUtilities.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" #include "Tools/KFparticle/KFUtilities.h" -#include "CommonConstants/PhysicsConstants.h" -#include "DCAFitter/DCAFitterN.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/RunningWorkflowInfo.h" -#include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/DCA.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 diff --git a/PWGHF/TableProducer/candidateCreatorB0.cxx b/PWGHF/TableProducer/candidateCreatorB0.cxx index b60e5e63a72..55ca18c67a3 100644 --- a/PWGHF/TableProducer/candidateCreatorB0.cxx +++ b/PWGHF/TableProducer/candidateCreatorB0.cxx @@ -15,20 +15,6 @@ /// /// \author Alexandre Bigot , IPHC Strasbourg -#include -#include -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "DCAFitter/DCAFitterN.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/DCA.h" -#include "ReconstructionDataFormats/V0.h" - -#include "Common/Core/trackUtilities.h" -#include "Common/DataModel/CollisionAssociationTables.h" - #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" @@ -37,6 +23,43 @@ #include "PWGHF/Utils/utilsMcGen.h" #include "PWGHF/Utils/utilsTrkCandHf.h" +#include "Common/Core/RecoDecay.h" +#include "Common/Core/trackUtilities.h" +#include "Common/DataModel/CollisionAssociationTables.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 + using namespace o2; using namespace o2::analysis; using namespace o2::aod; diff --git a/PWGHF/TableProducer/candidateCreatorBplus.cxx b/PWGHF/TableProducer/candidateCreatorBplus.cxx index fea1a2778b4..d04170c9a9a 100644 --- a/PWGHF/TableProducer/candidateCreatorBplus.cxx +++ b/PWGHF/TableProducer/candidateCreatorBplus.cxx @@ -18,20 +18,6 @@ /// \author Deepa Thomas , UT Austin /// \author Antonio Palasciano , Università degli Studi di Bari & INFN, Sezione di Bari -#include -#include -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "DCAFitter/DCAFitterN.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/DCA.h" -#include "ReconstructionDataFormats/V0.h" - -#include "Common/Core/trackUtilities.h" -#include "Common/DataModel/CollisionAssociationTables.h" - #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" @@ -40,6 +26,43 @@ #include "PWGHF/Utils/utilsMcGen.h" #include "PWGHF/Utils/utilsTrkCandHf.h" +#include "Common/Core/RecoDecay.h" +#include "Common/Core/trackUtilities.h" +#include "Common/DataModel/CollisionAssociationTables.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 + using namespace o2; using namespace o2::analysis; using namespace o2::hf_trkcandsel; diff --git a/PWGHF/TableProducer/candidateCreatorBs.cxx b/PWGHF/TableProducer/candidateCreatorBs.cxx index 4f8128e474b..6f1962e3ca3 100644 --- a/PWGHF/TableProducer/candidateCreatorBs.cxx +++ b/PWGHF/TableProducer/candidateCreatorBs.cxx @@ -15,20 +15,6 @@ /// /// \author Phil Stahlhut -#include -#include -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "DCAFitter/DCAFitterN.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/DCA.h" -#include "ReconstructionDataFormats/V0.h" - -#include "Common/Core/trackUtilities.h" -#include "Common/DataModel/CollisionAssociationTables.h" - #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" @@ -36,6 +22,43 @@ #include "PWGHF/Utils/utilsBfieldCCDB.h" #include "PWGHF/Utils/utilsTrkCandHf.h" +#include "Common/Core/RecoDecay.h" +#include "Common/Core/trackUtilities.h" +#include "Common/DataModel/CollisionAssociationTables.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 + using namespace o2; using namespace o2::analysis; using namespace o2::aod; diff --git a/PWGHF/TableProducer/candidateCreatorCascade.cxx b/PWGHF/TableProducer/candidateCreatorCascade.cxx index 04faa873da7..a7eb6ccc794 100644 --- a/PWGHF/TableProducer/candidateCreatorCascade.cxx +++ b/PWGHF/TableProducer/candidateCreatorCascade.cxx @@ -15,35 +15,50 @@ /// \author Chiara Zampolli, , CERN /// Paul Buehler, , Vienna -#include -#include -#include - -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "DCAFitter/DCAFitterN.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" -#include "Framework/RunningWorkflowInfo.h" -#include "ReconstructionDataFormats/DCA.h" -#include "ReconstructionDataFormats/V0.h" -#include "PWGLF/DataModel/LFStrangenessTables.h" - -#include "Common/Core/trackUtilities.h" - -#include "PWGLF/DataModel/mcCentrality.h" - #include "PWGHF/Core/CentralityEstimation.h" -#include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/Utils/utilsBfieldCCDB.h" #include "PWGHF/Utils/utilsEvSelHf.h" #include "PWGHF/Utils/utilsTrkCandHf.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" +#include "PWGLF/DataModel/mcCentrality.h" + +#include "Common/Core/RecoDecay.h" +#include "Common/Core/trackUtilities.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.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 using namespace o2; -using namespace o2::analysis; using namespace o2::hf_evsel; using namespace o2::hf_trkcandsel; using namespace o2::hf_centrality; diff --git a/PWGHF/TableProducer/candidateCreatorDstar.cxx b/PWGHF/TableProducer/candidateCreatorDstar.cxx index f25a09dbbb3..a6795dc8274 100644 --- a/PWGHF/TableProducer/candidateCreatorDstar.cxx +++ b/PWGHF/TableProducer/candidateCreatorDstar.cxx @@ -16,31 +16,49 @@ /// \author Deependra Sharma , IITB /// \author Fabrizio Grosa , CERN -// C++ -#include -#include -#include -// ROOT -#include -// O2 -#include "CommonConstants/PhysicsConstants.h" -#include "DCAFitter/DCAFitterN.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" -#include "Framework/RunningWorkflowInfo.h" -// O2Physics -#include "Common/Core/trackUtilities.h" -// PWGLF -#include "PWGLF/DataModel/mcCentrality.h" -// PWGHF #include "PWGHF/Core/CentralityEstimation.h" -#include "PWGHF/Core/SelectorCuts.h" +#include "PWGHF/Core/DecayChannels.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/Utils/utilsBfieldCCDB.h" #include "PWGHF/Utils/utilsEvSelHf.h" #include "PWGHF/Utils/utilsPid.h" #include "PWGHF/Utils/utilsTrkCandHf.h" +#include "PWGLF/DataModel/mcCentrality.h" + +#include "Common/Core/RecoDecay.h" +#include "Common/Core/trackUtilities.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.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 using namespace o2; using namespace o2::hf_evsel; diff --git a/PWGHF/TableProducer/candidateCreatorLb.cxx b/PWGHF/TableProducer/candidateCreatorLb.cxx index 49928fd70ad..655847fa97a 100644 --- a/PWGHF/TableProducer/candidateCreatorLb.cxx +++ b/PWGHF/TableProducer/candidateCreatorLb.cxx @@ -15,23 +15,39 @@ /// /// \author Panos Christakoglou , Nikhef -#include -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "DCAFitter/DCAFitterN.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/DCA.h" -#include "ReconstructionDataFormats/V0.h" - -#include "Common/Core/trackUtilities.h" - #include "PWGHF/Core/HfHelper.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" #include "PWGHF/Utils/utilsTrkCandHf.h" +#include "Common/Core/RecoDecay.h" +#include "Common/Core/trackUtilities.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::analysis; using namespace o2::aod; diff --git a/PWGHF/TableProducer/candidateCreatorMcGen.cxx b/PWGHF/TableProducer/candidateCreatorMcGen.cxx index 8da97722b8b..52d947c7828 100644 --- a/PWGHF/TableProducer/candidateCreatorMcGen.cxx +++ b/PWGHF/TableProducer/candidateCreatorMcGen.cxx @@ -14,21 +14,20 @@ /// /// \author Nima Zardoshti, nima.zardoshti@cern.ch, CERN -#include -#include -#include - -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" -#include "Framework/RunningWorkflowInfo.h" - #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/Utils/utilsMcGen.h" +#include +#include +#include +#include +#include +#include +#include + +#include +#include + using namespace o2; using namespace o2::framework; using namespace o2::constants::physics; diff --git a/PWGHF/TableProducer/candidateCreatorSigmac0plusplus.cxx b/PWGHF/TableProducer/candidateCreatorSigmac0plusplus.cxx index 3e9bf3fe4f5..bfcc42b733a 100644 --- a/PWGHF/TableProducer/candidateCreatorSigmac0plusplus.cxx +++ b/PWGHF/TableProducer/candidateCreatorSigmac0plusplus.cxx @@ -15,6 +15,8 @@ /// /// \author Mattia Faggin , University and INFN PADOVA +#include "PWGHF/Core/CentralityEstimation.h" +#include "PWGHF/Core/DecayChannels.h" #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" @@ -22,22 +24,40 @@ #include "PWGHF/Utils/utilsBfieldCCDB.h" // for dca recalculation #include "PWGHF/Utils/utilsEvSelHf.h" +#include "Common/Core/RecoDecay.h" #include "Common/Core/TrackSelection.h" #include "Common/Core/TrackSelectionDefaults.h" #include "Common/Core/trackUtilities.h" #include "Common/DataModel/CollisionAssociationTables.h" - -#include "CCDB/BasicCCDBManager.h" // for dca recalculation -#include "CommonConstants/PhysicsConstants.h" -#include "DataFormatsParameters/GRPMagField.h" // for dca recalculation -#include "DataFormatsParameters/GRPObject.h" // for dca recalculation -#include "DetectorsBase/GeometryManager.h" // for dca recalculation -#include "DetectorsBase/Propagator.h" // for dca recalculation -#include "DetectorsVertexing/PVertexer.h" // for dca recalculation -#include "Framework/AnalysisTask.h" -#include "Framework/RunningWorkflowInfo.h" -#include "Framework/runDataProcessing.h" - +#include "Common/DataModel/EventSelection.h" + +#include // for dca recalculation +#include +#include +#include // for dca recalculation +#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/PWGHF/TableProducer/candidateCreatorSigmac0plusplusCascade.cxx b/PWGHF/TableProducer/candidateCreatorSigmac0plusplusCascade.cxx index ee784c35fae..71a61bec437 100644 --- a/PWGHF/TableProducer/candidateCreatorSigmac0plusplusCascade.cxx +++ b/PWGHF/TableProducer/candidateCreatorSigmac0plusplusCascade.cxx @@ -15,21 +15,27 @@ /// \author Rutuparna Rath , INFN BOLOGNA and GSI Darmstadt /// In collaboration with Andrea Alici , INFN BOLOGNA -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - -#include "Common/Core/TrackSelection.h" -#include "Common/Core/trackUtilities.h" -#include "Common/Core/TrackSelectionDefaults.h" - #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + using namespace o2; using namespace o2::analysis; using namespace o2::constants::physics; diff --git a/PWGHF/TableProducer/candidateCreatorXic0Omegac0.cxx b/PWGHF/TableProducer/candidateCreatorXic0Omegac0.cxx index 754272af541..eac81b5ac5f 100644 --- a/PWGHF/TableProducer/candidateCreatorXic0Omegac0.cxx +++ b/PWGHF/TableProducer/candidateCreatorXic0Omegac0.cxx @@ -21,52 +21,59 @@ #define HomogeneousField // o2-linter: disable=name/macro (required by KFParticle) #endif -#include -#include -#include -#include - -/// includes KFParticle -#include "KFParticle.h" -#include "KFParticleBase.h" -#include "KFPTrack.h" -#include "KFPVertex.h" -#include "KFVertex.h" - -#include "CCDB/BasicCCDBManager.h" -#include "CommonConstants/PhysicsConstants.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DCAFitter/DCAFitterN.h" -#include "DetectorsBase/Propagator.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/runDataProcessing.h" -#include "Framework/RunningWorkflowInfo.h" -#include "ReconstructionDataFormats/DCA.h" -#include "ReconstructionDataFormats/Track.h" -#include "ReconstructionDataFormats/V0.h" +#include "PWGHF/Core/CentralityEstimation.h" +#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "PWGHF/Utils/utilsBfieldCCDB.h" +#include "PWGHF/Utils/utilsEvSelHf.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" +#include "PWGLF/DataModel/mcCentrality.h" #include "Common/Core/RecoDecay.h" #include "Common/Core/trackUtilities.h" -#include "Common/DataModel/CollisionAssociationTables.h" +#include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" #include "Tools/KFparticle/KFUtilities.h" -#include "PWGLF/DataModel/LFStrangenessTables.h" -#include "PWGLF/DataModel/mcCentrality.h" - -#include "PWGHF/Core/CentralityEstimation.h" -#include "PWGHF/Core/SelectorCuts.h" -#include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" -#include "PWGHF/Utils/utilsBfieldCCDB.h" -#include "PWGHF/Utils/utilsEvSelHf.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 using namespace o2; using namespace o2::track; -using namespace o2::analysis; using namespace o2::aod; using namespace o2::aod::cascdata; using namespace o2::aod::v0data; diff --git a/PWGHF/TableProducer/candidateCreatorXicToXiPiPi.cxx b/PWGHF/TableProducer/candidateCreatorXicToXiPiPi.cxx index 3f710601315..7063f970f44 100644 --- a/PWGHF/TableProducer/candidateCreatorXicToXiPiPi.cxx +++ b/PWGHF/TableProducer/candidateCreatorXicToXiPiPi.cxx @@ -21,34 +21,52 @@ #define HomogeneousField // o2-linter: disable=name/macro (required by KFParticle) #endif +#include "PWGHF/Core/CentralityEstimation.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/Utils/utilsBfieldCCDB.h" #include "PWGHF/Utils/utilsEvSelHf.h" #include "PWGLF/DataModel/LFStrangenessTables.h" #include "PWGLF/DataModel/mcCentrality.h" +#include "Common/Core/RecoDecay.h" #include "Common/Core/trackUtilities.h" -#include "Common/DataModel/CollisionAssociationTables.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" #include "Tools/KFparticle/KFUtilities.h" -#include "CommonConstants/PhysicsConstants.h" -#include "DCAFitter/DCAFitterN.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/RunningWorkflowInfo.h" -#include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/DCA.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 diff --git a/PWGHF/TableProducer/candidateCreatorXicc.cxx b/PWGHF/TableProducer/candidateCreatorXicc.cxx index e4455828b8d..915d6501d6f 100644 --- a/PWGHF/TableProducer/candidateCreatorXicc.cxx +++ b/PWGHF/TableProducer/candidateCreatorXicc.cxx @@ -17,18 +17,34 @@ /// \author Luigi Dello Stritto , SALERNO /// \author Mattia Faggin , University and INFN PADOVA -#include "CommonConstants/PhysicsConstants.h" -#include "DCAFitter/DCAFitterN.h" -#include "Framework/AnalysisTask.h" -#include "ReconstructionDataFormats/DCA.h" -#include "ReconstructionDataFormats/V0.h" - -#include "Common/Core/trackUtilities.h" - #include "PWGHF/Core/HfHelper.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "Common/Core/RecoDecay.h" +#include "Common/Core/trackUtilities.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::analysis; using namespace o2::constants::physics; @@ -41,7 +57,7 @@ void customize(std::vector& workflowOptions) workflowOptions.push_back(optionDoMC); } -#include "Framework/runDataProcessing.h" +#include /// Reconstruction of xicc candidates struct HfCandidateCreatorXicc { diff --git a/PWGHF/TableProducer/candidateSelectorB0ToDPi.cxx b/PWGHF/TableProducer/candidateSelectorB0ToDPi.cxx index cf7658810d8..60709a4e4dc 100644 --- a/PWGHF/TableProducer/candidateSelectorB0ToDPi.cxx +++ b/PWGHF/TableProducer/candidateSelectorB0ToDPi.cxx @@ -14,16 +14,6 @@ /// /// \author Alexandre Bigot , IPHC Strasbourg -#include -#include -#include - -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" -#include "Framework/RunningWorkflowInfo.h" - -#include "Common/Core/TrackSelectorPID.h" - #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/HfMlResponseB0ToDPi.h" #include "PWGHF/Core/SelectorCuts.h" @@ -31,6 +21,33 @@ #include "PWGHF/DataModel/CandidateSelectionTables.h" #include "PWGHF/Utils/utilsPid.h" +#include "Common/Core/TrackSelectorPID.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 + using namespace o2; using namespace o2::aod; using namespace o2::framework; diff --git a/PWGHF/TableProducer/candidateSelectorBplusToD0Pi.cxx b/PWGHF/TableProducer/candidateSelectorBplusToD0Pi.cxx index 154067f6bc2..1bcc8bff8e0 100644 --- a/PWGHF/TableProducer/candidateSelectorBplusToD0Pi.cxx +++ b/PWGHF/TableProducer/candidateSelectorBplusToD0Pi.cxx @@ -16,16 +16,6 @@ /// \author Deepa Thomas , UT Austin /// \author Nima Zardoshti , CERN -#include -#include -#include - -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" -#include "Framework/RunningWorkflowInfo.h" - -#include "Common/Core/TrackSelectorPID.h" - #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/HfMlResponseBplusToD0Pi.h" #include "PWGHF/Core/SelectorCuts.h" @@ -33,6 +23,34 @@ #include "PWGHF/DataModel/CandidateSelectionTables.h" #include "PWGHF/Utils/utilsPid.h" +#include "Common/Core/TrackSelectorPID.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 + using namespace o2; using namespace o2::aod; using namespace o2::framework; diff --git a/PWGHF/TableProducer/candidateSelectorBsToDsPi.cxx b/PWGHF/TableProducer/candidateSelectorBsToDsPi.cxx index cfd8f418e0e..05a66854ada 100644 --- a/PWGHF/TableProducer/candidateSelectorBsToDsPi.cxx +++ b/PWGHF/TableProducer/candidateSelectorBsToDsPi.cxx @@ -15,21 +15,37 @@ /// /// \author Phil Stahlhut -#include -#include - -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" -#include "Framework/RunningWorkflowInfo.h" - -#include "Common/Core/TrackSelectorPID.h" - #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/HfMlResponse.h" #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "Common/Core/TrackSelectorPID.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::aod; using namespace o2::framework; diff --git a/PWGHF/TableProducer/candidateSelectorD0.cxx b/PWGHF/TableProducer/candidateSelectorD0.cxx index ae0102b33fe..98634b9cf08 100644 --- a/PWGHF/TableProducer/candidateSelectorD0.cxx +++ b/PWGHF/TableProducer/candidateSelectorD0.cxx @@ -15,23 +15,34 @@ /// \author Nima Zardoshti , CERN /// \author Vít Kučera , CERN -#include -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - -#include "Common/Core/TrackSelectorPID.h" - #include "PWGHF/Core/HfHelper.h" -#include "PWGHF/Core/HfMlResponse.h" #include "PWGHF/Core/HfMlResponseD0ToKPi.h" #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" #include "PWGHF/Utils/utilsAnalysis.h" +#include "Common/Core/TrackSelectorPID.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + using namespace o2; using namespace o2::analysis; using namespace o2::framework; diff --git a/PWGHF/TableProducer/candidateSelectorDplusToPiKPi.cxx b/PWGHF/TableProducer/candidateSelectorDplusToPiKPi.cxx index 8295ddf1e62..a531b6dbab0 100644 --- a/PWGHF/TableProducer/candidateSelectorDplusToPiKPi.cxx +++ b/PWGHF/TableProducer/candidateSelectorDplusToPiKPi.cxx @@ -15,15 +15,6 @@ /// \author Fabio Catalano , Politecnico and INFN Torino /// \author Vít Kučera , CERN -#include -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - -#include "Common/Core/TrackSelectorPID.h" - #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/HfMlResponseDplusToPiKPi.h" #include "PWGHF/Core/SelectorCuts.h" @@ -31,6 +22,28 @@ #include "PWGHF/DataModel/CandidateSelectionTables.h" #include "PWGHF/Utils/utilsAnalysis.h" +#include "Common/Core/TrackSelectorPID.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include +#include + using namespace o2; using namespace o2::analysis; using namespace o2::framework; diff --git a/PWGHF/TableProducer/candidateSelectorDsToKKPi.cxx b/PWGHF/TableProducer/candidateSelectorDsToKKPi.cxx index 9196ce735de..80f22343ff1 100644 --- a/PWGHF/TableProducer/candidateSelectorDsToKKPi.cxx +++ b/PWGHF/TableProducer/candidateSelectorDsToKKPi.cxx @@ -15,15 +15,6 @@ /// \author Fabio Catalano , Universita and INFN Torino /// \author Stefano Politano , Politecnico and INFN Torino -#include -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - -#include "Common/Core/TrackSelectorPID.h" - #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/HfMlResponseDsToKKPi.h" #include "PWGHF/Core/SelectorCuts.h" @@ -31,6 +22,28 @@ #include "PWGHF/DataModel/CandidateSelectionTables.h" #include "PWGHF/Utils/utilsAnalysis.h" +#include "Common/Core/TrackSelectorPID.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include +#include + using namespace o2; using namespace o2::analysis; using namespace o2::framework; diff --git a/PWGHF/TableProducer/candidateSelectorDstarToD0Pi.cxx b/PWGHF/TableProducer/candidateSelectorDstarToD0Pi.cxx index cb058a18f6b..e1417802a33 100644 --- a/PWGHF/TableProducer/candidateSelectorDstarToD0Pi.cxx +++ b/PWGHF/TableProducer/candidateSelectorDstarToD0Pi.cxx @@ -15,19 +15,6 @@ /// \author Deependra Sharma , IITB /// \author Fabrizio Grosa , CERN -#include -#include -#include - -// O2 -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/Logger.h" -#include "Framework/runDataProcessing.h" -// O2Physics -#include "Common/Core/TrackSelectorPID.h" -// PWGHF #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/HfMlResponseDstarToD0Pi.h" #include "PWGHF/Core/SelectorCuts.h" @@ -35,6 +22,28 @@ #include "PWGHF/DataModel/CandidateSelectionTables.h" #include "PWGHF/Utils/utilsAnalysis.h" +#include "Common/Core/TrackSelectorPID.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include +#include + using namespace o2; using namespace o2::constants::physics; using namespace o2::analysis; diff --git a/PWGHF/TableProducer/candidateSelectorLbToLcPi.cxx b/PWGHF/TableProducer/candidateSelectorLbToLcPi.cxx index 29ef2154d59..74abba33758 100644 --- a/PWGHF/TableProducer/candidateSelectorLbToLcPi.cxx +++ b/PWGHF/TableProducer/candidateSelectorLbToLcPi.cxx @@ -14,19 +14,26 @@ /// /// \author Panos Christakoglou , Nikhef -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - -#include "Common/Core/TrackSelectorPID.h" - #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "Common/DataModel/PIDResponseTPC.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + using namespace o2; using namespace o2::aod; using namespace o2::framework; diff --git a/PWGHF/TableProducer/candidateSelectorLc.cxx b/PWGHF/TableProducer/candidateSelectorLc.cxx index d48cb5f3daa..2b06decbec7 100644 --- a/PWGHF/TableProducer/candidateSelectorLc.cxx +++ b/PWGHF/TableProducer/candidateSelectorLc.cxx @@ -17,21 +17,36 @@ /// \author Vít Kučera , CERN /// \author Grazia Luparello , INFN Trieste -#include -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - -#include "Common/Core/TrackSelectorPID.h" - #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/HfMlResponseLcToPKPi.h" #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "Common/Core/TrackSelectorPID.h" +#include "Common/DataModel/PIDResponseCombined.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::analysis; using namespace o2::framework; diff --git a/PWGHF/TableProducer/candidateSelectorLcPidMl.cxx b/PWGHF/TableProducer/candidateSelectorLcPidMl.cxx index b30ebec439a..6cb9aba452e 100644 --- a/PWGHF/TableProducer/candidateSelectorLcPidMl.cxx +++ b/PWGHF/TableProducer/candidateSelectorLcPidMl.cxx @@ -17,22 +17,41 @@ /// \author Vít Kučera , CERN /// \author Maja Kabus , CERN, Warsaw University of Technology -#include -#include -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "CCDB/CcdbApi.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" +#include "PWGHF/Core/SelectorCuts.h" +#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "Common/Core/RecoDecay.h" #include "Common/Core/TrackSelectorPID.h" #include "Common/Core/trackUtilities.h" +#include "Common/DataModel/PIDResponseCombined.h" #include "Tools/ML/model.h" -#include "PWGHF/Core/SelectorCuts.h" -#include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "CCDB/CcdbApi.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::analysis; diff --git a/PWGHF/TableProducer/candidateSelectorLcToK0sP.cxx b/PWGHF/TableProducer/candidateSelectorLcToK0sP.cxx index 53df1ed2dfe..a4a026a005b 100644 --- a/PWGHF/TableProducer/candidateSelectorLcToK0sP.cxx +++ b/PWGHF/TableProducer/candidateSelectorLcToK0sP.cxx @@ -17,22 +17,37 @@ /// Daniel Samitz, , Vienna /// Elisa Meninno, , Vienna -#include -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - -#include "Common/Core/TrackSelectorPID.h" - #include "PWGHF/Core/HfHelper.h" -#include "PWGHF/Core/HfMlResponse.h" #include "PWGHF/Core/HfMlResponseLcToK0sP.h" #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "Common/Core/TrackSelectorPID.h" +#include "Common/DataModel/PIDResponseCombined.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::analysis; using namespace o2::framework; diff --git a/PWGHF/TableProducer/candidateSelectorOmegac0ToOmegaKa.cxx b/PWGHF/TableProducer/candidateSelectorOmegac0ToOmegaKa.cxx index ce5787b730a..d65b56a40a9 100644 --- a/PWGHF/TableProducer/candidateSelectorOmegac0ToOmegaKa.cxx +++ b/PWGHF/TableProducer/candidateSelectorOmegac0ToOmegaKa.cxx @@ -13,17 +13,32 @@ /// \brief Omegac0 → Omega Ka selection task /// \author Federica Zanone , Heidelberg University -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectorPID.h" - #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" #include "PWGHF/Utils/utilsAnalysis.h" +#include "Common/Core/RecoDecay.h" +#include "Common/Core/TrackSelectorPID.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include + using namespace o2; using namespace o2::aod; using namespace o2::framework; diff --git a/PWGHF/TableProducer/candidateSelectorOmegac0ToOmegaPi.cxx b/PWGHF/TableProducer/candidateSelectorOmegac0ToOmegaPi.cxx index 24cb43ca348..40f6545243d 100644 --- a/PWGHF/TableProducer/candidateSelectorOmegac0ToOmegaPi.cxx +++ b/PWGHF/TableProducer/candidateSelectorOmegac0ToOmegaPi.cxx @@ -16,23 +16,40 @@ /// \author Yunfan Liu , China University of Geosciences /// \author Fabio Catalano , University of Houston -#include -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectorPID.h" - -#include "PWGHF/Core/HfMlResponse.h" #include "PWGHF/Core/HfMlResponseOmegacToOmegaPi.h" #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" #include "PWGHF/Utils/utilsAnalysis.h" +#include "Common/Core/RecoDecay.h" +#include "Common/Core/TrackSelectorPID.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::aod; using namespace o2::framework; diff --git a/PWGHF/TableProducer/candidateSelectorToXiPi.cxx b/PWGHF/TableProducer/candidateSelectorToXiPi.cxx index 8f118058f3e..4372e3cb40a 100644 --- a/PWGHF/TableProducer/candidateSelectorToXiPi.cxx +++ b/PWGHF/TableProducer/candidateSelectorToXiPi.cxx @@ -13,17 +13,32 @@ /// \brief Xic0 and Omegac0 → Xi Pi selection task /// \author Federica Zanone , Heidelberg University -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectorPID.h" - #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" #include "PWGHF/Utils/utilsAnalysis.h" +#include "Common/Core/RecoDecay.h" +#include "Common/Core/TrackSelectorPID.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include + using namespace o2; using namespace o2::aod; using namespace o2::framework; diff --git a/PWGHF/TableProducer/candidateSelectorXic0ToXiPiKf.cxx b/PWGHF/TableProducer/candidateSelectorXic0ToXiPiKf.cxx index 81327bb70e1..5d8a8f055e1 100644 --- a/PWGHF/TableProducer/candidateSelectorXic0ToXiPiKf.cxx +++ b/PWGHF/TableProducer/candidateSelectorXic0ToXiPiKf.cxx @@ -14,23 +14,38 @@ /// \author Ran Tu , Fudan University /// \author Tao Fang , Central China Normal University -#include -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectorPID.h" - #include "PWGHF/Core/HfMlResponseXic0ToXiPiKf.h" #include "PWGHF/Core/SelectorCuts.h" - #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" #include "PWGHF/Utils/utilsAnalysis.h" +#include "Common/Core/RecoDecay.h" +#include "Common/Core/TrackSelectorPID.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::aod; using namespace o2::framework; diff --git a/PWGHF/TableProducer/candidateSelectorXicToPKPi.cxx b/PWGHF/TableProducer/candidateSelectorXicToPKPi.cxx index c986f9d1423..14b010aeaa2 100644 --- a/PWGHF/TableProducer/candidateSelectorXicToPKPi.cxx +++ b/PWGHF/TableProducer/candidateSelectorXicToPKPi.cxx @@ -17,21 +17,34 @@ /// \author Vít Kučera , CERN /// \author Cristina Terrevoli , INFN BARI -#include -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - -#include "Common/Core/TrackSelectorPID.h" - -#include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/HfMlResponseXicToPKPi.h" +#include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "Common/Core/TrackSelectorPID.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include +#include + using namespace o2; using namespace o2::analysis; using namespace o2::framework; diff --git a/PWGHF/TableProducer/candidateSelectorXicToXiPiPi.cxx b/PWGHF/TableProducer/candidateSelectorXicToXiPiPi.cxx index fc52551630d..addb435e4a5 100644 --- a/PWGHF/TableProducer/candidateSelectorXicToXiPiPi.cxx +++ b/PWGHF/TableProducer/candidateSelectorXicToXiPiPi.cxx @@ -23,10 +23,23 @@ #include "Common/Core/TrackSelectorPID.h" -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include #include #include diff --git a/PWGHF/TableProducer/candidateSelectorXiccToPKPiPi.cxx b/PWGHF/TableProducer/candidateSelectorXiccToPKPiPi.cxx index 578cb27876d..dd178bd83f0 100644 --- a/PWGHF/TableProducer/candidateSelectorXiccToPKPiPi.cxx +++ b/PWGHF/TableProducer/candidateSelectorXiccToPKPiPi.cxx @@ -14,19 +14,25 @@ /// /// \author Gian Michele Innocenti , CERN -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - -#include "Common/Core/TrackSelectorPID.h" - #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "Common/Core/TrackSelectorPID.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + using namespace o2; using namespace o2::analysis; using namespace o2::framework; diff --git a/PWGHF/TableProducer/converterDstarIndices.cxx b/PWGHF/TableProducer/converterDstarIndices.cxx index 9596a571498..8b26f94610e 100644 --- a/PWGHF/TableProducer/converterDstarIndices.cxx +++ b/PWGHF/TableProducer/converterDstarIndices.cxx @@ -14,12 +14,12 @@ /// /// \author Fabrizio Grosa , CERN -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" - #include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include +#include +#include + using namespace o2; using namespace o2::framework; diff --git a/PWGHF/TableProducer/derivedDataCreatorB0ToDPi.cxx b/PWGHF/TableProducer/derivedDataCreatorB0ToDPi.cxx index 0dda7288169..897718122c3 100644 --- a/PWGHF/TableProducer/derivedDataCreatorB0ToDPi.cxx +++ b/PWGHF/TableProducer/derivedDataCreatorB0ToDPi.cxx @@ -15,26 +15,37 @@ /// /// \author Vít Kučera , Inha University -#include -#include -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" +#include "PWGHF/Core/HfHelper.h" +#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "PWGHF/DataModel/DerivedTables.h" +#include "PWGHF/Utils/utilsDerivedData.h" +#include "PWGLF/DataModel/mcCentrality.h" #include "Common/Core/RecoDecay.h" #include "Common/DataModel/Centrality.h" #include "Common/DataModel/Multiplicity.h" -#include "PWGLF/DataModel/mcCentrality.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include -#include "PWGHF/Core/HfHelper.h" -#include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" -#include "PWGHF/DataModel/DerivedTables.h" -#include "PWGHF/Utils/utilsDerivedData.h" -#include "PWGHF/Utils/utilsPid.h" +#include + +#include +#include +#include +#include +#include +#include +#include +#include using namespace o2; using namespace o2::framework; diff --git a/PWGHF/TableProducer/derivedDataCreatorBplusToD0Pi.cxx b/PWGHF/TableProducer/derivedDataCreatorBplusToD0Pi.cxx index abaf1573166..72a4555a14d 100644 --- a/PWGHF/TableProducer/derivedDataCreatorBplusToD0Pi.cxx +++ b/PWGHF/TableProducer/derivedDataCreatorBplusToD0Pi.cxx @@ -15,26 +15,38 @@ /// /// \author Vít Kučera , Inha University -#include -#include -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - -#include "Common/Core/RecoDecay.h" -#include "Common/DataModel/Centrality.h" -#include "Common/DataModel/Multiplicity.h" - -#include "PWGLF/DataModel/mcCentrality.h" - #include "PWGHF/Core/HfHelper.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" #include "PWGHF/DataModel/DerivedTables.h" #include "PWGHF/Utils/utilsDerivedData.h" #include "PWGHF/Utils/utilsPid.h" +#include "PWGLF/DataModel/mcCentrality.h" + +#include "Common/Core/RecoDecay.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 using namespace o2; using namespace o2::framework; diff --git a/PWGHF/TableProducer/derivedDataCreatorD0ToKPi.cxx b/PWGHF/TableProducer/derivedDataCreatorD0ToKPi.cxx index 8ddc3d4464f..98d2346c49b 100644 --- a/PWGHF/TableProducer/derivedDataCreatorD0ToKPi.cxx +++ b/PWGHF/TableProducer/derivedDataCreatorD0ToKPi.cxx @@ -15,26 +15,38 @@ /// /// \author Vít Kučera , Inha University -#include -#include -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - -#include "Common/Core/RecoDecay.h" -#include "Common/DataModel/Centrality.h" -#include "Common/DataModel/Multiplicity.h" - -#include "PWGLF/DataModel/mcCentrality.h" - #include "PWGHF/Core/HfHelper.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" #include "PWGHF/DataModel/DerivedTables.h" #include "PWGHF/Utils/utilsDerivedData.h" #include "PWGHF/Utils/utilsPid.h" +#include "PWGLF/DataModel/mcCentrality.h" + +#include "Common/Core/RecoDecay.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 using namespace o2; using namespace o2::framework; diff --git a/PWGHF/TableProducer/derivedDataCreatorDplusToPiKPi.cxx b/PWGHF/TableProducer/derivedDataCreatorDplusToPiKPi.cxx index 6897b30ec0e..96d3ed0acf4 100644 --- a/PWGHF/TableProducer/derivedDataCreatorDplusToPiKPi.cxx +++ b/PWGHF/TableProducer/derivedDataCreatorDplusToPiKPi.cxx @@ -15,25 +15,38 @@ /// /// \author Vít Kučera , Inha University -#include -#include -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" +#include "PWGHF/Core/DecayChannels.h" +#include "PWGHF/Core/HfHelper.h" +#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "PWGHF/DataModel/DerivedTables.h" +#include "PWGHF/Utils/utilsDerivedData.h" +#include "PWGLF/DataModel/mcCentrality.h" #include "Common/Core/RecoDecay.h" #include "Common/DataModel/Centrality.h" #include "Common/DataModel/Multiplicity.h" -#include "PWGLF/DataModel/mcCentrality.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include -#include "PWGHF/Core/HfHelper.h" -#include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" -#include "PWGHF/DataModel/DerivedTables.h" -#include "PWGHF/Utils/utilsDerivedData.h" +#include + +#include +#include +#include +#include +#include +#include +#include +#include using namespace o2; using namespace o2::framework; diff --git a/PWGHF/TableProducer/derivedDataCreatorDstarToD0Pi.cxx b/PWGHF/TableProducer/derivedDataCreatorDstarToD0Pi.cxx index 7c592e9ccb1..5a0d0b92915 100644 --- a/PWGHF/TableProducer/derivedDataCreatorDstarToD0Pi.cxx +++ b/PWGHF/TableProducer/derivedDataCreatorDstarToD0Pi.cxx @@ -15,24 +15,36 @@ /// /// \author Mingze Li , CCNU -#include -#include -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" +#include "PWGHF/Core/DecayChannels.h" +#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "PWGHF/DataModel/DerivedTables.h" +#include "PWGHF/Utils/utilsDerivedData.h" +#include "PWGLF/DataModel/mcCentrality.h" -#include "Common/Core/RecoDecay.h" #include "Common/DataModel/Centrality.h" #include "Common/DataModel/Multiplicity.h" -#include "PWGLF/DataModel/mcCentrality.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include -#include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" -#include "PWGHF/DataModel/DerivedTables.h" -#include "PWGHF/Utils/utilsDerivedData.h" +#include + +#include +#include +#include +#include +#include +#include +#include +#include using namespace o2; using namespace o2::framework; diff --git a/PWGHF/TableProducer/derivedDataCreatorLcToPKPi.cxx b/PWGHF/TableProducer/derivedDataCreatorLcToPKPi.cxx index a956d4ff202..1f17e65f910 100644 --- a/PWGHF/TableProducer/derivedDataCreatorLcToPKPi.cxx +++ b/PWGHF/TableProducer/derivedDataCreatorLcToPKPi.cxx @@ -15,25 +15,38 @@ /// /// \author Vít Kučera , Inha University -#include -#include -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" +#include "PWGHF/Core/DecayChannels.h" +#include "PWGHF/Core/HfHelper.h" +#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "PWGHF/DataModel/DerivedTables.h" +#include "PWGHF/Utils/utilsDerivedData.h" +#include "PWGLF/DataModel/mcCentrality.h" #include "Common/Core/RecoDecay.h" #include "Common/DataModel/Centrality.h" #include "Common/DataModel/Multiplicity.h" -#include "PWGLF/DataModel/mcCentrality.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include -#include "PWGHF/Core/HfHelper.h" -#include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" -#include "PWGHF/DataModel/DerivedTables.h" -#include "PWGHF/Utils/utilsDerivedData.h" +#include + +#include +#include +#include +#include +#include +#include +#include +#include using namespace o2; using namespace o2::framework; diff --git a/PWGHF/TableProducer/mcPidTof.cxx b/PWGHF/TableProducer/mcPidTof.cxx index 6a547938d51..1d22d776e2d 100644 --- a/PWGHF/TableProducer/mcPidTof.cxx +++ b/PWGHF/TableProducer/mcPidTof.cxx @@ -21,23 +21,43 @@ #include "Common/Core/TableHelper.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/FT0Corrected.h" -#include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/TrackSelectionTables.h" +#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/PIDResponseTOF.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 -#include #include using namespace o2; diff --git a/PWGHF/TableProducer/pidCreator.cxx b/PWGHF/TableProducer/pidCreator.cxx index 57da53a0d30..d4a236b5d72 100644 --- a/PWGHF/TableProducer/pidCreator.cxx +++ b/PWGHF/TableProducer/pidCreator.cxx @@ -14,15 +14,21 @@ /// /// \author Vít Kučera , Inha University -#include - -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" +#include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "Common/Core/TableHelper.h" -#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/PIDResponseTOF.h" +#include "Common/DataModel/PIDResponseTPC.h" -#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include +#include +#include +#include +#include +#include +#include + +#include using namespace o2; using namespace o2::framework; diff --git a/PWGHF/TableProducer/refitPvDummy.cxx b/PWGHF/TableProducer/refitPvDummy.cxx index 64b13f2d5cb..51b7db06236 100644 --- a/PWGHF/TableProducer/refitPvDummy.cxx +++ b/PWGHF/TableProducer/refitPvDummy.cxx @@ -14,14 +14,15 @@ /// /// \author Mattia Faggin , University and INFN Padova, Italy -#include "Framework/AnalysisTask.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/Track.h" +#include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "Common/Core/trackUtilities.h" -#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include +#include +#include +#include +#include using namespace o2; using namespace o2::framework; diff --git a/PWGHF/TableProducer/trackIndexSkimCreator.cxx b/PWGHF/TableProducer/trackIndexSkimCreator.cxx index 2c6dfd66343..ebe0713d03a 100644 --- a/PWGHF/TableProducer/trackIndexSkimCreator.cxx +++ b/PWGHF/TableProducer/trackIndexSkimCreator.cxx @@ -21,40 +21,64 @@ /// \author Federica Zanone , Heidelberg University /// \author Ruiqi Yin , Fudan University -#include // std::find -#include // std::distance -#include // std::string -#include // std::vector - -#include "CommonConstants/PhysicsConstants.h" -#include "CCDB/BasicCCDBManager.h" // for PV refit -#include "DataFormatsParameters/GRPMagField.h" // for PV refit -#include "DataFormatsParameters/GRPObject.h" // for PV refit -#include "DCAFitter/DCAFitterN.h" -#include "DetectorsBase/Propagator.h" // for PV refit -#include "DetectorsVertexing/PVertexer.h" // for PV refit -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/V0.h" -#include "ReconstructionDataFormats/Vertex.h" // for PV refit +#include "PWGHF/Core/CentralityEstimation.h" +#include "PWGHF/Core/SelectorCuts.h" +#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "PWGHF/Utils/utilsAnalysis.h" +#include "PWGHF/Utils/utilsBfieldCCDB.h" +#include "PWGHF/Utils/utilsEvSelHf.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" +#include "Common/CCDB/TriggerAliases.h" +#include "Common/Core/RecoDecay.h" #include "Common/Core/TrackSelectorPID.h" #include "Common/Core/trackUtilities.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 "Tools/ML/MlResponse.h" -#include "PWGLF/DataModel/LFStrangenessTables.h" +#include // for PV refit +#include +#include +#include +#include +#include +#include // for PV refit +#include // for PV refit +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include // for PV refit + +#include +#include + +#include +#include -#include "PWGHF/Core/CentralityEstimation.h" -#include "PWGHF/Core/SelectorCuts.h" -#include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/Utils/utilsAnalysis.h" -#include "PWGHF/Utils/utilsBfieldCCDB.h" -#include "PWGHF/Utils/utilsEvSelHf.h" +#include // std::find +#include +#include +#include +#include +#include // std::distance +#include +#include // std::string +#include // std::vector using namespace o2; using namespace o2::analysis; diff --git a/PWGHF/TableProducer/treeCreatorB0ToDPi.cxx b/PWGHF/TableProducer/treeCreatorB0ToDPi.cxx index 0288f19cac9..a2685a57e05 100644 --- a/PWGHF/TableProducer/treeCreatorB0ToDPi.cxx +++ b/PWGHF/TableProducer/treeCreatorB0ToDPi.cxx @@ -16,14 +16,26 @@ /// /// \author Alexandre Bigot , IPHC Strasbourg -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - #include "PWGHF/Core/HfHelper.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "Common/Core/RecoDecay.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; diff --git a/PWGHF/TableProducer/treeCreatorBplusToD0Pi.cxx b/PWGHF/TableProducer/treeCreatorBplusToD0Pi.cxx index 7b2c1145c3f..9a37fe1f54a 100644 --- a/PWGHF/TableProducer/treeCreatorBplusToD0Pi.cxx +++ b/PWGHF/TableProducer/treeCreatorBplusToD0Pi.cxx @@ -17,14 +17,27 @@ /// /// \author Antonio Palasciano , Università & INFN, Bari -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - #include "PWGHF/Core/HfHelper.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "Common/Core/RecoDecay.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; diff --git a/PWGHF/TableProducer/treeCreatorBsToDsPi.cxx b/PWGHF/TableProducer/treeCreatorBsToDsPi.cxx index bdbf09cfbed..f02b65f4107 100644 --- a/PWGHF/TableProducer/treeCreatorBsToDsPi.cxx +++ b/PWGHF/TableProducer/treeCreatorBsToDsPi.cxx @@ -16,14 +16,26 @@ /// \note Adapted from treeCreatorB0T0DPi.cxx /// \author Phil Stahlhut -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - #include "PWGHF/Core/HfHelper.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "Common/Core/RecoDecay.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; diff --git a/PWGHF/TableProducer/treeCreatorD0ToKPi.cxx b/PWGHF/TableProducer/treeCreatorD0ToKPi.cxx index 59bf26581c5..781a5b89ded 100644 --- a/PWGHF/TableProducer/treeCreatorD0ToKPi.cxx +++ b/PWGHF/TableProducer/treeCreatorD0ToKPi.cxx @@ -17,14 +17,28 @@ /// \author Nicolo' Jacazio , CERN /// \author Andrea Tavira García , IJCLab -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - #include "PWGHF/Core/HfHelper.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "Common/Core/RecoDecay.h" + +#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; diff --git a/PWGHF/TableProducer/treeCreatorDplusToPiKPi.cxx b/PWGHF/TableProducer/treeCreatorDplusToPiKPi.cxx index 08ae6c65552..b4baa783675 100644 --- a/PWGHF/TableProducer/treeCreatorDplusToPiKPi.cxx +++ b/PWGHF/TableProducer/treeCreatorDplusToPiKPi.cxx @@ -16,17 +16,27 @@ /// /// \author Alexandre Bigot , IPHC Strasbourg -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - -#include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/CentralityEstimation.h" +#include "PWGHF/Core/DecayChannels.h" +#include "PWGHF/Core/HfHelper.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "Common/Core/RecoDecay.h" +#include "Common/DataModel/Centrality.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; diff --git a/PWGHF/TableProducer/treeCreatorDsToKKPi.cxx b/PWGHF/TableProducer/treeCreatorDsToKKPi.cxx index 7a8547cf32a..ca3ed4db61a 100644 --- a/PWGHF/TableProducer/treeCreatorDsToKKPi.cxx +++ b/PWGHF/TableProducer/treeCreatorDsToKKPi.cxx @@ -17,17 +17,29 @@ /// \author Stefano Politanò , Politecnico & INFN, Torino /// \author Fabio Catalano , CERN -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - -#include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/CentralityEstimation.h" +#include "PWGHF/Core/DecayChannels.h" +#include "PWGHF/Core/HfHelper.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "Common/Core/RecoDecay.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; diff --git a/PWGHF/TableProducer/treeCreatorDstarToD0Pi.cxx b/PWGHF/TableProducer/treeCreatorDstarToD0Pi.cxx index 2b838d774b1..18ee43a111b 100644 --- a/PWGHF/TableProducer/treeCreatorDstarToD0Pi.cxx +++ b/PWGHF/TableProducer/treeCreatorDstarToD0Pi.cxx @@ -16,13 +16,23 @@ /// /// \author Fabrizio Grosa , CERN -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - +#include "PWGHF/Core/DecayChannels.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "Common/Core/RecoDecay.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; diff --git a/PWGHF/TableProducer/treeCreatorLbToLcPi.cxx b/PWGHF/TableProducer/treeCreatorLbToLcPi.cxx index 38a68453415..a60a7eba661 100644 --- a/PWGHF/TableProducer/treeCreatorLbToLcPi.cxx +++ b/PWGHF/TableProducer/treeCreatorLbToLcPi.cxx @@ -18,13 +18,22 @@ /// \author Panos Christakoglou , Nikhef /// \author Maurice Jongerhuis , University Utrecht -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - #include "PWGHF/Core/HfHelper.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "Common/Core/RecoDecay.h" +#include "Common/DataModel/PIDResponseTOF.h" +#include "Common/DataModel/PIDResponseTPC.h" + +#include +#include +#include +#include +#include + +#include + using namespace o2; using namespace o2::framework; diff --git a/PWGHF/TableProducer/treeCreatorLcToK0sP.cxx b/PWGHF/TableProducer/treeCreatorLcToK0sP.cxx index 35e15a7cb9f..0012108a45c 100644 --- a/PWGHF/TableProducer/treeCreatorLcToK0sP.cxx +++ b/PWGHF/TableProducer/treeCreatorLcToK0sP.cxx @@ -17,13 +17,24 @@ /// /// \author Daniel Samitz -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - #include "PWGHF/Core/HfHelper.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" + +#include "Common/Core/RecoDecay.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include using namespace o2; using namespace o2::framework; diff --git a/PWGHF/TableProducer/treeCreatorLcToPKPi.cxx b/PWGHF/TableProducer/treeCreatorLcToPKPi.cxx index abb9b3c220b..90b47824835 100644 --- a/PWGHF/TableProducer/treeCreatorLcToPKPi.cxx +++ b/PWGHF/TableProducer/treeCreatorLcToPKPi.cxx @@ -17,18 +17,32 @@ /// \author Nicolo' Jacazio , CERN /// \author Luigi Dello Stritto , CERN +#include "PWGHF/Core/DecayChannels.h" #include "PWGHF/Core/HfHelper.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "Common/Core/RecoDecay.h" #include "Common/DataModel/Centrality.h" #include "Common/DataModel/Multiplicity.h" -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include #include +#include +#include +#include +#include +#include +#include #include #include diff --git a/PWGHF/TableProducer/treeCreatorOmegac0ToOmegaKa.cxx b/PWGHF/TableProducer/treeCreatorOmegac0ToOmegaKa.cxx index ce441aa45d5..a16685f7b04 100644 --- a/PWGHF/TableProducer/treeCreatorOmegac0ToOmegaKa.cxx +++ b/PWGHF/TableProducer/treeCreatorOmegac0ToOmegaKa.cxx @@ -15,13 +15,22 @@ /// /// \author Federica Zanone , Heidelberg University -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" +#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "PWGHF/DataModel/CandidateSelectionTables.h" #include "Common/Core/RecoDecay.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/TrackSelectionTables.h" -#include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" +#include +#include +#include +#include +#include +#include +#include + +#include using namespace o2; using namespace o2::framework; diff --git a/PWGHF/TableProducer/treeCreatorOmegac0ToOmegaPi.cxx b/PWGHF/TableProducer/treeCreatorOmegac0ToOmegaPi.cxx index a1b8a2b3706..ad25a583f45 100644 --- a/PWGHF/TableProducer/treeCreatorOmegac0ToOmegaPi.cxx +++ b/PWGHF/TableProducer/treeCreatorOmegac0ToOmegaPi.cxx @@ -18,13 +18,24 @@ /// \author Fabio Catalano , University of Houston /// \author Ruiqi Yin , Fudan University -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" +#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "PWGHF/DataModel/CandidateSelectionTables.h" #include "Common/Core/RecoDecay.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/TrackSelectionTables.h" -#include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" +#include +#include +#include +#include +#include +#include +#include + +#include + +#include using namespace o2; using namespace o2::framework; diff --git a/PWGHF/TableProducer/treeCreatorOmegacSt.cxx b/PWGHF/TableProducer/treeCreatorOmegacSt.cxx index 4d3c59cfcd1..b74dafe4c5e 100644 --- a/PWGHF/TableProducer/treeCreatorOmegacSt.cxx +++ b/PWGHF/TableProducer/treeCreatorOmegacSt.cxx @@ -15,40 +15,55 @@ /// \author Jochen Klein /// \author Tiantian Cheng -#include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/Utils/utilsTrkCandHf.h" #include "PWGLF/DataModel/LFStrangenessTables.h" #include "Common/Core/RecoDecay.h" -#include "Common/Core/TrackSelection.h" #include "Common/Core/trackUtilities.h" #include "Common/DataModel/CollisionAssociationTables.h" #include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/PIDResponseTOF.h" +#include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/TrackSelectionTables.h" #include "EventFiltering/Zorro.h" #include "EventFiltering/ZorroSummary.h" -#include "CCDB/BasicCCDBManager.h" -#include "CommonConstants/PhysicsConstants.h" -#include "DCAFitter/DCAFitterN.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DetectorsBase/Propagator.h" -#include "Framework/ASoA.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/DCA.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 using namespace o2; diff --git a/PWGHF/TableProducer/treeCreatorTccToD0D0Pi.cxx b/PWGHF/TableProducer/treeCreatorTccToD0D0Pi.cxx index 84f32851aeb..a59713f4adf 100644 --- a/PWGHF/TableProducer/treeCreatorTccToD0D0Pi.cxx +++ b/PWGHF/TableProducer/treeCreatorTccToD0D0Pi.cxx @@ -14,35 +14,52 @@ /// \author Biao Zhang , Heidelberg University /// \author Fabrizio Grosa , CERN -#include -#include -#include -#include -#include -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "DCAFitter/DCAFitterN.h" -#include "Framework/AnalysisTask.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/DCA.h" -#include "ReconstructionDataFormats/V0.h" - -#include "Common/Core/trackUtilities.h" -#include "Common/Core/TrackSelection.h" -#include "Common/DataModel/CollisionAssociationTables.h" -#include "Common/Core/TrackSelectionDefaults.h" - -#include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/CentralityEstimation.h" +#include "PWGHF/Core/HfHelper.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" #include "PWGHF/Utils/utilsBfieldCCDB.h" -#include "PWGHF/Utils/utilsEvSelHf.h" -#include "PWGHF/D2H/DataModel/ReducedDataModel.h" #include "PWGHF/Utils/utilsTrkCandHf.h" -#include "PWGHF/D2H/Utils/utilsRedDataFormat.h" + +#include "Common/Core/RecoDecay.h" +#include "Common/Core/trackUtilities.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 +#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::analysis; diff --git a/PWGHF/TableProducer/treeCreatorToXiPi.cxx b/PWGHF/TableProducer/treeCreatorToXiPi.cxx index f19642f5151..88ca022029a 100644 --- a/PWGHF/TableProducer/treeCreatorToXiPi.cxx +++ b/PWGHF/TableProducer/treeCreatorToXiPi.cxx @@ -15,16 +15,26 @@ /// /// \author Federica Zanone , Heidelberg University -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - -#include "Common/Core/RecoDecay.h" - -#include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/CentralityEstimation.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "Common/Core/RecoDecay.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + using namespace o2; using namespace o2::framework; diff --git a/PWGHF/TableProducer/treeCreatorXic0ToXiPiKf.cxx b/PWGHF/TableProducer/treeCreatorXic0ToXiPiKf.cxx index 87355a4590b..ae0e919967a 100644 --- a/PWGHF/TableProducer/treeCreatorXic0ToXiPiKf.cxx +++ b/PWGHF/TableProducer/treeCreatorXic0ToXiPiKf.cxx @@ -14,18 +14,26 @@ /// In this file are defined and filled the output tables /// /// \author Ran Tu , Fudan University -/// \author Tao Fang , Central China Normal University -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - -#include "Common/Core/RecoDecay.h" - -#include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/CentralityEstimation.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "Common/Core/RecoDecay.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include +#include +#include +#include +#include +#include +#include + +#include + using namespace o2; using namespace o2::framework; diff --git a/PWGHF/TableProducer/treeCreatorXicToPKPi.cxx b/PWGHF/TableProducer/treeCreatorXicToPKPi.cxx index b038f28c80e..a7e592d910e 100644 --- a/PWGHF/TableProducer/treeCreatorXicToPKPi.cxx +++ b/PWGHF/TableProducer/treeCreatorXicToPKPi.cxx @@ -16,14 +16,24 @@ /// \author Himanshu Sharma , INFN Padova /// \author Cristina Terrevoli , INFN Bari -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - +#include "PWGHF/Core/DecayChannels.h" #include "PWGHF/Core/HfHelper.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "Common/Core/RecoDecay.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; diff --git a/PWGHF/TableProducer/treeCreatorXicToXiPiPi.cxx b/PWGHF/TableProducer/treeCreatorXicToXiPiPi.cxx index be12fd5cbeb..5f8e44e4a4b 100644 --- a/PWGHF/TableProducer/treeCreatorXicToXiPiPi.cxx +++ b/PWGHF/TableProducer/treeCreatorXicToXiPiPi.cxx @@ -19,15 +19,25 @@ #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" +#include "Common/Core/RecoDecay.h" -#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 o2::aod { diff --git a/PWGHF/TableProducer/treeCreatorXiccToPKPiPi.cxx b/PWGHF/TableProducer/treeCreatorXiccToPKPiPi.cxx index 2ceeb567de2..56ca3f152c6 100644 --- a/PWGHF/TableProducer/treeCreatorXiccToPKPiPi.cxx +++ b/PWGHF/TableProducer/treeCreatorXiccToPKPiPi.cxx @@ -17,14 +17,24 @@ /// /// \author Jinjoo Seo , Inha University -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - #include "PWGHF/Core/HfHelper.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "Common/Core/RecoDecay.h" +#include "Common/DataModel/PIDResponseTOF.h" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + using namespace o2; using namespace o2::framework; diff --git a/PWGHF/Tasks/taskCharmHadImpactPar.cxx b/PWGHF/Tasks/taskCharmHadImpactPar.cxx index 9671501387f..a20c49c922b 100644 --- a/PWGHF/Tasks/taskCharmHadImpactPar.cxx +++ b/PWGHF/Tasks/taskCharmHadImpactPar.cxx @@ -15,20 +15,34 @@ /// \author Fabrizio Grosa , CERN /// \author Antonio Palasciano , INFN Bari -#include -#include - -#include "Common/Core/RecoDecay.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" - -#include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/CentralityEstimation.h" +#include "PWGHF/Core/DecayChannels.h" +#include "PWGHF/Core/HfHelper.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" #include "PWGHF/Utils/utilsEvSelHf.h" +#include "Common/Core/RecoDecay.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + using namespace o2; using namespace o2::aod; using namespace o2::analysis; diff --git a/PWGHF/Tasks/taskLcCentrality.cxx b/PWGHF/Tasks/taskLcCentrality.cxx index 274421f8093..d866224d752 100644 --- a/PWGHF/Tasks/taskLcCentrality.cxx +++ b/PWGHF/Tasks/taskLcCentrality.cxx @@ -16,19 +16,28 @@ /// \author Luigi Dello Stritto , University and INFN SALERNO /// \author Vít Kučera , CERN -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" - -#include "Common/DataModel/Centrality.h" - +#include "PWGHF/Core/DecayChannels.h" #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "Common/Core/RecoDecay.h" +#include "Common/DataModel/Centrality.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + using namespace o2; using namespace o2::analysis; using namespace o2::framework; @@ -40,7 +49,7 @@ void customize(std::vector& workflowOptions) workflowOptions.push_back(optionDoMC); } -#include "Framework/runDataProcessing.h" +#include /// Λc± → p± K∓ π± analysis task struct HfTaskLcCentrality { diff --git a/PWGHF/Tasks/taskMcEfficiency.cxx b/PWGHF/Tasks/taskMcEfficiency.cxx index 410c3d67a8e..6d58957c664 100644 --- a/PWGHF/Tasks/taskMcEfficiency.cxx +++ b/PWGHF/Tasks/taskMcEfficiency.cxx @@ -14,25 +14,42 @@ /// /// \author Jan Fiete Grosse-Oetringhaus, CERN +#include "PWGHF/Core/HfHelper.h" +#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "PWGHF/DataModel/CandidateSelectionTables.h" + +#include "Common/Core/RecoDecay.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 "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "Framework/runDataProcessing.h" - -#include "Common/Core/RecoDecay.h" -#include "Common/DataModel/TrackSelectionTables.h" - -#include "PWGHF/Core/HfHelper.h" -#include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" - using namespace o2; using namespace o2::analysis; using namespace o2::constants::physics; @@ -299,7 +316,7 @@ struct HfTaskMcEfficiency { duplicates[hash]++; } /// end loop on pdg codes - } /// end loop over candidates + } /// end loop over candidates auto hDuplicateCount = registry.get(HIST("hDuplicateCount")); for (const auto& i : duplicates) { @@ -686,7 +703,7 @@ struct HfTaskMcEfficiency { } /// end "if(selected[...])" } /// end loop over MC particles - } /// end loop over PDG codes + } /// end loop over PDG codes } /// end candidate3ProngMcLoop diff --git a/PWGHF/Tasks/taskMcEfficiencyToXiPi.cxx b/PWGHF/Tasks/taskMcEfficiencyToXiPi.cxx index 01cac4a9028..fb70dda36d2 100644 --- a/PWGHF/Tasks/taskMcEfficiencyToXiPi.cxx +++ b/PWGHF/Tasks/taskMcEfficiencyToXiPi.cxx @@ -14,24 +14,31 @@ /// /// \author Federica Zanone, Heidelberg University -#include - -#include "TMCProcess.h" // for VMC Particle Production Process - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" +#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "PWGHF/DataModel/CandidateSelectionTables.h" #include "Common/Core/RecoDecay.h" +#include "Common/DataModel/EventSelection.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "PWGHF/Core/SelectorCuts.h" -#include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include // for VMC Particle Production Process +#include + +#include using namespace o2; -using namespace o2::analysis; using namespace o2::constants::physics; using namespace o2::framework; using namespace o2::framework::expressions; diff --git a/PWGHF/Tasks/taskMcGenPtRapShapes.cxx b/PWGHF/Tasks/taskMcGenPtRapShapes.cxx index e3e9deda1a9..01c795d0461 100644 --- a/PWGHF/Tasks/taskMcGenPtRapShapes.cxx +++ b/PWGHF/Tasks/taskMcGenPtRapShapes.cxx @@ -14,16 +14,26 @@ /// \author Fabrizio Grosa , CERN -#include -#include +#include "Common/Core/RecoDecay.h" -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" +#include +#include +#include +#include +#include +#include +#include +#include -#include "Common/Core/RecoDecay.h" +#include +#include + +#include +#include +#include +#include +#include +#include using namespace o2; using namespace o2::aod; diff --git a/PWGHF/Tasks/taskMcValidation.cxx b/PWGHF/Tasks/taskMcValidation.cxx index 269cd7b21ea..865a3a58d85 100644 --- a/PWGHF/Tasks/taskMcValidation.cxx +++ b/PWGHF/Tasks/taskMcValidation.cxx @@ -18,30 +18,56 @@ /// \author Fabrizio Grosa , CERN /// \author Fabio Catalano , CERN -#include -#include -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" -#include "Framework/RunningWorkflowInfo.h" -#include "Framework/StaticFor.h" - -#include "CCDB/BasicCCDBManager.h" -#include "Common/DataModel/CollisionAssociationTables.h" - -#include "PWGLF/DataModel/mcCentrality.h" - #include "PWGHF/Core/CentralityEstimation.h" -#include "PWGHF/Core/SelectorCuts.h" +#include "PWGHF/Core/DecayChannels.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" #include "PWGHF/Utils/utilsEvSelHf.h" +#include "PWGLF/DataModel/mcCentrality.h" + +#include "Common/Core/RecoDecay.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/CollisionAssociationTables.h" +#include "Common/DataModel/EventSelection.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 using namespace o2; -using namespace o2::analysis; using namespace o2::aod; using namespace o2::framework; using namespace o2::framework::expressions; diff --git a/PWGHF/Tasks/taskMultiplicityEstimatorCorrelation.cxx b/PWGHF/Tasks/taskMultiplicityEstimatorCorrelation.cxx index a7e0515eb2f..3e8537a47d1 100644 --- a/PWGHF/Tasks/taskMultiplicityEstimatorCorrelation.cxx +++ b/PWGHF/Tasks/taskMultiplicityEstimatorCorrelation.cxx @@ -14,16 +14,28 @@ /// /// \author Fabrizio Chinu , Università and INFN Torino +#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 "TPDGCode.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" -#include "Framework/StaticFor.h" -#include "Common/DataModel/Multiplicity.h" using namespace o2; using namespace o2::framework; diff --git a/PWGHF/Tasks/taskPidStudies.cxx b/PWGHF/Tasks/taskPidStudies.cxx index ad3943a7134..805266b76a9 100644 --- a/PWGHF/Tasks/taskPidStudies.cxx +++ b/PWGHF/Tasks/taskPidStudies.cxx @@ -17,26 +17,35 @@ /// \author Marcello Di Costanzo , Politecnico and INFN Torino /// \author Luca Aglietta , Università and INFN Torino -#include -#include - -#include "TPDGCode.h" - -#include "CCDB/BasicCCDBManager.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" -#include "Framework/HistogramRegistry.h" +#include "PWGHF/Core/CentralityEstimation.h" +#include "PWGHF/Utils/utilsEvSelHf.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" #include "Common/CCDB/ctpRateFetcher.h" -#include "Common/DataModel/PIDResponse.h" #include "Common/DataModel/Centrality.h" -#include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "PWGLF/DataModel/LFStrangenessTables.h" -#include "PWGLF/DataModel/LFStrangenessPIDTables.h" -#include "PWGHF/Utils/utilsEvSelHf.h" -#include "PWGHF/Core/CentralityEstimation.h" +#include "Common/DataModel/PIDResponseTOF.h" +#include "Common/DataModel/PIDResponseTPC.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include using namespace o2; using namespace o2::framework; diff --git a/PWGHF/Tasks/taskSelOptimisation.cxx b/PWGHF/Tasks/taskSelOptimisation.cxx index 8b701ea5a4c..d796a0c67b4 100644 --- a/PWGHF/Tasks/taskSelOptimisation.cxx +++ b/PWGHF/Tasks/taskSelOptimisation.cxx @@ -14,15 +14,30 @@ /// /// \author Fabrizio Grosa , CERN -#include -#include +#include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" +#include "Common/Core/RecoDecay.h" -#include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include using namespace o2; using namespace o2::framework; diff --git a/PWGHF/Utils/utilsBfieldCCDB.h b/PWGHF/Utils/utilsBfieldCCDB.h index 583e25fd01c..8d7166eca4a 100644 --- a/PWGHF/Utils/utilsBfieldCCDB.h +++ b/PWGHF/Utils/utilsBfieldCCDB.h @@ -16,14 +16,13 @@ #ifndef PWGHF_UTILS_UTILSBFIELDCCDB_H_ #define PWGHF_UTILS_UTILSBFIELDCCDB_H_ -#include - #include #include #include #include #include #include +#include #include // std::string diff --git a/PWGHF/Utils/utilsDerivedData.h b/PWGHF/Utils/utilsDerivedData.h index 23c08d3ac3c..044abed2f90 100644 --- a/PWGHF/Utils/utilsDerivedData.h +++ b/PWGHF/Utils/utilsDerivedData.h @@ -16,18 +16,17 @@ #ifndef PWGHF_UTILS_UTILSDERIVEDDATA_H_ #define PWGHF_UTILS_UTILSDERIVEDDATA_H_ -#include +#include "Common/Core/RecoDecay.h" -#include #include +#include #include +#include #include #include #include -#include "Common/Core/RecoDecay.h" - // Macro to store nSigma for prong _id_ with PID hypothesis _hyp_ in an array #define GET_N_SIGMA_PRONG(_array_, _candidate_, _id_, _hyp_) \ _array_[0] = _candidate_.nSigTpc##_hyp_##_id_(); \ diff --git a/PWGHF/Utils/utilsEvSelHf.h b/PWGHF/Utils/utilsEvSelHf.h index 4e649f7eddb..929d29e9e2e 100644 --- a/PWGHF/Utils/utilsEvSelHf.h +++ b/PWGHF/Utils/utilsEvSelHf.h @@ -19,6 +19,8 @@ #define PWGHF_UTILS_UTILSEVSELHF_H_ #include "PWGHF/Core/CentralityEstimation.h" +// +#include "PWGUD/Core/SGCutParHolder.h" #include "PWGUD/Core/SGSelector.h" #include "Common/CCDB/EventSelectionParams.h" @@ -31,12 +33,11 @@ #include #include #include +#include #include #include -#include - #include #include diff --git a/PWGHF/Utils/utilsMcGen.h b/PWGHF/Utils/utilsMcGen.h index 6c95b10b493..7c68e158925 100644 --- a/PWGHF/Utils/utilsMcGen.h +++ b/PWGHF/Utils/utilsMcGen.h @@ -24,12 +24,14 @@ #include "Common/Core/RecoDecay.h" #include +#include #include #include #include +#include #include #include diff --git a/PWGHF/Utils/utilsPid.h b/PWGHF/Utils/utilsPid.h index 3289e60c737..4590bb50b2c 100644 --- a/PWGHF/Utils/utilsPid.h +++ b/PWGHF/Utils/utilsPid.h @@ -17,13 +17,13 @@ #ifndef PWGHF_UTILS_UTILSPID_H_ #define PWGHF_UTILS_UTILSPID_H_ -#include - -#include - #include "Common/DataModel/PIDResponseTOF.h" #include "Common/DataModel/PIDResponseTPC.h" +#include + +#include + namespace o2::aod::pid_tpc_tof_utils { /// @brief Species of HF-candidate daughter tracks From cfd0ee34c025f762e6d4d66ebac2eddc5b31d0f3 Mon Sep 17 00:00:00 2001 From: Daiki Sekihata Date: Sat, 28 Jun 2025 18:30:37 +0200 Subject: [PATCH 258/871] [Common/TableProducer/PID] reduce dependency in pidTPCBase.cxx (#11824) --- Common/TableProducer/PID/pidTPCBase.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Common/TableProducer/PID/pidTPCBase.cxx b/Common/TableProducer/PID/pidTPCBase.cxx index e28f4a55b4d..1f9ef4278fc 100644 --- a/Common/TableProducer/PID/pidTPCBase.cxx +++ b/Common/TableProducer/PID/pidTPCBase.cxx @@ -171,7 +171,7 @@ struct DeDxCorrection { } PROCESS_SWITCH(DeDxCorrection, processRun3, "dEdx correction process", false); - void processDummy(ColEvSels const&) {} + void processDummy(aod::Collisions const&) {} PROCESS_SWITCH(DeDxCorrection, processDummy, "Do nothing", true); }; From 39c3366e02f7cc4798338cde5371a20413e76f2e Mon Sep 17 00:00:00 2001 From: Mattia Faggin Date: Sat, 28 Jun 2025 19:56:36 +0200 Subject: [PATCH 259/871] [PWGHF] reuse 3-prong gen. matching info in Sc creator. (#11818) Co-authored-by: Mattia Faggin --- .../candidateCreatorSigmac0plusplus.cxx | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/PWGHF/TableProducer/candidateCreatorSigmac0plusplus.cxx b/PWGHF/TableProducer/candidateCreatorSigmac0plusplus.cxx index bfcc42b733a..5767422b24f 100644 --- a/PWGHF/TableProducer/candidateCreatorSigmac0plusplus.cxx +++ b/PWGHF/TableProducer/candidateCreatorSigmac0plusplus.cxx @@ -417,7 +417,7 @@ struct HfCandidateSigmac0plusplusMc { using BCsInfo = soa::Join; using LambdacMc = soa::Join; - // using LambdacMcGen = soa::Join; + using McParticlesLcGenMatch = soa::Join; using McCollisionsNoCents = soa::Join; PresliceUnsorted colPerMcCollision = aod::mccollisionlabel::mcCollisionId; @@ -468,7 +468,7 @@ struct HfCandidateSigmac0plusplusMc { /// @param mcParticles table of generated particles void processMc(aod::McParticles const& mcParticles, aod::TracksWMc const& tracks, - LambdacMc const& candsLc /*, const LambdacMcGen&*/, + LambdacMc const& candsLc, McParticlesLcGenMatch const& mcParticlesLcGenMatch, McCollisionsNoCents const& collInfos, aod::McCollisions const&, BCsInfo const&) @@ -576,7 +576,7 @@ struct HfCandidateSigmac0plusplusMc { } /// end loop over reconstructed Σc0,++ candidates /// Match generated Σc0,++ candidates - for (const auto& particle : mcParticles) { + for (const auto& particle : mcParticlesLcGenMatch) { flag = 0; origin = 0; std::vector idxBhadMothers{}; @@ -603,26 +603,26 @@ struct HfCandidateSigmac0plusplusMc { /// → here we check level 1. first, and then levels 2. and 3. are inherited by the Λc+ → pK-π+ MC matching in candidateCreator3Prong.cxx /// look for Σc0,++(2455) - if (RecoDecay::isMatchedMCGen(mcParticles, particle, Pdg::kSigmaC0, std::array{static_cast(Pdg::kLambdaCPlus), static_cast(kPiMinus)}, true, &sign, 1)) { + if (RecoDecay::isMatchedMCGen(mcParticlesLcGenMatch, particle, Pdg::kSigmaC0, std::array{static_cast(Pdg::kLambdaCPlus), static_cast(kPiMinus)}, true, &sign, 1)) { // generated Σc0(2455) - for (const auto& daughter : particle.daughters_as()) { + for (const auto& daughter : particle.daughters_as()) { // look for Λc+ daughter decaying in pK-π+ if (std::abs(daughter.pdgCode()) != Pdg::kLambdaCPlus) continue; - if (RecoDecay::isMatchedMCGen(mcParticles, daughter, Pdg::kLambdaCPlus, std::array{+kProton, -kKPlus, +kPiPlus}, true, &sign, 2)) { + if (std::abs(daughter.flagMcMatchGen()) == o2::hf_decay::hf_cand_3prong::DecayChannelMain::LcToPKPi) { /// Λc+ daughter decaying in pK-π+ found! flag = sign * BIT(aod::hf_cand_sigmac::DecayType::Sc0ToPKPiPi); particleAntiparticle = isParticleAntiparticle(particle, Pdg::kSigmaC0); break; } } - } else if (RecoDecay::isMatchedMCGen(mcParticles, particle, Pdg::kSigmaCPlusPlus, std::array{static_cast(Pdg::kLambdaCPlus), static_cast(kPiPlus)}, true, &sign, 1)) { + } else if (RecoDecay::isMatchedMCGen(mcParticlesLcGenMatch, particle, Pdg::kSigmaCPlusPlus, std::array{static_cast(Pdg::kLambdaCPlus), static_cast(kPiPlus)}, true, &sign, 1)) { // generated Σc++(2455) - for (const auto& daughter : particle.daughters_as()) { + for (const auto& daughter : particle.daughters_as()) { // look for Λc+ daughter decaying in pK-π+ if (std::abs(daughter.pdgCode()) != Pdg::kLambdaCPlus) continue; - if (RecoDecay::isMatchedMCGen(mcParticles, daughter, Pdg::kLambdaCPlus, std::array{+kProton, -kKPlus, +kPiPlus}, true, &sign, 2)) { + if (std::abs(daughter.flagMcMatchGen()) == o2::hf_decay::hf_cand_3prong::DecayChannelMain::LcToPKPi) { /// Λc+ daughter decaying in pK-π+ found! flag = sign * BIT(aod::hf_cand_sigmac::DecayType::ScplusplusToPKPiPi); particleAntiparticle = isParticleAntiparticle(particle, Pdg::kSigmaCPlusPlus); @@ -633,26 +633,26 @@ struct HfCandidateSigmac0plusplusMc { /// look for Σc0,++(2520) if (flag == 0) { - if (RecoDecay::isMatchedMCGen(mcParticles, particle, Pdg::kSigmaCStar0, std::array{static_cast(Pdg::kLambdaCPlus), static_cast(kPiMinus)}, true, &sign, 1)) { + if (RecoDecay::isMatchedMCGen(mcParticlesLcGenMatch, particle, Pdg::kSigmaCStar0, std::array{static_cast(Pdg::kLambdaCPlus), static_cast(kPiMinus)}, true, &sign, 1)) { // generated Σc0(2520) - for (const auto& daughter : particle.daughters_as()) { + for (const auto& daughter : particle.daughters_as()) { // look for Λc+ daughter decaying in pK-π+ if (std::abs(daughter.pdgCode()) != Pdg::kLambdaCPlus) continue; - if (RecoDecay::isMatchedMCGen(mcParticles, daughter, Pdg::kLambdaCPlus, std::array{+kProton, -kKPlus, +kPiPlus}, true, &sign, 2)) { + if (std::abs(daughter.flagMcMatchGen()) == o2::hf_decay::hf_cand_3prong::DecayChannelMain::LcToPKPi) { /// Λc+ daughter decaying in pK-π+ found! flag = sign * BIT(aod::hf_cand_sigmac::DecayType::ScStar0ToPKPiPi); particleAntiparticle = isParticleAntiparticle(particle, Pdg::kSigmaCStar0); break; } } - } else if (RecoDecay::isMatchedMCGen(mcParticles, particle, Pdg::kSigmaCStarPlusPlus, std::array{static_cast(Pdg::kLambdaCPlus), static_cast(kPiPlus)}, true, &sign, 1)) { + } else if (RecoDecay::isMatchedMCGen(mcParticlesLcGenMatch, particle, Pdg::kSigmaCStarPlusPlus, std::array{static_cast(Pdg::kLambdaCPlus), static_cast(kPiPlus)}, true, &sign, 1)) { // generated Σc++(2520) - for (const auto& daughter : particle.daughters_as()) { + for (const auto& daughter : particle.daughters_as()) { // look for Λc+ daughter decaying in pK-π+ if (std::abs(daughter.pdgCode()) != Pdg::kLambdaCPlus) continue; - if (RecoDecay::isMatchedMCGen(mcParticles, daughter, Pdg::kLambdaCPlus, std::array{+kProton, -kKPlus, +kPiPlus}, true, &sign, 2)) { + if (std::abs(daughter.flagMcMatchGen()) == o2::hf_decay::hf_cand_3prong::DecayChannelMain::LcToPKPi) { /// Λc+ daughter decaying in pK-π+ found! flag = sign * BIT(aod::hf_cand_sigmac::DecayType::ScStarPlusPlusToPKPiPi); particleAntiparticle = isParticleAntiparticle(particle, Pdg::kSigmaCStarPlusPlus); @@ -664,7 +664,7 @@ struct HfCandidateSigmac0plusplusMc { /// check the origin (prompt vs. non-prompt) if (flag != 0) { - origin = RecoDecay::getCharmHadronOrigin(mcParticles, particle, false, &idxBhadMothers); + origin = RecoDecay::getCharmHadronOrigin(mcParticlesLcGenMatch, particle, false, &idxBhadMothers); } /// fill the table with results of generation level MC matching if (origin == RecoDecay::OriginType::NonPrompt) { From b5842b615e85162f8c9540e7330f37cfd172fdbd Mon Sep 17 00:00:00 2001 From: Yash Patley <52608802+yashpatley@users.noreply.github.com> Date: Sat, 28 Jun 2025 23:47:40 +0530 Subject: [PATCH 260/871] [PWGCF] Update lambdaR2Correlation.cxx (#11825) --- .../Tasks/lambdaR2Correlation.cxx | 73 ++++++++++++++----- 1 file changed, 53 insertions(+), 20 deletions(-) diff --git a/PWGCF/TwoParticleCorrelations/Tasks/lambdaR2Correlation.cxx b/PWGCF/TwoParticleCorrelations/Tasks/lambdaR2Correlation.cxx index 7c9bbc6ad67..3dd5ec474de 100644 --- a/PWGCF/TwoParticleCorrelations/Tasks/lambdaR2Correlation.cxx +++ b/PWGCF/TwoParticleCorrelations/Tasks/lambdaR2Correlation.cxx @@ -13,22 +13,25 @@ /// \brief R2 correlation of Lambda baryons. /// \author Yash Patley -#include -#include +#include "PWGLF/DataModel/LFStrangenessTables.h" -#include "Common/DataModel/PIDResponse.h" +#include "Common/Core/RecoDecay.h" #include "Common/DataModel/Centrality.h" +#include "Common/DataModel/CollisionAssociationTables.h" #include "Common/DataModel/EventSelection.h" -#include "Framework/AnalysisTask.h" +#include "Common/DataModel/PIDResponse.h" + +#include "CCDB/BasicCCDBManager.h" +#include "CommonConstants/PhysicsConstants.h" #include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisTask.h" #include "Framework/runDataProcessing.h" -#include "PWGLF/DataModel/LFStrangenessTables.h" -#include "PWGLF/DataModel/mcCentrality.h" -#include "CommonConstants/PhysicsConstants.h" -#include "Common/Core/RecoDecay.h" -#include "CCDB/BasicCCDBManager.h" + #include "TPDGCode.h" +#include +#include + using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; @@ -152,8 +155,8 @@ enum TrackLabels { kPassV0KinCuts, kPassV0TopoSel, kAllSelPassed, - kNotPrimaryLambda, - kNotSecondaryLambda, + kPrimaryLambda, + kSecondaryLambda, kLambdaDauNotMcParticle, kLambdaNotPrPiMinus, kAntiLambdaNotAntiPrPiPlus, @@ -242,14 +245,15 @@ struct LambdaTableProducer { Configurable cIsGoodITSLayers{"cIsGoodITSLayers", false, "Good ITS Layers All"}; // Tracks - Configurable cTrackMinPt{"cTrackMinPt", 0.16, "p_{T} minimum"}; - Configurable cTrackMaxPt{"cTrackMaxPt", 999.0, "p_{T} minimum"}; + Configurable cTrackMinPt{"cTrackMinPt", 0.15, "p_{T} minimum"}; + Configurable cTrackMaxPt{"cTrackMaxPt", 999.0, "p_{T} maximum"}; Configurable cTrackEtaCut{"cTrackEtaCut", 0.8, "Pseudorapidity cut"}; - Configurable cMinTpcCrossedRows{"cMinTpcCrossedRows", 80, "TPC Min Crossed Rows"}; + Configurable cMinTpcCrossedRows{"cMinTpcCrossedRows", 70, "TPC Min Crossed Rows"}; Configurable cMinTpcCROverCls{"cMinTpcCROverCls", 0.8, "Tpc Min Crossed Rows Over Findable Clusters"}; Configurable cMaxTpcSharedClusters{"cMaxTpcSharedClusters", 0.4, "Tpc Max Shared Clusters"}; Configurable cMaxChi2Tpc{"cMaxChi2Tpc", 4, "Max Chi2 Tpc"}; - Configurable cTpcNsigmaCut{"cTpcNsigmaCut", 5.0, "TPC NSigma Selection Cut"}; + Configurable cTpcNsigmaCut{"cTpcNsigmaCut", 3.0, "TPC NSigma Selection Cut"}; + Configurable cRemoveAmbiguousTracks{"cRemoveAmbiguousTracks", false, "Remove Ambiguous Tracks"}; // V0s Configurable cMinDcaProtonToPV{"cMinDcaProtonToPV", 0.02, "Minimum Proton DCAr to PV"}; @@ -436,8 +440,8 @@ struct LambdaTableProducer { 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::kNotPrimaryLambda, "kNotPrimaryLambda"); - histos.get(HIST("Tracks/h1f_tracks_info"))->GetXaxis()->SetBinLabel(TrackLabels::kNotSecondaryLambda, "kNotSecondaryLambda"); + 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"); @@ -736,6 +740,30 @@ struct LambdaTableProducer { return true; } + template + bool hasAmbiguousDaughters(V const& v0, T const&) + { + 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; + } + + // 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; + } + + // Pass as not ambiguous + return false; + } + template PrmScdType isPrimaryV0(V const& v0) { @@ -743,12 +771,12 @@ struct LambdaTableProducer { // check for secondary lambda if (!mcpart.isPhysicalPrimary()) { - histos.fill(HIST("Tracks/h1f_tracks_info"), kNotPrimaryLambda); + histos.fill(HIST("Tracks/h1f_tracks_info"), kSecondaryLambda); bSecondaryLambdaFlag = true; return kSecondary; } - histos.fill(HIST("Tracks/h1f_tracks_info"), kNotSecondaryLambda); + histos.fill(HIST("Tracks/h1f_tracks_info"), kPrimaryLambda); return kPrimary; } @@ -977,6 +1005,11 @@ struct LambdaTableProducer { // we have v0 as lambda histos.fill(HIST("Tracks/h1f_tracks_info"), kAllSelPassed); + // Remove lambda with ambiguous daughters + if (cRemoveAmbiguousTracks && hasAmbiguousDaughters(v0, tracks)) { + continue; + } + // Get Lambda mass and kinematic variables mass = (v0Type == kLambda) ? v0.mLambda() : v0.mAntiLambda(); pt = v0.pt(); @@ -1172,7 +1205,7 @@ struct LambdaTableProducer { using CollisionsRun3 = soa::Join; using CollisionsRun2 = soa::Join; - using Tracks = soa::Join; + using Tracks = soa::Join; using McV0Tracks = soa::Join; using TracksMC = soa::Join; From 6a8fb3218e74b48448e1f451c19df0456cb3483f Mon Sep 17 00:00:00 2001 From: Francesco Mazzaschi <43742195+fmazzasc@users.noreply.github.com> Date: Sun, 29 Jun 2025 09:18:29 +0200 Subject: [PATCH 261/871] [PWGLF] Fix MC for lambda1405 + add pi dau DCA cut (#11817) Co-authored-by: Francesco Mazzaschi --- PWGLF/Tasks/Resonances/lambda1405analysis.cxx | 21 ++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/PWGLF/Tasks/Resonances/lambda1405analysis.cxx b/PWGLF/Tasks/Resonances/lambda1405analysis.cxx index 205503c4438..602df2bac11 100644 --- a/PWGLF/Tasks/Resonances/lambda1405analysis.cxx +++ b/PWGLF/Tasks/Resonances/lambda1405analysis.cxx @@ -53,13 +53,18 @@ struct lambda1405analysis { // 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, "DCA to primary vertex for Sigma candidates (cm)"}; + 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 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 cutNSigmaPi{"cutNSigmaPi", 3, "NSigmaTPCPion"}; + Preslice mKinkPerCol = aod::track::collisionId; + Preslice mPerColTracks = aod::track::collisionId; + void init(InitContext const&) { // Axes @@ -108,7 +113,7 @@ struct lambda1405analysis { return false; } float sigmaRad = std::hypot(sigmaCand.xDecVtx(), sigmaCand.yDecVtx()); - if (sigmaCand.dcaMothPv() > cutDCAtoPVSigma || sigmaRad < cutSigmaRadius) { + if (std::abs(sigmaCand.dcaMothPv()) > cutDCAtoPVSigma || std::abs(sigmaCand.dcaDaugPv()) < cutDCAtoPVPiFromSigma || sigmaRad < cutSigmaRadius) { return false; } rLambda1405.fill(HIST("h2PtMassSigmaBeforeCuts"), sigmaCand.mothSign() * sigmaCand.ptMoth(), sigmaCand.mSigmaMinus()); @@ -138,13 +143,13 @@ struct lambda1405analysis { return false; // No valid pion track found } - void processData(CollisionsFull::iterator const& collision, aod::KinkCands const& KinkCands, TracksFull const& tracks) + void processData(CollisionsFull::iterator const& collision, aod::KinkCands const& kinkCands, TracksFull const& tracks) { if (std::abs(collision.posZ()) > cutzvertex || !collision.sel8()) { return; } rEventSelection.fill(HIST("hVertexZRec"), collision.posZ()); - for (const auto& sigmaCand : KinkCands) { + for (const auto& sigmaCand : kinkCands) { if (selectCandidate(sigmaCand, tracks)) { rLambda1405.fill(HIST("h2PtMass"), lambda1405Cand.sigmaSign * lambda1405Cand.pt, lambda1405Cand.mass); rLambda1405.fill(HIST("h2PtMassSigma"), lambda1405Cand.sigmaSign * lambda1405Cand.sigmaPt, lambda1405Cand.sigmaMass); @@ -155,15 +160,17 @@ struct lambda1405analysis { } 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 processMC(CollisionsFullMC const& collisions, aod::KinkCands const& kinkCands, aod::McTrackLabels const& trackLabelsMC, aod::McParticles const& particlesMC, TracksFull const& tracks) { for (const auto& collision : collisions) { if (std::abs(collision.posZ()) > cutzvertex || !collision.sel8()) { continue; } rEventSelection.fill(HIST("hVertexZRec"), collision.posZ()); - for (const auto& sigmaCand : KinkCands) { - if (selectCandidate(sigmaCand, tracks)) { + auto sigmaCandsPerCol = kinkCands.sliceBy(mKinkPerCol, collision.globalIndex()); + auto tracksPerCol = tracks.sliceBy(mPerColTracks, collision.globalIndex()); + for (const auto& sigmaCand : sigmaCandsPerCol) { + if (selectCandidate(sigmaCand, tracksPerCol)) { // Do MC association auto mcLabPiKink = trackLabelsMC.rawIteratorAt(lambda1405Cand.piFromSigmaID); auto mcLabSigma = trackLabelsMC.rawIteratorAt(lambda1405Cand.sigmaID); From a66c5fbbd04e02748843388915c2296d869c033f Mon Sep 17 00:00:00 2001 From: alcaliva <32872606+alcaliva@users.noreply.github.com> Date: Sun, 29 Jun 2025 13:10:46 +0200 Subject: [PATCH 262/871] [PWGLF] moved histogram from QC to main analysis + added jetPt spectrum (#11826) --- PWGLF/Tasks/Nuspex/antinucleiInJets.cxx | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/PWGLF/Tasks/Nuspex/antinucleiInJets.cxx b/PWGLF/Tasks/Nuspex/antinucleiInJets.cxx index 9b3495484e0..b4509b40f28 100644 --- a/PWGLF/Tasks/Nuspex/antinucleiInJets.cxx +++ b/PWGLF/Tasks/Nuspex/antinucleiInJets.cxx @@ -178,7 +178,6 @@ struct AntinucleiInJets { registryQC.add("nJetsFound", "nJetsFound", HistType::kTH1F, {{50, 0, 50, "#it{n}_{Jet}"}}); registryQC.add("nJetsInAcceptance", "nJetsInAcceptance", HistType::kTH1F, {{50, 0, 50, "#it{n}_{Jet}"}}); registryQC.add("nJetsSelectedHighPt", "nJetsSelectedHighPt", HistType::kTH1F, {{50, 0, 50, "#it{n}_{Jet}"}}); - registryQC.add("jetEffectiveArea", "jetEffectiveArea", HistType::kTH1F, {{2000, 0, 2, "Area/#piR^{2}"}}); registryQC.add("jetPtDifference", "jetPtDifference", HistType::kTH1F, {{200, -1, 1, "#Deltap_{T}^{jet}"}}); } @@ -194,6 +193,10 @@ struct AntinucleiInJets { registryData.add("number_of_events_data", "number of events in data", HistType::kTH1F, {{10, 0, 10, "counter"}}); registryData.add("number_of_rejected_events", "check on number of events rejected", HistType::kTH1F, {{10, 0, 10, "counter"}}); + // Jet Area + registryData.add("jetEffectiveArea", "jetEffectiveArea", HistType::kTH1F, {{2000, 0, 2, "Area/#piR^{2}"}}); + registryData.add("ptDistributionJet", "ptDistributionJet", HistType::kTH1F, {{2000, 0, 200, "#it{p}_{T} (GeV/#it{c})"}}); + // antiprotons registryData.add("antiproton_jet_tpc", "antiproton_jet_tpc", HistType::kTH2F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}, {400, -20.0, 20.0, "n#sigma_{TPC}"}}); registryData.add("antiproton_jet_tof", "antiproton_jet_tof", HistType::kTH2F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}, {400, -20.0, 20.0, "n#sigma_{TOF}"}}); @@ -612,6 +615,8 @@ struct AntinucleiInJets { auto jetForSub = jet; fastjet::PseudoJet jetMinusBkg = backgroundSub.doRhoAreaSub(jetForSub, rhoPerp, rhoMPerp); // if (getCorrectedPt(jetMinusBkg.pt(), responseMatrix) < minJetPt) + registryData.fill(HIST("ptDistributionJet"), jet.pt()); + if (jetMinusBkg.pt() < minJetPt) continue; isAtLeastOneJetSelected = true; @@ -624,6 +629,9 @@ struct AntinucleiInJets { getPerpendicularAxis(jetAxis, ueAxis1, +1); getPerpendicularAxis(jetAxis, ueAxis2, -1); + // Jet Area + registryData.fill(HIST("jetEffectiveArea"), jet.area() / (PI * rJet * rJet)); + // get jet constituents std::vector jetConstituents = jet.constituents(); o2::aod::ITSResponse itsResponse; @@ -906,7 +914,6 @@ struct AntinucleiInJets { getPerpendicularAxis(jetAxis, ueAxis1, +1); getPerpendicularAxis(jetAxis, ueAxis2, -1); - registryQC.fill(HIST("jetEffectiveArea"), jet.area() / (PI * rJet * rJet)); registryQC.fill(HIST("NchJetCone"), static_cast(jetConstituents.size())); // loop over jet constituents From acaaf0566f2e0d1cfdde478a4d0c6bdfc9e8a91e Mon Sep 17 00:00:00 2001 From: mcoquet642 <74600025+mcoquet642@users.noreply.github.com> Date: Sun, 29 Jun 2025 19:31:53 +0200 Subject: [PATCH 263/871] [PWGDQ] Fix for event-selected MCsignal in processMCGen (#11801) Co-authored-by: Maurice Coquet --- PWGDQ/Tasks/dqEfficiency_withAssoc.cxx | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/PWGDQ/Tasks/dqEfficiency_withAssoc.cxx b/PWGDQ/Tasks/dqEfficiency_withAssoc.cxx index a033e9a2032..e2a58ff5bf2 100644 --- a/PWGDQ/Tasks/dqEfficiency_withAssoc.cxx +++ b/PWGDQ/Tasks/dqEfficiency_withAssoc.cxx @@ -2159,11 +2159,16 @@ struct AnalysisSameEventPairing { continue; } - auto groupedMCTracks = mcTracks.sliceBy(perReducedMcGenEvent, event.reducedMCeventId()); - groupedMCTracks.bindInternalIndicesTo(&mcTracks); - for (auto& track : groupedMCTracks) { + // auto groupedMCTracks = mcTracks.sliceBy(perReducedMcGenEvent, event.reducedMCeventId()); + // groupedMCTracks.bindInternalIndicesTo(&mcTracks); + // for (auto& track : groupedMCTracks) { + for (auto& track : mcTracks) { + if (track.reducedMCeventId() != event.reducedMCeventId()) { + continue; + } VarManager::FillTrackMC(mcTracks, track); - auto track_raw = groupedMCTracks.rawIteratorAt(track.globalIndex()); + auto track_raw = mcTracks.rawIteratorAt(track.globalIndex()); + // auto track_raw = groupedMCTracks.rawIteratorAt(track.globalIndex()); for (auto& sig : fGenMCSignals) { if (sig->CheckSignal(true, track_raw)) { fHistMan->FillHistClass(Form("MCTruthGenSel_%s", sig->GetName()), VarManager::fgValues); From 81cfc2302406d95b5a30eb361cb9db896367e470 Mon Sep 17 00:00:00 2001 From: ddobrigk Date: Sun, 29 Jun 2025 21:34:01 +0200 Subject: [PATCH 264/871] [Common] Fuse new evsel with timestamp (#11827) Co-authored-by: ALICE Builder --- Common/TableProducer/CMakeLists.txt | 5 + .../TableProducer/eventSelectionService.cxx | 34 ++-- Common/TableProducer/timestampTester.cxx | 72 +++++++++ Common/Tools/EventSelectionTools.h | 54 ++++--- Common/Tools/timestampModule.h | 147 ++++++++++++++++++ 5 files changed, 277 insertions(+), 35 deletions(-) create mode 100644 Common/TableProducer/timestampTester.cxx create mode 100644 Common/Tools/timestampModule.h diff --git a/Common/TableProducer/CMakeLists.txt b/Common/TableProducer/CMakeLists.txt index 867fbffe856..cdd408d4bff 100644 --- a/Common/TableProducer/CMakeLists.txt +++ b/Common/TableProducer/CMakeLists.txt @@ -59,6 +59,11 @@ o2physics_add_dpl_workflow(timestamp PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(timestamptester + SOURCES timestampTester.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(weak-decay-indices SOURCES weakDecayIndices.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore diff --git a/Common/TableProducer/eventSelectionService.cxx b/Common/TableProducer/eventSelectionService.cxx index 996317e1ab3..35f17d531ab 100644 --- a/Common/TableProducer/eventSelectionService.cxx +++ b/Common/TableProducer/eventSelectionService.cxx @@ -24,6 +24,7 @@ #include "Common/Core/trackUtilities.h" #include "Common/DataModel/TrackSelectionTables.h" #include "Common/Tools/EventSelectionTools.h" +#include "Common/Tools/timestampModule.h" #include "CCDB/BasicCCDBManager.h" #include "CCDB/CcdbApi.h" @@ -45,18 +46,22 @@ using namespace o2::framework; MetadataHelper metadataInfo; // Metadata helper -using BCsWithRun2InfosTimestampsAndMatches = soa::Join; -using BCsWithRun3Matchings = soa::Join; +using BCsWithRun2InfosAndMatches = soa::Join; +using BCsWithRun3Matchings = soa::Join; using FullTracks = soa::Join; using FullTracksIU = soa::Join; struct eventselectionRun2 { + o2::common::timestamp::timestampConfigurables timestampConfigurables; + o2::common::timestamp::TimestampModule timestampMod; + o2::common::eventselection::bcselConfigurables bcselOpts; o2::common::eventselection::BcSelectionModule bcselmodule; o2::common::eventselection::evselConfigurables evselOpts; o2::common::eventselection::EventSelectionModule evselmodule; + Produces timestampTable; /// Table with SOR timestamps produced by the task Produces bcsel; Produces evsel; @@ -69,8 +74,8 @@ struct eventselectionRun2 { HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; - // the best: have readable cursors - // this: a stopgap solution to avoid spawning yet another device + // buffering intermediate results for passing + std::vector timestamps; std::vector bcselsbuffer; // auxiliary @@ -85,11 +90,12 @@ struct eventselectionRun2 { ccdb->setURL(ccdburl.value); // task-specific + timestampMod.init(timestampConfigurables, metadataInfo); bcselmodule.init(context, bcselOpts, histos); evselmodule.init(context, evselOpts, histos, metadataInfo); } - void process(BCsWithRun2InfosTimestampsAndMatches const& bcs, + void process(BCsWithRun2InfosAndMatches const& bcs, aod::Collisions const& collisions, aod::Zdcs const&, aod::FV0As const&, @@ -98,12 +104,16 @@ struct eventselectionRun2 { aod::FDDs const&, FullTracks const&) { - bcselmodule.processRun2(ccdb, bcs, bcselsbuffer, bcsel); - evselmodule.processRun2(ccdb, histos, collisions, tracklets, cache, bcselsbuffer, evsel); + timestampMod.process(bcs, ccdb, timestamps, timestampTable); + bcselmodule.processRun2(ccdb, bcs, timestamps, bcselsbuffer, bcsel); + evselmodule.processRun2(ccdb, histos, collisions, tracklets, cache, timestamps, bcselsbuffer, evsel); } }; struct eventselectionRun3 { + o2::common::timestamp::timestampConfigurables timestampConfigurables; + o2::common::timestamp::TimestampModule timestampMod; + o2::common::eventselection::bcselConfigurables bcselOpts; o2::common::eventselection::BcSelectionModule bcselmodule; @@ -113,6 +123,7 @@ struct eventselectionRun3 { o2::common::eventselection::lumiConfigurables lumiOpts; o2::common::eventselection::LumiModule lumimodule; + Produces timestampTable; /// Table with SOR timestamps produced by the task Produces bcsel; Produces evsel; @@ -127,6 +138,7 @@ struct eventselectionRun3 { // the best: have readable cursors // this: a stopgap solution to avoid spawning yet another device + std::vector timestamps; std::vector bcselsbuffer; // auxiliary @@ -141,6 +153,7 @@ struct eventselectionRun3 { ccdb->setURL(ccdburl.value); // task-specific + timestampMod.init(timestampConfigurables, metadataInfo); bcselmodule.init(context, bcselOpts, histos); evselmodule.init(context, evselOpts, histos, metadataInfo); lumimodule.init(context, lumiOpts, histos); @@ -154,9 +167,10 @@ struct eventselectionRun3 { aod::FDDs const&, FullTracksIU const&) { - bcselmodule.processRun3(ccdb, histos, bcs, bcselsbuffer, bcsel); - evselmodule.processRun3(ccdb, histos, bcs, collisions, pvTracks, ft0s, cache, bcselsbuffer, evsel); - lumimodule.process(ccdb, histos, bcs, bcselsbuffer); + timestampMod.process(bcs, ccdb, timestamps, timestampTable); + bcselmodule.processRun3(ccdb, histos, bcs, timestamps, bcselsbuffer, bcsel); + evselmodule.processRun3(ccdb, histos, bcs, collisions, pvTracks, ft0s, cache, timestamps, bcselsbuffer, evsel); + lumimodule.process(ccdb, histos, bcs, timestamps, bcselsbuffer); } }; diff --git a/Common/TableProducer/timestampTester.cxx b/Common/TableProducer/timestampTester.cxx new file mode 100644 index 00000000000..6a7f829e950 --- /dev/null +++ b/Common/TableProducer/timestampTester.cxx @@ -0,0 +1,72 @@ +// 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 timestamp.cxx +/// \author Nicolò Jacazio +/// \since 2020-06-22 +/// \brief A task to fill the timestamp table from run number. +/// Uses headers from CCDB +/// +#include "MetadataHelper.h" + +#include "Common/Tools/timestampModule.h" + +#include "CCDB/BasicCCDBManager.h" +#include "CommonDataFormat/InteractionRecord.h" +#include "DetectorsRaw/HBFUtils.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" + +#include +#include + +using namespace o2::framework; +using namespace o2::header; +using namespace o2; + +MetadataHelper metadataInfo; // Metadata helper + +struct TimestampTask { + Produces timestampTable; /// Table with SOR timestamps produced by the task + Service ccdb; /// CCDB manager to access orbit-reset timestamp + o2::ccdb::CcdbApi ccdb_api; /// API to access CCDB headers + + Configurable ccdb_url{"ccdb-url", "http://alice-ccdb.cern.ch", "URL of the CCDB database"}; + + o2::common::timestamp::timestampConfigurables timestampConfigurables; + o2::common::timestamp::TimestampModule timestampMod; + + std::vector timestampBuffer; + + void init(o2::framework::InitContext&) + { + // CCDB initialization + ccdb->setURL(ccdb_url.value); + ccdb_api.init(ccdb_url.value); + + // timestamp configuration + init + timestampMod.init(timestampConfigurables, metadataInfo); + } + + void process(aod::BCs const& bcs) + { + timestampMod.process(bcs, ccdb, timestampBuffer, timestampTable); + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + // Parse the metadata + metadataInfo.initMetadata(cfgc); + + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} diff --git a/Common/Tools/EventSelectionTools.h b/Common/Tools/EventSelectionTools.h index e7822a61556..c04b2f51b62 100644 --- a/Common/Tools/EventSelectionTools.h +++ b/Common/Tools/EventSelectionTools.h @@ -264,8 +264,8 @@ class BcSelectionModule } //__________________________________________________ - template - void processRun2(TCCDB const& ccdb, TBCs const& bcs, TBcSelBuffer& bcselbuffer, TBcSelCursor& bcsel) + template + void processRun2(TCCDB const& ccdb, TBCs const& bcs, TTimestamps const& timestamps, TBcSelBuffer& bcselbuffer, TBcSelCursor& bcsel) { if (bcselOpts.amIneeded.value == 0) { bcselbuffer.clear(); @@ -273,8 +273,9 @@ class BcSelectionModule } bcselbuffer.clear(); for (const auto& bc : bcs) { - par = ccdb->template getForTimeStamp("EventSelection/EventSelectionParams", bc.timestamp()); - aliases = ccdb->template getForTimeStamp("EventSelection/TriggerAliases", bc.timestamp()); + uint64_t timestamp = timestamps[bc.globalIndex()]; + par = ccdb->template getForTimeStamp("EventSelection/EventSelectionParams", timestamp); + aliases = ccdb->template getForTimeStamp("EventSelection/TriggerAliases", timestamp); // fill fired aliases uint32_t alias{0}; uint64_t triggerMask = bc.triggerMask(); @@ -401,8 +402,8 @@ class BcSelectionModule } // end processRun2 //__________________________________________________ - template - void processRun3(TCCDB const& ccdb, THistoRegistry& histos, TBCs const& bcs, TBcSelBuffer& bcselbuffer, TBcSelCursor& bcsel) + template + void processRun3(TCCDB const& ccdb, THistoRegistry& histos, TBCs const& bcs, TTimestamps const& timestamps, TBcSelBuffer& bcselbuffer, TBcSelCursor& bcsel) { if (bcselOpts.amIneeded.value == 0) { bcselbuffer.clear(); @@ -426,15 +427,16 @@ class BcSelectionModule // bc loop for (auto bc : bcs) { // o2-linter: disable=const-ref-in-for-loop (use bc as nonconst iterator) + uint64_t timestamp = timestamps[bc.globalIndex()]; // store rct flags uint32_t rct = lastRCT; int64_t thisTF = (bc.globalBC() - bcSOR) / nBCsPerTF; if (mapRCT != nullptr && thisTF != lastTF) { // skip for unanchored runs; do it once per TF - auto itrct = mapRCT->upper_bound(bc.timestamp()); + auto itrct = mapRCT->upper_bound(timestamp); if (itrct != mapRCT->begin()) itrct--; rct = itrct->second; - LOGP(debug, "sor={} eor={} ts={} rct={}", sorTimestamp, eorTimestamp, bc.timestamp(), rct); + LOGP(debug, "sor={} eor={} ts={} rct={}", sorTimestamp, eorTimestamp, timestamp, rct); lastRCT = rct; lastTF = thisTF; } @@ -560,10 +562,10 @@ class BcSelectionModule LOGP(debug, "foundFT0={}", foundFT0); const char* srun = Form("%d", run); - if (bc.timestamp() < sorTimestamp || bc.timestamp() > eorTimestamp) { + if (timestamp < sorTimestamp || timestamp > eorTimestamp) { histos.template get(HIST("bcselection/hCounterInvalidBCTimestamp"))->Fill(srun, 1); if (bcselOpts.confCheckRunDurationLimits.value) { - LOGF(warn, "Invalid BC timestamp: %d, run: %d, sor: %d, eor: %d", bc.timestamp(), run, sorTimestamp, eorTimestamp); + LOGF(warn, "Invalid BC timestamp: %d, run: %d, sor: %d, eor: %d", timestamp, run, sorTimestamp, eorTimestamp); alias = 0u; selection = 0u; } @@ -692,8 +694,8 @@ class EventSelectionModule } //__________________________________________________ - template - bool configure(TCCDB& ccdb, TBCs const& bcs) + template + bool configure(TCCDB& ccdb, TTimestamps const& timestamps, TBCs const& bcs) { int run = bcs.iteratorAt(0).runNumber(); // extract bc pattern from CCDB for data or anchored MC only @@ -705,7 +707,8 @@ class EventSelectionModule // duration of TF in bcs nBCsPerTF = evselOpts.confNumberOfOrbitsPerTF < 0 ? runInfo.orbitsPerTF * nBCsPerOrbit : evselOpts.confNumberOfOrbitsPerTF * nBCsPerOrbit; // colliding bc pattern - int64_t ts = bcs.iteratorAt(0).timestamp(); + int64_t ts = timestamps[0]; + // getForTimeStamp replaced with getSpecific to set metadata to zero // avoids crash related to specific run number auto grplhcif = ccdb->template getSpecific("GLO/Config/GRPLHCIF", ts); @@ -721,15 +724,16 @@ class EventSelectionModule } //__________________________________________________ - template - void processRun2(TCCDB const& ccdb, THistoRegistry& histos, TCollisions const& collisions, TTracklets const& tracklets, TSlicecache& cache, TBcSelBuffer const& bcselbuffer, TEvselCursor& evsel) + template + void processRun2(TCCDB const& ccdb, THistoRegistry& histos, TCollisions const& collisions, TTracklets const& tracklets, TSlicecache& cache, TTimestamps const& timestamps, TBcSelBuffer const& bcselbuffer, TEvselCursor& evsel) { if (evselOpts.amIneeded.value == 0) { return; // dummy process } for (const auto& col : collisions) { auto bc = col.template bc_as>(); - EventSelectionParams* par = ccdb->template getForTimeStamp("EventSelection/EventSelectionParams", bc.timestamp()); + uint64_t timestamp = timestamps[bc.globalIndex()]; + EventSelectionParams* par = ccdb->template getForTimeStamp("EventSelection/EventSelectionParams", timestamp); bool* applySelection = par->getSelection(evselOpts.muonSelection); if (evselOpts.isMC == 1) { applySelection[aod::evsel::kIsBBZAC] = 0; @@ -802,13 +806,13 @@ class EventSelectionModule } // end processRun2 //__________________________________________________ - template - void processRun3(TCCDB const& ccdb, THistoRegistry& histos, TBCs const& bcs, TCollisions const& cols, TPVTracks const& pvTracks, TFT0s const& ft0s, TSlicecache& cache, TBcSelBuffer const& bcselbuffer, TEvselCursor& evsel) + template + void processRun3(TCCDB const& ccdb, THistoRegistry& histos, TBCs const& bcs, TCollisions const& cols, TPVTracks const& pvTracks, TFT0s const& ft0s, TSlicecache& cache, TTimestamps const& timestamps, TBcSelBuffer const& bcselbuffer, TEvselCursor& evsel) { if (evselOpts.amIneeded.value == 0) { return; // dummy process } - if (!configure(ccdb, bcs)) + if (!configure(ccdb, timestamps, bcs)) return; // don't do anything in case configuration reported not ok int run = bcs.iteratorAt(0).runNumber(); @@ -1372,8 +1376,8 @@ class LumiModule } } - template - bool configure(TCCDB& ccdb, TBCs const& bcs) + template + bool configure(TCCDB& ccdb, TTimestamps const& timestamps, TBCs const& bcs) { if (bcs.size() == 0) return false; @@ -1382,7 +1386,7 @@ class LumiModule return false; if (run != lastRun && run >= 520259) { // o2-linter: disable=magic-number (scalers available for runs above 520120) lastRun = run; - int64_t ts = bcs.iteratorAt(0).timestamp(); + int64_t ts = timestamps[0]; // getting GRP LHCIF object to extract colliding system, energy and colliding bc pattern auto grplhcif = ccdb->template getForTimeStamp("GLO/Config/GRPLHCIF", ts); @@ -1511,14 +1515,14 @@ class LumiModule } //__________________________________________________ - template - void process(TCCDB& ccdb, THistoRegistry& histos, TBCs const& bcs, TBcSelBuffer const& bcselBuffer) + template + void process(TCCDB& ccdb, THistoRegistry& histos, TBCs const& bcs, TTimestamps const& timestamps, TBcSelBuffer const& bcselBuffer) { if (lumiOpts.amIneeded.value == 0) { return; } - if (!configure(ccdb, bcs)) + if (!configure(ccdb, timestamps, bcs)) return; // don't do anything in case configuration reported not ok int run = bcs.iteratorAt(0).runNumber(); diff --git a/Common/Tools/timestampModule.h b/Common/Tools/timestampModule.h new file mode 100644 index 00000000000..99241fa7713 --- /dev/null +++ b/Common/Tools/timestampModule.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. + +#ifndef COMMON_TOOLS_TIMESTAMPMODULEH_ +#define COMMON_TOOLS_TIMESTAMPMODULEH_ + +#include "Framework/AnalysisDataModel.h" + +#include +#include +#include + +namespace o2 +{ +namespace common +{ +namespace timestamp +{ + +// timestamp configurables +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 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) +}; + +//__________________________________________ +// time stamp module +// +// class to acquire time stamps to be used in +// modular (plugin) fashion + +class TimestampModule +{ + public: + TimestampModule() + { + // constructor: initialize at defaults + lastRunNumber = 0; + orbitResetTimestamp = 0; + }; + + o2::common::timestamp::timestampConfigurables timestampOpts; + + // objects necessary during processing + std::map mapRunToOrbitReset; /// Cache of orbit reset timestamps + std::map> mapRunToRunDuration; /// Cache of run duration timestamps + int lastRunNumber; /// Last run number processed + int64_t orbitResetTimestamp; /// Orbit-reset timestamp in us + std::pair runDuration; /// Pair of SOR and EOR timestamps + + template + void init(TTimestampOpts const& external_timestampOpts, TMetadatahelper const& metadataInfo) + { + timestampOpts = external_timestampOpts; + + if (timestampOpts.isRun2MC.value == -1) { + if ((!metadataInfo.isRun3()) && metadataInfo.isMC()) { + timestampOpts.isRun2MC.value = 1; + LOG(info) << "Autosetting the Run2 MC mode based on metadata"; + } else { + timestampOpts.isRun2MC.value = 0; + } + } + } + + template + void process(TBCs const& bcs, Tccdb const& ccdb, TTimestampBuffer& timestampbuffer, TCursor& timestampTable) + { + timestampbuffer.clear(); + for (auto const& bc : bcs) { + int runNumber = bc.runNumber(); + // We need to set the orbit-reset timestamp for the run number. + // This is done with caching if the run number was already processed before. + // If not the orbit-reset timestamp for the run number is queried from CCDB and added to the cache + if (runNumber == lastRunNumber) { // The run number coincides to the last run processed + LOGF(debug, "Using orbit-reset timestamp from last call"); + } else if (mapRunToOrbitReset.count(runNumber)) { // The run number was already requested before: getting it from cache! + LOGF(debug, "Getting orbit-reset timestamp from cache"); + orbitResetTimestamp = mapRunToOrbitReset[runNumber]; + runDuration = mapRunToRunDuration[runNumber]; + } else { // The run was not requested before: need to acccess CCDB! + LOGF(debug, "Getting start-of-run and end-of-run timestamps from CCDB"); + runDuration = ccdb->getRunDuration(runNumber, true); /// fatalise if timestamps are not found + int64_t sorTimestamp = runDuration.first; // timestamp of the SOR/SOX/STF in ms + int64_t eorTimestamp = runDuration.second; // timestamp of the EOR/EOX/ETF in ms + + const bool isUnanchoredRun3MC = runNumber >= 300000 && runNumber < 500000; + 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 + LOGF(debug, "Getting orbit-reset timestamp using start-of-run timestamp from CCDB"); + auto ctp = ccdb->template getForTimeStamp>(timestampOpts.orbit_reset_path.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 getForTimeStamp>(timestampOpts.orbit_reset_path.value.data(), eorTimestamp / 2 + sorTimestamp / 2); + orbitResetTimestamp = (*ctp)[0]; + } + + // Adding the timestamp to the cache map + std::pair::iterator, bool> check; + check = mapRunToOrbitReset.insert(std::pair(runNumber, orbitResetTimestamp)); + if (!check.second) { + LOGF(fatal, "Run number %i already existed with a orbit-reset timestamp of %llu", runNumber, check.first->second); + } + mapRunToRunDuration[runNumber] = runDuration; + LOGF(info, "Add new run number %i with orbit-reset timestamp %llu, SOR: %llu, EOR: %llu to cache", runNumber, orbitResetTimestamp, runDuration.first, runDuration.second); + } + + 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 + 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); + } else { + LOGF(debug, "Timestamp %llu us is out of run duration [%llu, %llu] ms", timestamp, runDuration.first, runDuration.second); + } + } + timestampbuffer.push_back(timestamp); // for buffering purposes + timestampTable(timestamp); + } + } +}; + +} // namespace timestamp +} // namespace common +} // namespace o2 + +#endif // COMMON_TOOLS_TIMESTAMPMODULEH_ From 18c347029d5789131ab31bf30a32e08dc4614e0a Mon Sep 17 00:00:00 2001 From: Nicolas Strangmann <77485327+nstrangm@users.noreply.github.com> Date: Sun, 29 Jun 2025 22:04:36 +0200 Subject: [PATCH 265/871] [PWGEM/PhotonMeson] Add eta meson functionality to bc wise gammagamma task (#11804) Co-authored-by: Nicolas Strangmann Co-authored-by: ALICE Action Bot --- PWGEM/PhotonMeson/DataModel/bcWiseTables.h | 20 +++-- .../TableProducer/bcWiseClusterSkimmer.cxx | 82 ++++++++++++------- .../Tasks/emcalBcWiseGammaGamma.cxx | 78 ++++++++++++------ 3 files changed, 118 insertions(+), 62 deletions(-) diff --git a/PWGEM/PhotonMeson/DataModel/bcWiseTables.h b/PWGEM/PhotonMeson/DataModel/bcWiseTables.h index f44769f1d94..55e7db691b1 100644 --- a/PWGEM/PhotonMeson/DataModel/bcWiseTables.h +++ b/PWGEM/PhotonMeson/DataModel/bcWiseTables.h @@ -19,10 +19,10 @@ #ifndef PWGEM_PHOTONMESON_DATAMODEL_BCWISETABLES_H_ #define PWGEM_PHOTONMESON_DATAMODEL_BCWISETABLES_H_ -#include - #include "Framework/AnalysisDataModel.h" +#include + namespace o2::aod { @@ -121,7 +121,7 @@ DECLARE_SOA_TABLE(BCWiseClusters, "AOD", "BCWISECLUSTER", //! table of skimmed E bcwisecluster::Definition, bcwisecluster::E, bcwisecluster::Eta, bcwisecluster::Phi, bcwisecluster::NCells, bcwisecluster::M02, bcwisecluster::Time, bcwisecluster::IsExotic, bcwisecluster::Pt); -namespace bcwisemcpi0s +namespace bcwisemcmesons { DECLARE_SOA_COLUMN(StoredPt, storedPt, uint16_t); //! Transverse momentum of generated pi0 (1 MeV -> Maximum pi0 pT of ~65 GeV) DECLARE_SOA_COLUMN(IsAccepted, isAccepted, bool); //! Both decay photons are within the EMCal acceptance @@ -129,22 +129,26 @@ DECLARE_SOA_COLUMN(IsPrimary, isPrimary, bool); //! mcParticle.isPhysicalPrima DECLARE_SOA_COLUMN(IsFromWD, isFromWD, bool); //! Pi0 from a weak decay according to pwgem::photonmeson::utils::mcutil::IsFromWD DECLARE_SOA_DYNAMIC_COLUMN(Pt, pt, [](uint16_t storedpt) -> float { return std::nextafter(storedpt / emdownscaling::downscalingFactors[emdownscaling::kpT], std::numeric_limits::infinity()); }); //! pT of pi0 (GeV) -} // namespace bcwisemcpi0s +} // namespace bcwisemcmesons DECLARE_SOA_TABLE(BCWiseMCPi0s, "AOD", "BCWISEMCPI0", //! table of pi0s on MC level - o2::soa::Index<>, BCWiseBCId, bcwisemcpi0s::StoredPt, bcwisemcpi0s::IsAccepted, bcwisemcpi0s::IsPrimary, bcwisemcpi0s::IsFromWD, - bcwisemcpi0s::Pt); + o2::soa::Index<>, BCWiseBCId, bcwisemcmesons::StoredPt, bcwisemcmesons::IsAccepted, bcwisemcmesons::IsPrimary, bcwisemcmesons::IsFromWD, + bcwisemcmesons::Pt); +DECLARE_SOA_TABLE(BCWiseMCEtas, "AOD", "BCWISEMCETA", //! table of eta mesons on MC level + o2::soa::Index<>, BCWiseBCId, bcwisemcmesons::StoredPt, bcwisemcmesons::IsAccepted, bcwisemcmesons::IsPrimary, bcwisemcmesons::IsFromWD, + bcwisemcmesons::Pt); namespace bcwisemccluster { -DECLARE_SOA_COLUMN(Pi0ID, pi0ID, int32_t); //! Index of the mother pi0 (-1 if not from pi0) +DECLARE_SOA_COLUMN(MesonID, mesonID, int32_t); //! Index of the mother mesom (-1 if not from a pi0 or eta) +DECLARE_SOA_COLUMN(IsEta, isEta, bool); //! Boolean flag to indicate if the cluster is from an eta meson, otherwise it is from a pi0 DECLARE_SOA_COLUMN(StoredTrueE, storedTrueE, uint16_t); //! energy of cluster inducing particle (1 MeV -> Maximum cluster energy of ~65 GeV) DECLARE_SOA_DYNAMIC_COLUMN(TrueE, trueE, [](uint16_t storedTrueE) -> float { return std::nextafter(storedTrueE / emdownscaling::downscalingFactors[emdownscaling::kEnergy], std::numeric_limits::infinity()); }); //! energy of cluster inducing particle (GeV) } // namespace bcwisemccluster DECLARE_SOA_TABLE(BCWiseMCClusters, "AOD", "BCWISEMCCLS", //! table of MC information for clusters -> To be joined with the cluster table - o2::soa::Index<>, BCWiseBCId, bcwisemccluster::Pi0ID, bcwisemccluster::StoredTrueE, + o2::soa::Index<>, BCWiseBCId, bcwisemccluster::MesonID, bcwisemccluster::IsEta, bcwisemccluster::StoredTrueE, bcwisemccluster::TrueE); } // namespace o2::aod diff --git a/PWGEM/PhotonMeson/TableProducer/bcWiseClusterSkimmer.cxx b/PWGEM/PhotonMeson/TableProducer/bcWiseClusterSkimmer.cxx index bc24734ee2d..49324fb7999 100644 --- a/PWGEM/PhotonMeson/TableProducer/bcWiseClusterSkimmer.cxx +++ b/PWGEM/PhotonMeson/TableProducer/bcWiseClusterSkimmer.cxx @@ -16,25 +16,25 @@ /// \author Nicolas Strangmann (nicolas.strangmann@cern.ch) - Goethe University Frankfurt /// -#include -#include -#include -#include +#include "PWGEM/PhotonMeson/DataModel/bcWiseTables.h" +#include "PWGEM/PhotonMeson/Utils/MCUtilities.h" +#include "PWGJE/DataModel/EMCALClusters.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" +#include "Common/CCDB/ctpRateFetcher.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" +#include "CCDB/BasicCCDBManager.h" +#include "DataFormatsParameters/GRPLHCIFData.h" #include "DetectorsBase/GeometryManager.h" #include "EMCALBase/Geometry.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/Centrality.h" -#include "Common/CCDB/ctpRateFetcher.h" -#include "CCDB/BasicCCDBManager.h" -#include "DataFormatsParameters/GRPLHCIFData.h" -#include "PWGJE/DataModel/EMCALClusters.h" -#include "PWGEM/PhotonMeson/Utils/MCUtilities.h" -#include "PWGEM/PhotonMeson/DataModel/bcWiseTables.h" +#include +#include +#include +#include using namespace o2; using namespace o2::aod::emdownscaling; @@ -56,6 +56,7 @@ struct bcWiseClusterSkimmer { Produces clusterTable; Produces collisionTable; Produces mcpi0Table; + Produces mcetaTable; Produces mcclusterTable; PresliceUnsorted perFoundBC = aod::evsel::foundBCId; @@ -70,7 +71,7 @@ struct bcWiseClusterSkimmer { Configurable cfgMinTime{"cfgMinTime", -25, "Minimum time of selected clusters (ns)"}; Configurable cfgMaxTime{"cfgMaxTime", 25, "Maximum time of selected clusters (ns)"}; Configurable cfgRapidityCut{"cfgRapidityCut", 0.8f, "Maximum absolute rapidity of counted generated particles"}; - Configurable cfgMinPtGenPi0{"cfgMinPtGenPi0", 0., "Minimum pT for stored generated pi0s (reduce disk space of derived data)"}; + Configurable cfgMinPtGen{"cfgMinPtGen", 0., "Minimum pT for stored generated mesons (reduce disk space of derived data)"}; Configurable cfgRequirekTVXinEMC{"cfgRequirekTVXinEMC", false, "Only store kTVXinEMC triggered BCs"}; Configurable cfgRequireGoodRCTQuality{"cfgRequireGoodRCTQuality", false, "Only store BCs with good quality of T0 and EMC in RCT"}; @@ -90,6 +91,7 @@ struct bcWiseClusterSkimmer { HistogramRegistry mHistManager{"output", {}, OutputObjHandlingPolicy::AnalysisObject, false, false}; std::map fMapPi0Index; // Map to connect the MC index of the pi0 to the one saved in the derived table + std::map fMapEtaIndex; // Map to connect the MC index of the eta to the one saved in the derived table void init(o2::framework::InitContext&) { @@ -108,7 +110,7 @@ struct bcWiseClusterSkimmer { LOG(info) << "| Shape cut: " << cfgMinM02 << " < M02 < " << cfgMaxM02; LOG(info) << "| Energy cut: " << cfgMinClusterEnergy << " < E < " << cfgMaxClusterEnergy; LOG(info) << "| Rapidity cut: |y| < " << cfgRapidityCut; - LOG(info) << "| Min gen pi0 pt: pT > " << cfgMinPtGenPi0; + LOG(info) << "| Min gen pt: pT > " << cfgMinPtGen; o2::emcal::Geometry::GetInstanceFromRunNumber(300000); if (cfgRequireGoodRCTQuality) @@ -154,31 +156,42 @@ struct bcWiseClusterSkimmer { { for (const auto& cluster : clusters) { float clusterInducerEnergy = 0.; - int32_t pi0MCIndex = -1; + int32_t mesonMCIndex = -1; if (cluster.amplitudeA().size() > 0) { int clusterInducerId = cluster.mcParticleIds()[0]; auto clusterInducer = mcParticles.iteratorAt(clusterInducerId); clusterInducerEnergy = clusterInducer.e(); - int daughterId = aod::pwgem::photonmeson::utils::mcutil::FindMotherInChain(clusterInducer, mcParticles, std::vector{111}); + int daughterId = aod::pwgem::photonmeson::utils::mcutil::FindMotherInChain(clusterInducer, mcParticles, std::vector{111, 221}); if (daughterId > 0) { - pi0MCIndex = mcParticles.iteratorAt(daughterId).mothersIds()[0]; - if (mcParticles.iteratorAt(pi0MCIndex).pt() < cfgMinPtGenPi0) - pi0MCIndex = -1; + mesonMCIndex = mcParticles.iteratorAt(daughterId).mothersIds()[0]; + if (mcParticles.iteratorAt(mesonMCIndex).pt() < cfgMinPtGen) + mesonMCIndex = -1; } } - if (pi0MCIndex >= 0) { - if (fMapPi0Index.find(pi0MCIndex) != fMapPi0Index.end()) // Some pi0s might not be found (not gg decay or too large y) - pi0MCIndex = fMapPi0Index[pi0MCIndex]; // If pi0 was stored in table, change index from the MC index to the pi0 index from this task - else // If pi0 was not stored, treat photon as if not from pi0 - pi0MCIndex = -1; + bool isEta = false; + if (mesonMCIndex >= 0) { + if (mcParticles.iteratorAt(mesonMCIndex).pdgCode() == 111) { + if (fMapPi0Index.find(mesonMCIndex) != fMapPi0Index.end()) // Some pi0s might not be found (not gg decay or too large y) + mesonMCIndex = fMapPi0Index[mesonMCIndex]; // If pi0 was stored in table, change index from the MC index to the pi0 index from this task + else // If pi0 was not stored, treat photon as if not from pi0 + mesonMCIndex = -1; + } else if (mcParticles.iteratorAt(mesonMCIndex).pdgCode() == 221) { + isEta = true; + if (fMapEtaIndex.find(mesonMCIndex) != fMapEtaIndex.end()) // Some etas might not be found (not gg decay or too large y) + mesonMCIndex = fMapEtaIndex[mesonMCIndex]; // If eta was stored in table, change index from the MC index to the eta index from this task + else // If eta was not stored, treat photon as if not from eta + mesonMCIndex = -1; + } else { + mesonMCIndex = -1; // Not a pi0 or eta + } } - mcclusterTable(bcID, pi0MCIndex, convertForStorage(clusterInducerEnergy, kEnergy)); + mcclusterTable(bcID, mesonMCIndex, isEta, convertForStorage(clusterInducerEnergy, kEnergy)); } } bool isBCSelected(const auto& bc) { - if (cfgRequirekTVXinEMC && !bc.selection_bit(aod::evsel::kIsTriggerTVX)) + if (cfgRequirekTVXinEMC && !bc.alias_bit(kTVXinEMC)) return false; if (cfgRequireGoodRCTQuality && !isFT0EMCGoodRCTChecker(bc)) return false; @@ -319,12 +332,18 @@ struct bcWiseClusterSkimmer { auto mcParticlesInColl = mcParticles.sliceBy(perMcCollision, mcCollision.globalIndex()); mHistManager.fill(HIST("CentralityVsGenMultiplicity"), bc.centFT0M(), mcParticlesInColl.size()); for (const auto& mcParticle : mcParticlesInColl) { - if (mcParticle.pdgCode() != 111 || std::abs(mcParticle.y()) > cfgRapidityCut || !isGammaGammaDecay(mcParticle, mcParticles) || mcParticle.pt() < cfgMinPtGenPi0) + if (std::abs(mcParticle.y()) > cfgRapidityCut || !isGammaGammaDecay(mcParticle, mcParticles) || mcParticle.pt() < cfgMinPtGen) continue; bool isPrimary = mcParticle.isPhysicalPrimary() || mcParticle.producedByGenerator(); bool isFromWD = (aod::pwgem::photonmeson::utils::mcutil::IsFromWD(mcCollision, mcParticle, mcParticles)) > 0; - mcpi0Table(bc.globalIndex(), convertForStorage(mcParticle.pt(), kpT), isAccepted(mcParticle, mcParticles), isPrimary, isFromWD); - fMapPi0Index[mcParticle.globalIndex()] = static_cast(mcpi0Table.lastIndex()); + + if (mcParticle.pdgCode() == 111) { + mcpi0Table(bc.globalIndex(), convertForStorage(mcParticle.pt(), kpT), isAccepted(mcParticle, mcParticles), isPrimary, isFromWD); + fMapPi0Index[mcParticle.globalIndex()] = static_cast(mcpi0Table.lastIndex()); + } else if (mcParticle.pdgCode() == 221) { + mcetaTable(bc.globalIndex(), convertForStorage(mcParticle.pt(), kpT), isAccepted(mcParticle, mcParticles), isPrimary, isFromWD); + fMapEtaIndex[mcParticle.globalIndex()] = static_cast(mcetaTable.lastIndex()); + } } } @@ -338,6 +357,7 @@ struct bcWiseClusterSkimmer { processClusterMCInfo(clustersInBC, bc.globalIndex(), mcParticles); } fMapPi0Index.clear(); + fMapEtaIndex.clear(); } } PROCESS_SWITCH(bcWiseClusterSkimmer, processMC, "Run skimming for MC", false); diff --git a/PWGEM/PhotonMeson/Tasks/emcalBcWiseGammaGamma.cxx b/PWGEM/PhotonMeson/Tasks/emcalBcWiseGammaGamma.cxx index 03c5cfb1b5c..9f2e5216e25 100644 --- a/PWGEM/PhotonMeson/Tasks/emcalBcWiseGammaGamma.cxx +++ b/PWGEM/PhotonMeson/Tasks/emcalBcWiseGammaGamma.cxx @@ -10,9 +10,9 @@ // or submit itself to any jurisdiction. // /// -/// \file emcalBcWisePi0.cxx +/// \file emcalBcWiseGammaGamma.cxx /// -/// \brief Task that extracts pi0s from BC wise derived data of EMCal clusters +/// \brief Task that extracts pi0s and eta mesons from BC wise derived data of EMCal clusters /// /// \author Nicolas Strangmann (nicolas.strangmann@cern.ch) Goethe University Frankfurt /// @@ -42,7 +42,7 @@ using SelectedMCClusters = soa::Filtered cfgRequirekTVXinEMC{"cfgRequirekTVXinEMC", true, "Reconstruct pi0s only in kTVXinEMC triggered BCs"}; + Configurable cfgRequirekTVXinEMC{"cfgRequirekTVXinEMC", true, "Reconstruct mesonss only in kTVXinEMC triggered BCs"}; Configurable cfgSelectOnlyUniqueAmbiguous{"cfgSelectOnlyUniqueAmbiguous", 0, "0: all clusters, 1: only unique clusters, 2: only ambiguous clusters"}; Configurable cfgClusterDefinition{"cfgClusterDefinition", 13, "Clusterizer to be selected, e.g. 13 for kV3MostSplitLowSeed"}; @@ -94,20 +94,28 @@ struct EmcalBcWiseGammaGamma { mHistManager.add("Cluster/Exotic", "Is cluster exotic?;#bf{Exotic?};#bf{FT0M centrality (%)};#bf{#it{N}_{clusters}}", HistType::kTH2F, {{2, -0.5, 1.5}, cfgCentralityBinning}); mHistManager.add("Cluster/EtaPhi", "Eta/Phi distribution of clusters;#eta;#phi;#bf{FT0M centrality (%)};#bf{#it{N}_{clusters}}", HistType::kTH3F, {{400, -0.8, 0.8}, {400, 0, constants::math::TwoPI}, cfgCentralityBinning}); - mHistManager.add("GG/invMassVsPt", "Invariant mass and pT of meson candidates;#bf{#it{M}^{#gamma#gamma} (GeV/#it{c}^{2})};#bf{#it{p}_{T}^{#gamma#gamma} (GeV/#it{c})};#bf{FT0M centrality (%)}", HistType::kTH3F, {{200, 0., 0.4}, {200, 0., 20.}, cfgCentralityBinning}); - mHistManager.add("GG/invMassVsPtBackground", "Invariant mass and pT of background meson candidates;#bf{#it{M}^{#gamma#gamma} (GeV/#it{c}^{2})};#bf{#it{p}_{T}^{#gamma#gamma} (GeV/#it{c})};#bf{FT0M centrality (%)}", HistType::kTH3F, {{200, 0., 0.4}, {200, 0., 20.}, cfgCentralityBinning}); + mHistManager.add("GG/invMassVsPt", "Invariant mass and pT of meson candidates;#bf{#it{M}^{#gamma#gamma} (GeV/#it{c}^{2})};#bf{#it{p}_{T}^{#gamma#gamma} (GeV/#it{c})};#bf{FT0M centrality (%)}", HistType::kTH3F, {{400, 0., 0.8}, {200, 0., 20.}, cfgCentralityBinning}); + mHistManager.add("GG/invMassVsPtBackground", "Invariant mass and pT of background meson candidates;#bf{#it{M}^{#gamma#gamma} (GeV/#it{c}^{2})};#bf{#it{p}_{T}^{#gamma#gamma} (GeV/#it{c})};#bf{FT0M centrality (%)}", HistType::kTH3F, {{400, 0., 0.8}, {200, 0., 20.}, cfgCentralityBinning}); if (cfgIsMC) { mHistManager.add("True/clusterERecVsETrue", "True vs reconstructed energy of cluster inducing particle;#bf{#it{E}_{rec} (GeV)};#bf{#it{E}_{true}^{cls inducing part} (GeV)};#bf{FT0M centrality (%)}", HistType::kTH3F, {{200, 0, 20}, {200, 0, 20}, cfgCentralityBinning}); - mHistManager.add("True/PtRecVsPtTrue", "True vs reconstructed pT of true pi0s;#bf{#it{p}_{T}^{rec} (GeV/#it{c})};#bf{#it{p}_{T}^{true} (GeV/#it{c})};#bf{FT0M centrality (%)}", HistType::kTH3F, {{200, 0., 20.}, {200, 0., 20.}, cfgCentralityBinning}); - mHistManager.add("True/invMassVsPt_Primary", "Reconstructed validated primary pi0;#bf{#it{M}^{#gamma#gamma} (GeV/#it{c}^{2})};#bf{#it{p}_{T}^{#gamma#gamma} (GeV/#it{c})};#bf{FT0M centrality (%)}", HistType::kTH3F, {{200, 0., 0.4}, {200, 0., 20.}, cfgCentralityBinning}); - mHistManager.add("True/invMassVsPt_Secondary", "Reconstructed validated pi0 from secondary decay;#bf{#it{M}^{#gamma#gamma} (GeV/#it{c}^{2})};#bf{#it{p}_{T}^{#gamma#gamma} (GeV/#it{c})};#bf{FT0M centrality (%)}", HistType::kTH3F, {{200, 0., 0.4}, {200, 0., 20.}, cfgCentralityBinning}); - mHistManager.add("True/invMassVsPt_HadronicShower", "Reconstructed validated pi0 from hadronic shower;#bf{#it{M}^{#gamma#gamma} (GeV/#it{c}^{2})};#bf{#it{p}_{T}^{#gamma#gamma} (GeV/#it{c})};#bf{FT0M centrality (%)}", HistType::kTH3F, {{200, 0., 0.4}, {200, 0., 20.}, cfgCentralityBinning}); + mHistManager.add("True/pi0_PtRecVsPtTrue", "True vs reconstructed pT of true pi0s;#bf{#it{p}_{T}^{rec} (GeV/#it{c})};#bf{#it{p}_{T}^{true} (GeV/#it{c})};#bf{FT0M centrality (%)}", HistType::kTH3F, {{200, 0., 20.}, {200, 0., 20.}, cfgCentralityBinning}); + mHistManager.add("True/pi0_invMassVsPt_Primary", "Reconstructed validated primary pi0;#bf{#it{M}^{#gamma#gamma} (GeV/#it{c}^{2})};#bf{#it{p}_{T}^{#gamma#gamma} (GeV/#it{c})};#bf{FT0M centrality (%)}", HistType::kTH3F, {{400, 0., 0.8}, {200, 0., 20.}, cfgCentralityBinning}); + mHistManager.add("True/pi0_invMassVsPt_Secondary", "Reconstructed validated pi0 from secondary decay;#bf{#it{M}^{#gamma#gamma} (GeV/#it{c}^{2})};#bf{#it{p}_{T}^{#gamma#gamma} (GeV/#it{c})};#bf{FT0M centrality (%)}", HistType::kTH3F, {{400, 0., 0.8}, {200, 0., 20.}, cfgCentralityBinning}); + mHistManager.add("True/pi0_invMassVsPt_HadronicShower", "Reconstructed validated pi0 from hadronic shower;#bf{#it{M}^{#gamma#gamma} (GeV/#it{c}^{2})};#bf{#it{p}_{T}^{#gamma#gamma} (GeV/#it{c})};#bf{FT0M centrality (%)}", HistType::kTH3F, {{400, 0., 0.8}, {200, 0., 20.}, cfgCentralityBinning}); + mHistManager.add("True/eta_PtRecVsPtTrue", "True vs reconstructed pT of true eta meson;#bf{#it{p}_{T}^{rec} (GeV/#it{c})};#bf{#it{p}_{T}^{true} (GeV/#it{c})};#bf{FT0M centrality (%)}", HistType::kTH3F, {{200, 0., 20.}, {200, 0., 20.}, cfgCentralityBinning}); + mHistManager.add("True/eta_invMassVsPt_Primary", "Reconstructed validated primary eta meson;#bf{#it{M}^{#gamma#gamma} (GeV/#it{c}^{2})};#bf{#it{p}_{T}^{#gamma#gamma} (GeV/#it{c})};#bf{FT0M centrality (%)}", HistType::kTH3F, {{400, 0., 0.8}, {200, 0., 20.}, cfgCentralityBinning}); + mHistManager.add("True/eta_invMassVsPt_Secondary", "Reconstructed validated eta meson from secondary decay;#bf{#it{M}^{#gamma#gamma} (GeV/#it{c}^{2})};#bf{#it{p}_{T}^{#gamma#gamma} (GeV/#it{c})};#bf{FT0M centrality (%)}", HistType::kTH3F, {{400, 0., 0.8}, {200, 0., 20.}, cfgCentralityBinning}); + mHistManager.add("True/eta_invMassVsPt_HadronicShower", "Reconstructed validated eta meson from hadronic shower;#bf{#it{M}^{#gamma#gamma} (GeV/#it{c}^{2})};#bf{#it{p}_{T}^{#gamma#gamma} (GeV/#it{c})};#bf{FT0M centrality (%)}", HistType::kTH3F, {{400, 0., 0.8}, {200, 0., 20.}, cfgCentralityBinning}); mHistManager.add("Generated/pi0_AllBCs", "pT spectrum of generated pi0s in all BCs;#bf{#it{p}_{T} (GeV/#it{c})};#bf{FT0M centrality (%)};#bf{#it{N}_{#pi^{0}}^{gen}}", HistType::kTH2F, {{200, 0, 20}, cfgCentralityBinning}); mHistManager.add("Generated/pi0_TVX", "pT spectrum of generated pi0s in TVX triggered BCs;#bf{#it{p}_{T} (GeV/#it{c})};#bf{FT0M centrality (%)};#bf{#it{N}_{#pi^{0}}^{gen}}", HistType::kTH2F, {{200, 0, 20}, cfgCentralityBinning}); mHistManager.add("Generated/pi0_kTVXinEMC", "pT spectrum of generated pi0s in kTVXinEMC triggered BCs;#bf{#it{p}_{T} (GeV/#it{c})};#bf{FT0M centrality (%)};#bf{#it{N}_{#pi^{0}}^{gen}}", HistType::kTH2F, {{200, 0, 20}, cfgCentralityBinning}); mHistManager.add("Accepted/pi0_kTVXinEMC", "pT spectrum of accepted pi0s in kTVXinEMC triggered BCs;#bf{#it{p}_{T} (GeV/#it{c})};#bf{FT0M centrality (%)};#bf{#it{N}_{#pi^{0}}^{acc}}", HistType::kTH2F, {{200, 0, 20}, cfgCentralityBinning}); + mHistManager.add("Generated/eta_AllBCs", "pT spectrum of generated eta mesons in all BCs;#bf{#it{p}_{T} (GeV/#it{c})};#bf{FT0M centrality (%)};#bf{#it{N}_{#eta}^{gen}}", HistType::kTH2F, {{200, 0, 20}, cfgCentralityBinning}); + mHistManager.add("Generated/eta_TVX", "pT spectrum of generated eta mesons in TVX triggered BCs;#bf{#it{p}_{T} (GeV/#it{c})};#bf{FT0M centrality (%)};#bf{#it{N}_{#eta}^{gen}}", HistType::kTH2F, {{200, 0, 20}, cfgCentralityBinning}); + mHistManager.add("Generated/eta_kTVXinEMC", "pT spectrum of generated eta mesons in kTVXinEMC triggered BCs;#bf{#it{p}_{T} (GeV/#it{c})};#bf{FT0M centrality (%)};#bf{#it{N}_{#eta}^{gen}}", HistType::kTH2F, {{200, 0, 20}, cfgCentralityBinning}); + mHistManager.add("Accepted/eta_kTVXinEMC", "pT spectrum of accepted eta mesons in kTVXinEMC triggered BCs;#bf{#it{p}_{T} (GeV/#it{c})};#bf{FT0M centrality (%)};#bf{#it{N}_{#eta}^{acc}}", HistType::kTH2F, {{200, 0, 20}, cfgCentralityBinning}); } } @@ -231,10 +239,10 @@ struct EmcalBcWiseGammaGamma { } } } - void reconstructTrueMesons(const auto& clusters, const auto& mcPi0s, const auto& bc) + void reconstructTrueMesons(const auto& clusters, const auto& mcPi0s, const auto& mcEtas, const auto& bc) { for (const auto& [g1, g2] : soa::combinations(soa::CombinationsStrictlyUpperIndexPolicy(clusters, clusters))) { - if (g1.pi0ID() == -1 || g1.pi0ID() != g2.pi0ID()) + if (g1.mesonID() != g2.mesonID() || g1.mesonID() == -1) continue; ROOT::Math::PtEtaPhiMVector v1(g1.pt(), g1.eta(), g1.phi(), 0.); @@ -247,16 +255,29 @@ struct EmcalBcWiseGammaGamma { if (openingAngle12 < cfgMinOpenAngle) continue; - const auto& mcPi0 = mcPi0s.iteratorAt(g1.pi0ID() - mcPi0s.offset()); + if (!g1.isEta()) { + const auto& mcPi0 = mcPi0s.iteratorAt(g1.mesonID() - mcPi0s.offset()); - mHistManager.fill(HIST("True/PtRecVsPtTrue"), v12.Pt(), mcPi0.pt(), bc.centrality()); + mHistManager.fill(HIST("True/pi0_PtRecVsPtTrue"), v12.Pt(), mcPi0.pt(), bc.centrality()); - if (mcPi0.isPrimary()) - mHistManager.fill(HIST("True/invMassVsPt_Primary"), v12.M(), v12.Pt(), bc.centrality()); - else if (mcPi0.isFromWD()) - mHistManager.fill(HIST("True/invMassVsPt_Secondary"), v12.M(), v12.Pt(), bc.centrality()); - else - mHistManager.fill(HIST("True/invMassVsPt_HadronicShower"), v12.M(), v12.Pt(), bc.centrality()); + if (mcPi0.isPrimary()) + mHistManager.fill(HIST("True/pi0_invMassVsPt_Primary"), v12.M(), v12.Pt(), bc.centrality()); + else if (mcPi0.isFromWD()) + mHistManager.fill(HIST("True/pi0_invMassVsPt_Secondary"), v12.M(), v12.Pt(), bc.centrality()); + else + mHistManager.fill(HIST("True/pi0_invMassVsPt_HadronicShower"), v12.M(), v12.Pt(), bc.centrality()); + } else { + const auto& mcEta = mcEtas.iteratorAt(g1.mesonID() - mcEtas.offset()); + + mHistManager.fill(HIST("True/eta_PtRecVsPtTrue"), v12.Pt(), mcEta.pt(), bc.centrality()); + + if (mcEta.isPrimary()) + mHistManager.fill(HIST("True/eta_invMassVsPt_Primary"), v12.M(), v12.Pt(), bc.centrality()); + else if (mcEta.isFromWD()) + mHistManager.fill(HIST("True/eta_invMassVsPt_Secondary"), v12.M(), v12.Pt(), bc.centrality()); + else + mHistManager.fill(HIST("True/eta_invMassVsPt_HadronicShower"), v12.M(), v12.Pt(), bc.centrality()); + } } } @@ -271,7 +292,7 @@ struct EmcalBcWiseGammaGamma { return true; } - void fillGeneratedPi0Hists(const auto& mcPi0s, const auto& bc) + void fillGeneratedMesonHists(const auto& mcPi0s, const auto& mcEtas, const auto& bc) { for (const auto& mcPi0 : mcPi0s) { if (mcPi0.isPrimary()) { @@ -284,6 +305,17 @@ struct EmcalBcWiseGammaGamma { mHistManager.fill(HIST("Accepted/pi0_kTVXinEMC"), mcPi0.pt(), bc.centrality()); } } + for (const auto& mcEta : mcEtas) { + if (mcEta.isPrimary()) { + mHistManager.fill(HIST("Generated/eta_AllBCs"), mcEta.pt(), bc.centrality()); + if (bc.hasTVX()) + mHistManager.fill(HIST("Generated/eta_TVX"), mcEta.pt(), bc.centrality()); + if (bc.haskTVXinEMC()) + mHistManager.fill(HIST("Generated/eta_kTVXinEMC"), mcEta.pt(), bc.centrality()); + if (mcEta.isAccepted() && bc.haskTVXinEMC()) + mHistManager.fill(HIST("Accepted/eta_kTVXinEMC"), mcEta.pt(), bc.centrality()); + } + } } void process(aod::BCWiseBCs::iterator const& bc, aod::BCWiseCollisions const& collisions, SelectedClusters const& clusters) @@ -298,12 +330,12 @@ struct EmcalBcWiseGammaGamma { reconstructMesons(clusters, bc); } - void processMCInfo(aod::BCWiseBCs::iterator const& bc, aod::BCWiseCollisions const& collisions, SelectedMCClusters const& clusters, aod::BCWiseMCPi0s const& mcPi0s) + void processMCInfo(aod::BCWiseBCs::iterator const& bc, aod::BCWiseCollisions const& collisions, SelectedMCClusters const& clusters, aod::BCWiseMCPi0s const& mcPi0s, aod::BCWiseMCEtas const& mcEtas) { if (!cfgIsMC) LOG(fatal) << "MC processing is not enabled, but the task is running on MC data. Please set cfgIsMC to true."; - fillGeneratedPi0Hists(mcPi0s, bc); // Fill before BC selection to also store pi0s in BCs that were not triggered + fillGeneratedMesonHists(mcPi0s, mcEtas, bc); // Fill before BC selection to also store pi0s and eta mesons in BCs that were not triggered if (!isBCSelected(bc, collisions)) return; @@ -311,7 +343,7 @@ struct EmcalBcWiseGammaGamma { for (const auto& cluster : clusters) mHistManager.fill(HIST("True/clusterERecVsETrue"), cluster.e(), cluster.trueE(), bc.centrality()); - reconstructTrueMesons(clusters, mcPi0s, bc); + reconstructTrueMesons(clusters, mcPi0s, mcEtas, bc); } PROCESS_SWITCH(EmcalBcWiseGammaGamma, processMCInfo, "Run true and gen", false); }; From 8fb6e004c32113c39fd1982ae8ad896fa24a62b3 Mon Sep 17 00:00:00 2001 From: Daiki Sekihata Date: Sun, 29 Jun 2025 23:46:04 +0200 Subject: [PATCH 266/871] [PWGEM/Dilepton] change from max pin to max p (#11828) --- .../treeCreatorElectronMLDDA.cxx | 88 ++++++++++--------- 1 file changed, 47 insertions(+), 41 deletions(-) diff --git a/PWGEM/Dilepton/TableProducer/treeCreatorElectronMLDDA.cxx b/PWGEM/Dilepton/TableProducer/treeCreatorElectronMLDDA.cxx index cb88ec1f45a..dc0ee410b7e 100644 --- a/PWGEM/Dilepton/TableProducer/treeCreatorElectronMLDDA.cxx +++ b/PWGEM/Dilepton/TableProducer/treeCreatorElectronMLDDA.cxx @@ -128,11 +128,11 @@ struct TreeCreatorElectronMLDDA { Configurable downscaling_kaon{"downscaling_kaon", 1.1, "down scaling factor to store kaon"}; Configurable downscaling_proton{"downscaling_proton", 0.005, "down scaling factor to store proton"}; - Configurable max_pin_for_downscaling_electron_primary{"max_pin_for_downscaling_electron_primary", 0.0, "max pin to apply down scaling factor to store primary electron for validation"}; - Configurable max_pin_for_downscaling_electron{"max_pin_for_downscaling_electron", 2.0, "max pin to apply down scaling factor to store electron"}; - Configurable max_pin_for_downscaling_pion{"max_pin_for_downscaling_pion", 2.0, "max pin to apply down scaling factor to store pion"}; - Configurable max_pin_for_downscaling_kaon{"max_pin_for_downscaling_kaon", 0.0, "max pin to apply down scaling factor to store kaon"}; - Configurable max_pin_for_downscaling_proton{"max_pin_for_downscaling_proton", 2.0, "max pin to apply down scaling factor to store proton"}; + Configurable max_p_for_downscaling_electron_primary{"max_p_for_downscaling_electron_primary", 0.0, "max p to apply down scaling factor to store primary electron for validation"}; + 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_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"}; struct : ConfigurableGroup { @@ -583,17 +583,41 @@ struct TreeCreatorElectronMLDDA { if (store_ele_band_only && !isElectron(track)) { return; } + mDcaInfoCov.set(999, 999, 999, 999, 999); + auto trackParCov = getTrackParCov(track); + // trackParCov.setPID(track.pidForTracking()); + trackParCov.setPID(o2::track::PID::Electron); // This is for eID in the end! + 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, trackParCov, 2.f, matCorr, &mDcaInfoCov); + float dcaXY = mDcaInfoCov.getY(); + float dcaZ = mDcaInfoCov.getZ(); - if (std::find(stored_trackIds.begin(), stored_trackIds.end(), track.globalIndex()) == stored_trackIds.end()) { - mDcaInfoCov.set(999, 999, 999, 999, 999); - auto trackParCov = getTrackParCov(track); - trackParCov.setPID(track.pidForTracking()); - 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, trackParCov, 2.f, matCorr, &mDcaInfoCov); - float dcaXY = mDcaInfoCov.getY(); - float dcaZ = mDcaInfoCov.getZ(); + if (tracktype == static_cast(o2::aod::pwgem::dilepton::ml::Track_Type::kPrimary)) { + if (dist01(engine) > downscaling_electron_primary && trackParCov.getP() < max_p_for_downscaling_electron_primary) { + return; + } + } else { // secondary + if (pidlabel == static_cast(o2::aod::pwgem::dilepton::ml::PID_Label::kElectron)) { + if (dist01(engine) > downscaling_electron && trackParCov.getP() < max_p_for_downscaling_electron) { + return; + } + } else if (pidlabel == static_cast(o2::aod::pwgem::dilepton::ml::PID_Label::kPion)) { + if (dist01(engine) > downscaling_pion && trackParCov.getP() < max_p_for_downscaling_pion) { + return; + } + } else if (pidlabel == static_cast(o2::aod::pwgem::dilepton::ml::PID_Label::kKaon)) { + if (dist01(engine) > downscaling_kaon && trackParCov.getP() < max_p_for_downscaling_kaon) { + return; + } + } else if (pidlabel == static_cast(o2::aod::pwgem::dilepton::ml::PID_Label::kProton)) { + if (dist01(engine) > downscaling_proton && trackParCov.getP() < max_p_for_downscaling_proton) { + return; + } + } + } + if (std::find(stored_trackIds.begin(), stored_trackIds.end(), track.globalIndex()) == stored_trackIds.end()) { emprimarytracks(collision.numContrib(), collision.trackOccupancyInTimeRange(), collision.ft0cOccupancyInTimeRange(), trackParCov.getPt(), trackParCov.getEta(), trackParCov.getPhi() > 0.f ? trackParCov.getPhi() : trackParCov.getPhi() + 2 * M_PI, trackParCov.getTgl(), track.sign(), dcaXY, dcaZ, trackParCov.getSigmaY2(), trackParCov.getSigmaZ2(), trackParCov.getSigmaZY(), @@ -758,20 +782,14 @@ struct TreeCreatorElectronMLDDA { registry.fill(HIST("V0/hTOFbeta_P_Pi"), neg.tpcInnerParam(), neg.beta()); registry.fill(HIST("V0/hTPCdEdx_P_Pi"), pos.tpcInnerParam(), pos.tpcSignal()); registry.fill(HIST("V0/hTOFbeta_P_Pi"), pos.tpcInnerParam(), pos.beta()); - if (dist01(engine) < downscaling_pion || pos.tpcInnerParam() > max_pin_for_downscaling_pion) { - fillTrackTable(collision, pos, static_cast(o2::aod::pwgem::dilepton::ml::PID_Label::kPion), static_cast(o2::aod::pwgem::dilepton::ml::Track_Type::kSecondary), false); - } - if (dist01(engine) < downscaling_pion || neg.tpcInnerParam() > max_pin_for_downscaling_pion) { - fillTrackTable(collision, neg, static_cast(o2::aod::pwgem::dilepton::ml::PID_Label::kPion), static_cast(o2::aod::pwgem::dilepton::ml::Track_Type::kSecondary), false); - } + fillTrackTable(collision, pos, static_cast(o2::aod::pwgem::dilepton::ml::PID_Label::kPion), static_cast(o2::aod::pwgem::dilepton::ml::Track_Type::kSecondary), false); + fillTrackTable(collision, neg, static_cast(o2::aod::pwgem::dilepton::ml::PID_Label::kPion), static_cast(o2::aod::pwgem::dilepton::ml::Track_Type::kSecondary), false); } } if (isProton(pos) && isPionTight(neg)) { registry.fill(HIST("V0/hMassLambda"), v0.mLambda()); if (v0cuts.cfg_min_mass_lambda < v0.mLambda() && v0.mLambda() < v0cuts.cfg_max_mass_lambda) { - if (dist01(engine) < downscaling_proton || pos.tpcInnerParam() > max_pin_for_downscaling_proton) { - fillTrackTable(collision, pos, static_cast(o2::aod::pwgem::dilepton::ml::PID_Label::kProton), static_cast(o2::aod::pwgem::dilepton::ml::Track_Type::kSecondary), false); - } + fillTrackTable(collision, pos, static_cast(o2::aod::pwgem::dilepton::ml::PID_Label::kProton), static_cast(o2::aod::pwgem::dilepton::ml::Track_Type::kSecondary), false); registry.fill(HIST("V0/hTPCdEdx_P_Pr"), pos.tpcInnerParam(), pos.tpcSignal()); registry.fill(HIST("V0/hTOFbeta_P_Pr"), pos.tpcInnerParam(), pos.beta()); } @@ -779,9 +797,7 @@ struct TreeCreatorElectronMLDDA { if (isPionTight(pos) && isProton(neg)) { registry.fill(HIST("V0/hMassAntiLambda"), v0.mAntiLambda()); if (v0cuts.cfg_min_mass_lambda < v0.mAntiLambda() && v0.mAntiLambda() < v0cuts.cfg_max_mass_lambda) { - if (dist01(engine) < downscaling_proton || neg.tpcInnerParam() > max_pin_for_downscaling_proton) { - fillTrackTable(collision, neg, static_cast(o2::aod::pwgem::dilepton::ml::PID_Label::kProton), static_cast(o2::aod::pwgem::dilepton::ml::Track_Type::kSecondary), false); - } + fillTrackTable(collision, neg, static_cast(o2::aod::pwgem::dilepton::ml::PID_Label::kProton), static_cast(o2::aod::pwgem::dilepton::ml::Track_Type::kSecondary), false); registry.fill(HIST("V0/hTPCdEdx_P_Pr"), neg.tpcInnerParam(), neg.tpcSignal()); registry.fill(HIST("V0/hTOFbeta_P_Pr"), neg.tpcInnerParam(), neg.beta()); } @@ -791,12 +807,8 @@ struct TreeCreatorElectronMLDDA { registry.fill(HIST("V0/hXY_Gamma"), v0.x(), v0.y()); registry.fill(HIST("V0/hMassGamma_Rxy"), v0.v0radius(), v0.mGamma()); if ((v0cuts.cfg_min_mass_photon < v0.mGamma() && v0.mGamma() < v0cuts.cfg_max_mass_photon)) { - if (dist01(engine) < downscaling_electron || pos.tpcInnerParam() > max_pin_for_downscaling_electron) { - fillTrackTable(collision, pos, static_cast(o2::aod::pwgem::dilepton::ml::PID_Label::kElectron), static_cast(o2::aod::pwgem::dilepton::ml::Track_Type::kSecondary), false); - } - if (dist01(engine) < downscaling_electron || neg.tpcInnerParam() > max_pin_for_downscaling_electron) { - fillTrackTable(collision, neg, static_cast(o2::aod::pwgem::dilepton::ml::PID_Label::kElectron), static_cast(o2::aod::pwgem::dilepton::ml::Track_Type::kSecondary), false); - } + fillTrackTable(collision, pos, static_cast(o2::aod::pwgem::dilepton::ml::PID_Label::kElectron), static_cast(o2::aod::pwgem::dilepton::ml::Track_Type::kSecondary), false); + fillTrackTable(collision, neg, static_cast(o2::aod::pwgem::dilepton::ml::PID_Label::kElectron), static_cast(o2::aod::pwgem::dilepton::ml::Track_Type::kSecondary), false); registry.fill(HIST("V0/hTPCdEdx_P_El"), neg.tpcInnerParam(), neg.tpcSignal()); registry.fill(HIST("V0/hTOFbeta_P_El"), neg.tpcInnerParam(), neg.beta()); registry.fill(HIST("V0/hTPCdEdx_P_El"), pos.tpcInnerParam(), pos.tpcSignal()); @@ -883,9 +895,7 @@ struct TreeCreatorElectronMLDDA { 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(), bachelor.beta()); - if (dist01(engine) < downscaling_kaon || bachelor.tpcInnerParam() > max_pin_for_downscaling_kaon) { - fillTrackTable(collision, bachelor, static_cast(o2::aod::pwgem::dilepton::ml::PID_Label::kKaon), static_cast(o2::aod::pwgem::dilepton::ml::Track_Type::kPrimary), false); - } + fillTrackTable(collision, bachelor, static_cast(o2::aod::pwgem::dilepton::ml::PID_Label::kKaon), static_cast(o2::aod::pwgem::dilepton::ml::Track_Type::kSecondary), false); } } } // end of cascade loop @@ -927,14 +937,10 @@ struct TreeCreatorElectronMLDDA { if ((dalitzcuts.cfg_min_mass_ee < v12.M() && v12.M() < dalitzcuts.cfg_max_mass_ee) && (dalitzcuts.cfg_min_phiv_ee < phiv && phiv < dalitzcuts.cfg_max_phiv_ee)) { // ee from pi0 dalitz decay is found. if (isElectronTight(pos) && isElectron(neg)) { - if (dist01(engine) < downscaling_electron_primary || neg.tpcInnerParam() > max_pin_for_downscaling_electron_primary) { - fillTrackTable(collision, neg, static_cast(o2::aod::pwgem::dilepton::ml::PID_Label::kElectron), static_cast(o2::aod::pwgem::dilepton::ml::Track_Type::kPrimary), true); // primary electron candidates - } + fillTrackTable(collision, neg, static_cast(o2::aod::pwgem::dilepton::ml::PID_Label::kElectron), static_cast(o2::aod::pwgem::dilepton::ml::Track_Type::kPrimary), true); // primary electron candidates } if (isElectron(pos) && isElectronTight(neg)) { - if (dist01(engine) < downscaling_electron_primary || pos.tpcInnerParam() > max_pin_for_downscaling_electron_primary) { - fillTrackTable(collision, pos, static_cast(o2::aod::pwgem::dilepton::ml::PID_Label::kElectron), static_cast(o2::aod::pwgem::dilepton::ml::Track_Type::kPrimary), true); // primary electron candidates - } + fillTrackTable(collision, pos, static_cast(o2::aod::pwgem::dilepton::ml::PID_Label::kElectron), static_cast(o2::aod::pwgem::dilepton::ml::Track_Type::kPrimary), true); // primary electron candidates } } } // end of ULS pair loop From fa2e6511a60ae2e0c023842b215c5750bbe43f3d Mon Sep 17 00:00:00 2001 From: Francesca Ercolessi Date: Mon, 30 Jun 2025 11:21:23 +0200 Subject: [PATCH 267/871] [DPG] TOF PID task: add 3d histograms vs momentum and eta (#11832) --- DPG/Tasks/AOTTrack/PID/TOF/qaPIDTOF.cxx | 38 +++++++++++++++++-------- 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/DPG/Tasks/AOTTrack/PID/TOF/qaPIDTOF.cxx b/DPG/Tasks/AOTTrack/PID/TOF/qaPIDTOF.cxx index 24e5a09a21a..e350f1bbf28 100644 --- a/DPG/Tasks/AOTTrack/PID/TOF/qaPIDTOF.cxx +++ b/DPG/Tasks/AOTTrack/PID/TOF/qaPIDTOF.cxx @@ -15,16 +15,17 @@ /// \brief Implementation for QA tasks of the TOF PID quantities /// -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/StaticFor.h" -#include "Common/DataModel/TrackSelectionTables.h" #include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/PIDResponse.h" #include "Common/DataModel/FT0Corrected.h" +#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/TrackSelectionTables.h" #include "Common/TableProducer/PID/pidTOFBase.h" +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/StaticFor.h" +#include "Framework/runDataProcessing.h" + using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; @@ -135,7 +136,7 @@ struct tofPidQa { Configurable ptDeltaTEtaPhiMapMin{"ptDeltaTEtaPhiMapMin", 1.45f, "Threshold in pT to build the map of the delta time as a function of eta and phi"}; Configurable ptDeltaTEtaPhiMapMax{"ptDeltaTEtaPhiMapMax", 1.55f, "Threshold in pT to build the map of the delta time as a function of eta and phi"}; Configurable splitSignalPerCharge{"splitSignalPerCharge", true, "Split the signal per charge (reduces memory footprint if off)"}; - Configurable enableVsMomentumHistograms{"enableVsMomentumHistograms", false, "Enables plots vs momentum instead of just pT (reduces memory footprint if off)"}; + Configurable enableVsMomentumHistograms{"enableVsMomentumHistograms", 0, "1: Enables plots vs momentum instead of just pT 2: Enables plots vs momentum vs eta instead of just pT (reduces memory footprint if off)"}; Configurable requireGoodMatchTracks{"requireGoodMatchTracks", false, "Require good match tracks"}; Configurable pvContributorsMin{"pvContributorsMin", -10, "Minimum pvContributors"}; Configurable pvContributorsMax{"pvContributorsMax", 10000, "Maximum pvContributors"}; @@ -238,11 +239,16 @@ struct tofPidQa { return; } - if (enableVsMomentumHistograms) { + if (enableVsMomentumHistograms == 1) { histos.add(hdelta_evtime_fill[id].data(), axisTitle, kTH2F, {pAxis, deltaAxis}); histos.add(hdelta_evtime_tof[id].data(), axisTitle, kTH2F, {pAxis, deltaAxis}); histos.add(hdelta_evtime_ft0[id].data(), axisTitle, kTH2F, {pAxis, deltaAxis}); histos.add(hdelta_evtime_tofft0[id].data(), axisTitle, kTH2F, {pAxis, deltaAxis}); + } else if (enableVsMomentumHistograms == 2) { + histos.add(hdelta_evtime_fill[id].data(), axisTitle, kTH3F, {pAxis, etaAxis, deltaAxis}); + histos.add(hdelta_evtime_tof[id].data(), axisTitle, kTH3F, {pAxis, etaAxis, deltaAxis}); + histos.add(hdelta_evtime_ft0[id].data(), axisTitle, kTH3F, {pAxis, etaAxis, deltaAxis}); + histos.add(hdelta_evtime_tofft0[id].data(), axisTitle, kTH3F, {pAxis, etaAxis, deltaAxis}); } if (splitSignalPerCharge) { @@ -598,8 +604,10 @@ struct tofPidQa { // Filling info split per ev. time if (enableEvTimeSplitting) { if (t.isEvTimeTOF() && t.isEvTimeT0AC()) { // TOF + FT0 Ev. Time - if (enableVsMomentumHistograms) { + if (enableVsMomentumHistograms == 1) { histos.fill(HIST(hdelta_evtime_tofft0[id]), t.p(), diff); + } else if (enableVsMomentumHistograms == 2) { + histos.fill(HIST(hdelta_evtime_tofft0[id]), t.p(), t.eta(), diff); } if (splitSignalPerCharge) { histos.fill(HIST(hdelta_pt_evtime_tofft0[id]), t.pt(), diff, t.sign()); @@ -607,8 +615,10 @@ struct tofPidQa { histos.fill(HIST(hdelta_pt_evtime_tofft0[id]), t.pt(), diff); } } else if (t.isEvTimeT0AC()) { // FT0 Ev. Time - if (enableVsMomentumHistograms) { + if (enableVsMomentumHistograms == 1) { histos.fill(HIST(hdelta_evtime_ft0[id]), t.p(), diff); + } else if (enableVsMomentumHistograms == 2) { + histos.fill(HIST(hdelta_evtime_ft0[id]), t.p(), t.eta(), diff); } if (splitSignalPerCharge) { histos.fill(HIST(hdelta_pt_evtime_ft0[id]), t.pt(), diff, t.sign()); @@ -616,8 +626,10 @@ struct tofPidQa { histos.fill(HIST(hdelta_pt_evtime_ft0[id]), t.pt(), diff); } } else if (t.isEvTimeTOF()) { // TOF Ev. Time - if (enableVsMomentumHistograms) { + if (enableVsMomentumHistograms == 1) { histos.fill(HIST(hdelta_evtime_tof[id]), t.p(), diff); + } else if (enableVsMomentumHistograms == 2) { + histos.fill(HIST(hdelta_evtime_tof[id]), t.p(), t.eta(), diff); } if (splitSignalPerCharge) { histos.fill(HIST(hdelta_pt_evtime_tof[id]), t.pt(), diff, t.sign()); @@ -625,8 +637,10 @@ struct tofPidQa { histos.fill(HIST(hdelta_pt_evtime_tof[id]), t.pt(), diff); } } else { // No Ev. Time -> Fill Ev. Time - if (enableVsMomentumHistograms) { + if (enableVsMomentumHistograms == 1) { histos.fill(HIST(hdelta_evtime_fill[id]), t.p(), diff); + } else if (enableVsMomentumHistograms == 2) { + histos.fill(HIST(hdelta_evtime_fill[id]), t.p(), t.eta(), diff); } if (splitSignalPerCharge) { histos.fill(HIST(hdelta_pt_evtime_fill[id]), t.pt(), diff, t.sign()); From 7eae58c5590f403861403171b793bf48ee3078b7 Mon Sep 17 00:00:00 2001 From: Gyula Bencedi Date: Mon, 30 Jun 2025 11:37:18 +0200 Subject: [PATCH 268/871] [PWGLF] Separate flags for QA histos filling (#11831) --- .../GlobalEventProperties/flattenictyPikp.cxx | 126 +++++++++--------- 1 file changed, 65 insertions(+), 61 deletions(-) diff --git a/PWGLF/Tasks/GlobalEventProperties/flattenictyPikp.cxx b/PWGLF/Tasks/GlobalEventProperties/flattenictyPikp.cxx index df99f8b7a6f..cf9c401c16b 100644 --- a/PWGLF/Tasks/GlobalEventProperties/flattenictyPikp.cxx +++ b/PWGLF/Tasks/GlobalEventProperties/flattenictyPikp.cxx @@ -196,7 +196,9 @@ struct FlattenictyPikp { Configurable applyCalibGain{"applyCalibGain", true, "equalize detector amplitudes"}; Configurable applyCalibVtx{"applyCalibVtx", false, "equalize Amp vs vtx"}; Configurable applyCalibDeDx{"applyCalibDeDx", true, "calibration of dedx signal"}; - Configurable cfgFillQAHisto{"cfgFillQAHisto", true, "fill QA histograms"}; + Configurable cfgFillTrackQaHist{"cfgFillTrackQaHist", false, "fill track QA histograms"}; + Configurable cfgFilldEdxQaHist{"cfgFilldEdxQaHist", false, "fill dEdx QA histograms"}; + Configurable cfgFillNsigmaQAHist{"cfgFillNsigmaQAHist", false, "fill nsigma QA histograms"}; Configurable cfgFillChrgType{"cfgFillChrgType", true, "fill histograms per charge types"}; Configurable> paramsFuncMIPposEta{"paramsFuncMIPposEta", std::vector{-1.f}, "parameters of pol2"}; Configurable> paramsFuncMIPnegEta{"paramsFuncMIPnegEta", std::vector{-1.f}, "parameters of pol2"}; @@ -407,63 +409,64 @@ struct FlattenictyPikp { if (doprocessFlat) { flatchrg.add("Events/hVtxZ", "Measured vertex z position", HistType::kTH1D, {vtxzAxis}); flatchrg.add("Events/hFlatVsMultEst", "hFlatVsMultEst", HistType::kTH2D, {flatAxis, multAxis}); - - if (cfgFillQAHisto) { - flatchrg.add("Tracks/postSel/hPtPhi", "; #it{p}_{T} (GeV/#it{c}); fmod(#varphi,#pi/9)", {HistType::kTH2D, {ptAxis, phiAxisMod}}); - // P vs PT vs ETA - flatchrg.add("Tracks/postSel/hPVsPtEta", "; #it{p} (GeV/#it{c}); #it{p}_{T} (GeV/#it{c}); #eta;", {HistType::kTH3D, {pAxis, ptAxis, etaAxis}}); - flatchrg.addClone("Tracks/postSel/", "Tracks/preSel/"); - // dEdx MIP, Plateau - flatchrg.add("Tracks/postCalib/all/hMIP", "; mult; flat; #eta; #LT dE/dx #GT_{MIP, primary tracks};", {HistType::kTHnSparseD, {multAxis, flatAxis, etaAxis, dEdxAxis}}); - flatchrg.add("Tracks/postCalib/all/hPlateau", "; mult; flat; #eta; #LT dE/dx #GT_{Plateau, primary tracks};", {HistType::kTHnSparseD, {multAxis, flatAxis, etaAxis, dEdxAxis}}); - flatchrg.add("Tracks/postCalib/all/hMIPVsEta", "; #eta; #LT dE/dx #GT_{MIP, primary tracks};", {HistType::kTH2D, {etaAxis, dEdxAxis}}); - flatchrg.add("Tracks/postCalib/all/pMIPVsEta", "; #eta; #LT dE/dx #GT_{MIP, primary tracks};", {HistType::kTProfile, {etaAxis}}); - flatchrg.add("Tracks/postCalib/all/hMIPVsPhi", "; #varphi; #LT dE/dx #GT_{MIP, primary tracks};", {HistType::kTH2D, {phiAxis, dEdxAxis}}); - flatchrg.add("Tracks/postCalib/all/pMIPVsPhi", "; #varphi; #LT dE/dx #GT_{MIP, primary tracks};", {HistType::kTProfile, {phiAxis}}); - flatchrg.add("Tracks/postCalib/all/hMIPVsPhiVsEta", "; #varphi; #LT dE/dx #GT_{MIP, primary tracks}; #eta;", {HistType::kTH3D, {phiAxis, dEdxAxis, etaAxis}}); - flatchrg.add("Tracks/postCalib/all/hPlateauVsEta", "; #eta; #LT dE/dx #GT_{Plateau, primary tracks};", {HistType::kTH2D, {etaAxis, dEdxAxis}}); - flatchrg.add("Tracks/postCalib/all/pPlateauVsEta", "; #eta; #LT dE/dx #GT_{Plateau, primary tracks};", {HistType::kTProfile, {etaAxis}}); - flatchrg.add("Tracks/postCalib/all/hPlateauVsPhi", "; #varphi; #LT dE/dx #GT_{Plateau, primary tracks};", {HistType::kTH2D, {phiAxis, dEdxAxis}}); - flatchrg.add("Tracks/postCalib/all/pPlateauVsPhi", "; #varphi; #LT dE/dx #GT_{Plateau, primary tracks};", {HistType::kTProfile, {phiAxis}}); - flatchrg.add("Tracks/postCalib/all/hPlateauVsPhiVsEta", "; #varphi; #LT dE/dx #GT_{Plateau, primary tracks}; #eta;", {HistType::kTH3D, {phiAxis, dEdxAxis, etaAxis}}); - if (cfgFillChrgType) { - flatchrg.addClone("Tracks/postCalib/all/", "Tracks/postCalib/pos/"); - flatchrg.addClone("Tracks/postCalib/all/", "Tracks/postCalib/neg/"); - flatchrg.addClone("Tracks/postCalib/all/", "Tracks/preCalib/all/"); - flatchrg.addClone("Tracks/preCalib/all/", "Tracks/preCalib/pos/"); - flatchrg.addClone("Tracks/preCalib/all/", "Tracks/preCalib/neg/"); + flatchrg.add("Tracks/postSel/hPVsPtEta", "; #it{p} (GeV/#it{c}); #it{p}_{T} (GeV/#it{c}); #eta;", {HistType::kTH3D, {pAxis, ptAxis, etaAxis}}); + if (cfgFillTrackQaHist || cfgFilldEdxQaHist || cfgFillNsigmaQAHist) { + if (cfgFillTrackQaHist) { + flatchrg.add("Tracks/postSel/hPtPhi", "; #it{p}_{T} (GeV/#it{c}); fmod(#varphi,#pi/9)", {HistType::kTH2D, {ptAxis, phiAxisMod}}); + flatchrg.add("Tracks/QA/hPtVsWOcutDCA", "hPtVsWOcutDCA", HistType::kTH2D, {ptAxis, dcaXYAxis}); + flatchrg.add("Tracks/QA/hPt", "", HistType::kTH1D, {ptAxis}); + flatchrg.add("Tracks/QA/hPhi", "", HistType::kTH1D, {phiAxis}); + flatchrg.add("Tracks/QA/hEta", "", HistType::kTH1D, {etaAxis}); + flatchrg.add("Tracks/QA/hDCAXYvsPt", "", HistType::kTH2D, {ptAxis, dcaXYAxis}); + flatchrg.add("Tracks/QA/hDCAZvsPt", "", HistType::kTH2D, {ptAxis, dcaZAxis}); + // tpc + flatchrg.add("Tracks/QA/hShTpcClvsPt", "", {HistType::kTH2D, {ptAxis, shCluserAxis}}); + flatchrg.add("Tracks/QA/hCrossTPCvsPt", "", {HistType::kTH2D, {ptAxis, clTpcAxis}}); + flatchrg.add("Tracks/QA/hTPCCluster", "N_{cluster}", HistType::kTH1D, {{200, -0.5, 199.5}}); + flatchrg.add("Tracks/QA/tpcNClsShared", " ; # shared TPC clusters TPC", HistType::kTH1D, {{165, -0.5, 164.5}}); + flatchrg.add("Tracks/QA/tpcCrossedRows", " ; # crossed TPC rows", HistType::kTH1D, {{165, -0.5, 164.5}}); + flatchrg.add("Tracks/QA/tpcCrossedRowsOverFindableCls", " ; crossed rows / findable TPC clusters", HistType::kTH1D, {{60, 0.7, 1.3}}); + // its + flatchrg.add("Tracks/QA/itsNCls", " ; # ITS clusters", HistType::kTH1D, {{8, -0.5, 7.5}}); + flatchrg.add("Tracks/QA/hChi2ITSTrkSegment", "chi2ITS", HistType::kTH1D, {{100, -0.5, 99.5}}); + // tof + flatchrg.add("Tracks/QA/hTOFPvsBeta", "Beta from TOF; #it{p} (GeV/#it{c}); #beta", {HistType::kTH2D, {pAxis, {120, 0.0, 1.2}}}); + flatchrg.add("Tracks/QA/hTOFpi", "Primary Pions from TOF; #eta; #it{p} (GeV/#it{c}); dEdx", {HistType::kTHnSparseD, {etaAxis, pAxis, dEdxAxis}}); + } + if (cfgFilldEdxQaHist) { + flatchrg.add("Tracks/postCalib/all/hMIP", "; mult; flat; #eta; #LT dE/dx #GT_{MIP, primary tracks};", {HistType::kTHnSparseD, {multAxis, flatAxis, etaAxis, dEdxAxis}}); + flatchrg.add("Tracks/postCalib/all/hPlateau", "; mult; flat; #eta; #LT dE/dx #GT_{Plateau, primary tracks};", {HistType::kTHnSparseD, {multAxis, flatAxis, etaAxis, dEdxAxis}}); + flatchrg.add("Tracks/postCalib/all/hMIPVsEta", "; #eta; #LT dE/dx #GT_{MIP, primary tracks};", {HistType::kTH2D, {etaAxis, dEdxAxis}}); + flatchrg.add("Tracks/postCalib/all/pMIPVsEta", "; #eta; #LT dE/dx #GT_{MIP, primary tracks};", {HistType::kTProfile, {etaAxis}}); + flatchrg.add("Tracks/postCalib/all/hMIPVsPhi", "; #varphi; #LT dE/dx #GT_{MIP, primary tracks};", {HistType::kTH2D, {phiAxis, dEdxAxis}}); + flatchrg.add("Tracks/postCalib/all/pMIPVsPhi", "; #varphi; #LT dE/dx #GT_{MIP, primary tracks};", {HistType::kTProfile, {phiAxis}}); + flatchrg.add("Tracks/postCalib/all/hMIPVsPhiVsEta", "; #varphi; #LT dE/dx #GT_{MIP, primary tracks}; #eta;", {HistType::kTH3D, {phiAxis, dEdxAxis, etaAxis}}); + flatchrg.add("Tracks/postCalib/all/hPlateauVsEta", "; #eta; #LT dE/dx #GT_{Plateau, primary tracks};", {HistType::kTH2D, {etaAxis, dEdxAxis}}); + flatchrg.add("Tracks/postCalib/all/pPlateauVsEta", "; #eta; #LT dE/dx #GT_{Plateau, primary tracks};", {HistType::kTProfile, {etaAxis}}); + flatchrg.add("Tracks/postCalib/all/hPlateauVsPhi", "; #varphi; #LT dE/dx #GT_{Plateau, primary tracks};", {HistType::kTH2D, {phiAxis, dEdxAxis}}); + flatchrg.add("Tracks/postCalib/all/pPlateauVsPhi", "; #varphi; #LT dE/dx #GT_{Plateau, primary tracks};", {HistType::kTProfile, {phiAxis}}); + flatchrg.add("Tracks/postCalib/all/hPlateauVsPhiVsEta", "; #varphi; #LT dE/dx #GT_{Plateau, primary tracks}; #eta;", {HistType::kTH3D, {phiAxis, dEdxAxis, etaAxis}}); + if (cfgFillChrgType) { + flatchrg.addClone("Tracks/postCalib/all/", "Tracks/postCalib/pos/"); + flatchrg.addClone("Tracks/postCalib/all/", "Tracks/postCalib/neg/"); + flatchrg.addClone("Tracks/postCalib/all/", "Tracks/preCalib/all/"); + flatchrg.addClone("Tracks/preCalib/all/", "Tracks/preCalib/pos/"); + flatchrg.addClone("Tracks/preCalib/all/", "Tracks/preCalib/neg/"); + } } - // fillTrackQA - flatchrg.add("Tracks/QA/hPtVsWOcutDCA", "hPtVsWOcutDCA", HistType::kTH2D, {ptAxis, dcaXYAxis}); - flatchrg.add("Tracks/QA/hPt", "", HistType::kTH1D, {ptAxis}); - flatchrg.add("Tracks/QA/hPhi", "", HistType::kTH1D, {phiAxis}); - flatchrg.add("Tracks/QA/hEta", "", HistType::kTH1D, {etaAxis}); - flatchrg.add("Tracks/QA/hDCAXYvsPt", "", HistType::kTH2D, {ptAxis, dcaXYAxis}); - flatchrg.add("Tracks/QA/hDCAZvsPt", "", HistType::kTH2D, {ptAxis, dcaZAxis}); - // tpc - flatchrg.add("Tracks/QA/hShTpcClvsPt", "", {HistType::kTH2D, {ptAxis, shCluserAxis}}); - flatchrg.add("Tracks/QA/hCrossTPCvsPt", "", {HistType::kTH2D, {ptAxis, clTpcAxis}}); - flatchrg.add("Tracks/QA/hTPCCluster", "N_{cluster}", HistType::kTH1D, {{200, -0.5, 199.5}}); - flatchrg.add("Tracks/QA/tpcNClsShared", " ; # shared TPC clusters TPC", HistType::kTH1D, {{165, -0.5, 164.5}}); - flatchrg.add("Tracks/QA/tpcCrossedRows", " ; # crossed TPC rows", HistType::kTH1D, {{165, -0.5, 164.5}}); - flatchrg.add("Tracks/QA/tpcCrossedRowsOverFindableCls", " ; crossed rows / findable TPC clusters", HistType::kTH1D, {{60, 0.7, 1.3}}); - // its - flatchrg.add("Tracks/QA/itsNCls", " ; # ITS clusters", HistType::kTH1D, {{8, -0.5, 7.5}}); - flatchrg.add("Tracks/QA/hChi2ITSTrkSegment", "chi2ITS", HistType::kTH1D, {{100, -0.5, 99.5}}); - // tof - flatchrg.add("Tracks/QA/hTOFPvsBeta", "Beta from TOF; #it{p} (GeV/#it{c}); #beta", {HistType::kTH2D, {pAxis, {120, 0.0, 1.2}}}); - flatchrg.add("Tracks/QA/hTOFpi", "Primary Pions from TOF; #eta; #it{p} (GeV/#it{c}); dEdx", {HistType::kTHnSparseD, {etaAxis, pAxis, dEdxAxis}}); - // nsigma - for (int i = 0; i < NpartChrg; i++) { - const std::string strID = Form("/%s/%s", (i < Npart) ? "pos" : "neg", Pid[i % Npart]); - hPtNsigmaTPC[i] = flatchrg.add("Tracks/hPtNsigmaTPC" + strID, " ; p_{T} (GeV/c)", HistType::kTH2D, {ptAxis, nSigmaTPCAxis}); - if (cfgStoreThnSparse) { - hThPtNsigmaTPC[i] = flatchrg.add("Tracks/hThPtNsigmaTPC" + strID, " ; p_{T} (GeV/c)", HistType::kTHnSparseD, {ptAxis, nSigmaTPCAxis, multAxis, flatAxis}); + if (cfgFillNsigmaQAHist) { + for (int i = 0; i < NpartChrg; i++) { + const std::string strID = Form("/%s/%s", (i < Npart) ? "pos" : "neg", Pid[i % Npart]); + hPtNsigmaTPC[i] = flatchrg.add("Tracks/hPtNsigmaTPC" + strID, " ; p_{T} (GeV/c)", HistType::kTH2D, {ptAxis, nSigmaTPCAxis}); + if (cfgStoreThnSparse) { + hThPtNsigmaTPC[i] = flatchrg.add("Tracks/hThPtNsigmaTPC" + strID, " ; p_{T} (GeV/c)", HistType::kTHnSparseD, {ptAxis, nSigmaTPCAxis, multAxis, flatAxis}); + } + hPtNsigmaTOF[i] = flatchrg.add("Tracks/hPtNsigmaTOF" + strID, " ; p_{T} (GeV/c)", HistType::kTH2D, {ptAxis, nSigmaTOFAxis}); + hPtNsigmaTPCTOF[i] = flatchrg.add("Tracks/hPtNsigmaTPCTOF" + strID, PidChrg[i], HistType::kTH2D, {nSigmaTPCAxis, nSigmaTOFAxis}); } - hPtNsigmaTOF[i] = flatchrg.add("Tracks/hPtNsigmaTOF" + strID, " ; p_{T} (GeV/c)", HistType::kTH2D, {ptAxis, nSigmaTOFAxis}); - hPtNsigmaTPCTOF[i] = flatchrg.add("Tracks/hPtNsigmaTPCTOF" + strID, PidChrg[i], HistType::kTH2D, {nSigmaTPCAxis, nSigmaTOFAxis}); } } + flatchrg.addClone("Tracks/postSel/", "Tracks/preSel/"); // FV0 QA flatchrg.add("FV0/hFV0AmplWCalib", "", HistType::kTH2D, {{48, -0.5, 47.5, "channel"}, {500, -0.5, +19999.5, "FV0 amplitude"}}); flatchrg.add("FV0/hFV0AmplvsVtxzWoCalib", "", HistType::kTH2D, {{30, -15.0, +15.0, "z vtx (cm)"}, {1000, -0.5, +39999.5, "FV0 amplitude"}}); @@ -694,14 +697,16 @@ struct FlattenictyPikp { for (const auto& track : tracks) { float dEdx = track.tpcSignal(); bool posP = (track.sign() * track.tpcInnerParam() > 0) ? true : false; - if (cfgFillQAHisto) { + if (cfgFillTrackQaHist) { fillTrackQA(track); } if (!isGoodTrack(track, magField)) { continue; } - if (cfgFillQAHisto) { + if (cfgFillTrackQaHist) { fillTrackQA(track); + } + if (cfgFilldEdxQaHist) { filldEdxQA(track, collision); if (posP) { filldEdxQA(track, collision); @@ -712,7 +717,7 @@ struct FlattenictyPikp { if (applyCalibDeDx) { dEdx *= (50.0 / getCalibration(true, track.eta())); } - if (cfgFillQAHisto) { + if (cfgFilldEdxQaHist) { filldEdxQA(track, collision); if (posP) { filldEdxQA(track, collision); @@ -823,13 +828,13 @@ struct FlattenictyPikp { phimodn += o2::constants::math::PI / 18.0; // to center gap in the middle phimodn = std::fmod(phimodn, o2::constants::math::PI / 9.0); - if (cfgFillQAHisto) { + if (cfgFillTrackQaHist) { flatchrg.fill(HIST("Tracks/preSel/hPtPhi"), track.pt(), phimodn); } if (phimodn < fphiCutHigh->Eval(track.pt()) && phimodn > fphiCutLow->Eval(track.pt())) { return false; } - if (cfgFillQAHisto) { + if (cfgFillTrackQaHist) { flatchrg.fill(HIST("Tracks/postSel/hPtPhi"), track.pt(), phimodn); } return true; @@ -1035,7 +1040,6 @@ struct FlattenictyPikp { } } } - flatchrg.fill(HIST(kPrefix) + HIST(kStatus[ft]) + HIST("hPVsPtEta"), track.tpcInnerParam(), track.pt(), track.eta()); } @@ -1423,7 +1427,7 @@ struct FlattenictyPikp { auto v0sPerCollision = v0s.sliceBy(perColV0s, collision.globalIndex()); v0sPerCollision.bindExternalIndices(&tracks); filldEdx(tracksPerCollision, v0sPerCollision, collision, bcs); - if (cfgFillQAHisto) { + if (cfgFillNsigmaQAHist) { fillNsigma(tracksPerCollision, collision); fillNsigma(tracksPerCollision, collision); fillNsigma(tracksPerCollision, collision); From 1b12a5e1486eb631ad1a786b07c8677cf21eb75f Mon Sep 17 00:00:00 2001 From: Fabrizio Date: Mon, 30 Jun 2025 11:54:09 +0200 Subject: [PATCH 269/871] [PWGHF] Fix event selection for generated signals (#11822) Co-authored-by: ALICE Action Bot --- PWGHF/D2H/DataModel/ReducedDataModel.h | 20 +- .../dataCreatorCharmHadPiReduced.cxx | 217 +++++++++++------- .../dataCreatorJpsiHadReduced.cxx | 72 ++++-- .../TableProducer/candidateCreator2Prong.cxx | 2 +- .../TableProducer/candidateCreator3Prong.cxx | 2 +- .../TableProducer/candidateCreatorCascade.cxx | 2 +- PWGHF/TableProducer/candidateCreatorDstar.cxx | 2 +- .../candidateCreatorSigmac0plusplus.cxx | 3 +- .../candidateCreatorXicToXiPiPi.cxx | 2 +- PWGHF/Tasks/taskMcValidation.cxx | 2 +- 10 files changed, 218 insertions(+), 106 deletions(-) diff --git a/PWGHF/D2H/DataModel/ReducedDataModel.h b/PWGHF/D2H/DataModel/ReducedDataModel.h index c23a22efcad..2675e4b70fe 100644 --- a/PWGHF/D2H/DataModel/ReducedDataModel.h +++ b/PWGHF/D2H/DataModel/ReducedDataModel.h @@ -832,7 +832,10 @@ DECLARE_SOA_TABLE(HfMcGenRedB0s, "AOD", "HFMCGENREDB0", //! Generation-level MC hf_b0_mc::EtaProng0, hf_b0_mc::PtProng1, hf_b0_mc::YProng1, - hf_b0_mc::EtaProng1); + hf_b0_mc::EtaProng1, + hf_reduced_collision::HfCollisionRejectionMap, + cent::CentFT0C, + cent::CentFT0M); // store all configurables values used in the first part of the workflow // so we can use them in the B0 part @@ -923,7 +926,10 @@ DECLARE_SOA_TABLE(HfMcGenRedBps, "AOD", "HFMCGENREDBP", //! Generation-level MC hf_bplus_mc::EtaProng0, hf_bplus_mc::PtProng1, hf_bplus_mc::YProng1, - hf_bplus_mc::EtaProng1); + hf_bplus_mc::EtaProng1, + hf_reduced_collision::HfCollisionRejectionMap, + cent::CentFT0C, + cent::CentFT0M); // store all configurables values used in the first part of the workflow // so we can use them in the Bplus part @@ -1025,7 +1031,10 @@ DECLARE_SOA_TABLE(HfMcGenRedBss, "AOD", "HFMCGENREDBS", //! Generation-level MC hf_bs_mc::EtaProng0, hf_bs_mc::PtProng1, hf_bs_mc::YProng1, - hf_bs_mc::EtaProng1); + hf_bs_mc::EtaProng1, + hf_reduced_collision::HfCollisionRejectionMap, + cent::CentFT0C, + cent::CentFT0M); // store all configurables values used in the first part of the workflow // so we can use them in the Bs part @@ -1109,7 +1118,10 @@ DECLARE_SOA_TABLE(HfMcGenRedLbs, "AOD", "HFMCGENREDLB", //! Generation-level MC hf_lb_mc::EtaProng0, hf_lb_mc::PtProng1, hf_lb_mc::YProng1, - hf_lb_mc::EtaProng1); + hf_lb_mc::EtaProng1, + hf_reduced_collision::HfCollisionRejectionMap, + cent::CentFT0C, + cent::CentFT0M); // store all configurables values used in the first part of the workflow // so we can use them in the B0 part diff --git a/PWGHF/D2H/TableProducer/dataCreatorCharmHadPiReduced.cxx b/PWGHF/D2H/TableProducer/dataCreatorCharmHadPiReduced.cxx index 9f3f1e6fb6d..ea593bd5ee0 100644 --- a/PWGHF/D2H/TableProducer/dataCreatorCharmHadPiReduced.cxx +++ b/PWGHF/D2H/TableProducer/dataCreatorCharmHadPiReduced.cxx @@ -38,6 +38,7 @@ #include "Common/DataModel/Qvectors.h" #include "Common/DataModel/TrackSelectionTables.h" +#include "Framework/RunningWorkflowInfo.h" #include #include #include @@ -62,8 +63,6 @@ #include #include -#include - #include #include #include @@ -149,9 +148,20 @@ struct HfDataCreatorCharmHadPiReduced { Produces rowHfLcPiMcCheckReduced; Produces rowHfLbMcGenReduced; + // generic configurables + struct : o2::framework::ConfigurableGroup { + // event selection + Configurable skipRejectedCollisions{"skipRejectedCollisions", true, "skips collisions rejected by the event selection, instead of flagging only"}; + // magnetic field setting from CCDB + Configurable ccdbUrl{"ccdbUrl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable ccdbPathGrpMag{"ccdbPathGrpMag", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object (Run 3)"}; + // pair selection + Configurable invMassWindowCharmHadPi{"invMassWindowCharmHadPi", 0.3, "invariant-mass window for CharmHad-Pi pair preselections (GeV/c2)"}; + // MC extra + Configurable checkDecayTypeMc{"checkDecayTypeMc", false, "flag to enable MC checks on decay type"}; + } configs; // vertexing struct : o2::framework::ConfigurableGroup { - // Configurable bz{"bz", 5., "magnetic field"}; Configurable propagateToPCA{"propagateToPCA", true, "create tracks version propagated to PCA"}; Configurable useAbsDCA{"useAbsDCA", false, "Minimise abs. distance rather than chi2"}; Configurable useWeightedFinalPCA{"useWeightedFinalPCA", false, "Recalculate vertex position using track covariances, effective only if useAbsDCA is true"}; @@ -168,8 +178,7 @@ struct HfDataCreatorCharmHadPiReduced { Configurable> binsPtPion{"binsPtPion", std::vector{hf_cuts_single_track::vecBinsPtTrack}, "track pT bin limits for pion DCA XY pT-dependent cut"}; Configurable> cutsTrackPionDCA{"cutsTrackPionDCA", {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 selections per pT bin for pions"}; } trackPionConfigurations; - Configurable invMassWindowCharmHadPi{"invMassWindowCharmHadPi", 0.3, "invariant-mass window for CharmHad-Pi pair preselections (GeV/c2)"}; - + // HF flags struct : o2::framework::ConfigurableGroup { Configurable selectionFlagDplus{"selectionFlagDplus", 7, "Selection Flag for D+"}; Configurable selectionFlagDs{"selectionFlagDs", 7, "Selection Flag for Ds"}; @@ -177,15 +186,10 @@ struct HfDataCreatorCharmHadPiReduced { Configurable selectionFlagD0bar{"selectionFlagD0bar", 1, "Selection Flag for D0bar"}; Configurable selectionFlagLc{"selectionFlagLc", 1, "Selection Flag for Lc"}; } hfflagConfigurations; - // magnetic field setting from CCDB - Configurable ccdbUrl{"ccdbUrl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; - Configurable ccdbPathGrpMag{"ccdbPathGrpMag", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object (Run 3)"}; - - // MC extra - Configurable checkDecayTypeMc{"checkDecayTypeMc", false, "flag to enable MC checks on decay type"}; HfHelper hfHelper; o2::hf_evsel::HfEventSelection hfEvSel; + o2::hf_evsel::HfEventSelectionMc hfEvSelMc; // CCDB service Service ccdb; @@ -224,6 +228,7 @@ struct HfDataCreatorCharmHadPiReduced { using CollisionsWCent = soa::Join; using CollisionsWCentAndMcLabels = soa::Join; using CollisionsWCentAndQvectors = soa::Join; + using BCsInfo = soa::Join; Filter filterSelectDplusCandidates = (aod::hf_sel_candidate_dplus::isSelDplusToPiKPi >= hfflagConfigurations.selectionFlagDplus); Filter filterSelectDsCandidates = (aod::hf_sel_candidate_ds::isSelDsToKKPi >= hfflagConfigurations.selectionFlagDs || aod::hf_sel_candidate_ds::isSelDsToPiKK >= hfflagConfigurations.selectionFlagDs); @@ -240,6 +245,7 @@ struct HfDataCreatorCharmHadPiReduced { Preslice candsLcPerCollisionWithMl = aod::track_association::collisionId; Preslice trackIndicesPerCollision = aod::track_association::collisionId; PresliceUnsorted colPerMcCollision = aod::mccollisionlabel::mcCollisionId; + Preslice mcParticlesPerMcCollision = aod::mcparticle::mcCollisionId; std::shared_ptr hCandidatesD0, hCandidatesDPlus, hCandidatesDs, hCandidatesLc; HistogramRegistry registry{"registry"}; @@ -247,7 +253,7 @@ struct HfDataCreatorCharmHadPiReduced { std::array arrPDGResonantDsPhiPi = {kPhi, kPiPlus}; // Ds± → Phi π± std::array arrPDGResonantDKstarK = {kK0Star892, kKPlus}; // Ds± → K*(892)0bar K± and D± → K*(892)0bar K± - void init(InitContext const&) + void init(InitContext& initContext) { std::array doProcess = {doprocessDplusPiData, doprocessDplusPiDataWithMl, doprocessDplusPiMc, doprocessDplusPiMcWithMl, doprocessDsPiData, doprocessDsPiDataWithMl, doprocessDsPiMc, doprocessDsPiMcWithMl, @@ -272,8 +278,8 @@ struct HfDataCreatorCharmHadPiReduced { massC = MassLambdaCPlus; massB = MassLambdaB0; } - invMass2ChHadPiMin = (massB - invMassWindowCharmHadPi) * (massB - invMassWindowCharmHadPi); - invMass2ChHadPiMax = (massB + invMassWindowCharmHadPi) * (massB + invMassWindowCharmHadPi); + invMass2ChHadPiMin = (massB - configs.invMassWindowCharmHadPi) * (massB - configs.invMassWindowCharmHadPi); + invMass2ChHadPiMax = (massB + configs.invMassWindowCharmHadPi) * (massB + configs.invMassWindowCharmHadPi); // Initialize fitter if (doprocessDplusPiData || doprocessDplusPiDataWithMl || doprocessDplusPiMc || doprocessDplusPiMcWithMl || @@ -298,7 +304,7 @@ struct HfDataCreatorCharmHadPiReduced { } // Configure CCDB access - ccdb->setURL(ccdbUrl); + ccdb->setURL(configs.ccdbUrl); ccdb->setCaching(true); ccdb->setLocalObjectValidityChecking(); runNumber = 0; @@ -354,6 +360,16 @@ struct HfDataCreatorCharmHadPiReduced { // init HF event selection helper hfEvSel.init(registry); + if (doprocessDplusPiMc || doprocessDplusPiMcWithMl || doprocessDsPiMc || doprocessDsPiMcWithMl || doprocessD0PiMc || doprocessD0PiMcWithMl || doprocessLcPiMc || doprocessLcPiMcWithMl) { + const auto& workflows = initContext.services().get(); + for (const DeviceSpec& device : workflows.devices) { + if (device.name.compare("hf-data-creator-charm-had-pi-reduced") == 0) { + // init HF event selection helper + hfEvSelMc.init(device, registry); + break; + } + } + } } /// Pion selection (D Pi <-- B0) @@ -471,7 +487,7 @@ struct HfDataCreatorCharmHadPiReduced { } // additional checks for correlated backgrounds - if (checkDecayTypeMc) { + if (configs.checkDecayTypeMc) { // B0 → Ds- π+ → (K- K+ π-) π+ if (!flag) { indexRec = RecoDecay::getMatchedMCRec(particlesMc, std::array{vecDaughtersB[0], vecDaughtersB[1], vecDaughtersB[2], vecDaughtersB[3]}, Pdg::kB0, std::array{-kKPlus, +kKPlus, -kPiPlus, +kPiPlus}, true, &sign, 3); @@ -598,7 +614,7 @@ struct HfDataCreatorCharmHadPiReduced { } // additional checks for correlated backgrounds - if (checkDecayTypeMc) { + if (configs.checkDecayTypeMc) { // B0 → Ds- π+ → (K- K+ π-) π+ if (!flag) { indexRec = RecoDecay::getMatchedMCRec(particlesMc, std::array{vecDaughtersB[0], vecDaughtersB[1], vecDaughtersB[2], vecDaughtersB[3]}, Pdg::kB0, std::array{-kKPlus, +kKPlus, -kPiPlus, +kPiPlus}, true, &sign, 3); @@ -738,7 +754,7 @@ struct HfDataCreatorCharmHadPiReduced { } } // additional checks for correlated backgrounds - if (checkDecayTypeMc) { + if (configs.checkDecayTypeMc) { if (!flag) { // B+ → D0(bar) K+ → (K+ π-) K+ indexRec = RecoDecay::getMatchedMCRec(particlesMc, std::array{vecDaughtersB[0], vecDaughtersB[1], vecDaughtersB[2]}, Pdg::kBPlus, std::array{+kKPlus, +kKPlus, -kPiPlus}, true, &sign, 2); @@ -837,7 +853,7 @@ struct HfDataCreatorCharmHadPiReduced { } // additional checks for correlated backgrounds - if (checkDecayTypeMc) { + if (configs.checkDecayTypeMc) { // Lb → Lc+ K- → (p K- π+) K- if (!flag) { indexRec = RecoDecay::getMatchedMCRec(particlesMc, std::array{vecDaughtersB[0], vecDaughtersB[1], vecDaughtersB[2], vecDaughtersB[3]}, Pdg::kLambdaB0, std::array{+kProton, -kKPlus, +kPiPlus, -kKPlus}, true, &sign, 3); @@ -921,15 +937,22 @@ struct HfDataCreatorCharmHadPiReduced { } } - template + template void runDataCreation(Coll const& collision, CCharmCands const& candsC, aod::TrackAssoc const& trackIndices, TTracks const&, PParticles const& particlesMc, uint64_t const& indexCollisionMaxNumContrib, - aod::BCsWithTimestamps const&) + BBCs const&) { + registry.fill(HIST("hEvents"), 1 + Event::Processed); + float centrality = -1.f; + auto hfRejMap = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb, registry); + if (configs.skipRejectedCollisions && hfRejMap != 0) { + return; + } + // helpers for ReducedTables filling int indexHfReducedCollision = hfReducedCollision.lastIndex() + 1; // std::map where the key is the track.globalIndex() and @@ -945,7 +968,7 @@ struct HfDataCreatorCharmHadPiReduced { auto bc = collision.template bc_as(); if (runNumber != bc.runNumber()) { LOG(info) << ">>>>>>>>>>>> Current run number: " << runNumber; - o2::parameters::GRPMagField* grpo = ccdb->getForTimeStamp(ccdbPathGrpMag, bc.timestamp()); + o2::parameters::GRPMagField* grpo = ccdb->getForTimeStamp(configs.ccdbPathGrpMag, bc.timestamp()); if (grpo == nullptr) { LOGF(fatal, "Run 3 GRP object (type o2::parameters::GRPMagField) is not available in CCDB for run=%d at timestamp=%llu", bc.runNumber(), bc.timestamp()); } @@ -1280,14 +1303,12 @@ struct HfDataCreatorCharmHadPiReduced { } } // candsC loop - registry.fill(HIST("hEvents"), 1 + Event::Processed); if (!fillHfReducedCollision) { registry.fill(HIST("hEvents"), 1 + Event::NoCharmHadPiSelected); return; } registry.fill(HIST("hEvents"), 1 + Event::CharmHadPiSelected); - float centrality = -1.f; - uint32_t hfRejMap = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb, registry); + // fill collision table if it contains a DPi pair a minima hfReducedCollision(collision.posX(), collision.posY(), collision.posZ(), collision.numContrib(), hfRejMap, bz); hfReducedCollExtra(collision.covXX(), collision.covXY(), collision.covYY(), @@ -1304,10 +1325,34 @@ struct HfDataCreatorCharmHadPiReduced { } template - void runMcGen(aod::McParticles const& particlesMc) + void runMcGen(aod::McCollision const& mcCollision, + aod::McParticles const& particlesMc, + CollisionsWCentAndMcLabels const& collisions, + BCsInfo const&) { + // Check event selection + float centDummy{-1.f}, centFT0C{-1.f}, centFT0M{-1.f}; + const auto collSlice = collisions.sliceBy(colPerMcCollision, mcCollision.globalIndex()); + auto hfRejMap = hfEvSelMc.getHfMcCollisionRejectionMask(mcCollision, collSlice, centDummy); + if (configs.skipRejectedCollisions && hfRejMap != 0) { + return; + } + + // get centrality + float multiplicity{0.f}; + for (const auto& collision : collSlice) { + float collMult = collision.numContrib(); + if (collMult > multiplicity) { + centFT0C = collision.centFT0C(); + centFT0M = collision.centFT0M(); + multiplicity = collMult; + } + } + + const auto mcParticlesPerMcColl = particlesMc.sliceBy(mcParticlesPerMcCollision, mcCollision.globalIndex()); + // Match generated particles. - for (const auto& particle : particlesMc) { + for (const auto& particle : mcParticlesPerMcColl) { int8_t sign{0}; int8_t flag{0}; if constexpr (decayChannel == DecayChannel::B0ToDminusPi) { @@ -1342,7 +1387,7 @@ struct HfDataCreatorCharmHadPiReduced { } rowHfB0McGenReduced(flag, -1 /*channel*/, ptParticle, yParticle, etaParticle, ptProngs[0], yProngs[0], etaProngs[0], - ptProngs[1], yProngs[1], etaProngs[1]); + ptProngs[1], yProngs[1], etaProngs[1], hfRejMap, centFT0C, centFT0M); } else if constexpr (decayChannel == DecayChannel::BsToDsminusPi) { // Bs → Ds- π+ if (RecoDecay::isMatchedMCGen(particlesMc, particle, Pdg::kBS, std::array{-static_cast(Pdg::kDS), +kPiPlus}, true)) { @@ -1368,7 +1413,7 @@ struct HfDataCreatorCharmHadPiReduced { } // additional checks for correlated backgrounds - if (checkDecayTypeMc) { + if (configs.checkDecayTypeMc) { // B0 → Ds- π+ if (!flag) { if (RecoDecay::isMatchedMCGen(particlesMc, particle, Pdg::kB0, std::array{-static_cast(Pdg::kDS), +kPiPlus}, true)) { @@ -1417,7 +1462,7 @@ struct HfDataCreatorCharmHadPiReduced { } rowHfBsMcGenReduced(flag, -1 /*channel*/, ptParticle, yParticle, etaParticle, ptProngs[0], yProngs[0], etaProngs[0], - ptProngs[1], yProngs[1], etaProngs[1]); + ptProngs[1], yProngs[1], etaProngs[1], hfRejMap, centFT0C, centFT0M); } else if constexpr (decayChannel == DecayChannel::BplusToD0barPi) { // B+ → D0bar π+ if (RecoDecay::isMatchedMCGen(particlesMc, particle, Pdg::kBPlus, std::array{-static_cast(Pdg::kD0), +kPiPlus}, true)) { @@ -1450,7 +1495,7 @@ struct HfDataCreatorCharmHadPiReduced { } rowHfBpMcGenReduced(flag, -1 /*channel*/, ptParticle, yParticle, etaParticle, ptProngs[0], yProngs[0], etaProngs[0], - ptProngs[1], yProngs[1], etaProngs[1]); + ptProngs[1], yProngs[1], etaProngs[1], hfRejMap, centFT0C, centFT0M); } else if constexpr (decayChannel == DecayChannel::LbToLcplusPi) { // Lb → Lc+ π- if (RecoDecay::isMatchedMCGen(particlesMc, particle, Pdg::kLambdaB0, std::array{static_cast(Pdg::kLambdaCPlus), -kPiPlus}, true)) { @@ -1483,7 +1528,7 @@ struct HfDataCreatorCharmHadPiReduced { } rowHfLbMcGenReduced(flag, ptParticle, yParticle, etaParticle, ptProngs[0], yProngs[0], etaProngs[0], - ptProngs[1], yProngs[1], etaProngs[1]); + ptProngs[1], yProngs[1], etaProngs[1], hfRejMap, centFT0C, centFT0M); } } // gen } @@ -1499,7 +1544,7 @@ struct HfDataCreatorCharmHadPiReduced { { // store configurables needed for B0 workflow if (!isHfCandBhadConfigFilled) { - rowCandidateConfigB0(hfflagConfigurations.selectionFlagDplus.value, invMassWindowCharmHadPi.value); + rowCandidateConfigB0(hfflagConfigurations.selectionFlagDplus.value, configs.invMassWindowCharmHadPi.value); isHfCandBhadConfigFilled = true; } @@ -1529,7 +1574,7 @@ struct HfDataCreatorCharmHadPiReduced { { // store configurables needed for B0 workflow if (!isHfCandBhadConfigFilled) { - rowCandidateConfigB0(hfflagConfigurations.selectionFlagDplus.value, invMassWindowCharmHadPi.value); + rowCandidateConfigB0(hfflagConfigurations.selectionFlagDplus.value, configs.invMassWindowCharmHadPi.value); isHfCandBhadConfigFilled = true; } @@ -1559,7 +1604,7 @@ struct HfDataCreatorCharmHadPiReduced { { // store configurables needed for B0 workflow if (!isHfCandBhadConfigFilled) { - rowCandidateConfigB0(hfflagConfigurations.selectionFlagDplus.value, invMassWindowCharmHadPi.value); + rowCandidateConfigB0(hfflagConfigurations.selectionFlagDplus.value, configs.invMassWindowCharmHadPi.value); isHfCandBhadConfigFilled = true; } @@ -1589,7 +1634,7 @@ struct HfDataCreatorCharmHadPiReduced { { // store configurables needed for B0 workflow if (!isHfCandBhadConfigFilled) { - rowCandidateConfigB0(hfflagConfigurations.selectionFlagDplus.value, invMassWindowCharmHadPi.value); + rowCandidateConfigB0(hfflagConfigurations.selectionFlagDplus.value, configs.invMassWindowCharmHadPi.value); isHfCandBhadConfigFilled = true; } @@ -1619,7 +1664,7 @@ struct HfDataCreatorCharmHadPiReduced { { // store configurables needed for Bs workflow if (!isHfCandBhadConfigFilled) { - rowCandidateConfigBs(hfflagConfigurations.selectionFlagDs.value, invMassWindowCharmHadPi.value); + rowCandidateConfigBs(hfflagConfigurations.selectionFlagDs.value, configs.invMassWindowCharmHadPi.value); isHfCandBhadConfigFilled = true; } @@ -1649,7 +1694,7 @@ struct HfDataCreatorCharmHadPiReduced { { // store configurables needed for Bs workflow if (!isHfCandBhadConfigFilled) { - rowCandidateConfigBs(hfflagConfigurations.selectionFlagDs.value, invMassWindowCharmHadPi.value); + rowCandidateConfigBs(hfflagConfigurations.selectionFlagDs.value, configs.invMassWindowCharmHadPi.value); isHfCandBhadConfigFilled = true; } @@ -1679,7 +1724,7 @@ struct HfDataCreatorCharmHadPiReduced { { // store configurables needed for Bs workflow if (!isHfCandBhadConfigFilled) { - rowCandidateConfigBs(hfflagConfigurations.selectionFlagDs.value, invMassWindowCharmHadPi.value); + rowCandidateConfigBs(hfflagConfigurations.selectionFlagDs.value, configs.invMassWindowCharmHadPi.value); isHfCandBhadConfigFilled = true; } @@ -1709,7 +1754,7 @@ struct HfDataCreatorCharmHadPiReduced { { // store configurables needed for Bs workflow if (!isHfCandBhadConfigFilled) { - rowCandidateConfigBs(hfflagConfigurations.selectionFlagDs.value, invMassWindowCharmHadPi.value); + rowCandidateConfigBs(hfflagConfigurations.selectionFlagDs.value, configs.invMassWindowCharmHadPi.value); isHfCandBhadConfigFilled = true; } @@ -1739,7 +1784,7 @@ struct HfDataCreatorCharmHadPiReduced { { // store configurables needed for B+ workflow if (!isHfCandBhadConfigFilled) { - rowCandidateConfigBplus(hfflagConfigurations.selectionFlagD0.value, hfflagConfigurations.selectionFlagD0bar.value, invMassWindowCharmHadPi.value); + rowCandidateConfigBplus(hfflagConfigurations.selectionFlagD0.value, hfflagConfigurations.selectionFlagD0bar.value, configs.invMassWindowCharmHadPi.value); isHfCandBhadConfigFilled = true; } @@ -1769,7 +1814,7 @@ struct HfDataCreatorCharmHadPiReduced { { // store configurables needed for B+ workflow if (!isHfCandBhadConfigFilled) { - rowCandidateConfigBplus(hfflagConfigurations.selectionFlagD0.value, hfflagConfigurations.selectionFlagD0bar.value, invMassWindowCharmHadPi.value); + rowCandidateConfigBplus(hfflagConfigurations.selectionFlagD0.value, hfflagConfigurations.selectionFlagD0bar.value, configs.invMassWindowCharmHadPi.value); isHfCandBhadConfigFilled = true; } @@ -1799,7 +1844,7 @@ struct HfDataCreatorCharmHadPiReduced { { // store configurables needed for B+ workflow if (!isHfCandBhadConfigFilled) { - rowCandidateConfigBplus(hfflagConfigurations.selectionFlagD0.value, hfflagConfigurations.selectionFlagD0bar.value, invMassWindowCharmHadPi.value); + rowCandidateConfigBplus(hfflagConfigurations.selectionFlagD0.value, hfflagConfigurations.selectionFlagD0bar.value, configs.invMassWindowCharmHadPi.value); isHfCandBhadConfigFilled = true; } @@ -1829,7 +1874,7 @@ struct HfDataCreatorCharmHadPiReduced { { // store configurables needed for B+ workflow if (!isHfCandBhadConfigFilled) { - rowCandidateConfigBplus(hfflagConfigurations.selectionFlagD0.value, hfflagConfigurations.selectionFlagD0bar.value, invMassWindowCharmHadPi.value); + rowCandidateConfigBplus(hfflagConfigurations.selectionFlagD0.value, hfflagConfigurations.selectionFlagD0bar.value, configs.invMassWindowCharmHadPi.value); isHfCandBhadConfigFilled = true; } @@ -1859,7 +1904,7 @@ struct HfDataCreatorCharmHadPiReduced { { // store configurables needed for Lb workflow if (!isHfCandBhadConfigFilled) { - rowCandidateConfigLb(hfflagConfigurations.selectionFlagLc.value, invMassWindowCharmHadPi.value); + rowCandidateConfigLb(hfflagConfigurations.selectionFlagLc.value, configs.invMassWindowCharmHadPi.value); isHfCandBhadConfigFilled = true; } @@ -1889,7 +1934,7 @@ struct HfDataCreatorCharmHadPiReduced { { // store configurables needed for Lb workflow if (!isHfCandBhadConfigFilled) { - rowCandidateConfigLb(hfflagConfigurations.selectionFlagLc.value, invMassWindowCharmHadPi.value); + rowCandidateConfigLb(hfflagConfigurations.selectionFlagLc.value, configs.invMassWindowCharmHadPi.value); isHfCandBhadConfigFilled = true; } @@ -1919,12 +1964,12 @@ struct HfDataCreatorCharmHadPiReduced { aod::TrackAssoc const& trackIndices, TracksPidWithSelAndMc const& tracks, aod::McParticles const& particlesMc, - aod::BCsWithTimestamps const& bcs, - McCollisions const&) + BCsInfo const& bcs, + McCollisions const& mcCollisions) { // store configurables needed for B0 workflow if (!isHfCandBhadConfigFilled) { - rowCandidateConfigB0(hfflagConfigurations.selectionFlagDplus.value, invMassWindowCharmHadPi.value); + rowCandidateConfigB0(hfflagConfigurations.selectionFlagDplus.value, configs.invMassWindowCharmHadPi.value); isHfCandBhadConfigFilled = true; } @@ -1945,7 +1990,9 @@ struct HfDataCreatorCharmHadPiReduced { } // handle normalization by the right number of collisions hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); - runMcGen(particlesMc); + for (const auto& mcCollision : mcCollisions) { + runMcGen(mcCollision, particlesMc, collisions, bcs); + } } PROCESS_SWITCH(HfDataCreatorCharmHadPiReduced, processDplusPiMc, "Process DplusPi with MC info and without ML info", false); @@ -1954,12 +2001,12 @@ struct HfDataCreatorCharmHadPiReduced { aod::TrackAssoc const& trackIndices, TracksPidWithSelAndMc const& tracks, aod::McParticles const& particlesMc, - aod::BCsWithTimestamps const& bcs, - McCollisions const&) + BCsInfo const& bcs, + McCollisions const& mcCollisions) { // store configurables needed for B0 workflow if (!isHfCandBhadConfigFilled) { - rowCandidateConfigB0(hfflagConfigurations.selectionFlagDplus.value, invMassWindowCharmHadPi.value); + rowCandidateConfigB0(hfflagConfigurations.selectionFlagDplus.value, configs.invMassWindowCharmHadPi.value); isHfCandBhadConfigFilled = true; } @@ -1980,7 +2027,9 @@ struct HfDataCreatorCharmHadPiReduced { } // handle normalization by the right number of collisions hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); - runMcGen(particlesMc); + for (const auto& mcCollision : mcCollisions) { + runMcGen(mcCollision, particlesMc, collisions, bcs); + } } PROCESS_SWITCH(HfDataCreatorCharmHadPiReduced, processDplusPiMcWithMl, "Process DplusPi with MC info and with ML info", false); @@ -1989,12 +2038,12 @@ struct HfDataCreatorCharmHadPiReduced { aod::TrackAssoc const& trackIndices, TracksPidWithSelAndMc const& tracks, aod::McParticles const& particlesMc, - aod::BCsWithTimestamps const& bcs, - McCollisions const&) + BCsInfo const& bcs, + McCollisions const& mcCollisions) { // store configurables needed for Bs workflow if (!isHfCandBhadConfigFilled) { - rowCandidateConfigBs(hfflagConfigurations.selectionFlagDs.value, invMassWindowCharmHadPi.value); + rowCandidateConfigBs(hfflagConfigurations.selectionFlagDs.value, configs.invMassWindowCharmHadPi.value); isHfCandBhadConfigFilled = true; } @@ -2015,7 +2064,9 @@ struct HfDataCreatorCharmHadPiReduced { } // handle normalization by the right number of collisions hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); - runMcGen(particlesMc); + for (const auto& mcCollision : mcCollisions) { + runMcGen(mcCollision, particlesMc, collisions, bcs); + } } PROCESS_SWITCH(HfDataCreatorCharmHadPiReduced, processDsPiMc, "Process DsPi with MC info and without ML info", false); @@ -2024,12 +2075,12 @@ struct HfDataCreatorCharmHadPiReduced { aod::TrackAssoc const& trackIndices, TracksPidWithSelAndMc const& tracks, aod::McParticles const& particlesMc, - aod::BCsWithTimestamps const& bcs, - McCollisions const&) + BCsInfo const& bcs, + McCollisions const& mcCollisions) { // store configurables needed for Bs workflow if (!isHfCandBhadConfigFilled) { - rowCandidateConfigBs(hfflagConfigurations.selectionFlagDs.value, invMassWindowCharmHadPi.value); + rowCandidateConfigBs(hfflagConfigurations.selectionFlagDs.value, configs.invMassWindowCharmHadPi.value); isHfCandBhadConfigFilled = true; } @@ -2050,7 +2101,9 @@ struct HfDataCreatorCharmHadPiReduced { } // handle normalization by the right number of collisions hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); - runMcGen(particlesMc); + for (const auto& mcCollision : mcCollisions) { + runMcGen(mcCollision, particlesMc, collisions, bcs); + } } PROCESS_SWITCH(HfDataCreatorCharmHadPiReduced, processDsPiMcWithMl, "Process DsPi with MC info and with ML info", false); @@ -2059,12 +2112,12 @@ struct HfDataCreatorCharmHadPiReduced { aod::TrackAssoc const& trackIndices, TracksPidWithSelAndMc const& tracks, aod::McParticles const& particlesMc, - aod::BCsWithTimestamps const& bcs, - McCollisions const&) + BCsInfo const& bcs, + McCollisions const& mcCollisions) { // store configurables needed for B+ workflow if (!isHfCandBhadConfigFilled) { - rowCandidateConfigBplus(hfflagConfigurations.selectionFlagD0.value, hfflagConfigurations.selectionFlagD0bar.value, invMassWindowCharmHadPi.value); + rowCandidateConfigBplus(hfflagConfigurations.selectionFlagD0.value, hfflagConfigurations.selectionFlagD0bar.value, configs.invMassWindowCharmHadPi.value); isHfCandBhadConfigFilled = true; } @@ -2085,7 +2138,9 @@ struct HfDataCreatorCharmHadPiReduced { } // handle normalization by the right number of collisions hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); - runMcGen(particlesMc); + for (const auto& mcCollision : mcCollisions) { + runMcGen(mcCollision, particlesMc, collisions, bcs); + } } PROCESS_SWITCH(HfDataCreatorCharmHadPiReduced, processD0PiMc, "Process D0Pi with MC info and without ML info", false); @@ -2094,12 +2149,12 @@ struct HfDataCreatorCharmHadPiReduced { aod::TrackAssoc const& trackIndices, TracksPidWithSelAndMc const& tracks, aod::McParticles const& particlesMc, - aod::BCsWithTimestamps const& bcs, - McCollisions const&) + BCsInfo const& bcs, + McCollisions const& mcCollisions) { // store configurables needed for B+ workflow if (!isHfCandBhadConfigFilled) { - rowCandidateConfigBplus(hfflagConfigurations.selectionFlagD0.value, hfflagConfigurations.selectionFlagD0bar.value, invMassWindowCharmHadPi.value); + rowCandidateConfigBplus(hfflagConfigurations.selectionFlagD0.value, hfflagConfigurations.selectionFlagD0bar.value, configs.invMassWindowCharmHadPi.value); isHfCandBhadConfigFilled = true; } @@ -2120,7 +2175,9 @@ struct HfDataCreatorCharmHadPiReduced { } // handle normalization by the right number of collisions hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); - runMcGen(particlesMc); + for (const auto& mcCollision : mcCollisions) { + runMcGen(mcCollision, particlesMc, collisions, bcs); + } } PROCESS_SWITCH(HfDataCreatorCharmHadPiReduced, processD0PiMcWithMl, "Process D0Pi with MC info and with ML info", false); @@ -2129,12 +2186,12 @@ struct HfDataCreatorCharmHadPiReduced { aod::TrackAssoc const& trackIndices, TracksPidWithSelAndMc const& tracks, aod::McParticles const& particlesMc, - aod::BCsWithTimestamps const& bcs, - McCollisions const&) + BCsInfo const& bcs, + McCollisions const& mcCollisions) { // store configurables needed for Lb workflow if (!isHfCandBhadConfigFilled) { - rowCandidateConfigLb(hfflagConfigurations.selectionFlagDplus.value, invMassWindowCharmHadPi.value); + rowCandidateConfigLb(hfflagConfigurations.selectionFlagDplus.value, configs.invMassWindowCharmHadPi.value); isHfCandBhadConfigFilled = true; } @@ -2155,7 +2212,9 @@ struct HfDataCreatorCharmHadPiReduced { } // handle normalization by the right number of collisions hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); - runMcGen(particlesMc); + for (const auto& mcCollision : mcCollisions) { + runMcGen(mcCollision, particlesMc, collisions, bcs); + } } PROCESS_SWITCH(HfDataCreatorCharmHadPiReduced, processLcPiMc, "Process LcPi with MC info and without ML info", false); @@ -2164,12 +2223,12 @@ struct HfDataCreatorCharmHadPiReduced { aod::TrackAssoc const& trackIndices, TracksPidWithSelAndMc const& tracks, aod::McParticles const& particlesMc, - aod::BCsWithTimestamps const& bcs, - McCollisions const&) + BCsInfo const& bcs, + McCollisions const& mcCollisions) { // store configurables needed for Lb workflow if (!isHfCandBhadConfigFilled) { - rowCandidateConfigLb(hfflagConfigurations.selectionFlagLc.value, invMassWindowCharmHadPi.value); + rowCandidateConfigLb(hfflagConfigurations.selectionFlagLc.value, configs.invMassWindowCharmHadPi.value); isHfCandBhadConfigFilled = true; } @@ -2190,7 +2249,9 @@ struct HfDataCreatorCharmHadPiReduced { } // handle normalization by the right number of collisions hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); - runMcGen(particlesMc); + for (const auto& mcCollision : mcCollisions) { + runMcGen(mcCollision, particlesMc, collisions, bcs); + } } PROCESS_SWITCH(HfDataCreatorCharmHadPiReduced, processLcPiMcWithMl, "Process LcPi with MC info and with ML info", false); diff --git a/PWGHF/D2H/TableProducer/dataCreatorJpsiHadReduced.cxx b/PWGHF/D2H/TableProducer/dataCreatorJpsiHadReduced.cxx index ed6321fe4ba..39f3aa45231 100644 --- a/PWGHF/D2H/TableProducer/dataCreatorJpsiHadReduced.cxx +++ b/PWGHF/D2H/TableProducer/dataCreatorJpsiHadReduced.cxx @@ -34,6 +34,7 @@ #include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/TrackSelectionTables.h" +#include "Framework/RunningWorkflowInfo.h" #include #include #include @@ -122,6 +123,7 @@ struct HfDataCreatorJpsiHadReduced { Produces rowCandidateConfigBplus; Produces rowCandidateConfigBs; + Configurable skipRejectedCollisions{"skipRejectedCollisions", true, "skips collisions rejected by the event selection, instead of flagging only"}; Configurable propagateToPCA{"propagateToPCA", true, "create tracks version propagated to PCA"}; Configurable useAbsDCA{"useAbsDCA", false, "Minimise abs. distance rather than chi2"}; Configurable useWeightedFinalPCA{"useWeightedFinalPCA", false, "Recalculate vertex position using track covariances, effective only if useAbsDCA is true"}; @@ -162,10 +164,12 @@ struct HfDataCreatorJpsiHadReduced { using TracksSel = soa::Join; using TracksPidWithSelAndMc = soa::Join; using CollisionsWCMcLabels = soa::Join; + using BCsInfo = soa::Join; Preslice candsJpsiPerCollision = aod::track_association::collisionId; Preslice trackIndicesPerCollision = aod::track_association::collisionId; PresliceUnsorted colPerMcCollision = aod::mccollisionlabel::mcCollisionId; + Preslice mcParticlesPerMcCollision = aod::mcparticle::mcCollisionId; o2::base::Propagator::MatCorrType noMatCorr = o2::base::Propagator::MatCorrType::USEMatCorrNONE; int runNumber; @@ -174,13 +178,15 @@ struct HfDataCreatorJpsiHadReduced { bool isHfCandBhadConfigFilled = false; o2::hf_evsel::HfEventSelection hfEvSel; + o2::hf_evsel::HfEventSelectionMc hfEvSelMc; + o2::vertexing::DCAFitterN<2> df2; o2::vertexing::DCAFitterN<3> df3; o2::vertexing::DCAFitterN<4> df4; HistogramRegistry registry{"registry"}; - void init(InitContext const&) + void init(InitContext& initContext) { std::array doProcess = {doprocessJpsiKData, doprocessJpsiKMc, doprocessJpsiPhiData, doprocessJpsiPhiMc}; if (std::accumulate(doProcess.begin(), doProcess.end(), 0) != 1) { @@ -270,6 +276,19 @@ struct HfDataCreatorJpsiHadReduced { invMass2JpsiHadMin = (MassBS - invMassWindowJpsiHad) * (MassBS - invMassWindowJpsiHad); invMass2JpsiHadMax = (MassBS + invMassWindowJpsiHad) * (MassBS + invMassWindowJpsiHad); } + + // init HF event selection helper + hfEvSel.init(registry); + if (doprocessJpsiKMc || doprocessJpsiPhiMc) { + const auto& workflows = initContext.services().get(); + for (const DeviceSpec& device : workflows.devices) { + if (device.name.compare("hf-data-creator-jpsi-had-reduced") == 0) { + // init HF event selection helper + hfEvSelMc.init(device, registry); + break; + } + } + } } /// Topological cuts @@ -512,10 +531,23 @@ struct HfDataCreatorJpsiHadReduced { } template - void runMcGen(aod::McParticles const& particlesMc) + void runMcGen(aod::McCollision const& mcCollision, + aod::McParticles const& particlesMc, + CollisionsWCMcLabels const& collisions, + BCsInfo const&) { + // Check event selection + float centDummy{-1.f}, centFT0C{-1.f}, centFT0M{-1.f}; + const auto collSlice = collisions.sliceBy(colPerMcCollision, mcCollision.globalIndex()); + auto hfRejMap = hfEvSelMc.getHfMcCollisionRejectionMask(mcCollision, collSlice, centDummy); + if (skipRejectedCollisions && hfRejMap != 0) { + return; + } + + const auto mcParticlesPerMcColl = particlesMc.sliceBy(mcParticlesPerMcCollision, mcCollision.globalIndex()); + // Match generated particles. - for (const auto& particle : particlesMc) { + for (const auto& particle : mcParticlesPerMcColl) { int8_t sign{0}, flag{0}, channel{0}; if constexpr (decChannel == DecayChannel::BplusToJpsiK) { // B+ → J/Psi K+ → (µ+µ-) K+ @@ -556,7 +588,7 @@ struct HfDataCreatorJpsiHadReduced { } rowHfBpMcGenReduced(flag, channel, ptParticle, yParticle, etaParticle, ptProngs[0], yProngs[0], etaProngs[0], - ptProngs[1], yProngs[1], etaProngs[1]); + ptProngs[1], yProngs[1], etaProngs[1], hfRejMap, centFT0C, centFT0M); } else if constexpr (decChannel == DecayChannel::BsToJpsiPhi) { // Bs → J/Psi phi → (µ+µ-) (K+K-) if (RecoDecay::isMatchedMCGen(particlesMc, particle, Pdg::kBS, std::array{static_cast(Pdg::kJPsi), +kKPlus, -kKPlus}, true, &sign, 2)) { @@ -596,22 +628,29 @@ struct HfDataCreatorJpsiHadReduced { } rowHfBsMcGenReduced(flag, channel, ptParticle, yParticle, etaParticle, ptProngs[0], yProngs[0], etaProngs[0], - ptProngs[1], yProngs[1], etaProngs[1]); + ptProngs[1], yProngs[1], etaProngs[1], hfRejMap, centFT0C, centFT0M); } } // gen } // Jpsi candidate selection - template + template void runDataCreation(Coll const& collision, JpsiCands const& candsJpsi, aod::TrackAssoc const& trackIndices, TTracks const&, PParticles const& particlesMc, uint64_t const& indexCollisionMaxNumContrib, - aod::BCsWithTimestamps const&) + BBCs const&) { + registry.fill(HIST("hEvents"), 1 + Event::Processed); + float centrality = -1.f; + auto hfRejMap = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb, registry); + if (skipRejectedCollisions && hfRejMap != 0) { + return; + } + // helpers for ReducedTables filling int indexHfReducedCollision = hfReducedCollision.lastIndex() + 1; // std::map where the key is the track.globalIndex() and @@ -959,14 +998,11 @@ struct HfDataCreatorJpsiHadReduced { } } // candsJpsi loop - registry.fill(HIST("hEvents"), 1 + Event::Processed); if (!fillHfReducedCollision) { registry.fill(HIST("hEvents"), 1 + Event::NoCharmHadPiSelected); return; } registry.fill(HIST("hEvents"), 1 + Event::CharmHadPiSelected); - float centrality = -1.f; - uint16_t hfRejMap = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb, registry); // fill collision table if it contains a J/Psi K pair at minimum hfReducedCollision(collision.posX(), collision.posY(), collision.posZ(), collision.numContrib(), hfRejMap, bz); hfReducedCollExtra(collision.covXX(), collision.covXY(), collision.covYY(), @@ -1047,8 +1083,8 @@ struct HfDataCreatorJpsiHadReduced { aod::TrackAssoc const& trackIndices, TracksPidWithSelAndMc const& tracks, aod::McParticles const& particlesMc, - aod::BCsWithTimestamps const& bcs, - McCollisions const&) + BCsInfo const& bcs, + McCollisions const& mcCollisions) { // store configurables needed for B+ workflow if (!isHfCandBhadConfigFilled) { @@ -1073,7 +1109,9 @@ struct HfDataCreatorJpsiHadReduced { } // handle normalization by the right number of collisions hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); - runMcGen(particlesMc); + for (const auto& mcCollision : mcCollisions) { + runMcGen(mcCollision, particlesMc, collisions, bcs); + } } PROCESS_SWITCH(HfDataCreatorJpsiHadReduced, processJpsiKMc, "Process J/Psi K with MC info", false); @@ -1082,8 +1120,8 @@ struct HfDataCreatorJpsiHadReduced { aod::TrackAssoc const& trackIndices, TracksPidWithSelAndMc const& tracks, aod::McParticles const& particlesMc, - aod::BCsWithTimestamps const& bcs, - McCollisions const&) + BCsInfo const& bcs, + McCollisions const& mcCollisions) { // store configurables needed for B+ workflow if (!isHfCandBhadConfigFilled) { @@ -1108,7 +1146,9 @@ struct HfDataCreatorJpsiHadReduced { } // handle normalization by the right number of collisions hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); - runMcGen(particlesMc); + for (const auto& mcCollision : mcCollisions) { + runMcGen(mcCollision, particlesMc, collisions, bcs); + } } PROCESS_SWITCH(HfDataCreatorJpsiHadReduced, processJpsiPhiMc, "Process J/Psi phi with MC info", false); }; diff --git a/PWGHF/TableProducer/candidateCreator2Prong.cxx b/PWGHF/TableProducer/candidateCreator2Prong.cxx index 895b8804cb9..700804d4ea5 100644 --- a/PWGHF/TableProducer/candidateCreator2Prong.cxx +++ b/PWGHF/TableProducer/candidateCreator2Prong.cxx @@ -1015,7 +1015,7 @@ struct HfCandidateCreator2ProngExpressions { const auto mcParticlesPerMcColl = mcParticles.sliceBy(mcParticlesPerMcCollision, mcCollision.globalIndex()); // Slice the collisions table to get the collision info for the current MC collision float centrality{-1.f}; - uint16_t rejectionMask{0}; + uint32_t rejectionMask{0u}; int nSplitColl = 0; if constexpr (centEstimator == CentralityEstimator::FT0C) { const auto collSlice = collInfos.sliceBy(colPerMcCollisionFT0C, mcCollision.globalIndex()); diff --git a/PWGHF/TableProducer/candidateCreator3Prong.cxx b/PWGHF/TableProducer/candidateCreator3Prong.cxx index 38c9bc0a30f..017752f248d 100644 --- a/PWGHF/TableProducer/candidateCreator3Prong.cxx +++ b/PWGHF/TableProducer/candidateCreator3Prong.cxx @@ -1304,7 +1304,7 @@ struct HfCandidateCreator3ProngExpressions { const auto mcParticlesPerMcColl = mcParticles.sliceBy(mcParticlesPerMcCollision, mcCollision.globalIndex()); // Slice the collisions table to get the collision info for the current MC collision float centrality{-1.f}; - uint16_t rejectionMask{0}; + uint32_t rejectionMask{0u}; int nSplitColl = 0; if constexpr (centEstimator == CentralityEstimator::FT0C) { const auto collSlice = collInfos.sliceBy(colPerMcCollisionFT0C, mcCollision.globalIndex()); diff --git a/PWGHF/TableProducer/candidateCreatorCascade.cxx b/PWGHF/TableProducer/candidateCreatorCascade.cxx index a7eb6ccc794..20e16710463 100644 --- a/PWGHF/TableProducer/candidateCreatorCascade.cxx +++ b/PWGHF/TableProducer/candidateCreatorCascade.cxx @@ -564,7 +564,7 @@ struct HfCandidateCreatorCascadeMc { const auto mcParticlesPerMcColl = mcParticles.sliceBy(mcParticlesPerMcCollision, mcCollision.globalIndex()); // Slice the collisions table to get the collision info for the current MC collision float centrality{-1.f}; - uint16_t rejectionMask{0}; + uint32_t rejectionMask{0u}; int nSplitColl = 0; if constexpr (centEstimator == CentralityEstimator::FT0C) { const auto collSlice = collInfos.sliceBy(colPerMcCollisionFT0C, mcCollision.globalIndex()); diff --git a/PWGHF/TableProducer/candidateCreatorDstar.cxx b/PWGHF/TableProducer/candidateCreatorDstar.cxx index a6795dc8274..9036717104b 100644 --- a/PWGHF/TableProducer/candidateCreatorDstar.cxx +++ b/PWGHF/TableProducer/candidateCreatorDstar.cxx @@ -732,7 +732,7 @@ struct HfCandidateCreatorDstarExpressions { const auto mcParticlesPerMcColl = mcParticles.sliceBy(mcParticlesPerMcCollision, mcCollision.globalIndex()); // Slice the collisions table to get the collision info for the current MC collision float centrality{-1.f}; - uint16_t rejectionMask{0}; + uint32_t rejectionMask{0u}; int nSplitColl = 0; if constexpr (centEstimator == CentralityEstimator::FT0C) { const auto collSlice = collInfos.sliceBy(colPerMcCollisionFT0C, mcCollision.globalIndex()); diff --git a/PWGHF/TableProducer/candidateCreatorSigmac0plusplus.cxx b/PWGHF/TableProducer/candidateCreatorSigmac0plusplus.cxx index 5767422b24f..e66702055d8 100644 --- a/PWGHF/TableProducer/candidateCreatorSigmac0plusplus.cxx +++ b/PWGHF/TableProducer/candidateCreatorSigmac0plusplus.cxx @@ -586,9 +586,8 @@ struct HfCandidateSigmac0plusplusMc { /// In case of need, readapt the code templetizing the function auto mcCollision = particle.mcCollision(); float centrality{-1.f}; - uint16_t rejectionMask{0}; const auto collSlice = collInfos.sliceBy(colPerMcCollision, mcCollision.globalIndex()); - rejectionMask = hfEvSelMc.getHfMcCollisionRejectionMask(mcCollision, collSlice, centrality); + auto rejectionMask = hfEvSelMc.getHfMcCollisionRejectionMask(mcCollision, collSlice, centrality); hfEvSelMc.fillHistograms(mcCollision, rejectionMask, 0); if (rejectionMask != 0) { // at least one event selection not satisfied --> reject gen particles from this collision diff --git a/PWGHF/TableProducer/candidateCreatorXicToXiPiPi.cxx b/PWGHF/TableProducer/candidateCreatorXicToXiPiPi.cxx index 7063f970f44..18ef07264db 100644 --- a/PWGHF/TableProducer/candidateCreatorXicToXiPiPi.cxx +++ b/PWGHF/TableProducer/candidateCreatorXicToXiPiPi.cxx @@ -1088,7 +1088,7 @@ struct HfCandidateCreatorXicToXiPiPiExpressions { const auto mcParticlesPerMcColl = mcParticles.sliceBy(mcParticlesPerMcCollision, mcCollision.globalIndex()); // Slice the collisions table to get the collision info for the current MC collision float centrality{-1.f}; - uint16_t rejectionMask{0}; + uint32_t rejectionMask{0u}; int nSplitColl = 0; if constexpr (centEstimator == o2::hf_centrality::CentralityEstimator::FT0C) { const auto collSlice = collInfos.sliceBy(colPerMcCollisionFT0C, mcCollision.globalIndex()); diff --git a/PWGHF/Tasks/taskMcValidation.cxx b/PWGHF/Tasks/taskMcValidation.cxx index 865a3a58d85..5feaf4f186b 100644 --- a/PWGHF/Tasks/taskMcValidation.cxx +++ b/PWGHF/Tasks/taskMcValidation.cxx @@ -287,7 +287,7 @@ struct HfTaskMcValidationGen { if (storeOccupancy) { occupancy = getOccupancyGenColl(recoCollisions, OccupancyEstimator::Its); } - uint16_t rejectionMask{0}; + uint32_t rejectionMask{0u}; if constexpr (centEstimator == CentralityEstimator::FT0C) { rejectionMask = hfEvSelMc.getHfMcCollisionRejectionMask(mcCollision, recoCollisions, centrality); } else if constexpr (centEstimator == CentralityEstimator::FT0M) { From e0e6be25671e46f3f032c1ed8405fa868848566d Mon Sep 17 00:00:00 2001 From: nkaratze Date: Mon, 30 Jun 2025 14:58:25 +0100 Subject: [PATCH 270/871] [PWGLF] v0ptinvmassplots Task: Added Event Selection and Corrections (plus some extra cuts) (#11836) Co-authored-by: nkaratze --- PWGLF/Tasks/Strangeness/v0ptinvmassplots.cxx | 661 ++++++++++++------- 1 file changed, 435 insertions(+), 226 deletions(-) diff --git a/PWGLF/Tasks/Strangeness/v0ptinvmassplots.cxx b/PWGLF/Tasks/Strangeness/v0ptinvmassplots.cxx index cf92a7cbc65..bd93c66cdfc 100644 --- a/PWGLF/Tasks/Strangeness/v0ptinvmassplots.cxx +++ b/PWGLF/Tasks/Strangeness/v0ptinvmassplots.cxx @@ -61,6 +61,7 @@ struct V0PtInvMassPlots { HistogramRegistry rLambdaMassPlotsPerPtBin{"LambdaMassPlotsPerPtBin", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; HistogramRegistry rAntilambdaMassPlotsPerPtBin{"AntilambdaMassPlotsPerPtBin", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; HistogramRegistry rFeeddownMatrices{"FeeddownMatrices", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry rMCCorrections{"rMCCorrections", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; // Configurable for histograms Configurable nBins{"nBins", 100, "N bins in all histos"}; @@ -73,28 +74,44 @@ struct V0PtInvMassPlots { Configurable nSigmaTPCProton{"nSigmaTPCProton", 4, "nSigmaTPCProton"}; Configurable compv0masscut{"compv0masscut", 0.01, "CompetitiveV0masscut (GeV)"}; Configurable etadau{"etadau", 0.8, "Eta Daughters"}; - Configurable rapidityCut{"rapidityCut", 0.5, "V0 Rapidity Window GenMC"}; - - // Configurable Kaonsh Topological Cuts (best cuts determined by v0topologicalcuts task) + Configurable rapidityCut{"rapidityCut", 0.5, "V0 Rapidity Window"}; + Configurable itsMinHits{"itsMinHits", 1.0, "Minimum Hits of Daughter Tracks in the ITS"}; + Configurable paramArmenterosCut{"paramArmenterosCut", 0.2, "Armenteros Cut on parameter"}; + + // Configurables switches for event selection + Configurable dosel8{"dosel8", true, "Enable sel8 event selection"}; + Configurable doNoTimeFrameBorder{"doNoTimeFrameBorder", true, "Enable NoTimeFrameBorder event selection"}; + Configurable doNoITSROFrameBorder{"doNoITSROFrameBorder", true, "Enable NoITSROFrameBorder event selection"}; + Configurable doIsTriggerTVX{"doIsTriggerTVX", true, "Enable IsTriggerTVX event selection"}; + Configurable docutZVertex{"docutZVertex", true, "Enable cutZVertex event selection"}; + Configurable doIsVertexTOFmatched{"doIsVertexTOFmatched", true, "Enable IsVertexTOFmatched event selection"}; + Configurable doNoSameBunchPileup{"doNoSameBunchPileup", true, "Enable NoSameBunchPileup event selection"}; + Configurable doIsVertexITSTPC{"doIsVertexITSTPC", true, "Enable IsVertexITSTPC event selection"}; + Configurable doisInelGt0{"doisInelGt0", true, "Enable isInelGt0 event selection"}; + + // Configurable Kaonsh Cuts (best cuts determined by v0topologicalcuts task) Configurable kaonshSettingdcav0dau{"kaonshSettingdcav0dau", 0.3, "DCA V0 Daughters"}; Configurable kaonshSettingdcapostopv{"kaonshSettingdcapostopv", 0.05, "DCA Pos To PV"}; Configurable kaonshSettingdcanegtopv{"kaonshSettingdcanegtopv", 0.05, "DCA Neg To PV"}; Configurable kaonshSettingcosPA{"kaonshSettingcosPA", 0.98, "V0 CosPA"}; // double -> N.B. dcos(x)/dx = 0 at x=0 Configurable kaonshSettingradius{"kaonshSettingradius", 0.50, "v0radius"}; + Configurable kaonshmaxct{"kaonshmaxct", 20.00, "K0sh maximum ct value"}; - // Configurable Lambda Topological Cuts (best cuts determined by v0topologicalcuts task) + // Configurable Lambda Cuts (best cuts determined by v0topologicalcuts task) Configurable lambdaSettingdcav0dau{"lambdaSettingdcav0dau", 0.3, "DCA V0 Daughters"}; Configurable lambdaSettingdcapostopv{"lambdaSettingdcapostopv", 0.05, "DCA Pos To PV"}; Configurable lambdaSettingdcanegtopv{"lambdaSettingdcanegtopv", 0.09, "DCA Neg To PV"}; Configurable lambdaSettingcosPA{"lambdaSettingcosPA", 0.98, "V0 CosPA"}; // double -> N.B. dcos(x)/dx = 0 at x=0 Configurable lambdaSettingradius{"lambdaSettingradius", 0.50, "v0radius"}; + Configurable lambdamaxct{"lambdamaxct", 30.00, "Lambda maximum ct value"}; - // Configurable Antilambda Topological Cuts (best cuts determined by v0topologicalcuts task) + // Configurable Antilambda Cuts (best cuts determined by v0topologicalcuts task) Configurable antilambdaSettingdcav0dau{"antilambdaSettingdcav0dau", 0.3, "DCA V0 Daughters"}; Configurable antilambdaSettingdcapostopv{"antilambdaSettingdcapostopv", 0.09, "DCA Pos To PV"}; Configurable antilambdaSettingdcanegtopv{"antilambdaSettingdcanegtopv", 0.05, "DCA Neg To PV"}; Configurable antilambdaSettingcosPA{"antilambdaSettingcosPA", 0.98, "V0 CosPA"}; // double -> N.B. dcos(x)/dx = 0 at x=0 Configurable antilambdaSettingradius{"antilambdaSettingradius", 0.50, "v0radius"}; + Configurable antilambdamaxct{"antilambdamaxct", 30.00, "Antilambda maximum ct value"}; // Configurables for Specific V0s analysis Configurable kzeroAnalysis{"kzeroAnalysis", true, "Enable Kzerosh Pt Analysis"}; @@ -162,25 +179,16 @@ struct V0PtInvMassPlots { antilambdahistvalue[i] = antilambdaPtbin; } - rPtAnalysis.add("hVertexZ", "hVertexZ", {HistType::kTH1F, {vertexZAxis}}); + // General Plots + rPtAnalysis.add("hNRecEvents_Data", "hNRecEvents_Data", {HistType::kTH1D, {{1, 0.f, 1.f}}}); + rPtAnalysis.add("hNV0s", "hNV0s", {HistType::kTH1D, {{10, 0.f, 10.f}}}); rPtAnalysis.add("hVertexZRec", "hVertexZRec", {HistType::kTH1F, {vertexZAxis}}); rPtAnalysis.add("hArmenterosPodolanskiPlot", "hArmenterosPodolanskiPlot", {HistType::kTH2F, {{armenterosasymAxis}, {armenterosQtAxis}}}); rPtAnalysis.add("hV0EtaDaughters", "hV0EtaDaughters", {HistType::kTH1F, {{nBins, -1.2f, 1.2f}}}); rPtAnalysis.add("V0Rapidity", "V0Rapidity", {HistType::kTH1F, {{nBins, -10.0f, 10.0f}}}); - // Generated Pt Spectrums For Feeddown - rPtAnalysis.add("GenParticleRapidity", "GenParticleRapidity", {HistType::kTH1F, {{nBins, -10.0f, 10.0f}}}); - rPtAnalysis.add("hXiMinusGeneratedPtSpectrum", "hXiMinusGeneratedPtSpectrum", {HistType::kTH1F, {lambdaPtAxis}}); - rPtAnalysis.add("hXiZeroGeneratedPtSpectrum", "hXiZeroGeneratedPtSpectrum", {HistType::kTH1F, {lambdaPtAxis}}); - rPtAnalysis.add("hOmegaGeneratedPtSpectrum", "hOmegaGeneratedPtSpectrum", {HistType::kTH1F, {lambdaPtAxis}}); - rPtAnalysis.add("hXiPlusGeneratedPtSpectrum", "hXiPlusGeneratedPtSpectrum", {HistType::kTH1F, {antilambdaPtAxis}}); - rPtAnalysis.add("hAntiXiZeroGeneratedPtSpectrum", "hAntiXiZeroGeneratedPtSpectrum", {HistType::kTH1F, {antilambdaPtAxis}}); - rPtAnalysis.add("hAntiOmegaGeneratedPtSpectrum", "hAntiOmegaGeneratedPtSpectrum", {HistType::kTH1F, {antilambdaPtAxis}}); - rPtAnalysis.add("hPhiGeneratedPtSpectrum", "hPhiGeneratedPtSpectrum", {HistType::kTH1F, {k0ShortPtAxis}}); - // Adding Kzerosh Histograms to registry if (kzeroAnalysis == true) { - rPtAnalysis.add("hK0ShGeneratedPtSpectrum", "hK0ShGeneratedPtSpectrum", {HistType::kTH1F, {k0ShortPtAxis}}); rPtAnalysis.add("hK0ShortReconstructedPtSpectrum", "hK0ShortReconstructedPtSpectrum", {HistType::kTH1F, {k0ShortPtAxis}}); rPtAnalysis.add("hMassK0ShortAll", "hMassK0ShortAll", {HistType::kTH1F, {k0ShortMassAxis}}); rPtAnalysis.add("hK0ShortPtSpectrumBeforeCuts", "hK0ShortPtSpectrumBeforeCuts", {HistType::kTH1F, {k0ShortPtAxis}}); @@ -199,7 +207,6 @@ struct V0PtInvMassPlots { // Adding Lambda Histograms if (lambdaAnalysis == true) { // same method as in Kzerosh above - rPtAnalysis.add("hLambdaGeneratedPtSpectrum", "hLambdaGeneratedPtSpectrum", {HistType::kTH1F, {lambdaPtAxis}}); rPtAnalysis.add("hLambdaReconstructedPtSpectrum", "hLambdaReconstructedPtSpectrum", {HistType::kTH1F, {lambdaPtAxis}}); rPtAnalysis.add("hMassLambdaAll", "hMassLambdaAll", {HistType::kTH1F, {lambdaMassAxis}}); rPtAnalysis.add("hLambdaPtSpectrumBeforeCuts", "hLambdaPtSpectrumBeforeCuts", {HistType::kTH1F, {lambdaPtAxis}}); @@ -240,69 +247,191 @@ struct V0PtInvMassPlots { rFeeddownMatrices.add("hAntiLambdaAntiXiZeroFeeddownMatrix", "hAntiLambdaAntiXiZeroFeeddownMatrix", {HistType::kTH2F, {{antilambdaPtAxis}, {antilambdaPtAxis}}}); rFeeddownMatrices.add("hAntiLambdaAntiOmegaFeeddownMatrix", "hAntiLambdaAntiOmegaPlusFeeddownMatrix", {HistType::kTH2F, {{antilambdaPtAxis}, {antilambdaPtAxis}}}); } + + // Particle Level Corrections + rMCCorrections.add("hK0ShSplitDenominatorPtSpectrum", "hK0ShSplitDenominatorPtSpectrum", {HistType::kTH1D, {k0ShortPtAxis}}); + rMCCorrections.add("hLambdaSplitDenominatorPtSpectrum", "hLambdaSplitDenominatorPtSpectrum", {HistType::kTH1D, {lambdaPtAxis}}); + rMCCorrections.add("hAntilambdaSplitDenominatorPtSpectrum", "hAntilambdaSplitDenominatorPtSpectrum", {HistType::kTH1F, {{antilambdaPtAxis}}}); + rMCCorrections.add("hK0ShSplitNumenatorPtSpectrum", "hK0ShSplitNumenatorPtSpectrum", {HistType::kTH1D, {k0ShortPtAxis}}); + rMCCorrections.add("hLambdaSplitNumenatorPtSpectrum", "hLambdaSplitNumenatorPtSpectrum", {HistType::kTH1D, {lambdaPtAxis}}); + rMCCorrections.add("hAntilambdaSplitNumenatorPtSpectrum", "hAntilambdaSplitNumenatorPtSpectrum", {HistType::kTH1F, {{antilambdaPtAxis}}}); + rMCCorrections.add("hK0ShBeforeEventSelectionPtSpectrum", "hK0ShBeforeEventSelectionPtSpectrum", {HistType::kTH1D, {k0ShortPtAxis}}); + rMCCorrections.add("hLambdaBeforeEventSelectionPtSpectrum", "hLambdaBeforeEventSelectionPtSpectrum", {HistType::kTH1D, {lambdaPtAxis}}); + rMCCorrections.add("hAntilambdaBeforeEventSelectionPtSpectrum", "hAntilambdaBeforeEventSelectionPtSpectrum", {HistType::kTH1F, {{antilambdaPtAxis}}}); + rMCCorrections.add("hK0ShAfterEventSelectionPtSpectrum", "hK0ShAfterEventSelectionPtSpectrum", {HistType::kTH1D, {k0ShortPtAxis}}); + rMCCorrections.add("hLambdaAfterEventSelectionPtSpectrum", "hLambdaAfterEventSelectionPtSpectrum", {HistType::kTH1D, {lambdaPtAxis}}); + rMCCorrections.add("hAntilambdaAfterEventSelectionPtSpectrum", "hAntilambdaAfterEventSelectionPtSpectrum", {HistType::kTH1F, {{antilambdaPtAxis}}}); + + // Event and V0s Corrections + rMCCorrections.add("hNEvents", "hNEvents", {HistType::kTH1D, {{10, 0.f, 10.f}}}); + rMCCorrections.add("hNEvents_Corrections", "hNEvents_Corrections", {HistType::kTH1D, {{10, 0.f, 10.f}}}); + rMCCorrections.add("hNRecEvents_MC", "hNRecEvents_MC", {HistType::kTH1D, {{1, 0.f, 1.f}}}); + + // Generated Level Pt Spectrums + rMCCorrections.add("GenParticleRapidity", "GenParticleRapidity", {HistType::kTH1F, {{nBins, -10.0f, 10.0f}}}); + rMCCorrections.add("hK0ShGeneratedPtSpectrum", "hK0ShGeneratedPtSpectrum", {HistType::kTH1F, {k0ShortPtAxis}}); + rMCCorrections.add("hLambdaGeneratedPtSpectrum", "hLambdaGeneratedPtSpectrum", {HistType::kTH1F, {lambdaPtAxis}}); + rMCCorrections.add("hAntilambdaGeneratedPtSpectrum", "hAntilambdaGeneratedPtSpectrum", {HistType::kTH1F, {{antilambdaPtAxis}}}); + rMCCorrections.add("hXiMinusGeneratedPtSpectrum", "hXiMinusGeneratedPtSpectrum", {HistType::kTH1F, {lambdaPtAxis}}); + rMCCorrections.add("hXiZeroGeneratedPtSpectrum", "hXiZeroGeneratedPtSpectrum", {HistType::kTH1F, {lambdaPtAxis}}); + rMCCorrections.add("hOmegaGeneratedPtSpectrum", "hOmegaGeneratedPtSpectrum", {HistType::kTH1F, {lambdaPtAxis}}); + rMCCorrections.add("hXiPlusGeneratedPtSpectrum", "hXiPlusGeneratedPtSpectrum", {HistType::kTH1F, {antilambdaPtAxis}}); + rMCCorrections.add("hAntiXiZeroGeneratedPtSpectrum", "hAntiXiZeroGeneratedPtSpectrum", {HistType::kTH1F, {antilambdaPtAxis}}); + rMCCorrections.add("hAntiOmegaGeneratedPtSpectrum", "hAntiOmegaGeneratedPtSpectrum", {HistType::kTH1F, {antilambdaPtAxis}}); + rMCCorrections.add("hPhiGeneratedPtSpectrum", "hPhiGeneratedPtSpectrum", {HistType::kTH1F, {k0ShortPtAxis}}); } - // Defining filters for events (event selection) - // Processed events will be already fulfilling the event selection requirements - Filter eventFilter = (o2::aod::evsel::sel8 == true); - Filter posZFilterMC = (nabs(o2::aod::mccollision::posZ) < cutZVertex); - Filter posZFilter = (nabs(o2::aod::collision::posZ) < cutZVertex); + // Event selection + template + bool acceptEvent(TCollision const& collision) + { + rMCCorrections.fill(HIST("hNEvents"), 0.5); + if (!(collision.sel8() && dosel8)) { + return false; + } + rMCCorrections.fill(HIST("hNEvents"), 1.5); + if (!(collision.selection_bit(aod::evsel::kNoTimeFrameBorder) && doNoTimeFrameBorder)) { + return false; + } + rMCCorrections.fill(HIST("hNEvents"), 2.5); + if (!(collision.selection_bit(aod::evsel::kNoITSROFrameBorder) && doNoITSROFrameBorder)) { + return false; + } + rMCCorrections.fill(HIST("hNEvents"), 3.5); + if (!(collision.selection_bit(aod::evsel::kIsTriggerTVX) && doIsTriggerTVX)) { + return false; + } + rMCCorrections.fill(HIST("hNEvents"), 4.5); + if (!(std::abs(collision.posZ()) < cutZVertex && docutZVertex)) { + return false; + } + rMCCorrections.fill(HIST("hNEvents"), 5.5); + if (!(collision.selection_bit(aod::evsel::kIsVertexTOFmatched) && doIsVertexTOFmatched)) { + return false; + } + rMCCorrections.fill(HIST("hNEvents"), 6.5); + if (!(collision.selection_bit(aod::evsel::kNoSameBunchPileup) && doNoSameBunchPileup)) { + return false; + } + rMCCorrections.fill(HIST("hNEvents"), 7.5); + if (!(collision.selection_bit(aod::evsel::kIsVertexITSTPC) && doIsVertexITSTPC)) { + return false; + } + rMCCorrections.fill(HIST("hNEvents"), 8.5); + if (!(collision.isInelGt0() && doisInelGt0)) { + return false; + } + rMCCorrections.fill(HIST("hNEvents"), 9.5); + return true; + } // Defining the type of the daughter tracks using DaughterTracks = soa::Join; - // This is the Process for the MC Generated Data - // void genMCProcess(soa::Filtered::iterator const&, - // const soa::SmallGroups>& collision, - // aod::McParticles const& mcParticles) - void genMCProcess( // soa::Filtered::iterator const&, - soa::Filtered>::iterator const& collision, + void genMCProcess( + aod::McCollisions::iterator const& /*mcCollisions*/, + soa::SmallGroups> const& collisions, aod::McParticles const& mcParticles) { + // Event Efficiency, Event Split and V0 Signal Loss Corrections + rMCCorrections.fill(HIST("hNEvents_Corrections"), 0.5); // Event Efficiency Denominator + + // Signal Loss Denominator Loop for (const auto& mcParticle : mcParticles) { - if (collision.isInelGt0()) { + if (!mcParticle.isPhysicalPrimary()) { + continue; + } + if (std::abs(mcParticle.y()) > rapidityCut) { + continue; + } + if (mcParticle.pdgCode() == kK0Short) // kzero matched + { + rMCCorrections.fill(HIST("hK0ShBeforeEventSelectionPtSpectrum"), mcParticle.pt()); + } + if (mcParticle.pdgCode() == kLambda0) // lambda matched + { + rMCCorrections.fill(HIST("hLambdaBeforeEventSelectionPtSpectrum"), mcParticle.pt()); + } + if (mcParticle.pdgCode() == kLambda0Bar) // antilambda matched + { + rMCCorrections.fill(HIST("hAntilambdaBeforeEventSelectionPtSpectrum"), mcParticle.pt()); + } + } + // End of Signal Loss Denominator Loop + + for (const auto& collision : collisions) { + rMCCorrections.fill(HIST("hNEvents_Corrections"), 1.5); // Number of Events Reconsctructed + if (!acceptEvent(collision)) { // Event Selection + return; + } + rMCCorrections.fill(HIST("hNEvents_Corrections"), 2.5); // Event Split Denomimator and Event Efficiency Numenator + // Signal Loss Numenator Loop + for (const auto& mcParticle : mcParticles) { + if (!mcParticle.isPhysicalPrimary()) { + continue; + } + if (std::abs(mcParticle.y()) > rapidityCut) { + continue; + } + if (mcParticle.pdgCode() == kK0Short) // kzero matched + { + rMCCorrections.fill(HIST("hK0ShAfterEventSelectionPtSpectrum"), mcParticle.pt()); + } + if (mcParticle.pdgCode() == kLambda0) // lambda matched + { + rMCCorrections.fill(HIST("hLambdaAfterEventSelectionPtSpectrum"), mcParticle.pt()); + } + if (mcParticle.pdgCode() == kLambda0Bar) // antilambda matched + { + rMCCorrections.fill(HIST("hAntilambdaAfterEventSelectionPtSpectrum"), mcParticle.pt()); + } + } + // End of Signal Loss Numenator Loop + + // Particles (of interest) Generated Pt Spectrum + for (const auto& mcParticle : mcParticles) { if (std::abs(mcParticle.y()) < rapidityCut) { if (mcParticle.isPhysicalPrimary()) { - rPtAnalysis.fill(HIST("GenParticleRapidity"), mcParticle.y()); + rMCCorrections.fill(HIST("GenParticleRapidity"), mcParticle.y()); if (mcParticle.pdgCode() == kK0Short) // kzero matched { - rPtAnalysis.fill(HIST("hK0ShGeneratedPtSpectrum"), mcParticle.pt()); + rMCCorrections.fill(HIST("hK0ShGeneratedPtSpectrum"), mcParticle.pt()); } if (mcParticle.pdgCode() == kLambda0) // lambda matched { - rPtAnalysis.fill(HIST("hLambdaGeneratedPtSpectrum"), mcParticle.pt()); + rMCCorrections.fill(HIST("hLambdaGeneratedPtSpectrum"), mcParticle.pt()); } if (mcParticle.pdgCode() == kLambda0Bar) // antilambda matched { - rPtAnalysis.fill(HIST("hAntilambdaGeneratedPtSpectrum"), mcParticle.pt()); + rMCCorrections.fill(HIST("hAntilambdaGeneratedPtSpectrum"), mcParticle.pt()); } if (mcParticle.pdgCode() == kXiMinus) // Xi Minus matched { - rPtAnalysis.fill(HIST("hXiMinusGeneratedPtSpectrum"), mcParticle.pt()); + rMCCorrections.fill(HIST("hXiMinusGeneratedPtSpectrum"), mcParticle.pt()); } if (mcParticle.pdgCode() == kXi0) // Xi Zero matched { - rPtAnalysis.fill(HIST("hXiZeroGeneratedPtSpectrum"), mcParticle.pt()); + rMCCorrections.fill(HIST("hXiZeroGeneratedPtSpectrum"), mcParticle.pt()); } if (mcParticle.pdgCode() == kOmegaMinus) // Omega matched { - rPtAnalysis.fill(HIST("hOmegaGeneratedPtSpectrum"), mcParticle.pt()); + rMCCorrections.fill(HIST("hOmegaGeneratedPtSpectrum"), mcParticle.pt()); } if (mcParticle.pdgCode() == kXiPlusBar) // Xi Plus matched { - rPtAnalysis.fill(HIST("hXiPlusGeneratedPtSpectrum"), mcParticle.pt()); + rMCCorrections.fill(HIST("hXiPlusGeneratedPtSpectrum"), mcParticle.pt()); } if (mcParticle.pdgCode() == -kXi0) // Anti-Xi Zero matched { - rPtAnalysis.fill(HIST("hAntiXiZeroGeneratedPtSpectrum"), mcParticle.pt()); + rMCCorrections.fill(HIST("hAntiXiZeroGeneratedPtSpectrum"), mcParticle.pt()); } if (mcParticle.pdgCode() == kOmegaPlusBar) // Anti-Omega matched { - rPtAnalysis.fill(HIST("hAntiOmegaGeneratedPtSpectrum"), mcParticle.pt()); + rMCCorrections.fill(HIST("hAntiOmegaGeneratedPtSpectrum"), mcParticle.pt()); } - if (mcParticle.pdgCode() == kPhi) // Anti-Omega matched + if (mcParticle.pdgCode() == kPhi) // Phi { - rPtAnalysis.fill(HIST("hPhiGeneratedPtSpectrum"), mcParticle.pt()); + rMCCorrections.fill(HIST("hPhiGeneratedPtSpectrum"), mcParticle.pt()); } } } @@ -310,10 +439,10 @@ struct V0PtInvMassPlots { } } // This is the Process for the MC reconstructed Data - void recMCProcess(soa::Filtered>::iterator const& collision, + void recMCProcess(soa::Join::iterator const& collision, soa::Join const& V0s, DaughterTracks const&, // no need to define a variable for tracks, if we don't access them directly - aod::McParticles const&) + aod::McParticles const& mcParticles) { // PDG mass values for Competitive V0 Cut old: const auto& mK0shPDG = 0.497611; double mK0shPDG = o2::constants::physics::MassK0Short; @@ -334,121 +463,183 @@ struct V0PtInvMassPlots { lambdaptedgevalues[i] = std::stod(pthistos::lambdaPtBins[i]); antilambdaPtedgevalues[i] = std::stod(pthistos::antilambdaPtBins[i]); } - rPtAnalysis.fill(HIST("hVertexZ"), collision.posZ()); - if (collision.isInelGt0()) { - for (const auto& v0 : V0s) { - rPtAnalysis.fill(HIST("hVertexZRec"), collision.posZ()); - // Checking that the V0 is a true K0s/Lambdas/Antilambdas and then filling the parameter histograms and the invariant mass plots for different cuts (which are taken from namespace) - if (v0.has_mcParticle()) { - auto v0mcParticle = v0.mcParticle(); - if (std::abs(v0mcParticle.y()) < rapidityCut) { - rPtAnalysis.fill(HIST("V0Rapidity"), v0.y()); - if (std::abs(v0.posTrack_as().eta()) < etadau && std::abs(v0.negTrack_as().eta()) < etadau) { // daughters pseudorapidityCut cut - rPtAnalysis.fill(HIST("hV0EtaDaughters"), v0.negTrack_as().eta()); - rPtAnalysis.fill(HIST("hV0EtaDaughters"), v0.posTrack_as().eta()); - if (kzeroAnalysis == true) { - if (v0mcParticle.pdgCode() == kK0Short) { // kzero matched - rPtAnalysis.fill(HIST("hMassK0ShortAll"), v0.mK0Short()); - rPtAnalysis.fill(HIST("hK0ShortPtSpectrumBeforeCuts"), v0.pt()); - if (std::abs(v0.mLambda() - mLambdaPDG) > compv0masscut && std::abs(v0.mAntiLambda() - mLambdaPDG) > compv0masscut) { // Kzero competitive v0 mass cut (cut out Lambdas and Anti-Lambdas) - // Implementing best kzero topological cuts - if (v0.v0cosPA() > kaonshSettingcosPA && v0.dcaV0daughters() < kaonshSettingdcav0dau && v0.v0radius() > kaonshSettingradius && std::abs(v0.dcapostopv()) > kaonshSettingdcapostopv && std::abs(v0.dcanegtopv()) > kaonshSettingdcanegtopv) { - rPtAnalysis.fill(HIST("hMassK0ShortAllAfterCuts"), v0.mK0Short()); - rPtAnalysis.fill(HIST("hK0ShortReconstructedPtSpectrum"), v0.pt()); - rPtAnalysis.fill(HIST("hK0shEtaDaughters"), v0.negTrack_as().eta()); - rPtAnalysis.fill(HIST("hK0shEtaDaughters"), v0.posTrack_as().eta()); - rPtAnalysis.fill(HIST("hK0shNegDaughterPt"), v0.negTrack_as().pt()); // Neg Daughter Pt - rPtAnalysis.fill(HIST("hK0shPosDaughterPt"), v0.posTrack_as().pt()); // Pos Daughter Pt - if (v0mcParticle.isPhysicalPrimary()) { - for (int i = 0; i < nmaxHistograms; i++) { - if (kaonptedgevalues[i] <= v0.pt() && v0.pt() < kaonptedgevalues[i + 1]) { // finding v0s with pt within the range of our bin edges - pthistos::kaonPt[i]->Fill(v0.mK0Short()); // filling the k0s namespace histograms + if (!acceptEvent(collision)) { // Event Selection + return; + } + rMCCorrections.fill(HIST("hNRecEvents_MC"), 1.0); // Event Split Numenator + + // v0 Signal Splitting Numenator Start + for (const auto& mcParticle : mcParticles) { + if (mcParticle.isPhysicalPrimary()) { + if (std::abs(mcParticle.y()) < rapidityCut) { + if (mcParticle.pdgCode() == kK0Short) { // kzero matched + rMCCorrections.fill(HIST("hK0ShSplitNumenatorPtSpectrum"), mcParticle.pt()); + } + if (mcParticle.pdgCode() == kLambda0) { // lambda matched + rMCCorrections.fill(HIST("hLambdaSplitNumenatorPtSpectrum"), mcParticle.pt()); + } + if (mcParticle.pdgCode() == kLambda0Bar) { // antilambda matched + rMCCorrections.fill(HIST("hAntilambdaSplitNumenatorPtSpectrum"), mcParticle.pt()); + } + } + } + } + // V0 Signal Splitting Numenator End + + for (const auto& v0 : V0s) { + const auto& posDaughterTrack = v0.posTrack_as(); // Daughter tracks for PID + const auto& negDaughterTrack = v0.negTrack_as(); // Daughter tracks for PID + rPtAnalysis.fill(HIST("hNV0s"), 0.5); + rPtAnalysis.fill(HIST("hVertexZRec"), collision.posZ()); + // Checking that the V0 is a true K0s/Lambdas/Antilambdas and then filling the parameter histograms and the invariant mass plots for different cuts (which are taken from namespace) + if (v0.has_mcParticle()) { + auto v0mcParticle = v0.mcParticle(); + rPtAnalysis.fill(HIST("hNV0s"), 1.5); + if (std::abs(v0mcParticle.y()) < rapidityCut) { + rPtAnalysis.fill(HIST("hNV0s"), 2.5); + rPtAnalysis.fill(HIST("V0Rapidity"), v0.y()); + + // signal splitting demoninator + if (v0mcParticle.isPhysicalPrimary()) { + if (v0mcParticle.pdgCode() == kK0Short) { // kzero matched + rMCCorrections.fill(HIST("hK0ShSplitDenominatorPtSpectrum"), v0mcParticle.pt()); + } + if (v0mcParticle.pdgCode() == kLambda0) { // lambda matched + rMCCorrections.fill(HIST("hLambdaSplitDenominatorPtSpectrum"), v0mcParticle.pt()); + } + if (v0mcParticle.pdgCode() == kLambda0Bar) { // antilambda matched + rMCCorrections.fill(HIST("hAntilambdaSplitDenominatorPtSpectrum"), v0mcParticle.pt()); + } + } + // signal splitting demoninator end + + if (std::abs(v0.posTrack_as().eta()) < etadau && std::abs(v0.negTrack_as().eta()) < etadau) { // daughters pseudorapidityCut cut + rPtAnalysis.fill(HIST("hNV0s"), 3.5); + rPtAnalysis.fill(HIST("hV0EtaDaughters"), v0.negTrack_as().eta()); + rPtAnalysis.fill(HIST("hV0EtaDaughters"), v0.posTrack_as().eta()); + if (v0.negTrack_as().isITSAfterburner() && v0.posTrack_as().isITSAfterburner()) { // ITS After Burner on daughter tracks + rPtAnalysis.fill(HIST("hNV0s"), 4.5); + if (v0.negTrack_as().itsNCls() >= itsMinHits && v0.posTrack_as().itsNCls() >= itsMinHits) { // Minimum hits in the ITS + rPtAnalysis.fill(HIST("hNV0s"), 5.5); + if (kzeroAnalysis == true) { + // kzero analysis + if (std::abs(posDaughterTrack.tpcNSigmaPi()) < nSigmaTPCPion && std::abs(negDaughterTrack.tpcNSigmaPi()) < nSigmaTPCPion) { // PID for two pions + if (v0mcParticle.pdgCode() == kK0Short) { // kzero matched + rPtAnalysis.fill(HIST("hMassK0ShortAll"), v0.mK0Short()); + rPtAnalysis.fill(HIST("hK0ShortPtSpectrumBeforeCuts"), v0.pt()); + if (std::abs(v0.mLambda() - mLambdaPDG) > compv0masscut && std::abs(v0.mAntiLambda() - mLambdaPDG) > compv0masscut) { // Kzero competitive v0 mass cut (cut out Lambdas and Anti-Lambdas) + // Implementing best kzero topological cuts + if (v0.v0radius() < kaonshmaxct) { + if (v0.qtarm() > (paramArmenterosCut * std::abs(v0.alpha()))) { + if (v0.v0cosPA() > kaonshSettingcosPA && v0.dcaV0daughters() < kaonshSettingdcav0dau && v0.v0radius() > kaonshSettingradius && std::abs(v0.dcapostopv()) > kaonshSettingdcapostopv && std::abs(v0.dcanegtopv()) > kaonshSettingdcanegtopv) { + rPtAnalysis.fill(HIST("hMassK0ShortAllAfterCuts"), v0.mK0Short()); + rPtAnalysis.fill(HIST("hK0ShortReconstructedPtSpectrum"), v0.pt()); + rPtAnalysis.fill(HIST("hK0shEtaDaughters"), v0.negTrack_as().eta()); + rPtAnalysis.fill(HIST("hK0shEtaDaughters"), v0.posTrack_as().eta()); + rPtAnalysis.fill(HIST("hK0shNegDaughterPt"), v0.negTrack_as().pt()); // Neg Daughter Pt + rPtAnalysis.fill(HIST("hK0shPosDaughterPt"), v0.posTrack_as().pt()); // Pos Daughter Pt + if (v0mcParticle.isPhysicalPrimary()) { + for (int i = 0; i < nmaxHistograms; i++) { + if (kaonptedgevalues[i] <= v0.pt() && v0.pt() < kaonptedgevalues[i + 1]) { // finding v0s with pt within the range of our bin edges + pthistos::kaonPt[i]->Fill(v0.mK0Short()); // filling the k0s namespace histograms + } + } + } + } } } } } } } - } - // lambda analysis - if (lambdaAnalysis == true) { - if (v0mcParticle.pdgCode() == kLambda0) { // lambda matched - rPtAnalysis.fill(HIST("hMassLambdaAll"), v0.mLambda()); - rPtAnalysis.fill(HIST("hLambdaPtSpectrumBeforeCuts"), v0.pt()); - if (std::abs(v0.mK0Short() - mK0shPDG) > compv0masscut) { // lambda competitive v0 mass cut (cut out Kaons) - // Implementing best lambda cuts - if (v0.v0cosPA() > lambdaSettingcosPA && v0.dcaV0daughters() < lambdaSettingdcav0dau && v0.v0radius() > lambdaSettingradius && std::abs(v0.dcapostopv()) > lambdaSettingdcapostopv && std::abs(v0.dcanegtopv()) > lambdaSettingdcanegtopv) { - rPtAnalysis.fill(HIST("hMassLambdaAllAfterCuts"), v0.mLambda()); - rPtAnalysis.fill(HIST("hLambdaReconstructedPtSpectrum"), v0.pt()); - rPtAnalysis.fill(HIST("hLambdaEtaDaughters"), v0.negTrack_as().eta()); - rPtAnalysis.fill(HIST("hLambdaEtaDaughters"), v0.posTrack_as().eta()); - rPtAnalysis.fill(HIST("hLambdaNegDaughterPt"), v0.negTrack_as().pt()); // Neg Daughter Pt - rPtAnalysis.fill(HIST("hLambdaPosDaughterPt"), v0.posTrack_as().pt()); // Pos Daughter Pt - if (v0mcParticle.isPhysicalPrimary()) { - for (int i = 0; i < nmaxHistograms; i++) { - if (lambdaptedgevalues[i] <= v0.pt() && v0.pt() < lambdaptedgevalues[i + 1]) { - pthistos::lambdaPt[i]->Fill(v0.mLambda()); - } - } - } - if (!v0mcParticle.isPhysicalPrimary()) { - auto v0mothers = v0mcParticle.mothers_as(); // Get mothers - if (!v0mothers.empty()) { - auto& v0mcParticleMother = v0mothers.front(); // First mother - if (v0mcParticleMother.pdgCode() == kXiMinus) // Xi Minus Mother Matched - { - rFeeddownMatrices.fill(HIST("hLambdaXiMinusFeeddownMatrix"), v0mcParticle.pt(), v0mcParticleMother.pt()); - } - if (v0mcParticleMother.pdgCode() == kXi0) // Xi Zero Mother Matched - { - rFeeddownMatrices.fill(HIST("hLambdaXiZeroFeeddownMatrix"), v0mcParticle.pt(), v0mcParticleMother.pt()); - } - if (v0mcParticleMother.pdgCode() == kOmegaMinus) // Omega Mother Matched - { - rFeeddownMatrices.fill(HIST("hLambdaOmegaFeeddownMatrix"), v0mcParticle.pt(), v0mcParticleMother.pt()); + // lambda analysis + if (lambdaAnalysis == true) { + if (std::abs(posDaughterTrack.tpcNSigmaPr()) < nSigmaTPCProton && std::abs(negDaughterTrack.tpcNSigmaPi()) < nSigmaTPCPion) { // TPC PID on daughter pion and proton for Lambda + if (v0mcParticle.pdgCode() == kLambda0) { // lambda matched + rPtAnalysis.fill(HIST("hMassLambdaAll"), v0.mLambda()); + rPtAnalysis.fill(HIST("hLambdaPtSpectrumBeforeCuts"), v0.pt()); + if (std::abs(v0.mK0Short() - mK0shPDG) > compv0masscut) { // lambda competitive v0 mass cut (cut out Kaons) + // Implementing best lambda cuts + if (v0.v0radius() < lambdamaxct) { + if (v0.v0cosPA() > lambdaSettingcosPA && v0.dcaV0daughters() < lambdaSettingdcav0dau && v0.v0radius() > lambdaSettingradius && std::abs(v0.dcapostopv()) > lambdaSettingdcapostopv && std::abs(v0.dcanegtopv()) > lambdaSettingdcanegtopv) { + rPtAnalysis.fill(HIST("hMassLambdaAllAfterCuts"), v0.mLambda()); + rPtAnalysis.fill(HIST("hLambdaReconstructedPtSpectrum"), v0.pt()); + rPtAnalysis.fill(HIST("hLambdaEtaDaughters"), v0.negTrack_as().eta()); + rPtAnalysis.fill(HIST("hLambdaEtaDaughters"), v0.posTrack_as().eta()); + rPtAnalysis.fill(HIST("hLambdaNegDaughterPt"), v0.negTrack_as().pt()); // Neg Daughter Pt + rPtAnalysis.fill(HIST("hLambdaPosDaughterPt"), v0.posTrack_as().pt()); // Pos Daughter Pt + if (v0mcParticle.isPhysicalPrimary()) { + for (int i = 0; i < nmaxHistograms; i++) { + if (lambdaptedgevalues[i] <= v0.pt() && v0.pt() < lambdaptedgevalues[i + 1]) { + pthistos::lambdaPt[i]->Fill(v0.mLambda()); + } + } + } + if (!v0mcParticle.isPhysicalPrimary()) { + auto v0mothers = v0mcParticle.mothers_as(); // Get mothers + if (!v0mothers.empty()) { + auto& v0mcParticleMother = v0mothers.front(); // First mother + if (v0mcParticleMother.pdgCode() == kXiMinus) // Xi Minus Mother Matched + { + rFeeddownMatrices.fill(HIST("hLambdaXiMinusFeeddownMatrix"), v0mcParticle.pt(), v0mcParticleMother.pt()); + } + if (v0mcParticleMother.pdgCode() == kXi0) // Xi Zero Mother Matched + { + rFeeddownMatrices.fill(HIST("hLambdaXiZeroFeeddownMatrix"), v0mcParticle.pt(), v0mcParticleMother.pt()); + } + if (v0mcParticleMother.pdgCode() == kOmegaMinus) // Omega Mother Matched + { + rFeeddownMatrices.fill(HIST("hLambdaOmegaFeeddownMatrix"), v0mcParticle.pt(), v0mcParticleMother.pt()); + } + } + } } } } } } } - } - // antilambda analysis - if (antiLambdaAnalysis == true) { - if (v0mcParticle.pdgCode() == kLambda0Bar) { // antilambda matched - rPtAnalysis.fill(HIST("hMassAntilambdaAll"), v0.mAntiLambda()); - rPtAnalysis.fill(HIST("hantilambdaPtSpectrumBeforeCuts"), v0.pt()); - if (std::abs(v0.mK0Short() - mK0shPDG) > compv0masscut) { // antilambda competitive v0 mass cut (cut out Kaons) - // Implementing best antilambda cuts - if (v0.v0cosPA() > antilambdaSettingcosPA && v0.dcaV0daughters() < antilambdaSettingdcav0dau && v0.v0radius() > antilambdaSettingradius && std::abs(v0.dcapostopv()) > antilambdaSettingdcapostopv && std::abs(v0.dcanegtopv()) > antilambdaSettingdcanegtopv) { - rPtAnalysis.fill(HIST("hMassAntilambdaAllAfterCuts"), v0.mAntiLambda()); - rPtAnalysis.fill(HIST("hAntilambdaReconstructedPtSpectrum"), v0.pt()); - rPtAnalysis.fill(HIST("hAntiLambdaEtaDaughters"), v0.negTrack_as().eta()); - rPtAnalysis.fill(HIST("hAntiLambdaEtaDaughters"), v0.posTrack_as().eta()); - rPtAnalysis.fill(HIST("hAntiLambdaNegDaughterPt"), v0.negTrack_as().pt()); // Neg Daughter Pt - rPtAnalysis.fill(HIST("hAntiLambdaPosDaughterPt"), v0.posTrack_as().pt()); // Pos Daughter Pt - if (v0mcParticle.isPhysicalPrimary()) { - for (int i = 0; i < nmaxHistograms; i++) { - if (antilambdaPtedgevalues[i] <= v0.pt() && v0.pt() < antilambdaPtedgevalues[i + 1]) { - pthistos::antilambdaPt[i]->Fill(v0.mAntiLambda()); - } - } - } - if (!v0mcParticle.isPhysicalPrimary()) { - auto v0mothers = v0mcParticle.mothers_as(); // Get mothers - if (!v0mothers.empty()) { - auto& v0mcParticleMother = v0mothers.front(); // First mother - if (v0mcParticleMother.pdgCode() == kXiPlusBar) // Xi Plus Mother Matched - { - rFeeddownMatrices.fill(HIST("hAntiLambdaXiPlusFeeddownMatrix"), v0mcParticle.pt(), v0mcParticleMother.pt()); - } - if (v0mcParticleMother.pdgCode() == -kXi0) // Anti-Xi Zero Mother Matched - { - rFeeddownMatrices.fill(HIST("hAntiLambdaAntiXiZeroFeeddownMatrix"), v0mcParticle.pt(), v0mcParticleMother.pt()); - } - if (v0mcParticleMother.pdgCode() == kOmegaPlusBar) // Anti-Omega (minus) Mother Matched - { - rFeeddownMatrices.fill(HIST("hAntiLambdaAntiOmegaFeeddownMatrix"), v0mcParticle.pt(), v0mcParticleMother.pt()); + // antilambda analysis + if (antiLambdaAnalysis == true) { + if (std::abs(negDaughterTrack.tpcNSigmaPr()) < nSigmaTPCProton && std::abs(posDaughterTrack.tpcNSigmaPi()) < nSigmaTPCPion) { // TPC PID on daughter pion and proton for AntiLambda + if (v0mcParticle.pdgCode() == kLambda0Bar) { // antilambda matched + rPtAnalysis.fill(HIST("hMassAntilambdaAll"), v0.mAntiLambda()); + rPtAnalysis.fill(HIST("hantilambdaPtSpectrumBeforeCuts"), v0.pt()); + if (std::abs(v0.mK0Short() - mK0shPDG) > compv0masscut) { // antilambda competitive v0 mass cut (cut out Kaons) + if (v0.v0radius() < antilambdamaxct) { + // Implementing best antilambda cuts + if (v0.v0cosPA() > antilambdaSettingcosPA && v0.dcaV0daughters() < antilambdaSettingdcav0dau && v0.v0radius() > antilambdaSettingradius && std::abs(v0.dcapostopv()) > antilambdaSettingdcapostopv && std::abs(v0.dcanegtopv()) > antilambdaSettingdcanegtopv) { + rPtAnalysis.fill(HIST("hMassAntilambdaAllAfterCuts"), v0.mAntiLambda()); + rPtAnalysis.fill(HIST("hAntilambdaReconstructedPtSpectrum"), v0.pt()); + rPtAnalysis.fill(HIST("hAntiLambdaEtaDaughters"), v0.negTrack_as().eta()); + rPtAnalysis.fill(HIST("hAntiLambdaEtaDaughters"), v0.posTrack_as().eta()); + rPtAnalysis.fill(HIST("hAntiLambdaNegDaughterPt"), v0.negTrack_as().pt()); // Neg Daughter Pt + rPtAnalysis.fill(HIST("hAntiLambdaPosDaughterPt"), v0.posTrack_as().pt()); // Pos Daughter Pt + if (v0mcParticle.isPhysicalPrimary()) { + for (int i = 0; i < nmaxHistograms; i++) { + if (antilambdaPtedgevalues[i] <= v0.pt() && v0.pt() < antilambdaPtedgevalues[i + 1]) { + pthistos::antilambdaPt[i]->Fill(v0.mAntiLambda()); + } + } + } + if (!v0mcParticle.isPhysicalPrimary()) { + auto v0mothers = v0mcParticle.mothers_as(); // Get mothers + if (!v0mothers.empty()) { + auto& v0mcParticleMother = v0mothers.front(); // First mother + if (v0mcParticleMother.pdgCode() == kXiPlusBar) // Xi Plus Mother Matched + { + rFeeddownMatrices.fill(HIST("hAntiLambdaXiPlusFeeddownMatrix"), v0mcParticle.pt(), v0mcParticleMother.pt()); + } + if (v0mcParticleMother.pdgCode() == -kXi0) // Anti-Xi Zero Mother Matched + { + rFeeddownMatrices.fill(HIST("hAntiLambdaAntiXiZeroFeeddownMatrix"), v0mcParticle.pt(), v0mcParticleMother.pt()); + } + if (v0mcParticleMother.pdgCode() == kOmegaPlusBar) // Anti-Omega (minus) Mother Matched + { + rFeeddownMatrices.fill(HIST("hAntiLambdaAntiOmegaFeeddownMatrix"), v0mcParticle.pt(), v0mcParticleMother.pt()); + } + } + } } } } @@ -463,7 +654,7 @@ struct V0PtInvMassPlots { } } // This is the process for Real Data - void dataProcess(soa::Filtered>::iterator const& collision, + void dataProcess(soa::Join::iterator const& collision, aod::V0Datas const& V0s, DaughterTracks const&) { @@ -484,94 +675,112 @@ struct V0PtInvMassPlots { lambdaptedgevalues[i] = std::stod(pthistos::lambdaPtBins[i]); antilambdaPtedgevalues[i] = std::stod(pthistos::antilambdaPtBins[i]); } - rPtAnalysis.fill(HIST("hVertexZ"), collision.posZ()); - if (collision.isInelGt0()) { - for (const auto& v0 : V0s) { - const auto& posDaughterTrack = v0.posTrack_as(); - const auto& negDaughterTrack = v0.negTrack_as(); - rPtAnalysis.fill(HIST("hVertexZRec"), collision.posZ()); - if (std::abs(v0.y()) < rapidityCut) { - rPtAnalysis.fill(HIST("V0Rapidity"), v0.y()); - if (std::abs(v0.posTrack_as().eta()) < etadau && std::abs(v0.negTrack_as().eta()) < etadau) { // daughters pseudorapidityCut cut - rPtAnalysis.fill(HIST("hV0EtaDaughters"), v0.negTrack_as().eta()); - rPtAnalysis.fill(HIST("hV0EtaDaughters"), v0.posTrack_as().eta()); - // Armenteros-Podolandski Plot Values - double pv0 = std::sqrt((v0.px() * v0.px()) + (v0.py() * v0.py()) + (v0.pz() * v0.pz())); - double pposdauparallelv0 = ((v0.posTrack_as().px() * v0.px()) + (v0.posTrack_as().py() * v0.py()) + (v0.posTrack_as().pz() * v0.pz())) / pv0; - double qValue = std::sqrt(((v0.posTrack_as().px() * v0.posTrack_as().px()) + (v0.posTrack_as().py() * v0.posTrack_as().py()) + (v0.posTrack_as().pz() * v0.posTrack_as().pz())) - (pposdauparallelv0 * pposdauparallelv0)); - double plpos = (v0.posTrack_as().px() * v0.px() / pv0) + (v0.posTrack_as().py() * v0.py() / pv0) + (v0.posTrack_as().pz() * v0.pz() / pv0); - double plneg = (v0.negTrack_as().px() * v0.px() / pv0) + (v0.negTrack_as().py() * v0.py() / pv0) + (v0.negTrack_as().pz() * v0.pz() / pv0); - double aValue = (plpos - plneg) / (plpos + plneg); - rPtAnalysis.fill(HIST("hArmenterosPodolanskiPlot"), aValue, qValue); - // kzero analysis - if (kzeroAnalysis == true) { - // Filling the five Kzero invariant mass plots for different cuts (which are taken from namespace), for full explanation see the first kzero cut filling in the MC process - rPtAnalysis.fill(HIST("hMassK0ShortAll"), v0.mK0Short()); - if (std::abs(v0.mLambda() - mLambdaPDG) > compv0masscut && std::abs(v0.mAntiLambda() - mLambdaPDG) > compv0masscut) { // antilambda competitive v0 mass cut (cut out Lambdas and Anti-Lambdas) - // Implementing best kzero cuts - if (std::abs(posDaughterTrack.tpcNSigmaPi()) < nSigmaTPCPion && std::abs(negDaughterTrack.tpcNSigmaPi()) < nSigmaTPCPion) { // TPC PID on daughter pions - rPtAnalysis.fill(HIST("hNSigmaPosPiFromK0s"), posDaughterTrack.tpcNSigmaPi(), posDaughterTrack.tpcInnerParam()); - rPtAnalysis.fill(HIST("hNSigmaNegPiFromK0s"), negDaughterTrack.tpcNSigmaPi(), negDaughterTrack.tpcInnerParam()); - if (v0.v0cosPA() > kaonshSettingcosPA && v0.dcaV0daughters() < kaonshSettingdcav0dau && v0.v0radius() > kaonshSettingradius && std::abs(v0.dcapostopv()) > kaonshSettingdcapostopv && std::abs(v0.dcanegtopv()) > kaonshSettingdcanegtopv) { - rPtAnalysis.fill(HIST("hMassK0ShortAllAfterCuts"), v0.mK0Short()); - rPtAnalysis.fill(HIST("hK0shEtaDaughters"), v0.negTrack_as().eta()); - rPtAnalysis.fill(HIST("hK0shEtaDaughters"), v0.posTrack_as().eta()); - rPtAnalysis.fill(HIST("hArmenterosPodolanskiPlotK0Short"), aValue, qValue); - rPtAnalysis.fill(HIST("hK0shNegDaughterPt"), v0.negTrack_as().pt()); // Neg Daughter Pt - rPtAnalysis.fill(HIST("hK0shPosDaughterPt"), v0.posTrack_as().pt()); // Pos Daughter Pt - for (int i = 0; i < nmaxHistograms; i++) { - if (kaonptedgevalues[i] <= v0.pt() && v0.pt() < kaonptedgevalues[i + 1]) { - pthistos::kaonPt[i]->Fill(v0.mK0Short()); + if (!acceptEvent(collision)) { // Event Selection + return; + } + rPtAnalysis.fill(HIST("hNRecEvents_Data"), 1.0); // Number of Reconstructed Events + for (const auto& v0 : V0s) { + rPtAnalysis.fill(HIST("hNV0s"), 0.5); + const auto& posDaughterTrack = v0.posTrack_as(); // Daughter tracks for PID + const auto& negDaughterTrack = v0.negTrack_as(); // Daughter tracks for PID + rPtAnalysis.fill(HIST("hVertexZRec"), collision.posZ()); + if (std::abs(v0.y()) < rapidityCut) { + rPtAnalysis.fill(HIST("hNV0s"), 1.5); + rPtAnalysis.fill(HIST("V0Rapidity"), v0.y()); + if (std::abs(v0.posTrack_as().eta()) < etadau && std::abs(v0.negTrack_as().eta()) < etadau) { // daughters pseudorapidityCut cut + rPtAnalysis.fill(HIST("hNV0s"), 2.5); + rPtAnalysis.fill(HIST("hV0EtaDaughters"), v0.negTrack_as().eta()); + rPtAnalysis.fill(HIST("hV0EtaDaughters"), v0.posTrack_as().eta()); + if (v0.negTrack_as().isITSAfterburner() && v0.posTrack_as().isITSAfterburner()) { // ITS After Burner on daughter tracks + rPtAnalysis.fill(HIST("hNV0s"), 3.5); + if (v0.negTrack_as().itsNCls() >= itsMinHits && v0.posTrack_as().itsNCls() >= itsMinHits) { // Minimum hits in the ITS + rPtAnalysis.fill(HIST("hNV0s"), 4.5); + // Armenteros-Podolandski Plot Values + double pv0 = std::sqrt((v0.px() * v0.px()) + (v0.py() * v0.py()) + (v0.pz() * v0.pz())); + double pposdauparallelv0 = ((v0.posTrack_as().px() * v0.px()) + (v0.posTrack_as().py() * v0.py()) + (v0.posTrack_as().pz() * v0.pz())) / pv0; + double qValue = std::sqrt(((v0.posTrack_as().px() * v0.posTrack_as().px()) + (v0.posTrack_as().py() * v0.posTrack_as().py()) + (v0.posTrack_as().pz() * v0.posTrack_as().pz())) - (pposdauparallelv0 * pposdauparallelv0)); + double plpos = (v0.posTrack_as().px() * v0.px() / pv0) + (v0.posTrack_as().py() * v0.py() / pv0) + (v0.posTrack_as().pz() * v0.pz() / pv0); + double plneg = (v0.negTrack_as().px() * v0.px() / pv0) + (v0.negTrack_as().py() * v0.py() / pv0) + (v0.negTrack_as().pz() * v0.pz() / pv0); + double aValue = (plpos - plneg) / (plpos + plneg); + rPtAnalysis.fill(HIST("hArmenterosPodolanskiPlot"), aValue, qValue); + // kzero analysis + if (kzeroAnalysis == true) { + // Filling the five Kzero invariant mass plots for different cuts (which are taken from namespace), for full explanation see the first kzero cut filling in the MC process + rPtAnalysis.fill(HIST("hMassK0ShortAll"), v0.mK0Short()); + if (std::abs(v0.mLambda() - mLambdaPDG) > compv0masscut && std::abs(v0.mAntiLambda() - mLambdaPDG) > compv0masscut) { // antilambda competitive v0 mass cut (cut out Lambdas and Anti-Lambdas) + // Implementing best kzero cuts + if (std::abs(posDaughterTrack.tpcNSigmaPi()) < nSigmaTPCPion && std::abs(negDaughterTrack.tpcNSigmaPi()) < nSigmaTPCPion) { // TPC PID on daughter pions + rPtAnalysis.fill(HIST("hNSigmaPosPiFromK0s"), posDaughterTrack.tpcNSigmaPi(), posDaughterTrack.tpcInnerParam()); + rPtAnalysis.fill(HIST("hNSigmaNegPiFromK0s"), negDaughterTrack.tpcNSigmaPi(), negDaughterTrack.tpcInnerParam()); + if (v0.v0radius() < kaonshmaxct) { + if (v0.qtarm() > (paramArmenterosCut * std::abs(v0.alpha()))) { + if (v0.v0cosPA() > kaonshSettingcosPA && v0.dcaV0daughters() < kaonshSettingdcav0dau && v0.v0radius() > kaonshSettingradius && std::abs(v0.dcapostopv()) > kaonshSettingdcapostopv && std::abs(v0.dcanegtopv()) > kaonshSettingdcanegtopv) { + rPtAnalysis.fill(HIST("hMassK0ShortAllAfterCuts"), v0.mK0Short()); + rPtAnalysis.fill(HIST("hK0shEtaDaughters"), v0.negTrack_as().eta()); + rPtAnalysis.fill(HIST("hK0shEtaDaughters"), v0.posTrack_as().eta()); + rPtAnalysis.fill(HIST("hArmenterosPodolanskiPlotK0Short"), aValue, qValue); + rPtAnalysis.fill(HIST("hK0shNegDaughterPt"), v0.negTrack_as().pt()); // Neg Daughter Pt + rPtAnalysis.fill(HIST("hK0shPosDaughterPt"), v0.posTrack_as().pt()); // Pos Daughter Pt + for (int i = 0; i < nmaxHistograms; i++) { + if (kaonptedgevalues[i] <= v0.pt() && v0.pt() < kaonptedgevalues[i + 1]) { + pthistos::kaonPt[i]->Fill(v0.mK0Short()); + } + } + } } } } } } - } - // lambda analysis - if (lambdaAnalysis == true) { - // Filling the five lambda invariant mass plots for different cuts (which are taken from namespace), for full explanation see the first kzero cut filling in the MC process - rPtAnalysis.fill(HIST("hMassLambdaAll"), v0.mLambda()); - if (std::abs(v0.mK0Short() - mK0shPDG) > compv0masscut) { // lambda competitive v0 mass cut (cut out Kaons) - if (std::abs(posDaughterTrack.tpcNSigmaPr()) < nSigmaTPCProton && std::abs(negDaughterTrack.tpcNSigmaPi()) < nSigmaTPCPion) { // TPC PID on daughter pion and proton for Lambda - rPtAnalysis.fill(HIST("hNSigmaPosProtonFromLambda"), posDaughterTrack.tpcNSigmaPr(), posDaughterTrack.tpcInnerParam()); - rPtAnalysis.fill(HIST("hNSigmaNegPionFromLambda"), negDaughterTrack.tpcNSigmaPi(), negDaughterTrack.tpcInnerParam()); - // Implementing best lambda cuts - if (v0.v0cosPA() > lambdaSettingcosPA && v0.dcaV0daughters() < lambdaSettingdcav0dau && v0.v0radius() > lambdaSettingradius && std::abs(v0.dcapostopv()) > lambdaSettingdcapostopv && std::abs(v0.dcanegtopv()) > lambdaSettingdcanegtopv) { - rPtAnalysis.fill(HIST("hMassLambdaAllAfterCuts"), v0.mLambda()); - rPtAnalysis.fill(HIST("hLambdaEtaDaughters"), v0.negTrack_as().eta()); - rPtAnalysis.fill(HIST("hLambdaEtaDaughters"), v0.posTrack_as().eta()); - rPtAnalysis.fill(HIST("hArmenterosPodolanskiPlotLambda"), aValue, qValue); - rPtAnalysis.fill(HIST("hLambdaNegDaughterPt"), v0.negTrack_as().pt()); // Neg Daughter Pt - rPtAnalysis.fill(HIST("hLambdaPosDaughterPt"), v0.posTrack_as().pt()); // Pos Daughter Pt - for (int i = 0; i < nmaxHistograms; i++) { - if (lambdaptedgevalues[i] <= v0.pt() && v0.pt() < lambdaptedgevalues[i + 1]) { - pthistos::lambdaPt[i]->Fill(v0.mLambda()); + // lambda analysis + if (lambdaAnalysis == true) { + // Filling the five lambda invariant mass plots for different cuts (which are taken from namespace), for full explanation see the first kzero cut filling in the MC process + rPtAnalysis.fill(HIST("hMassLambdaAll"), v0.mLambda()); + if (std::abs(v0.mK0Short() - mK0shPDG) > compv0masscut) { // lambda competitive v0 mass cut (cut out Kaons) + if (std::abs(posDaughterTrack.tpcNSigmaPr()) < nSigmaTPCProton && std::abs(negDaughterTrack.tpcNSigmaPi()) < nSigmaTPCPion) { // TPC PID on daughter pion and proton for Lambda + rPtAnalysis.fill(HIST("hNSigmaPosProtonFromLambda"), posDaughterTrack.tpcNSigmaPr(), posDaughterTrack.tpcInnerParam()); + rPtAnalysis.fill(HIST("hNSigmaNegPionFromLambda"), negDaughterTrack.tpcNSigmaPi(), negDaughterTrack.tpcInnerParam()); + // Implementing best lambda cuts + if (v0.v0radius() < lambdamaxct) { + if (v0.v0cosPA() > lambdaSettingcosPA && v0.dcaV0daughters() < lambdaSettingdcav0dau && v0.v0radius() > lambdaSettingradius && std::abs(v0.dcapostopv()) > lambdaSettingdcapostopv && std::abs(v0.dcanegtopv()) > lambdaSettingdcanegtopv) { + rPtAnalysis.fill(HIST("hMassLambdaAllAfterCuts"), v0.mLambda()); + rPtAnalysis.fill(HIST("hLambdaEtaDaughters"), v0.negTrack_as().eta()); + rPtAnalysis.fill(HIST("hLambdaEtaDaughters"), v0.posTrack_as().eta()); + rPtAnalysis.fill(HIST("hArmenterosPodolanskiPlotLambda"), aValue, qValue); + rPtAnalysis.fill(HIST("hLambdaNegDaughterPt"), v0.negTrack_as().pt()); // Neg Daughter Pt + rPtAnalysis.fill(HIST("hLambdaPosDaughterPt"), v0.posTrack_as().pt()); // Pos Daughter Pt + for (int i = 0; i < nmaxHistograms; i++) { + if (lambdaptedgevalues[i] <= v0.pt() && v0.pt() < lambdaptedgevalues[i + 1]) { + pthistos::lambdaPt[i]->Fill(v0.mLambda()); + } + } } } } } } - } - // anti-lambda analysis - if (antiLambdaAnalysis == true) { - // Filling the five Antilambda invariant mass plots for different cuts (which are taken from namespace), for full explanation see the first kzero cut filling in the MC process - rPtAnalysis.fill(HIST("hMassAntilambdaAll"), v0.mAntiLambda()); - if (std::abs(v0.mK0Short() - mK0shPDG) > compv0masscut) { // antilambda competitive v0 mass cut (cut out Kaons) - if (std::abs(negDaughterTrack.tpcNSigmaPr()) < nSigmaTPCProton && std::abs(posDaughterTrack.tpcNSigmaPi()) < nSigmaTPCPion) { // TPC PID on daughter pion and proton for AntiLambda - rPtAnalysis.fill(HIST("hNSigmaPosPionFromAntilambda"), posDaughterTrack.tpcNSigmaPi(), posDaughterTrack.tpcInnerParam()); - rPtAnalysis.fill(HIST("hNSigmaNegProtonFromAntilambda"), negDaughterTrack.tpcNSigmaPr(), negDaughterTrack.tpcInnerParam()); - // implementing best antilambda cuts - if (v0.v0cosPA() > antilambdaSettingcosPA && v0.dcaV0daughters() < antilambdaSettingdcav0dau && v0.v0radius() > antilambdaSettingradius && std::abs(v0.dcapostopv()) > antilambdaSettingdcapostopv && std::abs(v0.dcanegtopv()) > antilambdaSettingdcanegtopv) { - rPtAnalysis.fill(HIST("hMassAntilambdaAllAfterCuts"), v0.mAntiLambda()); - rPtAnalysis.fill(HIST("hAntiLambdaEtaDaughters"), v0.negTrack_as().eta()); - rPtAnalysis.fill(HIST("hAntiLambdaEtaDaughters"), v0.posTrack_as().eta()); - rPtAnalysis.fill(HIST("hArmenterosPodolanskiPlotAntiLambda"), aValue, qValue); - rPtAnalysis.fill(HIST("hAntiLambdaNegDaughterPt"), v0.negTrack_as().pt()); // Neg Daughter Pt - rPtAnalysis.fill(HIST("hAntiLambdaPosDaughterPt"), v0.posTrack_as().pt()); // Pos Daughter Pt - for (int i = 0; i < nmaxHistograms; i++) { - if (lambdaptedgevalues[i] <= v0.pt() && v0.pt() < lambdaptedgevalues[i + 1]) { - pthistos::antilambdaPt[i]->Fill(v0.mAntiLambda()); + // anti-lambda analysis + if (antiLambdaAnalysis == true) { + // Filling the five Antilambda invariant mass plots for different cuts (which are taken from namespace), for full explanation see the first kzero cut filling in the MC process + rPtAnalysis.fill(HIST("hMassAntilambdaAll"), v0.mAntiLambda()); + if (std::abs(v0.mK0Short() - mK0shPDG) > compv0masscut) { // antilambda competitive v0 mass cut (cut out Kaons) + if (std::abs(negDaughterTrack.tpcNSigmaPr()) < nSigmaTPCProton && std::abs(posDaughterTrack.tpcNSigmaPi()) < nSigmaTPCPion) { // TPC PID on daughter pion and proton for AntiLambda + rPtAnalysis.fill(HIST("hNSigmaPosPionFromAntilambda"), posDaughterTrack.tpcNSigmaPi(), posDaughterTrack.tpcInnerParam()); + rPtAnalysis.fill(HIST("hNSigmaNegProtonFromAntilambda"), negDaughterTrack.tpcNSigmaPr(), negDaughterTrack.tpcInnerParam()); + // implementing best antilambda cuts + if (v0.v0radius() < antilambdamaxct) { + if (v0.v0cosPA() > antilambdaSettingcosPA && v0.dcaV0daughters() < antilambdaSettingdcav0dau && v0.v0radius() > antilambdaSettingradius && std::abs(v0.dcapostopv()) > antilambdaSettingdcapostopv && std::abs(v0.dcanegtopv()) > antilambdaSettingdcanegtopv) { + rPtAnalysis.fill(HIST("hMassAntilambdaAllAfterCuts"), v0.mAntiLambda()); + rPtAnalysis.fill(HIST("hAntiLambdaEtaDaughters"), v0.negTrack_as().eta()); + rPtAnalysis.fill(HIST("hAntiLambdaEtaDaughters"), v0.posTrack_as().eta()); + rPtAnalysis.fill(HIST("hArmenterosPodolanskiPlotAntiLambda"), aValue, qValue); + rPtAnalysis.fill(HIST("hAntiLambdaNegDaughterPt"), v0.negTrack_as().pt()); // Neg Daughter Pt + rPtAnalysis.fill(HIST("hAntiLambdaPosDaughterPt"), v0.posTrack_as().pt()); // Pos Daughter Pt + for (int i = 0; i < nmaxHistograms; i++) { + if (lambdaptedgevalues[i] <= v0.pt() && v0.pt() < lambdaptedgevalues[i + 1]) { + pthistos::antilambdaPt[i]->Fill(v0.mAntiLambda()); + } + } } } } From 2ebc876b6881ec32b8ca7932188c5f4383ebf8e0 Mon Sep 17 00:00:00 2001 From: altsybee Date: Mon, 30 Jun 2025 16:06:55 +0200 Subject: [PATCH 271/871] [DPG] Update timeDependentQa.cxx - add mult distributions vs time (#11838) --- DPG/Tasks/AOTEvent/timeDependentQa.cxx | 52 ++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/DPG/Tasks/AOTEvent/timeDependentQa.cxx b/DPG/Tasks/AOTEvent/timeDependentQa.cxx index e742ee040fd..41f9748e5f3 100644 --- a/DPG/Tasks/AOTEvent/timeDependentQa.cxx +++ b/DPG/Tasks/AOTEvent/timeDependentQa.cxx @@ -54,6 +54,7 @@ const AxisSpec axisSparseDcaZ{100, -1., 1., "DCA_{z}, cm"}; struct TimeDependentQaTask { Configurable confTimeBinWidthInSec{"TimeBinWidthInSec", 0.5, "Width of time bins in seconds"}; // o2-linter: disable=name/configurable (temporary fix) Configurable confTimeWiderBinFactor{"TimeWideBinFactor", 4, "Factor for wider time bins for some 2D histograms"}; // o2-linter: disable=name/configurable (temporary fix) + Configurable confTimeMuchWiderBinFactor{"confTimeMuchWiderBinFactor", 20, "Factor for even wider time bins for some 2D histograms"}; // o2-linter: disable=name/configurable (temporary fix) Configurable confTakeVerticesWithUPCsettings{"ConsiderVerticesWithUPCsettings", 0, "Take vertices: 0 - all , 1 - only without UPC settings, 2 - only with UPC settings"}; // o2-linter: disable=name/configurable (temporary fix) Configurable confFlagFillPhiVsTimeHist{"FlagFillPhiVsTimeHist", 2, "0 - don't fill , 1 - fill only for global/7cls/TRD/TOF tracks, 2 - fill also layer-by-layer"}; // o2-linter: disable=name/configurable (temporary fix) Configurable confFlagFillEtaPhiVsTimeHist{"FlagFillEtaPhiVsTimeHist", 0, "0 - don't fill , 1 - fill"}; // o2-linter: disable=name/configurable (temporary fix) @@ -61,6 +62,13 @@ struct TimeDependentQaTask { Configurable confFlagCheckMshape{"FlagCheckMshape", 0, "0 - don't check , 1 - check"}; // o2-linter: disable=name/configurable (temporary fix) Configurable confFlagCheckQoverPtHist{"FlagCheckQoverPtHist", 1, "0 - don't check , 1 - check"}; // o2-linter: disable=name/configurable (temporary fix) + // for O-O and Ne-Ne run + Configurable confIncludeMultDistrVsTimeHistos{"confIncludeMultDistrVsTimeHistos", 0, ""}; // o2-linter: disable=name/configurable (temporary fix) + Configurable confMaxNtracksForTimeDepDistributions{"confMaxNtracksForTimeDepDistributions", 800, ""}; // o2-linter: disable=name/configurable (temporary fix) + Configurable confMaxZNACenergyForTimeDepDistributions{"confMaxZNACenergyForTimeDepDistributions", 80, ""}; // o2-linter: disable=name/configurable (temporary fix) + Configurable confMaxT0ACamplForTimeDepDistributions{"confMaxT0ACamplForTimeDepDistributions", 25000, ""}; // o2-linter: disable=name/configurable (temporary fix) + Configurable confMaxV0AamplForTimeDepDistributions{"confMaxV0AamplForTimeDepDistributions", 40000, ""}; // o2-linter: disable=name/configurable (temporary fix) + enum EvSelBitsToMonitor { enCollisionsAll = 0, enIsTriggerTVX, @@ -181,10 +189,12 @@ struct TimeDependentQaTask { maxSec = ceil(tsEOR / 1000.); int nTimeBins = static_cast((maxSec - minSec) / confTimeBinWidthInSec); int nTimeWideBins = static_cast((maxSec - minSec) / confTimeBinWidthInSec / confTimeWiderBinFactor); + int nTimeVeryWideBins = static_cast((maxSec - minSec) / confTimeBinWidthInSec / confTimeMuchWiderBinFactor); double timeInterval = nTimeBins * confTimeBinWidthInSec; const AxisSpec axisSeconds{nTimeBins, 0, timeInterval, "seconds"}; const AxisSpec axisSecondsWideBins{nTimeWideBins, 0, timeInterval, "seconds"}; + const AxisSpec axisSecondsVeryWideBins{nTimeVeryWideBins, 0, timeInterval, "seconds"}; histos.add("hSecondsBCsTVX", "", kTH1D, {axisSeconds}); histos.add("hSecondsBCsTVXandTFborderCuts", "", kTH1D, {axisSeconds}); @@ -208,6 +218,22 @@ struct TimeDependentQaTask { histos.add("hSecondsUPCverticesBeforeSel8", "", kTH2F, {axisSeconds, {2, -0.5, 1.5, "Is vertex with UPC settings after |vZ|<10 cut"}}); histos.add("hSecondsUPCvertices", "", kTH2F, {axisSeconds, {2, -0.5, 1.5, "Is vertex with UPC settings after |vZ|<10 and sel8 cuts"}}); + // shapes of distributions (added for the O-O run monitoring) + if (confIncludeMultDistrVsTimeHistos) { + int maxNtracks = confMaxNtracksForTimeDepDistributions; + float maxZNACenergyForTimeDepDistributions = confMaxZNACenergyForTimeDepDistributions; + float maxT0ACamplForTimeDepDistributions = confMaxT0ACamplForTimeDepDistributions; + float maxV0AamplForTimeDepDistributions = confMaxV0AamplForTimeDepDistributions; + histos.add("multDistributions/hSecondsDistrPVtracks", "", kTH2D, {axisSecondsVeryWideBins, {maxNtracks, -0.5, maxNtracks - 0.5, "n PV tracks"}}); + histos.add("multDistributions/hSecondsDistrZNA", "", kTH2D, {axisSecondsVeryWideBins, {320, 0, maxZNACenergyForTimeDepDistributions, "ZNA ampl"}}); + histos.add("multDistributions/hSecondsDistrZNC", "", kTH2D, {axisSecondsVeryWideBins, {320, 0, maxZNACenergyForTimeDepDistributions, "ZNC ampl"}}); + histos.add("multDistributions/hSecondsDistrZNACdiff", "", kTH2D, {axisSecondsVeryWideBins, {600, -maxZNACenergyForTimeDepDistributions, maxZNACenergyForTimeDepDistributions, "ZN A-C diff"}}); + histos.add("multDistributions/hSecondsDistrZNACdiffNorm", "", kTH2D, {axisSecondsVeryWideBins, {200, -1., 1., "ZN A-C diff"}}); + histos.add("multDistributions/hSecondsDistrT0A", "", kTH2D, {axisSecondsVeryWideBins, {250, 0, maxT0ACamplForTimeDepDistributions, "T0A ampl"}}); + histos.add("multDistributions/hSecondsDistrT0C", "", kTH2D, {axisSecondsVeryWideBins, {250, 0, maxT0ACamplForTimeDepDistributions, "T0C ampl"}}); + histos.add("multDistributions/hSecondsDistrV0A", "", kTH2D, {axisSecondsVeryWideBins, {400, 0, maxV0AamplForTimeDepDistributions, "V0A ampl"}}); + } + // ### QA event selection bits int nEvSelBits = enNumEvSelBits; histos.add("hSecondsEventSelBits", "", kTH2F, {axisSecondsWideBins, {nEvSelBits, -0.5, nEvSelBits - 0.5, "Monitoring of event selection bits"}}); @@ -534,6 +560,7 @@ struct TimeDependentQaTask { // ##### track loop auto tracksGrouped = tracks.sliceBy(perCollision, col.globalIndex()); + int nPVtracks = 0; for (const auto& track : tracksGrouped) { // if (!track.hasTPC() || !track.hasITS()) // continue; @@ -593,6 +620,8 @@ struct TimeDependentQaTask { histos.fill(HIST("PVcontrib/hSecondsNumClsIts"), secFromSOR, track.itsNCls()); histos.fill(HIST("PVcontrib/hSeconds2DNumClsIts"), secFromSOR, track.itsNCls()); histos.fill(HIST("PVcontrib/hSecondsChi2NClIts"), secFromSOR, track.itsChi2NCl()); + + nPVtracks++; } // ### global tracks @@ -728,6 +757,29 @@ struct TimeDependentQaTask { histos.fill(HIST("hSecondsITSglobalVsEtaPhi"), secFromSOR, track.eta(), track.phi()); } } + } // end of track loop + + // fill mult distributions vs time + if (confIncludeMultDistrVsTimeHistos) { + histos.fill(HIST("multDistributions/hSecondsDistrPVtracks"), secFromSOR, nPVtracks); + + // ZNA,C + // float multZNA = bc.has_zdc() ? bc.zdc().energyCommonZNA() : -999.f; + // float multZNC = bc.has_zdc() ? bc.zdc().energyCommonZNC() : -999.f; + histos.fill(HIST("multDistributions/hSecondsDistrZNA"), secFromSOR, col.multZNA()); + histos.fill(HIST("multDistributions/hSecondsDistrZNC"), secFromSOR, col.multZNC()); + float ZNdiff = col.multZNA() - col.multZNC(); + float ZNsum = col.multZNA() + col.multZNC(); + histos.fill(HIST("multDistributions/hSecondsDistrZNACdiff"), secFromSOR, ZNdiff); + if (ZNsum > 0) + histos.fill(HIST("multDistributions/hSecondsDistrZNACdiffNorm"), secFromSOR, ZNdiff / ZNsum); + + // FT0A,C, V0A + // float multT0A = bc.has_ft0() ? bc.ft0().sumAmpA() : -999.f; + // float multT0C = bc.has_ft0() ? fbcundBC.ft0().sumAmpC() : -999.f; + histos.fill(HIST("multDistributions/hSecondsDistrT0A"), secFromSOR, col.multFT0A()); + histos.fill(HIST("multDistributions/hSecondsDistrT0C"), secFromSOR, col.multFT0C()); + histos.fill(HIST("multDistributions/hSecondsDistrV0A"), secFromSOR, col.multFV0A()); } } } // end of collision loop From e63a9189b13b7d7b65a50360359018704a49755e Mon Sep 17 00:00:00 2001 From: Lucia Anna Tarasovicova Date: Mon, 30 Jun 2025 16:46:24 +0200 Subject: [PATCH 272/871] [PWGLF] change in hStrangeCorrelation.cxx (#11762) Co-authored-by: Lucia Anna Tarasovicova Co-authored-by: ddobrigk Co-authored-by: ALICE Action Bot --- PWGLF/DataModel/LFHStrangeCorrelationTables.h | 9 +- .../Tasks/Strangeness/hStrangeCorrelation.cxx | 245 +++++++++++++++--- 2 files changed, 211 insertions(+), 43 deletions(-) diff --git a/PWGLF/DataModel/LFHStrangeCorrelationTables.h b/PWGLF/DataModel/LFHStrangeCorrelationTables.h index 62b50667263..cbeedbdb66c 100644 --- a/PWGLF/DataModel/LFHStrangeCorrelationTables.h +++ b/PWGLF/DataModel/LFHStrangeCorrelationTables.h @@ -22,10 +22,15 @@ #ifndef PWGLF_DATAMODEL_LFHSTRANGECORRELATIONTABLES_H_ #define PWGLF_DATAMODEL_LFHSTRANGECORRELATIONTABLES_H_ -#include -#include "Framework/AnalysisDataModel.h" +/// this data model uses the LF one, add here +#include "PWGLF/DataModel/LFStrangenessTables.h" + #include "Common/Core/RecoDecay.h" + #include "CommonConstants/PhysicsConstants.h" +#include "Framework/AnalysisDataModel.h" + +#include // Simple checker #define bitcheck(var, nbit) ((var) & (1 << (nbit))) diff --git a/PWGLF/Tasks/Strangeness/hStrangeCorrelation.cxx b/PWGLF/Tasks/Strangeness/hStrangeCorrelation.cxx index f9952efca40..64e21a08976 100644 --- a/PWGLF/Tasks/Strangeness/hStrangeCorrelation.cxx +++ b/PWGLF/Tasks/Strangeness/hStrangeCorrelation.cxx @@ -21,25 +21,28 @@ /// \author David Dobrigkeit Chinellato (david.dobrigkeit.chinellato@cern.ch) /// \author Zhongbao Yin (Zhong-Bao.Yin@cern.ch) -#include -#include -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "PWGLF/DataModel/LFStrangenessTables.h" #include "PWGLF/DataModel/LFHStrangeCorrelationTables.h" + +#include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "EventFiltering/Zorro.h" +#include "EventFiltering/ZorroSummary.h" + +#include "CCDB/BasicCCDBManager.h" +#include "DataFormatsParameters/GRPMagField.h" #include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisTask.h" #include "Framework/O2DatabasePDGPlugin.h" -#include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/Centrality.h" #include "Framework/StaticFor.h" -#include "CCDB/BasicCCDBManager.h" +#include "Framework/runDataProcessing.h" + #include -#include "EventFiltering/Zorro.h" -#include "EventFiltering/ZorroSummary.h" +#include +#include using namespace o2; using namespace o2::constants::math; @@ -89,6 +92,7 @@ struct HStrangeCorrelation { Configurable doAutocorrelationRejection{"doAutocorrelationRejection", true, "reject pairs where trigger Id is the same as daughter particle Id"}; Configurable doMixingQAandEventQA{"doMixingQAandEventQA", true, "if true, add EvnetQA and MixingQA hist to histos"}; Configurable doITSClustersQA{"doITSClustersQA", true, "if true, add ITSCluster hist to histos"}; + Configurable doDeltaPhiStarCheck{"doDeltaPhiStarCheck", false, "if true, create and fill delta phi star histograms"}; Configurable triggerBinToSelect{"triggerBinToSelect", 0, "trigger bin to select on if processSelectEventWithTrigger enabled"}; Configurable triggerParticleCharge{"triggerParticleCharge", 0, "For checks, if 0 all charged tracks, if -1 only neg., if 1 only positive"}; @@ -511,7 +515,23 @@ struct HStrangeCorrelation { return false; return true; } - void fillCorrelationsV0(aod::TriggerTracks const& triggers, aod::AssocV0s const& assocs, bool mixing, float pvx, float pvy, float pvz, float mult) + double calculateAverageDeltaPhiStar(double* trigg, double* assoc, double B) + { + double dPhiStar = 0; + double dPhiStarMean = 0; + + double dPhi = assoc[0] - trigg[0]; + double phaseProton = (-0.3 * B * assoc[2]) / (2 * assoc[1]); + double phaseTrack = (-0.3 * B * trigg[2]) / (2 * trigg[1]); + + for (double r = 0.8; r <= 2.5; r += 0.05) { + dPhiStar = dPhi + std::asin(phaseProton * r) - std::asin(phaseTrack * r); + dPhiStarMean += (dPhiStar / 34); + } + + return dPhiStarMean; + } + void fillCorrelationsV0(aod::TriggerTracks const& triggers, aod::AssocV0s const& assocs, bool mixing, float pvx, float pvy, float pvz, float mult, double bField) { for (auto const& triggerTrack : triggers) { if (doTriggPhysicalPrimary && !triggerTrack.mcPhysicalPrimary()) @@ -532,6 +552,9 @@ struct HStrangeCorrelation { histos.fill(HIST("sameEvent/TriggerParticlesV0"), trigg.pt(), mult, weight); } + double triggSign = trigg.sign(); + double triggForDeltaPhiStar[] = {trigg.phi(), trigg.pt(), triggSign}; + for (auto const& assocCandidate : assocs) { auto assoc = assocCandidate.v0Core_as(); @@ -585,9 +608,25 @@ struct HStrangeCorrelation { float etaWeight = 1; if (systCuts.doOnTheFlyFlattening) { float preWeight = 1 - std::abs(deltaeta) / 1.6; - etaWeight = preWeight != 0 ? 1.0f / preWeight : 0.0f; + etaWeight = preWeight != 0 ? 1.0f / preWeight : 1.0f; } + double phiProton = postrack.phi(); // in Case of K0, both are pions, but the one in proton tagged is the positive one + double phiPion = negtrack.phi(); + double etaProton = postrack.eta(); + double etaPion = negtrack.eta(); + double ptProton = postrack.pt(); + double ptPion = negtrack.pt(); + double signProton = postrack.sign(); + if (assocCandidate.compatible(2, systCuts.dEdxCompatibility)) { + phiProton = negtrack.phi(); + etaProton = negtrack.eta(); + ptProton = negtrack.pt(); + signProton = negtrack.sign(); + } + double assocForDeltaPhiStar[] = {phiProton, ptProton, signProton}; + double assocForDeltaPhiStarPion[] = {phiPion, ptPion, -1}; + static_for<0, 2>([&](auto i) { constexpr int Index = i.value; float efficiency = 1.0f; @@ -604,8 +643,24 @@ struct HStrangeCorrelation { float weight = (applyEfficiencyCorrection || applyEfficiencyForTrigger) ? 1. / efficiency : 1.0f; weight = weight * etaWeight; if (TESTBIT(doCorrelation, Index) && (!applyEfficiencyCorrection || efficiency != 0) && (doPPAnalysis || (TESTBIT(selMap, Index) && TESTBIT(selMap, Index + 3)))) { - if (assocCandidate.compatible(Index, systCuts.dEdxCompatibility) && (!doMCassociation || assocCandidate.mcTrue(Index)) && (!doAssocPhysicalPrimary || assocCandidate.mcPhysicalPrimary()) && !mixing && -massWindowConfigurations.maxBgNSigma < assocCandidate.invMassNSigma(Index) && assocCandidate.invMassNSigma(Index) < -massWindowConfigurations.minBgNSigma) + if (assocCandidate.compatible(Index, systCuts.dEdxCompatibility) && (!doMCassociation || assocCandidate.mcTrue(Index)) && (!doAssocPhysicalPrimary || assocCandidate.mcPhysicalPrimary()) && !mixing && -massWindowConfigurations.maxBgNSigma < assocCandidate.invMassNSigma(Index) && assocCandidate.invMassNSigma(Index) < -massWindowConfigurations.minBgNSigma) { histos.fill(HIST("sameEvent/LeftBg/") + HIST(kV0names[Index]), deltaphi, deltaeta, ptassoc, pttrigger, pvz, mult, weight); + if (doDeltaPhiStarCheck) { + double deltaPhiStar = calculateAverageDeltaPhiStar(triggForDeltaPhiStar, assocForDeltaPhiStar, bField); + double deltaPhiStarPion = calculateAverageDeltaPhiStar(triggForDeltaPhiStar, assocForDeltaPhiStarPion, bField); + if ((Index == 0 && triggSign > 0) || (Index == 1 && triggSign > 0) || (Index == 2 && triggSign < 0)) { + histos.fill(HIST("sameEvent/LeftBg/") + HIST(kV0names[Index]) + HIST("DeltaPhiStar"), deltaPhiStar, trigg.eta() - etaProton, 0.5); + if (Index == 0) { + histos.fill(HIST("sameEvent/LeftBg/") + HIST(kV0names[Index]) + HIST("DeltaPhiStar"), deltaPhiStarPion, trigg.eta() - etaPion, -0.5); + } + } else { + histos.fill(HIST("sameEvent/LeftBg/") + HIST(kV0names[Index]) + HIST("DeltaPhiStar"), deltaPhiStar, trigg.eta() - etaProton, -0.5); + if (Index == 0) { + histos.fill(HIST("sameEvent/LeftBg/") + HIST(kV0names[Index]) + HIST("DeltaPhiStar"), deltaPhiStarPion, trigg.eta() - etaPion, 0.5); + } + } + } + } if (assocCandidate.compatible(Index, systCuts.dEdxCompatibility) && (!doMCassociation || assocCandidate.mcTrue(Index)) && (!doAssocPhysicalPrimary || assocCandidate.mcPhysicalPrimary()) && !mixing && -massWindowConfigurations.maxPeakNSigma < assocCandidate.invMassNSigma(Index) && assocCandidate.invMassNSigma(Index) < +massWindowConfigurations.maxPeakNSigma) { histos.fill(HIST("sameEvent/Signal/") + HIST(kV0names[Index]), deltaphi, deltaeta, ptassoc, pttrigger, pvz, mult, weight); if (std::abs(deltaphi) < 0.8 && doITSClustersQA) { @@ -616,9 +671,40 @@ struct HStrangeCorrelation { histos.fill(HIST("hITSClusters") + HIST(kV0names[Index]) + HIST("NegativeDaughterTransverse"), ptassoc, negtrack.itsNCls(), assoc.v0radius()); histos.fill(HIST("hITSClusters") + HIST(kV0names[Index]) + HIST("PositiveDaughterTransverse"), ptassoc, postrack.itsNCls(), assoc.v0radius()); } + if (doDeltaPhiStarCheck) { + double deltaPhiStar = calculateAverageDeltaPhiStar(triggForDeltaPhiStar, assocForDeltaPhiStar, bField); + double deltaPhiStarPion = calculateAverageDeltaPhiStar(triggForDeltaPhiStar, assocForDeltaPhiStarPion, bField); + if ((Index == 0 && triggSign > 0) || (Index == 1 && triggSign > 0) || (Index == 2 && triggSign < 0)) { + histos.fill(HIST("sameEvent/Signal/") + HIST(kV0names[Index]) + HIST("DeltaPhiStar"), deltaPhiStar, trigg.eta() - etaProton, 0.5); + if (Index == 0) { + histos.fill(HIST("sameEvent/Signal/") + HIST(kV0names[Index]) + HIST("DeltaPhiStar"), deltaPhiStarPion, trigg.eta() - etaPion, -0.5); + } + } else { + histos.fill(HIST("sameEvent/Signal/") + HIST(kV0names[Index]) + HIST("DeltaPhiStar"), deltaPhiStar, trigg.eta() - etaProton, -0.5); + if (Index == 0) { + histos.fill(HIST("sameEvent/Signal/") + HIST(kV0names[Index]) + HIST("DeltaPhiStar"), deltaPhiStarPion, trigg.eta() - etaPion, 0.5); + } + } + } } - if (assocCandidate.compatible(Index, systCuts.dEdxCompatibility) && (!doMCassociation || assocCandidate.mcTrue(Index)) && (!doAssocPhysicalPrimary || assocCandidate.mcPhysicalPrimary()) && !mixing && +massWindowConfigurations.minBgNSigma < assocCandidate.invMassNSigma(Index) && assocCandidate.invMassNSigma(Index) < +massWindowConfigurations.maxBgNSigma) + if (assocCandidate.compatible(Index, systCuts.dEdxCompatibility) && (!doMCassociation || assocCandidate.mcTrue(Index)) && (!doAssocPhysicalPrimary || assocCandidate.mcPhysicalPrimary()) && !mixing && +massWindowConfigurations.minBgNSigma < assocCandidate.invMassNSigma(Index) && assocCandidate.invMassNSigma(Index) < +massWindowConfigurations.maxBgNSigma) { histos.fill(HIST("sameEvent/RightBg/") + HIST(kV0names[Index]), deltaphi, deltaeta, ptassoc, pttrigger, pvz, mult, weight); + if (doDeltaPhiStarCheck) { + double deltaPhiStar = calculateAverageDeltaPhiStar(triggForDeltaPhiStar, assocForDeltaPhiStar, bField); + double deltaPhiStarPion = calculateAverageDeltaPhiStar(triggForDeltaPhiStar, assocForDeltaPhiStarPion, bField); + if ((Index == 0 && triggSign > 0) || (Index == 1 && triggSign > 0) || (Index == 2 && triggSign < 0)) { + histos.fill(HIST("sameEvent/RightBg/") + HIST(kV0names[Index]) + HIST("DeltaPhiStar"), deltaPhiStar, trigg.eta() - etaProton, 0.5); + if (Index == 0) { + histos.fill(HIST("sameEvent/RightBg/") + HIST(kV0names[Index]) + HIST("DeltaPhiStar"), deltaPhiStarPion, trigg.eta() - etaPion, -0.5); + } + } else { + histos.fill(HIST("sameEvent/RightBg/") + HIST(kV0names[Index]) + HIST("DeltaPhiStar"), deltaPhiStar, trigg.eta() - etaProton, -0.5); + if (Index == 0) { + histos.fill(HIST("sameEvent/RightBg/") + HIST(kV0names[Index]) + HIST("DeltaPhiStar"), deltaPhiStarPion, trigg.eta() - etaPion, 0.5); + } + } + } + } if (assocCandidate.compatible(Index, systCuts.dEdxCompatibility) && (!doMCassociation || assocCandidate.mcTrue(Index)) && (!doAssocPhysicalPrimary || assocCandidate.mcPhysicalPrimary()) && mixing && -massWindowConfigurations.maxBgNSigma < assocCandidate.invMassNSigma(Index) && assocCandidate.invMassNSigma(Index) < -massWindowConfigurations.minBgNSigma) histos.fill(HIST("mixedEvent/LeftBg/") + HIST(kV0names[Index]), deltaphi, deltaeta, ptassoc, pttrigger, pvz, mult, weight); if (assocCandidate.compatible(Index, systCuts.dEdxCompatibility) && (!doMCassociation || assocCandidate.mcTrue(Index)) && (!doAssocPhysicalPrimary || assocCandidate.mcPhysicalPrimary()) && mixing && -massWindowConfigurations.maxPeakNSigma < assocCandidate.invMassNSigma(Index) && assocCandidate.invMassNSigma(Index) < +massWindowConfigurations.maxPeakNSigma) @@ -631,7 +717,7 @@ struct HStrangeCorrelation { } } - void fillCorrelationsCascade(aod::TriggerTracks const& triggers, aod::AssocCascades const& assocs, bool mixing, float pvx, float pvy, float pvz, float mult) + void fillCorrelationsCascade(aod::TriggerTracks const& triggers, aod::AssocCascades const& assocs, bool mixing, float pvx, float pvy, float pvz, float mult, double bField) { for (auto const& triggerTrack : triggers) { if (doTriggPhysicalPrimary && !triggerTrack.mcPhysicalPrimary()) @@ -651,6 +737,9 @@ struct HStrangeCorrelation { float weight = (applyEfficiencyForTrigger) ? 1. / efficiency : 1.0f; histos.fill(HIST("sameEvent/TriggerParticlesCascade"), trigg.pt(), mult, weight); } + double triggSign = trigg.sign(); + double triggForDeltaPhiStar[] = {trigg.phi(), trigg.pt(), triggSign}; + for (auto const& assocCandidate : assocs) { auto assoc = assocCandidate.cascData(); @@ -687,7 +776,17 @@ struct HStrangeCorrelation { continue; } } - + double phiProton = postrack.phi(); + double etaProton = postrack.eta(); + double ptProton = postrack.pt(); + double signProton = postrack.sign(); + if (assoc.sign() > 0) { + phiProton = negtrack.phi(); + etaProton = negtrack.eta(); + ptProton = negtrack.pt(); + signProton = negtrack.sign(); + } + double assocForDeltaPhiStar[] = {phiProton, ptProton, signProton}; //---] track quality check [--- if (postrack.tpcNClsCrossedRows() < systCuts.minTPCNCrossedRowsAssociated || negtrack.tpcNClsCrossedRows() < systCuts.minTPCNCrossedRowsAssociated || bachtrack.tpcNClsCrossedRows() < systCuts.minTPCNCrossedRowsAssociated) continue; @@ -714,7 +813,7 @@ struct HStrangeCorrelation { float etaWeight = 1; if (systCuts.doOnTheFlyFlattening) { float preWeight = 1 - std::abs(deltaeta) / 1.6; - etaWeight = preWeight != 0 ? 1.0f / preWeight : 0.0f; + etaWeight = preWeight != 0 ? 1.0f / preWeight : 1.0f; } static_for<0, 3>([&](auto i) { @@ -732,12 +831,36 @@ struct HStrangeCorrelation { float weight = (applyEfficiencyCorrection || applyEfficiencyForTrigger) ? 1. / efficiency : 1.0f; weight = weight * etaWeight; if (TESTBIT(doCorrelation, Index + 3) && (!applyEfficiencyCorrection || efficiency != 0) && (doPPAnalysis || (TESTBIT(CascselMap, Index) && TESTBIT(CascselMap, Index + 4) && TESTBIT(CascselMap, Index + 8) && TESTBIT(CascselMap, Index + 12)))) { - if (assocCandidate.compatible(Index, systCuts.dEdxCompatibility) && (!doMCassociation || assocCandidate.mcTrue(Index)) && (!doAssocPhysicalPrimary || assocCandidate.mcPhysicalPrimary()) && !mixing && -massWindowConfigurations.maxBgNSigma < assocCandidate.invMassNSigma(Index) && assocCandidate.invMassNSigma(Index) < -massWindowConfigurations.minBgNSigma) + if (assocCandidate.compatible(Index, systCuts.dEdxCompatibility) && (!doMCassociation || assocCandidate.mcTrue(Index)) && (!doAssocPhysicalPrimary || assocCandidate.mcPhysicalPrimary()) && !mixing && -massWindowConfigurations.maxBgNSigma < assocCandidate.invMassNSigma(Index) && assocCandidate.invMassNSigma(Index) < -massWindowConfigurations.minBgNSigma) { histos.fill(HIST("sameEvent/LeftBg/") + HIST(kCascadenames[Index]), deltaphi, deltaeta, ptassoc, pttrigger, pvz, mult, weight); - if (assocCandidate.compatible(Index, systCuts.dEdxCompatibility) && (!doMCassociation || assocCandidate.mcTrue(Index)) && (!doAssocPhysicalPrimary || assocCandidate.mcPhysicalPrimary()) && !mixing && -massWindowConfigurations.maxPeakNSigma < assocCandidate.invMassNSigma(Index) && assocCandidate.invMassNSigma(Index) < +massWindowConfigurations.maxPeakNSigma) + if (doDeltaPhiStarCheck) { + double deltaPhiStar = calculateAverageDeltaPhiStar(triggForDeltaPhiStar, assocForDeltaPhiStar, bField); + if ((Index == 0 && triggSign > 0) || (Index == 1 && triggSign < 0) || (Index == 2 && triggSign > 0) || (Index == 3 && triggSign < 0)) + histos.fill(HIST("sameEvent/LeftBg/") + HIST(kCascadenames[Index]) + HIST("DeltaPhiStar"), deltaPhiStar, trigg.eta() - etaProton, 0.5); + else + histos.fill(HIST("sameEvent/LeftBg/") + HIST(kCascadenames[Index]) + HIST("DeltaPhiStar"), deltaPhiStar, trigg.eta() - etaProton, -0.5); + } + } + if (assocCandidate.compatible(Index, systCuts.dEdxCompatibility) && (!doMCassociation || assocCandidate.mcTrue(Index)) && (!doAssocPhysicalPrimary || assocCandidate.mcPhysicalPrimary()) && !mixing && -massWindowConfigurations.maxPeakNSigma < assocCandidate.invMassNSigma(Index) && assocCandidate.invMassNSigma(Index) < +massWindowConfigurations.maxPeakNSigma) { histos.fill(HIST("sameEvent/Signal/") + HIST(kCascadenames[Index]), deltaphi, deltaeta, ptassoc, pttrigger, pvz, mult, weight); - if (assocCandidate.compatible(Index, systCuts.dEdxCompatibility) && (!doMCassociation || assocCandidate.mcTrue(Index)) && (!doAssocPhysicalPrimary || assocCandidate.mcPhysicalPrimary()) && !mixing && +massWindowConfigurations.minBgNSigma < assocCandidate.invMassNSigma(Index) && assocCandidate.invMassNSigma(Index) < +massWindowConfigurations.maxBgNSigma) + if (doDeltaPhiStarCheck) { + double deltaPhiStar = calculateAverageDeltaPhiStar(triggForDeltaPhiStar, assocForDeltaPhiStar, bField); + if ((Index == 0 && triggSign > 0) || (Index == 1 && triggSign < 0) || (Index == 2 && triggSign > 0) || (Index == 3 && triggSign < 0)) + histos.fill(HIST("sameEvent/Signal/") + HIST(kCascadenames[Index]) + HIST("DeltaPhiStar"), deltaPhiStar, trigg.eta() - etaProton, 0.5); + else + histos.fill(HIST("sameEvent/Signal/") + HIST(kCascadenames[Index]) + HIST("DeltaPhiStar"), deltaPhiStar, trigg.eta() - etaProton, -0.5); + } + } + if (assocCandidate.compatible(Index, systCuts.dEdxCompatibility) && (!doMCassociation || assocCandidate.mcTrue(Index)) && (!doAssocPhysicalPrimary || assocCandidate.mcPhysicalPrimary()) && !mixing && +massWindowConfigurations.minBgNSigma < assocCandidate.invMassNSigma(Index) && assocCandidate.invMassNSigma(Index) < +massWindowConfigurations.maxBgNSigma) { histos.fill(HIST("sameEvent/RightBg/") + HIST(kCascadenames[Index]), deltaphi, deltaeta, ptassoc, pttrigger, pvz, mult, weight); + if (doDeltaPhiStarCheck) { + double deltaPhiStar = calculateAverageDeltaPhiStar(triggForDeltaPhiStar, assocForDeltaPhiStar, bField); + if ((Index == 0 && triggSign > 0) || (Index == 1 && triggSign < 0) || (Index == 2 && triggSign > 0) || (Index == 3 && triggSign < 0)) + histos.fill(HIST("sameEvent/RightBg/") + HIST(kCascadenames[Index]) + HIST("DeltaPhiStar"), deltaPhiStar, trigg.eta() - etaProton, 0.5); + else + histos.fill(HIST("sameEvent/RightBg/") + HIST(kCascadenames[Index]) + HIST("DeltaPhiStar"), deltaPhiStar, trigg.eta() - etaProton, -0.5); + } + } if (assocCandidate.compatible(Index, systCuts.dEdxCompatibility) && (!doMCassociation || assocCandidate.mcTrue(Index)) && (!doAssocPhysicalPrimary || assocCandidate.mcPhysicalPrimary()) && mixing && -massWindowConfigurations.maxBgNSigma < assocCandidate.invMassNSigma(Index) && assocCandidate.invMassNSigma(Index) < -massWindowConfigurations.minBgNSigma) histos.fill(HIST("mixedEvent/LeftBg/") + HIST(kCascadenames[Index]), deltaphi, deltaeta, ptassoc, pttrigger, pvz, mult, weight); if (assocCandidate.compatible(Index, systCuts.dEdxCompatibility) && (!doMCassociation || assocCandidate.mcTrue(Index)) && (!doAssocPhysicalPrimary || assocCandidate.mcPhysicalPrimary()) && mixing && -massWindowConfigurations.maxPeakNSigma < assocCandidate.invMassNSigma(Index) && assocCandidate.invMassNSigma(Index) < +massWindowConfigurations.maxPeakNSigma) @@ -750,7 +873,7 @@ struct HStrangeCorrelation { } } template - void fillCorrelationsHadron(TTriggers const& triggers, THadrons const& assocs, bool mixing, float pvz, float mult) + void fillCorrelationsHadron(TTriggers const& triggers, THadrons const& assocs, bool mixing, float pvz, float mult, double bField) { for (auto const& triggerTrack : triggers) { @@ -774,6 +897,8 @@ struct HStrangeCorrelation { else histos.fill(HIST("sameEvent/TriggerParticlesHadron"), trigg.pt(), mult, weight); } + double triggSign = trigg.sign(); + double triggForDeltaPhiStar[] = {trigg.phi(), trigg.pt(), triggSign}; for (auto const& assocTrack : assocs) { auto assoc = assocTrack.template track_as(); @@ -798,10 +923,13 @@ struct HStrangeCorrelation { float ptassoc = assoc.pt(); float pttrigger = trigg.pt(); + double assocSign = assoc.sign(); + double assocForDeltaPhiStar[] = {assoc.phi(), assoc.pt(), assocSign}; + float etaWeight = 1.; if (systCuts.doOnTheFlyFlattening) { float preWeight = 1 - std::abs(deltaeta) / 1.6; - etaWeight = preWeight != 0 ? 1.0f / preWeight : 0.0f; + etaWeight = preWeight != 0 ? 1.0f / preWeight : 1.0f; } // skip if basic ranges not met @@ -827,11 +955,21 @@ struct HStrangeCorrelation { efficiency = 1; } float weight = (applyEfficiencyCorrection || applyEfficiencyForTrigger) ? 1. / efficiency : 1.0f; - + double deltaPhiStar = calculateAverageDeltaPhiStar(triggForDeltaPhiStar, assocForDeltaPhiStar, bField); if (!mixing) { if constexpr (requires { assocTrack.nSigmaTPCPi(); }) { histos.fill(HIST("sameEvent/Signal/Pion"), deltaphi, deltaeta, ptassoc, pttrigger, pvz, mult, weight * etaWeight); + if (triggSign == assocSign && doDeltaPhiStarCheck) { + histos.fill(HIST("sameEvent/Signal/Pion") + HIST("DeltaPhiStar"), deltaPhiStar, trigg.eta() - assoc.eta(), 0.5); + } else if (doDeltaPhiStarCheck) { + histos.fill(HIST("sameEvent/Signal/Pion") + HIST("DeltaPhiStar"), deltaPhiStar, trigg.eta() - assoc.eta(), -0.5); + } } else { + if (triggSign == assocSign && doDeltaPhiStarCheck) { + histos.fill(HIST("sameEvent/Signal/Hadron") + HIST("DeltaPhiStar"), deltaPhiStar, trigg.eta() - assoc.eta(), 0.5); + } else if (doDeltaPhiStarCheck) { + histos.fill(HIST("sameEvent/Signal/Hadron") + HIST("DeltaPhiStar"), deltaPhiStar, trigg.eta() - assoc.eta(), -0.5); + } histos.fill(HIST("sameEvent/Signal/Hadron"), deltaphi, deltaeta, ptassoc, pttrigger, pvz, mult, weight * etaWeight); } } else { @@ -1094,6 +1232,9 @@ struct HStrangeCorrelation { histos.add(fmt::format("h3d{}Spectrum", kParticlenames[i]).c_str(), fmt::format("h3d{}Spectrum", kParticlenames[i]).c_str(), kTH3F, {axisPtQA, axisMult, axisMassNSigma}); histos.add(fmt::format("h3d{}SpectrumY", kParticlenames[i]).c_str(), fmt::format("h3d{}SpectrumY", kParticlenames[i]).c_str(), kTH3F, {axisPtQA, axisMult, axisMassNSigma}); histos.add(fmt::format("sameEvent/Signal/{}", kParticlenames[i]).c_str(), "", kTHnF, {axisDeltaPhiNDim, axisDeltaEtaNDim, axisPtAssocNDim, axisPtTriggerNDim, axisVtxZNDim, axisMultNDim}); + if (doDeltaPhiStarCheck) { + histos.add(fmt::format("sameEvent/Signal/{}DeltaPhiStar", kParticlenames[i]).c_str(), "", kTH3F, {{100, -0.3, 0.3}, {50, -0.05, 0.05}, {2, -1, 1}}); // -1 oposite charge, 1 same charge + } if (i < 7) { hStrange = true; histos.add(fmt::format("h{}EtaVsPtVsPhiBg", kParticlenames[i]).c_str(), "", kTH3F, {axisPtQA, axisEta, axisPhi}); @@ -1298,6 +1439,20 @@ struct HStrangeCorrelation { return true; } + double getMagneticField(uint64_t timestamp) + { + static parameters::GRPMagField* grpo = nullptr; + if (grpo == nullptr) { + grpo = ccdb->getForTimeStamp("GLO/Config/GRPMagField", timestamp); + if (grpo == nullptr) { + LOGF(fatal, "GRP object not found for timestamp %llu", timestamp); + return 0; + } + LOGF(info, "Retrieved GRP for timestamp %llu with magnetic field of %d kG", timestamp, grpo->getNominalL3Field()); + } + + return 0.1 * (grpo->getNominalL3Field()); // 1 T = 10 kG + } // if this process function is enabled, it will be such that only events with trigger particles within a given // trigger pt bin are taken for the entire processing. This allows for the calculation of e.g. efficiencies // within an event class that has a trigger (which may differ with respect to other cases, to be checked) @@ -1343,8 +1498,10 @@ struct HStrangeCorrelation { return; } + auto bc = collision.bc_as(); + auto bField = getMagneticField(bc.timestamp()); + if (applyEfficiencyCorrection) { - auto bc = collision.bc_as(); initEfficiencyFromCCDB(bc); } @@ -1408,7 +1565,7 @@ struct HStrangeCorrelation { // ________________________________________________ // Do hadron - hadron correlations - fillCorrelationsHadron(triggerTracks, assocHadrons, false, collision.posZ(), collision.centFT0M()); + fillCorrelationsHadron(triggerTracks, assocHadrons, false, collision.posZ(), collision.centFT0M(), bField); } void processSameEventHV0s(soa::Join::iterator const& collision, @@ -1438,9 +1595,9 @@ struct HStrangeCorrelation { histos.fill(HIST("EventQA/hMultFT0vsTPC"), cent, collision.multNTracksPVeta1()); } // Do basic QA - + auto bc = collision.bc_as(); + auto bField = getMagneticField(bc.timestamp()); if (applyEfficiencyCorrection) { - auto bc = collision.bc_as(); initEfficiencyFromCCDB(bc); } TH2F* hEfficiencyV0[3]; @@ -1508,7 +1665,7 @@ struct HStrangeCorrelation { // ________________________________________________ // Do hadron - V0 correlations - fillCorrelationsV0(triggerTracks, associatedV0s, false, collision.posX(), collision.posY(), collision.posZ(), cent); + fillCorrelationsV0(triggerTracks, associatedV0s, false, collision.posX(), collision.posY(), collision.posZ(), cent, bField); } void processSameEventHCascades(soa::Join::iterator const& collision, @@ -1537,8 +1694,9 @@ struct HStrangeCorrelation { histos.fill(HIST("EventQA/hPvz"), collision.posZ()); } // Do basic QA + auto bc = collision.bc_as(); + auto bField = getMagneticField(bc.timestamp()); if (applyEfficiencyCorrection) { - auto bc = collision.bc_as(); initEfficiencyFromCCDB(bc); } TH2F* hEfficiencyCascade[4]; @@ -1612,7 +1770,7 @@ struct HStrangeCorrelation { // ________________________________________________ // Do hadron - cascade correlations - fillCorrelationsCascade(triggerTracks, associatedCascades, false, collision.posX(), collision.posY(), collision.posZ(), cent); + fillCorrelationsCascade(triggerTracks, associatedCascades, false, collision.posX(), collision.posY(), collision.posZ(), cent, bField); } void processSameEventHPions(soa::Join::iterator const& collision, soa::Join const& associatedPions, soa::Join const& triggerTracks, @@ -1623,9 +1781,10 @@ struct HStrangeCorrelation { if (triggerPresenceMap.size() > 0 && !TESTBIT(triggerPresenceMap[collision.globalIndex()], triggerBinToSelect)) { return; } + auto bc = collision.bc_as(); + auto bField = getMagneticField(bc.timestamp()); if (applyEfficiencyCorrection) { - auto bc = collision.bc_as(); initEfficiencyFromCCDB(bc); } @@ -1661,7 +1820,7 @@ struct HStrangeCorrelation { // ________________________________________________ // Do hadron - Pion correlations - fillCorrelationsHadron(triggerTracks, associatedPions, false, collision.posZ(), collision.centFT0M()); + fillCorrelationsHadron(triggerTracks, associatedPions, false, collision.posZ(), collision.centFT0M(), bField); } void processMixedEventHHadrons(soa::Join const& collisions, @@ -1669,9 +1828,10 @@ struct HStrangeCorrelation { TracksComplete const&, aod::BCsWithTimestamps const&) { for (auto const& [collision1, collision2] : soa::selfCombinations(colBinning, mixingParameter, -1, collisions, collisions)) { + auto bc = collision1.bc_as(); + auto bField = getMagneticField(bc.timestamp()); // ________________________________________________ if (applyEfficiencyCorrection) { - auto bc = collision1.bc_as(); initEfficiencyFromCCDB(bc); } // ________________________________________________ @@ -1703,7 +1863,7 @@ struct HStrangeCorrelation { auto slicedAssocHadrons = assocHadrons.sliceBy(collisionSliceHadrons, collision2.globalIndex()); // ________________________________________________ // Do hadron - hadron correlations - fillCorrelationsHadron(slicedTriggerTracks, slicedAssocHadrons, true, collision1.posZ(), collision1.centFT0M()); + fillCorrelationsHadron(slicedTriggerTracks, slicedAssocHadrons, true, collision1.posZ(), collision1.centFT0M(), bField); } } @@ -1717,9 +1877,10 @@ struct HStrangeCorrelation { for (auto const& [collision1, collision2] : soa::selfCombinations(colBinning, mixingParameter, -1, collisions, collisions)) { double cent1 = doPPAnalysis ? collision1.centFT0M() : collision1.centFT0C(); double cent2 = doPPAnalysis ? collision2.centFT0M() : collision2.centFT0C(); + auto bc = collision1.bc_as(); + auto bField = getMagneticField(bc.timestamp()); // ________________________________________________ if (applyEfficiencyCorrection) { - auto bc = collision1.bc_as(); initEfficiencyFromCCDB(bc); } // ________________________________________________ @@ -1751,7 +1912,7 @@ struct HStrangeCorrelation { auto slicedAssocV0s = associatedV0s.sliceBy(collisionSliceV0s, collision2.globalIndex()); // ________________________________________________ // Do hadron - V0 correlations - fillCorrelationsV0(slicedTriggerTracks, slicedAssocV0s, true, collision1.posX(), collision1.posY(), collision1.posZ(), cent1); + fillCorrelationsV0(slicedTriggerTracks, slicedAssocV0s, true, collision1.posX(), collision1.posY(), collision1.posZ(), cent1, bField); } } void processMixedEventHCascades(soa::Join const& collisions, @@ -1765,8 +1926,9 @@ struct HStrangeCorrelation { double cent1 = doPPAnalysis ? collision1.centFT0M() : collision1.centFT0C(); double cent2 = doPPAnalysis ? collision2.centFT0M() : collision2.centFT0C(); // ________________________________________________ + auto bc = collision1.bc_as(); + auto bField = getMagneticField(bc.timestamp()); if (applyEfficiencyCorrection) { - auto bc = collision1.bc_as(); initEfficiencyFromCCDB(bc); } // ________________________________________________ @@ -1797,7 +1959,7 @@ struct HStrangeCorrelation { auto slicedAssocCascades = associatedCascades.sliceBy(collisionSliceCascades, collision2.globalIndex()); // ________________________________________________ // Do hadron - cascade correlations - fillCorrelationsCascade(slicedTriggerTracks, slicedAssocCascades, true, collision1.posX(), collision1.posY(), collision1.posZ(), cent1); + fillCorrelationsCascade(slicedTriggerTracks, slicedAssocCascades, true, collision1.posX(), collision1.posY(), collision1.posZ(), cent1, bField); } } void processMixedEventHPions(soa::Join const& collisions, @@ -1805,9 +1967,10 @@ struct HStrangeCorrelation { TracksComplete const&, aod::BCsWithTimestamps const&) { for (auto const& [collision1, collision2] : soa::selfCombinations(colBinning, mixingParameter, -1, collisions, collisions)) { + auto bc = collision1.bc_as(); + auto bField = getMagneticField(bc.timestamp()); // ________________________________________________ if (applyEfficiencyCorrection) { - auto bc = collision1.bc_as(); initEfficiencyFromCCDB(bc); } // ________________________________________________ @@ -1839,7 +2002,7 @@ struct HStrangeCorrelation { auto slicedAssocPions = assocPions.sliceBy(collisionSliceHadrons, collision2.globalIndex()); // ________________________________________________ // Do hadron - cascade correlations - fillCorrelationsHadron(slicedTriggerTracks, slicedAssocPions, true, collision1.posZ(), collision1.centFT0M()); + fillCorrelationsHadron(slicedTriggerTracks, slicedAssocPions, true, collision1.posZ(), collision1.centFT0M(), bField); } } From 8397c10d9f422b98ec1e87d90063e3ca324b06e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aust=C4=97ja=20=20Jurgaityt=C4=97?= <119352645+ZeptoStarling@users.noreply.github.com> Date: Mon, 30 Jun 2025 19:43:54 +0200 Subject: [PATCH 273/871] [PWGCF] Fix naming and other bugs in producer task for Pb-Pb collisions (#11844) Co-authored-by: ALICE Action Bot --- PWGCF/FemtoDream/Tasks/CMakeLists.txt | 2 +- .../Tasks/femtoDreamCollisionMasker.cxx | 2 +- ...mtoDreamTripletTaskTrackTrackTrackPbPb.cxx | 32 ++++++++++--------- 3 files changed, 19 insertions(+), 17 deletions(-) diff --git a/PWGCF/FemtoDream/Tasks/CMakeLists.txt b/PWGCF/FemtoDream/Tasks/CMakeLists.txt index 4c8613e3d40..eefdde89e9e 100644 --- a/PWGCF/FemtoDream/Tasks/CMakeLists.txt +++ b/PWGCF/FemtoDream/Tasks/CMakeLists.txt @@ -19,7 +19,7 @@ o2physics_add_dpl_workflow(femtodream-triplet-track-track-track PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore COMPONENT_NAME Analysis) -o2physics_add_dpl_workflow(femtodream-triplet-track-track-track-pbpb +o2physics_add_dpl_workflow(femtodream-triplet-track-track-track-pb-pb SOURCES femtoDreamTripletTaskTrackTrackTrackPbPb.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore COMPONENT_NAME Analysis) diff --git a/PWGCF/FemtoDream/Tasks/femtoDreamCollisionMasker.cxx b/PWGCF/FemtoDream/Tasks/femtoDreamCollisionMasker.cxx index 1ca9d808073..fddbee16a88 100644 --- a/PWGCF/FemtoDream/Tasks/femtoDreamCollisionMasker.cxx +++ b/PWGCF/FemtoDream/Tasks/femtoDreamCollisionMasker.cxx @@ -244,7 +244,7 @@ struct femoDreamCollisionMasker { NegChildPIDTPCBits.at(CollisionMasks::kPartTwo).push_back(option.defaultValue.get()); } } - } else if (device.name.find("femto-dream-triplet-task-track-track-track") != std::string::npos) { + } else if ((device.name.find("femto-dream-triplet-task-track-track-track") != std::string::npos) || (device.name.find("femto-dream-triplet-task-track-track-track-pb-pb") != std::string::npos)) { LOG(info) << "Matched workflow: " << device.name; TaskFinder = CollisionMasks::kTrackTrackTrack; for (auto const& option : device.options) { diff --git a/PWGCF/FemtoDream/Tasks/femtoDreamTripletTaskTrackTrackTrackPbPb.cxx b/PWGCF/FemtoDream/Tasks/femtoDreamTripletTaskTrackTrackTrackPbPb.cxx index ddb9737d7d5..f0d69344160 100644 --- a/PWGCF/FemtoDream/Tasks/femtoDreamTripletTaskTrackTrackTrackPbPb.cxx +++ b/PWGCF/FemtoDream/Tasks/femtoDreamTripletTaskTrackTrackTrackPbPb.cxx @@ -9,7 +9,7 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -/// \file femtoDreamTripletTaskTrackTrackTrack.cxx +/// \file femtoDreamTripletTaskTrackTrackTrackPbPb.cxx /// \brief Tasks that reads the track tables and creates track triplets; only three identical particles can be used /// \author Laura Serksnyte, TU München, laura.serksnyte@tum.de @@ -40,7 +40,7 @@ using namespace o2::framework; using namespace o2::framework::expressions; using namespace o2::soa; -struct femtoDreamTripletTaskTrackTrackTrack { +struct femtoDreamTripletTaskTrackTrackTrackPbPb { SliceCache cache; Preslice perCol = aod::femtodreamparticle::fdCollisionId; @@ -51,7 +51,7 @@ struct femtoDreamTripletTaskTrackTrackTrack { using FilteredFDCollisions = soa::Filtered; using FilteredFDCollision = FilteredFDCollisions::iterator; - using MaskedCollisions = soa::Join; + using MaskedCollisions = soa::Filtered>; using MaskedCollision = MaskedCollisions::iterator; aod::femtodreamcollision::BitMaskType MaskBit = -1; float mMassOne = -999, mMassTwo = -999, mMassThree = -999; @@ -163,7 +163,7 @@ struct femtoDreamTripletTaskTrackTrackTrack { ThreeBodyQARegistry.add("TrackMC_QA/hMazzachi", ";gen;(reco-gen)/gen", kTH2F, {{100, ConfMinpT, ConfMaxpT}, {300, -1, 1}}); } ThreeBodyQARegistry.add("TripletTaskQA/hCentrality", ";Centrality; Q3", kTH2F, {{100, 0, 100}, ConfQ3Bins}); - ThreeBodyQARegistry.add("TripletTaskQA/hCentralityME", ";Centrality;", kTH1F, {{100, 0.0, 100.0}}); + ThreeBodyQARegistry.add("TripletTaskQA/hCentralityME", ";Centrality;Entries", kTH1F, {{100, 0.0, 100.0}}); sameEventCont.init(&resultRegistry, ConfQ3Bins, ConfMultBins, ConfIsMC); mixedEventCont.init(&resultRegistry, ConfQ3Bins, ConfMultBins, ConfIsMC); @@ -185,7 +185,7 @@ struct femtoDreamTripletTaskTrackTrackTrack { int index = 0; auto& workflows = context.services().get(); for (DeviceSpec const& device : workflows.devices) { - if (device.name.find("femto-dream-triplet-task-track-track-track") != std::string::npos) { + if (device.name.find("femto-dream-triplet-task-track-track-track-pb-pb") != std::string::npos) { if (containsNameValuePair(device.options, "ConfCutPart", ConfCutPart.value) && containsNameValuePair(device.options, "ConfTPCPIDBit", ConfTPCPIDBit.value) && containsNameValuePair(device.options, "ConfTPCTOFPIDBit", ConfTPCTOFPIDBit.value) && @@ -295,7 +295,7 @@ struct femtoDreamTripletTaskTrackTrackTrack { } doSameEvent(thegroupSelectedParts, parts, col.magField(), col.multNtr(), col.multV0M()); } - PROCESS_SWITCH(femtoDreamTripletTaskTrackTrackTrack, processSameEvent, "Enable processing same event", true); + PROCESS_SWITCH(femtoDreamTripletTaskTrackTrackTrackPbPb, processSameEvent, "Enable processing same event", true); /// process function to call doSameEvent with Data which has a mask for containing particles or not /// \param col subscribe to the collision table (Data) @@ -312,7 +312,7 @@ struct femtoDreamTripletTaskTrackTrackTrack { } doSameEvent(thegroupSelectedParts, parts, col.magField(), col.multNtr(), col.multV0M()); } - PROCESS_SWITCH(femtoDreamTripletTaskTrackTrackTrack, processSameEventMasked, "Enable processing same event with masks", false); + PROCESS_SWITCH(femtoDreamTripletTaskTrackTrackTrackPbPb, processSameEventMasked, "Enable processing same event with masks", false); /// process function for to call doSameEvent with Monte Carlo /// \param col subscribe to the collision table (Monte Carlo Reconstructed reconstructed) @@ -333,7 +333,7 @@ struct femtoDreamTripletTaskTrackTrackTrack { } doSameEvent(thegroupSelectedParts, parts, col.magField(), col.multNtr(), col.multV0M()); } - PROCESS_SWITCH(femtoDreamTripletTaskTrackTrackTrack, processSameEventMC, "Enable processing same event for Monte Carlo", false); + PROCESS_SWITCH(femtoDreamTripletTaskTrackTrackTrackPbPb, processSameEventMC, "Enable processing same event for Monte Carlo", false); /// process function for to call doSameEvent with Monte Carlo which has a mask for containing particles or not /// \param col subscribe to the collision table (Monte Carlo Reconstructed reconstructed) @@ -354,7 +354,7 @@ struct femtoDreamTripletTaskTrackTrackTrack { } doSameEvent(thegroupSelectedParts, parts, col.magField(), col.multNtr(), col.multV0M()); } - PROCESS_SWITCH(femtoDreamTripletTaskTrackTrackTrack, processSameEventMCMasked, "Enable processing same event for Monte Carlo", false); + PROCESS_SWITCH(femtoDreamTripletTaskTrackTrackTrackPbPb, processSameEventMCMasked, "Enable processing same event for Monte Carlo", false); /// This function processes the mixed event /// \tparam PartitionType @@ -417,7 +417,7 @@ struct femtoDreamTripletTaskTrackTrackTrack { doMixedEvent(groupPartsOne, groupPartsTwo, groupPartsThree, parts, magFieldTesla1, multiplicityCol); } } - PROCESS_SWITCH(femtoDreamTripletTaskTrackTrackTrack, processMixedEvent, "Enable processing mixed events", true); + PROCESS_SWITCH(femtoDreamTripletTaskTrackTrackTrackPbPb, processMixedEvent, "Enable processing mixed events", true); /// process function for to call doMixedEvent with Data which has a mask for containing particles or not /// @param cols subscribe to the collisions table (Data) @@ -429,10 +429,12 @@ struct femtoDreamTripletTaskTrackTrackTrack { (ConfTracksInMixedEvent == 3 && (aod::femtodreamcollision::bitmaskTrackThree & MaskBit) == MaskBit); PartitionMaskedCol1.bindTable(cols); - for (auto& [collision1, collision2, collision3] : soa::selfCombinations(colBinning, ConfNEventsMix, -1, *PartitionMaskedCol1.mFiltered, *PartitionMaskedCol1.mFiltered, *PartitionMaskedCol1.mFiltered)) { const int multiplicityCol = collision1.multNtr(); ThreeBodyQARegistry.fill(HIST("TripletTaskQA/hMECollisionBins"), colBinning.getBin({collision1.posZ(), multiplicityCol})); + ThreeBodyQARegistry.fill(HIST("TripletTaskQA/hCentralityME"), collision1.multV0M()); + ThreeBodyQARegistry.fill(HIST("TripletTaskQA/hCentralityME"), collision2.multV0M()); + ThreeBodyQARegistry.fill(HIST("TripletTaskQA/hCentralityME"), collision3.multV0M()); auto groupPartsOne = SelectedParts->sliceByCached(aod::femtodreamparticle::fdCollisionId, collision1.globalIndex(), cache); auto groupPartsTwo = SelectedParts->sliceByCached(aod::femtodreamparticle::fdCollisionId, collision2.globalIndex(), cache); @@ -449,7 +451,7 @@ struct femtoDreamTripletTaskTrackTrackTrack { doMixedEvent(groupPartsOne, groupPartsTwo, groupPartsThree, parts, magFieldTesla1, multiplicityCol); } } - PROCESS_SWITCH(femtoDreamTripletTaskTrackTrackTrack, processMixedEventMasked, "Enable processing mixed events", false); + PROCESS_SWITCH(femtoDreamTripletTaskTrackTrackTrackPbPb, processMixedEventMasked, "Enable processing mixed events", false); /// brief process function for to call doMixedEvent with Monte Carlo /// @param cols subscribe to the collisions table (Monte Carlo Reconstructed reconstructed) @@ -480,7 +482,7 @@ struct femtoDreamTripletTaskTrackTrackTrack { doMixedEvent(groupPartsOne, groupPartsTwo, groupPartsThree, parts, magFieldTesla1, multiplicityCol); } } - PROCESS_SWITCH(femtoDreamTripletTaskTrackTrackTrack, processMixedEventMC, "Enable processing mixed events MC", false); + PROCESS_SWITCH(femtoDreamTripletTaskTrackTrackTrackPbPb, processMixedEventMC, "Enable processing mixed events MC", false); /// brief process function for to call doMixedEvent with Monte Carlo which has a mask for containing particles or not /// @param cols subscribe to the collisions table (Monte Carlo Reconstructed reconstructed) @@ -516,13 +518,13 @@ struct femtoDreamTripletTaskTrackTrackTrack { doMixedEvent(groupPartsOne, groupPartsTwo, groupPartsThree, parts, magFieldTesla1, multiplicityCol); } } - PROCESS_SWITCH(femtoDreamTripletTaskTrackTrackTrack, processMixedEventMCMasked, "Enable processing mixed events MC", false); + PROCESS_SWITCH(femtoDreamTripletTaskTrackTrackTrackPbPb, processMixedEventMCMasked, "Enable processing mixed events MC", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { WorkflowSpec workflow{ - adaptAnalysisTask(cfgc), + adaptAnalysisTask(cfgc), }; return workflow; } From 1abec0d464b3744bcb910d3da470eac8f6058eda Mon Sep 17 00:00:00 2001 From: EmilGorm <50658075+EmilGorm@users.noreply.github.com> Date: Mon, 30 Jun 2025 20:11:54 +0200 Subject: [PATCH 274/871] [PWGCF] Add additional cent estimators (#11834) --- PWGCF/GenericFramework/Tasks/CMakeLists.txt | 2 +- ...wGFWLightIons.cxx => flowGfwLightIons.cxx} | 91 ++++++++++++++++--- 2 files changed, 80 insertions(+), 13 deletions(-) rename PWGCF/GenericFramework/Tasks/{flowGFWLightIons.cxx => flowGfwLightIons.cxx} (95%) diff --git a/PWGCF/GenericFramework/Tasks/CMakeLists.txt b/PWGCF/GenericFramework/Tasks/CMakeLists.txt index 80f9072b932..338f173aa73 100644 --- a/PWGCF/GenericFramework/Tasks/CMakeLists.txt +++ b/PWGCF/GenericFramework/Tasks/CMakeLists.txt @@ -15,6 +15,6 @@ o2physics_add_dpl_workflow(flow-generic-framework COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(flow-gfw-light-ions - SOURCES flowGFWLightIons.cxx + SOURCES flowGfwLightIons.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::GFWCore COMPONENT_NAME Analysis) diff --git a/PWGCF/GenericFramework/Tasks/flowGFWLightIons.cxx b/PWGCF/GenericFramework/Tasks/flowGfwLightIons.cxx similarity index 95% rename from PWGCF/GenericFramework/Tasks/flowGFWLightIons.cxx rename to PWGCF/GenericFramework/Tasks/flowGfwLightIons.cxx index 8ed63475f1c..9e356c8fccf 100644 --- a/PWGCF/GenericFramework/Tasks/flowGFWLightIons.cxx +++ b/PWGCF/GenericFramework/Tasks/flowGfwLightIons.cxx @@ -9,7 +9,7 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -/// \file flowGFWLightIons.cxx +/// \file flowGfwLightIons.cxx /// \brief Dedicated GFW task to analyse angular correlations in light-ion collision systems /// \author Emil Gorm Nielsen, NBI, emil.gorm.nielsen@cern.ch @@ -165,7 +165,9 @@ struct FlowGfwLightIons { kCentFT0CVariant1, kCentFT0M, kCentFV0A, - kCentNTPV + kCentNTPV, + kCentNGlobal, + kCentMFT }; // Define global variables @@ -212,7 +214,7 @@ struct FlowGfwLightIons { void init(InitContext const&) { - LOGF(info, "flowGFWLightIons::init()"); + LOGF(info, "flowGfwLightIons::init()"); o2::analysis::gfw::regions.SetNames(cfgRegions->GetNames()); o2::analysis::gfw::regions.SetEtaMin(cfgRegions->GetEtaMin()); o2::analysis::gfw::regions.SetEtaMax(cfgRegions->GetEtaMax()); @@ -265,8 +267,15 @@ struct FlowGfwLightIons { case kCentNTPV: sCentralityEstimator = "NTPV"; break; + case kCentNGlobal: + sCentralityEstimator = "NGlobals"; + break; + case kCentMFT: + sCentralityEstimator = "MFT"; + break; default: sCentralityEstimator = "FT0C"; + break; } sCentralityEstimator += " centrality (%)"; AxisSpec centAxis = {o2::analysis::gfw::centbinning, sCentralityEstimator.c_str()}; @@ -296,7 +305,7 @@ struct FlowGfwLightIons { fPtAxis = new TAxis(ptbins, &o2::analysis::gfw::ptbinning[0]); if (doprocessMCGen || doprocessMCGenNoCent || doprocessOnTheFly) { - registry.add("MCGen/trackQA/nch_pt", "#it{p}_{T} vs multiplicity; N_{ch}; #it{p}_{T}", {HistType::kTH2D, {nchAxis, {100, o2::analysis::gfw::ptpoilow, o2::analysis::gfw::ptpoiup}}}); + registry.add("MCGen/trackQA/nch_pt", "#it{p}_{T} vs multiplicity; N_{ch}; #it{p}_{T}", {HistType::kTH2D, {nchAxis, ptAxis}}); registry.add("MCGen/trackQA/phi_eta_vtxZ", "", {HistType::kTH3D, {phiAxis, etaAxis, vtxAxis}}); registry.add("MCGen/trackQA/pt_ref", "Reference #it{p}_{T}; #it{p}_{T}; Counts", {HistType::kTH1D, {{100, o2::analysis::gfw::ptreflow, o2::analysis::gfw::ptrefup}}}); registry.add("MCGen/trackQA/pt_poi", "POI #it{p}_{T}; #it{p}_{T}; Counts", {HistType::kTH1D, {{100, o2::analysis::gfw::ptpoilow, o2::analysis::gfw::ptpoiup}}}); @@ -310,7 +319,7 @@ struct FlowGfwLightIons { if (doprocessMCReco || doprocessData || doprocessDataNoCent || doprocessMCRecoNoCent) { registry.add("trackQA/before/phi_eta_vtxZ", "", {HistType::kTH3D, {phiAxis, etaAxis, vtxAxis}}); registry.add("trackQA/before/pt_dcaXY_dcaZ", "", {HistType::kTH3D, {ptAxis, dcaXYAXis, dcaZAXis}}); - registry.add("trackQA/before/nch_pt", "#it{p}_{T} vs multiplicity; N_{ch}; #it{p}_{T}", {HistType::kTH2D, {nchAxis, {100, o2::analysis::gfw::ptpoilow, o2::analysis::gfw::ptpoiup}}}); + registry.add("trackQA/before/nch_pt", "#it{p}_{T} vs multiplicity; N_{ch}; #it{p}_{T}", {HistType::kTH2D, {nchAxis, ptAxis}}); registry.add("trackQA/before/chi2prTPCcls", "#chi^{2}/cluster for the TPC track segment; #chi^{2}/TPC cluster", {HistType::kTH1D, {{100, 0., 5.}}}); registry.add("trackQA/before/chi2prITScls", "#chi^{2}/cluster for the ITS track; #chi^{2}/ITS cluster", {HistType::kTH1D, {{100, 0., 50.}}}); registry.add("trackQA/before/nTPCClusters", "Number of found TPC clusters; TPC N_{cls}; Counts", {HistType::kTH1D, {{100, 40, 180}}}); @@ -770,10 +779,10 @@ struct FlowGfwLightIons { return; if (cfgFillWeights) { - fillWeights(mcParticle, vtxz, run); + fillWeights(track, vtxz, run); } else { fillPtSums(track); - fillGFW(mcParticle, vtxz, densitycorrections); + fillGFW(track, vtxz, densitycorrections); } if (cfgFillQA) { @@ -905,7 +914,7 @@ struct FlowGfwLightIons { return; } - void processData(soa::Filtered>::iterator const& collision, aod::BCsWithTimestamps const&, GFWTracks const& tracks) + void processData(soa::Filtered>::iterator const& collision, aod::BCsWithTimestamps const&, GFWTracks const& tracks) { auto bc = collision.bc_as(); int run = bc.runNumber(); @@ -959,8 +968,15 @@ struct FlowGfwLightIons { case kCentNTPV: centrality = collision.centNTPV(); break; + case kCentNGlobal: + centrality = collision.centNGlobal(); + break; + case kCentMFT: + centrality = collision.centMFT(); + break; default: centrality = collision.centFT0C(); + break; } if (cfgFillQA) fillEventQA(collision, tracks); @@ -1025,7 +1041,7 @@ struct FlowGfwLightIons { } PROCESS_SWITCH(FlowGfwLightIons, processDataNoCent, "Process analysis for non-derived data without centrality", true); - void processMCReco(soa::Filtered>::iterator const& collision, aod::BCsWithTimestamps const&, soa::Filtered> const& tracks, aod::McParticles const&) + void processMCReco(soa::Filtered>::iterator const& collision, aod::BCsWithTimestamps const&, soa::Filtered> const& tracks, aod::McParticles const&) { auto bc = collision.bc_as(); int run = bc.runNumber(); @@ -1036,7 +1052,33 @@ struct FlowGfwLightIons { } if (!collision.sel8()) return; - const auto centrality = collision.centFT0C(); + float centrality; + switch (cfgCentEstimator) { + case kCentFT0C: + centrality = collision.centFT0C(); + break; + case kCentFT0CVariant1: + centrality = collision.centFT0CVariant1(); + break; + case kCentFT0M: + centrality = collision.centFT0M(); + break; + case kCentFV0A: + centrality = collision.centFV0A(); + break; + case kCentNTPV: + centrality = collision.centNTPV(); + break; + case kCentNGlobal: + centrality = collision.centNGlobal(); + break; + case kCentMFT: + centrality = collision.centMFT(); + break; + default: + centrality = collision.centFT0C(); + break; + } if (cfgFillQA) fillEventQA(collision, tracks); registry.fill(HIST("eventQA/before/centrality"), centrality); @@ -1142,13 +1184,38 @@ struct FlowGfwLightIons { } PROCESS_SWITCH(FlowGfwLightIons, processMCRecoNoCent, "Process analysis for MC reconstructed events without centrality/mult table", false); - void processMCGen(soa::Filtered::iterator const& mcCollision, soa::SmallGroups> const& collisions, aod::McParticles const& particles, GFWTracks const& tracks) + void processMCGen(soa::Filtered::iterator const& mcCollision, soa::SmallGroups> const& collisions, aod::McParticles const& particles, GFWTracks const& tracks) { if (collisions.size() != 1) return; float centrality = -1; for (const auto& collision : collisions) { - centrality = collision.centFT0C(); + switch (cfgCentEstimator) { + case kCentFT0C: + centrality = collision.centFT0C(); + break; + case kCentFT0CVariant1: + centrality = collision.centFT0CVariant1(); + break; + case kCentFT0M: + centrality = collision.centFT0M(); + break; + case kCentFV0A: + centrality = collision.centFV0A(); + break; + case kCentNTPV: + centrality = collision.centNTPV(); + break; + case kCentNGlobal: + centrality = collision.centNGlobal(); + break; + case kCentMFT: + centrality = collision.centMFT(); + break; + default: + centrality = collision.centFT0C(); + break; + } } std::vector numberOfTracks; for (auto const& collision : collisions) { From 3d5d077f7d194d81367a7b7b9c25d682215aac1b Mon Sep 17 00:00:00 2001 From: "Paul Veen (paveen)" <80593165+ppoava@users.noreply.github.com> Date: Mon, 30 Jun 2025 20:39:19 +0200 Subject: [PATCH 275/871] [Common] Added pseudorapidity to qaMuon task (#11846) --- Common/Tasks/qaMuon.cxx | 150 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 149 insertions(+), 1 deletion(-) diff --git a/Common/Tasks/qaMuon.cxx b/Common/Tasks/qaMuon.cxx index 2c19b4bff67..a3781e09cc8 100644 --- a/Common/Tasks/qaMuon.cxx +++ b/Common/Tasks/qaMuon.cxx @@ -284,6 +284,33 @@ struct muonQa { registry.add("muons/TrackPDCA", "MCH track p #times DCA", {HistType::kTH1F, {pdcaAxis}}); registry.add("muons/TrackPhi", "MCH track #phi", {HistType::kTH1F, {phiAxis}}); + // muon origin from MCH quadrants + registry.add("muons/TrackEtaPos", "MCH #mu^{+} track #eta", {HistType::kTH1F, {etaAxis}}); + registry.add("muons/TrackEtaNeg", "MCH #mu^{-} track #eta", {HistType::kTH1F, {etaAxis}}); + // -- pT and eta + registry.add("muons/TrackPt_TrackEtaPos", "track pT and #eta", {HistType::kTH2F, {transverseMomentumAxis, etaAxis}}); + registry.add("muons/TrackPt_TrackEtaNeg", "track pT and #eta", {HistType::kTH2F, {transverseMomentumAxis, etaAxis}}); + // top-bottom + registry.add("muons/TrackEtaPos_T", "MCH #mu^{+} track #eta, top MCH CH1", {HistType::kTH1F, {etaAxis}}); + registry.add("muons/TrackEtaPos_B", "MCH #mu^{+} track #eta, bottom MCH CH1", {HistType::kTH1F, {etaAxis}}); + registry.add("muons/TrackEtaNeg_T", "MCH #mu^{-} track #eta, top MCH CH1", {HistType::kTH1F, {etaAxis}}); + registry.add("muons/TrackEtaNeg_B", "MCH #mu^{-} track #eta, bottom MCH CH1", {HistType::kTH1F, {etaAxis}}); + // -- pT and eta + registry.add("muons/TrackPt_TrackEtaPos_T", "track p_{T} and #eta, top MCH CH1", {HistType::kTH2F, {transverseMomentumAxis, etaAxis}}); + registry.add("muons/TrackPt_TrackEtaPos_B", "track p_{T} and #eta, bottom MCH CH1", {HistType::kTH2F, {transverseMomentumAxis, etaAxis}}); + registry.add("muons/TrackPt_TrackEtaNeg_T", "track p_{T} and #eta, top MCH CH1", {HistType::kTH2F, {transverseMomentumAxis, etaAxis}}); + registry.add("muons/TrackPt_TrackEtaNeg_B", "track p_{T} and #eta, bottom MCH CH1", {HistType::kTH2F, {transverseMomentumAxis, etaAxis}}); + // left-right + registry.add("muons/TrackEtaPos_L", "MCH #mu^{+} track #eta, left MCH CH1", {HistType::kTH1F, {etaAxis}}); + registry.add("muons/TrackEtaPos_R", "MCH #mu^{+} track #eta, right MCH CH1", {HistType::kTH1F, {etaAxis}}); + registry.add("muons/TrackEtaNeg_L", "MCH #mu^{-} track #eta, left MCH CH1", {HistType::kTH1F, {etaAxis}}); + registry.add("muons/TrackEtaNeg_R", "MCH #mu^{-} track #eta, right MCH CH1", {HistType::kTH1F, {etaAxis}}); + // -- pT and eta + registry.add("muons/TrackPt_TrackEtaPos_L", "track p_{T} and #eta, top MCH CH1", {HistType::kTH2F, {transverseMomentumAxis, etaAxis}}); + registry.add("muons/TrackPt_TrackEtaPos_R", "track p_{T} and #eta, bottom MCH CH1", {HistType::kTH2F, {transverseMomentumAxis, etaAxis}}); + registry.add("muons/TrackPt_TrackEtaNeg_L", "track p_{T} and #eta, top MCH CH1", {HistType::kTH2F, {transverseMomentumAxis, etaAxis}}); + registry.add("muons/TrackPt_TrackEtaNeg_R", "track p_{T} and #eta, bottom MCH CH1", {HistType::kTH2F, {transverseMomentumAxis, etaAxis}}); + // ====================== // Global muons plots // ====================== @@ -538,6 +565,7 @@ struct muonQa { AxisSpec invMassAxis = {400, 1, 5, "M_{#mu^{+}#mu^{-}} (GeV/c^{2})"}; AxisSpec invMassCorrelationAxis = {80, 0, 8, "M_{#mu^{+}#mu^{-}} (GeV/c^{2})"}; AxisSpec invMassAxisFull = {5000, 0, 100, "M_{#mu^{+}#mu^{-}} (GeV/c^{2})"}; + AxisSpec yPairAxis = {120, 0.0, 6.0, "#y_{pair}"}; AxisSpec invMassAxis2D = {750, 0, 15, "M_{#mu^{+}#mu^{-}} (GeV/c^{2})"}; AxisSpec pTAxis2D = {120, 0, 30, "p_{T} (GeV/c)"}; // MCH-MID tracks with MCH acceptance cuts @@ -667,11 +695,42 @@ struct muonQa { registryDimuon.add("dimuon/same-event/invariantMassFull_GlobalMuonKine_GlobalMatchesCuts_subleading_leading", "#mu^{+}#mu^{-} invariant mass", {HistType::kTH1F, {invMassAxisFull}}); registryDimuon.add("dimuon/same-event/invariantMass_GlobalMuonKine_GlobalMatchesCuts_subleading_subleading", "#mu^{+}#mu^{-} invariant mass", {HistType::kTH1F, {invMassAxis}}); registryDimuon.add("dimuon/same-event/invariantMassFull_GlobalMuonKine_GlobalMatchesCuts_subleading_subleading", "#mu^{+}#mu^{-} invariant mass", {HistType::kTH1F, {invMassAxisFull}}); - // invariant mass correlations registryDimuon.add("dimuon/same-event/invariantMass_MuonKine_vs_GlobalMuonKine", "M_{#mu^{+}#mu^{-}} - muon tracks vs. global tracks", {HistType::kTH2F, {invMassCorrelationAxis, invMassCorrelationAxis}}); registryDimuon.add("dimuon/same-event/invariantMass_ScaledMftKine_vs_GlobalMuonKine", "M_{#mu^{+}#mu^{-}} - rescaled MFT tracks vs. global tracks", {HistType::kTH2F, {invMassCorrelationAxis, invMassCorrelationAxis}}); registryDimuon.add("dimuon/same-event/invariantMass_GlobalMuonKine_subleading_vs_leading", "M_{#mu^{+}#mu^{-}} - subleading vs. leading matches", {HistType::kTH2F, {invMassCorrelationAxis, invMassCorrelationAxis}}); + + // pseudorapidity (only for MCH acceptance cuts) + // MCH-MID tracks with MCH acceptance cuts + registryDimuon.add("dimuon/same-event/rapPair_MuonKine_MuonCuts", "#eta of dimuon pair", {HistType::kTH1F, {yPairAxis}}); + // -- Mass and eta + registryDimuon.add("dimuon/same-event/invariantMass_rapPair_MuonKine_MuonCuts", "#mu^{+}#mu^{-} invariant mass", {HistType::kTH2F, {invMassAxis2D, yPairAxis}}); + // -- pT and eta + registryDimuon.add("dimuon/same-event/pT_rapPair_MuonKine_MuonCuts", "#mu^{+}#mu^{-} p_{T} and #eta", {HistType::kTH2F, {pTAxis2D, yPairAxis}}); + // MCH-MID tracks with MCH acceptance cuts and combinations from the top and bottom halfs of MCH + registryDimuon.add("dimuon/same-event/rapPair_MuonKine_MuonCuts_TT", "#eta of dimuon pair, top-top", {HistType::kTH1F, {yPairAxis}}); + registryDimuon.add("dimuon/same-event/rapPair_MuonKine_MuonCuts_TB", "#eta of dimuon pair, top-bottom or bottom-top", {HistType::kTH1F, {yPairAxis}}); + registryDimuon.add("dimuon/same-event/rapPair_MuonKine_MuonCuts_BB", "#eta of dimuon pair, bottom-bottom", {HistType::kTH1F, {yPairAxis}}); + // -- Mass and eta + registryDimuon.add("dimuon/same-event/invariantMass_rapPair_MuonKine_MuonCuts_TT", "#mu^{+}#mu^{-} invariant mass, top-top", {HistType::kTH2F, {invMassAxis2D, yPairAxis}}); + registryDimuon.add("dimuon/same-event/invariantMass_rapPair_MuonKine_MuonCuts_TB", "#mu^{+}#mu^{-} invariant mass, top-bottom or bottom-top", {HistType::kTH2F, {invMassAxis2D, yPairAxis}}); + registryDimuon.add("dimuon/same-event/invariantMass_rapPair_MuonKine_MuonCuts_BB", "#mu^{+}#mu^{-} invariant mass, bottom-bottom", {HistType::kTH2F, {invMassAxis2D, yPairAxis}}); + // -- pT and eta + registryDimuon.add("dimuon/same-event/pT_rapPair_MuonKine_MuonCuts_TT", "#mu^{+}#mu^{-} p_{T} and #eta, top-top", {HistType::kTH2F, {pTAxis2D, yPairAxis}}); + registryDimuon.add("dimuon/same-event/pT_rapPair_MuonKine_MuonCuts_TB", "#mu^{+}#mu^{-} p_{T} and #eta, top-bottom or bottom-top", {HistType::kTH2F, {pTAxis2D, yPairAxis}}); + registryDimuon.add("dimuon/same-event/pT_rapPair_MuonKine_MuonCuts_BB", "#mu^{+}#mu^{-} p_{T} and #eta, bottom-bottom", {HistType::kTH2F, {pTAxis2D, yPairAxis}}); + // MCH-MID tracks with MCH acceptance cuts and combinations from the left and right halfs of MCH + registryDimuon.add("dimuon/same-event/rapPair_MuonKine_MuonCuts_LL", "#eta of dimuon pair, left-left", {HistType::kTH1F, {yPairAxis}}); + registryDimuon.add("dimuon/same-event/rapPair_MuonKine_MuonCuts_LR", "#eta of dimuon pair, left-right or right-left", {HistType::kTH1F, {yPairAxis}}); + registryDimuon.add("dimuon/same-event/rapPair_MuonKine_MuonCuts_RR", "#eta of dimuon pair, right-right", {HistType::kTH1F, {yPairAxis}}); + // -- Mass and eta + registryDimuon.add("dimuon/same-event/invariantMass_rapPair_MuonKine_MuonCuts_LL", "#mu^{+}#mu^{-} invariant mass, left-left", {HistType::kTH2F, {invMassAxis2D, yPairAxis}}); + registryDimuon.add("dimuon/same-event/invariantMass_rapPair_MuonKine_MuonCuts_LR", "#mu^{+}#mu^{-} invariant mass, left-right or right-left", {HistType::kTH2F, {invMassAxis2D, yPairAxis}}); + registryDimuon.add("dimuon/same-event/invariantMass_rapPair_MuonKine_MuonCuts_RR", "#mu^{+}#mu^{-} invariant mass, right-right", {HistType::kTH2F, {invMassAxis2D, yPairAxis}}); + // -- pT and eta + registryDimuon.add("dimuon/same-event/pT_rapPair_MuonKine_MuonCuts_LL", "#mu^{+}#mu^{-} p_{T} and #eta, left-left", {HistType::kTH2F, {pTAxis2D, yPairAxis}}); + registryDimuon.add("dimuon/same-event/pT_rapPair_MuonKine_MuonCuts_LR", "#mu^{+}#mu^{-} p_{T} and #eta, left-right or right-left", {HistType::kTH2F, {pTAxis2D, yPairAxis}}); + registryDimuon.add("dimuon/same-event/pT_rapPair_MuonKine_MuonCuts_RR", "#mu^{+}#mu^{-} p_{T} and #eta, right-right", {HistType::kTH2F, {pTAxis2D, yPairAxis}}); } } @@ -1021,6 +1080,26 @@ struct muonQa { return dimuon.Pt(); } + template + double GetMuMuRap(VarT const& track1, VarT const& track2) + { + ROOT::Math::PxPyPzMVector muon1{ + track1.px, + track1.py, + track1.pz, + o2::constants::physics::MassMuon}; + + ROOT::Math::PxPyPzMVector muon2{ + track2.px, + track2.py, + track2.pz, + o2::constants::physics::MassMuon}; + + auto dimuon = muon1 + muon2; + + return dimuon.Y(); + } + template void GetMuonPairs(TMuons const& muons, TCandidates const& matchingCandidates, const std::map& collisionInfos, std::vector& muonPairs, @@ -1502,6 +1581,56 @@ struct muonQa { registry.get(HIST("muons/TrackPhi"))->Fill(fgValuesMCH.phi * 180.0 / TMath::Pi()); registry.get(HIST("muons/TrackDCA"))->Fill(std::sqrt(fgValuesMCH.dcaX * fgValuesMCH.dcaX + fgValuesMCH.dcaY * fgValuesMCH.dcaY)); } + + // muon origin for MCH top-bottom and left-right parts + if (IsGoodMuon(fgValuesMCH, fgValuesMCHpv, configMuons.fTrackChi2MchUp, configMuons.fPMchLow, configMuons.fPtMchLow, -1.E10, 1.E10, configMuons.fRabsLow, configMuons.fRabsUp, configMuons.fSigmaPdcaUp)) { + int Quadrant = GetQuadrantPhi(fgValuesMCH.phi * 180.0 / TMath::Pi()); + int TopBottom = (Quadrant == 0 || Quadrant == 1) ? 0 : 1; + int LeftRight = (Quadrant == 0 || Quadrant == 2) ? 0 : 1; + int PosNeg = fgValuesMCH.sign > 0 ? 0 : 1; + float eta = fgValuesMCH.eta; + float pT = fgValuesMCH.pT; + + // same-event case + if (PosNeg == 0) { + registry.get(HIST("muons/TrackEtaPos"))->Fill(eta); + registry.get(HIST("muons/TrackPt_TrackEtaPos"))->Fill(pT, eta); + + if (TopBottom == 0) { + registry.get(HIST("muons/TrackEtaPos_T"))->Fill(eta); + registry.get(HIST("muons/TrackPt_TrackEtaPos_T"))->Fill(pT, eta); + } else if (TopBottom == 1) { + registry.get(HIST("muons/TrackEtaPos_B"))->Fill(eta); + registry.get(HIST("muons/TrackPt_TrackEtaPos_B"))->Fill(pT, eta); + } + + if (LeftRight == 0) { + registry.get(HIST("muons/TrackEtaPos_L"))->Fill(eta); + registry.get(HIST("muons/TrackPt_TrackEtaPos_L"))->Fill(pT, eta); + } else if (LeftRight == 1) { + registry.get(HIST("muons/TrackEtaPos_R"))->Fill(eta); + registry.get(HIST("muons/TrackPt_TrackEtaPos_R"))->Fill(pT, eta); + } + } else if (PosNeg == 1) { + registry.get(HIST("muons/TrackEtaNeg"))->Fill(eta); + registry.get(HIST("muons/TrackPt_TrackEtaNeg"))->Fill(pT, eta); + if (TopBottom == 0) { + registry.get(HIST("muons/TrackEtaNeg_T"))->Fill(eta); + registry.get(HIST("muons/TrackPt_TrackEtaNeg_T"))->Fill(pT, eta); + } else if (TopBottom == 1) { + registry.get(HIST("muons/TrackEtaNeg_B"))->Fill(eta); + registry.get(HIST("muons/TrackPt_TrackEtaNeg_B"))->Fill(pT, eta); + } + + if (LeftRight == 0) { + registry.get(HIST("muons/TrackEtaNeg_L"))->Fill(eta); + registry.get(HIST("muons/TrackPt_TrackEtaNeg_L"))->Fill(pT, eta); + } else if (LeftRight == 1) { + registry.get(HIST("muons/TrackEtaNeg_R"))->Fill(eta); + registry.get(HIST("muons/TrackPt_TrackEtaNeg_R"))->Fill(pT, eta); + } + } + } } if constexpr (static_cast(GlobalMuonFillMap)) { @@ -2310,39 +2439,58 @@ struct muonQa { double mass = GetMuMuInvariantMass(fgValuesMuonPV1, fgValuesMuonPV2); double pT = GetMuMuPt(fgValuesMuonPV1, fgValuesMuonPV2); + double yPair = GetMuMuRap(fgValuesMuonPV1, fgValuesMuonPV2); if (goodMuonTracks) { if (sameEvent) { // same-event case registryDimuon.get(HIST("dimuon/same-event/invariantMass_MuonKine_MuonCuts"))->Fill(mass); registryDimuon.get(HIST("dimuon/same-event/invariantMassFull_MuonKine_MuonCuts"))->Fill(mass); registryDimuon.get(HIST("dimuon/same-event/invariantMass_pT_MuonKine_MuonCuts"))->Fill(mass, pT); + registryDimuon.get(HIST("dimuon/same-event/rapPair_MuonKine_MuonCuts"))->Fill(yPair); + registryDimuon.get(HIST("dimuon/same-event/invariantMass_rapPair_MuonKine_MuonCuts"))->Fill(mass, yPair); + registryDimuon.get(HIST("dimuon/same-event/pT_rapPair_MuonKine_MuonCuts"))->Fill(pT, yPair); if (TopBottom1 == 0 && TopBottom2 == 0) { registryDimuon.get(HIST("dimuon/same-event/invariantMass_MuonKine_MuonCuts_TT"))->Fill(mass); registryDimuon.get(HIST("dimuon/same-event/invariantMassFull_MuonKine_MuonCuts_TT"))->Fill(mass); registryDimuon.get(HIST("dimuon/same-event/invariantMass_pT_MuonKine_MuonCuts_TT"))->Fill(mass, pT); + registryDimuon.get(HIST("dimuon/same-event/rapPair_MuonKine_MuonCuts_TT"))->Fill(yPair); + registryDimuon.get(HIST("dimuon/same-event/invariantMass_rapPair_MuonKine_MuonCuts_TT"))->Fill(mass, yPair); + registryDimuon.get(HIST("dimuon/same-event/pT_rapPair_MuonKine_MuonCuts_TT"))->Fill(pT, yPair); } else if ((TopBottom1 == 0 && TopBottom2 == 1) || (TopBottom1 == 1 && TopBottom2 == 0)) { registryDimuon.get(HIST("dimuon/same-event/invariantMass_MuonKine_MuonCuts_TB"))->Fill(mass); registryDimuon.get(HIST("dimuon/same-event/invariantMassFull_MuonKine_MuonCuts_TB"))->Fill(mass); registryDimuon.get(HIST("dimuon/same-event/invariantMass_pT_MuonKine_MuonCuts_TB"))->Fill(mass, pT); + registryDimuon.get(HIST("dimuon/same-event/rapPair_MuonKine_MuonCuts_TB"))->Fill(yPair); + registryDimuon.get(HIST("dimuon/same-event/invariantMass_rapPair_MuonKine_MuonCuts_TB"))->Fill(mass, yPair); + registryDimuon.get(HIST("dimuon/same-event/pT_rapPair_MuonKine_MuonCuts_TB"))->Fill(pT, yPair); } else if (TopBottom1 == 1 && TopBottom2 == 1) { registryDimuon.get(HIST("dimuon/same-event/invariantMass_MuonKine_MuonCuts_BB"))->Fill(mass); registryDimuon.get(HIST("dimuon/same-event/invariantMassFull_MuonKine_MuonCuts_BB"))->Fill(mass); registryDimuon.get(HIST("dimuon/same-event/invariantMass_pT_MuonKine_MuonCuts_BB"))->Fill(mass, pT); + registryDimuon.get(HIST("dimuon/same-event/rapPair_MuonKine_MuonCuts_BB"))->Fill(yPair); + registryDimuon.get(HIST("dimuon/same-event/invariantMass_rapPair_MuonKine_MuonCuts_BB"))->Fill(mass, yPair); + registryDimuon.get(HIST("dimuon/same-event/pT_rapPair_MuonKine_MuonCuts_BB"))->Fill(pT, yPair); } if (LeftRight1 == 0 && LeftRight2 == 0) { registryDimuon.get(HIST("dimuon/same-event/invariantMass_MuonKine_MuonCuts_LL"))->Fill(mass); registryDimuon.get(HIST("dimuon/same-event/invariantMassFull_MuonKine_MuonCuts_LL"))->Fill(mass); registryDimuon.get(HIST("dimuon/same-event/invariantMass_pT_MuonKine_MuonCuts_LL"))->Fill(mass, pT); + registryDimuon.get(HIST("dimuon/same-event/rapPair_MuonKine_MuonCuts_LL"))->Fill(yPair); + registryDimuon.get(HIST("dimuon/same-event/invariantMass_rapPair_MuonKine_MuonCuts_LL"))->Fill(mass, yPair); } else if ((LeftRight1 == 0 && LeftRight2 == 1) || (LeftRight1 == 1 && LeftRight2 == 0)) { registryDimuon.get(HIST("dimuon/same-event/invariantMass_MuonKine_MuonCuts_LR"))->Fill(mass); registryDimuon.get(HIST("dimuon/same-event/invariantMassFull_MuonKine_MuonCuts_LR"))->Fill(mass); registryDimuon.get(HIST("dimuon/same-event/invariantMass_pT_MuonKine_MuonCuts_LR"))->Fill(mass, pT); + registryDimuon.get(HIST("dimuon/same-event/rapPair_MuonKine_MuonCuts_LR"))->Fill(yPair); + registryDimuon.get(HIST("dimuon/same-event/invariantMass_rapPair_MuonKine_MuonCuts_LR"))->Fill(mass, yPair); } else if (LeftRight1 == 1 && LeftRight2 == 1) { registryDimuon.get(HIST("dimuon/same-event/invariantMass_MuonKine_MuonCuts_RR"))->Fill(mass); registryDimuon.get(HIST("dimuon/same-event/invariantMassFull_MuonKine_MuonCuts_RR"))->Fill(mass); registryDimuon.get(HIST("dimuon/same-event/invariantMass_pT_MuonKine_MuonCuts_RR"))->Fill(mass, pT); + registryDimuon.get(HIST("dimuon/same-event/rapPair_MuonKine_MuonCuts_RR"))->Fill(yPair); + registryDimuon.get(HIST("dimuon/same-event/invariantMass_rapPair_MuonKine_MuonCuts_RR"))->Fill(mass, yPair); } } else { // event-mixing case From 11e0094989c232dcde47e18ece56b638f7db62c8 Mon Sep 17 00:00:00 2001 From: Anantha Padmanabhan M Nair <82643666+ananthapadmanabhan18@users.noreply.github.com> Date: Tue, 1 Jul 2025 00:14:41 +0530 Subject: [PATCH 276/871] [PWGUD] Modified a wrongly placed histogram for four pion pt (#11821) --- PWGUD/Tasks/exclusiveRhoTo4Pi.cxx | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/PWGUD/Tasks/exclusiveRhoTo4Pi.cxx b/PWGUD/Tasks/exclusiveRhoTo4Pi.cxx index e40ff901666..5268b739c72 100644 --- a/PWGUD/Tasks/exclusiveRhoTo4Pi.cxx +++ b/PWGUD/Tasks/exclusiveRhoTo4Pi.cxx @@ -641,18 +641,22 @@ struct ExclusiveRhoTo4Pi { // Four Pion Transverse Momentum histosData.add("fourpion_pT_0_charge", "Event pT in 0 Charge Events With Track Selection and PID Selection of Pi; pT [GeV/c]; Events", kTH1F, {pTAxis}); + histosData.add("fourpion_pT_0_charge_within_rap", "Event pT in 0 Charge Events With Track Selection and PID Selection of Pi; pT [GeV/c]; Events", kTH1F, {pTAxis}); histosData.add("fourpion_pT_non_0_charge", "Event pT in Non 0 Charge Events With Track Selection and PID Selection of Pi; pT [GeV/c]; Events", kTH1F, {pTAxis}); // Four Pion Eta histosData.add("fourpion_eta_0_charge", "Four Pion #eta (0 charge); #eta; Events", kTH1F, {{1000, -1.1, 1.1}}); + histosData.add("fourpion_eta_0_charge_within_rap", "Four Pion #eta (0 charge within rap); #eta; Events", kTH1F, {{1000, -1.1, 1.1}}); histosData.add("fourpion_eta_non_0_charge", "Four Pion #eta (non 0 charge); #eta; #eta; Events", kTH1F, {{1000, -1.1, 1.1}}); // Four Pion Phi histosData.add("fourpion_phi_0_charge", "Four Pion #phi (0 charge); #phi [rad]; Events", kTH1F, {phiAxis}); + histosData.add("fourpion_phi_0_charge_within_rap", "Four Pion #phi (0 charge within rap); #phi [rad]; Events", kTH1F, {phiAxis}); histosData.add("fourpion_phi_non_0_charge", "Four Pion #phi (non 0 charge); #phi [rad]; Events", kTH1F, {phiAxis}); // Four Pion Rapidity histosData.add("fourpion_rap_0_charge", "Four Pion Rapidity (0 charge); y; Events", kTH1F, {{1000, -2.5, 2.5}}); + histosData.add("fourpion_rap_0_charge_within_rap", "Four Pion Rapidity (0 charge within rap); y; Events", kTH1F, {{1000, -2.5, 2.5}}); histosData.add("fourpion_rap_non_0_charge", "Four Pion Rapidity (non 0 charge); y; Events", kTH1F, {rapidityAxis}); // Four Pion Mass @@ -1117,7 +1121,10 @@ struct ExclusiveRhoTo4Pi { fourPiPhiPair1, fourPiPhiPair2, fourPiCosThetaPair1, fourPiCosThetaPair2); if (std::fabs(p1234.Rapidity()) < rhoRapCut) { - histosData.fill(HIST("fourpion_pT_0_charge"), p1234.Pt()); + histosData.fill(HIST("fourpion_pT_0_charge_within_rap"), p1234.Pt()); + histosData.fill(HIST("fourpion_eta_0_charge_within_rap"), p1234.Eta()); + histosData.fill(HIST("fourpion_phi_0_charge_within_rap"), p1234.Phi()); + histosData.fill(HIST("fourpion_rap_0_charge_within_rap"), p1234.Rapidity()); if (p1234.Pt() < rhoPtCut) { histosData.fill(HIST("EventsCounts_vs_runNo"), collision.runNumber(), 5); // Fill the Invariant Mass Histogram From f28eb61bb50fe7ca5cce79d8b9f613daabda177f Mon Sep 17 00:00:00 2001 From: sawan <124118453+sawankumawat@users.noreply.github.com> Date: Tue, 1 Jul 2025 00:58:31 +0530 Subject: [PATCH 277/871] [PWGLF] Optimised code (#11830) Co-authored-by: Sawan Sawan --- PWGLF/Tasks/Resonances/kstarqa.cxx | 425 ++++++++++++++++------------- 1 file changed, 229 insertions(+), 196 deletions(-) diff --git a/PWGLF/Tasks/Resonances/kstarqa.cxx b/PWGLF/Tasks/Resonances/kstarqa.cxx index 804e8538824..02b25ed6af2 100644 --- a/PWGLF/Tasks/Resonances/kstarqa.cxx +++ b/PWGLF/Tasks/Resonances/kstarqa.cxx @@ -15,22 +15,8 @@ /// \since 13/03/2024 // #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "TRandom3.h" -#include "Math/Vector3D.h" -#include "Math/Vector4D.h" -#include "Math/GenVector/Boost.h" -#include "CCDB/BasicCCDBManager.h" -#include "CCDB/CcdbApi.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" + #include "Common/Core/TrackSelection.h" #include "Common/Core/trackUtilities.h" #include "Common/DataModel/Centrality.h" @@ -38,6 +24,9 @@ #include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/PIDResponse.h" #include "Common/DataModel/TrackSelectionTables.h" + +#include "CCDB/BasicCCDBManager.h" +#include "CCDB/CcdbApi.h" #include "CommonConstants/PhysicsConstants.h" #include "Framework/ASoAHelpers.h" #include "Framework/AnalysisDataModel.h" @@ -45,19 +34,43 @@ #include "Framework/HistogramRegistry.h" #include "Framework/StepTHn.h" #include "Framework/runDataProcessing.h" -#include "PWGLF/DataModel/LFStrangenessTables.h" #include "ReconstructionDataFormats/Track.h" +#include "Math/GenVector/Boost.h" +#include "Math/Vector3D.h" +#include "Math/Vector4D.h" +#include "TRandom3.h" +#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::soa; using std::array; +using namespace o2::aod::rctsel; struct Kstarqa { SliceCache cache; + struct : ConfigurableGroup { + Configurable requireRCTFlagChecker{"requireRCTFlagChecker", true, "Check event quality in run condition table"}; + 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"}; + } rctCut; + RCTFlagsChecker rctChecker; + // Histograms are defined with HistogramRegistry HistogramRegistry rEventSelection{"eventSelection", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; HistogramRegistry hInvMass{"hInvMass", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; @@ -66,12 +79,13 @@ struct Kstarqa { // Confugrable for QA histograms Configurable calcLikeSign{"calcLikeSign", true, "Calculate Like Sign"}; - Configurable calcRotational{"calcRotational", true, "Calculate Rotational"}; + Configurable calcRotational{"calcRotational", false, "Calculate Rotational"}; Configurable cQAplots{"cQAplots", true, "cQAplots"}; Configurable cQAevents{"cQAevents", true, "Multiplicity dist, DCAxy, DCAz"}; Configurable onlyTOF{"onlyTOF", false, "only TOF tracks"}; Configurable onlyTOFHIT{"onlyTOFHIT", false, "accept only TOF hit tracks at high pt"}; Configurable onlyTPC{"onlyTPC", true, "only TPC tracks"}; + Configurable cRotations{"cRotations", 3, "Number of random rotations in the rotational background"}; // Configurables for track selections Configurable rotationalCut{"rotationalCut", 10, "Cut value (Rotation angle pi - pi/cut and pi + pi/cut)"}; @@ -91,9 +105,9 @@ struct Kstarqa { Configurable cfgGlobalWoDCATrack{"cfgGlobalWoDCATrack", false, "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 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 cFakeTrack{"cFakeTrack", true, "Fake track selection"}; // PID selections Configurable nsigmaCutTPCPi{"nsigmaCutTPCPi", 3.0, "TPC Nsigma cut for pions"}; @@ -103,25 +117,21 @@ struct Kstarqa { Configurable nsigmaCutCombined{"nsigmaCutCombined", 3.0, "Combined Nsigma cut"}; // Event selection configurables - Configurable timFrameEvsel{"timFrameEvsel", false, "TPC Time frame boundary cut"}; - Configurable cTVXEvsel{"cTVXEvsel", false, "Triggger selection"}; + Configurable timFrameEvsel{"timFrameEvsel", true, "TPC Time frame boundary cut"}; + Configurable cTVXEvsel{"cTVXEvsel", true, "Triggger selection"}; Configurable cutzvertex{"cutzvertex", 10.0f, "Accepted z-vertex range (cm)"}; // Configurable cMID{"cMID", false, "Misidentification of tracks"}; // Configurable for histograms - Configurable nBins{"nBins", 100, "No. of bins in Vz distribution"}; - Configurable nBinsinvMass{"nBinsinvMass", 180, "N bins in invMass hInvMass"}; - Configurable invMassbinlow{"invMassbinlow", 0.6, "invMass bin low"}; - Configurable invMassbinhigh{"invMassbinhigh", 1.5, "invMass bin high"}; - Configurable nBinspT{"nBinspT", 200, "N bins in pT hInvMass"}; - Configurable pTbinlow{"pTbinlow", 0.0, "pT bin low"}; - Configurable pTbinhigh{"pTbinhigh", 20.0, "pT bin high"}; Configurable avoidsplitrackMC{"avoidsplitrackMC", true, "avoid split track in MC"}; Configurable cAllGenCollisions{"cAllGenCollisions", false, "To fill all generated collisions for the signal loss calculations"}; - ConfigurableAxis binsMultPlot{"binsMultPlot", {201, -0.5f, 200.5f}, "centrality axis bins"}; + ConfigurableAxis binsMultPlot{"binsMultPlot", {110, 0.0, 110}, "THnSpare multiplicity axis"}; ConfigurableAxis axisdEdx{"axisdEdx", {1, 0.0f, 200.0f}, "dE/dx (a.u.)"}; ConfigurableAxis axisPtfordEbydx{"axisPtfordEbydx", {1, 0, 20}, "pT (GeV/c)"}; ConfigurableAxis axisMultdist{"axisMultdist", {1, 0, 70000}, "Multiplicity distribution"}; + ConfigurableAxis configThnAxisPOL{"configThnAxisPOL", {20, -1.0, 1.0}, "Costheta axis"}; + ConfigurableAxis invMassKstarAxis{"invMassKstar", {300, 0.7f, 1.3f}, "Kstar invariant mass axis"}; + ConfigurableAxis ptAxisKstar{"ptAxisKstar", {200, 0.0f, 20.0f}, "Kstar pT axis"}; // Event plane configurables Configurable boostDaugter1{"boostDaugter1", false, "Boost daughter Kaon in the COM frame"}; @@ -130,24 +140,25 @@ struct Kstarqa { Configurable activateTHnSparseCosThStarProduction{"activateTHnSparseCosThStarProduction", false, "Activate the THnSparse with cosThStar w.r.t. production axis"}; Configurable activateTHnSparseCosThStarBeam{"activateTHnSparseCosThStarBeam", false, "Activate the THnSparse with cosThStar w.r.t. beam axis (Gottified jackson frame)"}; Configurable activateTHnSparseCosThStarRandom{"activateTHnSparseCosThStarRandom", false, "Activate the THnSparse with cosThStar w.r.t. random axis"}; - Configurable cRotations{"cRotations", 3, "Number of random rotations in the rotational background"}; - ConfigurableAxis configThnAxisPOL{"configThnAxisPOL", {20, -1.0, 1.0}, "Costheta axis"}; + TRandom* rn = new TRandom(); void init(InitContext const&) { + rctChecker.init(rctCut.cfgEvtRCTFlagCheckerLabel, rctCut.cfgEvtRCTFlagCheckerZDCCheck, rctCut.cfgEvtRCTFlagCheckerLimitAcceptAsBad); // Axes - AxisSpec vertexZAxis = {nBins, -15., 15., "vrtx_{Z} [cm] for plots"}; - AxisSpec ptAxis = {nBinspT, pTbinlow, pTbinhigh, "#it{p}_{T} (GeV/#it{c})"}; - AxisSpec invmassAxis = {nBinsinvMass, invMassbinlow, invMassbinhigh, "Invariant mass (GeV/#it{c}^{2})"}; + AxisSpec vertexZAxis = {60, -15., 15., "vrtx_{Z} [cm] for plots"}; + AxisSpec ptAxis = {ptAxisKstar, "#it{p}_{T} (GeV/#it{c})"}; + AxisSpec invmassAxis = {invMassKstarAxis, "Invariant mass (GeV/#it{c}^{2})"}; AxisSpec thnAxisPOL{configThnAxisPOL, "cos(#theta)"}; + AxisSpec multiplicityAxis = {binsMultPlot, "Multiplicity Axis"}; // Histograms // Event selection rEventSelection.add("hVertexZRec", "hVertexZRec", {HistType::kTH1F, {vertexZAxis}}); - rEventSelection.add("hmult", "Multiplicity percentile", kTH1F, {{binsMultPlot}}); + rEventSelection.add("hMultiplicity", "Multiplicity percentile", kTH1F, {{110, 0, 110}}); - // for primary tracks + // for primary tracksbinsMultPlot if (cQAplots) { hOthers.add("dE_by_dx_TPC", "dE/dx signal in the TPC as a function of pT", kTH2F, {axisPtfordEbydx, axisdEdx}); hOthers.add("hphi", "Phi distribution", kTH1F, {{65, 0, 6.5}}); @@ -155,45 +166,47 @@ struct Kstarqa { 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}}); - hPID.add("Before/hNsigmaTPC_Ka_before", "N #sigma Kaon TPC before", kTH2F, {{100, 0.0f, 10.0f}, {200, -10.0f, 10.0f}}); - hPID.add("Before/hNsigmaTOF_Ka_before", "N #sigma Kaon TOF before", kTH2F, {{100, 0.0f, 10.0f}, {200, -10.0f, 10.0f}}); - hPID.add("Before/hNsigmaTPC_Pi_before", "N #sigma Pion TPC before", kTH2F, {{100, 0.0f, 10.0f}, {200, -10.0f, 10.0f}}); - hPID.add("Before/hNsigmaTOF_Pi_before", "N #sigma Pion TOF before", kTH2F, {{100, 0.0f, 10.0f}, {200, -10.0f, 10.0f}}); - hPID.add("Before/hNsigma_TPC_TOF_Ka_before", "N #sigma Kaon TOF before", kTH2F, {{100, -5.0f, 5.0f}, {100, -5.0f, 5.0f}}); - hPID.add("Before/hNsigma_TPC_TOF_Pi_before", "N #sigma Pion TOF before", kTH2F, {{100, -5.0f, 5.0f}, {100, -5.0f, 5.0f}}); - hPID.add("h1PID_TPC_kaon_data", "Kaon PID distribution in data", kTH1F, {{100, -10.0f, 10.0f}}); - hPID.add("h1PID_TPC_pion_data", "Pion PID distribution in data", kTH1F, {{100, -10.0f, 10.0f}}); - hPID.add("h1PID_TPC_kaon_MC", "Kaon PID distribution in MC", kTH1F, {{100, -10.0f, 10.0f}}); - hPID.add("h1PID_TPC_pion_MC", "Pion PID distribution in MC", kTH1F, {{100, -10.0f, 10.0f}}); - hPID.add("h1PID_TOF_kaon_data", "Kaon PID distribution in data", kTH1F, {{100, -10.0f, 10.0f}}); - hPID.add("h1PID_TOF_pion_data", "Pion PID distribution in data", kTH1F, {{100, -10.0f, 10.0f}}); - hPID.add("h1PID_TOF_kaon_MC", "Kaon PID distribution in MC", kTH1F, {{100, -10.0f, 10.0f}}); - hPID.add("h1PID_TOF_pion_MC", "Pion PID distribution in MC", kTH1F, {{100, -10.0f, 10.0f}}); - - hPID.add("After/hNsigmaPionTPC_after", "N #Pi TPC after", kTH2F, {{100, 0.0f, 10.0f}, {200, -10.0f, 10.0f}}); - hPID.add("After/hNsigmaPionTOF_after", "N #Pi TOF after", kTH2F, {{100, 0.0f, 10.0f}, {200, -10.0f, 10.0f}}); - hPID.add("After/hNsigmaKaonTPC_after", "N #sigma Kaon TPC after", kTH2F, {{100, 0.0f, 10.0f}, {200, -10.0f, 10.0f}}); - hPID.add("After/hNsigmaKaonTOF_after", "N #sigma Kaon TOF after", kTH2F, {{100, 0.0f, 10.0f}, {200, -10.0f, 10.0f}}); - hPID.add("After/hNsigma_TPC_TOF_Ka_after", "N #sigma Kaon TOF after", kTH2F, {{100, -5.0f, 5.0f}, {100, -5.0f, 5.0f}}); - hPID.add("After/hNsigma_TPC_TOF_Pi_after", "N #sigma Pion TOF after", kTH2F, {{100, -5.0f, 5.0f}, {100, -5.0f, 5.0f}}); + hPID.add("Before/hNsigmaTPC_Ka_before", "N #sigma Kaon TPC before", kTH2F, {{50, 0.0f, 10.0f}, {100, -10.0f, 10.0f}}); + hPID.add("Before/hNsigmaTOF_Ka_before", "N #sigma Kaon TOF before", kTH2F, {{50, 0.0f, 10.0f}, {100, -10.0f, 10.0f}}); + hPID.add("Before/hNsigmaTPC_Pi_before", "N #sigma Pion TPC before", kTH2F, {{50, 0.0f, 10.0f}, {100, -10.0f, 10.0f}}); + hPID.add("Before/hNsigmaTOF_Pi_before", "N #sigma Pion TOF before", kTH2F, {{50, 0.0f, 10.0f}, {100, -10.0f, 10.0f}}); + hPID.add("Before/hNsigma_TPC_TOF_Ka_before", "N #sigma Kaon TOF before", kTH2F, {{50, -5.0f, 5.0f}, {50, -5.0f, 5.0f}}); + hPID.add("Before/hNsigma_TPC_TOF_Pi_before", "N #sigma Pion TOF before", kTH2F, {{50, -5.0f, 5.0f}, {50, -5.0f, 5.0f}}); + + hPID.add("Before/h1PID_TPC_pos_kaon", "Kaon PID distribution in data", kTH1F, {{100, -10.0f, 10.0f}}); + hPID.add("Before/h1PID_TPC_pos_pion", "Pion PID distribution in data", kTH1F, {{100, -10.0f, 10.0f}}); + hPID.add("Before/h1PID_TOF_pos_kaon", "Kaon PID distribution in data", kTH1F, {{100, -10.0f, 10.0f}}); + hPID.add("Before/h1PID_TOF_pos_pion", "Pion PID distribution in data", kTH1F, {{100, -10.0f, 10.0f}}); + hPID.add("Before/h1PID_TPC_neg_kaon", "Kaon PID distribution in data", kTH1F, {{100, -10.0f, 10.0f}}); + hPID.add("Before/h1PID_TPC_neg_pion", "Pion PID distribution in data", kTH1F, {{100, -10.0f, 10.0f}}); + hPID.add("Before/h1PID_TOF_neg_kaon", "Kaon PID distribution in data", kTH1F, {{100, -10.0f, 10.0f}}); + hPID.add("Before/h1PID_TOF_neg_pion", "Pion PID distribution in data", kTH1F, {{100, -10.0f, 10.0f}}); + + hPID.add("After/hNsigmaPionTPC_after", "N #Pi TPC after", kTH2F, {{50, 0.0f, 10.0f}, {100, -10.0f, 10.0f}}); + hPID.add("After/hNsigmaPionTOF_after", "N #Pi TOF after", kTH2F, {{50, 0.0f, 10.0f}, {100, -10.0f, 10.0f}}); + hPID.add("After/hNsigmaKaonTPC_after", "N #sigma Kaon TPC after", kTH2F, {{50, 0.0f, 10.0f}, {100, -10.0f, 10.0f}}); + hPID.add("After/hNsigmaKaonTOF_after", "N #sigma Kaon TOF after", kTH2F, {{50, 0.0f, 10.0f}, {100, -10.0f, 10.0f}}); + hPID.add("After/hNsigma_TPC_TOF_Ka_after", "N #sigma Kaon TOF after", kTH2F, {{50, -5.0f, 5.0f}, {50, -5.0f, 5.0f}}); + hPID.add("After/hNsigma_TPC_TOF_Pi_after", "N #sigma Pion TOF after", kTH2F, {{50, -5.0f, 5.0f}, {50, -5.0f, 5.0f}}); } // KStar histograms - hInvMass.add("h3KstarInvMassUnlikeSign", "kstar Unlike Sign", kTHnSparseF, {binsMultPlot, ptAxis, invmassAxis, thnAxisPOL}); - hInvMass.add("h3KstarInvMassMixed", "kstar Mixed", kTHnSparseF, {binsMultPlot, ptAxis, invmassAxis, thnAxisPOL}); + hInvMass.add("h3KstarInvMassUnlikeSign", "kstar Unlike Sign", kTHnSparseF, {multiplicityAxis, ptAxis, invmassAxis, thnAxisPOL}); + hInvMass.add("h3KstarInvMassMixed", "kstar Mixed", kTHnSparseF, {multiplicityAxis, ptAxis, invmassAxis, thnAxisPOL}); if (calcLikeSign) - hInvMass.add("h3KstarInvMasslikeSign", "kstar like Sign", kTHnSparseF, {binsMultPlot, ptAxis, invmassAxis, thnAxisPOL}); + hInvMass.add("h3KstarInvMasslikeSign", "kstar like Sign", kTHnSparseF, {multiplicityAxis, ptAxis, invmassAxis, thnAxisPOL}); if (calcRotational) - hInvMass.add("h3KstarInvMassRotated", "kstar rotated", kTHnSparseF, {binsMultPlot, ptAxis, invmassAxis, thnAxisPOL}); + hInvMass.add("h3KstarInvMassRotated", "kstar rotated", kTHnSparseF, {multiplicityAxis, ptAxis, invmassAxis, thnAxisPOL}); - // MC generated histograms - hInvMass.add("hk892GenpT", "pT distribution of True MC K(892)0", kTH2F, {ptAxis, binsMultPlot}); - // hInvMass.add("hk892GenpTAnti", "pT distribution of True MC Anti-K(892)0", kTH2F, {ptAxis}, {binsMultPlot}); - // Reconstructed MC histogram + // MC histograms + hInvMass.add("hk892GenpT", "pT distribution of True MC K(892)0", kTHnSparseF, {ptAxis, multiplicityAxis}); + hInvMass.add("hk892GenpT2", "pT distribution of True MC K(892)0", kTHnSparseF, {ptAxis, multiplicityAxis}); hInvMass.add("h1KstarRecMass", "Invariant mass of kstar meson", kTH1F, {invmassAxis}); - hInvMass.add("h2KstarRecpt1", "pT of kstar meson", kTH2F, {ptAxis, binsMultPlot}); - hInvMass.add("h2KstarRecpt2", "pT of generated kstar meson", kTH2F, {ptAxis, binsMultPlot}); + hInvMass.add("h2KstarRecpt1", "pT of kstar meson", kTHnSparseF, {ptAxis, multiplicityAxis, invmassAxis}); + hInvMass.add("h2KstarRecpt2", "pT of generated kstar meson", kTHnSparseF, {ptAxis, multiplicityAxis}); hInvMass.add("h1genmass", "Invariant mass of generated kstar meson", kTH1F, {invmassAxis}); + hInvMass.add("h1GenMult", "Multiplicity generated", kTH1F, {multiplicityAxis}); + hInvMass.add("h1RecMult", "Multiplicity reconstructed", kTH1F, {multiplicityAxis}); rEventSelection.add("events_check_data", "No. of events in the data", kTH1I, {{20, 0, 20}}); rEventSelection.add("events_check", "No. of events in the generated MC", kTH1I, {{20, 0, 20}}); rEventSelection.add("events_checkrec", "No. of events in the reconstructed MC", kTH1I, {{20, 0, 20}}); @@ -205,8 +218,8 @@ struct Kstarqa { // hInvMass.add("multdist_FT0A", "FT0A Multiplicity distribution", kTH1F, {axisMultdist}); // hInvMass.add("multdist_FT0C", "FT0C Multiplicity distribution", kTH1F, {axisMultdist}); // hInvMass.add("hNcontributor", "Number of primary vertex contributor", kTH1F, {{2000, 0.0f, 10000.0f}}); - rEventSelection.add("hDcaxy", "Dcaxy distribution", kTH1F, {{200, -1.0f, 1.0f}}); - rEventSelection.add("hDcaz", "Dcaz distribution", kTH1F, {{200, -1.0f, 1.0f}}); + rEventSelection.add("hDcaxy", "Dcaxy distribution", kTH1F, {{50, -1.0f, 1.0f}}); + rEventSelection.add("hDcaz", "Dcaz distribution", kTH1F, {{50, -1.0f, 1.0f}}); } } @@ -417,124 +430,122 @@ struct Kstarqa { using TrackCandidatesMC = soa::Filtered>; //*********Varibles declaration*************** - TLorentzVector lv1, lv2, lv3, lv4, lv5; - float multiplicity = 0.0f; - float theta2; - ROOT::Math::PxPyPzMVector daughter1, daughter2, daughterSelected, fourVecDau1, fourVecMother, fourVecDauCM; - ROOT::Math::XYZVector threeVecDauCM, helicityVec, randomVec, beamVec, normalVec; + float multiplicity{-1.0}, theta2; + ROOT::Math::PxPyPzMVector daughter1, daughter2, daughterRot, mother, motherRot, daughterSelected, fourVecDauCM, daughterRotCM; + ROOT::Math::XYZVector randomVec, beamVec, normalVec; bool isMix = false; - template - void fillInvMass(const T1& track1, const T2& track2, const T3& lv2, const T4& lv3, float multiplicity, bool isMix) + template + void fillInvMass(const T1& daughter1, const T1& daughter2, const T1& mother, float multiplicity, bool isMix, const T2& track1, const T2& track2) { - daughter1 = ROOT::Math::PxPyPzMVector(track1.px(), track1.py(), track1.pz(), massKa); // Kaon - daughter2 = ROOT::Math::PxPyPzMVector(track2.px(), track2.py(), track2.pz(), massPi); // Pion - daughterSelected = (boostDaugter1) ? daughter1 : daughter2; - auto selectedDauMass = (boostDaugter1) ? massKa : massPi; - - // polarization calculations - - fourVecDau1 = ROOT::Math::PxPyPzMVector(daughterSelected.Px(), daughterSelected.Py(), daughterSelected.Pz(), selectedDauMass); // Kaon or Pion + daughterSelected = (boostDaugter1) ? daughter1 : daughter2; // polarization calculations + ROOT::Math::Boost boost{mother.BoostToCM()}; // boost mother to center of mass frame + fourVecDauCM = boost(daughterSelected); // boost the frame of daughter same as mother - fourVecMother = ROOT::Math::PxPyPzMVector(lv3.Px(), lv3.Py(), lv3.Pz(), lv3.M()); // mass of KshortKshort pair - ROOT::Math::Boost boost{fourVecMother.BoostToCM()}; // boost mother to center of mass frame - fourVecDauCM = boost(fourVecDau1); // boost the frame of daughter same as mother - threeVecDauCM = fourVecDauCM.Vect(); // get the 3 vector of daughter in the frame of mother - - if (std::abs(lv3.Rapidity()) < 0.5) { + if (std::abs(mother.Rapidity()) < 0.5) { if (activateTHnSparseCosThStarHelicity) { - helicityVec = fourVecMother.Vect(); // 3 vector of mother in COM frame - auto cosThetaStarHelicity = helicityVec.Dot(threeVecDauCM) / (std::sqrt(threeVecDauCM.Mag2()) * std::sqrt(helicityVec.Mag2())); + auto cosThetaStarHelicity = mother.Vect().Dot(fourVecDauCM.Vect()) / (std::sqrt(fourVecDauCM.Vect().Mag2()) * std::sqrt(mother.Vect().Mag2())); if (track1.sign() * track2.sign() < 0) { if (!isMix) { - hInvMass.fill(HIST("h3KstarInvMassUnlikeSign"), multiplicity, lv3.Pt(), lv3.M(), cosThetaStarHelicity); + hInvMass.fill(HIST("h3KstarInvMassUnlikeSign"), multiplicity, mother.Pt(), mother.M(), cosThetaStarHelicity); for (int i = 0; i < cRotations; i++) { theta2 = rn->Uniform(o2::constants::math::PI - o2::constants::math::PI / rotationalCut, o2::constants::math::PI + o2::constants::math::PI / rotationalCut); - lv4.SetPtEtaPhiM(track1.pt(), track1.eta(), track1.phi() + theta2, massKa); // for rotated background - lv5 = lv2 + lv4; + + 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); + + auto cosThetaStarHelicityRot = motherRot.Vect().Dot(daughterRotCM.Vect()) / (std::sqrt(daughterRotCM.Vect().Mag2()) * std::sqrt(motherRot.Vect().Mag2())); + if (calcRotational) - hInvMass.fill(HIST("h3KstarInvMassRotated"), multiplicity, lv5.Pt(), lv5.M(), cosThetaStarHelicity); + hInvMass.fill(HIST("h3KstarInvMassRotated"), multiplicity, motherRot.Pt(), motherRot.M(), cosThetaStarHelicityRot); } } else { - hInvMass.fill(HIST("h3KstarInvMassMixed"), multiplicity, lv3.Pt(), lv3.M(), cosThetaStarHelicity); + hInvMass.fill(HIST("h3KstarInvMassMixed"), multiplicity, mother.Pt(), mother.M(), cosThetaStarHelicity); } } else { if (!isMix) { if (calcLikeSign) - hInvMass.fill(HIST("h3KstarInvMasslikeSign"), multiplicity, lv3.Pt(), lv3.M(), cosThetaStarHelicity); + hInvMass.fill(HIST("h3KstarInvMasslikeSign"), multiplicity, mother.Pt(), mother.M(), cosThetaStarHelicity); } } } else if (activateTHnSparseCosThStarProduction) { - normalVec = ROOT::Math::XYZVector(lv3.Py(), -lv3.Px(), 0.f); - auto cosThetaStarProduction = normalVec.Dot(threeVecDauCM) / (std::sqrt(threeVecDauCM.Mag2()) * std::sqrt(normalVec.Mag2())); + normalVec = ROOT::Math::XYZVector(mother.Py(), -mother.Px(), 0.f); + auto cosThetaStarProduction = normalVec.Dot(fourVecDauCM.Vect()) / (std::sqrt(fourVecDauCM.Vect().Mag2()) * std::sqrt(normalVec.Mag2())); if (track1.sign() * track2.sign() < 0) { if (!isMix) { - hInvMass.fill(HIST("h3KstarInvMassUnlikeSign"), multiplicity, lv3.Pt(), lv3.M(), cosThetaStarProduction); + hInvMass.fill(HIST("h3KstarInvMassUnlikeSign"), multiplicity, mother.Pt(), mother.M(), cosThetaStarProduction); for (int i = 0; i < cRotations; i++) { theta2 = rn->Uniform(0, o2::constants::math::PI); - lv4.SetPtEtaPhiM(track1.pt(), track1.eta(), track1.phi() + theta2, massKa); // for rotated background - lv5 = lv2 + lv4; + 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 (calcRotational) - hInvMass.fill(HIST("h3KstarInvMassRotated"), multiplicity, lv5.Pt(), lv5.M(), cosThetaStarProduction); + hInvMass.fill(HIST("h3KstarInvMassRotated"), multiplicity, motherRot.Pt(), motherRot.M(), cosThetaStarProduction); } } else { - hInvMass.fill(HIST("h3KstarInvMassMixed"), multiplicity, lv3.Pt(), lv3.M(), cosThetaStarProduction); + hInvMass.fill(HIST("h3KstarInvMassMixed"), multiplicity, mother.Pt(), mother.M(), cosThetaStarProduction); } } else { if (!isMix) { if (calcLikeSign) - hInvMass.fill(HIST("h3KstarInvMasslikeSign"), multiplicity, lv3.Pt(), lv3.M(), cosThetaStarProduction); + hInvMass.fill(HIST("h3KstarInvMasslikeSign"), multiplicity, mother.Pt(), mother.M(), cosThetaStarProduction); } } } else if (activateTHnSparseCosThStarBeam) { beamVec = ROOT::Math::XYZVector(0.f, 0.f, 1.f); - auto cosThetaStarBeam = beamVec.Dot(threeVecDauCM) / std::sqrt(threeVecDauCM.Mag2()); + auto cosThetaStarBeam = beamVec.Dot(fourVecDauCM.Vect()) / std::sqrt(fourVecDauCM.Vect().Mag2()); if (track1.sign() * track2.sign() < 0) { if (!isMix) { - hInvMass.fill(HIST("h3KstarInvMassUnlikeSign"), multiplicity, lv3.Pt(), lv3.M(), cosThetaStarBeam); + hInvMass.fill(HIST("h3KstarInvMassUnlikeSign"), multiplicity, mother.Pt(), mother.M(), cosThetaStarBeam); for (int i = 0; i < cRotations; i++) { theta2 = rn->Uniform(0, o2::constants::math::PI); - lv4.SetPtEtaPhiM(track1.pt(), track1.eta(), track1.phi() + theta2, massKa); // for rotated background - lv5 = lv2 + lv4; + 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 (calcRotational) - hInvMass.fill(HIST("h3KstarInvMassRotated"), multiplicity, lv5.Pt(), lv5.M(), cosThetaStarBeam); + hInvMass.fill(HIST("h3KstarInvMassRotated"), multiplicity, motherRot.Pt(), motherRot.M(), cosThetaStarBeam); } } else { - hInvMass.fill(HIST("h3KstarInvMassMixed"), multiplicity, lv3.Pt(), lv3.M(), cosThetaStarBeam); + hInvMass.fill(HIST("h3KstarInvMassMixed"), multiplicity, mother.Pt(), mother.M(), cosThetaStarBeam); } } else { if (calcLikeSign) - hInvMass.fill(HIST("h3KstarInvMasslikeSign"), multiplicity, lv3.Pt(), lv3.M(), cosThetaStarBeam); + hInvMass.fill(HIST("h3KstarInvMasslikeSign"), multiplicity, mother.Pt(), mother.M(), cosThetaStarBeam); } } else if (activateTHnSparseCosThStarRandom) { auto phiRandom = gRandom->Uniform(0.f, constants::math::TwoPI); auto thetaRandom = gRandom->Uniform(0.f, constants::math::PI); randomVec = ROOT::Math::XYZVector(std::sin(thetaRandom) * std::cos(phiRandom), std::sin(thetaRandom) * std::sin(phiRandom), std::cos(thetaRandom)); - auto cosThetaStarRandom = randomVec.Dot(threeVecDauCM) / std::sqrt(threeVecDauCM.Mag2()); + auto cosThetaStarRandom = randomVec.Dot(fourVecDauCM.Vect()) / std::sqrt(fourVecDauCM.Vect().Mag2()); if (track1.sign() * track2.sign() < 0) { if (!isMix) { - hInvMass.fill(HIST("h3KstarInvMassUnlikeSign"), multiplicity, lv3.Pt(), lv3.M(), cosThetaStarRandom); + hInvMass.fill(HIST("h3KstarInvMassUnlikeSign"), multiplicity, mother.Pt(), mother.M(), cosThetaStarRandom); for (int i = 0; i < cRotations; i++) { theta2 = rn->Uniform(0, o2::constants::math::PI); - lv4.SetPtEtaPhiM(track1.pt(), track1.eta(), track1.phi() + theta2, massKa); // for rotated background - lv5 = lv2 + lv4; + 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 (calcRotational) - hInvMass.fill(HIST("h3KstarInvMassRotated"), multiplicity, lv5.Pt(), lv5.M(), cosThetaStarRandom); + hInvMass.fill(HIST("h3KstarInvMassRotated"), multiplicity, motherRot.Pt(), motherRot.M(), cosThetaStarRandom); } } else { - hInvMass.fill(HIST("h3KstarInvMassMixed"), multiplicity, lv3.Pt(), lv3.M(), cosThetaStarRandom); + hInvMass.fill(HIST("h3KstarInvMassMixed"), multiplicity, mother.Pt(), mother.M(), cosThetaStarRandom); } } else { if (!isMix) { if (calcLikeSign) - hInvMass.fill(HIST("h3KstarInvMasslikeSign"), multiplicity, lv3.Pt(), lv3.M(), cosThetaStarRandom); + hInvMass.fill(HIST("h3KstarInvMasslikeSign"), multiplicity, mother.Pt(), mother.M(), cosThetaStarRandom); } } } @@ -556,19 +567,24 @@ struct Kstarqa { if (timFrameEvsel && (!collision.selection_bit(aod::evsel::kNoTimeFrameBorder) || !collision.selection_bit(aod::evsel::kNoITSROFrameBorder))) { return; } - rEventSelection.fill(HIST("events_check_data"), 2.5); if (!collision.sel8()) { return; } + rEventSelection.fill(HIST("events_check_data"), 2.5); + + if (rctCut.requireRCTFlagChecker && !rctChecker(collision)) { + return; + } rEventSelection.fill(HIST("events_check_data"), 3.5); + multiplicity = -1; multiplicity = collision.centFT0M(); // Fill the event counter if (cQAevents) { rEventSelection.fill(HIST("hVertexZRec"), collision.posZ()); - rEventSelection.fill(HIST("hmult"), multiplicity); + rEventSelection.fill(HIST("hMultiplicity"), multiplicity); rEventSelection.fill(HIST("multdist_FT0M"), collision.multFT0M()); // rEventSelection.fill(HIST("multdist_FT0A"), collision.multFT0A()); // rEventSelection.fill(HIST("multdist_FT0C"), collision.multFT0C()); @@ -576,6 +592,14 @@ struct Kstarqa { } for (const auto& [track1, track2] : combinations(CombinationsFullIndexPolicy(tracks, tracks))) { + if (!selectionTrack(track1)) { + continue; + } + if (!selectionTrack(track2)) { + continue; + } + rEventSelection.fill(HIST("events_check_data"), 4.5); + if (cQAplots) { hPID.fill(HIST("Before/hNsigmaTPC_Ka_before"), track1.pt(), track1.tpcNSigmaKa()); hPID.fill(HIST("Before/hNsigmaTOF_Ka_before"), track1.pt(), track1.tofNSigmaKa()); @@ -583,23 +607,24 @@ struct Kstarqa { hPID.fill(HIST("Before/hNsigmaTOF_Pi_before"), track2.pt(), track2.tofNSigmaPi()); hPID.fill(HIST("Before/hNsigma_TPC_TOF_Ka_before"), track1.tpcNSigmaKa(), track1.tofNSigmaKa()); hPID.fill(HIST("Before/hNsigma_TPC_TOF_Pi_before"), track2.tpcNSigmaPi(), track2.tofNSigmaPi()); - hPID.fill(HIST("h1PID_TPC_kaon_data"), track1.tpcNSigmaKa()); - hPID.fill(HIST("h1PID_TPC_pion_data"), track2.tpcNSigmaPi()); - hPID.fill(HIST("h1PID_TOF_kaon_data"), track1.tofNSigmaKa()); - hPID.fill(HIST("h1PID_TOF_pion_data"), track2.tofNSigmaPi()); hOthers.fill(HIST("hCRFC_before"), track1.tpcCrossedRowsOverFindableCls()); hOthers.fill(HIST("dE_by_dx_TPC"), track1.p(), track1.tpcSignal()); hOthers.fill(HIST("hphi"), track1.phi()); - } - rEventSelection.fill(HIST("events_check_data"), 4.5); - if (!selectionTrack(track1)) { - continue; - } - if (!selectionTrack(track2)) { - continue; + 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()); + } } + rEventSelection.fill(HIST("events_check_data"), 5.5); // if (counter < 1e4) // std::cout << "TOF beta value is " << track1.beta() << std::endl; @@ -650,12 +675,11 @@ struct Kstarqa { rEventSelection.fill(HIST("events_check_data"), 8.5); - lv3.SetPtEtaPhiM(0.0, 0.0, 0.0, 0.0); - lv1.SetPtEtaPhiM(track1.pt(), track1.eta(), track1.phi(), massKa); - lv2.SetPtEtaPhiM(track2.pt(), track2.eta(), track2.phi(), massPi); - lv3 = lv1 + lv2; + 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 isMix = false; - fillInvMass(track1, track2, lv2, lv3, multiplicity, isMix); + fillInvMass(daughter1, daughter2, mother, multiplicity, isMix, track1, track2); } } @@ -694,6 +718,13 @@ struct Kstarqa { return; } + if (rctCut.requireRCTFlagChecker && !rctChecker(c1)) { + continue; + } + if (rctCut.requireRCTFlagChecker && !rctChecker(c2)) { + continue; + } + multiplicity = c1.centFT0M(); for (const auto& [t1, t2] : o2::soa::combinations(o2::soa::CombinationsFullIndexPolicy(tracks1, tracks2))) { @@ -716,23 +747,17 @@ struct Kstarqa { // continue; // } - // TLorentzVector vKAON; - // vKAON.SetPtEtaPhiM(t1.pt(), t1.eta(), t1.phi(), massKa); - // TLorentzVector vPION; - // vPION.SetPtEtaPhiM(t2.pt(), t2.eta(), t2.phi(), massPi); - lv3.SetPtEtaPhiM(0.0, 0.0, 0.0, 0.0); - lv1.SetPtEtaPhiM(t1.pt(), t1.eta(), t1.phi(), massKa); - lv2.SetPtEtaPhiM(t2.pt(), t2.eta(), t2.phi(), massPi); + 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; // Kstar meson - // TLorentzVector kstar = vKAON + vPION; - lv3 = lv1 + lv2; isMix = true; // if (std::abs(kstar.Rapidity()) < 0.5) { // fillInvMass(t1, t2, vPION, kstar, multiplicity, isMix); - if (std::abs(lv3.Rapidity()) < 0.5) { - fillInvMass(t1, t2, lv2, lv3, multiplicity, isMix); + if (std::abs(mother.Rapidity()) < 0.5) { + fillInvMass(daughter1, daughter2, mother, multiplicity, isMix, t1, t2); } } } @@ -761,8 +786,7 @@ struct Kstarqa { std::vector selectedEvents(collisions.size()); int nevts = 0; - - multiplicity = 0; + multiplicity = -1.0; for (const auto& collision : collisions) { // if (!collision.sel8() || std::abs(collision.mcCollision().posZ()) > cutzvertex) { if (std::abs(collision.mcCollision().posZ()) > cutzvertex) { @@ -775,7 +799,11 @@ struct Kstarqa { if (cTVXEvsel && (!collision.selection_bit(aod::evsel::kIsTriggerTVX))) { continue; } + if (!collision.sel8()) { + continue; + } multiplicity = collision.centFT0M(); + hInvMass.fill(HIST("h1GenMult"), multiplicity); selectedEvents[nevts++] = collision.mcCollision_as().globalIndex(); } selectedEvents.resize(nevts); @@ -814,21 +842,19 @@ struct Kstarqa { rEventSelection.fill(HIST("events_check"), 8.5); if (std::abs(kCurrentDaughter.pdgCode()) == 321) { - // if (kCurrentDaughter.pdgCode() == +321) { passkaon = true; - rEventSelection.fill(HIST("events_check"), 9.5); + daughter1 = ROOT::Math::PxPyPzMVector(kCurrentDaughter.px(), kCurrentDaughter.py(), kCurrentDaughter.pz(), massKa); } else if (std::abs(kCurrentDaughter.pdgCode()) == 211) { - //} else if (kCurrentDaughter.pdgCode() == -321) { passpion = true; - // rEventSelection.fill(HIST("events_check"), 10.5); + daughter2 = ROOT::Math::PxPyPzMVector(kCurrentDaughter.px(), kCurrentDaughter.py(), kCurrentDaughter.pz(), massPi); } } if (passkaon && passpion) { - // if (mcParticle.pdgCode() > 0) + mother = daughter1 + daughter2; // Kstar meson hInvMass.fill(HIST("hk892GenpT"), mcParticle.pt(), multiplicity); - // else - // hInvMass.fill(HIST("hk892GenpTAnti"), mcParticle.pt()); + hInvMass.fill(HIST("hk892GenpT2"), mother.Pt(), multiplicity); + hInvMass.fill(HIST("h1genmass"), mother.M()); } } } @@ -837,9 +863,6 @@ struct Kstarqa { void processRec(EventCandidatesMC::iterator const& collision, TrackCandidatesMC const& tracks, aod::McParticles const&, aod::McCollisions const& /*mcCollisions*/) { - // TLorentzVector lDecayDaughter1, lDecayDaughter2, lResonance; - multiplicity = collision.centFT0M(); - rEventSelection.fill(HIST("events_checkrec"), 0.5); if (!collision.has_mcCollision()) { @@ -863,6 +886,12 @@ struct Kstarqa { } rEventSelection.fill(HIST("events_checkrec"), 4.5); + if (!collision.sel8()) { + return; + } + multiplicity = collision.centFT0M(); + hInvMass.fill(HIST("h1RecMult"), multiplicity); + auto oldindex = -999; for (const auto& track1 : tracks) { if (!selectionTrack(track1)) { @@ -903,13 +932,21 @@ struct Kstarqa { int track1PDG = std::abs(mctrack1.pdgCode()); int track2PDG = std::abs(mctrack2.pdgCode()); - if (cQAplots && track1PDG == 211) { - hPID.fill(HIST("h1PID_TPC_kaon_MC"), track1.tpcNSigmaKa()); - hPID.fill(HIST("h1PID_TOF_kaon_MC"), track1.tofNSigmaKa()); + if (cQAplots && (mctrack1.pdgCode() == 211 || mctrack2.pdgCode() == 211)) { // pion + hPID.fill(HIST("Before/h1PID_TPC_pos_pion"), track2.tpcNSigmaPi()); + hPID.fill(HIST("Before/h1PID_TOF_pos_pion"), track2.tofNSigmaPi()); + } + if (cQAplots && (mctrack1.pdgCode() == 321 || mctrack2.pdgCode() == 321)) { // kaon + hPID.fill(HIST("Before/h1PID_TPC_pos_kaon"), track2.tpcNSigmaKa()); + hPID.fill(HIST("Before/h1PID_TOF_pos_kaon"), track2.tofNSigmaKa()); } - if (cQAplots && track1PDG == 321) { - hPID.fill(HIST("h1PID_TPC_pion_MC"), track1.tpcNSigmaPi()); - hPID.fill(HIST("h1PID_TOF_pion_MC"), track1.tofNSigmaPi()); + if (cQAplots && (mctrack1.pdgCode() == -211 || mctrack2.pdgCode() == -211)) { // negative track pion + hPID.fill(HIST("Before/h1PID_TPC_neg_pion"), track1.tpcNSigmaPi()); + hPID.fill(HIST("Before/h1PID_TOF_neg_pion"), track1.tofNSigmaPi()); + } + if (cQAplots && (mctrack1.pdgCode() == -321 || mctrack2.pdgCode() == -321)) { // negative track kaon + hPID.fill(HIST("Before/h1PID_TPC_neg_kaon"), track1.tpcNSigmaKa()); + hPID.fill(HIST("Before/h1PID_TOF_neg_kaon"), track1.tofNSigmaKa()); } if (!mctrack1.isPhysicalPrimary()) { @@ -925,23 +962,13 @@ struct Kstarqa { // if (!(track1PDG == 321 && track2PDG == 211)) { // continue; // } - if (!(track1PDG == 211) && !(track1PDG == 321)) { + if ((track1PDG != 211) && (track1PDG != 321)) { continue; } - if (!(track2PDG == 211) && !(track2PDG == 321)) { + if ((track2PDG != 211) && (track2PDG != 321)) { continue; } rEventSelection.fill(HIST("events_checkrec"), 13.5); - - if (track1PDG == 211) { - if (!(selectionPID(track1, 0) && selectionPID(track2, 1))) { // pion and kaon - continue; - } - } else { - if (!(selectionPID(track1, 1) && selectionPID(track2, 0))) { // kaon and pion - continue; - } - } rEventSelection.fill(HIST("events_checkrec"), 14.5); for (const auto& mothertrack1 : mctrack1.mothers_as()) { @@ -970,28 +997,34 @@ struct Kstarqa { continue; } + if (track1PDG == 211) { + if (!(selectionPID(track1, 0) && selectionPID(track2, 1))) { // pion and kaon + continue; + } + } else { + if (!(selectionPID(track1, 1) && selectionPID(track2, 0))) { // kaon and pion + continue; + } + } + if (avoidsplitrackMC && oldindex == mothertrack1.globalIndex()) { hInvMass.fill(HIST("h1KSRecsplit"), mothertrack1.pt()); continue; } oldindex = mothertrack1.globalIndex(); - pvec0 = std::array{track1.px(), track1.py(), track1.pz()}; - pvec1 = std::array{track2.px(), track2.py(), track2.pz()}; - auto arrMomrec = std::array{pvec0, pvec1}; - auto motherP = mothertrack1.p(); - auto motherE = mothertrack1.e(); - auto genMass = std::sqrt(motherE * motherE - motherP * motherP); - auto recMass = RecoDecay::m(arrMomrec, std::array{massKa, massPi}); - auto recpt = std::sqrt((track1.px() + track2.px()) * (track1.px() + track2.px()) + (track1.py() + track2.py()) * (track1.py() + track2.py())); - //// Resonance reconstruction - // lDecayDaughter1.SetXYZM(track1.px(), track1.py(), track1.pz(), massKa); - // lDecayDaughter2.SetXYZM(track2.px(), track2.py(), track2.pz(), massPi); - // lResonance = lDecayDaughter1 + lDecayDaughter2; - - hInvMass.fill(HIST("h1KstarRecMass"), recMass); - hInvMass.fill(HIST("h1genmass"), genMass); - hInvMass.fill(HIST("h2KstarRecpt1"), mothertrack1.pt(), multiplicity); - hInvMass.fill(HIST("h2KstarRecpt2"), recpt, multiplicity); + if (track1.sign() * track2.sign() < 0) { + 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.Rapidity() >= 0) { + continue; + } + + hInvMass.fill(HIST("h1KstarRecMass"), mother.M()); + hInvMass.fill(HIST("h2KstarRecpt1"), mother.Pt(), multiplicity, mother.M()); + hInvMass.fill(HIST("h2KstarRecpt2"), mothertrack1.pt(), multiplicity); + } } } } From 96475a29412de6dcff08a44cd271587b3ab734d6 Mon Sep 17 00:00:00 2001 From: ddobrigk Date: Mon, 30 Jun 2025 22:17:38 +0200 Subject: [PATCH 278/871] [Common] fix bc_as bug (#11848) --- Common/Tools/EventSelectionTools.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Common/Tools/EventSelectionTools.h b/Common/Tools/EventSelectionTools.h index c04b2f51b62..31a2b48b062 100644 --- a/Common/Tools/EventSelectionTools.h +++ b/Common/Tools/EventSelectionTools.h @@ -731,7 +731,7 @@ class EventSelectionModule return; // dummy process } for (const auto& col : collisions) { - auto bc = col.template bc_as>(); + auto bc = col.template bc_as>(); uint64_t timestamp = timestamps[bc.globalIndex()]; EventSelectionParams* par = ccdb->template getForTimeStamp("EventSelection/EventSelectionParams", timestamp); bool* applySelection = par->getSelection(evselOpts.muonSelection); @@ -837,7 +837,7 @@ class EventSelectionModule if (mapGlobalBcWithTVX.size() == 0) { LOGP(error, "FT0 table is empty or corrupted. Filling evsel table with dummy values"); for (const auto& col : cols) { - auto bc = col.template bc_as>(); + auto bc = col.template bc_as>(); int32_t foundBC = bc.globalIndex(); int32_t foundFT0 = bcselbuffer[bc.globalIndex()].foundFT0Id; int32_t foundFV0 = bcselbuffer[bc.globalIndex()].foundFV0Id; @@ -877,7 +877,7 @@ class EventSelectionModule // first loop to match collisions to TVX, also extract other per-collision information for further use for (const auto& col : cols) { int32_t colIndex = col.globalIndex(); - auto bc = col.template bc_as>(); + auto bc = col.template bc_as>(); vCollVz[colIndex] = col.posZ(); @@ -977,7 +977,7 @@ class EventSelectionModule if (vIsVertexTPC[colIndex] > 0 && vIsVertexTOF[colIndex] == 0 && vIsVertexHighPtTPC[colIndex] == 0) { float weightedTime = vWeightedTimesTPCnoTOFnoTRD[colIndex]; float weightedSigma = vWeightedSigmaTPCnoTOFnoTRD[colIndex]; - auto bc = col.template bc_as>(); + auto bc = col.template bc_as>(); int64_t globalBC = bc.globalBC(); int64_t meanBC = globalBC + TMath::Nint(weightedTime / bcNS); int64_t sigmaBC = TMath::CeilNint(weightedSigma / bcNS); From f24eb756bf639a6650d13a93e37625a7b14250fe Mon Sep 17 00:00:00 2001 From: Daiki Sekihata Date: Mon, 30 Jun 2025 23:07:37 +0200 Subject: [PATCH 279/871] [PWGEM/Dilepton] add a task to produce derived data for primary track (#11849) --- PWGEM/Dilepton/DataModel/dileptonTables.h | 41 +- PWGEM/Dilepton/DataModel/lmeeMLTables.h | 4 +- PWGEM/Dilepton/TableProducer/CMakeLists.txt | 5 + PWGEM/Dilepton/TableProducer/filterEoI.cxx | 15 +- .../TableProducer/skimmerPrimaryElectron.cxx | 2 +- .../TableProducer/skimmerPrimaryTrack.cxx | 417 ++++++++++++++++++ .../treeCreatorElectronMLDDA.cxx | 6 +- 7 files changed, 471 insertions(+), 19 deletions(-) create mode 100644 PWGEM/Dilepton/TableProducer/skimmerPrimaryTrack.cxx diff --git a/PWGEM/Dilepton/DataModel/dileptonTables.h b/PWGEM/Dilepton/DataModel/dileptonTables.h index 244d5ada6cc..7da56ec4255 100644 --- a/PWGEM/Dilepton/DataModel/dileptonTables.h +++ b/PWGEM/Dilepton/DataModel/dileptonTables.h @@ -9,17 +9,19 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#include -#include -#include #include "Common/Core/RecoDecay.h" -#include "Framework/AnalysisDataModel.h" -#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" #include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/PIDResponse.h" #include "Common/DataModel/Qvectors.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include "Framework/AnalysisDataModel.h" + +#include +#include +#include #ifndef PWGEM_DILEPTON_DATAMODEL_DILEPTONTABLES_H_ #define PWGEM_DILEPTON_DATAMODEL_DILEPTONTABLES_H_ @@ -641,6 +643,31 @@ DECLARE_SOA_TABLE(EMGlobalMuonSelfIds, "AOD", "EMGLMUSELFID", emprimarymuon::Glo // iterators using EMGlobalMuonSelfId = EMGlobalMuonSelfIds::iterator; +DECLARE_SOA_TABLE_VERSIONED(EMPrimaryTracks_000, "AOD", "EMPRIMARYTRACK", 0, //! + o2::soa::Index<>, emprimaryelectron::CollisionId, + emprimaryelectron::TrackId, emprimaryelectron::Sign, + track::Pt, track::Eta, track::Phi, track::DcaXY, track::DcaZ, + track::TPCNClsFindable, track::TPCNClsFindableMinusFound, track::TPCNClsFindableMinusCrossedRows, track::TPCNClsShared, track::TPCChi2NCl, + track::ITSClusterSizes, track::ITSChi2NCl, track::DetectorMap, + + // dynamic column + track::TPCNClsFound, + track::TPCNClsCrossedRows, + track::TPCCrossedRowsOverFindableCls, + track::TPCFoundOverFindableCls, + track::TPCFractionSharedCls, + track::v001::ITSClusterMap, track::v001::ITSNCls, track::v001::ITSNClsInnerBarrel, + track::HasITS, track::HasTPC, track::HasTRD, track::HasTOF, + emprimaryelectron::Signed1Pt, + emprimaryelectron::P, + emprimaryelectron::Px, + emprimaryelectron::Py, + emprimaryelectron::Pz); + +using EMPrimaryTracks = EMPrimaryTracks_000; +// iterators +using EMPrimaryTrack = EMPrimaryTracks::iterator; + // Dummy data for MC namespace emdummydata { diff --git a/PWGEM/Dilepton/DataModel/lmeeMLTables.h b/PWGEM/Dilepton/DataModel/lmeeMLTables.h index bf90ace9b7b..147729b238f 100644 --- a/PWGEM/Dilepton/DataModel/lmeeMLTables.h +++ b/PWGEM/Dilepton/DataModel/lmeeMLTables.h @@ -85,7 +85,7 @@ DECLARE_SOA_DYNAMIC_COLUMN(MeanClusterSizeITSob, meanClusterSizeITSob, [](uint32 } // namespace emprimarytrack // reconstructed track information -DECLARE_SOA_TABLE(EMPrimaryTracks, "AOD", "EMPTRACK", //! +DECLARE_SOA_TABLE(EMMLPrimaryTracks, "AOD", "EMMLPTRACK", //! o2::soa::Index<>, collision::NumContrib, evsel::NumTracksInTimeRange, evsel::SumAmpFT0CInTimeRange, track::Pt, track::Eta, track::Phi, track::Tgl, emprimarytrack::Sign, track::DcaXY, track::DcaZ, track::CYY, track::CZZ, track::CZY, @@ -101,7 +101,7 @@ DECLARE_SOA_TABLE(EMPrimaryTracks, "AOD", "EMPTRACK", //! emprimarytrack::MeanClusterSizeITSob); // iterators -using EMPrimaryTrack = EMPrimaryTracks::iterator; +using EMMLPrimaryTrack = EMMLPrimaryTracks::iterator; } // namespace o2::aod diff --git a/PWGEM/Dilepton/TableProducer/CMakeLists.txt b/PWGEM/Dilepton/TableProducer/CMakeLists.txt index e756d0a9fc7..fd2d85bb04c 100644 --- a/PWGEM/Dilepton/TableProducer/CMakeLists.txt +++ b/PWGEM/Dilepton/TableProducer/CMakeLists.txt @@ -30,6 +30,11 @@ o2physics_add_dpl_workflow(skimmer-primary-muon PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::GlobalTracking COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(skimmer-primary-track + SOURCES skimmerPrimaryTrack.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(skimmer-secondary-electron SOURCES skimmerSecondaryElectron.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore diff --git a/PWGEM/Dilepton/TableProducer/filterEoI.cxx b/PWGEM/Dilepton/TableProducer/filterEoI.cxx index 9edaeb784dc..9e44960f7de 100644 --- a/PWGEM/Dilepton/TableProducer/filterEoI.cxx +++ b/PWGEM/Dilepton/TableProducer/filterEoI.cxx @@ -14,12 +14,13 @@ // This code filters events that are interesting for dilepton analyses. // Please write to: daiki.sekihata@cern.ch -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.h" #include "PWGEM/Dilepton/DataModel/dileptonTables.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" + using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; @@ -31,6 +32,8 @@ struct filterEoI { kFwdMuon = 0x2, }; Produces emeoi; + Configurable minNElectrons{"minNElectrons", 1, "min number of e+ and e- at midrapidity"}; + Configurable minNMuons{"minNMuons", 1, "min number of mu+ and mu- at forward rapidity"}; HistogramRegistry fRegistry{"output"}; void init(o2::framework::InitContext&) @@ -57,14 +60,14 @@ struct filterEoI { if constexpr (static_cast(system & kElectron)) { auto electrons_coll = electrons.sliceBy(perCollision_el, collision.globalIndex()); - if (electrons_coll.size() > 0) { + if (electrons_coll.size() >= minNElectrons) { does_electron_exist = true; fRegistry.fill(HIST("hEventCounter"), 2); } } if constexpr (static_cast(system & kFwdMuon)) { auto muons_coll = muons.sliceBy(perCollision_mu, collision.globalIndex()); - if (muons_coll.size() > 0) { + if (muons_coll.size() >= minNMuons) { does_fwdmuon_exist = true; fRegistry.fill(HIST("hEventCounter"), 3); } diff --git a/PWGEM/Dilepton/TableProducer/skimmerPrimaryElectron.cxx b/PWGEM/Dilepton/TableProducer/skimmerPrimaryElectron.cxx index 39a5700db60..96bd1fec6e5 100644 --- a/PWGEM/Dilepton/TableProducer/skimmerPrimaryElectron.cxx +++ b/PWGEM/Dilepton/TableProducer/skimmerPrimaryElectron.cxx @@ -59,7 +59,7 @@ using MyTrackMC = MyTracksMC::iterator; struct skimmerPrimaryElectron { SliceCache cache; - Preslice perCol = o2::aod::track::collisionId; + Preslice perCol = o2::aod::track::collisionId; Produces emprimaryelectrons; Produces emprimaryelectronscov; diff --git a/PWGEM/Dilepton/TableProducer/skimmerPrimaryTrack.cxx b/PWGEM/Dilepton/TableProducer/skimmerPrimaryTrack.cxx new file mode 100644 index 00000000000..93cbd031f88 --- /dev/null +++ b/PWGEM/Dilepton/TableProducer/skimmerPrimaryTrack.cxx @@ -0,0 +1,417 @@ +// 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 tracks. +/// \author daiki.sekihata@cern.ch + +#include "PWGEM/Dilepton/DataModel/dileptonTables.h" +#include "PWGEM/Dilepton/Utils/PairUtilities.h" + +#include "Common/Core/TableHelper.h" +#include "Common/Core/trackUtilities.h" +#include "Common/DataModel/CollisionAssociationTables.h" +#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/PIDResponseITS.h" + +#include "CCDB/BasicCCDBManager.h" +#include "CommonConstants/PhysicsConstants.h" +#include "DataFormatsCalibration/MeanVertexObject.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "DataFormatsParameters/GRPObject.h" +#include "DetectorsBase/GeometryManager.h" +#include "DetectorsBase/Propagator.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" + +#include "Math/Vector4D.h" + +#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 MyCollisions = soa::Join; +using MyCollisionsWithSWT = soa::Join; + +using MyTracks = soa::Join; +using MyTrack = MyTracks::iterator; +using MyTracksMC = soa::Join; +using MyTrackMC = MyTracksMC::iterator; + +struct skimmerPrimaryTrack { + SliceCache cache; + Preslice perCol = o2::aod::track::collisionId; + Produces emprimarytracks; + + // Configurables + 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 mVtxPath{"mVtxPath", "GLO/Calib/MeanVertex", "Path of the mean vertex file"}; + Configurable skipGRPOquery{"skipGRPOquery", true, "skip grpo query"}; + + // Operation and minimisation criteria + Configurable fillQAHistogram{"fillQAHistogram", false, "flag to fill QA histograms"}; + Configurable d_bz_input{"d_bz_input", -999, "bz field in kG, -999 is automatic"}; + Configurable min_ncluster_tpc{"min_ncluster_tpc", 0, "min ncluster tpc"}; + Configurable mincrossedrows{"mincrossedrows", 70, "min. crossed rows"}; + Configurable min_tpc_cr_findable_ratio{"min_tpc_cr_findable_ratio", 0.8, "min. TPC Ncr/Nf ratio"}; + Configurable min_ncluster_its{"min_ncluster_its", 4, "min ncluster its"}; + Configurable min_ncluster_itsib{"min_ncluster_itsib", 1, "min ncluster itsib"}; + Configurable maxchi2tpc{"maxchi2tpc", 5.0, "max. chi2/NclsTPC"}; + Configurable maxchi2its{"maxchi2its", 36.0, "max. chi2/NclsITS"}; + Configurable minpt{"minpt", 0.15, "min pt for ITS-TPC track"}; + Configurable maxeta{"maxeta", 2.0, "eta acceptance"}; + Configurable dca_xy_max{"dca_xy_max", 1.0, "max DCAxy in cm"}; + Configurable dca_z_max{"dca_z_max", 1.0, "max DCAz in cm"}; + Configurable dca_3d_sigma_max{"dca_3d_sigma_max", 1e+10, "max DCA 3D in sigma"}; + Configurable max_frac_shared_clusters_tpc{"max_frac_shared_clusters_tpc", 999.f, "max fraction of shared clusters in TPC"}; + + HistogramRegistry fRegistry{"output", {}, OutputObjHandlingPolicy::AnalysisObject, false, false}; + + int mRunNumber; + float d_bz; + Service ccdb; + // o2::base::Propagator::MatCorrType matCorr = o2::base::Propagator::MatCorrType::USEMatCorrNONE; + 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; + + void init(InitContext&) + { + mRunNumber = 0; + d_bz = 0; + + ccdb->setURL(ccdburl); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + ccdb->setFatalWhenNull(false); + + if (fillQAHistogram) { + fRegistry.add("Track/hPt", "pT;p_{T} (GeV/c)", kTH1F, {{1000, 0.0f, 10}}, false); + fRegistry.add("Track/hQoverPt", "q/pT;q/p_{T} (GeV/c)^{-1}", kTH1F, {{4000, -20, 20}}, false); + fRegistry.add("Track/hEtaPhi", "#eta vs. #varphi;#varphi (rad.);#eta", kTH2F, {{90, 0, 2 * M_PI}, {80, -2.0f, 2.0f}}, false); + fRegistry.add("Track/hDCAxyz", "DCA xy vs. z;DCA_{xy} (cm);DCA_{z} (cm)", kTH2F, {{200, -1.0f, 1.0f}, {200, -1.0f, 1.0f}}, false); + fRegistry.add("Track/hDCAxyzSigma", "DCA xy vs. z;DCA_{xy} (#sigma);DCA_{z} (#sigma)", kTH2F, {{200, -10.0f, 10.0f}, {200, -10.0f, 10.0f}}, false); + fRegistry.add("Track/hDCAxyRes_Pt", "DCA_{xy} resolution vs. pT;p_{T} (GeV/c);DCA_{xy} resolution (#mum)", kTH2F, {{1000, 0, 10}, {500, 0., 500}}, false); + fRegistry.add("Track/hDCAzRes_Pt", "DCA_{z} resolution vs. pT;p_{T} (GeV/c);DCA_{z} resolution (#mum)", kTH2F, {{1000, 0, 10}, {500, 0., 500}}, false); + fRegistry.add("Track/hNclsTPC", "number of TPC clusters", kTH1F, {{161, -0.5, 160.5}}, false); + fRegistry.add("Track/hNcrTPC", "number of TPC crossed rows", kTH1F, {{161, -0.5, 160.5}}, false); + fRegistry.add("Track/hChi2TPC", "chi2/number of TPC clusters", kTH1F, {{100, 0, 10}}, false); + fRegistry.add("Track/hTPCNcr2Nf", "TPC Ncr/Nfindable", kTH1F, {{200, 0, 2}}, false); + fRegistry.add("Track/hTPCNcls2Nf", "TPC Ncls/Nfindable", kTH1F, {{200, 0, 2}}, false); + fRegistry.add("Track/hTPCNclsShared", "TPC Ncls shared/Ncls;p_{T} (GeV/c);N_{cls}^{shared}/N_{cls} in TPC", kTH2F, {{1000, 0, 10}, {100, 0, 1}}, false); + fRegistry.add("Track/hNclsITS", "number of ITS clusters", kTH1F, {{8, -0.5, 7.5}}, false); + fRegistry.add("Track/hChi2ITS", "chi2/number of ITS clusters", kTH1F, {{800, 0, 40}}, false); + fRegistry.add("Track/hITSClusterMap", "ITS cluster map", kTH1F, {{128, -0.5, 127.5}}, false); + fRegistry.add("Track/hTPCdEdx", "TPC dE/dx;p_{in} (GeV/c);TPC dE/dx (a.u.)", kTH2F, {{1000, 0, 10}, {200, 0, 200}}, false); + } + } + + void initCCDB(aod::BCsWithTimestamps::iterator 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(lutPath, bc.timestamp())); + } else { + LOG(info) << "Material look-up table already in place. Not reloading."; + } + + // In case override, don't proceed, please - no CCDB access required + if (d_bz_input > -990) { + d_bz = d_bz_input; + o2::parameters::GRPMagField grpmag; + if (std::fabs(d_bz) > 1e-5) { + grpmag.setL3Current(30000.f / (d_bz / 5.0f)); + } + o2::base::Propagator::initFieldFromGRP(&grpmag); + o2::base::Propagator::Instance()->setMatLUT(lut); + mMeanVtx = ccdb->getForTimeStamp(mVtxPath, bc.timestamp()); + mRunNumber = bc.runNumber(); + return; + } + + auto run3grp_timestamp = bc.timestamp(); + o2::parameters::GRPObject* grpo = 0x0; + o2::parameters::GRPMagField* grpmag = 0x0; + if (!skipGRPOquery) { + grpo = ccdb->getForTimeStamp(grpPath, run3grp_timestamp); + } + if (grpo) { + o2::base::Propagator::initFieldFromGRP(grpo); + o2::base::Propagator::Instance()->setMatLUT(lut); + mMeanVtx = ccdb->getForTimeStamp(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(grpmagPath, run3grp_timestamp); + if (!grpmag) { + LOG(fatal) << "Got nullptr from CCDB for path " << grpmagPath << " of object GRPMagField and " << grpPath << " of object GRPObject for timestamp " << run3grp_timestamp; + } + o2::base::Propagator::initFieldFromGRP(grpmag); + o2::base::Propagator::Instance()->setMatLUT(lut); + mMeanVtx = ccdb->getForTimeStamp(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(); + } + + template + bool checkTrack(TCollision const& collision, TTrack const& track) + { + if constexpr (isMC) { + if (!track.has_mcParticle()) { + return false; + } + } + + if (!track.hasITS() || !track.hasTPC()) { + return false; + } + + if (track.itsChi2NCl() > maxchi2its) { + return false; + } + if (track.itsNCls() < min_ncluster_its) { + return false; + } + if (track.itsNClsInnerBarrel() < min_ncluster_itsib) { + return false; + } + + if (track.tpcChi2NCl() > maxchi2tpc) { + return false; + } + + if (track.tpcNClsFound() < min_ncluster_tpc) { + return false; + } + + if (track.tpcNClsCrossedRows() < mincrossedrows) { + return false; + } + + if (track.tpcCrossedRowsOverFindableCls() < min_tpc_cr_findable_ratio) { + return false; + } + + if (track.tpcFractionSharedCls() > max_frac_shared_clusters_tpc) { + return false; + } + + o2::dataformats::DCA mDcaInfoCov; + mDcaInfoCov.set(999, 999, 999, 999, 999); + auto trackParCov = getTrackParCov(track); + trackParCov.setPID(track.pidForTracking()); + 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, trackParCov, 2.f, matCorr, &mDcaInfoCov); + float dcaXY = mDcaInfoCov.getY(); + float dcaZ = mDcaInfoCov.getZ(); + + if (std::fabs(dcaXY) > dca_xy_max || std::fabs(dcaZ) > dca_z_max) { + return false; + } + + float dca_3d = 999.f; + float det = trackParCov.getSigmaY2() * trackParCov.getSigmaZ2() - trackParCov.getSigmaZY() * trackParCov.getSigmaZY(); + if (det < 0) { + dca_3d = 999.f; + } else { + float chi2 = (dcaXY * dcaXY * trackParCov.getSigmaZ2() + dcaZ * dcaZ * trackParCov.getSigmaY2() - 2. * dcaXY * dcaZ * trackParCov.getSigmaZY()) / det; + dca_3d = std::sqrt(std::fabs(chi2) / 2.); + } + if (dca_3d > dca_3d_sigma_max) { + return false; + } + + if (std::fabs(trackParCov.getEta()) > maxeta || trackParCov.getPt() < minpt) { + return false; + } + + return true; + } + + template + void fillTrackTable(TCollision const& collision, TTrack const& track) + { + if (std::find(stored_trackIds.begin(), stored_trackIds.end(), std::pair{collision.globalIndex(), track.globalIndex()}) == stored_trackIds.end()) { + o2::dataformats::DCA mDcaInfoCov; + mDcaInfoCov.set(999, 999, 999, 999, 999); + auto trackParCov = getTrackParCov(track); + trackParCov.setPID(track.pidForTracking()); + 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, trackParCov, 2.f, matCorr, &mDcaInfoCov); + float dcaXY = mDcaInfoCov.getY(); + float dcaZ = mDcaInfoCov.getZ(); + + float pt_recalc = trackParCov.getPt(); + float eta_recalc = trackParCov.getEta(); + float phi_recalc = trackParCov.getPhi(); + o2::math_utils::bringTo02Pi(phi_recalc); + + emprimarytracks(collision.globalIndex(), track.globalIndex(), track.sign(), + pt_recalc, eta_recalc, phi_recalc, dcaXY, dcaZ, + track.tpcNClsFindable(), track.tpcNClsFindableMinusFound(), track.tpcNClsFindableMinusCrossedRows(), track.tpcNClsShared(), track.tpcChi2NCl(), + track.itsClusterSizes(), track.itsChi2NCl(), track.detectorMap()); + + stored_trackIds.emplace_back(std::pair{collision.globalIndex(), track.globalIndex()}); + + if (fillQAHistogram) { + fRegistry.fill(HIST("Track/hPt"), pt_recalc); + fRegistry.fill(HIST("Track/hQoverPt"), track.sign() / pt_recalc); + fRegistry.fill(HIST("Track/hEtaPhi"), phi_recalc, eta_recalc); + fRegistry.fill(HIST("Track/hDCAxyz"), dcaXY, dcaZ); + fRegistry.fill(HIST("Track/hDCAxyzSigma"), dcaXY / std::sqrt(trackParCov.getSigmaY2()), dcaZ / std::sqrt(trackParCov.getSigmaZ2())); + fRegistry.fill(HIST("Track/hDCAxyRes_Pt"), pt_recalc, std::sqrt(trackParCov.getSigmaY2()) * 1e+4); // convert cm to um + fRegistry.fill(HIST("Track/hDCAzRes_Pt"), pt_recalc, std::sqrt(trackParCov.getSigmaZ2()) * 1e+4); // convert cm to um + fRegistry.fill(HIST("Track/hNclsITS"), track.itsNCls()); + fRegistry.fill(HIST("Track/hNclsTPC"), track.tpcNClsFound()); + fRegistry.fill(HIST("Track/hNcrTPC"), track.tpcNClsCrossedRows()); + fRegistry.fill(HIST("Track/hTPCNcr2Nf"), track.tpcCrossedRowsOverFindableCls()); + fRegistry.fill(HIST("Track/hTPCNcls2Nf"), track.tpcFoundOverFindableCls()); + fRegistry.fill(HIST("Track/hTPCNclsShared"), track.pt(), track.tpcFractionSharedCls()); + fRegistry.fill(HIST("Track/hChi2TPC"), track.tpcChi2NCl()); + fRegistry.fill(HIST("Track/hChi2ITS"), track.itsChi2NCl()); + fRegistry.fill(HIST("Track/hITSClusterMap"), track.itsClusterMap()); + fRegistry.fill(HIST("Track/hTPCdEdx"), track.tpcInnerParam(), track.tpcSignal()); + } + } + } + + Preslice trackIndicesPerCollision = aod::track_association::collisionId; + std::vector> stored_trackIds; + Filter trackFilter = o2::aod::track::itsChi2NCl < maxchi2its && o2::aod::track::tpcChi2NCl < maxchi2tpc && ncheckbit(aod::track::v001::detectorMap, (uint8_t)o2::aod::track::ITS) == true && ncheckbit(aod::track::v001::detectorMap, (uint8_t)o2::aod::track::TPC) == true; + using MyFilteredTracks = soa::Filtered; + + // ---------- for data ---------- + + void processRec(MyCollisions const& collisions, aod::BCsWithTimestamps const&, MyFilteredTracks const& tracks) + { + stored_trackIds.reserve(tracks.size()); + + for (const auto& collision : collisions) { + auto bc = collision.template foundBC_as(); + initCCDB(bc); + if (!collision.isSelected()) { + continue; + } + if (!collision.isEoI()) { // events with at least 1 lepton for data reduction. + continue; + } + + auto tracks_per_coll = tracks.sliceBy(perCol, collision.globalIndex()); + for (const auto& track : tracks_per_coll) { + if (!checkTrack(collision, track)) { + continue; + } + fillTrackTable(collision, track); + } + + } // end of collision loop + + stored_trackIds.clear(); + stored_trackIds.shrink_to_fit(); + } + PROCESS_SWITCH(skimmerPrimaryTrack, processRec, "process reconstructed info only", true); // standalone + + void processRec_SWT(MyCollisionsWithSWT const& collisions, aod::BCsWithTimestamps const&, MyFilteredTracks const& tracks) + { + stored_trackIds.reserve(tracks.size()); + + for (const auto& collision : collisions) { + auto bc = collision.template foundBC_as(); + initCCDB(bc); + + if (!collision.isSelected()) { + continue; + } + if (!collision.isEoI()) { // events with at least 1 lepton for data reduction. + continue; + } + if (collision.swtaliastmp_raw() == 0) { + continue; + } + + auto tracks_per_coll = tracks.sliceBy(perCol, collision.globalIndex()); + for (const auto& track : tracks_per_coll) { + if (!checkTrack(collision, track)) { + continue; + } + fillTrackTable(collision, track); + } + + } // end of collision loop + + stored_trackIds.clear(); + stored_trackIds.shrink_to_fit(); + } + PROCESS_SWITCH(skimmerPrimaryTrack, processRec_SWT, "process reconstructed info only", false); // standalone with swt + + // ---------- for MC ---------- + + using MyFilteredTracksMC = soa::Filtered; + void processMC(soa::Join const& collisions, aod::McCollisions const&, aod::BCsWithTimestamps const&, MyFilteredTracksMC const& tracks) + { + stored_trackIds.reserve(tracks.size()); + + for (const auto& collision : collisions) { + if (!collision.has_mcCollision()) { + continue; + } + auto bc = collision.template foundBC_as(); + initCCDB(bc); + + if (!collision.isSelected()) { + continue; + } + if (!collision.isEoI()) { // events with at least 1 lepton for data reduction. + continue; + } + + auto tracks_per_coll = tracks.sliceBy(perCol, collision.globalIndex()); + for (const auto& track : tracks_per_coll) { + if (!checkTrack(collision, track)) { + continue; + } + fillTrackTable(collision, track); + } + } // end of collision loop + + stored_trackIds.clear(); + stored_trackIds.shrink_to_fit(); + } + PROCESS_SWITCH(skimmerPrimaryTrack, processMC, "process reconstructed and MC info ", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc, TaskName{"skimmer-primary-track"})}; +} diff --git a/PWGEM/Dilepton/TableProducer/treeCreatorElectronMLDDA.cxx b/PWGEM/Dilepton/TableProducer/treeCreatorElectronMLDDA.cxx index dc0ee410b7e..a42c7c805d4 100644 --- a/PWGEM/Dilepton/TableProducer/treeCreatorElectronMLDDA.cxx +++ b/PWGEM/Dilepton/TableProducer/treeCreatorElectronMLDDA.cxx @@ -65,7 +65,7 @@ using MyTrack = MyTracks::iterator; struct TreeCreatorElectronMLDDA { SliceCache cache; - Produces emprimarytracks; // flat table containing collision + track information + Produces emprimarytracks; // flat table containing collision + track information // Basic checks HistogramRegistry registry{ @@ -990,7 +990,7 @@ struct MLTrackQC { }, }; - void processQC(aod::EMPrimaryTracks const& tracks) + void processQC(aod::EMMLPrimaryTracks const& tracks) { for (const auto& track : tracks) { registry.fill(HIST("hTPCdEdx_P_All"), track.p(), track.tpcSignal()); @@ -1025,7 +1025,7 @@ struct MLTrackQC { } PROCESS_SWITCH(MLTrackQC, processQC, "process QC for single track level", false); - void processDummy(aod::EMPrimaryTracks const&) {} + void processDummy(aod::EMMLPrimaryTracks const&) {} PROCESS_SWITCH(MLTrackQC, processDummy, "process dummy", true); }; From 2d84ca1fe60ea0fb832acad7c37f18217ae13df2 Mon Sep 17 00:00:00 2001 From: feisenhu <53603353+feisenhu@users.noreply.github.com> Date: Mon, 30 Jun 2025 23:32:16 +0200 Subject: [PATCH 280/871] [PWGEM] Implement histogram for momentum loss vs DCA, intention to select track w/wo Bremsstrahlung (#11843) --- PWGEM/Dilepton/Core/DileptonMC.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/PWGEM/Dilepton/Core/DileptonMC.h b/PWGEM/Dilepton/Core/DileptonMC.h index 150d4971fbf..86274047388 100644 --- a/PWGEM/Dilepton/Core/DileptonMC.h +++ b/PWGEM/Dilepton/Core/DileptonMC.h @@ -425,6 +425,10 @@ struct DileptonMC { fRegistry.add("Pair/sm/Photon/hMvsRxy", "m_{ee} vs. r_{xy};r_{xy}^{true} (cm);m_{ee} (GeV/c^{2})", kTH2F, {{100, 0, 100}, {100, 0.0f, 1.0f}}, true); fRegistry.add("Pair/sm/PromptPi0/hMvsPhiV", "m_{ee} vs. #varphi_{V};#varphi (rad.);m_{ee} (GeV/c^{2})", kTH2F, {{90, 0, M_PI}, {100, 0.0f, 1.0f}}, true); fRegistry.add("Pair/sm/NonPromptPi0/hMvsPhiV", "m_{ee} vs. #varphi_{V};#varphi (rad.);m_{ee} (GeV/c^{2})", kTH2F, {{90, 0, M_PI}, {100, 0.0f, 1.0f}}, true); + fRegistry.add("Pair/sm/PromptPi0/hDeltaPtvsDCA", Form("p^{gen}_{T,e} - p^{rec}_{T,e} vs. DCA_{ee};%s;p^{gen}_{T,e} - p^{rec}_{T,e} (GeV/c)", pair_dca_axis_title.c_str()), kTH2F, {{160, 0, 8.}, {220, -1.f, +10.f}}, true); + fRegistry.add("Pair/sm/NonPromptPi0/hDeltaPtvsDCA", Form("p^{gen}_{T,e} - p^{rec}_{T,e} vs. DCA_{ee};%s;p^{gen}_{T,e} - p^{rec}_{T,e} (GeV/c)", pair_dca_axis_title.c_str()), kTH2F, {{160, 0, 8.}, {220, -1.f, +10.f}}, true); + fRegistry.add("Pair/sm/PromptJPsi/hDeltaPtvsDCA", Form("p^{gen}_{T,e} - p^{rec}_{T,e} vs. DCA_{ee};%s;p^{gen}_{T,e} - p^{rec}_{T,e} (GeV/c)", pair_dca_axis_title.c_str()), kTH2F, {{160, 0, 8.}, {220, -1.f, +10.f}}, true); + fRegistry.add("Pair/sm/NonPromptJPsi/hDeltaPtvsDCA", Form("p^{gen}_{T,e} - p^{rec}_{T,e} vs. DCA_{ee};%s;p^{gen}_{T,e} - p^{rec}_{T,e} (GeV/c)", pair_dca_axis_title.c_str()), kTH2F, {{160, 0, 8.}, {220, -1.f, +10.f}}, true); } fRegistry.add("Pair/ccbar/c2l_c2l/hadron_hadron/hs", "hs pair", kTHnSparseD, {axis_mass, axis_pt, axis_y, axis_dphi_ee, axis_deta_ee, axis_cos_theta_cs, axis_phi_cs, axis_aco, axis_asym_pt, axis_dphi_e_ee, axis_dca}, true); @@ -973,15 +977,21 @@ struct DileptonMC { auto mcmother = mcparticles.iteratorAt(mother_id); if (mcmother.isPhysicalPrimary() || mcmother.producedByGenerator()) { if ((t1mc.isPhysicalPrimary() || t1mc.producedByGenerator()) && (t2mc.isPhysicalPrimary() || t2mc.producedByGenerator())) { + float deltaPt1 = t1mc.pt() - t1.pt(); + float deltaPt2 = t2mc.pt() - t2.pt(); switch (std::abs(mcmother.pdgCode())) { case 111: if (IsFromCharm(mcmother, mcparticles) < 0 && IsFromBeauty(mcmother, mcparticles) < 0) { // prompt pi0 fRegistry.fill(HIST("Pair/sm/PromptPi0/hs"), v12.M(), v12.Pt(), v12.Rapidity(), dphi, deta, std::fabs(cos_thetaCS), std::fabs(phiCS), aco, asym, std::fabs(dphi_e_ee), pair_dca, weight); + fRegistry.fill(HIST("Pair/sm/PromptPi0/hDeltaPtvsDCA"), pair_dca, deltaPt1); + fRegistry.fill(HIST("Pair/sm/PromptPi0/hDeltaPtvsDCA"), pair_dca, deltaPt2); if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { fRegistry.fill(HIST("Pair/sm/PromptPi0/hMvsPhiV"), phiv, v12.M()); } } else { // non-prompt pi0 fRegistry.fill(HIST("Pair/sm/NonPromptPi0/hs"), v12.M(), v12.Pt(), v12.Rapidity(), dphi, deta, std::fabs(cos_thetaCS), std::fabs(phiCS), aco, asym, std::fabs(dphi_e_ee), pair_dca, weight); + fRegistry.fill(HIST("Pair/sm/NonPromptPi0/hDeltaPtvsDCA"), pair_dca, deltaPt1); + fRegistry.fill(HIST("Pair/sm/NonPromptPi0/hDeltaPtvsDCA"), pair_dca, deltaPt2); if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { fRegistry.fill(HIST("Pair/sm/NonPromptPi0/hMvsPhiV"), phiv, v12.M()); } @@ -1011,8 +1021,12 @@ struct DileptonMC { case 443: { if (IsFromBeauty(mcmother, mcparticles) > 0) { fRegistry.fill(HIST("Pair/sm/NonPromptJPsi/hs"), v12.M(), v12.Pt(), v12.Rapidity(), dphi, deta, std::fabs(cos_thetaCS), std::fabs(phiCS), aco, asym, std::fabs(dphi_e_ee), pair_dca, weight); + fRegistry.fill(HIST("Pair/sm/NonPromptJPsi/hDeltaPtvsDCA"), pair_dca, deltaPt1); + fRegistry.fill(HIST("Pair/sm/NonPromptJPsi/hDeltaPtvsDCA"), pair_dca, deltaPt2); } else { fRegistry.fill(HIST("Pair/sm/PromptJPsi/hs"), v12.M(), v12.Pt(), v12.Rapidity(), dphi, deta, std::fabs(cos_thetaCS), std::fabs(phiCS), aco, asym, std::fabs(dphi_e_ee), pair_dca, weight); + fRegistry.fill(HIST("Pair/sm/PromptJPsi/hDeltaPtvsDCA"), pair_dca, deltaPt1); + fRegistry.fill(HIST("Pair/sm/PromptJPsi/hDeltaPtvsDCA"), pair_dca, deltaPt2); } break; } From 3e4433bec92455762fcac09c49139269e38bd1e0 Mon Sep 17 00:00:00 2001 From: omvazque Date: Mon, 30 Jun 2025 17:00:59 -0500 Subject: [PATCH 281/871] [PWGLF] Select MC charged particles (#11850) --- PWGLF/Tasks/GlobalEventProperties/uccZdc.cxx | 113 +++++++++++++++---- 1 file changed, 91 insertions(+), 22 deletions(-) diff --git a/PWGLF/Tasks/GlobalEventProperties/uccZdc.cxx b/PWGLF/Tasks/GlobalEventProperties/uccZdc.cxx index 261a5a0284e..c00bd607966 100644 --- a/PWGLF/Tasks/GlobalEventProperties/uccZdc.cxx +++ b/PWGLF/Tasks/GlobalEventProperties/uccZdc.cxx @@ -69,6 +69,7 @@ struct UccZdc { static constexpr float kCollEnergy{2.68}; static constexpr float kZero{0.}; + static constexpr float kMinCharge{3.f}; // Configurables Event Selection Configurable isNoCollInTimeRangeStrict{"isNoCollInTimeRangeStrict", true, "use isNoCollInTimeRangeStrict?"}; @@ -710,6 +711,7 @@ struct UccZdc { std::vector pTs; std::vector vecFD; + std::vector vecEff; std::vector vecOneOverEff; // Calculates the Nch multiplicity @@ -747,7 +749,7 @@ struct UccZdc { // Fill vectors for [pT] measurement pTs.clear(); vecFD.clear(); - vecOneOverEff.clear(); + vecEff.clear(); for (const auto& track : tracks) { // Track Selection if (!track.isGlobalTrack()) { @@ -771,7 +773,7 @@ struct UccZdc { } if ((effValue > 0.) && (fdValue > 0.)) { pTs.emplace_back(pt); - vecOneOverEff.emplace_back(1. / effValue); + vecEff.emplace_back(effValue); vecFD.emplace_back(fdValue); } // To calculate event-averaged @@ -780,7 +782,7 @@ struct UccZdc { double p1, p2, p3, p4, w1, w2, w3, w4; p1 = p2 = p3 = p4 = w1 = w2 = w3 = w4 = 0.0; - getPTpowers(pTs, vecOneOverEff, vecFD, p1, w1, p2, w2, p3, w3, p4, w4); + getPTpowers(pTs, vecEff, vecFD, p1, w1, p2, w2, p3, w3, p4, w4); // EbE one-particle pT correlation double oneParCorr{p1 / w1}; @@ -819,6 +821,7 @@ struct UccZdc { // Preslice perMCCollision = aod::mcparticle::mcCollisionId; Preslice perCollision = aod::track::collisionId; + Service pdg; TRandom* randPointer = new TRandom(); void processMCclosure(aod::McCollisions::iterator const& mccollision, soa::SmallGroups const& collisions, o2::aod::BCsRun3 const& /*bcs*/, aod::FT0s const& /*ft0s*/, aod::McParticles const& mcParticles, TheFilteredSimTracks const& simTracks) { @@ -879,9 +882,10 @@ struct UccZdc { return; } - std::vector pTs; - std::vector vecFD; - std::vector vecOneOverEff; + std::vector pTs; + std::vector vecFD; + std::vector vecEff; + std::vector vecOneOverEffXFD; // std::vector wIs; const auto& groupedTracks{simTracks.sliceBy(perCollision, collision.globalIndex())}; @@ -901,6 +905,8 @@ struct UccZdc { } // Calculates the event weight, W_k + const int foundNchBin{efficiency->GetXaxis()->FindBin(nchRaw)}; + for (const auto& track : groupedTracks) { // Track Selection if (track.eta() < minEta || track.eta() > maxEta) { @@ -912,12 +918,31 @@ struct UccZdc { if (!track.isGlobalTrack()) { continue; } + if (!track.has_mcParticle()) { + continue; + } + const auto& particle{track.mcParticle()}; - float pt{track.pt()}; - int foundNchBin{efficiency->GetXaxis()->FindBin(nchRaw)}; - int foundPtBin{efficiency->GetYaxis()->FindBin(pt)}; - float effValue{1.}; - float fdValue{1.}; + auto charge{0.}; + // Get the MC particle + auto* pdgParticle = pdg->GetParticle(particle.pdgCode()); + if (pdgParticle != nullptr) { + charge = pdgParticle->Charge(); + } else { + continue; + } + + // Is it a charged particle? + if (std::abs(charge) < kMinCharge) { + continue; + } + // Is it a primary particle? + // if (!particle.isPhysicalPrimary()) { continue; } + + const double pt{static_cast(track.pt())}; + const int foundPtBin{efficiency->GetYaxis()->FindBin(pt)}; + double effValue{1.}; + double fdValue{1.}; if (applyEff) { effValue = efficiency->GetBinContent(foundNchBin, foundPtBin); @@ -925,19 +950,19 @@ struct UccZdc { } if ((effValue > 0.) && (fdValue > 0.)) { pTs.emplace_back(pt); - vecOneOverEff.emplace_back(1. / effValue); + vecEff.emplace_back(effValue); vecFD.emplace_back(fdValue); + vecOneOverEffXFD.emplace_back(fdValue / effValue); } } - - nchMult = std::accumulate(vecOneOverEff.begin(), vecOneOverEff.end(), 0); + nchMult = std::accumulate(vecOneOverEffXFD.begin(), vecOneOverEffXFD.end(), 0); if (nchMult < minNchSel) { return; } double p1, p2, p3, p4, w1, w2, w3, w4; p1 = p2 = p3 = p4 = w1 = w2 = w3 = w4 = 0.0; - getPTpowers(pTs, vecOneOverEff, vecFD, p1, w1, p2, w2, p3, w3, p4, w4); + getPTpowers(pTs, vecEff, vecFD, p1, w1, p2, w2, p3, w3, p4, w4); const double denTwoParCorr{std::pow(w1, 2.) - w2}; const double numTwoParCorr{std::pow(p1, 2.) - p2}; @@ -971,6 +996,21 @@ struct UccZdc { if (particle.pt() < minPt || particle.pt() > maxPt) { continue; } + + auto charge{0.}; + // Get the MC particle + auto* pdgParticle = pdg->GetParticle(particle.pdgCode()); + if (pdgParticle != nullptr) { + charge = pdgParticle->Charge(); + } else { + continue; + } + + // Is it a charged particle? + if (std::abs(charge) < kMinCharge) { + continue; + } + // Is it a primary particle? if (!particle.isPhysicalPrimary()) { continue; } @@ -1044,9 +1084,23 @@ struct UccZdc { if (!track.has_mcParticle()) { continue; } - registry.fill(HIST("Pt_all_ch"), nchRaw, track.pt()); - + // Get the MC particle const auto& particle{track.mcParticle()}; + auto charge{0.}; + auto* pdgParticle = pdg->GetParticle(particle.pdgCode()); + if (pdgParticle != nullptr) { + charge = pdgParticle->Charge(); + } else { + continue; + } + + // Is it a charged particle? + if (std::abs(charge) < kMinCharge) { + continue; + } + // All charged particles + registry.fill(HIST("Pt_all_ch"), nchRaw, track.pt()); + // Is it a primary particle? if (!particle.isPhysicalPrimary()) { continue; } @@ -1075,6 +1129,21 @@ struct UccZdc { if (particle.pt() < minPt || particle.pt() > maxPt) { continue; } + + auto charge{0.}; + // Get the MC particle + auto* pdgParticle = pdg->GetParticle(particle.pdgCode()); + if (pdgParticle != nullptr) { + charge = pdgParticle->Charge(); + } else { + continue; + } + + // Is it a charged particle? + if (std::abs(charge) < kMinCharge) { + continue; + } + // Is it a primary particle? if (!particle.isPhysicalPrimary()) { continue; } @@ -1101,14 +1170,14 @@ struct UccZdc { PROCESS_SWITCH(UccZdc, processMCclosure, "Process MC closure", false); template - void getPTpowers(const T& pTs, const T& vecOneOverEff, const T& vecFD, U& pOne, U& wOne, U& pTwo, U& wTwo, U& pThree, U& wThree, U& pFour, U& wFour) + void getPTpowers(const T& pTs, const T& vecEff, const T& vecFD, U& pOne, U& wOne, U& pTwo, U& wTwo, U& pThree, U& wThree, U& pFour, U& wFour) { pOne = wOne = pTwo = wTwo = pThree = wThree = pFour = wFour = 0.; for (std::size_t i = 0; i < pTs.size(); ++i) { - const float pTi{pTs.at(i)}; - const float eFFi{vecOneOverEff.at(i)}; - const float fDi{vecFD.at(i)}; - const float wEighti{eFFi * fDi}; + const double pTi{pTs.at(i)}; + const double eFFi{vecEff.at(i)}; + const double fDi{vecFD.at(i)}; + const double wEighti{std::pow(eFFi, -1.) * fDi}; pOne += wEighti * pTi; wOne += wEighti; pTwo += std::pow(wEighti * pTi, 2.); From 75b5596d58e17be4b0d2dfb92d95d1fbdfe06c8b Mon Sep 17 00:00:00 2001 From: altsybee Date: Tue, 1 Jul 2025 01:36:23 +0200 Subject: [PATCH 282/871] [DPG] Update timeDependentQa.cxx - improve config par names (#11847) --- DPG/Tasks/AOTEvent/timeDependentQa.cxx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/DPG/Tasks/AOTEvent/timeDependentQa.cxx b/DPG/Tasks/AOTEvent/timeDependentQa.cxx index 41f9748e5f3..766c6aa5520 100644 --- a/DPG/Tasks/AOTEvent/timeDependentQa.cxx +++ b/DPG/Tasks/AOTEvent/timeDependentQa.cxx @@ -54,7 +54,7 @@ const AxisSpec axisSparseDcaZ{100, -1., 1., "DCA_{z}, cm"}; struct TimeDependentQaTask { Configurable confTimeBinWidthInSec{"TimeBinWidthInSec", 0.5, "Width of time bins in seconds"}; // o2-linter: disable=name/configurable (temporary fix) Configurable confTimeWiderBinFactor{"TimeWideBinFactor", 4, "Factor for wider time bins for some 2D histograms"}; // o2-linter: disable=name/configurable (temporary fix) - Configurable confTimeMuchWiderBinFactor{"confTimeMuchWiderBinFactor", 20, "Factor for even wider time bins for some 2D histograms"}; // o2-linter: disable=name/configurable (temporary fix) + Configurable confTimeMuchWiderBinFactor{"TimeMuchWiderBinFactor", 20, "Factor for even wider time bins for some 2D histograms"}; // o2-linter: disable=name/configurable (temporary fix) Configurable confTakeVerticesWithUPCsettings{"ConsiderVerticesWithUPCsettings", 0, "Take vertices: 0 - all , 1 - only without UPC settings, 2 - only with UPC settings"}; // o2-linter: disable=name/configurable (temporary fix) Configurable confFlagFillPhiVsTimeHist{"FlagFillPhiVsTimeHist", 2, "0 - don't fill , 1 - fill only for global/7cls/TRD/TOF tracks, 2 - fill also layer-by-layer"}; // o2-linter: disable=name/configurable (temporary fix) Configurable confFlagFillEtaPhiVsTimeHist{"FlagFillEtaPhiVsTimeHist", 0, "0 - don't fill , 1 - fill"}; // o2-linter: disable=name/configurable (temporary fix) @@ -63,11 +63,11 @@ struct TimeDependentQaTask { Configurable confFlagCheckQoverPtHist{"FlagCheckQoverPtHist", 1, "0 - don't check , 1 - check"}; // o2-linter: disable=name/configurable (temporary fix) // for O-O and Ne-Ne run - Configurable confIncludeMultDistrVsTimeHistos{"confIncludeMultDistrVsTimeHistos", 0, ""}; // o2-linter: disable=name/configurable (temporary fix) - Configurable confMaxNtracksForTimeDepDistributions{"confMaxNtracksForTimeDepDistributions", 800, ""}; // o2-linter: disable=name/configurable (temporary fix) - Configurable confMaxZNACenergyForTimeDepDistributions{"confMaxZNACenergyForTimeDepDistributions", 80, ""}; // o2-linter: disable=name/configurable (temporary fix) - Configurable confMaxT0ACamplForTimeDepDistributions{"confMaxT0ACamplForTimeDepDistributions", 25000, ""}; // o2-linter: disable=name/configurable (temporary fix) - Configurable confMaxV0AamplForTimeDepDistributions{"confMaxV0AamplForTimeDepDistributions", 40000, ""}; // o2-linter: disable=name/configurable (temporary fix) + Configurable confIncludeMultDistrVsTimeHistos{"IncludeMultDistrVsTimeHistos", 0, ""}; // o2-linter: disable=name/configurable (temporary fix) + Configurable confMaxNtracksForTimeDepDistributions{"MaxNtracksForTimeDepDistributions", 800, ""}; // o2-linter: disable=name/configurable (temporary fix) + Configurable confMaxZNACenergyForTimeDepDistributions{"MaxZNACenergyForTimeDepDistributions", 80, ""}; // o2-linter: disable=name/configurable (temporary fix) + Configurable confMaxT0ACamplForTimeDepDistributions{"MaxT0ACamplForTimeDepDistributions", 25000, ""}; // o2-linter: disable=name/configurable (temporary fix) + Configurable confMaxV0AamplForTimeDepDistributions{"MaxV0AamplForTimeDepDistributions", 40000, ""}; // o2-linter: disable=name/configurable (temporary fix) enum EvSelBitsToMonitor { enCollisionsAll = 0, From db6382bd567e3d2b5212d7e7ae26ce2222de42d3 Mon Sep 17 00:00:00 2001 From: sangwoo <141385263+sangwoo184@users.noreply.github.com> Date: Tue, 1 Jul 2025 11:32:16 +0900 Subject: [PATCH 283/871] [PWGLF] optimized track index selection and fixed PID selection (#11775) Co-authored-by: sangwoo Co-authored-by: sangwoo --- PWGLF/Tasks/Resonances/f0980pbpbanalysis.cxx | 104 +++++++++++-------- 1 file changed, 63 insertions(+), 41 deletions(-) diff --git a/PWGLF/Tasks/Resonances/f0980pbpbanalysis.cxx b/PWGLF/Tasks/Resonances/f0980pbpbanalysis.cxx index 51046fcaa16..caf80357b2d 100644 --- a/PWGLF/Tasks/Resonances/f0980pbpbanalysis.cxx +++ b/PWGLF/Tasks/Resonances/f0980pbpbanalysis.cxx @@ -15,50 +15,46 @@ #include #include -#include + #include -#include #include +#include +#include // #include #include // #include "TLorentzVector.h" -#include "TRandom3.h" -#include "TF1.h" -#include "TVector2.h" -#include "Math/Vector3D.h" -#include "Math/Vector4D.h" -#include "Math/GenVector/Boost.h" -#include - -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/StepTHn.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/StaticFor.h" - -#include "Common/DataModel/PIDResponse.h" -#include "Common/DataModel/Multiplicity.h" +#include "Common/Core/TrackSelection.h" +#include "Common/Core/trackUtilities.h" #include "Common/DataModel/Centrality.h" -#include "Common/DataModel/TrackSelectionTables.h" #include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/PIDResponse.h" #include "Common/DataModel/Qvectors.h" +#include "Common/DataModel/TrackSelectionTables.h" -#include "Common/Core/trackUtilities.h" -#include "Common/Core/TrackSelection.h" - +#include "CCDB/BasicCCDBManager.h" +#include "CCDB/CcdbApi.h" #include "CommonConstants/PhysicsConstants.h" - -#include "ReconstructionDataFormats/Track.h" - -#include "DataFormatsParameters/GRPObject.h" #include "DataFormatsParameters/GRPMagField.h" +#include "DataFormatsParameters/GRPObject.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/O2DatabasePDGPlugin.h" +#include "Framework/StaticFor.h" +#include "Framework/StepTHn.h" +#include "Framework/runDataProcessing.h" +#include "ReconstructionDataFormats/Track.h" -#include "CCDB/CcdbApi.h" -#include "CCDB/BasicCCDBManager.h" +#include "Math/GenVector/Boost.h" +#include "Math/Vector3D.h" +#include "Math/Vector4D.h" +#include "TF1.h" +#include "TRandom3.h" +#include "TVector2.h" +#include // from phi #include "Common/DataModel/PIDResponseITS.h" @@ -132,7 +128,8 @@ struct F0980pbpbanalysis { Configurable cfgTOFBetaCut{"cfgTOFBetaCut", 0.0, "cut TOF beta"}; Configurable cfgDeepAngleSel{"cfgDeepAngleSel", true, "Deep Angle cut"}; Configurable cfgDeepAngle{"cfgDeepAngle", 0.04, "Deep Angle cut value"}; - Configurable cfgTrackIndexSel{"cfgTrackIndexSel", false, "Index selection flag"}; + Configurable cfgTrackIndexSelType{"cfgTrackIndexSelType", 1, "Index selection type"}; + Configurable cMaxTiednSigmaPion{"cMaxTiednSigmaPion", 3.0, "Combined nSigma cut for Pion"}; ConfigurableAxis massAxis{"massAxis", {400, 0.2, 2.2}, "Invariant mass axis"}; ConfigurableAxis ptAxis{"ptAxis", {VARIABLE_WIDTH, 0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.8, 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0, 6.0, 7.0, 8.0, 10.0, 13.0, 20.0}, "Transverse momentum Binning"}; @@ -174,6 +171,12 @@ struct F0980pbpbanalysis { PtlKaon = 1, }; + enum IndexSelList { + None = 0, + woSame = 1, + leq = 2 + }; + TRandom* rn = new TRandom(); // float theta2; @@ -212,6 +215,7 @@ struct F0980pbpbanalysis { template bool eventSelected(TCollision collision) { + constexpr double QvecAmpMin = 1e-4; if (!collision.sel8()) { return 0; } @@ -234,7 +238,7 @@ struct F0980pbpbanalysis { if (!collision.selection_bit(aod::evsel::kNoSameBunchPileup)) { return 0; } - if (cfgQvecSel && (collision.qvecAmp()[detId] < 1e-4 || collision.qvecAmp()[refAId] < 1e-4 || collision.qvecAmp()[refBId] < 1e-4)) { + if (cfgQvecSel && (collision.qvecAmp()[detId] < QvecAmpMin || collision.qvecAmp()[refAId] < QvecAmpMin || collision.qvecAmp()[refBId] < QvecAmpMin)) { return 0; } if (cfgOccupancySel && (collision.trackOccupancyInTimeRange() > cfgOccupancyMax || collision.trackOccupancyInTimeRange() < cfgOccupancyMin)) { @@ -320,12 +324,15 @@ struct F0980pbpbanalysis { } } } else if (cfgSelectPID == PIDList::PIDTest) { - if (track.hasTOF()) { - if (std::fabs(getTofNSigma(track)) > cMaxTOFnSigmaPion) { - return 0; - } - if (std::fabs(getTpcNSigma(track)) > cMaxTPCnSigmaPion) { - return 0; + if (cfgUSETOF) { + if (track.hasTOF()) { + if ((getTpcNSigma(track) * getTpcNSigma(track) + getTofNSigma(track) * getTofNSigma(track)) > (cMaxTiednSigmaPion * cMaxTiednSigmaPion)) { + return 0; + } + } else { + if (std::fabs(getTpcNSigma(track)) > cMaxTPCnSigmaPionS) { + return 0; + } } } else { if (std::fabs(getTpcNSigma(track)) > cMaxTPCnSigmaPionS) { @@ -336,6 +343,21 @@ struct F0980pbpbanalysis { return 1; } + template + bool indexSelection(const TrackType1 track1, const TrackType2 track2) + { + if (cfgTrackIndexSelType == IndexSelList::woSame) { + if (track2.globalIndex() == track1.globalIndex()) { + return 0; + } + } else if (cfgTrackIndexSelType == IndexSelList::leq) { + if (track2.globalIndex() <= track1.globalIndex()) { + return 0; + } + } + return 1; + } + template bool selectionPair(const TrackType1 track1, const TrackType2 track2) { @@ -420,11 +442,11 @@ struct F0980pbpbanalysis { histos.fill(HIST("QA/TPC_TOF_selected"), getTpcNSigma(trk2), getTofNSigma(trk2)); } - if (cfgTrackIndexSel && cfgSelectPID == PIDList::PIDTest && trk2.globalIndex() <= trk1.globalIndex()) { + if (!indexSelection(trk1, trk2)) { continue; } - if (cfgSelectPID == PIDList::PIDTest && !selectionPair(trk1, trk2)) { + if (!selectionPair(trk1, trk2)) { continue; } From d0ac9c098926dae3b3f1b1f669188b0232785052 Mon Sep 17 00:00:00 2001 From: SuJeong Ji <120470463+SuJeong-Ji@users.noreply.github.com> Date: Tue, 1 Jul 2025 13:15:05 +0900 Subject: [PATCH 284/871] [PWGLF] chk892Flow.cxx : Added occupancy axis and fill invariant mass distribution for K0s (#11829) Co-authored-by: ALICE Action Bot --- PWGLF/Tasks/Resonances/chk892Flow.cxx | 59 ++++++++++++++++----------- 1 file changed, 35 insertions(+), 24 deletions(-) diff --git a/PWGLF/Tasks/Resonances/chk892Flow.cxx b/PWGLF/Tasks/Resonances/chk892Flow.cxx index 18e21f5dd11..2c616d81406 100644 --- a/PWGLF/Tasks/Resonances/chk892Flow.cxx +++ b/PWGLF/Tasks/Resonances/chk892Flow.cxx @@ -118,6 +118,7 @@ struct Chk892Flow { ConfigurableAxis cfgBinsPtQA{"cfgBinsPtQA", {VARIABLE_WIDTH, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0, 3.2, 3.4, 3.6, 3.8, 4.0, 4.2, 4.4, 4.6, 4.8, 5.0, 5.2, 5.4, 5.6, 5.8, 6.0, 6.2, 6.4, 6.6, 6.8, 7.0, 7.2, 7.4, 7.6, 7.8, 8.0, 8.2, 8.4, 8.6, 8.8, 9.0, 9.2, 9.4, 9.6, 9.8, 10.0}, "Binning of the pT axis"}; ConfigurableAxis cfgBinsCent{"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 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"}; + ConfigurableAxis cfgBinsOccu{"cfgBinsOccu", {VARIABLE_WIDTH, 0, 500, 1000, 2500, 9999}, "Binning of the occupancy 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"}; ConfigurableAxis cfgAxisV2{"cfgAxisV2", {200, -1, 1}, "Binning of the v2 axis (+-1 for EP method)"}; @@ -136,8 +137,8 @@ struct Chk892Flow { o2::analysis::CollisonCuts colCuts; struct : ConfigurableGroup { Configurable cfgEvtZvtx{"cfgEvtZvtx", 10.f, "Evt sel: Max. z-Vertex (cm)"}; - Configurable cfgEvtOccupancyInTimeRangeMax{"cfgEvtOccupancyInTimeRangeMax", -1, "Evt sel: maximum track occupancy"}; - Configurable cfgEvtOccupancyInTimeRangeMin{"cfgEvtOccupancyInTimeRangeMin", -1, "Evt sel: minimum track occupancy"}; + // Configurable cfgEvtOccupancyInTimeRangeMax{"cfgEvtOccupancyInTimeRangeMax", -1, "Evt sel: maximum track occupancy"}; + // Configurable cfgEvtOccupancyInTimeRangeMin{"cfgEvtOccupancyInTimeRangeMin", -1, "Evt sel: minimum track occupancy"}; Configurable cfgEvtTriggerCheck{"cfgEvtTriggerCheck", false, "Evt sel: check for trigger"}; Configurable cfgEvtOfflineCheck{"cfgEvtOfflineCheck", true, "Evt sel: check for offline selection"}; Configurable cfgEvtTriggerTVXSel{"cfgEvtTriggerTVXSel", false, "Evt sel: triggerTVX selection (MB)"}; @@ -257,7 +258,7 @@ struct Chk892Flow { { lCentrality = -999; - colCuts.setCuts(EventCuts.cfgEvtZvtx, EventCuts.cfgEvtTriggerCheck, EventCuts.cfgEvtOfflineCheck, /*checkRun3*/ true, /*triggerTVXsel*/ false, EventCuts.cfgEvtOccupancyInTimeRangeMax, EventCuts.cfgEvtOccupancyInTimeRangeMin); + colCuts.setCuts(EventCuts.cfgEvtZvtx, EventCuts.cfgEvtTriggerCheck, EventCuts.cfgEvtOfflineCheck, /*checkRun3*/ true, /*triggerTVXsel*/ false, /*EventCuts.cfgEvtOccupancyInTimeRangeMax*/ false, /*EventCuts.cfgEvtOccupancyInTimeRangeMin*/ false); colCuts.init(&histos); colCuts.setTriggerTVX(EventCuts.cfgEvtTriggerTVXSel); colCuts.setApplyTFBorderCut(EventCuts.cfgEvtTFBorderCut); @@ -277,6 +278,7 @@ struct Chk892Flow { AxisSpec ptAxisQA = {AxisConfig.cfgBinsPtQA, "#it{p}_{T} (GeV/#it{c})"}; AxisSpec v2Axis = {AxisConfig.cfgAxisV2, "#v_{2}"}; AxisSpec phiAxis = {AxisConfig.cfgAxisPhi, "2(#phi-#Psi_{2})"}; + AxisSpec occuAxis = {AxisConfig.cfgBinsOccu, "Occupancy"}; AxisSpec radiusAxis = {50, 0, 5, "Radius (cm)"}; AxisSpec cpaAxis = {30, 0.97, 1.0, "CPA"}; AxisSpec tauAxis = {250, 0, 25, "Lifetime (cm)"}; @@ -284,7 +286,7 @@ struct Chk892Flow { AxisSpec dcaxyAxis = {100, 0, 1, "DCA_{#it{xy}} (cm)"}; AxisSpec dcazAxis = {200, 0, 2, "DCA_{#it{z}} (cm)"}; AxisSpec yAxis = {50, -1, 1, "Rapidity"}; - AxisSpec invMassAxisK0s = {400 / AxisConfig.cNbinsDiv, 0.3, 0.7, "Invariant Mass (GeV/#it{c}^2)"}; // K0s ~497.611 + AxisSpec invMassAxisK0s = {800 / AxisConfig.cNbinsDiv, 0.46, 0.54, "Invariant Mass (GeV/#it{c}^2)"}; // K0s ~497.611 AxisSpec invMassAxisReso = {900 / AxisConfig.cNbinsDiv, 0.5f, 1.4f, "Invariant Mass (GeV/#it{c}^2)"}; // chK(892) ~892 AxisSpec pidQAAxis = {130 / AxisConfig.cNbinsDivQA, -6.5, 6.5}; @@ -296,7 +298,8 @@ struct Chk892Flow { histos.add("QA/K0sCutCheck", "Check K0s cut", HistType::kTH1D, {AxisSpec{13, -0.5, 12.5, "Check"}}); } histos.add("QA/before/CentDist", "Centrality distribution", {HistType::kTH1D, {centAxis}}); - histos.add("QA/before/VtxZ", "Centrality distribution", {HistType::kTH1D, {vtxzAxis}}); + histos.add("QA/before/VtxZ", "z-vertex distribution", {HistType::kTH1D, {vtxzAxis}}); + histos.add("QA/before/Occupancy", "Occupancy distribution", {HistType::kTH1D, {occuAxis}}); // EventPlane histos.add("QA/EP/hEPDet", "Event plane distribution of FT0C (Det = A)", {HistType::kTH2D, {centAxis, epAxis}}); @@ -443,16 +446,16 @@ struct Chk892Flow { // Invariant mass nSparse if (AnalysisConfig.cfgFillAdditionalAxis) { - histos.add("hInvmass_Kstar", "Invariant mass of unlike-sign chK(892)", HistType::kTHnSparseD, {axisType, centAxis, ptAxis, invMassAxisReso, v2Axis, phiAxis}); - histos.add("hInvmass_K0s", "Invariant mass of unlike-sign K0s", HistType::kTHnSparseD, {centAxis, ptAxis, invMassAxisK0s, v2Axis, phiAxis}); + histos.add("hInvmass_Kstar", "Invariant mass of unlike-sign chK(892)", HistType::kTHnSparseD, {axisType, centAxis, ptAxis, invMassAxisReso, v2Axis, phiAxis, occuAxis}); + histos.add("hInvmass_K0s", "Invariant mass of unlike-sign K0s", HistType::kTHnSparseD, {centAxis, ptAxis, invMassAxisK0s, v2Axis, phiAxis, occuAxis}); if (doprocessMC) { - histos.add("hInvmass_Kstar_MC", "Invariant mass of unlike chK(892)", HistType::kTHnSparseD, {axisType, centAxis, ptAxis, invMassAxisReso, v2Axis, phiAxis}); + histos.add("hInvmass_Kstar_MC", "Invariant mass of unlike chK(892)", HistType::kTHnSparseD, {axisType, centAxis, ptAxis, invMassAxisReso, v2Axis, phiAxis, occuAxis}); } } else { - histos.add("hInvmass_Kstar", "Invariant mass of unlike-sign chK(892)", HistType::kTHnSparseD, {axisType, centAxis, ptAxis, invMassAxisReso, v2Axis}); - histos.add("hInvmass_K0s", "Invariant mass of unlike-sign K0s", HistType::kTHnSparseD, {centAxis, ptAxis, invMassAxisK0s, v2Axis}); + histos.add("hInvmass_Kstar", "Invariant mass of unlike-sign chK(892)", HistType::kTHnSparseD, {axisType, centAxis, ptAxis, invMassAxisReso, v2Axis, occuAxis}); + histos.add("hInvmass_K0s", "Invariant mass of unlike-sign K0s", HistType::kTHnSparseD, {centAxis, ptAxis, invMassAxisK0s, v2Axis, occuAxis}); if (doprocessMC) { - histos.add("hInvmass_Kstar_MC", "Invariant mass of unlike chK(892)", HistType::kTHnSparseD, {axisType, centAxis, ptAxis, invMassAxisReso, v2Axis}); + histos.add("hInvmass_Kstar_MC", "Invariant mass of unlike chK(892)", HistType::kTHnSparseD, {axisType, centAxis, ptAxis, invMassAxisReso, v2Axis, occuAxis}); } } @@ -520,9 +523,9 @@ struct Chk892Flow { histos.add("QAMC/kstarv2vsinvmass_noKstar", "Invariant mass vs v2 of unlike-sign no chK(892)", HistType::kTH2D, {invMassAxisReso, v2Axis}); if (AnalysisConfig.cfgFillAdditionalAxis) { - histos.add("hInvmass_Kstar_MC", "Invariant mass of unlike chK(892)", HistType::kTHnSparseD, {axisType, centAxis, ptAxis, invMassAxisReso, v2Axis, phiAxis}); + histos.add("hInvmass_Kstar_MC", "Invariant mass of unlike chK(892)", HistType::kTHnSparseD, {axisType, centAxis, ptAxis, invMassAxisReso, v2Axis, phiAxis, occuAxis}); } else { - histos.add("hInvmass_Kstar_MC", "Invariant mass of unlike chK(892)", HistType::kTHnSparseD, {axisType, centAxis, ptAxis, invMassAxisReso, v2Axis}); + histos.add("hInvmass_Kstar_MC", "Invariant mass of unlike chK(892)", HistType::kTHnSparseD, {axisType, centAxis, ptAxis, invMassAxisReso, v2Axis, occuAxis}); } } @@ -891,9 +894,15 @@ struct Chk892Flow { auto trkkPropTau = k0sCand.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * MassK0Short; auto trkkMass = k0sCand.mK0Short(); - lResoSecondary.SetXYZM(k0sCand.px(), k0sCand.py(), k0sCand.pz(), MassK0Short); + // lResoSecondary.SetXYZM(k0sCand.px(), k0sCand.py(), k0sCand.pz(), MassK0Short); + lResoSecondary.SetXYZM(k0sCand.px(), k0sCand.py(), k0sCand.pz(), trkkMass); auto lPhiMinusPsiK0s = RecoDecay::constrainAngle(lResoSecondary.Phi() - lEPDet, 0.0, 2); // constrain angle to range 0, Pi - auto v2K0s = std::cos(static_cast(nmode) * lPhiMinusPsiK0s); + // auto v2K0s = std::cos(static_cast(nmode) * lPhiMinusPsiK0s); + + float cosNPhi_K0s = std::cos(static_cast(nmode) * lResoSecondary.Phi()); + float sinNPhi_K0s = std::sin(static_cast(nmode) * lResoSecondary.Phi()); + + auto v2K0s = cosNPhi_K0s * collision.qvecRe()[lQvecDetInd] + sinNPhi_K0s * collision.qvecIm()[lQvecDetInd]; if constexpr (!IsMix) { if (AnalysisConfig.cfgFillQAPlots) { // Seconddary QA plots @@ -962,15 +971,15 @@ struct Chk892Flow { histos.fill(HIST("QA/after/k0sv2vsinvmass"), lResoSecondary.M(), v2K0s); if (AnalysisConfig.cfgFillAdditionalAxis) { - histos.fill(HIST("hInvmass_K0s"), lCentrality, lResoSecondary.Pt(), lResoSecondary.M(), v2K0s, static_cast(nmode) * lPhiMinusPsiK0s); + histos.fill(HIST("hInvmass_K0s"), lCentrality, lResoSecondary.Pt(), lResoSecondary.M(), v2K0s, static_cast(nmode) * lPhiMinusPsiK0s, collision.trackOccupancyInTimeRange()); } else { - histos.fill(HIST("hInvmass_K0s"), lCentrality, lResoSecondary.Pt(), lResoSecondary.M(), v2K0s); + histos.fill(HIST("hInvmass_K0s"), lCentrality, lResoSecondary.Pt(), lResoSecondary.M(), v2K0s, collision.trackOccupancyInTimeRange()); } } if (AnalysisConfig.cfgFillAdditionalAxis) { - histos.fill(HIST("hInvmass_K0s"), lCentrality, lResoSecondary.Pt(), lResoSecondary.M(), v2K0s, static_cast(nmode) * lPhiMinusPsiK0s); + histos.fill(HIST("hInvmass_K0s"), lCentrality, lResoSecondary.Pt(), lResoSecondary.M(), v2K0s, static_cast(nmode) * lPhiMinusPsiK0s, collision.trackOccupancyInTimeRange()); } else { - histos.fill(HIST("hInvmass_K0s"), lCentrality, lResoSecondary.Pt(), lResoSecondary.M(), v2K0s); + histos.fill(HIST("hInvmass_K0s"), lCentrality, lResoSecondary.Pt(), lResoSecondary.M(), v2K0s, collision.trackOccupancyInTimeRange()); } k0sIndicies.push_back(k0sCand.index()); } @@ -980,9 +989,11 @@ struct Chk892Flow { for (const auto& k0sIndex : k0sIndicies) { auto bTrack = dTracks1.rawIteratorAt(trackIndex); auto k0sCand = dTracks2.rawIteratorAt(k0sIndex); + auto trkkMass = k0sCand.mK0Short(); lDecayDaughter_bach.SetXYZM(bTrack.px(), bTrack.py(), bTrack.pz(), MassPionCharged); - lResoSecondary.SetXYZM(k0sCand.px(), k0sCand.py(), k0sCand.pz(), MassK0Short); + // lResoSecondary.SetXYZM(k0sCand.px(), k0sCand.py(), k0sCand.pz(), MassK0Short); + lResoSecondary.SetXYZM(k0sCand.px(), k0sCand.py(), k0sCand.pz(), trkkMass); lResoKstar = lResoSecondary + lDecayDaughter_bach; auto resoPhi = lResoKstar.Phi(); // EP method @@ -1016,9 +1027,9 @@ struct Chk892Flow { histos.fill(HIST("QA/after/kstarv2vsinvmass"), lResoKstar.M(), resoFlowValue); } if (AnalysisConfig.cfgFillAdditionalAxis) { - histos.fill(HIST("hInvmass_Kstar"), typeKstar, lCentrality, lResoKstar.Pt(), lResoKstar.M(), resoFlowValue, static_cast(nmode) * lPhiMinusPsiKstar); + histos.fill(HIST("hInvmass_Kstar"), typeKstar, lCentrality, lResoKstar.Pt(), lResoKstar.M(), resoFlowValue, static_cast(nmode) * lPhiMinusPsiKstar, collision.trackOccupancyInTimeRange()); } else { - histos.fill(HIST("hInvmass_Kstar"), typeKstar, lCentrality, lResoKstar.Pt(), lResoKstar.M(), resoFlowValue); + histos.fill(HIST("hInvmass_Kstar"), typeKstar, lCentrality, lResoKstar.Pt(), lResoKstar.M(), resoFlowValue, collision.trackOccupancyInTimeRange()); } if (BkgEstimationConfig.cfgFillRotBkg) { @@ -1046,9 +1057,9 @@ struct Chk892Flow { } typeKstar = bTrack.sign() > 0 ? BinType::kKstarP_Rot : BinType::kKstarN_Rot; if (AnalysisConfig.cfgFillAdditionalAxis) { - histos.fill(HIST("hInvmass_Kstar"), typeKstar, lCentrality, lResonanceRot.Pt(), lResonanceRot.M(), resoFlowValue, static_cast(nmode) * lPhiMinusPsiKstar); + histos.fill(HIST("hInvmass_Kstar"), typeKstar, lCentrality, lResonanceRot.Pt(), lResonanceRot.M(), resoFlowValue, static_cast(nmode) * lPhiMinusPsiKstar, collision.trackOccupancyInTimeRange()); } else { - histos.fill(HIST("hInvmass_Kstar"), typeKstar, lCentrality, lResonanceRot.Pt(), lResonanceRot.M(), resoFlowValue); + histos.fill(HIST("hInvmass_Kstar"), typeKstar, lCentrality, lResonanceRot.Pt(), lResonanceRot.M(), resoFlowValue, collision.trackOccupancyInTimeRange()); } } } From caf8a07adc315e3b1ae1d78c220f5e2168f5778a Mon Sep 17 00:00:00 2001 From: skundu692 <86804743+skundu692@users.noreply.github.com> Date: Tue, 1 Jul 2025 06:26:07 +0200 Subject: [PATCH 285/871] [PWGLF] Improve event mixing (#11845) --- .../Tasks/Strangeness/lambdaspincorrderived.cxx | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/PWGLF/Tasks/Strangeness/lambdaspincorrderived.cxx b/PWGLF/Tasks/Strangeness/lambdaspincorrderived.cxx index 78bc5c5fa5e..978d5528a69 100644 --- a/PWGLF/Tasks/Strangeness/lambdaspincorrderived.cxx +++ b/PWGLF/Tasks/Strangeness/lambdaspincorrderived.cxx @@ -82,6 +82,14 @@ struct lambdaspincorrderived { { histos.add("hCentrality", "Centrality distribution", kTH1F, {{configThnAxisCentrality}}); + histos.add("hLambdaSameForLL", "hLambdaSameForLL", HistType::kTH3D, {{50, 0.0, 5.0}, {32, -0.8, 0.8}, {72, 0.0, 2.0 * TMath::Pi()}}, true); + histos.add("hLambdaSameForLAL", "hLambdaSameForLAL", HistType::kTH3D, {{50, 0.0, 5.0}, {32, -0.8, 0.8}, {72, 0.0, 2.0 * TMath::Pi()}}, true); + histos.add("hAntiLambdaSameForALAL", "hAntiLambdaSameForALAL", HistType::kTH3D, {{50, 0.0, 5.0}, {32, -0.8, 0.8}, {72, 0.0, 2.0 * TMath::Pi()}}, true); + + histos.add("hLambdaMixForLL", "hLambdaMixForLL", HistType::kTH3D, {{50, 0.0, 5.0}, {32, -0.8, 0.8}, {72, 0.0, 2.0 * TMath::Pi()}}, true); + histos.add("hLambdaMixForLAL", "hLambdaMixForLAL", HistType::kTH3D, {{50, 0.0, 5.0}, {32, -0.8, 0.8}, {72, 0.0, 2.0 * TMath::Pi()}}, true); + histos.add("hAntiLambdaMixForALAL", "hAntiLambdaMixForALAL", HistType::kTH3D, {{50, 0.0, 5.0}, {32, -0.8, 0.8}, {72, 0.0, 2.0 * TMath::Pi()}}, true); + histos.add("hSparseLambdaLambda", "hSparseLambdaLambda", HistType::kTHnSparseF, {configThnAxisInvMass, configThnAxisInvMass, configThnAxisPol, configThnAxisCentrality, configThnAxisR}, true); histos.add("hSparseLambdaAntiLambda", "hSparseLambdaAntiLambda", HistType::kTHnSparseF, {configThnAxisInvMass, configThnAxisInvMass, configThnAxisPol, configThnAxisCentrality, configThnAxisR}, true); histos.add("hSparseAntiLambdaAntiLambda", "hSparseAntiLambdaAntiLambda", HistType::kTHnSparseF, {configThnAxisInvMass, configThnAxisInvMass, configThnAxisPol, configThnAxisCentrality, configThnAxisR}, true); @@ -127,6 +135,9 @@ struct lambdaspincorrderived { template bool checkKinematics(T1 const& candidate1, T2 const& candidate2) { + if (candidate1.v0Status() != candidate2.v0Status()) { + return false; + } if (std::abs(candidate1.lambdaPt() - candidate2.lambdaPt()) > ptMix) { return false; } @@ -186,18 +197,24 @@ struct lambdaspincorrderived { if (datatype == 0) { if (tag1 == 0 && tag2 == 0) { histos.fill(HIST("hSparseLambdaLambda"), particle1.M(), particle2.M(), cosThetaDiff, centrality, deltaR); + histos.fill(HIST("hLambdaSameForLL"), particle1.Pt(), particle1.Eta(), RecoDecay::constrainAngle(particle1.Phi(), 0.0F)); } else if ((tag1 == 0 && tag2 == 1) || (tag1 == 1 && tag2 == 0)) { histos.fill(HIST("hSparseLambdaAntiLambda"), particle1.M(), particle2.M(), cosThetaDiff, centrality, deltaR); + histos.fill(HIST("hLambdaSameForLAL"), particle1.Pt(), particle1.Eta(), RecoDecay::constrainAngle(particle1.Phi(), 0.0F)); } else if (tag1 == 1 && tag2 == 1) { histos.fill(HIST("hSparseAntiLambdaAntiLambda"), particle1.M(), particle2.M(), cosThetaDiff, centrality, deltaR); + histos.fill(HIST("hAntiLambdaSameForALAL"), particle1.Pt(), particle1.Eta(), RecoDecay::constrainAngle(particle1.Phi(), 0.0F)); } } else if (datatype == 1) { if (tag1 == 0 && tag2 == 0) { histos.fill(HIST("hSparseLambdaLambdaMixed"), particle1.M(), particle2.M(), cosThetaDiff, centrality, deltaR); + histos.fill(HIST("hLambdaMixForLL"), particle1.Pt(), particle1.Eta(), RecoDecay::constrainAngle(particle1.Phi(), 0.0F)); } else if ((tag1 == 0 && tag2 == 1) || (tag1 == 1 && tag2 == 0)) { histos.fill(HIST("hSparseLambdaAntiLambdaMixed"), particle1.M(), particle2.M(), cosThetaDiff, centrality, deltaR); + histos.fill(HIST("hLambdaMixForLAL"), particle1.Pt(), particle1.Eta(), RecoDecay::constrainAngle(particle1.Phi(), 0.0F)); } else if (tag1 == 1 && tag2 == 1) { histos.fill(HIST("hSparseAntiLambdaAntiLambdaMixed"), particle1.M(), particle2.M(), cosThetaDiff, centrality, deltaR); + histos.fill(HIST("hAntiLambdaMixForALAL"), particle1.Pt(), particle1.Eta(), RecoDecay::constrainAngle(particle1.Phi(), 0.0F)); } } } From dfb6b1a00fc1917d074ea2e2d2f148dbc0711d03 Mon Sep 17 00:00:00 2001 From: Giovanni Malfattore <89481844+giovannimalfattore@users.noreply.github.com> Date: Tue, 1 Jul 2025 08:48:38 +0200 Subject: [PATCH 286/871] [PWGLF] NucleiTask - Add missing histo for DCA (#11837) --- PWGLF/Tasks/Nuspex/LFNucleiBATask.cxx | 471 +++++++++++++------------- 1 file changed, 235 insertions(+), 236 deletions(-) diff --git a/PWGLF/Tasks/Nuspex/LFNucleiBATask.cxx b/PWGLF/Tasks/Nuspex/LFNucleiBATask.cxx index 2f018baca7d..ea5e12d8ec4 100644 --- a/PWGLF/Tasks/Nuspex/LFNucleiBATask.cxx +++ b/PWGLF/Tasks/Nuspex/LFNucleiBATask.cxx @@ -42,7 +42,7 @@ #include "ReconstructionDataFormats/Track.h" #include -#include +// #include #include @@ -81,18 +81,18 @@ struct LFNucleiBATask { // Set the event selection cuts struct : ConfigurableGroup { 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)"}; } evselOptions; // Set the multiplity event limits - Configurable cfgLowMultCut{"cfgLowMultCut", 0.0f, "Accepted multiplicity percentage lower limit"}; - Configurable cfgHighMultCut{"cfgHighMultCut", 100.0f, "Accepted multiplicity percentage higher limit"}; + Configurable cfgMultCutLow{"cfgMultCutLow", 0.0f, "Accepted multiplicity percentage lower limit"}; + Configurable cfgMultCutHigh{"cfgMultCutHigh", 100.0f, "Accepted multiplicity percentage higher limit"}; // Set the z-vertex event cut limits - Configurable cfgHighCutVertex{"cfgHighCutVertex", 10.0f, "Accepted z-vertex upper limit"}; - Configurable cfgLowCutVertex{"cfgLowCutVertex", -10.0f, "Accepted z-vertex lower limit"}; + Configurable cfgVzCutLow{"cfgVzCutLow", -10.0f, "Accepted z-vertex lower limit"}; + Configurable cfgVzCutHigh{"cfgVzCutHigh", 10.0f, "Accepted z-vertex upper limit"}; // Set the quality cuts for tracks struct : ConfigurableGroup { @@ -108,10 +108,10 @@ struct LFNucleiBATask { // Set the kinematic and PID cuts for tracks struct : ConfigurableGroup { - Configurable pCut{"pCut", 0.3f, "Value of the p selection for spectra (default 0.3)"}; - Configurable etaCut{"etaCut", 0.8f, "Value of the eta selection for spectra (default 0.8)"}; - Configurable yLowCut{"yLowCut", -1.0f, "Value of the low rapidity selection for spectra (default -1.0)"}; - Configurable yHighCut{"yHighCut", 1.0f, "Value of the high rapidity selection for spectra (default 1.0)"}; + Configurable cfgMomentumCut{"cfgMomentumCut", 0.3f, "Value of the p selection for spectra (default 0.3)"}; + Configurable cfgEtaCut{"cfgEtaCut", 0.8f, "Value of the eta selection for spectra (default 0.8)"}; + Configurable cfgRapidityCutLow{"cfgRapidityCutLow", -1.0f, "Value of the low rapidity selection for spectra (default -1.0)"}; + Configurable cfgRapidityCutHigh{"cfgRapidityCutHigh", 1.0f, "Value of the high rapidity selection for spectra (default 1.0)"}; } kinemOptions; Configurable isPVContributorCut{"isPVContributorCut", false, "Flag to enable isPVContributor cut."}; @@ -132,7 +132,7 @@ struct LFNucleiBATask { } nsigmaITSvar; // Set additional cuts (used for debug) - Configurable betaCut{"betaCut", 0.4f, "Value of the beta selection for TOF cut (default 0.4)"}; + Configurable cfgBetaCut{"cfgBetaCut", 0.4f, "Value of the beta selection for TOF cut (default 0.4)"}; // Set the axis used in this task ConfigurableAxis binsPercentile{"binsPercentile", {100, 0, 100}, "Centrality FT0M"}; @@ -159,11 +159,11 @@ struct LFNucleiBATask { Configurable enableEvTimeSplitting{"enableEvTimeSplitting", false, "Flag to enable histograms splitting depending on the Event Time used"}; } filterOptions; - Configurable enableDCACustomCut{"enableDCACustomCut", false, "Flag to enable DCA custom cuts - unflag to use standard isGlobalCut DCA cut"}; + Configurable enableCustomDCACut{"enableCustomDCACut", false, "Flag to enable DCA custom cuts - unflag to use standard isGlobalCut DCA cut"}; struct : ConfigurableGroup { - Configurable DCACustomConfig{"DCACustomConfig", 0, "Select to use: pT independent DCAxy and DCAz CustomCut (0), pT dependent DCAxy and DCAz cut (1), pt dependent DCAxy, DCAz CustomCut (2) DCAxy CustomCut, pT dependent DCAz (3) or a circular DCAxy,z cut (4) for tracks. Need 'enableDCACustomCut' to be enabled."}; - Configurable DCAxyCustomCut{"DCAxyCustomCut", 0.05f, "Value of the DCAxy selection for spectra (default 0.05 cm)"}; - Configurable DCAzCustomCut{"DCAzCustomCut", 0.5f, "Value of the DCAz selection for spectra (default 0.5 cm)"}; + Configurable cfgCustomDCA{"cfgCustomDCA", 0, "Select to use: pT independent DCAxy and DCAz CustomCut (0), pT dependent DCAxy and DCAz cut (1), pt dependent DCAxy, DCAz CustomCut (2) DCAxy CustomCut, pT dependent DCAz (3) or a circular DCAxy,z cut (4) for tracks. Need 'enableCustomDCACut' to be enabled."}; + Configurable cfgCustomDCAxy{"cfgCustomDCAxy", 0.05f, "Value of the DCAxy selection for spectra (default 0.05 cm)"}; + Configurable cfgCustomDCAz{"cfgCustomDCAz", 0.5f, "Value of the DCAz selection for spectra (default 0.5 cm)"}; } dcaConfOptions; Configurable> parDCAxycuts{"parDCAxycuts", {0.004f, 0.013f, 1, 1}, "Parameters for Pt dependent DCAxy cut (if enabled): |DCAxy| < [3] * ([O] + [1]/Pt^[2])."}; @@ -179,18 +179,20 @@ struct LFNucleiBATask { Configurable enableExpSignalTPC{"enableExpSignalTPC", true, "Flag to export dEdX - dEdX(exp) plots."}; Configurable enableExpSignalTOF{"enableExpSignalTOF", false, "Flag to export T - T(exp) plots."}; Configurable enableBetaCut{"enableBetaCut", false, "Flag to enable TOF histograms with beta cut for debug"}; + Configurable enablePIDplot{"enablePIDplot", false, "Flag to enable PID histograms for debug"}; + Configurable enableEffPlots{"enableEffPlots", false, "Flag to enable histograms for efficiency debug."}; + Configurable enableNoTOFPlots{"enableNoTOFPlots", false, "Flag to enable histograms for TOF debug."}; + } outFlagOptions; - Configurable enablePIDplot{"enablePIDplot", false, "Flag to enable PID histograms for debug"}; Configurable enableDebug{"enableDebug", false, "Flag to enable histograms for debug"}; - Configurable enablePtSpectra{"enablePtSpectra", false, "Flag to enable histograms for efficiency debug."}; Configurable usenITSLayer{"usenITSLayer", false, "Flag to enable ITS layer hit"}; Configurable useHasTRDConfig{"useHasTRDConfig", 0, "No selections on TRD (0); With TRD (1); Without TRD (2)"}; Configurable massTOFConfig{"massTOFConfig", 0, "Estimate massTOF using beta with (0) TPC momentum (1) TOF expected momentum (2) p momentum."}; Configurable helium3Pt{"helium3Pt", 0, "Select use default pT (0) or use instead 2*pT (1) for helium-3"}; - Configurable DeuteronPt{"DeuteronPt", 0, "Select (0) to apply deuteron pT shift or (1) to use default pT."}; - Configurable antiDeuteronPt{"antiDeuteronPt", 0, "Select (0) to apply antideuteron pT shift or (1) to use default pT."}; + Configurable unableDPtShift{"unableDPtShift", 0, "Select (0) to apply deuteron pT shift or (1) to use default pT."}; + Configurable unableAntiDPtShift{"unableAntiDPtShift", 0, "Select (0) to apply antideuteron pT shift or (1) to use default pT."}; // Additional function used for pT-shift calibration TF1* fShiftPtHe = 0; @@ -198,30 +200,30 @@ struct LFNucleiBATask { TF1* fShiftAntiD = 0; TF1* fShiftD = 0; - Configurable enablePtShiftAntiD{"enablePtShiftAntiD", true, "Flag to enable Pt shift (for antiDeuteron only)"}; Configurable enablePtShiftD{"enablePtShiftD", true, "Flag to enable Pt shift (for Deuteron only)"}; - Configurable> parShiftPtAntiD{"parShiftPtAntiD", {-0.0955412, 0.798164, -0.536111, 0.0887876, -1.11022e-13}, "Parameters for Pt shift (if enabled)."}; + Configurable enablePtShiftAntiD{"enablePtShiftAntiD", true, "Flag to enable Pt shift (for antiDeuteron only)"}; Configurable> parShiftPtD{"parShiftPtD", {-0.0955412, 0.798164, -0.536111, 0.0887876, -1.11022e-13}, "Parameters for Pt shift (if enabled)."}; + Configurable> parShiftPtAntiD{"parShiftPtAntiD", {-0.0955412, 0.798164, -0.536111, 0.0887876, -1.11022e-13}, "Parameters for Pt shift (if enabled)."}; - Configurable enablePtShift{"enablePtShift", false, "Flag to enable Pt shift (for He only)"}; + Configurable enablePtShiftHe{"enablePtShiftHe", false, "Flag to enable Pt shift (for He only)"}; Configurable> parShiftPtHe{"parShiftPtHe", {0.0f, 0.1f, 0.1f, 0.1f, 0.1f}, "Parameters for helium3-Pt shift (if enabled)."}; - Configurable> parShiftPtantiHe{"parShiftPtantiHe", {0.0f, 0.1f, 0.1f, 0.1f, 0.1f}, "Parameters for anti-helium3-Pt shift (if enabled)."}; + Configurable> parShiftPtAntiHe{"parShiftPtAntiHe", {0.0f, 0.1f, 0.1f, 0.1f, 0.1f}, "Parameters for anti-helium3-Pt shift (if enabled)."}; Configurable enableCentrality{"enableCentrality", true, "Flag to enable centrality 3D histos)"}; // PDG codes and masses used in this analysis - static constexpr int PDGPion = 211; - static constexpr int PDGKaon = 321; - static constexpr int PDGProton = 2212; - static constexpr int PDGDeuteron = 1000010020; - static constexpr int PDGTriton = 1000010030; - static constexpr int PDGHelium = 1000020030; - static constexpr int PDGAlpha = 1000020040; - static constexpr float MassProtonVal = 0.938272088f; - static constexpr float MassDeuteronVal = 1.87561f; - static constexpr float MassTritonVal = 2.80892f; - static constexpr float MassHeliumVal = 2.80839f; - static constexpr float MassAlphaVal = 3.72738f; + static constexpr int PDGPion = PDG_t::kPiPlus; + static constexpr int PDGKaon = PDG_t::kKPlus; + static constexpr int PDGProton = PDG_t::kProton; + static constexpr int PDGDeuteron = o2::constants::physics::Pdg::kDeuteron; + static constexpr int PDGTriton = o2::constants::physics::Pdg::kTriton; + static constexpr int PDGHelium = o2::constants::physics::Pdg::kHelium3; + static constexpr int PDGAlpha = o2::constants::physics::Pdg::kAlpha; + static constexpr float MassProtonVal = o2::constants::physics::MassProton; + static constexpr float MassDeuteronVal = o2::constants::physics::MassDeuteron; + static constexpr float MassTritonVal = o2::constants::physics::MassTriton; + static constexpr float MassHeliumVal = o2::constants::physics::MassHelium3; + static constexpr float MassAlphaVal = o2::constants::physics::MassAlpha; template float averageClusterSizeTrk(const TrackType& track) @@ -346,7 +348,7 @@ struct LFNucleiBATask { h->GetXaxis()->SetBinLabel(8, "Multiplicity cut"); histos.add("event/h1VtxZ", "V_{z};V_{z} (in cm); counts", HistType::kTH1F, {{1500, -15, 15}}); - if (enablePIDplot) { + if (outFlagOptions.enablePIDplot) { histos.add("tracks/h1pT", "Track #it{p}_{T}; #it{p}_{T} (GeV/#it{c}); counts", HistType::kTH1F, {{500, 0., 10.}}); histos.add("tracks/h1p", "Track momentum; p (GeV/#it{c}); counts", HistType::kTH1F, {{500, 0., 10.}}); } @@ -358,7 +360,7 @@ struct LFNucleiBATask { histos.add("qa/h1chi2ITS", "#chi^{2}_{ITS}/n_{ITS}; #chi^{2}_{ITS}/n_{ITS};counts", HistType::kTH1F, {{51, -0.5, 50.5}}); histos.add("qa/h1chi2TPC", "#chi^{2}_{TPC}/n_{TPC}; #chi^{2}_{TPC}/n_{TPC}; counts", HistType::kTH1F, {{11, -0.5, 10.5}}); - if (enablePtSpectra) { + if (outFlagOptions.enableEffPlots) { histos.add("tracks/eff/h2pVsTPCmomentum", "#it{p}_{TPC} vs #it{p}; #it{p}_{TPC}; #it{p}", HistType::kTH2F, {{200, 0.f, 8.f}, {200, 0.f, 8.f}}); if (outFlagOptions.doTOFplots) histos.add("tracks/eff/h2TPCmomentumVsTOFExpMomentum", "#it{p}_{TOF} vs #it{p}_{TPC}; #it{p}_{TOF}; #it{p}_{TPC}", HistType::kTH2F, {{200, 0.f, 8.f}, {200, 0.f, 8.f}}); @@ -414,7 +416,7 @@ struct LFNucleiBATask { debugHistos.add("debug/tracks/h2PionYvsPt", "#it{y} vs #it{p}_{T} (#pi)", HistType::kTH2F, {{200, -2.0, 2.0}, {ptAxis}}); } - if (enablePtSpectra) { + if (outFlagOptions.enableEffPlots) { if (enableDebug) { debugHistos.add("tracks/eff/hPtP", "Track #it{p}_{T}; #it{p}_{T} (GeV/#it{c}); counts", HistType::kTH1F, {{400, 0., 8.}}); debugHistos.add("tracks/eff/hPtantiP", "Track #it{p}_{T}; #it{p}_{T} (GeV/#it{c}); counts", HistType::kTH1F, {{400, 0., 8.}}); @@ -469,16 +471,12 @@ struct LFNucleiBATask { histos.add("tracks/dca/before/hDCAzVsPt", "DCAz vs Pt", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); if (enablePr) { - // histos.add("tracks/proton/dca/before/hDCAxyVsDCAzVsPtProton", "DCAxy vs DCAz vs Pt/z (p)", HistType::kTH3F, {{140, -0.7f, 0.7f}, {160, -0.8f, 0.8f}, {binsPtHe}}); - // histos.add("tracks/proton/dca/before/hDCAxyVsDCAzVsPtantiProton", "DCAxy vs DCAz vs Pt/z (#bar{p})", HistType::kTH3F, {{140, -0.7f, 0.7f}, {160, -0.8f, 0.8f}, {binsPtHe}}); histos.add("tracks/proton/dca/before/hDCAxyVsPtProton", "DCAxy vs Pt (p)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); histos.add("tracks/proton/dca/before/hDCAxyVsPtantiProton", "DCAxy vs Pt (#bar{p})", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); histos.add("tracks/proton/dca/before/hDCAzVsPtProton", "DCAz vs Pt (p)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); histos.add("tracks/proton/dca/before/hDCAzVsPtantiProton", "DCAz vs Pt (#bar{p})", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); } if (enableDe) { - // histos.add("tracks/deuteron/dca/before/hDCAxyVsDCAzVsPtDeuteron", "DCAxy vs DCAz vs Pt/z (d)", HistType::kTH3F, {{140, -0.7f, 0.7f}, {160, -0.8f, 0.8f}, {binsPtHe}}); - // histos.add("tracks/deuteron/dca/before/hDCAxyVsDCAzVsPtantiDeuteron", "DCAxy vs DCAz vs Pt/z (#bar{d})", HistType::kTH3F, {{140, -0.7f, 0.7f}, {160, -0.8f, 0.8f}, {binsPtHe}}); if (enableCentrality) { histos.add("tracks/deuteron/dca/before/hDCAxyVsPtDeuteronVsMult", "DCAxy vs Pt (d)", HistType::kTH3F, {{ptAxis}, {dcaxyAxis}, {binsPercentile}}); histos.add("tracks/deuteron/dca/before/hDCAxyVsPtantiDeuteronVsMult", "DCAxy vs Pt (#bar{d})", HistType::kTH3F, {{ptAxis}, {dcaxyAxis}, {binsPercentile}}); @@ -489,14 +487,14 @@ struct LFNucleiBATask { histos.add("tracks/deuteron/dca/before/hDCAzVsPtDeuteron", "DCAz vs Pt (d)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); histos.add("tracks/deuteron/dca/before/hDCAzVsPtantiDeuteron", "DCAz vs Pt (#bar{d})", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); - histos.add("tracks/deuteron/dca/before/hDCAxyVsPtDeuteronNoTOF", "DCAxy vs Pt (d)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); - histos.add("tracks/deuteron/dca/before/hDCAxyVsPtantiDeuteronNoTOF", "DCAxy vs Pt (#bar{d})", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); - histos.add("tracks/deuteron/dca/before/hDCAzVsPtDeuteronNoTOF", "DCAz vs Pt (d)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); - histos.add("tracks/deuteron/dca/before/hDCAzVsPtantiDeuteronNoTOF", "DCAz vs Pt (#bar{d})", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + if (outFlagOptions.enableNoTOFPlots) { + histos.add("tracks/deuteron/dca/before/hDCAxyVsPtDeuteronNoTOF", "DCAxy vs Pt (d)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + histos.add("tracks/deuteron/dca/before/hDCAxyVsPtantiDeuteronNoTOF", "DCAxy vs Pt (#bar{d})", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + histos.add("tracks/deuteron/dca/before/hDCAzVsPtDeuteronNoTOF", "DCAz vs Pt (d)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + histos.add("tracks/deuteron/dca/before/hDCAzVsPtantiDeuteronNoTOF", "DCAz vs Pt (#bar{d})", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + } } if (enableTr) { - // histos.add("tracks/triton/dca/before/hDCAxyVsDCAzVsPtTriton", "DCAxy vs DCAz vs Pt/z (t)", HistType::kTH3F, {{140, -0.7f, 0.7f}, {160, -0.8f, 0.8f}, {binsPtHe}}); - // histos.add("tracks/triton/dca/before/hDCAxyVsDCAzVsPtantiTriton", "DCAxy vs DCAz vs Pt/z (#bar{t})", HistType::kTH3F, {{140, -0.7f, 0.7f}, {160, -0.8f, 0.8f}, {binsPtHe}}); histos.add("tracks/triton/dca/before/hDCAxyVsPtTriton", "DCAxy vs Pt (t)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); histos.add("tracks/triton/dca/before/hDCAxyVsPtantiTriton", "DCAxy vs Pt (#bar{t})", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); histos.add("tracks/triton/dca/before/hDCAzVsPtTriton", "DCAz vs Pt (t)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); @@ -510,10 +508,12 @@ struct LFNucleiBATask { histos.add("tracks/helium/dca/before/hDCAzVsPtHelium", "DCAz vs Pt (He)", HistType::kTH2F, {{ptZHeAxis}, {dcazAxis}}); histos.add("tracks/helium/dca/before/hDCAzVsPtantiHelium", "DCAz vs Pt (#bar{He})", HistType::kTH2F, {{ptZHeAxis}, {dcazAxis}}); - histos.add("tracks/helium/dca/before/hDCAxyVsPtHeliumNoTOF", "DCAxy vs Pt (He)", HistType::kTH2F, {{ptZHeAxis}, {dcaxyAxis}}); - histos.add("tracks/helium/dca/before/hDCAxyVsPtantiHeliumNoTOF", "DCAxy vs Pt (#bar{He})", HistType::kTH2F, {{ptZHeAxis}, {dcaxyAxis}}); - histos.add("tracks/helium/dca/before/hDCAzVsPtHeliumNoTOF", "DCAz vs Pt (He)", HistType::kTH2F, {{ptZHeAxis}, {dcazAxis}}); - histos.add("tracks/helium/dca/before/hDCAzVsPtantiHeliumNoTOF", "DCAz vs Pt (#bar{He})", HistType::kTH2F, {{ptZHeAxis}, {dcazAxis}}); + if (outFlagOptions.enableNoTOFPlots) { + histos.add("tracks/helium/dca/before/hDCAxyVsPtHeliumNoTOF", "DCAxy vs Pt (He)", HistType::kTH2F, {{ptZHeAxis}, {dcaxyAxis}}); + histos.add("tracks/helium/dca/before/hDCAxyVsPtantiHeliumNoTOF", "DCAxy vs Pt (#bar{He})", HistType::kTH2F, {{ptZHeAxis}, {dcaxyAxis}}); + histos.add("tracks/helium/dca/before/hDCAzVsPtHeliumNoTOF", "DCAz vs Pt (He)", HistType::kTH2F, {{ptZHeAxis}, {dcazAxis}}); + histos.add("tracks/helium/dca/before/hDCAzVsPtantiHeliumNoTOF", "DCAz vs Pt (#bar{He})", HistType::kTH2F, {{ptZHeAxis}, {dcazAxis}}); + } if (outFlagOptions.doTOFplots) { histos.add("tracks/helium/dca/before/TOF/hDCAxyVsDCAzVsPtHelium", "DCAxy vs DCAz vs Pt/z (He) (w/TOF); DCAxy; DCAz", HistType::kTH3F, {{140, -0.7f, 0.7f}, {160, -0.8f, 0.8f}, {binsPtZHe}}); @@ -525,8 +525,6 @@ struct LFNucleiBATask { } } if (enableAl) { - // histos.add("tracks/alpha/dca/before/hDCAxyVsDCAzVsPtAlpha", "DCAxy vs DCAz vs Pt/z (#alpha)", HistType::kTH3F, {{140, -0.7f, 0.7f}, {160, -0.8f, 0.8f}, {binsPtZHe}}); - // histos.add("tracks/alpha/dca/before/hDCAxyVsDCAzVsPtantiAlpha", "DCAxy vs DCAz vs Pt/z (#bar{#alpha})", HistType::kTH3F, {{140, -0.7f, 0.7f}, {160, -0.8f, 0.8f}, {binsPtZHe}}); histos.add("tracks/alpha/dca/before/hDCAxyVsPtAlpha", "DCAxy vs Pt (#alpha)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); histos.add("tracks/alpha/dca/before/hDCAxyVsPtantiAlpha", "DCAxy vs Pt (#bar{#alpha})", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); histos.add("tracks/alpha/dca/before/hDCAzVsPtAlpha", "DCAz vs Pt (#alpha)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); @@ -819,11 +817,11 @@ struct LFNucleiBATask { histos.add("tracks/triton/h1antiTritonSpectraTrueTransport", "#it{p}_{T} (#bar{t})", HistType::kTH1F, {ptAxis}); } if (enableHe) { - histos.add("tracks/helium/h1HeliumSpectraTrue", "#it{p}_{T}/z (He)", HistType::kTH1F, {ptZHeAxis}); - histos.add("tracks/helium/h1HeliumSpectraTrueWPID", "#it{p}_{T}/z (He)", HistType::kTH1F, {ptZHeAxis}); - histos.add("tracks/helium/h1HeliumSpectraTruePrim", "#it{p}_{T}/z (He)", HistType::kTH1F, {ptZHeAxis}); - histos.add("tracks/helium/h1HeliumSpectraTrueSec", "#it{p}_{T}/z (He)", HistType::kTH1F, {ptZHeAxis}); - histos.add("tracks/helium/h1HeliumSpectraTrueTransport", "#it{p}_{T}/z (He)", HistType::kTH1F, {ptZHeAxis}); + // histos.add("tracks/helium/h1HeliumSpectraTrue", "#it{p}_{T}/z (He)", HistType::kTH1F, {ptZHeAxis}); + // histos.add("tracks/helium/h1HeliumSpectraTrueWPID", "#it{p}_{T}/z (He)", HistType::kTH1F, {ptZHeAxis}); + // histos.add("tracks/helium/h1HeliumSpectraTruePrim", "#it{p}_{T}/z (He)", HistType::kTH1F, {ptZHeAxis}); + // histos.add("tracks/helium/h1HeliumSpectraTrueSec", "#it{p}_{T}/z (He)", HistType::kTH1F, {ptZHeAxis}); + // histos.add("tracks/helium/h1HeliumSpectraTrueTransport", "#it{p}_{T}/z (He)", HistType::kTH1F, {ptZHeAxis}); histos.add("tracks/helium/h1HeliumSpectraTrue_Z2", "#it{p}_{T} (He)", HistType::kTH1F, {ptHeAxis}); histos.add("tracks/helium/h1HeliumSpectraTrueWPID_Z2", "#it{p}_{T} (He)", HistType::kTH1F, {ptHeAxis}); @@ -831,11 +829,11 @@ struct LFNucleiBATask { histos.add("tracks/helium/h1HeliumSpectraTrueSec_Z2", "#it{p}_{T} (He)", HistType::kTH1F, {ptHeAxis}); histos.add("tracks/helium/h1HeliumSpectraTrueTransport_Z2", "#it{p}_{T} (He)", HistType::kTH1F, {ptHeAxis}); - histos.add("tracks/helium/h1antiHeliumSpectraTrue", "#it{p}_{T}/z (He)", HistType::kTH1F, {ptZHeAxis}); - histos.add("tracks/helium/h1antiHeliumSpectraTrueWPID", "#it{p}_{T}/z (He)", HistType::kTH1F, {ptZHeAxis}); - histos.add("tracks/helium/h1antiHeliumSpectraTruePrim", "#it{p}_{T}/z (He)", HistType::kTH1F, {ptZHeAxis}); - histos.add("tracks/helium/h1antiHeliumSpectraTrueSec", "#it{p}_{T}/z (He)", HistType::kTH1F, {ptZHeAxis}); - histos.add("tracks/helium/h1antiHeliumSpectraTrueTransport", "#it{p}_{T}/z (He)", HistType::kTH1F, {ptZHeAxis}); + // histos.add("tracks/helium/h1antiHeliumSpectraTrue", "#it{p}_{T}/z (He)", HistType::kTH1F, {ptZHeAxis}); + // histos.add("tracks/helium/h1antiHeliumSpectraTrueWPID", "#it{p}_{T}/z (He)", HistType::kTH1F, {ptZHeAxis}); + // histos.add("tracks/helium/h1antiHeliumSpectraTruePrim", "#it{p}_{T}/z (He)", HistType::kTH1F, {ptZHeAxis}); + // histos.add("tracks/helium/h1antiHeliumSpectraTrueSec", "#it{p}_{T}/z (He)", HistType::kTH1F, {ptZHeAxis}); + // histos.add("tracks/helium/h1antiHeliumSpectraTrueTransport", "#it{p}_{T}/z (He)", HistType::kTH1F, {ptZHeAxis}); histos.add("tracks/helium/h1antiHeliumSpectraTrue_Z2", "#it{p}_{T} (He)", HistType::kTH1F, {ptHeAxis}); histos.add("tracks/helium/h1antiHeliumSpectraTrueWPID_Z2", "#it{p}_{T} (He)", HistType::kTH1F, {ptHeAxis}); @@ -847,12 +845,12 @@ struct LFNucleiBATask { histos.add("tracks/helium/TOF/h1HeliumSpectraTruePrim_Z2", "#it{p}_{T} (He)", HistType::kTH1F, {ptHeAxis}); histos.add("tracks/helium/TOF/h1antiHeliumSpectraTruePrim_Z2", "#it{p}_{T} (He)", HistType::kTH1F, {ptHeAxis}); } - if (enablePtSpectra) { - histos.add("tracks/eff/helium/hPtHeTrue", "Track #it{p}_{T} (He); #it{p}_{T} (GeV/#it{c}); counts", HistType::kTH1F, {{400, 0., 8.}}); - histos.add("tracks/eff/helium/hPtantiHeTrue", "Track #it{p}_{T} (#bar{He}); #it{p}_{T} (GeV/#it{c}); counts", HistType::kTH1F, {{400, 0., 8.}}); + if (outFlagOptions.enableEffPlots) { + histos.add("tracks/eff/helium/hPtHeTrue_Z2", "Track #it{p}_{T} (He); #it{p}_{T} (GeV/#it{c}); counts", HistType::kTH1F, {{400, 0., 8.}}); + histos.add("tracks/eff/helium/hPtantiHeTrue_Z2", "Track #it{p}_{T} (#bar{He}); #it{p}_{T} (GeV/#it{c}); counts", HistType::kTH1F, {{400, 0., 8.}}); if (outFlagOptions.doTOFplots) { - histos.add("tracks/eff/helium/hPtHeTOFTrue", "Track #it{p}_{T} (He); #it{p}_{T} (GeV/#it{c}); counts", HistType::kTH1F, {{400, 0., 8.}}); - histos.add("tracks/eff/helium/hPtantiHeTOFTrue", "Track #it{p}_{T} (#bar{He}); #it{p}_{T} (GeV/#it{c}); counts", HistType::kTH1F, {{400, 0., 8.}}); + histos.add("tracks/eff/helium/hPtHeTOFTrue_Z2", "Track #it{p}_{T} (He); #it{p}_{T} (GeV/#it{c}); counts", HistType::kTH1F, {{400, 0., 8.}}); + histos.add("tracks/eff/helium/hPtantiHeTOFTrue_Z2", "Track #it{p}_{T} (#bar{He}); #it{p}_{T} (GeV/#it{c}); counts", HistType::kTH1F, {{400, 0., 8.}}); } } } @@ -1187,12 +1185,14 @@ struct LFNucleiBATask { histos.add("tracks/helium/dca/before/fake/hDCAxyVsPtHeliumTruePrim", "DCAxy vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcaxyAxis}}); histos.add("tracks/helium/dca/before/fake/hDCAxyVsPtHeliumTrueSec", "DCAxy vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcaxyAxis}}); + histos.add("tracks/helium/dca/before/fake/hDCAxyVsPtHeliumTrueMaterial", "DCAxy vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcaxyAxis}}); histos.add("tracks/helium/dca/before/fake/hDCAxyVsPtHeliumTrueTransport", "DCAxy vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcaxyAxis}}); histos.add("tracks/helium/dca/before/fake/hDCAxyVsPtantiHeliumTrue", "DCAxy vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcaxyAxis}}); histos.add("tracks/helium/dca/before/fake/hDCAxyVsPtantiHeliumTruePrim", "DCAxy vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcaxyAxis}}); histos.add("tracks/helium/dca/before/fake/hDCAxyVsPtantiHeliumTrueSec", "DCAxy vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcaxyAxis}}); + histos.add("tracks/helium/dca/before/fake/hDCAxyVsPtantiHeliumTrueMaterial", "DCAxy vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcaxyAxis}}); histos.add("tracks/helium/dca/before/fake/hDCAxyVsPtantiHeliumTrueTransport", "DCAxy vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcaxyAxis}}); histos.add("tracks/helium/dca/before/fake/hDCAzVsPtHeliumTrue", "DCAz vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcazAxis}}); @@ -1517,7 +1517,7 @@ struct LFNucleiBATask { } // Bethe-Bloch TPC distribution and Beta vs pT TOF distribution - if (nsigmaITSvar.showAverageClusterSize && enablePIDplot) { + if (nsigmaITSvar.showAverageClusterSize && outFlagOptions.enablePIDplot) { histos.add("tracks/averageClusterSize", "", HistType::kTH2F, {{pZAxis}, {avClsAxis}}); histos.add("tracks/averageClusterSizePerCoslInv", "", HistType::kTH2F, {{pZAxis}, {avClsEffAxis}}); } @@ -1525,27 +1525,27 @@ struct LFNucleiBATask { debugHistos.add("debug/h2TPCsignVsTPCmomentum_AllTracks", "TPC <-dE/dX> vs #it{p}/Z (w/o rejection); Signed #it{p} (GeV/#it{c}); TPC <-dE/dx> (a.u.)", HistType::kTH2F, {{400, -8.f, 8.f}, {dedxAxis}}); debugHistos.add("debug/h2TPCsignVsTPCmomentum_FakeHits", "TPC <-dE/dX> vs #it{p}/Z (Fake hits); Signed #it{p} (GeV/#it{c}); TPC <-dE/dx> (a.u.)", HistType::kTH2F, {{400, -8.f, 8.f}, {dedxAxis}}); } - if (enablePIDplot) { + if (outFlagOptions.enablePIDplot) { histos.add("tracks/h2TPCsignVsTPCmomentum", "TPC <-dE/dX> vs #it{p}/Z; Signed #it{p} (GeV/#it{c}); TPC <-dE/dx> (a.u.)", HistType::kTH2F, {{400, -8.f, 8.f}, {dedxAxis}}); if (enablePr) { - histos.add("tracks/proton/h2TPCsignVsTPCmomentumProton", "TPC <-dE/dX> vs #it{p}/Z; Signed #it{p} (GeV/#it{c}); TPC <-dE/dx> (a.u.)", HistType::kTH2F, {{400, 0.f, 8.f}, {dedxAxis}}); - histos.add("tracks/proton/h2TPCsignVsTPCmomentumantiProton", "TPC <-dE/dX> vs #it{p}/Z; Signed #it{p} (GeV/#it{c}); TPC <-dE/dx> (a.u.)", HistType::kTH2F, {{400, 0.f, 8.f}, {dedxAxis}}); + histos.add("tracks/proton/h2TPCsignVsTPCmomentumProton", "TPC <-dE/dX> vs #it{p}/Z; Signed #it{p} (GeV/#it{c}); TPC <-dE/dx> (a.u.)", HistType::kTH2F, {{200, 0.f, 8.f}, {dedxAxis}}); + histos.add("tracks/proton/h2TPCsignVsTPCmomentumantiProton", "TPC <-dE/dX> vs #it{p}/Z; Signed #it{p} (GeV/#it{c}); TPC <-dE/dx> (a.u.)", HistType::kTH2F, {{200, 0.f, 8.f}, {dedxAxis}}); } if (enableDe) { - histos.add("tracks/deuteron/h2TPCsignVsTPCmomentumDeuteron", "TPC <-dE/dX> vs #it{p}/Z; Signed #it{p} (GeV/#it{c}); TPC <-dE/dx> (a.u.)", HistType::kTH2F, {{400, 0.f, 8.f}, {dedxAxis}}); - histos.add("tracks/deuteron/h2TPCsignVsTPCmomentumantiDeuteron", "TPC <-dE/dX> vs #it{p}/Z; Signed #it{p} (GeV/#it{c}); TPC <-dE/dx> (a.u.)", HistType::kTH2F, {{400, 0.f, 8.f}, {dedxAxis}}); + histos.add("tracks/deuteron/h2TPCsignVsTPCmomentumDeuteron", "TPC <-dE/dX> vs #it{p}/Z; Signed #it{p} (GeV/#it{c}); TPC <-dE/dx> (a.u.)", HistType::kTH2F, {{200, 0.f, 8.f}, {dedxAxis}}); + histos.add("tracks/deuteron/h2TPCsignVsTPCmomentumantiDeuteron", "TPC <-dE/dX> vs #it{p}/Z; Signed #it{p} (GeV/#it{c}); TPC <-dE/dx> (a.u.)", HistType::kTH2F, {{200, 0.f, 8.f}, {dedxAxis}}); } if (enableTr) { - histos.add("tracks/triton/h2TPCsignVsTPCmomentumTriton", "TPC <-dE/dX> vs #it{p}/Z; Signed #it{p} (GeV/#it{c}); TPC <-dE/dx> (a.u.)", HistType::kTH2F, {{400, 0.f, 8.f}, {dedxAxis}}); - histos.add("tracks/triton/h2TPCsignVsTPCmomentumantiTriton", "TPC <-dE/dX> vs #it{p}/Z; Signed #it{p} (GeV/#it{c}); TPC <-dE/dx> (a.u.)", HistType::kTH2F, {{400, 0.f, 8.f}, {dedxAxis}}); + histos.add("tracks/triton/h2TPCsignVsTPCmomentumTriton", "TPC <-dE/dX> vs #it{p}/Z; Signed #it{p} (GeV/#it{c}); TPC <-dE/dx> (a.u.)", HistType::kTH2F, {{200, 0.f, 8.f}, {dedxAxis}}); + histos.add("tracks/triton/h2TPCsignVsTPCmomentumantiTriton", "TPC <-dE/dX> vs #it{p}/Z; Signed #it{p} (GeV/#it{c}); TPC <-dE/dx> (a.u.)", HistType::kTH2F, {{200, 0.f, 8.f}, {dedxAxis}}); } if (enableHe) { - histos.add("tracks/helium/h2TPCsignVsTPCmomentumHelium", "TPC <-dE/dX> vs #it{p}/Z; Signed #it{p} (GeV/#it{c}); TPC <-dE/dx> (a.u.)", HistType::kTH2F, {{400, 0.f, 8.f}, {dedxAxis}}); - histos.add("tracks/helium/h2TPCsignVsTPCmomentumantiHelium", "TPC <-dE/dX> vs #it{p}/Z; Signed #it{p} (GeV/#it{c}); TPC <-dE/dx> (a.u.)", HistType::kTH2F, {{400, 0.f, 8.f}, {dedxAxis}}); + histos.add("tracks/helium/h2TPCsignVsTPCmomentumHelium", "TPC <-dE/dX> vs #it{p}/Z; Signed #it{p} (GeV/#it{c}); TPC <-dE/dx> (a.u.)", HistType::kTH2F, {{200, 0.f, 8.f}, {dedxAxis}}); + histos.add("tracks/helium/h2TPCsignVsTPCmomentumantiHelium", "TPC <-dE/dX> vs #it{p}/Z; Signed #it{p} (GeV/#it{c}); TPC <-dE/dx> (a.u.)", HistType::kTH2F, {{200, 0.f, 8.f}, {dedxAxis}}); } if (enableAl) { - histos.add("tracks/alpha/h2TPCsignVsTPCmomentumAlpha", "TPC <-dE/dX> vs #it{p}/Z; Signed #it{p} (GeV/#it{c}); TPC <-dE/dx> (a.u.)", HistType::kTH2F, {{400, 0.f, 8.f}, {dedxAxis}}); - histos.add("tracks/alpha/h2TPCsignVsTPCmomentumantiAlpha", "TPC <-dE/dX> vs #it{p}/Z; Signed #it{p} (GeV/#it{c}); TPC <-dE/dx> (a.u.)", HistType::kTH2F, {{400, 0.f, 8.f}, {dedxAxis}}); + histos.add("tracks/alpha/h2TPCsignVsTPCmomentumAlpha", "TPC <-dE/dX> vs #it{p}/Z; Signed #it{p} (GeV/#it{c}); TPC <-dE/dx> (a.u.)", HistType::kTH2F, {{200, 0.f, 8.f}, {dedxAxis}}); + histos.add("tracks/alpha/h2TPCsignVsTPCmomentumantiAlpha", "TPC <-dE/dX> vs #it{p}/Z; Signed #it{p} (GeV/#it{c}); TPC <-dE/dx> (a.u.)", HistType::kTH2F, {{200, 0.f, 8.f}, {dedxAxis}}); } } @@ -1556,7 +1556,7 @@ struct LFNucleiBATask { } } - if (outFlagOptions.doTOFplots && enablePIDplot) { + if (outFlagOptions.doTOFplots && outFlagOptions.enablePIDplot) { histos.add("tracks/h2TPCsignVsBetaGamma", "TPC <-dE/dX> vs #beta#gamma/Z; Signed #beta#gamma; TPC <-dE/dx> (a.u.)", HistType::kTH2F, {{250, -5.f, 5.f}, {dedxAxis}}); histos.add("tracks/h2TOFbetaVsP", "TOF #beta vs #it{p}/Z; Signed #it{p} (GeV/#it{c}); TOF #beta", HistType::kTH2F, {{250, -5.f, 5.f}, {betaAxis}}); if (outFlagOptions.enableBetaCut) @@ -1684,7 +1684,7 @@ struct LFNucleiBATask { histos.add("tracks/helium/h2antiHeliumVspTNSigmaTOF", "NSigmaTOF(#bar{He}) vs #it{p}_{T}/z; #it{p}_{T}/z (GeV/#it{c}); NSigmaTOF", HistType::kTH2F, {{ptZHeAxis}, {sigmaTOFAxis}}); } // TOF mass histograms - if (enablePIDplot) + if (outFlagOptions.enablePIDplot) histos.add("tracks/h2TOFmassVsPt", "h2TOFmassVsPt; TOFmass; #it{p}_{T} (GeV)", HistType::kTH2F, {{180, 0.4, 4.}, {250, 0., 5.}}); if (enablePr) { histos.add("tracks/proton/h2TOFmassProtonVsPt", "h2TOFmassProtonVsPt; TOFmass; #it{p}_{T} (GeV)", HistType::kTH2F, {{180, 0.4, 4.}, {250, 0., 5.}}); @@ -2103,7 +2103,7 @@ struct LFNucleiBATask { if constexpr (!IsFilteredData) { if (!event.selection_bit(aod::evsel::kIsTriggerTVX)) { - if (evselOptions.TVXtrigger) + if (evselOptions.useTVXtrigger) return; } else { histos.fill(HIST("event/eventSelection"), 1); @@ -2141,18 +2141,17 @@ struct LFNucleiBATask { if (enableDebug) debugHistos.fill(HIST("qa/h1VtxZ_sel8"), event.posZ()); - if (event.posZ() < cfgLowCutVertex || event.posZ() > cfgHighCutVertex) + if (event.posZ() < cfgVzCutLow || event.posZ() > cfgVzCutHigh) return; histos.fill(HIST("event/eventSelection"), 6); } else { - if (event.posZ() < cfgLowCutVertex || event.posZ() > cfgHighCutVertex) + if (event.posZ() < cfgVzCutLow || event.posZ() > cfgVzCutHigh) return; if (evselOptions.removeTFBorder && !event.selection_bit(aod::evsel::kNoTimeFrameBorder)) return; } - - if (event.centFT0M() < cfgLowMultCut || event.centFT0M() > cfgHighMultCut) { + if (event.centFT0M() < cfgMultCutLow || event.centFT0M() > cfgMultCutHigh) { return; } histos.fill(HIST("event/eventSelection"), 7); @@ -2210,7 +2209,14 @@ struct LFNucleiBATask { if ((track.itsChi2NCl() < itsChi2NclRange[0]) || (track.itsChi2NCl() > itsChi2NclRange[1])) continue; - if (enablePIDplot) { + // p cut + if (std::abs(track.tpcInnerParam()) < kinemOptions.cfgMomentumCut) + continue; + // eta cut + if (std::abs(track.eta()) > kinemOptions.cfgEtaCut) + continue; + + if (outFlagOptions.enablePIDplot) { histos.fill(HIST("tracks/h1pT"), track.pt()); histos.fill(HIST("tracks/h1p"), track.p()); } @@ -2220,15 +2226,15 @@ struct LFNucleiBATask { float shiftPtPos = 0.f; float shiftPtNeg = 0.f; - if (enablePtShift && !fShiftPtHe) { + if (enablePtShiftHe && !fShiftPtHe) { fShiftPtHe = new TF1("fShiftPtHe", "[0] * TMath::Exp([1] + [2] * x) + [3] + [4] * x", 0.f, 8.f); auto par = (std::vector)parShiftPtHe; fShiftPtHe->SetParameters(par[0], par[1], par[2], par[3], par[4]); } - if (enablePtShift && !fShiftPtantiHe) { + if (enablePtShiftHe && !fShiftPtantiHe) { fShiftPtantiHe = new TF1("fShiftPtantiHe", "[0] * TMath::Exp([1] + [2] * x) + [3] + [4] * x", 0.f, 8.f); - auto par = (std::vector)parShiftPtantiHe; + auto par = (std::vector)parShiftPtAntiHe; fShiftPtantiHe->SetParameters(par[0], par[1], par[2], par[3], par[4]); } @@ -2238,7 +2244,7 @@ struct LFNucleiBATask { fShiftAntiD->SetParameters(par[0], par[1], par[2], par[3], par[4]); } - switch (antiDeuteronPt) { + switch (unableAntiDPtShift) { case 0: if (enablePtShiftAntiD && fShiftAntiD) { auto shiftAntiD = fShiftAntiD->Eval(track.pt()); @@ -2256,7 +2262,7 @@ struct LFNucleiBATask { fShiftD->SetParameters(par[0], par[1], par[2], par[3], par[4]); } - switch (DeuteronPt) { + switch (unableDPtShift) { case 0: if (enablePtShiftD && fShiftD) { auto shiftD = fShiftD->Eval(track.pt()); @@ -2271,12 +2277,12 @@ struct LFNucleiBATask { switch (helium3Pt) { case 0: hePt = track.pt(); - if (enablePtShift && fShiftPtHe) { + if (enablePtShiftHe && fShiftPtHe) { shiftPtPos = fShiftPtHe->Eval(2 * track.pt()); hePt = track.pt() - shiftPtPos / 2.f; } antihePt = track.pt(); - if (enablePtShift && fShiftPtantiHe) { + if (enablePtShiftHe && fShiftPtantiHe) { shiftPtNeg = fShiftPtantiHe->Eval(2 * track.pt()); antihePt = track.pt() - shiftPtNeg / 2.f; } @@ -2351,20 +2357,20 @@ struct LFNucleiBATask { bool passDCAxyzCut = false; - switch (dcaConfOptions.DCACustomConfig) { + switch (dcaConfOptions.cfgCustomDCA) { case 0: - passDCAxyCut = (std::abs(track.dcaXY()) <= dcaConfOptions.DCAxyCustomCut); - passDCAzCut = (std::abs(track.dcaZ()) <= dcaConfOptions.DCAzCustomCut); - - passDCAxyCutDe = (std::abs(track.dcaXY()) <= dcaConfOptions.DCAxyCustomCut); - passDCAzCutDe = (std::abs(track.dcaZ()) <= dcaConfOptions.DCAzCustomCut); - passDCAxyCutAntiDe = (std::abs(track.dcaXY()) <= dcaConfOptions.DCAxyCustomCut); - passDCAzCutAntiDe = (std::abs(track.dcaZ()) <= dcaConfOptions.DCAzCustomCut); - - passDCAxyCutHe = (std::abs(track.dcaXY()) <= dcaConfOptions.DCAxyCustomCut); - passDCAzCutHe = (std::abs(track.dcaZ()) <= dcaConfOptions.DCAzCustomCut); - passDCAxyCutAntiHe = (std::abs(track.dcaXY()) <= dcaConfOptions.DCAxyCustomCut); - passDCAzCutAntiHe = (std::abs(track.dcaZ()) <= dcaConfOptions.DCAzCustomCut); + passDCAxyCut = (std::abs(track.dcaXY()) <= dcaConfOptions.cfgCustomDCAxy); + passDCAzCut = (std::abs(track.dcaZ()) <= dcaConfOptions.cfgCustomDCAz); + + passDCAxyCutDe = (std::abs(track.dcaXY()) <= dcaConfOptions.cfgCustomDCAxy); + passDCAzCutDe = (std::abs(track.dcaZ()) <= dcaConfOptions.cfgCustomDCAz); + passDCAxyCutAntiDe = (std::abs(track.dcaXY()) <= dcaConfOptions.cfgCustomDCAxy); + passDCAzCutAntiDe = (std::abs(track.dcaZ()) <= dcaConfOptions.cfgCustomDCAz); + + passDCAxyCutHe = (std::abs(track.dcaXY()) <= dcaConfOptions.cfgCustomDCAxy); + passDCAzCutHe = (std::abs(track.dcaZ()) <= dcaConfOptions.cfgCustomDCAz); + passDCAxyCutAntiHe = (std::abs(track.dcaXY()) <= dcaConfOptions.cfgCustomDCAxy); + passDCAzCutAntiHe = (std::abs(track.dcaZ()) <= dcaConfOptions.cfgCustomDCAz); break; case 1: passDCAxyCut = (std::abs(track.dcaXY()) <= parDCAxy[3] * (parDCAxy[0] + parDCAxy[1] / std::pow(track.pt(), parDCAxy[2]))); @@ -2382,45 +2388,45 @@ struct LFNucleiBATask { break; case 2: passDCAxyCut = (std::abs(track.dcaXY()) <= parDCAxy[3] * (parDCAxy[0] + parDCAxy[1] / std::pow(track.pt(), parDCAxy[2]))); - passDCAzCut = (std::abs(track.dcaZ()) <= dcaConfOptions.DCAzCustomCut); + passDCAzCut = (std::abs(track.dcaZ()) <= dcaConfOptions.cfgCustomDCAz); passDCAxyCutDe = (std::abs(track.dcaXY()) <= parDCAxy[3] * (parDCAxy[0] + parDCAxy[1] / std::pow(DPt, parDCAxy[2]))); - passDCAzCutDe = (std::abs(track.dcaZ()) <= dcaConfOptions.DCAzCustomCut); + passDCAzCutDe = (std::abs(track.dcaZ()) <= dcaConfOptions.cfgCustomDCAz); passDCAxyCutAntiDe = (std::abs(track.dcaXY()) <= parDCAxy[3] * (parDCAxy[0] + parDCAxy[1] / std::pow(antiDPt, parDCAxy[2]))); - passDCAzCutAntiDe = (std::abs(track.dcaZ()) <= dcaConfOptions.DCAzCustomCut); + passDCAzCutAntiDe = (std::abs(track.dcaZ()) <= dcaConfOptions.cfgCustomDCAz); passDCAxyCutHe = (std::abs(track.dcaXY()) <= parDCAxy[3] * (parDCAxy[0] + parDCAxy[1] / std::pow(hePt, parDCAxy[2]))); - passDCAzCutHe = (std::abs(track.dcaZ()) <= dcaConfOptions.DCAzCustomCut); + passDCAzCutHe = (std::abs(track.dcaZ()) <= dcaConfOptions.cfgCustomDCAz); passDCAxyCutAntiHe = (std::abs(track.dcaXY()) <= parDCAxy[3] * (parDCAxy[0] + parDCAxy[1] / std::pow(antihePt, parDCAxy[2]))); - passDCAzCutAntiHe = (std::abs(track.dcaZ()) <= dcaConfOptions.DCAzCustomCut); + passDCAzCutAntiHe = (std::abs(track.dcaZ()) <= dcaConfOptions.cfgCustomDCAz); break; case 3: - passDCAxyCut = (std::abs(track.dcaXY()) <= dcaConfOptions.DCAxyCustomCut); + passDCAxyCut = (std::abs(track.dcaXY()) <= dcaConfOptions.cfgCustomDCAxy); passDCAzCut = (std::abs(track.dcaZ()) <= parDCAz[3] * (parDCAz[0] + parDCAz[1] / std::pow(track.pt(), parDCAz[2]))); - passDCAxyCutDe = (std::abs(track.dcaXY()) <= dcaConfOptions.DCAxyCustomCut); + passDCAxyCutDe = (std::abs(track.dcaXY()) <= dcaConfOptions.cfgCustomDCAxy); passDCAzCutDe = (std::abs(track.dcaZ()) <= parDCAz[3] * (parDCAz[0] + parDCAz[1] / std::pow(DPt, parDCAz[2]))); - passDCAxyCutAntiDe = (std::abs(track.dcaXY()) <= dcaConfOptions.DCAxyCustomCut); + passDCAxyCutAntiDe = (std::abs(track.dcaXY()) <= dcaConfOptions.cfgCustomDCAxy); passDCAzCutAntiDe = (std::abs(track.dcaZ()) <= parDCAz[3] * (parDCAz[0] + parDCAz[1] / std::pow(antiDPt, parDCAz[2]))); - passDCAxyCutHe = (std::abs(track.dcaXY()) <= dcaConfOptions.DCAxyCustomCut); + passDCAxyCutHe = (std::abs(track.dcaXY()) <= dcaConfOptions.cfgCustomDCAxy); passDCAzCutHe = (std::abs(track.dcaZ()) <= parDCAz[3] * (parDCAz[0] + parDCAz[1] / std::pow(hePt, parDCAz[2]))); - passDCAxyCutAntiHe = (std::abs(track.dcaXY()) <= dcaConfOptions.DCAxyCustomCut); + passDCAxyCutAntiHe = (std::abs(track.dcaXY()) <= dcaConfOptions.cfgCustomDCAxy); passDCAzCutAntiHe = (std::abs(track.dcaZ()) <= parDCAz[3] * (parDCAz[0] + parDCAz[1] / std::pow(antihePt, parDCAz[2]))); break; case 4: - passDCAxyCut = std::pow(track.dcaXY(), 2) / std::pow(dcaConfOptions.DCAxyCustomCut, 2) + std::pow(track.dcaZ(), 2) / std::pow(dcaConfOptions.DCAzCustomCut, 2) <= 1; - passDCAzCut = std::pow(track.dcaXY(), 2) / std::pow(dcaConfOptions.DCAxyCustomCut, 2) + std::pow(track.dcaZ(), 2) / std::pow(dcaConfOptions.DCAzCustomCut, 2) <= 1; - - passDCAxyCutDe = std::pow(track.dcaXY(), 2) / std::pow(dcaConfOptions.DCAxyCustomCut, 2) + std::pow(track.dcaZ(), 2) / std::pow(dcaConfOptions.DCAzCustomCut, 2) <= 1; - passDCAzCutDe = std::pow(track.dcaXY(), 2) / std::pow(dcaConfOptions.DCAxyCustomCut, 2) + std::pow(track.dcaZ(), 2) / std::pow(dcaConfOptions.DCAzCustomCut, 2) <= 1; - passDCAxyCutAntiDe = std::pow(track.dcaXY(), 2) / std::pow(dcaConfOptions.DCAxyCustomCut, 2) + std::pow(track.dcaZ(), 2) / std::pow(dcaConfOptions.DCAzCustomCut, 2) <= 1; - passDCAzCutAntiDe = std::pow(track.dcaXY(), 2) / std::pow(dcaConfOptions.DCAxyCustomCut, 2) + std::pow(track.dcaZ(), 2) / std::pow(dcaConfOptions.DCAzCustomCut, 2) <= 1; - - passDCAxyCutHe = std::pow(track.dcaXY(), 2) / std::pow(dcaConfOptions.DCAxyCustomCut, 2) + std::pow(track.dcaZ(), 2) / std::pow(dcaConfOptions.DCAzCustomCut, 2) <= 1; - passDCAzCutHe = std::pow(track.dcaXY(), 2) / std::pow(dcaConfOptions.DCAxyCustomCut, 2) + std::pow(track.dcaZ(), 2) / std::pow(dcaConfOptions.DCAzCustomCut, 2) <= 1; - passDCAxyCutAntiHe = std::pow(track.dcaXY(), 2) / std::pow(dcaConfOptions.DCAxyCustomCut, 2) + std::pow(track.dcaZ(), 2) / std::pow(dcaConfOptions.DCAzCustomCut, 2) <= 1; - passDCAzCutAntiHe = std::pow(track.dcaXY(), 2) / std::pow(dcaConfOptions.DCAxyCustomCut, 2) + std::pow(track.dcaZ(), 2) / std::pow(dcaConfOptions.DCAzCustomCut, 2) <= 1; + passDCAxyCut = std::pow(track.dcaXY(), 2) / std::pow(dcaConfOptions.cfgCustomDCAxy, 2) + std::pow(track.dcaZ(), 2) / std::pow(dcaConfOptions.cfgCustomDCAz, 2) <= 1; + passDCAzCut = std::pow(track.dcaXY(), 2) / std::pow(dcaConfOptions.cfgCustomDCAxy, 2) + std::pow(track.dcaZ(), 2) / std::pow(dcaConfOptions.cfgCustomDCAz, 2) <= 1; + + passDCAxyCutDe = std::pow(track.dcaXY(), 2) / std::pow(dcaConfOptions.cfgCustomDCAxy, 2) + std::pow(track.dcaZ(), 2) / std::pow(dcaConfOptions.cfgCustomDCAz, 2) <= 1; + passDCAzCutDe = std::pow(track.dcaXY(), 2) / std::pow(dcaConfOptions.cfgCustomDCAxy, 2) + std::pow(track.dcaZ(), 2) / std::pow(dcaConfOptions.cfgCustomDCAz, 2) <= 1; + passDCAxyCutAntiDe = std::pow(track.dcaXY(), 2) / std::pow(dcaConfOptions.cfgCustomDCAxy, 2) + std::pow(track.dcaZ(), 2) / std::pow(dcaConfOptions.cfgCustomDCAz, 2) <= 1; + passDCAzCutAntiDe = std::pow(track.dcaXY(), 2) / std::pow(dcaConfOptions.cfgCustomDCAxy, 2) + std::pow(track.dcaZ(), 2) / std::pow(dcaConfOptions.cfgCustomDCAz, 2) <= 1; + + passDCAxyCutHe = std::pow(track.dcaXY(), 2) / std::pow(dcaConfOptions.cfgCustomDCAxy, 2) + std::pow(track.dcaZ(), 2) / std::pow(dcaConfOptions.cfgCustomDCAz, 2) <= 1; + passDCAzCutHe = std::pow(track.dcaXY(), 2) / std::pow(dcaConfOptions.cfgCustomDCAxy, 2) + std::pow(track.dcaZ(), 2) / std::pow(dcaConfOptions.cfgCustomDCAz, 2) <= 1; + passDCAxyCutAntiHe = std::pow(track.dcaXY(), 2) / std::pow(dcaConfOptions.cfgCustomDCAxy, 2) + std::pow(track.dcaZ(), 2) / std::pow(dcaConfOptions.cfgCustomDCAz, 2) <= 1; + passDCAzCutAntiHe = std::pow(track.dcaXY(), 2) / std::pow(dcaConfOptions.cfgCustomDCAxy, 2) + std::pow(track.dcaZ(), 2) / std::pow(dcaConfOptions.cfgCustomDCAz, 2) <= 1; break; case 5: passDCAxyCut = std::pow(track.dcaXY(), 2) / std::pow(parDCAxy[3] * (parDCAxy[0] + parDCAxy[1] / std::pow(track.pt(), parDCAxy[2])), 2) + std::pow(track.dcaZ(), 2) / std::pow(parDCAz[3] * (parDCAz[0] + parDCAz[1] / std::pow(track.pt(), parDCAz[2])), 2) <= 1; @@ -2438,19 +2444,12 @@ struct LFNucleiBATask { break; } - // p cut - if (std::abs(track.tpcInnerParam()) < kinemOptions.pCut) - continue; - // eta cut - if (std::abs(track.eta()) > kinemOptions.etaCut) - continue; - // Rapidity cuts - prRapCut = track.rapidity(o2::track::PID::getMass2Z(o2::track::PID::Proton)) > kinemOptions.yLowCut && track.rapidity(o2::track::PID::getMass2Z(o2::track::PID::Proton)) < kinemOptions.yHighCut; - deRapCut = track.rapidity(o2::track::PID::getMass2Z(o2::track::PID::Deuteron)) > kinemOptions.yLowCut && track.rapidity(o2::track::PID::getMass2Z(o2::track::PID::Deuteron)) < kinemOptions.yHighCut; - trRapCut = track.rapidity(o2::track::PID::getMass2Z(o2::track::PID::Triton)) > kinemOptions.yLowCut && track.rapidity(o2::track::PID::getMass2Z(o2::track::PID::Triton)) < kinemOptions.yHighCut; - heRapCut = track.rapidity(o2::track::PID::getMass2Z(o2::track::PID::Helium3)) > kinemOptions.yLowCut && track.rapidity(o2::track::PID::getMass2Z(o2::track::PID::Helium3)) < kinemOptions.yHighCut; - alRapCut = track.rapidity(o2::track::PID::getMass2Z(o2::track::PID::Alpha)) > kinemOptions.yLowCut && track.rapidity(o2::track::PID::getMass2Z(o2::track::PID::Alpha)) < kinemOptions.yHighCut; + prRapCut = track.rapidity(o2::track::PID::getMass2Z(o2::track::PID::Proton)) > kinemOptions.cfgRapidityCutLow && track.rapidity(o2::track::PID::getMass2Z(o2::track::PID::Proton)) < kinemOptions.cfgRapidityCutHigh; + deRapCut = track.rapidity(o2::track::PID::getMass2Z(o2::track::PID::Deuteron)) > kinemOptions.cfgRapidityCutLow && track.rapidity(o2::track::PID::getMass2Z(o2::track::PID::Deuteron)) < kinemOptions.cfgRapidityCutHigh; + trRapCut = track.rapidity(o2::track::PID::getMass2Z(o2::track::PID::Triton)) > kinemOptions.cfgRapidityCutLow && track.rapidity(o2::track::PID::getMass2Z(o2::track::PID::Triton)) < kinemOptions.cfgRapidityCutHigh; + heRapCut = track.rapidity(o2::track::PID::getMass2Z(o2::track::PID::Helium3)) > kinemOptions.cfgRapidityCutLow && track.rapidity(o2::track::PID::getMass2Z(o2::track::PID::Helium3)) < kinemOptions.cfgRapidityCutHigh; + alRapCut = track.rapidity(o2::track::PID::getMass2Z(o2::track::PID::Alpha)) > kinemOptions.cfgRapidityCutLow && track.rapidity(o2::track::PID::getMass2Z(o2::track::PID::Alpha)) < kinemOptions.cfgRapidityCutHigh; isDeuteron = enableDe && deRapCut; isHelium = enableHe && heRapCut; @@ -2550,19 +2549,19 @@ struct LFNucleiBATask { if (isDeWoDCAzWTPCpid) { histos.fill(HIST("tracks/deuteron/dca/before/hDCAzVsPtDeuteron"), DPt, track.dcaZ()); - if (!track.hasTOF()) + if (!track.hasTOF() && (outFlagOptions.enableNoTOFPlots)) histos.fill(HIST("tracks/deuteron/dca/before/hDCAzVsPtDeuteronNoTOF"), DPt, track.dcaZ()); } if (isAntiDeWoDCAzWTPCpid) { histos.fill(HIST("tracks/deuteron/dca/before/hDCAzVsPtantiDeuteron"), antiDPt, track.dcaZ()); - if (!track.hasTOF()) + if (!track.hasTOF() && (outFlagOptions.enableNoTOFPlots)) histos.fill(HIST("tracks/deuteron/dca/before/hDCAzVsPtantiDeuteronNoTOF"), antiDPt, track.dcaZ()); } if (isHeWoDCAzWTPCpid) { histos.fill(HIST("tracks/helium/dca/before/hDCAzVsPtHelium"), hePt, track.dcaZ()); - if (!track.hasTOF()) + if (!track.hasTOF() && (outFlagOptions.enableNoTOFPlots)) histos.fill(HIST("tracks/helium/dca/before/hDCAzVsPtHeliumNoTOF"), hePt, track.dcaZ()); if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/helium/dca/before/TOF/hDCAzVsPtHelium"), hePt, track.dcaZ()); @@ -2571,7 +2570,7 @@ struct LFNucleiBATask { if (isAntiHeWoDCAzWTPCpid) { histos.fill(HIST("tracks/helium/dca/before/hDCAzVsPtantiHelium"), antihePt, track.dcaZ()); - if (!track.hasTOF()) + if (!track.hasTOF() && (outFlagOptions.enableNoTOFPlots)) histos.fill(HIST("tracks/helium/dca/before/hDCAzVsPtantiHeliumNoTOF"), hePt, track.dcaZ()); if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/helium/dca/before/TOF/hDCAzVsPtantiHelium"), antihePt, track.dcaZ()); @@ -3046,7 +3045,7 @@ struct LFNucleiBATask { histos.fill(HIST("tracks/deuteron/dca/before/hDCAxyVsPtDeuteronVsMult"), DPt, track.dcaXY(), event.centFT0M()); else histos.fill(HIST("tracks/deuteron/dca/before/hDCAxyVsPtDeuteron"), DPt, track.dcaXY()); - if (!track.hasTOF()) + if (!track.hasTOF() && (outFlagOptions.enableNoTOFPlots)) histos.fill(HIST("tracks/deuteron/dca/before/hDCAxyVsPtDeuteronNoTOF"), DPt, track.dcaXY()); } if (isAntiDeWoDCAxyWTPCpid) { @@ -3056,13 +3055,13 @@ struct LFNucleiBATask { histos.fill(HIST("tracks/deuteron/dca/before/hDCAxyVsPtantiDeuteronVsMult"), antiDPt, track.dcaXY(), event.centFT0M()); else histos.fill(HIST("tracks/deuteron/dca/before/hDCAxyVsPtantiDeuteron"), antiDPt, track.dcaXY()); - if (!track.hasTOF()) + if (!track.hasTOF() && (outFlagOptions.enableNoTOFPlots)) histos.fill(HIST("tracks/deuteron/dca/before/hDCAxyVsPtantiDeuteronNoTOF"), antiDPt, track.dcaXY()); } if (isHeWoDCAxyWTPCpid) { histos.fill(HIST("tracks/helium/dca/before/hDCAxyVsPtHelium"), hePt, track.dcaXY()); - if (!track.hasTOF()) + if (!track.hasTOF() && (outFlagOptions.enableNoTOFPlots)) histos.fill(HIST("tracks/helium/dca/before/hDCAxyVsPtHeliumNoTOF"), hePt, track.dcaXY()); if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/helium/dca/before/TOF/hDCAxyVsPtHelium"), hePt, track.dcaXY()); @@ -3070,7 +3069,7 @@ struct LFNucleiBATask { } if (isAntiHeWoDCAxyWTPCpid) { histos.fill(HIST("tracks/helium/dca/before/hDCAxyVsPtantiHelium"), antihePt, track.dcaXY()); - if (!track.hasTOF()) + if (!track.hasTOF() && (outFlagOptions.enableNoTOFPlots)) histos.fill(HIST("tracks/helium/dca/before/hDCAxyVsPtantiHeliumNoTOF"), antihePt, track.dcaXY()); if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/helium/dca/before/TOF/hDCAxyVsPtantiHelium"), antihePt, track.dcaXY()); @@ -3652,7 +3651,7 @@ struct LFNucleiBATask { // DCA Cut if constexpr (!IsFilteredData) { if (filterOptions.enableIsGlobalTrack) { - if (!enableDCACustomCut) { + if (!enableCustomDCACut) { if (!track.isGlobalTrack()) continue; } else { @@ -3804,7 +3803,7 @@ struct LFNucleiBATask { debugHistos.fill(HIST("debug/tracks/kaon/h2KaonVspTNSigmaTPC"), track.pt(), track.tpcNSigmaKa()); } - if (enablePtSpectra) + if (outFlagOptions.enableEffPlots) histos.fill(HIST("tracks/eff/h2pVsTPCmomentum"), track.tpcInnerParam(), track.p()); if (filterOptions.enableFiltering) { @@ -3812,11 +3811,11 @@ struct LFNucleiBATask { continue; } - if (enablePIDplot) + if (outFlagOptions.enablePIDplot) histos.fill(HIST("tracks/h2TPCsignVsTPCmomentum"), track.tpcInnerParam() / (1.f * track.sign()), track.tpcSignal()); if constexpr (!IsFilteredData) { - if (nsigmaITSvar.showAverageClusterSize && enablePIDplot) { + if (nsigmaITSvar.showAverageClusterSize && outFlagOptions.enablePIDplot) { histos.fill(HIST("tracks/averageClusterSize"), track.p(), averageClusterSizeTrk(track)); histos.fill(HIST("tracks/averageClusterSizePerCoslInv"), track.p(), averageClusterSizePerCoslInv(track)); } @@ -3921,7 +3920,7 @@ struct LFNucleiBATask { evtimeHistos.fill(HIST("tracks/evtime/ft0tof/proton/h3ProtonNSigmaTPCvsNSigmaTOFvsPt"), track.tpcNSigmaPr(), track.tofNSigmaPr(), track.pt()); if (enableDe) evtimeHistos.fill(HIST("tracks/evtime/ft0tof/deuteron/h3DeuteronNSigmaTPCvsNSigmaTOFvsPt"), track.tpcNSigmaDe(), track.tofNSigmaDe(), DPt); - if (enableDebug && (track.beta() > betaCut)) { + if (enableDebug && (track.beta() > cfgBetaCut)) { if (enablePr) debugHistos.fill(HIST("debug/evtime/ft0tof/proton/h2ProtonVspTNSigmaTPC_BetaCut"), track.pt(), track.tpcNSigmaPr()); if (enableDe) @@ -3953,7 +3952,7 @@ struct LFNucleiBATask { evtimeHistos.fill(HIST("tracks/evtime/ft0/proton/h3ProtonNSigmaTPCvsNSigmaTOFvsPt"), track.tpcNSigmaPr(), track.tofNSigmaPr(), track.pt()); if (enableDe) evtimeHistos.fill(HIST("tracks/evtime/ft0/deuteron/h3DeuteronNSigmaTPCvsNSigmaTOFvsPt"), track.tpcNSigmaDe(), track.tofNSigmaDe(), DPt); - if (enableDebug && (track.beta() > betaCut)) { + if (enableDebug && (track.beta() > cfgBetaCut)) { if (enablePr) debugHistos.fill(HIST("debug/evtime/ft0/proton/h2ProtonVspTNSigmaTPC_BetaCut"), track.pt(), track.tpcNSigmaPr()); if (enableDe) @@ -3985,7 +3984,7 @@ struct LFNucleiBATask { evtimeHistos.fill(HIST("tracks/evtime/tof/proton/h3ProtonNSigmaTPCvsNSigmaTOFvsPt"), track.tpcNSigmaPr(), track.tofNSigmaPr(), track.pt()); if (enableDe) evtimeHistos.fill(HIST("tracks/evtime/tof/deuteron/h3DeuteronNSigmaTPCvsNSigmaTOFvsPt"), track.tpcNSigmaDe(), track.tofNSigmaDe(), DPt); - if (enableDebug && (track.beta() > betaCut)) { + if (enableDebug && (track.beta() > cfgBetaCut)) { if (enablePr) debugHistos.fill(HIST("debug/evtime/tof/proton/h2ProtonVspTNSigmaTPC_BetaCut"), track.pt(), track.tpcNSigmaPr()); if (enableDe) @@ -4019,7 +4018,7 @@ struct LFNucleiBATask { evtimeHistos.fill(HIST("tracks/evtime/fill/proton/h3ProtonNSigmaTPCvsNSigmaTOFvsPt"), track.tpcNSigmaPr(), track.tofNSigmaPr(), track.pt()); if (enableDe) evtimeHistos.fill(HIST("tracks/evtime/fill/deuteron/h3DeuteronNSigmaTPCvsNSigmaTOFvsPt"), track.tpcNSigmaDe(), track.tofNSigmaDe(), DPt); - if (enableDebug && (track.beta() > betaCut)) { + if (enableDebug && (track.beta() > cfgBetaCut)) { if (enablePr) debugHistos.fill(HIST("debug/evtime/fill/proton/h2ProtonVspTNSigmaTPC_BetaCut"), track.pt(), track.tpcNSigmaPr()); if (enableDe) @@ -4075,7 +4074,7 @@ struct LFNucleiBATask { evtimeHistos.fill(HIST("tracks/evtime/ft0tof/proton/h3antiProtonNSigmaTPCvsNSigmaTOFvsPt"), track.tpcNSigmaPr(), track.tofNSigmaPr(), track.pt()); if (enableDe) evtimeHistos.fill(HIST("tracks/evtime/ft0tof/deuteron/h3antiDeuteronNSigmaTPCvsNSigmaTOFvsPt"), track.tpcNSigmaDe(), track.tofNSigmaDe(), antiDPt); - if (enableDebug && (track.beta() > betaCut)) { + if (enableDebug && (track.beta() > cfgBetaCut)) { if (enablePr) debugHistos.fill(HIST("debug/evtime/ft0tof/proton/h2antiProtonVspTNSigmaTPC_BetaCut"), track.pt(), track.tpcNSigmaPr()); if (enableDe) @@ -4323,7 +4322,7 @@ struct LFNucleiBATask { if (passDCAxyzCut) { // PID - if (enablePtSpectra && enableDebug) { + if (outFlagOptions.enableEffPlots && enableDebug) { if (track.sign() > 0) { debugHistos.fill(HIST("tracks/eff/hPtP"), track.pt()); debugHistos.fill(HIST("tracks/eff/hPtPrebinned"), track.pt()); @@ -4336,7 +4335,7 @@ struct LFNucleiBATask { if (enablePr) { if (std::abs(track.tpcNSigmaPr()) < nsigmaTPCvar.nsigmaTPCPr && prRapCut) { if (track.sign() > 0) { - if (enablePtSpectra) { + if (outFlagOptions.enableEffPlots) { histos.fill(HIST("tracks/eff/proton/hPtPr"), track.pt()); histos.fill(HIST("tracks/eff/proton/hPtPrrebinned"), track.pt()); histos.fill(HIST("tracks/eff/proton/h2pVsTPCmomentumPr"), track.tpcInnerParam(), track.p()); @@ -4345,10 +4344,10 @@ struct LFNucleiBATask { histos.fill(HIST("tracks/proton/h2ProtonYvsPt"), track.rapidity(o2::track::PID::getMass2Z(o2::track::PID::Proton)), track.pt()); histos.fill(HIST("tracks/proton/h2ProtonEtavsPt"), track.eta(), track.pt()); - if (enablePIDplot) + if (outFlagOptions.enablePIDplot) histos.fill(HIST("tracks/proton/h2TPCsignVsTPCmomentumProton"), track.tpcInnerParam(), track.tpcSignal()); } else { - if (enablePtSpectra) { + if (outFlagOptions.enableEffPlots) { histos.fill(HIST("tracks/eff/proton/hPtantiPr"), track.pt()); histos.fill(HIST("tracks/eff/proton/hPtantiPrrebinned"), track.pt()); histos.fill(HIST("tracks/eff/proton/h2pVsTPCmomentumantiPr"), track.tpcInnerParam(), track.p()); @@ -4357,7 +4356,7 @@ struct LFNucleiBATask { histos.fill(HIST("tracks/proton/h2antiProtonYvsPt"), track.rapidity(o2::track::PID::getMass2Z(o2::track::PID::Proton)), track.pt()); histos.fill(HIST("tracks/proton/h2antiProtonEtavsPt"), track.eta(), track.pt()); - if (enablePIDplot) + if (outFlagOptions.enablePIDplot) histos.fill(HIST("tracks/proton/h2TPCsignVsTPCmomentumantiProton"), track.tpcInnerParam(), track.tpcSignal()); } } @@ -4365,20 +4364,20 @@ struct LFNucleiBATask { if (enableTr) { if ((isTritonTPCpid) && trRapCut) { if (track.sign() > 0) { - if (enablePtSpectra) { + if (outFlagOptions.enableEffPlots) { histos.fill(HIST("tracks/eff/triton/hPtTr"), track.pt()); histos.fill(HIST("tracks/eff/triton/h2pVsTPCmomentumTr"), track.tpcInnerParam(), track.p()); } histos.fill(HIST("tracks/triton/h1TritonSpectra"), track.pt()); - if (enablePIDplot) + if (outFlagOptions.enablePIDplot) histos.fill(HIST("tracks/triton/h2TPCsignVsTPCmomentumTriton"), track.tpcInnerParam(), track.tpcSignal()); } else { - if (enablePtSpectra) { + if (outFlagOptions.enableEffPlots) { histos.fill(HIST("tracks/eff/triton/hPtantiTr"), track.pt()); histos.fill(HIST("tracks/eff/triton/h2pVsTPCmomentumantiTr"), track.tpcInnerParam(), track.p()); } histos.fill(HIST("tracks/triton/h1antiTritonSpectra"), track.pt()); - if (enablePIDplot) + if (outFlagOptions.enablePIDplot) histos.fill(HIST("tracks/triton/h2TPCsignVsTPCmomentumantiTriton"), track.tpcInnerParam(), track.tpcSignal()); } } @@ -4387,18 +4386,18 @@ struct LFNucleiBATask { if ((std::abs(track.tpcNSigmaAl()) < nsigmaTPCvar.nsigmaTPCAl) && alRapCut) { if (track.sign() > 0) { histos.fill(HIST("tracks/alpha/h1AlphaSpectra"), track.pt()); - if (enablePIDplot) + if (outFlagOptions.enablePIDplot) histos.fill(HIST("tracks/alpha/h2TPCsignVsTPCmomentumAlpha"), track.tpcInnerParam(), track.tpcSignal()); } else { histos.fill(HIST("tracks/alpha/h1antiAlphaSpectra"), track.pt()); - if (enablePIDplot) + if (outFlagOptions.enablePIDplot) histos.fill(HIST("tracks/alpha/h2TPCsignVsTPCmomentumantiAlpha"), track.tpcInnerParam(), track.tpcSignal()); } } } if (outFlagOptions.doTOFplots && track.hasTOF()) { - if (enablePtSpectra && enableDebug) { + if (outFlagOptions.enableEffPlots && enableDebug) { if (track.sign() > 0) { debugHistos.fill(HIST("tracks/eff/hPtPTOF"), track.pt()); debugHistos.fill(HIST("tracks/eff/hPtPTOFrebinned"), track.pt()); @@ -4408,9 +4407,9 @@ struct LFNucleiBATask { } } - if (outFlagOptions.enableBetaCut && (track.beta() > betaCut) && enablePIDplot) + if (outFlagOptions.enableBetaCut && (track.beta() > cfgBetaCut) && outFlagOptions.enablePIDplot) histos.fill(HIST("tracks/h2TOFbetaVsP_BetaCut"), track.p() / (1.f * track.sign()), track.beta()); - if (enablePIDplot) { + if (outFlagOptions.enablePIDplot) { switch (useHasTRDConfig) { case 0: histos.fill(HIST("tracks/h2TOFbetaVsP"), track.p() / (1.f * track.sign()), track.beta()); @@ -4428,20 +4427,20 @@ struct LFNucleiBATask { } } - if (enablePtSpectra) + if (outFlagOptions.enableEffPlots) histos.fill(HIST("tracks/eff/h2TPCmomentumVsTOFExpMomentum"), track.tofExpMom(), track.tpcInnerParam()); if (enablePr && prRapCut) { if (std::abs(track.tpcNSigmaPr()) < nsigmaTPCvar.nsigmaTPCPr && track.sign() > 0) { histos.fill(HIST("tracks/proton/h2ProtonTOFbetaVsP"), track.p(), track.beta()); - if (enablePtSpectra) { + if (outFlagOptions.enableEffPlots) { histos.fill(HIST("tracks/eff/proton/h2pVsTOFExpMomentumPr"), track.tofExpMom(), track.p()); histos.fill(HIST("tracks/eff/proton/h2TPCmomentumVsTOFExpMomentumPr"), track.tofExpMom(), track.tpcInnerParam()); } } if (std::abs(track.tpcNSigmaPr()) < nsigmaTPCvar.nsigmaTPCPr && track.sign() < 0) { histos.fill(HIST("tracks/proton/h2antiProtonTOFbetaVsP"), track.p(), track.beta()); - if (enablePtSpectra) { + if (outFlagOptions.enableEffPlots) { histos.fill(HIST("tracks/eff/proton/h2pVsTOFExpMomentumantiPr"), track.tofExpMom(), track.p()); histos.fill(HIST("tracks/eff/proton/h2TPCmomentumVsTOFExpMomentumantiPr"), track.tofExpMom(), track.tpcInnerParam()); } @@ -4450,14 +4449,14 @@ struct LFNucleiBATask { if (enableTr && trRapCut) { if (isTritonTPCpid && track.sign() > 0) { histos.fill(HIST("tracks/triton/h2TritonTOFbetaVsP"), track.p(), track.beta()); - if (enablePtSpectra) { + if (outFlagOptions.enableEffPlots) { histos.fill(HIST("tracks/eff/triton/h2pVsTOFExpMomentumTr"), track.tofExpMom(), track.p()); histos.fill(HIST("tracks/eff/triton/h2TPCmomentumVsTOFExpMomentumTr"), track.tofExpMom(), track.tpcInnerParam()); } } if (isTritonTPCpid && track.sign() < 0) { histos.fill(HIST("tracks/triton/h2antiTritonTOFbetaVsP"), track.p(), track.beta()); - if (enablePtSpectra) { + if (outFlagOptions.enableEffPlots) { histos.fill(HIST("tracks/eff/triton/h2pVsTOFExpMomentumantiTr"), track.tofExpMom(), track.p()); histos.fill(HIST("tracks/eff/triton/h2TPCmomentumVsTOFExpMomentumantiTr"), track.tofExpMom(), track.tpcInnerParam()); } @@ -4482,27 +4481,27 @@ struct LFNucleiBATask { } if (isDeWTPCpid) { - if (enablePtSpectra) { + if (outFlagOptions.enableEffPlots) { histos.fill(HIST("tracks/eff/deuteron/hPtDe"), DPt); histos.fill(HIST("tracks/eff/deuteron/h2pVsTPCmomentumDe"), track.tpcInnerParam(), track.p()); } histos.fill(HIST("tracks/deuteron/h1DeuteronSpectra"), DPt); histos.fill(HIST("tracks/deuteron/h2DeuteronYvsPt"), track.rapidity(o2::track::PID::getMass2Z(o2::track::PID::Deuteron)), DPt); - if (enablePIDplot) + if (outFlagOptions.enablePIDplot) histos.fill(HIST("tracks/deuteron/h2TPCsignVsTPCmomentumDeuteron"), track.tpcInnerParam(), track.tpcSignal()); } if (isAntiDeWTPCpid) { - if (enablePtSpectra) { + if (outFlagOptions.enableEffPlots) { histos.fill(HIST("tracks/eff/deuteron/hPtantiDe"), antiDPt); histos.fill(HIST("tracks/eff/deuteron/h2pVsTPCmomentumantiDe"), track.tpcInnerParam(), track.p()); } histos.fill(HIST("tracks/deuteron/h1antiDeuteronSpectra"), antiDPt); histos.fill(HIST("tracks/deuteron/h2antiDeuteronYvsPt"), track.rapidity(o2::track::PID::getMass2Z(o2::track::PID::Deuteron)), antiDPt); - if (enablePIDplot) + if (outFlagOptions.enablePIDplot) histos.fill(HIST("tracks/deuteron/h2TPCsignVsTPCmomentumantiDeuteron"), track.tpcInnerParam(), track.tpcSignal()); } if (isHeWTPCpid) { - if (enablePtSpectra) { + if (outFlagOptions.enableEffPlots) { histos.fill(HIST("tracks/eff/helium/hPtHe"), 2 * hePt); histos.fill(HIST("tracks/eff/helium/h2pVsTPCmomentumHe"), heTPCmomentum, heP); } @@ -4512,11 +4511,11 @@ struct LFNucleiBATask { histos.fill(HIST("tracks/helium/h2HeliumYvsPt_Z2"), track.rapidity(o2::track::PID::getMass2Z(o2::track::PID::Helium3)), 2 * hePt); histos.fill(HIST("tracks/helium/h2HeliumEtavsPt"), track.eta(), hePt); histos.fill(HIST("tracks/helium/h2HeliumEtavsPt_Z2"), track.eta(), 2 * hePt); - if (enablePIDplot) + if (outFlagOptions.enablePIDplot) histos.fill(HIST("tracks/helium/h2TPCsignVsTPCmomentumHelium"), heTPCmomentum, track.tpcSignal()); } if (isAntiHeWTPCpid) { - if (enablePtSpectra) { + if (outFlagOptions.enableEffPlots) { histos.fill(HIST("tracks/eff/helium/hPtantiHe"), 2 * antihePt); histos.fill(HIST("tracks/eff/helium/h2pVsTPCmomentumantiHe"), antiheTPCmomentum, antiheP); } @@ -4526,21 +4525,21 @@ struct LFNucleiBATask { histos.fill(HIST("tracks/helium/h2antiHeliumYvsPt_Z2"), track.rapidity(o2::track::PID::getMass2Z(o2::track::PID::Helium3)), 2 * antihePt); histos.fill(HIST("tracks/helium/h2antiHeliumEtavsPt"), track.eta(), antihePt); histos.fill(HIST("tracks/helium/h2antiHeliumEtavsPt_Z2"), track.eta(), 2 * antihePt); - if (enablePIDplot) + if (outFlagOptions.enablePIDplot) histos.fill(HIST("tracks/helium/h2TPCsignVsTPCmomentumantiHelium"), antiheTPCmomentum, track.tpcSignal()); } if (outFlagOptions.doTOFplots && track.hasTOF()) { if (isDeWTPCpid) { histos.fill(HIST("tracks/deuteron/h2DeuteronTOFbetaVsP"), track.p(), track.beta()); - if (enablePtSpectra) { + if (outFlagOptions.enableEffPlots) { histos.fill(HIST("tracks/eff/deuteron/h2pVsTOFExpMomentumDe"), track.tofExpMom(), track.p()); histos.fill(HIST("tracks/eff/deuteron/h2TPCmomentumVsTOFExpMomentumDe"), track.tofExpMom(), track.tpcInnerParam()); } } if (isAntiDeWTPCpid) { histos.fill(HIST("tracks/deuteron/h2antiDeuteronTOFbetaVsP"), track.p(), track.beta()); - if (enablePtSpectra) { + if (outFlagOptions.enableEffPlots) { histos.fill(HIST("tracks/eff/deuteron/h2pVsTOFExpMomentumantiDe"), track.tofExpMom(), track.p()); histos.fill(HIST("tracks/eff/deuteron/h2TPCmomentumVsTOFExpMomentumantiDe"), track.tofExpMom(), track.tpcInnerParam()); } @@ -4548,7 +4547,7 @@ struct LFNucleiBATask { if (isHeWTPCpid) { histos.fill(HIST("tracks/helium/h2HeliumTOFbetaVsP"), heP, track.beta()); - if (enablePtSpectra) { + if (outFlagOptions.enableEffPlots) { histos.fill(HIST("tracks/eff/helium/h2pVsTOFExpMomentumHe"), track.tofExpMom(), heP); histos.fill(HIST("tracks/eff/helium/h2TPCmomentumVsTOFExpMomentumHe"), track.tofExpMom(), heTPCmomentum); } @@ -4556,7 +4555,7 @@ struct LFNucleiBATask { if (isAntiHeWTPCpid) { histos.fill(HIST("tracks/helium/h2antiHeliumTOFbetaVsP"), antiheP, track.beta()); - if (enablePtSpectra) { + if (outFlagOptions.enableEffPlots) { histos.fill(HIST("tracks/eff/helium/h2pVsTOFExpMomentumantiHe"), track.tofExpMom(), antiheP); histos.fill(HIST("tracks/eff/helium/h2TPCmomentumVsTOFExpMomentumantiHe"), track.tofExpMom(), antiheTPCmomentum); } @@ -4580,7 +4579,7 @@ struct LFNucleiBATask { massTOFantihe = antiheP * std::sqrt(1.f / (track.beta() * track.beta()) - 1.f); break; } - if (passDCAxyzCut && outFlagOptions.doTOFplots && enablePIDplot) + if (passDCAxyzCut && outFlagOptions.doTOFplots && outFlagOptions.enablePIDplot) histos.fill(HIST("tracks/h2TPCsignVsBetaGamma"), (track.beta() * gamma) / (1.f * track.sign()), track.tpcSignal()); } else { massTOF = -99.f; @@ -4589,7 +4588,7 @@ struct LFNucleiBATask { } if (passDCAxyzCut) { - if (enablePIDplot) + if (outFlagOptions.enablePIDplot) histos.fill(HIST("tracks/h2TOFmassVsPt"), massTOF, track.pt()); if (filterOptions.enableEvTimeSplitting) { if (track.isEvTimeTOF() && track.isEvTimeT0AC()) { @@ -4606,13 +4605,13 @@ struct LFNucleiBATask { if (enablePr) { if ((std::abs(track.tpcNSigmaPr()) < nsigmaTPCvar.nsigmaTPCPr) && prRapCut) { if (track.sign() > 0) { - if (enablePtSpectra) { + if (outFlagOptions.enableEffPlots) { histos.fill(HIST("tracks/eff/proton/hPtPrTOF"), track.pt()); histos.fill(HIST("tracks/eff/proton/hPtPrTOFrebinned"), track.pt()); } histos.fill(HIST("tracks/proton/h2TOFmassProtonVsPt"), massTOF, track.pt()); histos.fill(HIST("tracks/proton/h2TOFmass2ProtonVsPt"), massTOF * massTOF - MassProtonVal * MassProtonVal, track.pt()); - if (outFlagOptions.enableBetaCut && (track.beta() > betaCut)) { + if (outFlagOptions.enableBetaCut && (track.beta() > cfgBetaCut)) { histos.fill(HIST("tracks/proton/h2TOFmassProtonVsPt_BetaCut"), massTOF, track.pt()); histos.fill(HIST("tracks/proton/h2TOFmass2ProtonVsPt_BetaCut"), massTOF * massTOF - MassProtonVal * MassProtonVal, track.pt()); } @@ -4630,13 +4629,13 @@ struct LFNucleiBATask { } } } else { - if (enablePtSpectra) { + if (outFlagOptions.enableEffPlots) { histos.fill(HIST("tracks/eff/proton/hPtantiPrTOF"), track.pt()); histos.fill(HIST("tracks/eff/proton/hPtantiPrTOFrebinned"), track.pt()); } histos.fill(HIST("tracks/proton/h2TOFmassantiProtonVsPt"), massTOF, track.pt()); histos.fill(HIST("tracks/proton/h2TOFmass2antiProtonVsPt"), massTOF * massTOF - MassProtonVal * MassProtonVal, track.pt()); - if (outFlagOptions.enableBetaCut && (track.beta() > betaCut)) { + if (outFlagOptions.enableBetaCut && (track.beta() > cfgBetaCut)) { histos.fill(HIST("tracks/proton/h2TOFmassantiProtonVsPt_BetaCut"), massTOF, track.pt()); histos.fill(HIST("tracks/proton/h2TOFmass2antiProtonVsPt_BetaCut"), massTOF * massTOF - MassProtonVal * MassProtonVal, track.pt()); } @@ -4660,20 +4659,20 @@ struct LFNucleiBATask { if (enableTr) { if ((isTritonTPCpid) && trRapCut) { if (track.sign() > 0) { - if (enablePtSpectra) + if (outFlagOptions.enableEffPlots) histos.fill(HIST("tracks/eff/triton/hPtTrTOF"), track.pt()); histos.fill(HIST("tracks/triton/h2TOFmassTritonVsPt"), massTOF, track.pt()); histos.fill(HIST("tracks/triton/h2TOFmass2TritonVsPt"), massTOF * massTOF - MassTritonVal * MassTritonVal, track.pt()); - if (outFlagOptions.enableBetaCut && (track.beta() > betaCut)) { + if (outFlagOptions.enableBetaCut && (track.beta() > cfgBetaCut)) { histos.fill(HIST("tracks/triton/h2TOFmassTritonVsPt_BetaCut"), massTOF, track.pt()); histos.fill(HIST("tracks/triton/h2TOFmass2TritonVsPt_BetaCut"), massTOF * massTOF - MassTritonVal * MassTritonVal, track.pt()); } } else { - if (enablePtSpectra) + if (outFlagOptions.enableEffPlots) histos.fill(HIST("tracks/eff/triton/hPtantiTrTOF"), track.pt()); histos.fill(HIST("tracks/triton/h2TOFmassantiTritonVsPt"), massTOF, track.pt()); histos.fill(HIST("tracks/triton/h2TOFmass2antiTritonVsPt"), massTOF * massTOF - MassTritonVal * MassTritonVal, track.pt()); - if (outFlagOptions.enableBetaCut && (track.beta() > betaCut)) { + if (outFlagOptions.enableBetaCut && (track.beta() > cfgBetaCut)) { histos.fill(HIST("tracks/triton/h2TOFmassantiTritonVsPt_BetaCut"), massTOF, track.pt()); histos.fill(HIST("tracks/triton/h2TOFmass2antiTritonVsPt_BetaCut"), massTOF * massTOF - MassTritonVal * MassTritonVal, track.pt()); } @@ -4683,14 +4682,14 @@ struct LFNucleiBATask { } if (isDeWTPCpid) { - if (enablePtSpectra) + if (outFlagOptions.enableEffPlots) histos.fill(HIST("tracks/eff/deuteron/hPtDeTOF"), DPt); histos.fill(HIST("tracks/deuteron/h2TOFmassDeuteronVsPt"), massTOF, DPt); if (enableCentrality) histos.fill(HIST("tracks/deuteron/h3TOFmass2DeuteronVsPtVsMult"), massTOF * massTOF - MassDeuteronVal * MassDeuteronVal, DPt, event.centFT0M()); else histos.fill(HIST("tracks/deuteron/h2TOFmass2DeuteronVsPt"), massTOF * massTOF - MassDeuteronVal * MassDeuteronVal, DPt); - if (outFlagOptions.enableBetaCut && (track.beta() > betaCut)) { + if (outFlagOptions.enableBetaCut && (track.beta() > cfgBetaCut)) { histos.fill(HIST("tracks/deuteron/h2TOFmassDeuteronVsPt_BetaCut"), massTOF, DPt); histos.fill(HIST("tracks/deuteron/h2TOFmass2DeuteronVsPt_BetaCut"), massTOF * massTOF - MassDeuteronVal * MassDeuteronVal, DPt); } @@ -4709,14 +4708,14 @@ struct LFNucleiBATask { } } if (isAntiDeWTPCpid) { - if (enablePtSpectra) + if (outFlagOptions.enableEffPlots) histos.fill(HIST("tracks/eff/deuteron/hPtantiDeTOF"), antiDPt); histos.fill(HIST("tracks/deuteron/h2TOFmassantiDeuteronVsPt"), massTOF, antiDPt); if (enableCentrality) histos.fill(HIST("tracks/deuteron/h3TOFmass2antiDeuteronVsPtVsMult"), massTOF * massTOF - MassDeuteronVal * MassDeuteronVal, antiDPt, event.centFT0M()); else histos.fill(HIST("tracks/deuteron/h2TOFmass2antiDeuteronVsPt"), massTOF * massTOF - MassDeuteronVal * MassDeuteronVal, antiDPt); - if (outFlagOptions.enableBetaCut && (track.beta() > betaCut)) { + if (outFlagOptions.enableBetaCut && (track.beta() > cfgBetaCut)) { histos.fill(HIST("tracks/deuteron/h2TOFmassantiDeuteronVsPt_BetaCut"), massTOF, antiDPt); histos.fill(HIST("tracks/deuteron/h2TOFmass2antiDeuteronVsPt_BetaCut"), massTOF * massTOF - MassDeuteronVal * MassDeuteronVal, antiDPt); } @@ -4736,12 +4735,12 @@ struct LFNucleiBATask { } if (isHeWTPCpid) { - if (enablePtSpectra) + if (outFlagOptions.enableEffPlots) histos.fill(HIST("tracks/eff/helium/hPtHeTOF"), 2 * hePt); histos.fill(HIST("tracks/helium/h2TOFmassHeliumVsPt"), 2.f * massTOFhe, hePt); histos.fill(HIST("tracks/helium/h2TOFmassDeltaHeliumVsPt"), 2.f * massTOFhe - MassHeliumVal, hePt); histos.fill(HIST("tracks/helium/h2TOFmass2HeliumVsPt"), 2.f * massTOFhe * 2.f * massTOFhe - MassHeliumVal * MassHeliumVal, hePt); - if (outFlagOptions.enableBetaCut && (track.beta() > betaCut)) { + if (outFlagOptions.enableBetaCut && (track.beta() > cfgBetaCut)) { histos.fill(HIST("tracks/helium/h2TOFmassHeliumVsPt_BetaCut"), 2.f * massTOFhe, hePt); histos.fill(HIST("tracks/helium/h2TOFmass2HeliumVsPt_BetaCut"), 2.f * massTOFhe * 2.f * massTOFhe - MassHeliumVal * MassHeliumVal, hePt); } @@ -4749,12 +4748,12 @@ struct LFNucleiBATask { histos.fill(HIST("tracks/helium/h2HeliumTOFExpSignalDiffVsPtCut"), hePt, track.tofExpSignalDiffHe()); } if (isAntiHeWTPCpid) { - if (enablePtSpectra) + if (outFlagOptions.enableEffPlots) histos.fill(HIST("tracks/eff/helium/hPtantiHeTOF"), 2 * antihePt); histos.fill(HIST("tracks/helium/h2TOFmassantiHeliumVsPt"), 2.f * massTOFantihe, antihePt); histos.fill(HIST("tracks/helium/h2TOFmassDeltaantiHeliumVsPt"), 2.f * massTOFantihe - MassHeliumVal, antihePt); histos.fill(HIST("tracks/helium/h2TOFmass2antiHeliumVsPt"), 2.f * massTOFantihe * 2.f * massTOFantihe - MassHeliumVal * MassHeliumVal, antihePt); - if (outFlagOptions.enableBetaCut && (track.beta() > betaCut)) { + if (outFlagOptions.enableBetaCut && (track.beta() > cfgBetaCut)) { histos.fill(HIST("tracks/helium/h2TOFmassantiHeliumVsPt_BetaCut"), 2.f * massTOFantihe, antihePt); histos.fill(HIST("tracks/helium/h2TOFmass2antiHeliumVsPt_BetaCut"), 2.f * massTOFantihe * 2.f * massTOFantihe - MassHeliumVal * MassHeliumVal, antihePt); } @@ -5481,7 +5480,7 @@ struct LFNucleiBATask { break; case PDGHelium: if (isHelium && passDCAzCutHe && passDCAxyCutHe) { - histos.fill(HIST("tracks/helium/h1HeliumSpectraTrue"), hePt); + // histos.fill(HIST("tracks/helium/h1HeliumSpectraTrue"), hePt); histos.fill(HIST("tracks/helium/h1HeliumSpectraTrue_Z2"), 2 * hePt); if (outFlagOptions.makeDCAAfterCutPlots) { @@ -5494,17 +5493,17 @@ struct LFNucleiBATask { } } if (std::abs(track.tpcNSigmaHe()) < nsigmaTPCvar.nsigmaTPCHe) { - histos.fill(HIST("tracks/helium/h1HeliumSpectraTrueWPID"), hePt); + // histos.fill(HIST("tracks/helium/h1HeliumSpectraTrueWPID"), hePt); histos.fill(HIST("tracks/helium/h1HeliumSpectraTrueWPID_Z2"), 2 * hePt); - if (enablePtSpectra) { - histos.fill(HIST("tracks/eff/helium/hPtHeTrue"), 2 * hePt); + if (outFlagOptions.enableEffPlots) { + histos.fill(HIST("tracks/eff/helium/hPtHeTrue_Z2"), 2 * hePt); if (track.hasTOF() && outFlagOptions.doTOFplots) { - histos.fill(HIST("tracks/eff/helium/hPtHeTOFTrue"), 2 * hePt); + histos.fill(HIST("tracks/eff/helium/hPtHeTOFTrue_Z2"), 2 * hePt); } } } if (isPhysPrim) { - histos.fill(HIST("tracks/helium/h1HeliumSpectraTruePrim"), hePt); + // histos.fill(HIST("tracks/helium/h1HeliumSpectraTruePrim"), hePt); histos.fill(HIST("tracks/helium/h1HeliumSpectraTruePrim_Z2"), 2 * hePt); if (std::abs(track.tpcNSigmaHe()) < nsigmaTPCvar.nsigmaTPCHe) { @@ -5524,7 +5523,7 @@ struct LFNucleiBATask { } if (!isPhysPrim && !isProdByGen) { - histos.fill(HIST("tracks/helium/h1HeliumSpectraTrueTransport"), hePt); + // histos.fill(HIST("tracks/helium/h1HeliumSpectraTrueTransport"), hePt); histos.fill(HIST("tracks/helium/h1HeliumSpectraTrueTransport_Z2"), 2 * hePt); if (outFlagOptions.makeDCAAfterCutPlots) { @@ -5536,7 +5535,7 @@ struct LFNucleiBATask { } } if (isWeakDecay) { - histos.fill(HIST("tracks/helium/h1HeliumSpectraTrueSec"), hePt); + // histos.fill(HIST("tracks/helium/h1HeliumSpectraTrueSec"), hePt); histos.fill(HIST("tracks/helium/h1HeliumSpectraTrueSec_Z2"), 2 * hePt); if (outFlagOptions.makeDCAAfterCutPlots) { @@ -5553,7 +5552,7 @@ struct LFNucleiBATask { break; case -PDGHelium: if (isHelium && passDCAzCutAntiHe && passDCAxyCutAntiHe) { - histos.fill(HIST("tracks/helium/h1antiHeliumSpectraTrue"), antihePt); + // histos.fill(HIST("tracks/helium/h1antiHeliumSpectraTrue"), antihePt); histos.fill(HIST("tracks/helium/h1antiHeliumSpectraTrue_Z2"), 2 * antihePt); if (outFlagOptions.makeDCAAfterCutPlots) { @@ -5565,17 +5564,17 @@ struct LFNucleiBATask { } } if (std::abs(track.tpcNSigmaHe()) < nsigmaTPCvar.nsigmaTPCHe) { - histos.fill(HIST("tracks/helium/h1antiHeliumSpectraTrueWPID"), antihePt); + // histos.fill(HIST("tracks/helium/h1antiHeliumSpectraTrueWPID"), antihePt); histos.fill(HIST("tracks/helium/h1antiHeliumSpectraTrueWPID_Z2"), 2 * antihePt); - if (enablePtSpectra) { - histos.fill(HIST("tracks/eff/helium/hPtantiHeTrue"), 2 * antihePt); + if (outFlagOptions.enableEffPlots) { + histos.fill(HIST("tracks/eff/helium/hPtantiHeTrue_Z2"), 2 * antihePt); if (track.hasTOF() && outFlagOptions.doTOFplots) { - histos.fill(HIST("tracks/eff/helium/hPtantiHeTOFTrue"), 2 * antihePt); + histos.fill(HIST("tracks/eff/helium/hPtantiHeTOFTrue_Z2"), 2 * antihePt); } } } if (isPhysPrim) { - histos.fill(HIST("tracks/helium/h1antiHeliumSpectraTruePrim"), antihePt); + // histos.fill(HIST("tracks/helium/h1antiHeliumSpectraTruePrim"), antihePt); histos.fill(HIST("tracks/helium/h1antiHeliumSpectraTruePrim_Z2"), 2 * antihePt); if (std::abs(track.tpcNSigmaHe()) < nsigmaTPCvar.nsigmaTPCHe) { @@ -5594,7 +5593,7 @@ struct LFNucleiBATask { } } if (!isPhysPrim && !isProdByGen) { - histos.fill(HIST("tracks/helium/h1antiHeliumSpectraTrueTransport"), antihePt); + // histos.fill(HIST("tracks/helium/h1antiHeliumSpectraTrueTransport"), antihePt); histos.fill(HIST("tracks/helium/h1antiHeliumSpectraTrueTransport_Z2"), 2 * antihePt); if (outFlagOptions.makeDCAAfterCutPlots) { @@ -5607,7 +5606,7 @@ struct LFNucleiBATask { } if (isWeakDecay) { - histos.fill(HIST("tracks/helium/h1antiHeliumSpectraTrueSec"), antihePt); + // histos.fill(HIST("tracks/helium/h1antiHeliumSpectraTrueSec"), antihePt); histos.fill(HIST("tracks/helium/h1antiHeliumSpectraTrueSec_Z2"), 2 * antihePt); if (outFlagOptions.makeDCAAfterCutPlots) { @@ -5800,7 +5799,7 @@ struct LFNucleiBATask { const auto& particlesInCollision = mcParticles.sliceByCached(aod::mcparticle::mcCollisionId, collision.mcCollision().globalIndex(), cache); for (const auto& mcParticle : particlesInCollision) { - if (mcParticle.y() > kinemOptions.yHighCut || mcParticle.y() < kinemOptions.yLowCut) { + if (mcParticle.y() > kinemOptions.cfgRapidityCutHigh || mcParticle.y() < kinemOptions.cfgRapidityCutLow) { continue; } spectraGen.fill(HIST("LfEv/pT_nocut"), mcParticle.pt()); @@ -5813,7 +5812,7 @@ struct LFNucleiBATask { } if (collision.selection_bit(aod::evsel::kIsTriggerTVX)) { for (const auto& mcParticle : particlesInCollision) { - if (mcParticle.y() > kinemOptions.yHighCut || mcParticle.y() < kinemOptions.yLowCut) { + if (mcParticle.y() > kinemOptions.cfgRapidityCutHigh || mcParticle.y() < kinemOptions.cfgRapidityCutLow) { continue; } @@ -5828,7 +5827,7 @@ struct LFNucleiBATask { } if (collision.selection_bit(aod::evsel::kNoTimeFrameBorder)) { for (const auto& mcParticle : particlesInCollision) { - if (mcParticle.y() > kinemOptions.yHighCut || mcParticle.y() < kinemOptions.yLowCut) { + if (mcParticle.y() > kinemOptions.cfgRapidityCutHigh || mcParticle.y() < kinemOptions.cfgRapidityCutLow) { continue; } @@ -5843,7 +5842,7 @@ struct LFNucleiBATask { } if (collision.selection_bit(aod::evsel::kNoITSROFrameBorder)) { for (const auto& mcParticle : particlesInCollision) { - if (mcParticle.y() > kinemOptions.yHighCut || mcParticle.y() < kinemOptions.yLowCut) { + if (mcParticle.y() > kinemOptions.cfgRapidityCutHigh || mcParticle.y() < kinemOptions.cfgRapidityCutLow) { continue; } @@ -5858,7 +5857,7 @@ struct LFNucleiBATask { } if ((collision.selection_bit(aod::evsel::kIsTriggerTVX)) && (collision.selection_bit(aod::evsel::kNoTimeFrameBorder))) { for (const auto& mcParticle : particlesInCollision) { - if (mcParticle.y() > kinemOptions.yHighCut || mcParticle.y() < kinemOptions.yLowCut) { + if (mcParticle.y() > kinemOptions.cfgRapidityCutHigh || mcParticle.y() < kinemOptions.cfgRapidityCutLow) { continue; } @@ -5879,7 +5878,7 @@ struct LFNucleiBATask { } if (collision.sel8()) { for (const auto& mcParticle : particlesInCollision) { - if (mcParticle.y() > kinemOptions.yHighCut || mcParticle.y() < kinemOptions.yLowCut) { + if (mcParticle.y() > kinemOptions.cfgRapidityCutHigh || mcParticle.y() < kinemOptions.cfgRapidityCutLow) { continue; } @@ -5921,13 +5920,13 @@ struct LFNucleiBATask { // LOOP OVER GENERATED MC PARTICLES void processMCGen(soa::Join::iterator const& mcCollision, - aod::McParticles& mcParticles) + aod::McParticles const& mcParticles) { spectraGen.fill(HIST("histGenVetxZ"), mcCollision.posZ()); - if (mcCollision.centFT0M() > cfgHighMultCut || mcCollision.centFT0M() < cfgLowMultCut) + if (mcCollision.centFT0M() < cfgMultCutLow || mcCollision.centFT0M() > cfgMultCutHigh) return; for (auto& mcParticleGen : mcParticles) { - if (mcParticleGen.y() > kinemOptions.yHighCut || mcParticleGen.y() < kinemOptions.yLowCut) { + if (mcParticleGen.y() > kinemOptions.cfgRapidityCutHigh || mcParticleGen.y() < kinemOptions.cfgRapidityCutLow) { continue; } @@ -6161,7 +6160,7 @@ struct LFNucleiBATask { aod::McParticles const& mcParticles, const soa::SmallGroups& recoColls) { - if (std::abs(mcCollision.posZ()) < cfgHighCutVertex) { + if (std::abs(mcCollision.posZ()) < cfgVzCutHigh) { evLossHistos.fill(HIST("evLoss/hEvent"), 0.5); } @@ -6170,7 +6169,7 @@ struct LFNucleiBATask { // Check if there is an event reconstructed for a generated event for (const auto& recoColl : recoColls) { - if (std::abs(recoColl.posZ()) > cfgHighCutVertex) + if (std::abs(recoColl.posZ()) > cfgVzCutHigh) continue; if (recoColl.selection_bit(o2::aod::evsel::kIsTriggerTVX)) { isTvxEvent = true; From 7de84fe5484f8020ebebdcb1ff093ab781e5dd5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Jacazio?= Date: Tue, 1 Jul 2025 09:21:30 +0200 Subject: [PATCH 287/871] [Common] Enclose TableHelper in o2::common namespace (#11808) --- Common/Core/TableHelper.cxx | 12 ++++++------ Common/Core/TableHelper.h | 10 ++++++++++ 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/Common/Core/TableHelper.cxx b/Common/Core/TableHelper.cxx index 4af58f00428..04745ffe694 100644 --- a/Common/Core/TableHelper.cxx +++ b/Common/Core/TableHelper.cxx @@ -17,14 +17,14 @@ #include "Common/Core/TableHelper.h" -#include - #include "Framework/InitContext.h" #include "Framework/RunningWorkflowInfo.h" +#include + /// Function to print the table required in the full workflow /// @param initContext initContext of the init function -void printTablesInWorkflow(o2::framework::InitContext& initContext) +void o2::common::core::printTablesInWorkflow(o2::framework::InitContext& initContext) { auto& workflows = initContext.services().get(); for (auto const& device : workflows.devices) { @@ -37,7 +37,7 @@ void printTablesInWorkflow(o2::framework::InitContext& initContext) /// Function to check if a table is required in a workflow /// @param initContext initContext of the init function /// @param table name of the table to check for -bool isTableRequiredInWorkflow(o2::framework::InitContext& initContext, const std::string& table) +bool o2::common::core::isTableRequiredInWorkflow(o2::framework::InitContext& initContext, const std::string& table) { LOG(debug) << "Checking if table " << table << " is needed"; bool tableNeeded = false; @@ -57,7 +57,7 @@ bool isTableRequiredInWorkflow(o2::framework::InitContext& initContext, const st /// @param initContext initContext of the init function /// @param table name of the table to check for /// @param flag bool value of flag to set, if the given value is true it will be kept, disregarding the table usage in the workflow. -void enableFlagIfTableRequired(o2::framework::InitContext& initContext, const std::string& table, bool& flag) +void o2::common::core::enableFlagIfTableRequired(o2::framework::InitContext& initContext, const std::string& table, bool& flag) { if (flag) { LOG(info) << "Table enabled: " + table; @@ -75,7 +75,7 @@ void enableFlagIfTableRequired(o2::framework::InitContext& initContext, const st /// @param initContext initContext of the init function /// @param table name of the table to check for /// @param flag int value of flag to set, only if initially set to -1. Initial values of 0 or 1 will be kept disregarding the table usage in the workflow. -void enableFlagIfTableRequired(o2::framework::InitContext& initContext, const std::string& table, int& flag) +void o2::common::core::enableFlagIfTableRequired(o2::framework::InitContext& initContext, const std::string& table, int& flag) { if (flag > 0) { flag = 1; diff --git a/Common/Core/TableHelper.h b/Common/Core/TableHelper.h index afb42c5669a..56d2264ed6c 100644 --- a/Common/Core/TableHelper.h +++ b/Common/Core/TableHelper.h @@ -24,6 +24,9 @@ #include +namespace o2::common::core +{ + /// Function to print the table required in the full workflow /// @param initContext initContext of the init function void printTablesInWorkflow(o2::framework::InitContext& initContext); @@ -109,4 +112,11 @@ bool getTaskOptionValue(o2::framework::InitContext& initContext, const std::stri return getTaskOptionValue(initContext, taskName, configurable.name, configurable.value, verbose); } +} // namespace o2::common::core + +using o2::common::core::enableFlagIfTableRequired; +using o2::common::core::getTaskOptionValue; +using o2::common::core::isTableRequiredInWorkflow; +using o2::common::core::printTablesInWorkflow; + #endif // COMMON_CORE_TABLEHELPER_H_ From 1a9ec7f14f0bea84225f9c89ee780b8606cc96db Mon Sep 17 00:00:00 2001 From: Francesco Mazzaschi <43742195+fmazzasc@users.noreply.github.com> Date: Tue, 1 Jul 2025 10:48:19 +0200 Subject: [PATCH 288/871] [PWGLF] Fix MC generated information (#11815) Co-authored-by: Francesco Mazzaschi Co-authored-by: ALICE Action Bot --- PWGLF/Tasks/Strangeness/sigmaminustask.cxx | 88 ++++++++++++++-------- 1 file changed, 58 insertions(+), 30 deletions(-) diff --git a/PWGLF/Tasks/Strangeness/sigmaminustask.cxx b/PWGLF/Tasks/Strangeness/sigmaminustask.cxx index f7332656cb2..ac588fb8597 100644 --- a/PWGLF/Tasks/Strangeness/sigmaminustask.cxx +++ b/PWGLF/Tasks/Strangeness/sigmaminustask.cxx @@ -28,7 +28,7 @@ using namespace o2::framework::expressions; using TracksFull = soa::Join; using CollisionsFull = soa::Join; -using CollisionsFullMC = soa::Join; +using CollisionsFullMC = soa::Join; struct sigmaminustask { // Histograms are defined with HistogramRegistry @@ -39,6 +39,8 @@ struct sigmaminustask { Configurable cutzvertex{"cutzvertex", 10.0f, "Accepted z-vertex range (cm)"}; Configurable cutNSigmaPi{"cutNSigmaPi", 4, "NSigmaTPCPion"}; + Preslice mPerCol = aod::track::collisionId; + void init(InitContext const&) { // Axes @@ -58,7 +60,8 @@ struct sigmaminustask { if (doprocessMC) { // Add MC histograms if needed - rSigmaMinus.add("h2MassSigmaMinusPtMC", "h2MassSigmaMinusPtMC", {HistType::kTH2F, {ptAxis, sigmaMassAxis}}); + rSigmaMinus.add("h2MassPtMCRec", "h2MassPtMCRec", {HistType::kTH2F, {ptAxis, sigmaMassAxis}}); + rSigmaMinus.add("h2MassPtMCGen", "h2MassPtMCGen", {HistType::kTH2F, {ptAxis, sigmaMassAxis}}); } } @@ -80,46 +83,71 @@ struct sigmaminustask { } PROCESS_SWITCH(sigmaminustask, processData, "Data processing", true); - void processMC(CollisionsFullMC::iterator const& collision, aod::KinkCands const& KinkCands, aod::McTrackLabels const& trackLabelsMC, aod::McParticles const&, TracksFull const&) + void processMC(CollisionsFullMC const& collisions, aod::KinkCands const& KinkCands, aod::McTrackLabels const& trackLabelsMC, aod::McParticles const& particlesMC, TracksFull const&) { - if (std::abs(collision.posZ()) > cutzvertex || !collision.sel8()) { - return; - } - rEventSelection.fill(HIST("hVertexZRec"), collision.posZ()); - for (const auto& kinkCand : KinkCands) { - auto dauTrack = kinkCand.trackDaug_as(); - auto mothTrack = kinkCand.trackMoth_as(); - if (dauTrack.sign() != mothTrack.sign()) { - LOG(info) << "Skipping kink candidate with opposite sign daughter and mother: " << kinkCand.globalIndex(); - continue; // Skip if the daughter has the opposite sign as the mother - } - if (abs(dauTrack.tpcNSigmaPi()) > cutNSigmaPi) { + for (const auto& collision : collisions) { + if (std::abs(collision.posZ()) > cutzvertex || !collision.sel8()) { continue; } - rSigmaMinus.fill(HIST("h2MassSigmaMinusPt"), kinkCand.mothSign() * kinkCand.ptMoth(), kinkCand.mSigmaMinus()); - rSigmaMinus.fill(HIST("h2SigmaMassVsXiMass"), kinkCand.mXiMinus(), kinkCand.mSigmaMinus()); - rSigmaMinus.fill(HIST("h2NSigmaPiPt"), kinkCand.mothSign() * kinkCand.ptMoth(), dauTrack.tpcNSigmaPi()); - // do MC association - auto mcLabSigma = trackLabelsMC.rawIteratorAt(mothTrack.globalIndex()); - auto mcLabPiDau = trackLabelsMC.rawIteratorAt(dauTrack.globalIndex()); - if (mcLabSigma.has_mcParticle() && mcLabPiDau.has_mcParticle()) { - auto mcTrackSigma = mcLabSigma.mcParticle_as(); - auto mcTrackPiDau = mcLabPiDau.mcParticle_as(); - if (!mcTrackPiDau.has_mothers()) { + rEventSelection.fill(HIST("hVertexZRec"), collision.posZ()); + auto kinkCandPerColl = KinkCands.sliceBy(mPerCol, collision.globalIndex()); + for (const auto& kinkCand : kinkCandPerColl) { + auto dauTrack = kinkCand.trackDaug_as(); + auto mothTrack = kinkCand.trackMoth_as(); + if (dauTrack.sign() != mothTrack.sign()) { + LOG(info) << "Skipping kink candidate with opposite sign daughter and mother: " << kinkCand.globalIndex(); + continue; // Skip if the daughter has the opposite sign as the mother + } + if (abs(dauTrack.tpcNSigmaPi()) > cutNSigmaPi) { continue; } - for (auto& piMother : mcTrackPiDau.mothers_as()) { - if (piMother.globalIndex() != mcTrackSigma.globalIndex()) { + + rSigmaMinus.fill(HIST("h2MassSigmaMinusPt"), kinkCand.mothSign() * kinkCand.ptMoth(), kinkCand.mSigmaMinus()); + rSigmaMinus.fill(HIST("h2SigmaMassVsXiMass"), kinkCand.mXiMinus(), kinkCand.mSigmaMinus()); + rSigmaMinus.fill(HIST("h2NSigmaPiPt"), kinkCand.mothSign() * kinkCand.ptMoth(), dauTrack.tpcNSigmaPi()); + // do MC association + auto mcLabSigma = trackLabelsMC.rawIteratorAt(mothTrack.globalIndex()); + auto mcLabPiDau = trackLabelsMC.rawIteratorAt(dauTrack.globalIndex()); + if (mcLabSigma.has_mcParticle() && mcLabPiDau.has_mcParticle()) { + auto mcTrackSigma = mcLabSigma.mcParticle_as(); + auto mcTrackPiDau = mcLabPiDau.mcParticle_as(); + if (!mcTrackPiDau.has_mothers()) { continue; } - if (std::abs(mcTrackSigma.pdgCode()) != 3112 || std::abs(mcTrackPiDau.pdgCode()) != 211) { - continue; + for (auto& piMother : mcTrackPiDau.mothers_as()) { + if (piMother.globalIndex() != mcTrackSigma.globalIndex()) { + continue; + } + if (std::abs(mcTrackSigma.pdgCode()) != 3112 || std::abs(mcTrackPiDau.pdgCode()) != 211) { + continue; + } + rSigmaMinus.fill(HIST("h2MassPtMCRec"), kinkCand.mothSign() * kinkCand.ptMoth(), kinkCand.mSigmaMinus()); } - rSigmaMinus.fill(HIST("h2MassSigmaMinusPtMC"), kinkCand.mothSign() * kinkCand.ptMoth(), kinkCand.mSigmaMinus()); } } } + for (const auto& mcPart : particlesMC) { + if (std::abs(mcPart.pdgCode()) != 3112 || std::abs(mcPart.y()) > 0.5) { + continue; + } + if (!mcPart.has_daughters()) { + continue; // Skip if no daughters + } + bool hasSigmaDaughter = false; + for (const auto& daughter : mcPart.daughters_as()) { + if (std::abs(daughter.pdgCode()) == 211) { // Sigma PDG code + hasSigmaDaughter = true; + break; // Found a pi daughter, exit loop + } + } + if (!hasSigmaDaughter) { + continue; // Skip if no pi daughter found + } + float mcMass = std::sqrt(mcPart.e() * mcPart.e() - mcPart.p() * mcPart.p()); + int sigmaSign = mcPart.pdgCode() > 0 ? 1 : -1; // Determine the sign of the Sigma + rSigmaMinus.fill(HIST("h2MassPtMCGen"), sigmaSign * mcPart.pt(), mcMass); + } } PROCESS_SWITCH(sigmaminustask, processMC, "MC processing", false); }; From 8024ef0c322dd50b7190718805c7a2b4d167ea81 Mon Sep 17 00:00:00 2001 From: Fabrizio Date: Tue, 1 Jul 2025 13:14:22 +0200 Subject: [PATCH 289/871] [PWGHF] Fix BC type in bc_as<> in B data creators (#11851) --- PWGHF/D2H/TableProducer/dataCreatorCharmHadPiReduced.cxx | 2 +- PWGHF/D2H/TableProducer/dataCreatorJpsiHadReduced.cxx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/PWGHF/D2H/TableProducer/dataCreatorCharmHadPiReduced.cxx b/PWGHF/D2H/TableProducer/dataCreatorCharmHadPiReduced.cxx index ea593bd5ee0..a0748273b1b 100644 --- a/PWGHF/D2H/TableProducer/dataCreatorCharmHadPiReduced.cxx +++ b/PWGHF/D2H/TableProducer/dataCreatorCharmHadPiReduced.cxx @@ -965,7 +965,7 @@ struct HfDataCreatorCharmHadPiReduced { // Set the magnetic field from ccdb. // The static instance of the propagator was already modified in the HFTrackIndexSkimCreator, // but this is not true when running on Run2 data/MC already converted into AO2Ds. - auto bc = collision.template bc_as(); + auto bc = collision.template bc_as(); if (runNumber != bc.runNumber()) { LOG(info) << ">>>>>>>>>>>> Current run number: " << runNumber; o2::parameters::GRPMagField* grpo = ccdb->getForTimeStamp(configs.ccdbPathGrpMag, bc.timestamp()); diff --git a/PWGHF/D2H/TableProducer/dataCreatorJpsiHadReduced.cxx b/PWGHF/D2H/TableProducer/dataCreatorJpsiHadReduced.cxx index 39f3aa45231..08a8ccfeed6 100644 --- a/PWGHF/D2H/TableProducer/dataCreatorJpsiHadReduced.cxx +++ b/PWGHF/D2H/TableProducer/dataCreatorJpsiHadReduced.cxx @@ -665,7 +665,7 @@ struct HfDataCreatorJpsiHadReduced { // Set the magnetic field from ccdb. // The static instance of the propagator was already modified in the HFTrackIndexSkimCreator, // but this is not true when running on Run2 data/MC already converted into AO2Ds. - auto bc = collision.template bc_as(); + auto bc = collision.template bc_as(); if (runNumber != bc.runNumber()) { LOG(info) << ">>>>>>>>>>>> Current run number: " << runNumber; o2::parameters::GRPMagField* grpo = ccdb->getForTimeStamp(ccdbPathGrpMag, bc.timestamp()); From 4e484f3d6dab0517e5a3a0e1074d2a5d8e7a0a9b Mon Sep 17 00:00:00 2001 From: shreyasiacharya <34233706+shreyasiacharya@users.noreply.github.com> Date: Tue, 1 Jul 2025 13:21:48 +0200 Subject: [PATCH 290/871] [PWGDQ] Codes and files for prompt and non-prompt JPsi separation (#11803) --- PWGDQ/Macros/Prompt-np-Seprataion.zip | Bin 0 -> 5178200 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 PWGDQ/Macros/Prompt-np-Seprataion.zip diff --git a/PWGDQ/Macros/Prompt-np-Seprataion.zip b/PWGDQ/Macros/Prompt-np-Seprataion.zip new file mode 100644 index 0000000000000000000000000000000000000000..0647129344595caa99c9dc4f7f827a9b1546e932 GIT binary patch literal 5178200 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
hCk=3MR%2Ak^Q3gmpr-VCvn@6$#r*qp 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

  • tqchDmaNd5$J|qDmJs@T+;oq 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

    ^SgSh5ASw;VzEGU=o33MdyLuEGk2@Zi|^1I*% zF}XDf)6vN+cK=P%T`%xQ@d0=MHFMb-B_r<10rs-RyubN)Qx6_#yn{lNR#etc(#Vd} zZQnEcgLvoIVl^h&o6T8LZDg1!y7~8>=mm0?tk%8DvTJ?S*6?khIe@nze6O%_6Y_Vw(y;7fxgzO0H)o zinbYp;{kN>Q3e8Uo)<6E?7-YWdl*WO6oChZpP)Zy>}A5wQADH~Q08L<8VhGgFeb*y z#zXZNYgJK_FNU3(E4@9cJ+bMq->_ke?r}L$nAfA!GKF*#*5)Iicwxe(Y(m|x?gPPd zkSF(t_^3uit>2z5Gvs4KrjPiUg2IL($d0MS^ArXmXV3$yPydWuwFZs24J~foH)!i} zAuc%P%Vq8}jVd1WYLoT(m_F9^u+3dm9N8Fya-kXKN*KvDft>KSWrGCNvBK<0ls!OE z3L&}>0ee#^%>5`KQiZSTb|Gp-F%&Bz;)Veg)5MUO?sXa!3R&nx;*j?Ko)oNn832zl ze<&04ND>;HsVDTtnpfjH8m?}Vr;5~Bu$*^~;@g`HY1Jd7a>S?v`vI9zI~|<9nA=^W z9SwrL^PJW>8C#z@j#<{4G-AhMj}-zk&+OM_>gxu?v*f7=oYAM1!GUl+W#xlvO$!h| z!PB#BB?qm+LS-G!Cj`B(u~QE?8$(D~0dD_uNcJ&}Ay^ace2+7_6v`3jy`WAA@5!@b z*rxr@!Z82XyGElFrJc@sgpJR@W$MW9nAdBQO3u!QM6SCK`ZgkSn>|rXu!ov~AG(ac zjtofXwK1^&H`3kL>}rC*)0HcwCa3o-bwr)zat@w_ZfERBz9%sCc6wKG)!Mw){SsAF zF%&na-L@W8ZTKi?K)tpz3ymHotl+t3(G@&xHOUjU#-M%(YmpekyCEBs->p%QcOo2zT!x(TqOUBS`-Z%-FjhpzK<*h2==Sk zT$_vf{gnFox~0RVDO3#A3*_S5-Z3&O0yAbDlxGmX@4$i(Qv&X!c(yLqd)3kXd4U|} zddl5o-ZifP784bAb^1{F8G-NnFKxwa1P8efie*HuGT^4Ib;=W{BqIUi!5kB9>zURv zt!5MmKNQ|V9Qv!6CDQTDP%XJ#OovEcC#i8T7}d*T)rI%=j9K|Z=m(XI{~;^*wz~>?ajaTc^rp}}`O?+w(P zN>78QlswR;BgA-05866>X!E2ytso);kYVbICH-c9avnL};XCsb9f64xmjXEgnR&F} z`_EksWJ?uxe8WV9{PUrdA3> zm@}ft^>I?VEnM5%%LB;K-FLHiaz_B0eyrbPC#Z(L{NkzYO1SYVl!JjN8pWz4W61hL(pST>LKaKRG{H7G?r3C~u)RX09=-t8iB6;Bw zU~uAM7Y)i)+BPB;(=jp1J}dW!6JBDQnE}@o(t)qY70QpCwLMXBgch0-N(7YI5eqIV&>shI)1$G$9R*u`R6D-^y@)fha~_6Ep`plx zu2ON=9qgpm)4eTS8Op#K7P-7Vbwx6;a+h*w)uu$q+J91+YRGA4!QIk(v;OJ2M>3Be zU6;X0w>BwRtXs3M$V8z!aIq2UNO+nD1!I&@LX=g!f@i0&JBh#Hv>#yNJC!5mgKW=- zo;a@=gvuKik~W6n#ySUf#F!16HA;{S!E%ZJg|G#rHEq`~J8I5K| zM4Xd?m?OeTy%Uz-iTA`LUiw&T>(Kk&$xd$>RNvxti_pR8nwyH0m0bzz{CEz)_~aQY zgv|TrHZc_7EUw8py7XjbeKi;vQK{#QV#`dtAEEyE1%y6q%-&p|5h;XSJkDqubC2^F z;RJ7B4H{bR_h3M>eU_rr;BhZ&;STf1mq9SD7n6`@i@J&as-F5*i^gg81jMGA)%im@ zj!b7y@=K#V~tN*3WJOuUd z4X&kt&&y&A&aBqkCVKd3D_t^<&C7#Z$Ok)(O=^$Iu=tOT^mkw25?#nR>^fqV6i;V3 z0?jK($ zq>kI-SpsQeg!u=s5~sSwE;&F3_#9^wT}N$4d#>xgjcuZHLhqFx2bz~mf}UU4gzC0J z6zo^*j14>_C`W1oA_}ETc^&1a8KG0|3hAs^G8R*RWDzIje`4xSjR*A*qflfs>bM||| zE7lsAz%5zj{OAs>5$YCR1NO_7I(86~^nxZKZ$ShtYg=YIHj+@ZCzH;@XN*Z*pQQVCbEKbLZR;H zZ+T)7VdR=p3t+0>>h?Bg+MeRPpNk<^ZE=N=Dl!0~{dJ}Kc_OOJueTz&WAe41xJxIVyc-JJtIR8~VhKT4*q~X3PxHYfO&El&iKKV`9a!v+vevO$|xjSq( z?!a{Z#z}K+>yo51bX)|kY(DIj@F{ z-f9}}{YnK}n-y1_Yc>PN@0aQv*JaYoEcyU>>*ub#{5mua} zsH3fM z6#zg_!AK59tJxdFkNA%nAk{jy6e075cpZYND$#}=3$~mOUdTQ9)vfpTj#Ir`XZh*rh9$_K`-bWh7P*;F&pwgN`$J0 zuNmfQ1sW3e9HBzeT^L(r1b?OWRN6s=WvUPPO4+q!;U^oY8UCs6`&JO z>NKs8@*8T`sp*kepr^%ObHKi-)j2!l(rn=mNCw?=g;SRd-~FhOq~(T1Kkaa9?1}d{ z^`~+Qvwqd|Yk(3)iY&`>8DWghF$YgOx*j{mPk?RFy31a#gOun|KHS3+I=`$NC)zjL zB#Q`2y52|L@EDafloCfSPSGWmaV1A{3z8@H#daO0&_i}>!wtcODTG=y>>R|B54R(N z*UTIX;qE||A1SO4ZZPMejyO@pZ%?4louFV0c#fPoEn0bU*`gw(E;@6~2M?@NGIroGj( zSop~3?~sj*^x3Fi$QsEc9VU>Hclz~C73iCpt})lklx@;VLCN|cfGhnh*IsQ5ivprb zq+`SazcG1BOre{wUC#|NIV~pBe?aWZmsPy;(1td5iq+y^swT(^>4{nD>*e( z>fpH+ZJUBJNtp@N;ii1-W-AGXuo`} zg5-AZ?M%poUj*S!CqnpRluP)Q6{h4@5SC3}a3s|bob)<$@A)-?s`#$l@4Le1{o3&t zU54p$hPr=){-Ip zu&=YOcgm7P-4ijOyQ1t;wvN;b61b9|mF5x|Z_AUdY0%BO>AJms@E<9PgY+U{%SM*T z4MBRPxt4y-Q^fb`YAyN7sWWN1QoC`Bq4l*S_BEsSa-1?~tNF;k_UR@R{gM@m>JmE} z5}c$fa}le&vxaxAz+L!!oa)bLf+lM@>amwoF@SyXWJDKq2(z1k2&8UVY}&FiTYk?b zK*@uHqt1keWg-Z#znl9FEEynH9RHl^8IW?!7E3MbS!28M@Cy5Yy!~elk$$>DR}VV| zUSp0@ZU_@aau8n+%BoD5l<)|2&u7AO#E5qkPDlklO%A}GIf^}@$epO?n=V)~7!)^V zHmuDNr-k>J96Trm>c8_gR#l*qIc#Lf&Qn6Qi3sSvSVx5HHN6MyU7aa27=3r^uBV_U z7vM$hXkU}v+{r|FgsTIhh73~Q-y~%z@QRf!&d?XQ0@3BOA);CGh3PN*YtIw28yn&P zX#|on7dRY{nD*5GA3iqk^7zU1SkTeCMj~eV%M>L2F6VSNc#dlge3)4&@QPyduX(a# z-km%80rqXS*eqDbghw#GbN1G{dBV+NQ#f}3bG$7EIjYE$8G19EeW~BK5A)&toa9UHlDpI(q*+aE3sAUB&dBP|B8wa$t zg%Rra2)W4YaGV5$Q1TfS?NP6aoaoc(M(SNB#7ANf3SN;IDJQd4WI|BTrLbsST!~a6 zxy#4NR)nEs+p}fkO23l6In;@*Di>=cZhXAg3&w9~*XKjXN1+gMzyUR-li%Z5+zzmK zeCuGrc2s(%r#R}8ewT1pL-WVHW~p=@w8)pRQM)%vJ++Je#dc6y39EaCqXp2NcN68WyGGxCu$jJGE8r)O|% z?+s~$%$}s%7ecg5wz|T)u03;WK6U^(naF`4+-tbTs&7)o0$&!nYoB?zEj{s(qy`h4 zUon02M_MZNJB(diK=#U$7<5C3AJzln?WiYMLC32L>-yIi$Z#$>SWLpDQCtVB-8`LP z9WxL+h(1mi*=+sM1k?7V?>A}9M^tBiZ7_<`UZGdxK!Cn$Y7~i{_(DVs+kNkT_R4E8 zQm2-|>Z@C&GySwg+|hK_r`70#XL_m`q1q zP@w)gQp@eGNWEqKy!pD=vXMGr?bi{;cCn*0P3odIaq8-aizjrs!uxGH+D>51v%ZQ= zV0Rm%mNa{rP@W$^TzU~eJnZaoSJV0vP}{(43HUbLBdVp3srna8q&U4xa`D@uT(7O7 zd7gW=8(B|DOF7OK-S800J8x!GUw*)wGP_kz2yra86*gM5fw%(ECjB^-pdSK|B)tNJ z7u~W!R|Bo^*$fe-jL1m$#WhlDv>FgM9ovomo|W*B}dXy z-`R{H2i+|DA6;$jIb~~jVn9E(-l!gNi4~ZT?_eSfL?3e5z4{8##LbIJ&nS|gLMkyw zh$CIkaWx6=+AupEmivE6r{TR)G>>XYAT@eqUSMS1tND>Pz_#6 zjSR{y4}3kqXtA^-Ra|7~u|7F@8unF1vPKY}DK2xxdC;%8Zf#n6Kg?TjWLA^zi7U+A zqJT1$H5GkHTT1N6;wGJ!)*pN^knb?Um7R-%u?5vfbuCrdeocm!JsQ_d*`t5&1r(IN zRZs`q7D|N7u#HfPuk1YFA=>_~caF#3TyiEN}N=A4|9ow-1};)!7f zIVuU(yprU$nbEirn{Q=;Jg`sm*}V+z06zsZLiTM4h=5wdm8BheD|+tS8*GvcV{IyN zzFGZcW)VZO<6 zbh~&=LVH7iz<5F;M)N@+VftdQxEMmpdYxmiha!kV1Nu>7uQAERBtfOf4p?@8#{7~q zvO@eWwoX(hd(`Y6rj;Kw_>o5_Ri_n<2!pI~T=6FDO~cMww|mHB!uN zNbYu77x~hjOW@wFFIlxrJQhMru#zxs;5$V(B${OWjm|@rmddV_Rr+*AOqsn(A5o6jj@Ji_@U0A4e;LOO;{Tj3=uzMd?NLlOWF58PtWsl&D z+okL8L2!v+$En`HNUuil0nr4UC23nyPYNk(IOC1yX`62c8`c~QH^T!Tk|VfN7O*sD zegqqteGPZu-;|usj77yA{%jWfoG_~_K2`V2ER=wI9(f|#S$L~VU6OEtKBuY!`-G^0 zpn%<}4+$o=z0Y3TJsN&yaERx9>e+ywVq$>jz7eId?=`QE)KHtbZ$@*+hDY0!8+qxH z`;+GjDL|1EL4th`Qq+uhF1QRK0F~MK7Q7Ob57&CBGrN`;nh-x!ENOB9eBj_6$&?h} zN-3}Vi55Fx?gZYd2g7on3x@WmqW;nbcTATd>Lz5gyUR)fkn001c^w)v5TBcvN*057 zqy`b+M`E#z6@h6vb-ylN#8buc4*e&J?%B#$X&Z^v>HG&tWnK)$!3Zs$J-iL*%QfNL zYmD6pLK!3yk5fwFjI0tLY$f|0uneT0*cf2X_;ghya(}~wM}C(U;XI}kZd+o(8BhM< zSOFD$10&v+@{mP(*eAWzx*Ul5myoOxe`|Wv7C({g(pLG7X?5wq`Ufi%DFHjGQr>Eg z>S3amq#i6g>un)gi4sGi6@yu`Z|k_kk9Tm1*{kjkX_u3UtMjB2!|k8Hh>6qtYK`~T z62rS;#5K+qs|%?D3k%LPr_Jc9RBlU8V<{%me5u2|w<4>UeGMzera-(5999cl-4yilCyO?%aJyJeHu%iAzJNl1^juGKTZ7Mftx5uC-b^~66 zOvH_y`bk`Q?pFtQ$!@;5CLs04g=wcp<(AMN7h2iYf5Y(spqzadqRp z#W$0Bby-TNBq8r-gw4?5<5+%$Lwi1$Y{K$e!xet--?$+Z;6A7VMYabq+s=`=UV-T8 zPIMtF3ry@~+h&H3QRr#xgsY|RCI(%?^r}2znYX{Jrqrzu$8X*(bbs`9m!R~Z8Y>R< zAsi~U=nU1LHcY{0J0;2GO)c8HS`R(Q1G!Y3B-gr06FcZHTvWEzF~q1&=Fl)jY4ih2m%&gmv{MNiy`DT$|U@$>R*LSVtsxkenQ#8wdUZKe7XhW+=O<1 z(8N0ro4OXhu#jxE3KsJZ$W?NP)5h*;6JDBg-Q(UO1UCtJA~OILUkotlf9wmfsGEnT=HqysXBDyN1cL-*|kUcS?2kqsTjKAZ;Q-Fg=OCSA~z z+b>$la)C9EXK3gJ)2O^16{Wu2QgzxV*x-(uaZsN0zNJg6-RBI6=m%b9yxVei#?x&! z6Fd>2nF@Uba}jzUCFFECp#%I8Fa0XD9yXc<6OI=SHiIV!J>eKGdd)1K=&nb2u;xZH zqcGms-17_VMid5)Ge^>Q6xi3BVXY^Z`6%jWMd46@n%U5k@>ZUOAHi58ceV374dsgAn zg)@Sk&@`D&N;G_SzPv=i%5~nUV$waY#N_fXC{fE5dbHi1-Gl7ZU>KCPjYU`uno z!ogM-W$x2T8GS%dBY(DxrCkQmCMP6>XOzmE?#*2B-PD^iD7euUB>h$NmogNK zYs)oOIa$;<9A)23q5T7mXV51hBk+BX#tI)P9rd-C<-04^GQLPgNtto^Awp$fvqFZP z##g~bfG2_9h;6o8(at2b?C|{lGd-U%qbJc<)V`R-84?Up{S=_*qxCVe)v7 zAEtQhrUhg(8Z0r0caEEWdDDcog0oLDW1&b($o6{JE$|v39ZCBGlA}*afy#YoMxt$U zh|zjtF8+YT?V)%gKTe1gp6f9)O&Ht51TU<57bIHqO$HwU%(0^;(MJ5ReVDZ-nj#!a zs)uS%`7ITs1q(tTL>Mr+hq9jw5<6ng>`5*7{ZLpwY~?a8;hT2UG&Fl2n4f$N`UVJQ zCfft)7SpJv9IeFlABM%|+%5y?8eKMV@9mhU{Ov&Srj@k6w?!U{CAk<>=W1W2@}7{H znmRg88-3@;>0F!-f776{G+bv+>>Li7(Y}k#C^G6k^kOByognKY+q@m#Y6zVWune$+ zuM_Q(T4-!7j;>XgS&(puImPKT#M<^!3Dt%UmZL(a%F<8cEDEX8pVL)$;gP|@wDJuV zcL4)69kxaP@x}brDcPSpYUR@RVA|*>pUL!{O7p-glOsQvHhm>YU5v4NWv>q6by7v@ zZ%asJ{yjYh6cMs{I95Q_8_HqnuP#(ro}_$>qOjQg3+74cy;mCqJ7qU+h>+zVd8OWslNzD(iuqOkVWi7(MSclA6?3Q40ZdHkR+@YvRt`B>D!c-G)6B)8)NTDN1*{5 zmI<>6Q(n8;i<7;s5B=FZ))(zwkR9&KV>=E-2TsGB@}2W)trq%K$#act09uvhQ?@$f z7X2`IKH|W5iuSs8RQ91n1NV|7B)2U%D!&Ul4LFYs)Fy#!^)JR?$V=5lFy)%(To22trI98XRq_BbHM;&n>B)$7DDjMrA!fY2h@>(Vxm^MG;TE%5) zifL##0iS%0+@GtBY4(Z)LOzTGNb6w{uv|my?a`ebL4VivKJ9*5YIO++y$8T%(AEuc9l%sUh99y@c zDq#hcADtnZEEpmrEda_dnddJXMc2$nO21 zfLM&T8*CQoYh~TDP0JiZC(k@R1QI#l9izNsm!#a%PE5V@HBAjm~h7!a8*KTxjl)5NyJ?Eq_zR-dXF zA_wrbfqZF-&HJV}2lqC}ODIU9nRLsxqzD~zM*+!Ma-;C0J1n1Gw5|Jn3n#DHj9ZRc8%gb9s;)i8XScH~ zJ=h2~6jC(VmJb%YLLmza3}l4#VjsOo#MTP9S04pA_q@PzYSqDDI_kvz{8_$=)dO!6 zb)lT-MAixAJ6V+jvnjbK#<_k&N#)R4?>3_Vq4)qxw%dJ@Mp!pgbufkMegg;Y`T`G! z-i(n!qc;Vx6o5AxLE3~oC)GEdH4$*ys>9pk>|_rn>W4L&Ra}xzdgRoxc((+}M-kI{ zfD^puy_UJw<^X0%f{~>gdWj`>HOyF>R4@nlaFBCpEF?O2_A*eau9j>x&PleupirT71>3Gdu%n)_yp{9|hZU-`)83d9 z!+t}lkokFRRe|u9c5gp$^LV&w?1&+wQU)pu=^tyfxFHz#KtEx=D>}{Qn8V4D7jvC^ zXDRXytR8CDz)%v-@@pUR+Sh&iteK%1IO=nnmk*xdIZ2d_Yt93Cn=o#4%`Uzpk!b+~ z)#yoNvf@GyU3=He!e?z?%P-LysvJ!DbG5xZ&J??&uKDTu2YdAxU-Eg91JRRy1n3q` zuq-`yf#9DCW;-bB=mv$`jW*%NLq^-Qc;m<;iQ`%;&S-sOy5K6Oc(U*gh?~HBZ2rNq zMDG1G`#$EMnPCJtDeZkg;V|y-h}UZpYv6r|`u#S}bJdPf5*A zFe|Q@w23+Qh$jQK1>Z10s&?vYniQ-%(R0+(ekA1vUxSL$x}rJ*XX}bL1S}%Itb%fP zmNj23yaK#mBh}Q8lq*dzlIbBUO5k2E++*(#y7t}pa_BVq>#UqK%Bs8;8s9+f6ZeTU z>OC1*E4pRU)-|*i%1}y;1p+Zk@zji|;lq+KJO-Fo%Gu#x&rmAbX{v$+1Oacb_2}*5 z4X1^=rQDccp*$05m{>?(&qcCEoiZ1t5w#zlr3;*Mf#5b5sri@!RqE|w?FSpm)B<{= zKaxkiYnQ|YD4r~?kj|D4U(gUaH?;J7@>JF$<$X<_tbS5P32jq#0P-1q)RTv2jbYyH z6C@4mwX^@o8jp}c3T}fJguiIV*CtH%-VWtADm-KzTu{<}8{p5e#3vrKX;`-PGi%L~x?LRYT&w?T!tGE^R;=Pbq3MJYe!~?~Z zg`cYWr5A(Ic`av!6&d=-mTh5#Imn-iGTZvWeW%7;^7F(_B)TT?-q60$ZK==MLiLRq zfOstS-*@CU+5Lhw_Wv+SyJFW^(SIDzpgCjzw!qK+c z9E2ah9f3eQV8oake@FJCOq^|;70B!el*L7Z*CV^7!isc7qM~rBiD~f^Gq@sYAUkR_V)W2SsLXf= zy=~?fw-5wK%@Rcz5ANu!peLSwX8DI{&lG0!n)Sy{AFIA$4j=Pcs+CUg?uEdTd}&n2 zNIX7F3s*ABR>RUy{O}gsqpTrdM@0HV;wt=NgS?U+cR!@yD>x$&OXp6HAQZv27+2c; z=8MBAAH(Q!Zr?lDYbUt;0>@1G(Vu-s-YtQ!sZ-zJs@Wq3Lo?@; zy{%>$bq9?jf-p{ZkM~IY<4=4|yWZIx20&8DCpNv|Z8R|!(^_`iz^2c=z#t1D(W1{1 z8Z0ztGxLFRdCPaA^nPm>(IY=E(H1BQ(-8*5cylm;Qh=M($O5XQ$mBa4h4p;Hv^sW= z5P8?84l#T!nDp%eQejRxW@`o*h2aE><>MErMD2Hjl9&e+Pr&B4t@%3j#b-o#ST$jbTuW0x7Af6+2f<$q}z zMgTw<>R+^sFeDog!0;bC(7zraAP4}g;yeH?RyQ`F|1R(!Gv$8>1P1s72HgJwq5bFe*nd-^_5UiV z`|nDi%|#rXosC>v98CV_&^doYQ~!HtFdzWo-_HU87~X<%{w_6?ZbbDAt%cU9l>sXi z96_cD1Oos-1pl%~NOS+8Mfe|YP*XerC;~Y!RaNKz%Q0F1$HYHDpMe2$NdF2thp2}E zc+s|yyq~XNbA){&$gwu91?L&U^3-3<4f4AeTeW&1e50JR-x^Pgv(23zb!Qkr^edQ> zYM^oSS|G3C(a!| zEPzMn5#q$7O?#>J$KN`gnBA6iu#4+bc2}3ZFYLT*OtnbdW^GnIU9}DMt+;yzbbz}M z>*2`Q+2_II2`aH%w~CIe=Wm!0T?2N6s=N&mlH1%?&#;F+s{}oE!@J>>jRd`x*1XMqS~7N=$3RF3qVAeC{||@DTaB+l|t!F2Lqaf;scYXq0m=q zDK07-P#pk$9ZsGREy~?2AO@-wFg|)%{>1RH6K@ak;0iQlu@xlwNvWz4aYz+;d+AsA z{d;UFQejbI?KWhjbalM5Nkhu}AnL(=3j ztaLIcBUUoXB2G$a7y_A)$8c~o=rOjyu)O73;(VOlew zz`BA1QyXznW#z<@d7yjX!lZ*!2b3NYoCSn=`mb;#I#kHqJm4Au6OYm(=t+}cvrLs29~ur zJfx3es~KM(aE*=@EDk4&D8*_LK|~tRMl>v9GR@`5poFks$MJ%tyjpQXe;6$~YBzEU zpY8|`7uE=3#LCu&oY)p1(4~qMBV{=vF(HxRflsQ91P4wHMiyz6$Y{QS&HH_DQ16wQ+W5e&)bo-dv2Ezf2$=7 ztW*L5jqfH&qGAFt0oVc6<3L3|J0<(cOP3coj~S-F_R{;1_B`I&)ECX!Hf0CZwdW1d zNFbQD?Ge7w+C{#=K?0aC_nPLAgU&>%%+!Co|F%Yt8Zb45I{`Kv;?dgi#Sp{Eh4}MZ z%uc!ls1CtFZ;eE#qQqN^P?;`e5NaUlESgv2xZ^SwbbSSkxg=7Hm-CZtW97%UeVcpq z`1_}yp>dWeS8EMc@|RQ`G>6N_!{aY@Q+!ZjrbHKb>FGmKi-ty8x@IlRHvUV!NthV#QA@l1AzT? z;(3d>@{fbRL+(GF0T}1`0YIUm&DapuNcS1NIxQ9by?22BauHJfZC2#X{~<*EKbzIU z|G~dPnE%}=?teO2u@(TJfd1R5CJ6w|g>UwY9Ou=5RH>pVtfm0-%nu$$`%xHX-&Qwy;#X zl_R@rF`rvY0Nmj;7aZ%aa-hq6gE4rKlx+~0qCX)*cO>@L@yw)e&#v{r!cS}QYroGg z>{r9_5_5ephtBMObjfW@o0I*1=He*>NvMczQW{ex3Esz6;Zg>w7ZiCBa8rXX z$*^|uuYm6|On}MYF1Th^m`vl0O6e~$;-=iCSoYv;=wy44ia3zIC3n6&%`u@sF19@Z zJ@=!)M~HbL_oe*NkJz(8b%S2Ot63e-4c^*~aZZvK{L@x#a7SRWo8*0X8xo?G2d_*b zkSAw86plivpA(PzrW}zBVStJ+i1s)TyPv0SdH~f@^v{R)7|G_2SnN+U$tzykYxdZR z{PCmPQK_yh`g2LvGw&M3x6l|5uBhdSuh?Iw)N7cyBD+ZpZiwk(hgL{SL zd9sq+7~%6WP8`>~p97E)`&7g2*|=5%GFu=XXyn5syCA6T9UAuW+0kEP6(+#;L_J_u z(uoJIHT9qPRf0Q^Nv6PPx-o(WZf()$T+Md|AU)(&xA$135ekjH_JFQR6&c4=&3lrw zc=R<~l_Q)#jf^-JPH*`&uBik?IatJV!BO4V&94$eeRGXAB=KAf5}SV-i)}J&Z<5#< zM>HL?Z4-43W4TZUF2>uybWKn|TSVRCs^M-+Yd({JzW~)Y?^$)WX;SAuR(Li|ed2JB zuZSAwFB95v`=%4vD>)1kqAV*$Z1az^{s6@JG*1|k$wm_3HFFd;>T^zB(KWvkIqKhK z(T|_(DCzJNN;|Ak(sM8ubS2R5q%7VNICv`*q#V>LP3`RNu0&&=k(kawBY6}S9eX$) z*Om=@2T@&X{HnO2sJ!k&pL{GR{agp-pgHdZsg9Ho>CSachR-Om$EV5OqH`oz8hg(y zt#vz=T60*0czM{#L< zc=d`*dm*rQ`#p8Q1U1qRD6i94bG8k?!uus?XtOhzQGM`4^hC!-fJOHp06Q=c?tcF; z;zdS2aUbNxj7&a}sqp_eTsqW%p7=ew z<|_-?sB|wCKt_cZp1$pbYnd4t{>*232SX`1))eBE#W>7`_f z>it8Su)Pg4dZ%c{g@|(7YFls?B7NH+BOZY}CP#?21XmT09aHWN4@XYYWg%o-D`3+UT5aP46tz8HA zU7K;dD@ml)%~o3Hj?SB;QNZoR9(dl*5vpsy=rjlNyfX;K(R>?11kB7znZ{3M`_Y}os!#@m+&hDYmwyQ=su$PFK8%O9zh z-y~`}vDt1az|%dYVc)V6JOx8%spHWG4~cnZvY#OOmidQ^j71vyCilzyhZ5UA!OvOG z5ecrcdH8JCCY^p%%6`6fiHjpgU}&1Z{bXd?G|l0=$JYiUeKE z^t+0|Eg?n?71C5G2*)2pt=Hj|KzRWDM}pW{wT4REgsE<6@wW1Ci)uL6p;Fs>HHrdE zC7fk!<4d7zXC#Mt;zB+#GMAD2KUg*fc_%+x2?Qo(hKX~gsT%Wbu5d6l72FQq(jdlm z5I1n{fpf=fwiUBH1Z0MBBoFh%;`Ky};PM%t@YhB-%Y<%&(KbO0x|OdU%}Zhm58(@= zcdT_g%Ga0dsbfDksk+$QJS|wt{bcr0Vs3QJvtK=1Et~>(R9y4|A)@~bEN+jJyh;^p z!qp@8pkn_o#_qAX5~%GGaO~v7wr$()*tT_I+g8W6ZQHiZj-8Hro_A37)_j@y3H!s| z_r0pF+Up46tAk6a)DxNK%p)=xFaLUs@K0cR(KP4^(lktWD8Fk8tSgpSX>QEmzewkH z;>@uxKuGAI3QwqlG1yQfg4x^ zZK}w>@p;#C@Jd+l)*pr4w9Si7C*H> z6$Grf?9f2%iiNzYM*Q{_J)O$r;bZaLZ8<{i+2p{l5 zfY{|)DegIFU;r?}c~YBS39L6T5S(?P^E|j^_uwxUZ^bTOS!Q_;wY<@JZU{<*_nX7< z=c?Ts1gDPo$Q1|6ccrS2s%c)8ZRhYxXe^y6c>wHK1|aBs&+m0m5k4rUT^VA>ky~4W z=4XT=1>NZcZx9!K;z=hyOAW_HhjYLuLY)nfB%AZa@NdTv=SJ2urWlO{DVYsKiYDDi z(heDG?}+$L22*;T_-2IuCS-!q_3gz5z1e6!!-|H<)OmH5q$rbB~ule8V07@095pR?Fhga1%Ob>fye<|o^-Kfdk=9i%UDTwW=dZHY}PE-2Kxsk zxUh)d;t`Uh7g+2v&hX$uUAxo$c921G?c=xtD^XIQlKdcr9{5R0f5lXplL@l+SUzGj zk9iybFhI}0q`J*|MP~xn-vbv1Qkd=BTzgWPPxKi}y8vuXkjy6PLPpVWk$W4I1QZus zWEIY&TGmS@Z>9WhMu(0G5HdZSUmQx8L%f&QBRiWD6GN;Dc3_JC^O_eC&_V4wxX*uT zNf5PgvaPSv$Uz!_uC}eh@+4Fp1U} zR-xxcC!gvEmSjtdwPz~d#oy-185w{5s)!(l+ac^5IWw}kro!Qa zHpDS8)J>k-lc_rs&mF>d0oh|lhuZQ_JpHRhdhQjzcln%Zson5aIMlr=NfYrLYY-aj zgU#!v5o8`y_(1bW-Jg9@2YF>HMf&UjCbRBb@*Pw6{a)-zFZKrYM;M{{Qt)tUTiBxH zii5X1NO9s{TNW1Uz3*zug;`K#!B|ThnSk+LWZ(-y<%os~Y^RIj-yEUo#)d!n9WB{K zx*jJ-0@0BtmBg*nC@yUP%=uN2xO%I5y_sA6aQYfl=RQivZhehy&WV+{VpV5F+Sq;K zt_bB*LF%;Iz+9hDHT_7K4&$hf?xC=b=8hG6Xr)hm`fiL>Ps3ug*Q~fVbfaWB<@=x3 z@?AuQI}V`@wi+8MPVI6uy|>V?TeIA5`-{fu3!il`*ND^AzTk{)=(HCo^u*!&letyM zzxjY0XRE8=;GJ6P0z63AS8@Bblo4yBvtb}7$F=dsDLm_`y-b+1A~G>o$WtE2`)#}A zTNJueLdVc+#DE*N^L4oJg+%3@Xq%RZc5mdZbR-`t&qZ=hsvot&6D|v<2$50J=ScXu zFMet}Z__Qb^n+&D+_tZMaFG&_3sRt+M!!9n^^KCE1+7FSV0+mOx=SdD){#SZt1$PT zGNr+Qe1SkIZQHYpS&`E@fP?%48~2JS=e17ok0(Aq5#lavAGe2T(J=Ih)jFx1K}6&( zxj~IoQ_&lE{SL2S?^9F|7c^%*m6F$X5Q(#t=anGDE*ZD2p$o|^hxp1>s`9$CjH9sW z7A3k`IqKL=EzJ!ca%um?C!se<_*tXn(SrfF)D}M2s*sVEf{fgCh1N#!S5~vmg2NQ} z=OIojqSH2PyI`WYvy}=DYr-0eeAKOE2hwD0_XeRWEkeU^q>+0v$1P*zl^u0*fM3*J zdl{8W1zL1)ty$;?7{V40y;Xh*20ty__YSVQM=k}tjAB>+Lg`yi|46?H(GHr-JmB< zblY}*6KN324^(a0$o2nV$TEF1#i1 z+iKp15M>`Jc-!^o^&jYgu&afzZ&ZKG^G|dlC!(%ST{vS`Qyif5uZ<+O*qF|%K)P5W z2tX%3^D51Q(g2ih%C3CN+CKxDr_cD+L4GR_L) z#DY&v&Cw`%w_*8(kSPA!G#QsZaR`Z;GG5?{1E_+)zlD;&dAwJ6)0MRpYO1@&+{ z+C7!&pctI#%8me5nR3_B+|Yv$*7$BigAd&)9v62O_azEMo%E+Vxga;LA|~^Q-44FN zYDbha1@q``I6@mo9C=OC_Mb8JZZN404DKPMh}5t{dX{p!C%1g$8C}im@NiVl5Zm~w zB)`TpO=6 zVje7R*W*0By@8GS#w|bQX+L3R0>Oe)lV$wp!fk?}vb;~%xn8exZ5Mvh6vsX?)Uo2f z_zb`%91Fbmi^RFAcw8fZqy7?7d*PL9WD{2Nz*mJaU*W(@cmI;vl4)){nmZqkBC$Wu zb72DysA*e7mDdX>-fY_){}%tU{^^cycSl}$7E|Au%#a0041APhn!q=v=1km@kji)_ zMD(0~$>1%>Im4$FCA@GD`BXE<6Wxskwtl*D=ba_tfeF3wm`COl|Hl7S=|O0`laBnK z89$?WU(kvo*9Av!P)sWF29AA6x9OeN^@aw2;Lg04T-Pxydb%eu@tI3{&A}hG8)E$y zB8f@(X#F>q!tKrIkb@ZS4!v(p3RZ{NDEifP<5b;(DGO{a8&~AFjnI__)Xt2WvwAT{be^kORU_@E0sJi><;330{UT zs`1z{V`s2s1&`hMyzr8njBh3-;7&KEV%t;KCtlu>%OC^XB#a*s{M=b=kFvDND=+Nz zS2bT2?yVBrh;pZ=1A=P;WRw5~kq1k{PVYOlymf;9B3buS%T|)pos7vv?ik#If_@sf zGh;njpbMAWe1NdD|sgFJ`t zVayX%blNsf2@=_2m{hFatYp#$1mKDW9RP_n``Up^1NEgUE5=(_^OrQiD+V|@H7%|O)sQLvTI@3yuk$+b!8Mi19(-8f&(Pc! zQy{-)o-%aEg2D6jwtUnpX@C>jl4?9v{I(<`2NiJ|Z%F5PC^3rT$Z4-+N*6e?3;#mJ zxu@tK!ABeb#+!m^%qH_r57WZA7imimP8dse1Z;aDOo?hzgF=OwztqgO4OC})rdRh6 z;UgHe0F~OnXLxO6OoKEb*Kn^&_?eDQWqZ!Xa24^LQ-(((_KmWn#kiN&dJ3g}810)S z&K?4G9g~qB^pfZ`hQwCD3^ODL@$!zY?#dfK>!%Eu2VKGrTE?M2ZSs>ULD3tI4VRfq z-*21Vq{?nprZ(GyC_xydtuV%(@nGJ0AZ2gN3U49I79?Bal~vVerZ%*%?azSGy5hxV z2yb4$w(h4Y=rt1zi{)^%{!Q>FjOtb43N{nJtJKI_-hjrs+q8S1;8oENeY+^-M^3@9 zkWEc`)X4#v^+d6>&fZ8PBleg*7W2f|aco^!QLf}ZUo!M!h*okoH)U^p$q_1?)Yo{R zyTa571NElg=;#w7^Hzc@%emazuX9Oz0XS1C)jq-9ii;o;HIo|cU8}$?cVLNt_56BmrDo%@d%pZF@rp3C z5xh@KBmq(=pBjh|iTXgpVX{>*!rQGt; zNb}l2ePTzwP|#9-n;WK-PCJ+jP54+FfnE_(3qPT-tBi7FFk}7~LZX2bvLheM+@X`s z566_e2OH5*3f0!84+rIUVl<|Mlp2 zo@zu&p*>j9vWN-s3~wh@71X?Wv82BNs`he%Lba z&PL2ci{M%0CkFquE^hSkUja*%nFdld4}em|wGeeiM5o#HeHo*aS)Yv3$67p=L@;+% zmk_afcRv0J^%=b;h>bmTW?IOW=<8DL4F|xE4~Q&us3s&@>X$gkr&oMJk9`jO(}!lf z_KUXFMY`ZEM%rZfp;YK1g)<3y&o*SoWkkS(u18APls_1b%0vn*jFFqH3xc{n$o`tjYUM7qlHmySO)})J@p*}cowg4|-I>SiI*-#g zVHm;|1`QGsTq*|;)2;H$xry^!jJQQNsr#OY`6zl~M?_d_J&@KfKIe6?qs4Cq$1qsp zZ*|)D(tg(g*qadjb+BHe`GGWJ28kUWW4w=z`0GK&tEkXy;X83%(G0<&c6YhfYA)1o{x!ekHNES>x%AQhAXS zGJW3UVB;NV2NpXUevw1&c>0sP@C+uIywHjFo7gJ8D%OQ^{ZSz|{r=Pa4p?OKqHK$< zm6&^W+b#9t&gd#o&+F|_d^>RU`i!_c|8UoYkU@y#Y**w}#pc@itH%;lrkri{REEMjI()x%K9)}N7X|FyKoD2#kn6OdoB{n3xAf(aQW{jViR3K(L8Ov1&-PC99 z=pHq~lec|E;V^6?9iHdwiA&i*!=B`W1bYK>_MZYjtpn?PLt$YoQgksXI@M%s2&n9= z#{JYJ9Ky_QF&3b?^-ZV+zX8T-D_FsGAq||fVGa^#dElcL3sG3!Fvl^=4@c|~{@Igi znVIK~DW|5Krv(*|th%V=9mpk7{7%F?XGF5vCoPIkFYAPCzEC3VvA5J`l!0@Fahqtp zUg=(w#8Rq@FC(YRB9Om#C!mHEgb1; zKr-z@f^(^`!?8W4(mQ*nExB4F%a2~&pw+q1)lC=cxqYQOHOX3+CGTz!`st7vZO7K7 zQ+{hC%uufo$pz&}lDx9S&StvnP7;j1mQ$<|k#Uih24c!~41vk)kppi%q8EItB?$uA zZS|UGNQB)x`3kOrM;E>NL;R-t-Uc73B?pR-Kay92a}sWjK#*NoqYb}9**(juwPSkV zzRE?qe{*3`@g<;?_<5{a<**q_JZsJoTM+Q{stF-V|bIVq@KXd-Vf!`&~cf$Sm zG{M7v?i>?mB_4XND^w1*2ZWS>8i+}E;er3jRR<);6=g+9chv_z>uIuUhrS0TZw~wX zCxmd0c*dCle~*iRbKTM4mYw{T`XWbA5wMXC0~vbx=}V^IvoOE=pObd>(4&1P`yCO) zIi`5k-*U7&P1@RhV4^|g=#z}^ZD5FfWCc&6?2KHk6CPsmv2Ih1YUi@TsRADn+pSPp zgP#ffUf5AhxpI@Q9OMg^T>(5VTN}2#YkBBpCWMngRPqC~`mF*K1c)@g#F)80MbIq_5X(n!2A~zs3-kzOn?Cc)W$|5njYDT9|0QV zpa3xP-0N41Qzt5i%_)U|QVl1yJQmJ{i{73h-icqRLfWIifRYB20h10BKolL~jZMgh zR1zFjZFIcUp)5`WB!5sBc-%^iGIP0Lru5L}a9Ap-cWEOO7%5I0D;%=2n5H13L$L?; zx8W#;h_Kgp#c``y{z-tK>A5R9<-)%2L9Dc!za$rc+Dyh8eEGeIa3KJt6eh?h`X;+m z@FN^@KNKcmU<|oLurC=Jr@DnC{K`JD`%4T-&K4wf3avUj7a6JmXT%4QgD}Kkovz&;UTJ^9=Y(Ew-&6Wd*i3u zWIx-|oUmt$N41wW_IZM%T}S3(`1~!S|1`{i=05YCiTgcTTtz+{^1Dtig#Ou-NkCN=VGIgn z`eEz3IIAJMvZ|R7Xnh{N;(x+Rq_-@S5*-{okNx!ytUvZ0$LL=QtoL}))XO?E(!3zK zJ1t?pgzO%k%*#kDM};5fMLE+#i#=t@Xj`5%9&++v0NLeBQur6B48RiktpK#={X3e` zkAUk`qc4f`w4uH(qWXq6482MpvtU3oaG)E#hhTmPZ^tds>2f@e_fXnm{-*x;@vq@rWRmsu7sO2veqG29G_EoA6YxPIIOWR{?ozRdLeunQI3TyB2KWZpx72tOxp2D?Ed-9ixMS><9CdI}QfLOh_>6^Ues zBZsKb9A4P9V{~tBRNXUeVcGw4%N^cXqCJK27G=rql90K~27AZ{-U=>2twlS}L;S;1 zeY83T)8oPB1G+p9k6qhAlVe9mQ1~FkTW!nov7=RCYtTSEn&eNx~e}zg~=AKeSxEWrcN!Mzq8-hxVz|!nd*3r`YKJGrq#PNJ}$fyhvFZEO$ zeU2m4JpQ7xR3=E~v~&Ya;A{jD=T>SDPm9&y<#G%$;*UZ)o);LGzuu%n>ROc^kX9dS zubKE=kchk+_SaR@?Wvz1$gEv|s(lTl2V}kk(eBN?=*T=;f6*&e)Ktt?AU{F!KG{yk zlz1x0?Re%ZXD8}7?8)DF3Irs&^t>39Njw{zT*-rZLo4QP>iVrrD^J2{r+b!rLVwQY za}k^Y_4$Upa}W9XEJpu`N;^Cts!y;H(rmSG3zN{ijyU${6*ZV2hPe`8b+aQ&EB>?T z*RC+-bpk}u`LaTuH2^-b7#cWMBlX3)-RBT+~g>ch(CXPYanBu{{HO5-qq`c zMx|~i@49OMiY@So-8Cu2{G-!&;5Ym}Y~x7@C=@je*qr&1R9TuJpj&gn9|xlPC%7~A zaHMLxf!ieT2Hhfeh&ie5VMU~fIasdHoxe^{#D2DJaBx>zt;UkX-wA^fay@mo@}uPD zA9`#d85DFYR__>7Q?2NC;WXKu?>Ti^pt+KqXe&xKrO0N0M2<>Ro zp}H1$e7lOr0c=j3OZ!e(2fW@Ggys2(G276a8FPW7Yw9h*u3<;jX^4WiczormtSn#Z zA-#M`5Kb6b0)3S*J4Clzx202F`6>-{J;=wM<}&9jfrG`YM24If>yRVF0!`P?2(bjG z$lZJdA7vj9I(jXNcA89&S_}OCgMH!=G1+NBz8Q5U=P*J%H_7u#MOwS`5V2$(x{s(% zVSZ+iGv*gczzMn)O4No=A?+?s2ij$mM2xeRqrL=E3IR#&#YSoPyAAcHS|J6m`?09a z>9j@%kf34BUg1v55Lha4A6b@ zJH}J(tp1HaXa4nh2U0i>R`zx>Y4lr6v+hDnVrbBH7hFlrZxN_%%fH;+bc;iLLC-zc zW4pFI0X|_{IuTY?e2KY^WDB%pQXs7Bm6;CtaZC3q0fHZSrT@dcum^DF0$7DNwVb)@FS=a&Hueb@ z(mhoC-=Jez>D)>!h4Vk_RK0_I%iiwL}$kk@fY*<~n4@SWYyFS3U zOP-iq_VEG-*zds@sm7X)}7>qmvmMEH;@aDYDZS$C*?!=P;oL-7?_zeTd(9 z{X*9ZPUY_4x&>p(Rp-D4>wPLD^HSx5r4A#%ST2^z?OuH3fjibPjxkXiT_;lWCCIl5 z^6UoDpxCU`f!WJ2hldyinBA~Rvp#iRf`N|rF8IM6D4L_TyBe2TJeceEUMo11)O&Ga z#}an8dDlq|=Q%S19*S2gRPlQ&S1U%cAk*IUjDp8uX?siG*M%lWb?_}f!YtVSuhcFL z;|oPHFGn2O=K(F)_2j6MQV8QOM5%Tjtsq}i1_u8#=v4)<$X$4M2c)3T5f2%mfDFhg zjB6~o`t52$bIg}d}$g+eC52L?LK8Q@Xx>=w%N^f^OTP(ah2>|U(|;ZlpTC%iu< zd!&jtBa5C+o&sk&N3NCO>*feO4Lj^oo7sQB!ZWd^NNDyeoVg*Cs^R~Iwbg--vK=b# zft!Y4WgUF|A%(1KVT@T9m*~lg-u4Ka%!~k|f7e5SM-;idBI;}E(={LPv+p5{dap0^ z&)x|!k3BOdEtDho@>VVmP9cW6ov(p>GZ}G0Q?hQ?V?7*Vo6Cs{uihC3pYvmX?bAT` z!$bf>2%Vmu$6-WgXnZNwMh(Pq{*4GLS~sl4%afn3izAnrffV0jN5;uRM6%_fg~?8} zIQ%CPmQ%y)}!0$WDI%FZq63^Y$yzKkH zlStjm<FMK;6?rpk_ouEw^0fg`begUije&3|7cI z2?2_4$zdN8_}o8Nd`GpGlnTf3H|qM%Tx*AmT#7pR6XsWn{9y#P(r=W+-b9>-Poub6 zJTTyzLX|fsUB$-BI-&y#(Hx$v=5y>&qeIj2>H=&KyIxoEgt)@zhE*fAw#BZSGtZJ> zHM!C#m%o5f{BX>oY#^W4n3j(1EFm3tP-d^-NAOY$YFl}RS6>QCYKHgZSIr4l#W1>`SZL^oJ{0$ZU|M<-74rm9c>BXs2ciZ=Ia8^7 zgj+1DYB~*AB4|fk1xf9-6kQY{Ih`J^m+;9$J!8Rj-GPrAB9aU5X~*S!AZGj(vr*H; z$5-Oiays(AM$PZ~EH=UUm=JxI+ALXc0dUE9cQ6E;Ptt6gC_JVZ+ZwvvJWC8~5dvyI z*fTqw>^x2s8pd(bH69!d9p}UiE+v5GeH-GpH4+pib>pXnEV9RVogRasA+I`yd;s66 zS4pMfx#v};+;rdtcL9Fw$cvYpbQApi>sK^Y{C4mCVv>Gke}lVQCln>F*3e2w16T`% zvKLAm=S<|NKzczYBq7vG~$+P~GDMz9LPq$s@Bw=K2B43o)nama2lt?ux;8 z05zwgMasE!3$+iJL6Gf04{rf-e;xV4h6>i4!h2XrsZp{uc}hMPfAvz~s8>@Imey^B z_lEl*`xCnOs>i~t*P^B}m&0G6o^<}cI%Mzo*#k}c4rdMEX#SbEV}gcgy!Q!iSD|Cg2db6!dTB9vHz8~$b+M#@k~ zhl{sr;ulUw;x}n*`DayR-k|&=r2NQF?1E8BB(l+5;K*GXYFby|`k@q=V-5}0-I(?q zd*c$$y1wD&rWTM74I)%=DJWMSfbmzw)VoGuvM?+0vdkGMk4GS2<^Ivq(eN+Ih}Q;3 znUOUg_DvYV9TEYoA3XY;Mg!f85bF4co{--LbX1Zxju(+^Yr6rmja+M!;$o{;H1D7| zE!Z3lBF}mKLl4uRVWQK!Yp;Tgv(px-RUqLg<(aOJuCA18Kg23&3}w}a zdTq)!x${x1fK6Y__Cy41MhBa@Wt|fuqZaOB2dJsG$I_Q65hCBmW9J!f+2E@aG{oO- z)Ei&0nN3`{$AP8N^M4H8?pVZ#)c1xo+&t#=tht3B~%D^QmGh7_334cD}cOX zBffsEllH3CHzRjwXV<*7oY1y8V`Q9~TLONb-4ODI%i=|*OS~)g@zJEca0No+w2Vgw zpbt4IC=l!C$Nl=UcxLu4n+<<@mS6xyb)Y!C5J)uRK7^s|E#X*q`Yx8SeA;qqy^7fX zw7iY}_o%{+k-F8NtJ1eL93=G(Nhth#MvAww>x|isDf8hPGziq9jS89xybV~hgq|+2 zc0V9h>QIfko}OoAcKq2fzJwUzI%`q?;tsFua~K&UaBF1oyQL!9DuJ?&5-sNYu|gmsc4IWCPV zBmmV@*KOUgX6H$JW=!^c)68R{lA#F>9Qq!4us?BS#CUKbR{{Fi9k8SbbGoJvoz|v~ z^o5&&DoB7*kg0sNB8X?dhno;YM;Nbf0s=>gb$w4Qh5kr{$&8Lz{1TyxSXn+Y^J zOs5f|^WaIA!__cYvNyTi)fN3gMa%=odM&7{GvK;Q1S2D%OIlg9297upe=JYmZ zfjGBnA`VpnlD0pFbTc>;dSyJMv}-hsZes@hPznaN*lL2U+{O!s24)PF&!bW{(S zkId2mA-wC;I$JMcs9IZ5SNC>l@(D+98yZywdl9e&Xi0iKzsu+CKs|4$?$-o^$2Nno z2MJ^=&%MnD|FM*~ui@^RI^DlFN<*^*$dZ=7V-+(5J?N7lGp{(4WZBKdcKa}<#l?dTm29$ z`9S9?j60cm>>^7b#rPa@gI~|-cx>@=gm6U{*;8f>d+>yIS*0ICHw;~m;+Dko5q90$ zu7vH{<#0#nT)iN^r5qh|4h;*{msU@)o|}s&&`3%*$~g5^Z}cW z+s9G)#AwQhf48E=iFnjIhc-s1{A@Rll=t@h)B~noUro&Fh9O>N&@A$-*{pyIwKzwi z4bfSK5g5|fsxO(hu$4&->9OGcuZB4K(O#pY*T zb~`TAxGOQN9A4YA3ve3U|4X>nIP*3;T%*P2{P1@)1R+yvQ@0w*1Cn2JK=t1RMYGs+ z(qMT;)5oV{ron%?$aKYN|5;YrO0l{RtjReB*(6w;q^nwo!;rr&FdS8rKz*331}zgg zXVv=n_pn+Hikh@NOhA1q@zv(pSH7ZgEbanfPOL?l1HeT0{5se@u@{jNe4c^O0=9t1 z)8CK?7_aHjh(9h+C$h>@I&83~RFz$XquX!Tf;ufJIaKL?e1P~4vLCVQHkyJ#U#Jzw zlEI4})ErH>Yi5tZ!M)Bq_z_slD#z7M@;ajWOQphv_t~@?V{XScBnbxnh2h@46in@Y zcEDe`Ga-VfyTDM>PvWAY#xHq7OL!+h$a@w+wY+%~Ddmq3T%k|PpI%$YwfPcnH<_ZbSF>Vp=e%?DW;kQn+ltz@#Aw7f!I?RWl(9be;9OPRenGVd8eW$(6*D;IvS3Q7USG$v(c-oNVxpWM#)XmbWXJp5L(K}VN7=te_FKlaY#9Z>wZhE8xb7GSj^P^L<&f!v?;~-O-?r!2ujVqm%31=OXinfV@eeN-~Bg+*3Eg0GD zAUErGN_+J+;@*Lh`C!Vv>wq}Lxg<3nSJe0Qipt2QbI&@Bs%}~)JpmOA86Hzud!c(F z_m*O2`41K!40P%F$A7EF+liJ0xki0AwYC?d&t^5x*iY*j^oqnkYAb6BDUcqwxvBL} zj`ZN{?g8q3-O=F!$A?Lr)T@vzn?k*_w|20+5c-gSHI>q8uMve~n&A}hadoKQV71m3 zMXUF981iP6{PY0uqAKeeus)`05#2Eh0T!&P(hONaj+H0vO1FJ5i{It}!upc1B~KfF zdL%$WJ-nCPA*m4X#^WdRhm}+p8eNuIRTZ>PhCat8*nv(7+lip_KGW+;DXMv)?|%>i zTYkncS)F582dhV8{KP2DipD$cZp~R^)8Tbt=RovK@r8 z+#0@LX!RAa+y^@`gFB(Na(&J#s(pFgjq-AXo{`lJq>xJvRqKEWCZiV$&;!r#I@q=3 zu*YdOm2rpcvQ&egi^39&ic@3{)sO{yA(tnP<;r=GRoxNcr15vXsB~V<4*VR4<%34}ZhEjJz)4btEnde2PekYG}HtxMJ8;PvKO z&N*LnN|6bs zWJx$wt2-(-5p6)(8An>jH#TLYUITZRJ0=O7t>Q+XweIhLVmiDh>UD`QOnNWga)wU9 zKY3eH(+7bc4Akdx6I8-M#mjEvxvvmw%M@=dCk`aT^6w~nx%~3F2k8$IJfKi+)AA7g zHKE+`L54zLg2(A`yOwuns@9+#v!&n@>8uVJjtDOfUn4Z?>WrtX!RMn~7*eYpf5CC$ zG6di+TG{rpaf2^?l?s+W$O8+P1%AkU7?!1%ZvYR9{eaA$3ECC;BRe0rzZ2!%Cc|GW?T< zhw`3bS~)lx5XtU?-lt4i^4SYfyLX~*f*37-*F;bl$jNV->Y;8&&(}F+ozEu8f^V#H zJlE-R*E_;GYH$ApK?K^um>XlpjU+%7Uv?uD~3nOnt!SGly z(pv86@^4CuSeVi4?A9%oc*W?0V_jW8lq+nlho=!}u#Y{Zo$PQAg??6;xKN|+#IJ}Q z@mV>01bg#i)U9zoe|{KXCnCK@^Ftzc_iB_)xkZLs6iBQytsxmU4X?bBrta2YUnLm% zdC)~WVaaJJdQToYCDi46Upvw8ibC@dd?Dg1-b$2@0FiTM<#j%Q_68>m6666n8BY@x zO$MTv@3W>Gc#Ydm7#4QV^NFKSy=Iylz#}Nn$ULazqT!FPUf4J))(rYx9=m(y^s@I) zOOO`8;R$ab!#KRgZ%-_EQvb}r;j1&}?FV>?Z8&aTU|bS3p}A);zTs?1xaFMLF;E&Y z>5gBn3zOwkQ!6~t3#Bw?5SFD0Oae23L6EE-GVqK1+!SxXUSI>m0p5gX5q2!lef`Uo zT#_v=ZS;tqQoIe6O`fpZXgFe!m>?u|5g^CVp;!|gAOmMdgR45fRCF1nC)_V?-pZ7d zYfTuNO4PW#r4Q6%i`~cQmpDAI7LvO)Ll;jAKJ=oKOW|rdIs|eh`~m}1rR$+E13o;v zj36fYqTF}?)Kv{GBv~U#305;kI`N86A)&Q;XKXN^n^*ZJUxaK2cXlq~FOJS=@L)pa z2LO4O*fd;U4bZSXOq2@=sG~Sz1&hJu7!2f;#l%Epo2tOxB_}JPOO-wdjc%WKQxwe7 zHuaIWkPgQm!cZpIjZhZcQH(~;Bk2>!i-w-|P`?l=S7LuxP)00e=tr}+L-N<<(#!lA zb`!e8@W0n2EtNWyEqVJA1xUWR6FPYBdQWbM_62u$u-ulA%JL5ej)}>zu&?h$c5XAx z^@O&((WnnR*5L%F!}{K@j4tf+Y|Us2e;f30toR2oJ6uAx^x9bSPoFA4RamqIf4u0H zme*5H`|3iVaS;#SfCb{e!0XOMh=P9V)Nl3bWu^cfb6RY0nC=2!y*ZR~Of&iJRhsbs z0a34VBnA`;x(_v^*aNa@ZbPFvttMVr`yH35Sp@!ggateoZwN z%;}&kUJ3d~osqI{o@=l9Nugl^46fPy#$I3;ILiGHZZ*oQiwS6Xh|#d;!MG3OQT7Dg zLZ6hE@}5+1e6U*t<3a(jz>*XEgE>o6|N`W3MP9AsaExOO!`1#7WalG>9A0aj)2ae5kn)-Svg9e z^-&bTlBW9$D7Z72hU*$1J#p-<6mLK_#KZWA*sqr&f=G~jGM*>e`&}kwft576`K_W^ zmUviCu~j9IZ~1RbHaz)V5rtO?DK$^ zDL*m&d65d|OI_0$O%jcsoSrS|$iMy-@T>V=Qf~`Bn=+gQuf&_1DJN+!YIjca51?-v z=>~Lz!AZpyPd}90-llwYXwnDI+9*xu*#%otP`-@CXV2q0BJ0<9r*O6n8|Gm4EojXW znbEJe!*X+GrVGmn9i>a`>J~ep01-xw>1w8XGza_`ZY*B#V(@o30}#FC?j8pVScl(2 z4{q$>732b!kl9}Bq9^-R6+hMgbprH{W>TL< zb1#Y+F$vqvyqS-RH>03C`^_6ae#JL`riKejlyA+C_*ylN%*G&p_dp;t-f!XBoAeW!iMG*ZP(*-6}RLRChP4R)(V6a)mJn|qhM1Gy6(i&$!dFV2?0WP zkLe_7vJ46!FpNhOp1!Nh`Fi3p95my5+Llm&69j8WXIlktBfCqTiW=^{jrL9o_vt%m zd%Nj^z{Hbrf+K^4PCs8tYY(pzfq;-t{5K1u{=Wqb9D36KZDFAPS83e;8^gf<7lyGR z|L=chkb!pDNG5Uo&z`vU8e(gvbHcm|2fxJJ6P?QDU!kbqLiTM$j!?#YgSq?kW5i7< zj+0g%ZJX=5m540Ru;8!|un-7#ebe7UJh<1@Q>^*6DlVm9B>vZ7)c9*>Yeb1gzAO@) z7D%F@d_g(r9zD;&gJa08#990TW0n09@pa6ociC4X%5tO^9S#UpobG|liU9+er4ony z_LIx?n~08qfP3gJ+03AJ@h4dLq`NkJK=EA(m29lKr*XOw!D^%d!dFHai1wN+KK}r^ zYxRaRyOg)=Ujif=B2cg(2NN+PDiX7&L|&;6w-|Lx^{@@xoeDt&&_-_QiM@g<@dM&D zl^b!?8CzOuOWN8-ftUn;fuI4l1Zr=pY{=eWrzMKR34t`&wf#Y|@oMhpW`dr;P)*mx zD2`ZzcY1gjqvCd~ZpHB8bNQ*o_AH|0kBId z@&%9FUBwNZ^SCGCX+ER}>o&###80p4!9aF?7#1}k9d=n~m}R2k{Ya6c-t9ZI*3VE{%hORzRyxy@e3d0PL|d;e=RoyZk*i6I5V+!`4{SfF z)&^@jxeA`tsG83*qWxO7^ho zeXEov!y0AWz332qLuM6iy~6NyU(gFRtc^z+y&el0UP8`m+Xe7T|JK#IQ}Nr?j-ZQL z7x~UI4R7}`FsH@R)?nhFs?&kC3_eelVW20tZ94XBm20`bz%31~@&ncsAR8r4V?8E@ z!vW0sx}F}TJ(@?5jS8aJOPmUA|7y-VLF-^eas=C)DWdS!jRP9|<(C_iVi;!}shMlS z>K@XL-h+Y2=)LSx;+Mk|#Uz0djv(*Au(oDIpTh6L=0wV{(l$HnmL%@lY6q9oEiB~v zzm4~$j>4yuy|wRaRx#zPvVBWd`T17&oFTU(L-y*%d+Tj2pJgzYI*D=j@z{M<%y>Dx z^fI9KWll5Di{1Bn0SWn)vpaHfJNO!f4rMkr-V!=_?+Bn;5#YjC`3Pq=)U=FuQewg3 zte0IxV%$JRpk|$S(S+Zb(ybzsaQ`l=E2x-)FE06l?iAR)v?%{ZD}U)+n41Gr;USx5 z-o__ql4j4;(F$I0)G2vYH@DoBIwdJ^L|?jW)0T4PmejvoNZx4&Eb(=&Y(r#2ZsfpX zhf{5yT@i?9RMJKg4XV%OY;k!0)u5cDwV8(NZ8SQZAEC!gvKAc9K9+g{gp!iq-T#x6 zdAknyKp1W$Ifl%F;TMNjT#m3K)wO^VEj)}(n?PQ9#Nc*k28W|x^wp-nyv)j8s z#2Z79RBywwC~w5@p1-^C3UWSZO95=1aet+xM)9PgUB^MBBUSk8^RFC@{S%}(7v3>@ zXT?iK7TOD6=)sdS!HkB4EV0~^04OHYj$fW}Ld-D57y*YO<$5LTa~>wl1?3e#IS8(6 z)l63W2if$9uo>t9)Bl68d+f~w;2tzy+ivgLwr#spTX${Swr$(C?RM%;ZClgX=gICS z|LmLn2q!sjuAExVfZMq+Gs&LD?T{Vf#`}2q|XC)}739|`Gq|_3w^+t+24%v>e z=k$bL-Qqe1lQA}#(iE7I?z>|dsdA>mTWB{Q*8-yk9K zj+q)?DuCHHL{r-tn(l^qZn}{cOtj#exPuO=$ua#*L--;3K@m3RHKvsfC+27ibg=4) zeI>!GT{Kh^L=7lgC~3I82kq7=zHDqrK> z**^Q~7|OR)H;gH6qd~(bXFpj_24J_KOx1?;PD_>B4XAjezlo^S`zomtQFFZCX5`xe z$zb(_N8#}qIjqb|f^6u14Bp_cNL`B)AaF%=5onAo8d=yW5MV}oiSPr=mwh8AtQ3qZPl4X-{r=8Dpk6egu~@Snk2I zgRqVBge5G0n<3eidYWVwwyQ%n^<`$hpeM*8fe&qs;HG(D^EB_kX7cc*(=2fz{CJW_ zI10vLF*8Pa}Z(bNOxM~}vhL6=VUIp>Hw-1)5Hib>E5PC1$b%B#lj?<_x#NsPFTmjve# z*W4b*n?)E%!ejpyF}ZWPvcKZz#;t!L?Ejig^hahK$upITzz-2UaEZ!&Y(dd>!GpU~ z)MGoAw}TR51=$?fWDZLh_J7~j1=Nwrsm@Xq(jwgt+i-RhUpNx;x8b8yyq1!36wo+H zsO5v?l(ceo7W_^hard`p&Lb?C3$7M9n6+osAm>X1iN%GYNfw-)J!B=1*UuylC#w<| zbBx3}r~E9ppK0;dB*B{|ox1);p%T%FvDp9WN_xiX_I$GS{(a7#O=wo9RTYC|bWw;I z?(-ra)HUTEcKUr#wooekwZci5yImh z{tbcS$B8vP>!926K!GP53GGP3Q>bgr$|%q)6~vbj7=03isquz`9dVB|1pN<8V#gh9 z1T&ySlAZZ8bk(aWj86s{f(4Js%J&BO&X_Lo?wIzB8Y}W67h8cH4mr@LKG|hJo7tkH zzb32bC>sY;sZ!3TG_-?Rt)&M8)`>~bVBXytnj4O7!S5~d1eM*`PnnvV-(x+ps*-0( zo6c3R+%<+O<9U%=o}`e+iEUZHQ}}YSe&B9Uinv@@Vx+d5a>UduzRxId+;3k+x&gK4 zz!ZP3Qx!A40p^n-BBDAR44OtNc)xg{{qQ-V7_N!Uoute!zI>y z=xn+2t005!f@+a+Uh362gHv{s?4rX-tOwUDm*)cgwOLeXN*P@w-F-BMcq@Xj>$eUU zV_b9ETlyWZRn-Xw^bx_JlWF@R;OqI^n;l021A38D+ym<0n~Asx#+S*Q$Hj9Z<*q1? z0AYSCXJ_#anI*FVkk9T3Ec=}mozyoI6c+dlznx@IA@Cs)v==rN{c$31i zk?*e>(f-o3;}XhbmNP^ji^aILk2PkN_L|E+ZHsqYZ$N}8LQ$Q=1F#3_Dm9$SWd!HA zOzjiWGowTHHS|-N&xe9rmlQGtzBG~;4CLD$TyPLLvblF}`VPdDK;_mtH(lrnIk5HO|DHr#T#Y+-E@m+r%0jjLc^6*F zpkG?@M>O$Fk1V{62K6=gCF;!CMtWIe^*qmD`qYL-^Bf_^p&7Q%HV|gCrf5WB3mV_5 zNGY771_O$@FeLxQ+Thlbkj3m1f0?7%A~j~=)4HQ5r8W|!(P)4m#`8-WS%agv@+!5{ zs$ou4;Fm-kKdtZz4@FJxU__k-Y7ip6h(=s~XsWX;J}R(>$Jzi9a^2rHZr^}NoD-cv z&!_UrmN6{!uOO@aW)ug*Es1C-K5emc#N_@FV?D}zv*akD$9+Tw&6Nv+8lyRnapjL? z&E!wBN9$Rn2$AnFX;2mS#| z;Wm>rz8fh$E)!h%Lti!RY%H}PcUoHYU(L14VhD)8=(h9l7Jx|?4PhicxC*I0o8NrP zFuI#DDaIUJ9%Z=M|6t1O$p9rxa>Of22!VwX%>98x<^irzP>_b8uuMHL5#{kMK|M{8 zD61vx>EBQY0((+Oq6zeA=8(dkwrsKHcvGpQ$-fnOx*1_h{%sapYxB74Oe3hSS8L3~ zBQ8IH{c35K`&VvXM*mZlk^){eUc%!W(RB#2cY?dnN zoN>PU#$R{CWvTo}V$Xvtdq0ZGjX%+));x%W|IxC~#rz4fnF{U9V|Sn6tQ&SQHg|n`@puJdV*AkR zZfcCln>KS!=*^3yt%w7w4S{2ZrPf*`#)I&jE?_r5PLS<$*Qo0EuxEwIW2Y-JU><)9e~sBNYw0rpg8f_A7`AP(@Hvd3Sgw zh4Q#rbf<3jg6vwnb4ElaU7&QHiownY2j45_KK%hDQs7JL;w6cF=v2=E? zLS=U>>FCNQQ#s{iv=FEtNCEwv;LxcLO^%iVKN*{6q%fZ^$4TA3Qsxwp@{G^D@kKiT z$$&dznV{Gc`FwGbECL`zW(rbK>~3YzVytuf-XLS54;y^NjEbh<`0(T@ImBmYCsn#h z^)65v+mMyfwT(n;A6Be!P&zZ$e>xbU)X@O;&dPIio0t4;RxXioewaP(i1P1fnt7xv zNZHSrgdU4eTi!;Xyys7>7PjJG=jq=a*KsYr$Jg2*o^`n1Fk~6^mt1Z$LvFeL>q;sG zSDbcHsYds5W6#e>5)z;5dgfwniQ`guKSOTR#Z@*UUR6D)7=XWe=5ZrS_n;A~cel_k zfNvxTrfFNFECH+NYB|mCW~iW2dvag7_eIhllC*tNDofPBL|vnYIBCpq_m}nRI*7h* z8$$tpY)`O+A=1gxbr(v(q>JE%n3 zop#sO?Ft}CF1%g8=|wBP-H-wIR6B;kU|@;e{a}f2O)lO3?*IXzBRMD%iBJ6*J-qHQ zyKX39TLLH^JfFJJk>X2I))OR&M3go#522hGQ$xxC?)@-3s1gQDUL3N zuX2;6g^|ZtBdBU#*Wvvg&vw#x9~AkvyNrx+6wF5uqxzq@gq0emQ+D4l0v9x<@$bZN}!o*)s4OmzV99MD7nTS({VnKFEbuQ1=J?Px?ZX z<-Ilxg}$r%uaw0r*F`jfUQvvSf?}&Njxp~}a*!em@^g$MMclvzsB&Tr5qPjy73afp z(QNjF_3DPMp=|q!<$UJ<4EjaxsT5ZwwZ-z2NmB%D^KrqxW&c{F`x=rLtSgCtdutM1 z8Y>Pwq|bLNwH9M>Kl&9^e^P;#_eL6PTP~hgGA85Lx5@3LYCVuS%F$wz0h^N=ylRlf z?>auFnPFD=E=Z6`2!+|cISQ_xAzl-P+bdd}l==NZL$?Ux|IbOafAqXvw&uE|w z%?cIOCOR-b3S?5$GE&>GYXpBD6X`0Cm2>NGTqPa;OYOS12s3n;e70a?rZ^|)^vuT! zb;dg66$iNUCZ$Z)zEgTmxzCY8p0be5HA!!ECpb47if~S!>ePJFP>OICq|jrVCVv+b zgYBR>IzZDnWwU8ly@$gYClu8od^4mRkl|!!agbB*xMW%w+(w0%8trZYBwgCbQLbl) z$5-g3ja|0y_i?}cHV#pc`kJF~lAbVP*jUrKBeEs)K{S0ExR;loRK!+(qz<&Mr(aK{ z8{I7@blMGx!)s>t$hlR)wQe{f>C~L-GMiwUz0@j6T(tYqe0ZFjR8+wKSRrb3)It`G zi-qQ9PizFRr$}pt@%~>EDZ1E%rnfB=4ie^t{zqGp~bN z|H$;e3t-^$B{o)WljfG&!UY=8UE4WU&mX7_Z2m#>01G@4qThN6tFi9Ywku@Ky&Q zX!sTM+bORM_{_8Zv|DCWk%XS}cDo*Yu5Il!KFkkas#IJif{=GPS)D)FX6X&Mz>#mT z2^=(RIA1~)nxh!jMFBgdEcbic*E-SzwQ~O@ZBQGGT;7N|oF+}|!|`s0rW)n3zS@o? z-9MJ2_*k=-YoPH?hV|94;A0C&)vCvF$_?jaBD`D6v&dSFu;)IGgHdC)EqhcM{&MJ9 z8KTjb!g_64k!kbwklj0o-)P(>5(1I3-W43Z5(!qc<$T*+CUQ_XM!0nGfbC*Gt@@76r)uV^HyTm?U~lXW@xW zvrkV(^6WS%h}GT7k0@xz_Rqo{5#(~_ZI$2bM~t=^pK@EJLl8wz^sVZKgl!V_JX#|; zKzR*KceVBoJz|sJq4J>-54j$ggQ^iC-Y=BgFkW~91RYTqRay4UAYG~m2- zO@pL)7b#<=X-!Q`^>^)^52ne2B)Qd_$_-9)>EtZzS0ri8d-IF%c!9v%=(vEDf@ci3 zoQ@a(VHeZ5a~m{+b&hz}CsLxeZyid-|JNX}rJGTZ8XlGRX?rYUmQ62lF!N8i;CVag zu$>mCGQm}F)D9SWYrM0s*8V1qDh;%r6LHI;ul;qgub>}-K=M8Upe#xl3BRitQmM%KWuPz~cPKHwY`!|p1`Ux=e14;Q- zy6dLNld6q8NlgH1Ca9zf*g73GV%Xr2xD@V!*-&!i45Ka+wT<8(xBdXeeFARwRX7Z!v)yat@&La zj$e`^N)@ghcjWP8`EY{7sd+Aio0E`}C9W77xIZS1Hc$1+KPZ%OgY;CD)56_%&=wi*NC9e#!DyfFX!^z zegDhh!9J1u)|`z}_~aX@5vNss;c$$vH0~BVSp1KD0#xiv&^7gJ;TuF62OBr}ZG2w6gf?(I`PAlX7XO22*I+FAl9|bk?mDeO^Za zYy+Z_#W{anHYmzbh?1Q94e!+r_&;DkAAE)^ys?5JdAu5qmCCqhO2V!$aGcy-?6X*0 zY)~!-eVes>Yr?!}5S0(A>BAf=JkNEOW*2Data@=7%Xt>bH(fvER}c#0-lZx#%MI(*E zrBQnu9eYt`kh!iX;qk+$lO6^725X4WSh?eiu4Z1JQR?gfwXxtUTqi$Nc<2PkfuM?G zC?|1lC;zRhr_uhByQJ-*6CiHR@B11XUC+uPBcw62EJzcOSmtqUURiE@=-h%~IE?&e z>?*Fr`-1>|)pIJ9V&?2dnx0qt$=@dCQoT4Hhb*4FNir_%8>W%M0YG3J_L}h&i*m~0 z9X#FJndePD&)(Nw|jxDl2=QAo6&;?qdOy4v<4wqqB+;?Mg z^hmgH%?it$35{`aHX~^1xCWv!xB|E9j5$O2gzcTm7x zyf5GEu?J1g{jREt^{5@H3qa5lmV5!1Y5ro&QO zY&l>MB0Sujco-QRCMFy^j6$5!F1#IMCVgcA0nsi9p>ZfR>N1dc;eC%wZwE)HF(2$LO|GI6r- z#(lU`&%U!<8pLqK9e8T6HzH`7|6j+1^uHaGvV*Ppf4>0z|2-4xe?61U|MX0V z|Mg6=|Hm_JgH#bg;1fvZ7V4$s`9km3Yw`lO-v!qv|9Wv8?#@S0Y)ZQ)$7ts%cKvmy zm5s%NgZ+kqhE>tljjWt*!Fg^3^tyLd^6h*)ZrW)?~i2-ulGxOcbp?6SF-*^1`d6(L9#`SSXi)Y^za7LtnA-z z0gMtU`FUR*P!R@*1cyIb!$&2i;=NJ45KTEHTea(u$0nXN-iQb%+xN%&95-lu6+vX3 zBXxn;(>ZVG;BkK_alZ8sz!E#_Wrp}*8LT=8WEDL~#e7989teCPZ(sS?>Sf#*3X?QQ(Wx_m?q;k?5FN#FgDLYysv`v2>5Zh zSvWyA(Ho*rll6s|yD+L(OK5mfiQuLFMWy9&(K-cU50_Q7A2*tx@uY=WRhKXskV6sZ zz;h1pIxiV8GWV#{&(4cDga3f($9bv^X2rc*o}kP5oMUz|`^(FJX9w+Rhvp1x zfnfmhN@W}~tVrP(_$mY=W)7%u4o-pYw<*$Mf4YKpBiub>Vk(*E)d`^snyH8< zvoGYsdv-O<5o+olPar)hx%s}K%3Jth$wL8o)%mGx=j4tQo>Vxq3O=9{@ocf121fp; zapZ%&M{rs8r*?@JhZ}z}xg&Gy#?|zE#3!$CdOQf?@pG!?Xo1DrCO)tFUVIAQqspVc ze`Cak2`a@0`7IU)`2k=tG1|;*)#_&AY@j-+6XZhrbD${9s^pnmQ?ZNT*QkSQdha(b z5Hpqdnu996JOqYv^W>WvlwlU@><=wmYK9Ywq))wGGTGu`*&2GTew0{7BUXdaZQ`wd zN!8W4a#*B_F83JVbDiHB(9!mgcO&>v_3-$oQzvnzGPZJw5Mr+&=9k(4%Wky1v*3_$G*6_V`fyA+`3U2Utz0(+Yg^&-B(A zEOhNL^LmJ%z?#XfRPnb^auEws%8ORr`#sUv@{H^pp9aie09`o7n=6{h2#|2D7*_9l z^Bj zx)4E%OhGMe+%-OU$W9NiTpL4TLheaGYUEx^9H&G8JmK=X^WcNfa^&qT75H6|$0Z$Q z_)aj2wp}TFzG2_TmQIWh68!v=`1rSBA6j)j4y{TbgA1)xX6}iPIWxXF4g^eVq&|xntTF|uyvROFR{W#d`ZOjt zt0;$1#>fH3qF(4B!2&WAs2+2cZIDn$XEG#qTO74=$6N4U1qb85Tqv=4;yY_5Mz&Ie z{MmhNb85PxnH+m$V8=*$nKw&ik*-^rjF>1a+*@x)6Xr<9&~1lTsSSiHC0js3ms#Dt zN3%6R^x+PwelL#R8!v`!c-P1k@T|Q^S~$DDhkBil) z@IRP%>)AtBN<0%M&A!1WL`IU(svk7mhG$u0d{5IT*$z%p{fedQIN7?mtP+bB4kV6C zehtl<4EEv*j1+57vbu_rJ)UoHytq}st$7{iR=86v3d=(q?Zba!zd$}dpHfz1{A3-4 z*nAjRfyUK)D`po9CW(_Ft*#aa)Svs>7)}mDlCpPES>te>fcYUM!?P#NG4f(!Wg|C{ zd)<;>7M!m>SaRPBROdz3Q9;9wXUDjbV2WPj8XQh$19jSdpBBZaByC9P+rMF{9bgJ) zK2k~Ae*wnDW3h)Vh$Tesf`p>CGbnhNOVZjm+q-cVaC+q)UTtWzxmTcGQmG**yG-lI|2Mc7Hn@>EG zKgs@J{KIc418AZ7rN<)}qZx$ETKX3siXj*pmZ-dXH`7^Dj>CFz3{o19dPJGNB$rF%L;HNN!>lfr z$m9QWeb#^iNwa$*reD#;D(J0->%934j+5^K+O5Yc-V-Q02=+ir5guh1h4f1&q*ZZt z43R_z*(={~^on*2t3HxovKNH>+KN$azg0o@R?NFOkKt#&Y} z^3^6HZwS_&PJty}EGi7`S1gKP*-Q@9hk^xHY-z!4I3WH9p$gUz3Wj9>D)nNTcyVaC zcg`OXhH2O}bgOSAe6h+d;6O4N`IoX}ZbYB=lnE1Uw9A&%oXz$ZlK9IIKAjZkwPXIE zr($q39G62cxOzFI+`UOp8`4-|vz&o>+I3TZ;;Ae#6yfpU{KSXqx&PxS{1h(pcGCIh zJRu^1sbWw*+4)Nt0h!-4BIvwih-E!r;#(+NdH#gO^myHtGmNM zn`lq#0dZnJ%8{BY+WE+Ta_~h8j-4CL?Biz(8UHZmmPg#iW5z_af=-NeKu+SOtOhrNw(5Sk|~c_Fx6BVO((iwyNe6dYDKStJXBsH zeq#^%OXY*3rwpCd93w5pD5VI6v^ulbJ*Kg4%$yta#)fe ztT{C4caKKH0=@;Kf)9B%&|XELwhQ9^X=UxPP@Rcke$y{20s$E zCNc*VLgDaZM222kpgDfjWs;bJ2N&dQgSrTE=(EAl;}DH)T%e6?_9x=o#S>Ykj=~_8 z4LFqenN*3N`89<9POfG%#*~sm4{mo|FdzF@Y^AQZCK&Mki|oVD2>31eH+K$ud(Hlm zK$JcdlhtckTuP7w1(zkCRhfPdpu#03D#*)-eitCBvh!4)i1jqK0xx5#FN>1KE8L<}5i&92Neww96?}sr==HIizX!3Nw7{@EyU~6L zSW$~Jp5z>w@-^WNK{6|G2=nB~%0&JHN)fc0%*NO7N82%Dea2JaOKbtQvp}ie3JMcO zG|ofyOJ)8tIc?@QgzJKmrl8-j0oG*QXK=%Y{K`x9C%_mEX-Udh(6G#Uv%#LeA}YI> zy7p}8w(xbI(5xo1&Z81QKpwfpld)J`C}KRDVk7>$yu$89o{dpTks7K zqL{<+d|x)&8{$J(4Z)Q2UCt{Hp!?|spxC9}=z>Gz)LHj1B=kat2^&ySgxr zZJ6LJ9C!+(O|a?&&6rh0hU61&B^OJM#C-An&4vkVQ_fdfA?`Z1Pow$#%h6{fErjhI z`Jt&PSBUqUPQJ5;JWK=*JVW6chZgM&5EW-wsSIh8G3Z9j{DqPRN0l-=n%_%IR*oE-evJUYt4v_D9hrT=MTtOVfU3s9E7bHMR?v37P{=JJr6lDc@Eb8K>&=Hr_Z&(faYuo8lm5T7!d!Q0yrxVo7s{~n?M1@t=|6wCM$L-utV64fqQ$#mx@)DNw(^{2}km8%CkwXfjXU@P8H8&i3 zd72lM!A@l;dZOnW)W|ACuC_Q=LgenBtBk-Eym=lb#7j6PRb1$_21_~FIFyw$W)J4H zcnw|6>zu?<6QBwS=N^G1daz3ee<+IA5`d>3deVsUJU+t^7(onTBHhazXs!A@vsswA z&~sBtik^coT+6jbz3-gvZ%a#*2`t9vaMd~~nf-up|D^(gNhIErTDKA13Ok1S z1hS(_1)|!y~?fUB4uUrV!=V#QJxLwm%87bXzQTMqTstOOK;S&L!l_0`V zh&+`55Z8MqDhgw@1JL!Bd|PO0{p*Jg==~tBd$=VIzB%cI(0d*!hzQbYG^ML_x-s#P za%>@!D+>fmU^(iz!}{fyh?&!H5Nch_)T%pep1boR>gqXrW}k@tp~*UJhN&Xi62rm& zCrk>0i)9SAgx0vIr!%K6c~)=xy8XvGj5 zJe%bb96&Vl6I3p=7?4`nmzcDug5JgFn9yGQKAr~l5Q8G}P?|t8Cl=v{Ja#^(gXBQB zhI3Db5IIDQ*Xu9)-Yvj7?Bv@Gmb&x?xiU4}+E%ViH)s?o z^N_~u!)9$UM6l-XPOYqE+z4_N(ju)?zq1XXRz$EME{|m7D?XQV(lDE+XE(5qkt^uV zcAp>?=}m&m`3j2RCMvqsP^$X8W>Tt@i}L9;TZE1vh8mgb%=AXAFkvBEy!@{ALd~Ye zaow6<;PU>?V(aYoN=2T3Z;JR?UZA?ei)`)stUcvHI)G}XIXnTo|A^%Q^&d*hwkyx< z9tkcT&m@&Sfh=d=lVy1%$xM2|Z)fBrj&0DkeF+i6VPDBsF#a&=LJTl>zI=ver-;Z9|pB$=>6KyKnO}=&CI8=41_bVp8 z>0_k!hDyS~rvU%mfx14cb*%aLTK`fmeK{23NHk~ zW#mSBe~mdyLe1-F(-P#n3%N`{iWMp}_fRw|;Bg%oe-&h`E4WGtv3fwavnEo3R}h(0 zk-^HIW8MlosJ)RFGJ4YI_M8d#$&Po^S4>5Ph z)kRuEbsu=knv0e@9$3qS`uQhI`h?HN7b)2N8x)_QVMjgT3bnJ)c-!{6 zA$^_*$LYe=pzkedLIRs)!~_7Gv(EEcq=2=(99d}EC03XebCX7yDKsg9|F=J>O}){L z35VaRx3*?Oq8r*H3@}C36Lm)$9LELE0c*l4=;qdlLl+n=7PFOr8O3IVT~w=uwP#*n zczg8h5{dAf&PvZnodCw29N;+^VhS-$;P5vNRRIgq2E9O)< zB&t3TAQb>EKP&;<@h3G(RkP={=hpto7hRd~L#pnVPbrRZa@p1UWw~c%qO5^_;zQ-M zwOt&&=U-Mqq!CD;UScXyamw%$Oy-o}p7UzJ-R+vPKhM6Ih%xU`&682DvBVlFfAU*s zyr5WQ#y?m;?4cQFPF)_vTPDRi0Nf&t0nX>8IZcf7rY6ndec4xZo~$By-6WyweqMdq z(y0N{U;rH(KBRH@kjt|utI87gc9^leYb|XqE_G`|$1(1EE-<6Zn$Z>uY%t-*3{tvQ z?PRR&UYQhmlXu?S((0tK4X_n)lVBJYHC9tonSdA52QAh9{&+Jxa?9+dn}GQ5HMOP< zYYrbdRehoQ@>&d)8HlDwBzc6>^(4PS$dvkPUvg#WL588W7wC&~$?B27rlpC(^ESHi z2RCWSK}`El3wFq$8zZ|x{Bf{VDXL&(GMOt(?X4mb{O88`>K3ieYd)z+Q>19cG)TVG z#UOJ|rD!)kr*K-qHomT%Z+6riW<7?_Rae$`!Pa9$*i46HqMEAB>3CFK)QX znPOQsH3-{>9EFtAt~AZ2_aKllwXqv^v@dtuRyk05@5ogo#^5P2?MrL<)uE`KJyxS_ zTNm$nZs3oF3|5hLpN~dh_l0zQxT}Is6kuimz7Jarw)spzp55l~` zt805M^jzL3tc6t6i`TnCh?>YF)Oc)Kwy_8G2U4c+Hxx#N+!)3=ldJfJx4%L^s%?75 zVvy4r$IAtwuUx)JDpYoe?S+~fZLS7#tegnz$8ma+SQW$y1*^olzyKTzl4!e>fN$d+ zn4KHyV$aeR4ZFL29-gOsGMZt{!E{LJlodCA5TWq(o28WPpgzgla4pdU9rz<5S+VA` z%BU1G%~&7{F7#k9T%Bc>aRn*}IbknHaRUPJVvvS|V%ht?&#>aufisB|ho1etpu)L5 zKd~yQ5gP8Z*l!wLx@K?OUvFg~DLWNXDl3Dm=Q`z|JkZ2bJo2qs`dx#TNOj^r;B|G1 zrsg3YQb833M>wqTw7=#gUX(iQm76*8MtLwp~g85+u<&Vz0(4-HS5F&)-y!c&QIJ0Ub?tkUDiCgFpo>&nruA_iUA;s2ZBRJZpZQKz?&A5X(x9spdSk0EhQYo$Y`GuM2 zb8~OVKFfBc*SfLMb-&~m%Y4ae&I#TrezrZr_Oe6Vc*4T!$3in&Zd<*)k|nQ8*x9@( z<4E5?2=0eX72Q$uWeFm11CZtwGF+&L83%Em#dSt}UpZrSQ3zb6;X;rO0}=1CF~J+M z#KmJMH@yL}8VXh!W{QFPbLTsW*Lper+3D2`qGnJk3}1(q^~Y$mQfO{o8$b{Ox(l=d z;~^_07UX@0delExpZ5<+akw$#k4$KRKVrXTY=*F=0aQy6 z)Vi&j)gcqX`i#Y>&;P`^vx}|9p3Uh7m$K;f3NnB&@;d z+RZLfZU>*1;5d4M5NQ3QNxw`l5_X4xkZ2f%3F#wyYr!2G^`bXG%V<^+_JF017R&qf z7AA+#q>Gw@E1kqwAl~N93&>%%j2Xf~M@)%Thj?R){&s7_*!1CQMg7kjG49cTX4}$` zdAH;_2M@gz`2Ml?0cJcu^x;QsL>ywwZ*o=;e@v^)b6c^nNE2z@K zeD(X=Fd8p6LA>A*gu5hwXbL9L#ZuZybItCx|JcmqQ8GeD-Q^FIhU0<|Cho_>SyT3r zv<{wgWt1}zt^Gte9Dn)qq%U+W?+LFNHzq}00^f$ zMBIF?j^Y#eu`z8nUag zWzb@8C~F4n7RlZk6VVO$3|scjfY|`5@I(5Fb&D^I?3Z<`eml8OUVLGnsR$h*bn?+Y zkizFFcFflOsNZ(&!atK#qWWt?GAU(XbC#!}zToTKOhthfKL@k>p{e@rHfu;caS!SV zQ}vq_nLO=v6{#NDPp^JTk=uZys2%buDt|IlQTnjq4P6kMW&PNw{2}LSzH6Qe6|a|Q z3kP>xO}x&;VH^RC3iPKw#Lta*z#04UYE89}*`!zv&vZF@f!g^uz7%Ip#Az-}95?@a zOJlJY2=4=pa`a?_75$%?#C5K%?)gSbuzOab>di1XRHF9}6Q=o&eqoWVpXTzmHb?45 zaxmLbwo>09%|gkn7;5b6N{on~;kc=xUl&h+wAkzlr`w1^6yFr=KX$`uA>~clBUJp6 zpG+9c`e395(83#}?bkXFTK<{wG6jv8Z)g<)gURo`N9@XiCTB z5%{ng#||hj_@j8kc_I;mJ;RBsM#`W4b6aY@Tcgh*dZk|tE;HsRg%4JErAsEK6JF;L zcGsKhC)u`p=iB9MxM7Qs+K3_74m8{(d`7=sx;S_NuzKuwt6-ntn$QkI5^-<#!~zx) z6*C+`xiUHAyy<4kKA=@DzfnSZA|f~VB;3THs|qpBf&!x%=w)IV_S+p>s@DGLfj|J0 zAgk;KD(8WTN;x9g#^U*Fb|0dyHH4sX9;9)|ymDy+F3|)>qHi-hg%1o8v>!;fG>m@D z-2yVOS5HM6ZSvf<@~1FivHc;%xKlJuxoVvM2O^^^ z=A`3I^S>xN%h)=aY+dhd*k)#knVFfHnVBhO=9rn8nVG!}am>ujF*}BsF?O8$eKQ)J zIdhNh(XH90Q?IUm7v6!fd4+8ahC7+ z5@{TD$XF>`_*qx`O1}8@z3E}l>q(2`JWK)j2DDc^Jgv)Z%^fvTyjF*Ph>c`rUW44B z4`*#w7rrjhYNNIvDB3NAP@0K6jDGMX$i~lS_*AHN>Oeq);r-k}POI5U>kSdEIoe(T zy%U?bjbKP4Ao6hZGnxsRJ{SJ)!nEARoS>al8Yq^vQfvHdR6!gR!EmHjbUi*jrlDwjb!Gl6tl)?wuacFN_SOrs70Uqxi6h zQOfh5vQ)iw-g!tw^x}!mt1#DucSu`E%I;wLAzPh#?ha&X;8x{x$2j>L!@Z0J~BEw6~gGjZ^6;D)Y?x?}H!O!36S2d0d+cf&Dy^gCH z4q_jIeRB)Lh@C^LNguJjsnAOu)AIIX$>HaM^W>I;3c?fHIqt2}>x9mJtXyZ4vL3=s z+J`1)b0c0|(AHB6_qQ}KV$zp8UH!9cKKn@LN2!Q1l#_$?k_->6O{ zU%aVmUeae#>DoHV=_`Z0O^K#>;BPZ5h^7xFObh28T{)EemJ?vE z$h0Z#D!?j*sCt3s?y9qt}a`x}>LIlJ#mxcuFeH$$D@Q{evAw7#+24%Vgh{ zg;XNozAtBgCQC88eQtnnJ$=Dh>@3A5@|8Mv{_vJ`+|vd7dn3Ah9@kKEu84HBrvTwX zuD8@Z-j>yepJiP0QTTWo{;(OB+H7wn9GCIVBI#H&o)3aLrq2WW#3wG~c788%^BeZzJR4+n_DzmxxD!%}tUvJi4>iW4 z$xhLU3jT|lH6MCU;wI{B>vxKD4*}7RncK^q%R85YqtpPGT*O!k6nXgr-DJ$}MnydW zC=*Sbc@$`;E$0<`b<=AtuG4(X7hY}k6y;8y#>BS0HP*Nzw0XV0GeS}wK>8{UlhlO} zON|pW!p%>!?jrX3xI8VlTyxXJJ?4&$gu$o1D}#&`$?yU=TFBv+b0>HCm-e>!zgux<)z$Z%(&!DmvuGy)dd(Mrma zJtEI`gSy&jBh{d!i}IQi(E9tQ(-iP>mANqNQa0z)#M*FFGlbGIw#nm*r!7NEdQ#f- z8AQ;R#o*~2eNWx76gBem1v_R_lKXW^q)54`qwYbSn+EWK{~0Rod7q2qeKsY*d}R|! zVmbQQu@T2{&&+qN-L9`#1lnJAQZu31HQl)3p}l33D3Pgt zmqknD!MJ}oFkLw^k?yb=mT*!-uRX$Wh#zOA#0}d=S?1F=9An~bl{sMID=9i2S(XFB zB&)$ck+0u0aHp)>vI64yA>J?9|74OaQBMx)CTv*xXN>+z@cZA2}$@ibeTd@avKwV-=S{XqFm2wLko^Y3O zZ7-;lBhQrDb5)fUsdTu_SwKceL-rVl#cx9?^EJOp5lyYvFw&2idIx;*#&f{5l3^Of z&7d3#!yhF@!NE-Zq@>V*1tfMqO(V<_N&7=;muQH?`}8pl6&(RZ|K7+RX&had$!P3; z<~ifz-NP}@{rj$zaYSXnLBhZv4G+y1Q9;j~wS{hJDMDl|k!6hk3HKguWN{Z=Y@V}r zzRyT0^#Q+-qmdAgY1awk3p3(A)U)8Y$a<1W%{Y{c{yMgLJ!?!inN|=s0^)VOUC^ z4Vl27s6vG?1@!ao2@wfT(8(nC5`#0pNUb zBtq>LM%Uma{=~mIL=^OtR92#UOhYUVHKC;5joWyuilNOKV$1Ay4d%>*cJI`&be~ z&1foO?b%O#fVDO;q!%R;Oe|T2(LHzAM9XuUExtpG$>>$r3BHDGC&z;~FXP8GJRo7h zajS+d^0&g?@K=GcAj1Q=04n}{BcIzi_+lhg`iQ}hNjY@(vY8Q7&$VKtFaeV zXtzP5qi}=j9_U{Jn8zBhVnT*U2+NY)p*^)KNLcbJ>B!m#PmUPv5^^; zJMx=YW|nqhxG{F<@h^TIR9hB?VdA)YpN81kXo{Gp%=wE2OFNvy|;&f$|q1iXkN9nv5kU-gNisRXc1t*LQ{=Z2PQ>6rh zsI_vFPGYbc1dyA@ z@A3~Jq>-IB_P&}ywAgtn{lF4SPNS4sNaVp2Csr2&M`bH->i#Qn#atWX{i~NQEo2{Q+;LEi*Dv z^LdE1o^04e>JDlp9FpoJiFQwGAbiap_0KRHhm4OPp^iC%mF<@H94Q#9BPxzbL7M)o zIc+RR&40mPpQoE{s4s(F$RM3@;>|fa?jFJ2 zk5~H0o1y9jGm_5$7IUc1Ca8t;a{qN$w{%Wy%D=Ifr^`H}5W$Sbf!nm`x)Q|^7tm4= zRRH;kL$_qiexsfAB$1ni;VBZ?-%@X6Q)zN24I`J(n0Yq%8*x{dd9w8$Gq3k+H!03zAA!gH?}5%EO5D!Xnzk8S7!P=3ilu~;cePj{urQ& zxzyQ`%|z!q$obB))7L#>pa{oc;kedk`ApDh5lpeBU!{f$5pLOe~h`itz1MGdg`n`5s&1#&O{I(lZq z!FVn^#CH~r0LDn!sB0IvEp0yB2^S^1KR6VmwL(m1Ba8F993(Hh#crVt^vMZ5LO1vF zPs2QL)%1}BkoOs@(RT_Y9PDP1?1?|yZo&z#-dP~mDht^9wA)exz*)ku@paph5;l&A z7)Lmo^liyFxP)UVx2pR;=<&KnTX`D%=NfxN$kxxg)hHq*Ru(M9ruq`jeS~o3})WO`>qWQQY29;|No%V&WUqe~+I?|Dgwb5NmV2b+hxQd|W z8ADAoqkF#)4W}&(kr))DFb~sLae{L4$x-Cr?oZfYnkPiAh4nLHXA~UPYEd32>yjWKi?y@ zpU2d{$gF}9nJdk=P9#I{q8i-I0HaN^wlEM!dv>&YL&>b&1@{87R5 z$-l?4tN!NXRP>PK$ruW5<8g_V`AU%&XQ)Xh5d`>62J?d&EcWE)aDzZ9dxs~nZzG4} zqEBbk@2i0ktqf*Q4`>&k4Jn_Me%in3psjHT76{Sh)Kt6|IrQVL+fK!f6If>ML*`+> z%Z47}3IbK#gSnh_g$aJcZuNJfRvooS+U~)pAwGb#2)Z(CYO0;1(Y+3`{kiGg9|^01 zm}3rd5(PBQP?%QRlK9J=>|Ehu;TF@^tfqtp(dirW>g*Be`CiprfSI|&M&qWMHArm~ z7s9761$2o%e}c%0)hs(C!`E_uZ2O?yzVEqLp-0QI;Oi?S2F{V4ZIr%mmVuGGl7g_m!Sf4xPDT=i27?0cM%6 zGjj&hf7#o|vyhAyAcyTv^}%<+qhVjAQU4H0#BDJOUtUj~DmWY$d#7KaUT5tPj}KL70{v$g+0z zbxSFwnhhT$nHi3k0_W}g3)BkDKr1yL^27w}zEAbv&0+gtgmIlS3e$`N%`@qElx!X| z`(@))jdcm6KamA=X;b8Oi6-NKP4~i(#+^BbsEn6uW!-K8BujYrtuq*rbLDYWlkueM zt|(PkwYqf|tU?>7@AFyrxKR&GkUB3(dpa2`FIIjQEQ;i?Ivo+KpgBA~yNB;QR&1-lqku;{z$o*QZX6giXjLH#Z=ln+g@*@f4y zK+L%DgASSOBZw$TU96#Fi5hu~{Uj#T>h+G7$gWFqewmY=I#U~pI5{(`bwx?mp(U9p zDfHIlaEv6i7q<5@I=JrR1zygrdk94I=?h)pN>2N>D4fC=7dTeG4R{x^qUyQ|-DrSq z0QQBfu|46!s4J1$%~(|ZEC*%$5razG8S^C?d(MahKC9D6bTKa0-V7~}$>LLqd!GXE z6D!VI-l@q-R=LVe46{4Ir)jJN2cp`=XO~8{=htNK??gwP88#Ca#U1kgul?|d{UK+$ z&r)qT2na{2)ujyF*qu0hwaoZjUQYR@>0_**GuK7Y@jQnF|4ebAoNt4D=2lGv%stI` zXiR~RgLl6>dcPfnt~eOknyqS;b?jNNJ+H@b;v}^eq5*H`xS+vWK>~?*C$FDkvid%o z^&^U)vF0Xgd8}>ori00M)i`N$G(?ZK;SR)%`N9)w_s%4LgkC#*D>EH&I@R= zh!MJtBX(DxZwY!r9{G8DduZ2J7`;P)i;E7z;TF=U48Yiu}oA=&$_Rh%nJdE~$swzuwzB_dr4d-Lrd&zYY?p zhmUnxnG8@cNdAzGmwoM)a?PuzY_j}BG)Fzhrk(C%zQR$(E#aW4b#R zyn&R6wOL%-70ifCN--R{7{!Lg^LT95LF#5o>B-fz(C{!2YmxptlfH%dEgBO6jigP` zY-l_ZcymXbLwHQ=d&xI08@o;y6?Ko+HfhL$wjG{pfxtB|$yXNkY6U0I<+PyeuN$tc z-B)i+%S$btMX+f7o)kpiOKs#*br+i!0}jA`V@bR#jVuS@a+nULbOodw#5c17v*264*K`^#1MvBJ|GMEIX}lBFt| z8ZcdFefUGvFFIOEo;jPeHvpD@be6j{9rk#*hzS_2W8x(dqi8LtpNxpJwbB@`(Y_1T zNJyK2V+Sgse=Ufd2MWo%i&4u4QISy8DLIni+eYfXsi3q0J59i>&0h3dm-N*}| zN&wni1mz&zfx>rony@z5I;;X}v)ZYX4>JfBiF*)hOG7@RaEEh@F*s1~!G_bGEkG(_ zKtKcPtpu{gf}(qN*T`hC{for-GUmLuq6!O)X6d0U?&=A6Wx*JIp6Z(w+*Tl}g`{i$IM;|O#oYYLJhR0@t)gp*U*_ae4pY{u)QlW2JlzF+8b!%PQ0 z6iO7VB$Z&YVXTSn7W=}o-8V7}^C;GJ=WYptTh>tmtFS~|*~m2E;Na<3u%690uaB^o zHS|zFogbu1`)z(>zfmb}e@_R3Yux5=FT~V@s=P#Z2yLZc2z%JrYQltxsdi2jfZ&$m zhe@a*_V0KwQKLEpL6d3%_^N@;o7!UZtIOx^o$%NS{VKp6DT}xnzf58RP{Nc*Qu3aP zQ)kZ`Dq|Cd%J#kdSX3)TuWaUWci1L7Oqpi%EKAv}7fW=QD#UcGF!1FwdlSE-ZQ39V zWGlql6&?o0O8=y`v)k2^q|$Se#T`Y-`|n8NusMqnd?u)xRWHt|Z0-nj;0~v+|E{v) zrgvQM?DvC>Ck$N8?`7;DUX(at9f>tfC6D`quSroi#J*61$+(e99+=0U9xMDguwlHS zieq~%?Lxl^jZdN*Fg~bR#ZL!Cehy^weHNf_z7O`2h7`59(Z|;%7+cd~Vug_UfINJG z;p_6YHV6LUK?HvZ4EDiDNYXA{_NCId`&DNLi=1<>kZwKWH&T6rLp=VVT^h_p4tRAC z!SsX%)e8DhjMHx4qJ<`aCXA@Fz;`^UU zAvh_K({ss59a3*`HGKq+Xc)_mrwgwL+i74nzbr)Vm8yJsumvnQrKBEA?4pjVy}aKc zHYLc*139X;vUuvlBC`}0l>We7{*r_!LfLpKqNiqKtw4vY9NPveU2cZ8W=L8@copyx)x0nIeWMI!{lz*c?O(zJgZb~ooZT( z)VpEV0R9<3D3XMLD|^$R9LBa*f{LTE*B{w`;ftR+IxUeQ@{FON9_UUuZ2-ZMj)%%; zfn`EtLEx{_)l)Q7TikXR4(o44U);YXBLR(|Q+GBhLWVnoYHn}@jms~3@lh994i3k~ z(F!fIYsSfJ2pbG%c0B?l%&)&HHCg<|-IHeSs2coD;eJpvO|Db5^&BvWYuU?D8BjKs z#FU{<$c*vj%m!#7X)KFJ0+l98aJ4YF{^ zK_dpGF#N|j^*!plM#`R^0GksLb_z-mM}P6l>&@zn=p_nKQrjk0B~vabGoLI(vV%$n z5=#)SW07BroHLFIz=KP=EKnk!PDnB*9R{_?WVDNiK{)`lfs`7)j4z=_n4=L0Am> z7Sx_Mv|AW)DF;HFR6M{Gn#5v;)``m$i|$5dB8x+1m<`!+-zyc{E(EcrcvkX{n6aft zi%7IJ@bN(I>efkQXd|Sms^S=5+LU26Q1I zQh9`jAIW&aX-mb4ob%15eQTAzJ+D2bcua4T2dtSyZ8u>z6tmW1KeREEV4sg-b{B-h zCb8Pyjg?0pzT>S&&*}May&VAu=8kosKKND-8IsWZjNl}5ebJS+2xF#XqLe(4cT#0G@BJ2Yd}mLUe`n=#y2Tke&Io1 z69P%eA`~kbKZdNZ+068N&{YA^v{@Se_(~sZ+d6MLme#gd=Ws7nLMYK4!+jQ{P7odA zKqxb7`<)u4F{r*Ijr(HK7ag!sCNw>gS>! z*3UXqA@H$?yP&kGmK%v*cG)ooy-nuiEa1Xp}-lJ1#$u<;MKQ|>jn`&xYKS}hXd?(SDl z-)ceHjEZooINq}2lM7OKjtE6qOHvEL96PQ%EHp}4q8O|xe?7X^NMexd;ZBOvTv9YS zYgH5msw&13cK8bf9))nd{nhIZ9y`ip*rWUxGVj?5q%I1poNvq#@7Zz4*D>s3iJ=mf z2oVCka`Y*Ar_@=*X#ozpiS7bf?A(>&7DJS{xA&qI3}YB0k$x6Xg^7@rO`-~Ff_SMl zh?J1o+#|`@jjo&zxTMX3>@2B_#?-1 z8<2_5fNN!Ibbp-j5t2a*N-53qzgxI=4u|k)=ai4ysZ^|Wz;Y3`Fcm^0GD6bkL)5^G zgk?^wyah8eG7mq&y6N#8_#5~$$=YN*Hqk^UCvDgw6_wo@29@`&Y7OW6{Suq?{vEkp z_$OEIok;TjT+q-n6d=N8+sb@}PW4f!6dt9_kv?+aNd`dyTEd`-k+5{t@~Un-kw z8_!ZF5IQ4#D!u;L73G4h1W4~hIwY%3Vou#BR_>?6tdbwr%yB|CJV<`nVK9u#@`X>N z+g(xoBS*k~bySF%kgX0ef|{-n{p2gPk!EidZU}abR$Iw4VhXs}Po0T*)*)nHfDL&Z3-^$0{Y()h8~oB2?=thH>uf4jRA`(+ zo^qHtax?C|vx-8g1359h0AgQdc)G+2+IVVb4hBoQ?9bh;E z4Gv`W!x}Jt&L)wt z<;j(`n4zuikvT-9-s6buueu%r1^aBex4`*;t9;aN*eP|p58QTk!Akrkngi&j$~^X~ z{^bw`d6=2AKN_s{A<#L_IyZ`%gk#+ZwukOBs#zf0g(PrQWA!&anE8>;L)C!^P{n^t zq|dEV-%B5adNt#XX){RAh7rG;bk}=`er;0yNITC{5ScSFPih5A)->&}C_p}?6x01& z-5XkWZ_(2)8tsqB2{~8RZ8ZeBZMoVRAZbF26@&`<2{Winbch7~+QDS|rY_0cN)vjh zJ2Ss2$Btr?&d+bOsX%|z0Z8lIFY%wM#Z}(Yq11QfJ0s&(&~L|SlfT{r|9Jy}Fo1M68jf%VItzh(I_&e}eaI@{ zsOcd}(_c|i|4p6Eztn{${--*;|5B&y;jV1;|059VZ-He0E^q|!cU!=JT>mJLDiDDE zcQv|=zv-^nf0OjD?W^F!$o^9jyp_0Q%&Sss}l)U$I%oHv!gRyB*-X&HMpY4XU+)x?Hj$=9OEzkAs4SN>g*8}tZi1D zD_M&1@bs4*TS)IeU!cagNo1)BEDx(y)l9!JJ>em|8H&y1o;a`#V)2k4F?-2rHT>`$ zkW3{VI9pH);VbS>)ti}j-n%6c#Z|<6)tkc6&0&SqlB*C`3H(X1yc~yGHtVKhV$(ANEJc^jy`w9KQFvs7e|`* zK;{Y^W$6rqEE8ZER5dA=Fg2Y6sYxydBl;J**swn;`mGsJ_$VN#evwcXP_NzLa4fv1iZ#s<8Aie-EIv}MEq zMPJ4(Mgo1OQb`jQAJ}g??h^D?1O^xngl7t(6ZCvcz6y}0o-8NUzhO#-74fD!z*Y|m zXLU^}cT8tjbyB8W&Qz8G!IBebg=kbd?~FR5G%V$HyGN6GDqI!8Ed01nD1ZFP8)_GwkzFS7!s^A_H z_GVT^{^%g^iv)ApZD?L5%WOf^ufM;ePZg7@NRcR1oXA7mJvmut)7i1Yb*%HUOi$#_ zlfB*|a(I*1^G|=KXFVgt`NZYT^2>(rN+-uwc3jqU00jVm(D^%kP&@uBeIhUaTlzSd z|3~`#_lm#L2MGeuf%?z%=|K5}3cyyA;AbhfUwuEe??#r;Lh>9O49dr}vg45ugLL#; ziWW34<+?>ue)YR4*pYE~1j|dk)RP2Ns{)}CddZV%Splp7E1hkL3 z&f}ogSD@L-qI3m#-Z(c_@_svZdd7^uz6F?=Wn1ue)Zw+v7~2Su-{WUK1OAjQB4B`M zoA9aFI%5Zzf?$9nfS&FCx$!G;wRlP@Nry6ow8QcrStaH%AfF;q(@}{COiYbM+&u_Z zwB&eT(?EqV(w?OR%tWEFUc2P(pkveol+s0Jok~v>O`qlS7lGwG1&Q%B%t?s6S^kZL zR5UIBsjEM}G`<^ENsY8=&^+;8E$`f4(pUC=B^FFF$$zdBD3A}9@59MLV$JTi{k1sA zXCL}TjG0o6Si>N&*$7W4cIA`n(Zl2%23>xqR9i*q9o#ts`oSWeIPEH~F^?S6L?8Vr z*@>P0_L-p_9?qIShTI&r+FnQo?D*{^-dqlUK6;S)GNpPUAIP7AQzltr=Y`wDgCuK<5PivJ1*U|GNb0EZBL=3(s6ZZiAy z+pGHft^xn8;MM0q-18?-&2c1o746+*D-C)ku}Y7cQlWGHlxSaa zM|1U&E1b-~2Ei5X#+~O?>Z?qtm)fz?5!bgVi|?s@$V#4MDaXbN8uVYsfYgZrM80K_@ z)A-Z-jbR3WPen-ms__~O-0RSj)TP}nZLwvHvW-jfdG$?Cavai7N5 z%sa>~1|YM;Rcrn#%-zTGj#A{}@|REkjgB4=cY75X)YQ0J3J^~Njt8$|qur{zh88bSWW#$iy|FedJiuqiDRe4egSMSyC)Gf~rq zL$b%;FRu(O=0i^7td2TH^aJ8po_9KuM9xSe^dzVZ(Ym>zGD_ZfnADKboNx;5P`064 z^y^N0oNlFshBjnbUiv3DF7Jpfp08+09Q6^ur(@b!o7EaID14x46Nn+`ypB2&I!Jvm z1)3ibH$>A+6NrjknMixYyD)p{(|#|I9e5b-#wVfp>B7A+&+J60bz&r;ZHKLQYc*Z* zL)4W%Ha!RIDC-a?m2S)TR`;NnGq*{;7 z5kZ|Ui~KZXM6tN@8F@Wirn_eW9ULY%v=!v7k1%_Mqc?yD8{}Px{R22IvXeO7jXt*S zqrFTC7F8~ixubD#Zu}`5$*EvOrSKc5?eWc~&?bi11g4V=)4owQ zl}K!vFP->F-FyC3Y$5;obT@P&4>s((%UA<-SKtvHikuix#A$Aa7WD zLG?QDeLqcs%y3V!c_f6a1E`lq8jB})hRg#oY;+}OFg4F~Hrf`(SM7TE^r$Ra>xVj4wsxFAtCAjH+zW z5F%nr8um;Q?HS6QJBrE^D(gatjI#4~@CC1ZKd>x< zd)^CXQWb?hxG#v{*d9+H>DpeIF$uDZrfx#+uC?(I{Iyg6UG*ajev4`PQja0aa2dY< zLiF+}=mp_8KZs)tP5HcAa-{fNyZg75&7-_ zs;8D?WWq$|RD6tZ2+|Yg&kuyFQ}UloiWd-I6)$mh?xRTFOoHbgf`P7WZ^V-;@*HJ2 zhb}$n?slmOM(k4_Lbg-egn2*bjk94Ij~cO}mpnqdCEe&;??dn=XxO(f>sll=kP_og zoqb;LsGM4jGC$-TQJKv8>R7iEiN=vVr&USekcEPD(_YC#lXi8f;&@i>hWy3{9R-7RrCnaH-o&w_m2lKIX0 z^ZowPP*0qS=LsWYT-5x}?Ki2FwT-!V;>fPi7g%IHy_*d!~ zsYe13QoGazlKmt}_&4(QrjepTaSOyn26m~bdo@#z`1{xAii-J@(ApodWwzk6c5-aW z9K!ZHB6~fAoF|z~#Ra7!4{@iP-{i_4Sfmeo)C;hc?G7=KVzB{rb-F| zw4EbyA3aL(Mx^I=v`MpT=hcxvkMY4toukXujj?>*6`$mbmhjS*Is78M*lwbRLoaRs zTkTgN{01X=szJ9i(O%!Yg$B4I7(WrnX5AUgiy?s zk@XM{IrfDF(oHuPa$G@bRHl7oyemx90o zVG?1xD(g2Wh+mb;1J7dI2#1@KGF|}GwFN4GBRph}p@*8^iaxWtS!X1^HL>$*@2eCK z5y#;Ekt#BExGQD#e0Hzunw-1!Kot*+qZM^<`G>W=V0d{qYj(YH6F>h#t*R?6;rRH`D0!ETPbo7CAf6gh|p(mN>X|YDKgXLs5oy3`K zWzMM!r?MHt9%YQ1TyDfYiT#QD6RjxRIAGQCeZGaTDfM$zwywBuT+CO_U#g7}mK^VED94E~zI>+KTDXHAtS0};c~=woHaZDUqB zC2R3pM&0uOJuKyrO~rP#)5Y*7{p}5UqO^cx`riwm9!M&4$Y&6h@An?pfHQ8+x(Sof zg3L*G2QY6NsC#m>rvwJP-<=19M`Jn% z(QuYE^Fv_Dhs?BM84#vN#P)_sbxDmiU~(ZfDuK9O@tw zXsK@(R#1G&B*!ec0N;e5SoATb{>lw{6Q=i0xQo5}-O}q~@ z_JemJuJOD$GCHQBwg}_hj($XgT;Hf0jmQ6Sau~bC00I9U*wR;q?#~?Gtpl7)RF4@; za^}XW;lXTcZ$!l7hrl@SEAF0klif+vai!H?R$k%lgFc+(JVBLEb<&9XiEHDDUkgtIlt`cu5{Te3-7CXwtPVxfn=edQ-K5MnI zZOD;tJYk}IG~h@E@PO#wrWfEXRM}U83-LwdcE`wW76?OnWJ9kro+P=H_qv)5sU)fi zMXBxD>!U&15bxRT$Gul6T{gERdyA$!pj1P?kG2r-0rKS&%=i@j;?B=F9Cz_tnhT{| z(YX!{v42zrji7;c(Bj+eqzPCG8RQ$a@1yq*dUl$>$U`k`!6L7hz6 ziwt!=0(nD2nh?1t%8f(YQ>=WhtX7NykI)kf^!x(ro&cOQ1d!fSYc7XoTWWl_;6{O( ze>M2=YZm^9sOdd_lEWpm+9o#zbRwbUF8mE!{>y3UD`BojGxNER+;I)|etO81tby$8 zNa8KFMAnvQTfu?OGsX%Jw9{gtn^$O=Kk~Y-5$yv;QB03+b0@8M0!3_u^>5Pz=tV=& zE-#7tlWfXWM$v#$e*wQL3J)TA_)iKSzl)e~;pAp|bNijT<^-IJUKp4QYnm)`K6T^0 zpw6kJ7G<-Pcs`TUeNF>0V%NWBx2_RSO*rR%p3}2S{cDoqPl(8@(z`o9d(k=}CIe{| zoq=~(>BB+bM5refG=@U-%vma6duZ{ZWG`Pqg!OBl?%>pW^|MI1kthOq$eD#n9Cv#T zN0%DEq2cZ6ibjBSjRYoOB@9x%({sFklW+DjtubQPjKV|Yh-$8L_Ge4+X zHb_JXO#(f11%q<4?VCU`l`m>W)?m&Yi6_OtFfTPzrzMR{4o~89Fg1&(0_xRX<@}4tC#? z1!N<7^12=+eG}YF%ateqM*&Q$^859f#ddy9vbO|c0rez5g}E{kp_{i}l*`Cjjw1CklFK7J|GNagmitfM!(H zhv`&F0o1T=xWSiM%VpX;;Rzk^zbC>wzw!`%D*-*5AnL!`4iSrds!W#P{RB0zrBar= zFE>l3e5KlWp5SIM7u0KgW@gP-LF ze94)eYt1d3D!z|3aY3=gE8u8%E{`*0OuB${c@Mn7hh>m2w(gm$@${;xs9S@~AU{xc z&CRki)ja=IY8wXivAdoh8ELP;B$Nje`$w~DU46yKcBtIWlsDQpeF-nfibbYJSSJzC z`hL@|rVR8aF0}Jbqj?rxf0FutPPO%WSvi)nuZ`EUTpzc92(B9fq9fu@UV5F%a~q!&`_ zS6Z6TF9e)N?zZC>6iaIlLd(^i3y3#W2IV-LW~VJ^+{99+zDEY$^s>)787GNx#`M+V zR~Dm!Rh0se<-hRJpGl~$T41x0o}|AbKs@#FUzcn8R;Z2Vk`Rl>d%)LTam$p2x`sHG z{q$~i3Xm&#BWVFs_L_Z=#`>byA2k0T#_l0V7l26ejZ zlyz=*Pjti|vzfciWv=p#Co*$<@qDn^A@QIc=5$DVljTC`jfVZyvG|BSzjGn3%A&|n zPb~9vl=H+qa}r-_^s~T?tDInRMv{pGM34^}c!DkyHCLtF2ZbSE6pTB(q>pZRS6=H6 zs;1(7>#46YN)NoKdjqS7hSzoIW@Jj1(RU#1h+nPsJ{QGC%B4La*ut_eICZT^cWAr` zqB9Lo?hiG9QD4Yw_pVf)r$)?m#+?YM}nH$=4vwbL$z0tyc zk6SU>OB?0ke)0o<7h}EJmAq(LS8m5yLU5&e4vMZa3WKxCUO5Qp3@E35Ve5L(6enV9 zn{BHy1R$Pqt66UU^7^kL5kypAJyqhyxz}(+N2t+|r_G7yt?k(x@8C@QlTp7kyw+n9 z&VC7!KIpJ#HlJ9~51sqtY;03RlQQ15vB1v_otH)I}k?wv($)@12Dq9h*h=TNU#7{K&QWM zC9OetzQp|Rk#A4ZF1!a@Gsas5Czq0o#NWv%JxRjWwA$#Ik0HE^i%uXTCzC(jZ_qs& zk2yTEq3v;sg?LJ#KGYUn03o7ZqzPUmh_0VzNly6vKMfd22;-9((8coP37q6y6Nhl! zDkQ4D!a#4(k+FJ*k$f@)TPci*c2HrC+^ue?7fG7o+z_Suz!;bMXTCW}9|Wk=3g2Z3M1@@71I^d9c@04& zcY{DziuR*?8)v?V!DrYMonM{LuX@F9mJ`6}9x=TW$0G#O3!damugn8S zIo)^WDt8f2vYitlUs1g0c&hvRm_%l80QxzmHE00K@SPbHyVjOo zdf72m>n2m(kWp?~N$5?s{FX&ur4QV$P9V=la8E(kb9;=+6$YFk?mEPqn8lqno+kew z=vd!uRSqKcnME&9NAeY0VPGz5{&7{L3!(NhL4Vi1RZ7lWDjzt6{;}qX5kAQ}d|hT^ zCf}46&;~kXvHzjsUsQ>8(jcz86T7|y2796u0^~G}luP;<>22En(Orot`=bQz`1%)G zJ0t`U%PuOwtdN+JgUBgo#$EwS5~Z7<&YThB6AzDWGcFQJ7d7GZ@qu6kO1YOZ?4A^z z=Qftg8?Bf-yy-5ai~*nH=^bSW}|ahwcc2aC+@Cpy?43@@TvI-pbm7uPL2*R4zmq|Abd=6 zalK%8w0g#qcq-9tlHnW8^~@G76i_e_$a@$vO?OowAl!@pz#7&6#hOy@{~K$-%@tk$ z|4(Isl=4$p-{58-T`)=w==?z^+M=E7-g(l2ngUF@^ zHNT~Tl!o)%!jDxVN=TJIS-1%21M;!HP>ij1x=mhn>VKx*-TPoJug6-kT$n5(%^JeF zDJrjmQd~0^Z2fqqAPT!Y6dbgLYU-Aq&1Z@746 zS*$@A;(Im5_Uw&o9ejq@yd)9($Q$n~ylpe&OSAeY1PUcGD_-(&TvU1v1#*c_xoErs zF3HQhfgrO))+7x@AlP1V(9clekPZNgqOnL`UK_FN2=mN7PLYB~xTuOiT5Dz^3g@fU zT3Yn82bF`nyGqf+I!1N}u-N9QQd$W< z&FrNbDzXG{v<{nf&m5=`>4jrX3O>h|d%V_d zm|fd#p;Q7wYVe6`WaWg>$s?Y0&>5)=V%;XmtqxdHHVxcZ&_MRxIIy$;0Fc0x^bv81hBHi>dFGOuWdM z7k(}59D0aupIm1%{sARBSkIQk$IWtIt{;l@FOFz95X<3RNWus@3WQzxyxMsEJT$m<0} zNA$0}%4P;7osUc1ldUIEHp-^?JW3vsix&*xa@6|2a-fc^#M`b&m;5rC!3|1W2Q11m zw?*vEG~E|i;CFvR3RddDjY088}Su5ioJOQL;k>`>bEJ? zwoNvtTUG@&q)F?cHbz*!*~~+LjX1Z=>?O;I78hdL5q(qVsaCc6UrpizfK4qw7Tuj5 zn)3I&XQx{3BCq`2dBdi5KMY}p3$XA5N%?q#vbYx+dV9=#*$=FSl8a;NatcoC_sYwQ ztTV+YXl`Imxo{@|5`!MLP*12?WAZ~3V`yI9$rsH+=41$3Q<`bWvsNPP)a4+VsZym8~^A!W~B zhKN%uH_P}kvBMHkUH(*%ING8Z^@OHE&pEW@g0>&qmOKi0ozrzzoG1j^Dfa_?2EJ<2 z10`S1&&lgnDZ3lCq{NW>D*Jac2zY^<1J_+DumE4CGSmbsa}>ouKdomsaLQ~1%jh*X zI;@4kh{`cv{Z6Y3Gn?Qng15%mfQ z+sL&8RcJn@>9#UP1Ot$c9d0kS+Jjh&cZHT82GW%dk4ete-S%BV*BsAzZ1ISd8gx@` z#g3=Mbb#k9fXsr1{#>k??c1EK37xNs-_4$%K-S zBlQ{%pD*jc`SS2E;14}W)ERM{69Ls=_iXjJmMKD#PpGsT0+?N$P0@Y0 z^lbk-kg!H(?X4nl-FkB0ygQ~lycR1*bLUYgQ~o5^-t^>9i2zG-+7ZO~T(%pdrEL>K zUcn3q8I8K;l8PyggY@jNn&o#Z8bmYZ5bV<|$dDd6n>wX6D$uIBidhWy3z4Rg<#JCfH65>2XHP(#cQXMOFx6C2!UH-Nn0u~<78 zy*bF?bwA?{a5#})E%}I=P@yLteF(q*@-@CRh5`i1QvwVx3MIWhImloSk=I^m(x#KQ zKUY;F_Q!~1|s^) z6hqs3QHfJ)S$$vCx~mwVNd##q_Z0#?Iw80)+98i?y>^uCxXzp5SOoKY4NQTRLpMkT zMUQBsjR+4L0i9DWJsABmKD4o(!{#lT{F4B6}lBq15|9yv z8vtpGFv&irW7>c;tg#1~g;6gYEcsl@c=uxUj_gVQIV~F90LO1}h^yu{lXZ)C+|~cI zqH;kR8;`?6VqlZpaa?e3|63^2N0*DSfRn-nrxGM!2CeU6K70WB;n9eO+ujFw7W^lb zUW5C9=V};-`r<*@UxQ(U{mH79eWT=bkqGCZy|jF9E8Y1w{KS;v z<6BwOERCR=!`iSgzM{|-!T@gGwvo9IMy-CSs6>9`qCug?XgpQ-9rV!j<; zkrX`%#nL5Hq{&HOBHRRThzAj|oH!4t!W2Wd{%II*AYQoru{X{5wO%JwnmcZ&_-9e) z^0(rkX8{EMUQ4lCA0AmNc6x{Ltw+M{>>bIB4KtYaf zfy%)}51I*J{P3z$gGxYWnmY(pkB-*k^_D!4!M(n-tT3WWt^T9<=JZ|@sw;VH`mbj5 zGi`0+u6Fq=Gf)yD^Lk0xi9I`rRN1xkrZ;c5AR&^$#@c1)GY%9Fj#l$URLN631fkX4drh8SO z3rY-gU5BctF05g@Zi;ShP3lv-W-x1E%v8>zsP9eOoXh0OSFU1A0LHH?ZD=PUck{Fc z1X_o7Y#**tw2%4rv7AF_?l@R<#gyTX!{Q07j-zKC!st8-_#|PA>t$4t6w?)pP{Ua{CR}{Dse2(v_`+8(ZxU?TM3~}+qp_NcAt;>zDaCCbW~{&$ zW7)v0vQEp3*q3U5XDaQ;#MZJGQgampW6+uK=FXk^*eggofWLQYov&WFdo;5hcM{of zZx;0~A4>HvCP;RHBIp$|MB*25yt_<=aY}P zd)%qyNI=M11L@O!dXhOI8Tqxbm*(Tld8#Ad94{j1j0zllVB&BrKyXQy2KkO(#|xn7 zbKFKwzW}CwM{RC&AyYEfv*oa}!5?s|UfL#2&hnA_E z*|MeCpUDNa2(nNZ_}8RS5N{N&=seZPy`DPgt;yXA%Y@zAf$qhqS#+*hpX=89?1mrI z-vOhYYbGh#;vmf9c%m`^>GTH-CWf!QXtWoU z816IxULJ8I#b%y&*bBQ;h6Op9I)R+e7d#k8r#|(D$g-Y+blkbVqf7t^)U``_yJfsEwgg zn>=cLPI3`9nsC3$Qseswg&2Kt)Px06(e2_)QM^m4ZzDt2I+5iIwl1SRuja?vA>D$C z)8`6v3xG%P#8y|3P-5fnzs)S%NcKMHWMi*Ls|*N=uO77j3W2g zQ)4aq97WNuQZx+qVexlNf>!gB!?UI@4Z5y4M8T$KQP3-Fo| zY7X3C;)L@}I$JE***$0}TF|%MjzyTxcyi+i@Auxb6aeD#4-c)!t%mqtA#EUeP^fwq zAA5fjS1(=>xQYkOLo;)(?H0HL=(fW63YkKwQRKXd1-o`3tQVreU^}eTt(-$_7j@$PulF{CM$$GT}`mn_Pk3}^_SqO_SkCg87L zp)wt=DmGY3cAQDzoqR`X8lNP!8(4K!kD_unBi4?BCLLQk055Oq>_Sk?S^Z4MVMC-K zj!0?n`m*|o08yGbAMuL3NYja`HyDAd$Z^ke;G%h*f<=(ZN5|GcRuuh(-9#p&wDOu9 zgkV9B=m;*H^aT%OghEY^liCDIp0LYA3|wZOg1qSTq z?`T9&#Uqh_-T3&JJ5jE(o2&jK;0;1wk|hJJnj^ULWWvPJ9F^GqI}mrRz|z%EeEV!7 zUSD?@%0R1CbW6`lMQ4U-Qx>A|jMzSOI-!sMXAJOM(m1-lRPF{Vo&>K&>Mht$z0Z>J zu}VI?zDjB@TXzg8_;4JVRo+m|>}0YCmJ!Bht-RIo&+y|Xp|jtDr>?~o0pOv ztsHyl;X>U<3{vYra@cIpzIAIj7aAdxu6IXycll%BNjZ1U+i~KdbUWA{%H>rnUuZwI znkO-w&Tg>ChEu5MJ*uP^9bSKWbg1*x#B_ug-B;>@;eI~QN*;?n@4QglKzSg^`3}*X z0;1!9sLGCBu<%09juVP8hykqoiIq9qKU}!)aDWQEV5}^{aZpp&xZ!pkY{d2C(-S-w zEdR!X7Y5-q08J*zAsmh0177^PFq8N%#cOU0prvTfw%=Gh&clk07jfNSg0k)_h&iAR zRNa?eeA9v+o|CLDtcF?hf#2UxtvEd3(bq4IfVAQl?t;N6-8HL`WLIfgUozySV1&ql zMQA~3*$F~58*pXq+()f`?mFlVPgUEBcuY7aJTv+YCF!y{P!ln&?H@ZgO1Sm5%NRZf z9JAYmMZ6b58{aZVo`g+R>zP0k0?7YD7#$r&MEd(<8@$V8#qe#%(4oSmf~a+PrEjg^ zLIzQaX(?2MeC*GA31JX2&rT3c9m}h3@?5N)pnyW&r;Hp^kc_|=t5)MzK-4>tS)x@d zyKQ2HgeQpF7ILZU9@6y3B=W#bh-Eq<&CQY%zgTPG`BH*rMJ|xY6$v8Qj~k-NEA)MK z*fff+n#X-+7+0)D)o}P)2 z8r*;n>?5;;5OI3MsuJb-jmU;fsKm;O+H~vG#|PT7wwU$$DD;>j7hh+TY}5ap<3zYU zZ}6k-R;ajJcM$G|X(1mXsO_CZw=AyAvaIh6G%L_iQ~)1hO#)7te+spWnpA!VFt<1} zmU^GU%kP=YJxA7xiR(BXL`PNn21aiPhrzMeBMGt#6F=&T_T(3bE880$eA}uYY3FYD zJ)qMP*!|`$Z{{nWJT&mF>UZ$*#uQmFhr`v02yYhhB6cAADzktubk<77B@{w^!DC)X z2!3}o(dtisDqRW_fVcm^_M#CT3CAH#*O1c6mD<758X=6EH_7FT!zO=fC|%K83a4iU zsZS9da|c_YtNZeN0mLd*(84=II>*yRXRorefqf^b4Q9b@`eG&w@}|{=Bs?9u}YtK5mu) z$cxF0L7UZ>>k_Mc-bOF%`#YWy#@haKf#(ebFNpYRIuTV)>vmZ9rNAtlvW;&uKxi*{ z$ZOD^-H^es=LSS9S~Lv0M#7ZcnwPtAl(m0Qqg)#D7f+OqIx*-|FSwP6{Nt?R%Gb>b z7t;1pW#B&{Aea9mmTJ>7sN<~6i8KNH;-bFgtrLILlnQoH52g7=ifqUqMEYK?vxTX! zwCe(sXpr2v1d0%#!d&B#ci|HWAOt9u)x)w`vC7kiUz_c+r(;XFgrmq1)`=~nSXRjY zJ(V=^YJ9=f5R_;UeP|shLX28sp%KTn`#hOKCNT?6Zco+|C3rLhK zt4lm1Xuo*J5x^=C88t+0;O=jo9U8Em)SFE`h!aZS7hJpHolZWJ;8=+lF8u?nO}-Eo z`p1V@%{6(PA5|Y&f*IYFNAM4ZVXr5hX3E@W_%UB(J4f!R6~X4jjA7A=F*lRK3!4v) z2(H~>U|_$H%@P>KW*<;WWVz25FKO}wsKjsQevn2Mr^r7mkcTYadhY3_1jH$R|8kP8 zP*J(QBg*@6j_SE_zz30UM_wq%MU5eCKQ!dIiz-$^HkcO#bEtlq)O1LmyBSGkA!c{b zwuWJaX%m773-#5}xqEM>1B%Z-LGWF<)st6HGTpyvz%cQmxAiTH&>szVf#C;O-|E>p zTW5=ROsYx>TqnwOATsDvUm!=CiC8;POp$OLMR)yiMFKlpxx&RuRAe~#n$g#K*`b%XbR{Ww<(3jiYM)9s zV-t;^dr;o*_$)cQsV&dQqlWQZwqg(^$JebD=6h0{0qJ7R{AAj!8rNSmsW+T`2(6 zw7+7^70pRNp+p4=1m6x%F9)Tl;_c z9*R6Dn;d~$rC8F*5AmJCPiKz6c54JXDt_y;sVrWL#y zHA(n?-vHYMGDvvubI&M9p`55fd9Z{$2zy&Q(G^&ifs_P@?IX#9UW zAH@Ip8}a{!zW>=@{=)kY=!-iCg1KpOVMjt*kb>M6QpG`8+Ql#zWlzpKx!SV@jb)_E zvO_R?-8O)^Ol2A2=u7&q`jTE`hfA~BFFz$YBnu=hq`5nk9a)e%%kaEC0ewyj-Q_W= z(y|e$Q{XeLr#fUg`4tC`HAg5z9)t4HE7xq{Xk$A2_bf<#0gF#{%&4Rj7J7frREnMb zsP3^H#Q-nDM6d@aNtl4p!=indyiYVbr~$FUY&u!#qZ%Y$$6F#-2pbp=>R2jlH*mHd zUf)u%3C<|v*}EMFs-*|MZKW*^`7a9xkY#5=%aZJhuUf{+HMpNWtSGs8Ed#^rGP=M* zv)BVeez`4oIXj{5(LdnH2tfB32&5D-S`L@gwxuNISsh#hPyOQy84|u8%Q&LlVB!q; z=-7Cxw;bX5#nQ@b&>bC3J0~#&L)P|tsSQ5dyRrlpPNWhDA;~GDK%0@b7|HTK!y3*I zq~aewNsMiJ^!qS0rN8-kEDs4u2DKz%VO@7^)akYGK=mg)-n41j=Yo;vN+~G= zFZd;Woz{H&Ns)cx!}04#(pMUq(5)aetwv_%ajZeL%UNQ`@?H^z8!4)mUzA2rWAUzP z-+`!_hF!OlvmKU~kv@k0S!Q3FfyLj^NqN}A=o^I7LTf3+ik>HdtolcmHuAx_e)72b zo%ZXt;(dPE8^s^}r z29QGB;WR~l!h|8R9>5~r2$*1Us)fgsgmtZ%O)aujnyd&O*Zzv7*n5-0^v8=!aj8LJ z?~1C2;p&GcErg@^N{Q~?-CLUXmP?C;JX!Y1(~?(HdWc74CSSy9A@j>dTRw(5qb5xfEGCqh9L2(}=!{LZ% z47DGjU7-|##%kg94O2vp`i3PGnjn(|R@9T*5mD?Y#7#~*iHc?}Xa;SD+Ts0kK)Z0m zGW0~qftk&afUe(2NTkear%r;W&XBr%xaye9pjE?G{r@?S=-ymxU&qkKYCA2@*p8hxzY)U3N(C zrR1wU1re_$Zu?$KYS~7Y2H;}$!<;Abm;nje_+L%PR;8{$H$>QC?~Y(8yWJi?*4I>x!Ey7@7aF{Wc+Muw!@BI8>H$1*iYe*1 zrGQlGS+x#b0RNRG(1T};uPD^6OaX|UgcvD1~w!OYPqoLe>{?9n&mgG24KZ$@xW53wIhDQ%9uwDyGb1 zk87LUHDNd5f!xGEt@3C93N#=DG6E+;2j6?zJi|jiN)P%73@0(ExL;}d$IwRV5yR?) zH+*a{XE=2SE$JHC)N8Cc6o?gZRft2xuV|mUK|fulq@p5-%|Hw)I18LYn-|i|pY{}0 z6B3#OBW!3ij*`oH2}hK@1PGdebLK6J0jCdap|_58>p>A3!kilM9lxG+(RaYK=biZj zG`t;>;xM`>a?TpFD1YEHEF|8q(TzdVGJ0RL^H7gh>{w`HweJ8F=#kVW+ak~Csg1sP z($5V1S#Jf)fu?xqva|JLK6ytES*nZfkpHIAuF9kFd(?y6)wU42(FuoW4s$SE*`Ecu z{;wO7#tU7S0ao+CP&8T&WwV)$APRqI1ZxVi+5_q$m% z7Hn9%Tm|WhNZH~qLH28Z{nEU#P&@?P}0sR=S<&uy4afZXA^E4M-42}t%e zR`7=~m}#5Y+E(u%SRO~*SQi2%%=|g_6}4aw-Y|H>57C+uO($bFZkgyElC^lhOzi5U zmlVn{76;|So$dk8$ljolr0iI&dY!IJ#4=)G-8{4*wVORB3wM>wqQ6XZ&P3Q|Yf-%iJlU~WkS*a^WT9l0 z&7Rd_9h3Z=3@S7E|r0f*Aqrtmrb{%x)(&I$_3kk?`>={o(1^4 z1?St5-ATwf1*OVC(&)lM+S7Xqb~1nXK-?h;`dbzV$cR1C-n*JQgkxxVTPRS%SV95q z9hQ?f;gao@%2ft!#E?Y@&>m&YSI&$R2uf?rT59na*(Z39GCWz|o4hJl;&RUCr>&y| zEiPM{LWDt-76BSaT?J_4+%n9yd^7{&(2R|oagZT~b?GYo#>AH9*h2v`kjXW4(1P%`KnY&phYz7k4H$Co# z>7uRQzzgb{In2uma(XUvlUXn<95;mqtXGz#O&xEd$<+C4kVSL z{S-s6IG{1RQ^z{sv(4ehw|FgQ8T2Ed>iiVx^xA=Hk~Ri5Xe7|>ear{(yrmOOZ@tks z#E5ZruR+4#k#)2Yhu}Y1-|^E)pxg&ByK<3geNF*W zbKI8rb`r?*4`HkMO&nJWtVP};%DQxNa(CS*))%R-xV<_xQhq0|0K07Nn9u?>PtcE$ zdJ|j|f6RrPHd{6fk+IUi>$y+#BN*3{p2)_mw@&ON z4<#TV*n+z^g2H%j<#~7b$S2;k<&F!GOH@*rDjJIY@f+yknM$%%)joSph`kJ*6i>PoIZ>{7j%bj2VgLs^>3vGVMzb5i< z^a;&Bd(qQ+RDw0ft`0r*?AuHcP> zrf4H>uR|KSUDgv1Co~PwS769*HJNk|@Uviy8z|BPSldr*h4fD7Ij8wTB#tYhAHPW1 zi93+lPBlc|AEpWL3=9!ubxVgKH)T}5`E8@{5a5>jEQZ=|B1sCsp@kCUBmGD?qZy&d z9AB3(s@*@FL>`C2$T4|tP?;k* z+A^DYLCwvGEWP8=&`kK(6d$8nQ3gL{8hr`=A@&x5MP#wg+22qkIU4(R`Adz^*lJ3M zHAe)crV%j_?Qb`PxdKzP)X<*h9g3M~K8o|`Tv~b~#FVciO&#$HdUQ0vTePEvs(4I; z&E8&V1J-#h7k2IW_eqaN)b09sUB-QD%YL4|7miAx5w57n0tIA-{qXcOOL*Bmjz%Ft zvTUV|3Dh~qi1Q%Qj*vhi3vMAC?6OIlkZ&bM4KCaVw0{|R_L>Oca6M;jJA<>+-~#dA?iX`M*`gz4ZPKK~7P%@>u+D!mX4Ej2$5r$^>sdu2A23Fe@{NHM=umi!yr=lq9v`+2E-t`XUhv)2X!rTNNk#T|ACreg|qSuQYC zQb9@NLDivtsC23j5>K;OV=M8SsOY3VNMcgYnFPHCS-NrM8-0_WRu@v{LGj@v4#9ve7nkqM)n-zOT*(BJgOJU#gE)V-!P{%!S~Fm(N9 zM2-NHwV7Mzb}oqqbM_G=S?S;Sk&DVZX! z9LV%BY?Bh+Qz+bh=;2?!KfOybj;e(c;W~ybG!mWEG6@}mS{n!}aNAtjlGgTnSe}8} zUGx^wEDu=(WLwY|i@<4~PVNZ!ECgH6;{Uq%rY+PVFW_Y>x?5$J|7BBJZc?e~!k|bK zJ{=-mqtDxGGS?4)ntownft`!fwk!1AEY=RwJzRqi>tT}9O8+*6l2(-5d%kfv~X=t=2Jr9C;!-K~QduTGmf= zIi~hp%pLj=!j7|8+Ar1+h1ph!4htjw8%;?tD~@7M#WTfh}q~SwAYVC2^|a zR`Ne&J1AHj|0L2@@yZiI&xp~>ZA$6xKrN+>I%UWI!7T3-VbJ0uv@n}|My`tZI}Vx~ z(lZ#xJhyu}z=%TVtvRdei=bm|(+3rMyeIx~#Fgbdw*0pD=h=tS0?&mYDl`W&vlNGo z{&C>2gcx}%lC~P%L3yybBNhQwPYx3OCWp`E!!SDEXpPX4khhzD$Lf;>~r)`kmh2wg;Kekx}i}tMp99Avjr| zCqXYWVt{rzC6Z;C1P=F*;!s0*xm}OvGk$^8o1uD1mygvIv`xXIEOIc;7!mxN1bmTo zHqMI+iK#yZ64^zs6ny6_|C4={Hi9jTYjXw6jggt-hZ*x;WG?KQqyWTY6R0Uc=YKKm zGz?-B6n0sLt;3oGPrOq_=GN0RyH)Y~@@=@b&u%;|#vz#PO3Z9X5So&_TL=uHC-^dD zUbOb_HNAaM;kTfvo@JXMSVJad7xd#SnYGnrkLj0zaS= zb})x$&QL6M*~JfcCIzjF2qBvD){LJ54-`KqGhKT3XQi|Y{Z4{bv}DXiGy4+@VfplH zsifwtOsleKC1f0?#}v6Y!J?vNAhRv8Ei*8fEoai7Cc7aXSHr*+uIl&E3gz05%bSNs z+6(shYMqDr6VspXADCs-FHg!C-4aBH31Rrh)BUizVJUD2$YN}L3;^wbG(`IZFmb$n|AHCQE<159VDV2(j539z<1kxY-)Q52>v4nJI~FppsEHedDn9<=Jgb|q}Ik#1LN zjwLwJgj?IYL?;tpSQLilR3Hvl6!K8OjPzQ9x5Uwhv&0SfTr_F}nI{0Rr=;;@)~27N zO((bPjj`*+K$(aj6fIfLOh)~yFz6s-5ayiR%-NA8EL!ZfJJgn)M~ag%FqL;8Bhy2$5KRM6gxDJqs2>Pl zh=Ul;c|_#!9Wgf@fIND~kh*UGe3a$iqM6e%YXK+aTKO??Q?wl5hm`VX7I)|bA*fu4 zSEkIU-=w(^S9o3Ri?c3HLRI}v4T7)b;wXP_sqn4YIfQWZ{CXF6Xbe$sY)G9>l8-}? zziThF%YrV&FTYEZ0Re%c-{=)@pL_bK!>{5A3(wbO{ zG8u_v5Je*D!yf;DCy?}j!{Ew9eN&ntr*I8PIEo8iR`Xhc)=&++MvhsUWao%FtE&s! z@1|_6AG5J*u;+e3yH&^`jPhbSuF4(U(8;g@`kdoy*o*5q>aMsH&OkByj`t6| z93^|FqDHwOolMGME9(ai)bbFBJ9RV63Y!2lO%_pK8jqlC6;N)=MucMtKLsi11d6~0Vius6Z%0cB#3usG zWFbBH(@&pRLF)S1t4`RMPZY9gKOcU>MsC)F7vBX1NW+{B;nY30o zniZYkSQ#hwW@X`GxK%!mf}-}oVIeoHnu68GAqgAM<9?VFCMi(G+2IMzd;(Z^g|L}C zE%JV)r@AGW>@By+#B&C5QGV4<4&ixb4#x;a+ugrO#{PK|kBBmw6ZTe?*BG0n9lr@8 z1y=7yILy!xuU*em<~U+jMQ8&b8^B(RMZV{@Y2L!R<@G&h38_RMh*pK|KwwJoK${D) z;57G+q?ES5J|!!;WxDNBC&^Z@V~U4w611?EcMEBia&4djHJ(M5FbCAt@K8o3?E=x+ z?=g$lfOAdkK*LPkr4m?rw+e!B+K$(>q$~Pr6Up{bo~=T99DB@cMyBM3yYBr#{24zx zR!Zm3H>|QQA8YK2TU~RM`cur()sk;?91Sox|b}AO9G3Q5i1e zBX@{soH07Hb7|h04QE%t^Q}-9#-0rU$T*spsa@}Weg4iAhd`^w)K$N> zTcE(z#Zq<6XK{zkF*H6>K{WC)%z92C++PJGJ4ijGj}h(g{Ts zkgzs6Q0NochJYgMfeM+2W%pu~u;N-&%pU)4gp0|u@@(&saq<0Y_$ZJZ+kB-1*GB@9 z2WJ{xW??7L2{jA$IfW*8-~8woGriP6PU=i4ApJf+hKvOrx-hGfQ+howxTMdzKo?5g z4c>`=ENmCZp8!HtJ9c%hA(~0>H|d#+IMPv=TCgSE_$?~j(Q}xO6<1jT5xzKeA_r>e zbnVFhyY3~VA?x^A|K=(`3Rg|*Y22umlKR=+wc(D=##IeKr}GRHE0o5a+TxQKDRHT7o=_?Wgz^<3#Bx-%D*fHCa9 z;@ymGV8oKX^+XfmBPgv9ZU_=PPdpL!K=Tuh1Y6chMOifBQJag&FuVQII32T!QAs>C zYKNLyk0srV3_csGUH$yRE>{LW`LX#(##EVdnG}cB zV)Tk=_ZAuRR=&&X`9$KA?{cY??BP(EyV6ix`%~Js{42)4N!=PAqYc~fPVye~33*;I z1dO{>&3uR3t}Ux9wf@W6J*8&Fo7?vURF@194vEEqqjQcUy8CS&uA!<4UG8+>Chvs!+T@;ErV!u6Fm{d9_>pBSTw zUDJ_2sn9}*sgYVei-6$_PK+r4j5@$TPQ-= zTF|jro#SWmTdD4=r=9w@x=1T$^kR}lF zE_#xv>36mJYuv%xSy#MV-8velRIdq2 zv-LoLtb)_<7aJGbeY2ls%_dz;<;cSTBqFY@_RR{iZ&v^Yl>M0$%Do|Yv(6h} z=nHC{?O#{1HJvsYGdjAEF^{5eJcj2PhL*M^*uyLK!XfelU~;DE0?nA!CC1_fEeF8T-*N!Ln+NVy+2 zR2ZvORj#8^=IeHR5mnV}+J-+^Uqn<~XB@z;4#G!x41@JgtbWtoC_NvS`h-n$cT;dQ z@zVf-(O|gB8O!l^NPVn;^>Q^K7xy~`PUc^I)}kCv?l!zCuh&NIV4n!6t*-VO)z?kb(*MA!;eWuY z-v7etZqNS>s|f!GRuvs=&HnrB<^LO4@&6lGKmQY0!~Pps>s(m>2UzD|=&a!g6?S1d zT02v8(RV5qm;nwMmkYf1Fof%mzAk@bOac49yDK~_e;lr-iK!u}AZZ|N!d$x5Ehecl z{PST-cpV1)o_MN>Uab-7=98_ zV;PbZTRP)AnR1=rk*Ha`j@XX&4(=u}aPMR`1QPk~$~hq$q&NPMkt2Za?44BjNnRCO zYgDCZXCU+USu6RZ-pVJj?~*461HJsMCJbFODx{+T;hJR!PM6;y+*U1lgqxDV?z?_@ zw3ZIrF?Ep5%OH7#-&L`z_|)k`TPXp4sJl@CA=fYm*Pl^yf6`Z)ygzu&gUq|)jbM=jNTpMZpZTqH2Y~{5!@?_u$X{V>_J0j> zLpFAwo*K1L&QT@X5p$wCvMina$(0HU-i0CNyKZA(bt>m*4MoR@{O=Bgmx?i4h|lUX z?C4LzmKPRH`NQG5aP&9fu z85Pf}^!f%|sj?UfehIsoC*b8eQR52;lz+4DB#p$o3WLQRKHCVD(m{h5h`g-E=JQZl zg$?im8_ba$Jgbr^nImJmdX^zhZ`6u1U@VD&O;7F`mv_-B79bA#jKhgKC1BQrre1~t z<*Lw@IeI{m5Pw3IT&-%HO(8ai?8M8!Pf1TmS}tUD65@wmsZlREZJ2tZU^mx!V({(a z@Q2XKgxhfXRdym^LCuCu&)W>qovG-+Y|eO&R~3U;JbxvHn~>oUD1;N-6vBY$$y7Ij z<p{K&?1Bcd$;H$ce0ifu(d?EF1d z+B;p5->Oe~jt^8_6!l4=9oE5U(nvbxAn!t&y+O>!QJjzRVa7Zf zcuRKSb{8^AaOgjsMhtG%KK0W}h;8({wn{OmlKI_j>afUUBnP$4-J%XXuqhSiYj#t` z@1$>Mw#XSiZ_qhTQ{rMEm>&{Lp0v%~O!kx5N82|NSOx-C4l|?<=F=`nQp1!Y8jg70 z1uR?DmCXBz7zjzx%Lt`26RGw-?Y8B@u-xg+sQZ1VwHs{$;l)-Y-rrk)PR8g+x8&KSy4#$R$hFZ^G?)pFJ;Q!7{3Y-W zCzo;R}ac|&+oVKYbWaN9Uom$ShS4e~f{#I_QhNSgj4QxRKiJW23b@ zFDN21@rTD`gC>79kQwUBL6$1Pr*xk0(QsQMk`{j{Js7u;G62deJah(;K+Q%tAib9r zz-NY2(qW5HK291hJ99A^8R|{sufb^#*k?j@JSm(xWSE4a*ZTHE%N4HK^$%$@rhS^$ zo0hXen#cIpZ)Wei-pKnd#iyBPp)&%uDO4lBx^M`O{qBIN7-f{?K84)V;fpAzqc*tb z!Z#GS`c*I%P23j5^+2#9{MViOxA}0>-N)~=U&NK>d&&5#Ho8kT7*p1 zE2K{Nr$uzs?&e#epIEUEXPJ>HC==0>3TOGlVl1JhUakC;Ynh?Lrra;F9&NXN;}w$^ z!e0*kJ~RKue|t9(=Vq693hT6kk|irs+Z}CMzw=v;qGgd|6Jle6G3W^(A@MO0GW>pM z_M$7FdPP^9%eK9^isAxQ)aKqeE>fH0qKjST3yntVmoPLtHFmT>Ne}r$h0oiCimhNM zZ*8$wI+=eulwcPg`0Q&)v@g)bS3`ujgNMRTT%fplmLXEvt`(7q zJng#dq5$&ugf^ZkU&JyRQE^8$oQ#943tnw#oTZ1gyyk2dHN`h-$zX^=;r2^z0ah}0 zg@+UZW=sKm!9lCCa$}(6Y=bTFX+(CN1m3}@B67+DjyD2)ov3!3-81VAkdv@pnzcO1PZsSdP({o%`O=F>$fl8-V>@B__*ZMtmZ^o zsrSMA#hHd3^R<^+?QrwLaGI2j$!tr9-eO0%*xQ;&d`syqTVd*lpJm5ybyuZgQQ`0| zINSNVquvJUl0FXCl0@0SQ^ z5O*Fgm=03CjdT6Gnwi^WMX=q=?pH&A&?^@39aHq=#yfk|qOaYFd)G7X!x@0Y9z2!G z^}(5a>}dtDK!EAMSLD_}6hi20slBrqF!|T$)2k9a2Ycw90|eZPGj{gaZkeD{}4m2DY;=WbbqNVd=gj=KK1d0qYiBn#P+_NbJ_|fD=5+D7Ua$VJAql zgS2$C19dunJ*;4$Ri|$*?-|m%mt7n!Zf0v}c;!Y3jdR`gn3AbkVm zmS+`auf*93hcRSry30hn6Dndx_K^YOOBnUdx^XYD6iw!0J;-HYDzD@8+bt1C5Q&1MVUs59JiopSmIXXQcO#)#;U^J@3@vl&09RJofmUltT_ zOO-DoSsj&ywFYSyKO`u}j=O!-=TMaLLuRj5)VVobrltlozb9s>Em)TDWATLiHl51X zD3@h@px-Atv$Ef>lbiC0_u3{qBR1Rx$=a6@71R2!PZqk#VrfrU)+0UHvJaj>A3I<@ zPQ-Og2h>Btx?8l$JhH|B=d_w z-{S6q?Lq~-j^eqlwb1pqVpB-C6O=-}!V~AGi{P@}E*XL8+6JKz>VUe}Gt%37M{LFh za@0m$DTkZ}b7npzi$fC#t1GMi0)32xbxpPkQ5>f;{`- zj*##Q4_(4WybUNM54N!#%oh=K+{4kDh*(IuA3(|BH6ECiUch>1-k%|nLw>G;tX+<< zA~QMAKl_<|9`3$bo0_vKw|+*QC7oQ7{nngDxD`Z$8J0N{u%}FL$*vehW%M_liPS zOX+?6+>Rv9yptsGh};ULEuNdiC1VEODls%xDOudP%ary7ze;P5kdKu+-1m-9?Y*b) zaa2Fap*zaqR-PaO{5vYft+O-zyCYViLuVI<-3aTJv6QZm^n;_)!)yL*Y|dO}O%%S` zG`+pv@tCmB_LitxL3{Wr9XoJB(cxH@B-Zn|U$VTwT?4g5pE;;Fv?7h{P!?)b+>#Lw zTQp=lqIq_)UcnnlMzUD(2)4Z{ilB3RAqe*z&BjqcEi0utiz*32>_pG-b}Q5h#WL}k zRBCbI9)ig$PfWn{hIV>W+BZT^eq_u=-s3IF`PR*!%1bSwa;`q6qG$YfP_%kTKSNv{psKR|)svr4~ zk(8-B2VLVBUcWvEVkTqEe1~9F1VQo4{lZ$3tepvE_v(Ubf)`NVm0QX6uK7JLB4^I5 zH?9bhDJSKA8B?~{g&^od$p)LT_-Y|tZTN?yih__l$3BcvZVq%x6#*pvgg`#fn(_OP z;-MtaU(FU}22rj?#Y%~=Ii!AT$PESyH`G@Wa)4MHodVJc#39sFEe z0tUc06Sr`8O7o+RTi5EveoKeFJBx9&pv@YAzMJ-VSuVOh3yJJxjXE4xf8qXSSHz1b z5^_qBEV4Qxi0;BjXd6cSeml|_lcRw8La2Y(YKD}&UU*UBGnyPpK;3OzQDyw2sSw^# zd<>Wy28b%P@7}QS%XbvH{LnB*Tle4`g;@ZGh!b+YUob4LmWpKz)mwZ-vDzAnRpz`y zS!Rnfd$gsHxVfz;+r0;2jtFy6d6&`3|HNVu(_2aDpQ040`a0+Ga01E|!tcxZSoNR| zMPdtbkN{-;SR1uo(_wZR@s%ozW{P?nClN%hSM6A-JWrni1wsfs7?LEP(fDe+BnT1u zwIvO9%beIp?xEseN{~JH4&(y5A{xm0?$|$^@Nyx9KCLrYCbaJsj+i+^g%jlXZqklh zhfygU=g>KejJMt=Q3K7i_x>y-a^7=(9_AB~J%Is9%J0wU6Z);;QLa`OH|6FpXR!x*}Te;2RzhvwPd1Y zjebSdNrXS9MM4`X_X|_!`tR>j0zBfmn5rAfjAL}chZQ7IK3y0_y|Uh7iA;c!XsZJ4 zwl~8hOkOK*+}zY*ttIas*P85FNacYMmab`jO&X3$Z}b{je04uYh3GvYb;7neL_G60-DowmL~#Ivy{M^Y?D;mP@f2(4 zkN0H``z84;Ey3GM<(po{NVR463F8=blI?<$iep<6T?jMUUimIKaGFoX!=#&wm+M{n zAiTfdH^VhnshtbME_mfQ*>(6MQe>P2h z;6le8uLry_rnH>E+Ra?xL1<}8xAnSQmc%7EDG;maDEY1G59gj2a zGaYIu4iPR%niNJ5@s!^dyOd|D1`|4L^FULx&^w$*;iuNgnB}3vp}VN&&Img~PFl>v zKzGK5HT4f+IpSE5Y?mesr#;KpO#~k6`|+ImIyUO#vS+mJ>MdBSTZ|am;qw#+x4f$- z5}r#~@_mGn@#&popd_O0(m?gWjpykPvQhFz=P4L0M8Pm#Ovl3?wfEyLjz}0cdlRfS zN=vkZ@~IWP*<)nf@aS7L9n3|z{l5U!WaH*rfNA?yPNLCR`kLZjf{_T9d7U{d!V7WE zG^7^#aq%)!hi(RwI5oWeC%@o098U)+Haez+dZOYR>WIv%<8I+bWh6x&iZSBXo8ZgL z910v^zw`dwTR4SK?==@&e*iZ2sIs^s$sQktXyK9&T7l zI<>EGsuC;3X4`|o2o=(3i-cW122RViii0?kZ~l>ADocpowbJZUx2Bv^A1DV}{EJYlKNIpLtD7m_JLR%kopb_+3dX+SB@ZngW> z(he%LiqW_c*M-)D-%Ga&$fqni&}|yAt-ph|HAsMyus)>m--=A(Czf2a+j-es$Q5>U zl=U_BD(rPALgjS{mF|pmH%;}*Y@TC7#9^~3gUGeCI71q&INN@7wEpJ*?JIed$nRXR$bA80N6GM@l@9{)b`pjYOa5ZKoj8du0pgL_) z#Xla8zdzW!;JBNY}k9PIm^waj5T4!BakZ;zUjuD9Rs$ zVEDN)WKKmoY)3^D5bYR%4nH`>WF)CbHTz2lPegZUBpAJ>uC6IdrEIDz^*Ou?By5gu z0(dSQ&e<#c&EBt4gLzsDk}*OE>ZY|t5Lwz@l_!{l!&eM3dAI0v7|)~gz%^I|(k_Mb z%h2xi^=1W7AT&ipn<7}D+xeZhAPcYQJUg8m4wHU!Ha#=GW?PV@gKMrT^+=-O;Prq* zaJGBMQW011(cmPD3)dxK|0{NL1HEH!JmZKC0b|KF*?tupCzhW7w0`teUVD|IRTXhWty;Op^FoAExc(f*}ZM=#{(WC50BJMx(bmQ&j z#fGp*i@4J}jZLVMdY6KSrBkWEd|RP{SqGp<(}D}Fry zC#`^^gS3Q}>30XI&%Rs&fSJmpTlSJ`W>{gN4a`H&-OF%IFZUHIxZi_p(Gd;|g3}bs zLVgV4Bb;6%fsh5DE8^qmsHmV9I?}eqK>y^c8vnvq|KqwU{2Tti^HubJ@>MkpGZT9= z4|@}L3l**Z8M2c74O!3s6|#Pu0N}4|{)VhKvM}nTT1doqR7y6CL}}w3wFz$BgDo8P z3Uk56MZC2a@(3~dE|VPYUw*!xnnyH6Nm0Tuz|g`3xTMY|LU^M9YkJBK-4}gNh=#$R z+J9j&Q#Ks>VIi6=$U(n>U|WUJL+eTVJ1?B7(943PUg8O*%ou8rn-eh1l>NeOn}lu` zS`9U_=$+YmL%6AkQl<_J*)6Bg<8AG6tt7d!3T|#h!|%T}#`ls%I((WOji>t-K0RWFC@9vtL*8oP?@b*sHeTu@ey zD&{*};g9Oh1DBbAUk5;SeG2M35gj~$*w&1cCMfel+37FYYbD2E4{-f&aa7T+34 zvJM>+IjnMT7{uf^goQpc&=VBy8vWm5?*ZrC$WDWwrLr5TqKz&{kU@VW@<;qjsXS@@ zR>iMqTq!^ZgOYgIyZ1xY%M@TX)ddxO^YW$kjLmk-v~!6`8AfIZLs}loY<;%hq6X?Y zMl~rIg2E4E`e5M-zL3a{a`Ot*ALr0qQ!xzc{%Tq>Q_*_CHUtTBpAYLYPES=d@G)_O zh>X^!RsAuL@Bsr?ZGe&2SRIhRz?tKlYA~nYf~WCBK4jbC*Xz4bT&?SI44Egw?W=`J z&4|fCs{^MD`h)ZC%U=C}v|`S@iTL7xYK zoi;J^rvfCM9cO3D`tcwaU2%O~uhzAyhW_*B8iJjAENlXLiqtVL*_{lP0SvsA98w`=)=5Kw1V{)_D5xm(|K5AMOvX z{o|CLh#wG$m4hA#d4-vRX>|4ox(e?ROgopi7PeHQ+TRac;IsHP#OaaII&vbBvlTQ{ z>ZnKxWDTOWy3}Gf#$`_zX*hGmGbcC_k>Wd{QWBIOTa>KzNlxGwiXR~<)-z&GK9FKX zXG2Yy->uIMMQ_X9Ii=Bm?v2j=%-XUa@7KqM&_l3{TbNHXgx;N!Oz%@2%0BLuIAvnM z*!_ph@Tg$g(9C<$+4_0wfFC{NZA z^jRF6?_u9V4nVkX$&PZuKJ*Ng&2T4hklL+Ak=-kd2ZfaJ&IAnXl**gGmyv$bsD%d%`@ChtjG|yl zL`>leh`_>$cFl#zBusxI3g9DKAJKRG_;O5D%M2H@(4^wu4S)=tIj1T^mykUm%PID( zum_iBrF7^!n7TFmK^K1#KWRk*Kd0G=_n-|bJdM6~$F4|4fx|wQCH1=+gtTi)+el20 zCR>o(nCOndH#NnjaqRZLNp9YS*_;*KSG)(giYaX!EqQ3m?3dwV^>SVf+OhWh7C<&J zg8xPy3FjSWws|&(V%z?j*;VTtjGvfbE}eW`0fB*lrgUyVE*0sDDVjc>xmm9lVWpHC zSOH9Cl24QnC%HJ#WV(5DU_@tz3Lfk#PmB7KGf7Yyl<~*x-j^_#R!Bl&`*Se%&7|rJ zKT34ShqzmKBt8Qiv+P{}O{AGG!tU`-Ecr(*tlN{0N=`7&)s&Y4#UD+XkoAhRv0zBP z@FtM+JzAjR!`8t&_e?Yo@CUkDe(J-e z{mn%G&&#dZFbCDv9;i$}H! zcK$h0#Ow=|5Fg@?ld5&#gbLt9aR@~!>dqwVQkd|*u=V{)@AAKFi|`(ZbX)5Pk4xg6 z;Z}S#lg~Ib+FbxuvO+YYxt?tMeCRzM*X)$#4M6RyU4W|(Vf|OW_|QtF<=ox_kzCI& zDaQP&GQgPEhac8dKti~hdB;Y|hatzfz%jLD!Y!`R@8Le|c$+ZFm#LIOli>?rDUF|t zbE5*@+V|@&`iVdpn8JKq?ZnS4Y@0$q?)aF%JuZ=}loQF=v-f^=V0#VkX_V4@XquC@ znhO9wT`h;3EVCc;N)HX$aRYPOIgQ0(`SD}T9zqPCEsI-ad8_0eM%)e8xRlCYRyI)I zWLDEcVRZcyo7ZtBN@63?A#4#?C1$U!rn%K}c+KZA6>b?tGeUxgkuB zx%|j3>laqThfKLM9ToTa!W_=)2Sk}5KFsfH4V`$(HowbO0^}z+_WSO~K)5V~akfox z)Du!pb}wnyB#=Oy>EvAHaj?#GFhplU(8fIw!ZthQf4lb}i1kLL8A^Hrci4q-T)#~A z$jlBZFLXN7Ys*v+W?7n#NAVSn$`)Jh7lrNLQg*Q}s>MpmG$67?2<71lL0}D(FSP9z zsUMt#vF5?Y8pWAHEYTj+F_wO2c?BT`HZRAue&>A6|8goYUP$Y0IYO3khfTNG3&eJ2 z9OciI@p$%xo)bbVTe2X4$s>y$1NY7eq$4>bz=ZluxR@7Ime`z#=_UgTFywSJJqA!^ zC2+MjPNfuj2PpOFl`({r7#+3xFgVNdx7j&sB@GSzk?A-nC(Re4c3^2$krAUWA6iyW zaWMMp=*##Z;kx-Pe3q=TX__t5l&Kz>Xm)b4+N15c+B1u(AkN;um}M4|U9tO^0I+)m zH{?i;w4f<1VphCUp9#A@i%6Z`9{xF+6Nw3gVM{K{Or-I&_=U@>3tS-9B(ePDHABO0 z;NME_02_4C@wXo=r|TIBSHZRwS=y6eZon4juYpAAwn?HnHIUK#iWa|T?9NFLnSgOR z#I{i$m|;ln;TBqfxu~ONA{;X?$Z&o?z-jCe2(=AB391g-hTam{r70LqGEQRk`-bL- zY*2c{mjl%`r{SDpQ}p`;dm`5I1^0d`&qnHYeg}P#NPF|JhN0k>l64#xS!m1k%3#Z} z4iw|bX!)d4Z7+rz>N;#n+N>6xr6saz^ZV%$a|Rh4aj|Hh97OKZLhJPuZif-Gdocb& zM4Hk;Y15(m(6C!ULeoy7YQ`$Z3=&4vawZVN>~=MH+g4g6@>y&c1uD&&morLF>00(@ zsWsHwJ8&Pm9?@c(2eEFc&^5H(9A1*a#0(~w^)(C|{SjN;h1z5WgvpzJHr>MXMbX%! zopdX~zhq*Rd!Y!6q_YSH*M1Z+BPhhlh5U-csQL+R|K3%tgnHpeF9Xb{3|8Z-v&)Tk zc5~*T_3gNTNqy@{W@0a$nV;e+{TC}u@zx#0lNd2O2c!9*Jz;>aixiD-!rN$@wrIi; z5@nF5nn3{<+T;_7UPJe4-jXnmdy|!DgaE7EnSYog{L zzM6Z7(H4J-A?5c`t-B%lgZGy4f}Z0u=NJ%tuGf({Pcq@-%S4Kg=r-EN=^m2HSlL@u zozLf`=HKi3CdPmR!%mj0X?DDlQyRuib=W(2+POGL*Fk9-~2+)UnjLup0dtU&Wu8tbAbr1BjJbFiam@1;4MKbHdFw{Cq|O7Omu1k?Ia z2LA?cgf?G6iJpaP7x7~qMzmX#-!=>kxv@}~dp{CA-Rh!0>Zp$L)j*{9ppcM&Cf&pu z(((6&Q>PHXWYImPmL=^e-k&a-I)4x1VC?jT947*6i#S;@iT>KkbJvN5^FWw{k)_T( zQ)gcKo(RUzpVQpF{(g3+YyO?7dz-@TCi>GhF_C)OkECxOCujaPif^_W%mE5GCLj`h z&)10~~ep-sO5(BBc<1&PLHhKLiv+R`46YYv=^brM0(S>!RD2=qL^l3(Cy(jZa<+8syebCE}U&)sf^chloV^<;c%ZB9=|D& zt(kH8cNICc zp%*F4XKzi8n6kRp9Bm>#YnjJ6B}$&rRAcIJ92ac$p3mx4I0W&7fP%1k=>y-aaN|>kI05N7p&mSM}RcoPGpeKWNdDo;7h)nt8+iW4)i#wv%OE!Oy%vj z9Fkn{6whyq&W|yT{6vtMtsX({8Ii7q995)hI0)aj`KJvGqQQX7Lyx%Wxw;FuDx`g4 zX9c0SoHKH*&{mKpjl&M*6#n`t4bPU-SCTXa-u7h{GjR<~12ILP^^&_*7%fg>fPC^a z%d28KrH!eukle1WevkbG1NY7$+Kfh@+K%5fpl|L_biDkbrN-|E)~bP3$G<*?$a7+v z1$}1XwBCm&wwN>h@02*2KKs*iK1O0?okUp*<)=QcmgQ)g(s9}|B9w2)@KpT}t)Qkk zWL_&ob%Y?tg2q@LHuxHY^4z32Zhk`?de^kEXKr1Hfz#A~r!l#8+;7|F8QX+ftuoP8 z!rfrN8F=5*Ki#D?uJ;=N2&uvJIZSpuUo#eMCSqhAQ6ZRaLL|+0NGbHwd$QdkfKP7- zZL?6P2lDn<8^isQ*HrjEJU6JqZZew?2FIoC5t1uPbBy- zfs*)nm)dr1exQm7I0uKYox&jqs8TU|l#tMw7N3Y1w^Oj%6KY;2_9Op=TUzg8D8!8t zC_ZtDf`89nW5g)P43cdXnY65%gKE&I7W?XNusGX=69)m!v zW$V3t^TvysD+3sPsBzZJC#^S35UmLLJRtkSc;>D4hB{2Ak=5$?4Ba`$m|n`pSZ<;K zDdKUII43vY&*;esBkEc!6S`z%v6uw4CfHJ&F}z3cEv^w_&_xT7-Gp+6Gmu>2z)cG8 zBc+Zg8w53{tM+55=%Bt8eKYU2pbj*^hEFJmi5Zz9*(Wa;Nc;d6HEP1YC8pp>2n)uT zdmKE!AMfw3M{}$tN%A{dQ!ZXg6n%@LUvz2!_AJsv!bM)Q_i4T$mfUs6d9eyUnXJ$VtD)8kk*l9Hsg{F0i^#=`$}?;S%Y~IOM%dfklE;EA0wQ$IE&UtT-d}0{1UP@ z7)EkIDCza04eu>}^K`Bf$PFjZw(vEt`A0B%=p!HtT}$w2gU@~c{lX-Ye?fFjJWb0r zwv?jR0wy^pGx%5f1K*k`h4`W165*dcSeK`VwG2WHxMdL%=TW=#oTlu{#8CzE7H+~w zfq33#ANqlC(UC-sZxz_Jlrt_^=oF%!c;Zhmo!+-0-J-wiVWc-g4F-pp^8Jg_LhA84 z2BAYV%V!B}BIwOh+|w?>dNetT9TIha>(0%ff-!qz)8wq2yP`G)C|w9w3T?YfMyKfU z)DJYjPeIGb_Kd($QqR+$FhAIIq9BIt;n;d}nS{}9i#95!eB*S)Em!D+E}kYIKYy_V zkWPolCOpfKrv|cK2^CR9~mRrP7O^+Qy zGi#KRuS23)m%xWn8*VOQwvF}PgQp~`ezk9RSh>cu)ugSu!%LC^xKP)31ld?P?*)%FfY%;vaEC1*8C?}@Xn**uSKDsqO13Cs^ftBp-nsp{nnSNE zcs{vCgO8jlwmI4FmLcH9w)lm}D&Ag&#@L{RAJveag<2_9we35?k-93d0<&Myk-*f| zKNH2{CO=a84TICWeQ}2QXV%=a3W`DkAi;*zw2}y#YT%ExDZ-2!)Pg2F0gowsy+h^R z@JuHQF0&pRAABeI*KtvYpP-k-@bpjli-oAc@h@~c z7yJSAtLd7_8N_9LhsA{ieElYnyYz7dWyWjHxT}%f5>>`^H&h?gHObrqBW*P-0m#7Cbvyx|8*7G@O|~;%v-mWXi}3V4o|jCr!n)1$`zAU%C3Kark2O7_?ME}EBEh@Q5M?T% zBao%i7ZwceO6Wb}#^gMQq7Jl_RBSTvAF<})5Bxl2peEE`uLNP9{y-Q2(ggGrjDf>7 zNnj6i|1CJqI2eOpu;n5=M_A@GfXuOBJsN!iEg%sw$pw#I+n`!wK4y+_%#IG)R!q8{ zS(Os%9ir`ou;Mego_AASjqkBaf4|b1!LWs9QlOkvrpy&hh@m`2!h>Pafu+hqILw7gL{0(Ma_*V9~6cmY^yQHV~#tT zk9Nxmw7tr0$XI(%kCXPIB)X8sLpP;28hs}MmNI{f%rp9;$}c=J&XPV|Fm013h?g_~ zF1Vq=SJZE8(aX8;sP;|vq(+x`Pa1IXm^ogX;XLUi2pOL}s6x#H_KdDTHeNCclnBg` zCHk3J;-xfnJb3d?SE%jpILdDbJ3ucYe@ft&px-idB}O14oFctTt!Hz-GqJ6Eqq;JQ zgZgRZ;!B4P+mtdJM=gkUtt?9lb0DzEuhJj5jxJA~>efziaf&rbxZUMp3j=mNW2Y>T zCvkb%&2uF{;PuoX+Ukb6j;XWE44~ErKh}gjQB%$(*|hBtctESAd231=vvN6VLzDBZ z!>r$2t{8-l?KdU&)x%G9TG~eZic$bb_qG`#SCgVQ@>!?D7hk4QCY0w zF)=j8R9!6peFru%+)P@OFlz!+*}wo8MOB+@#r)QyOI@BtvJ6qqslRF%TDe|VndzHF zKuc&R>M;kMqc^U3RZ=YLlZ$X{r!RpQ9t7bU+Q6IhT5RuSvuH{0djfLX6CFJ$N8G~?FOUvG?A4uUFcOb-8wn_{bE%Xd7-EeyNGQc zfchEERps$iC40|K#@VC5^w}>$GUQk6*tJBqrsE2p zKAa{T403){yy26BEWM``;lG(gtq6RnAJL1u>zso&G;ay4w~=E4seXL#UGLgYcU8-g zLvs0Qa_2o&S%+4fR{%rg^Ad%k_KAw^;AFGKpwkYV9v$M z=36#POGJ`I4jGLs^h02gxDfON>)9y|rMR#;5X*_}x-)gh0)TEtk&GDS``@A5 zl<{dp;+&y7ss$sXNx1|dojyuV7BApKzpP1(NqJ!Uv0|-F>Bl>-#kPZS7#P@B-+PdJ zbLA^F(QivP#8|5(so{oE-5)UeG1r)sdN>6gQU>!k{>=QFslwF%gQ;5lZ<30DE6D2yQsMUB1})h1vj;#vGXp&mI94T|f9=2BQB(nDu`M!-f5KVYvS(OxeR-+4BEK z8_wU_aQ{`?U&A#2&;|}b6XB$K1H<}jdcwab(fvP4lK))^yrsC4tE-8do0Hl9>>BQG z*Np$_nh*@Y^7o?rH3*QP35TZ!uM8B(WvvRY*kA5GVp?001Ba{zlfQv;UAI z_Sbv_JW>FBv;>rfhUS+ad_B(HZBs(-l%GM37sROP=-l(QvXd(}GYz^=JBQm} zhwS`m)fE5=024s_&o?i4R^OT3zWkt+WIS{+bI-2r8~g&XC%!mqDvOmG$S8tSz386% zw(yhd>^{bon-9SsnLaZL>8TP{%uEzjvt5SDx2t9t5WQd&D0(so^6{uKuaXt321`F_ z?Q`97Oe9(#pvR5);T6)zDxy^w-=RLjQ3EiZmEwo?EtZsX`DD-}C1EYbcL9CnyGBI{ z0-{_(o%Q+eJiN|i)5ZlFjI~G%=rUq53&T2mqr*uWq$+G| znL6`gfCzf#ng!|6sax{K2I5P;0X4j&Eod@%xT7RX2K36$bMQX|NcgnWTXBs;CM2445qvClB}nYKEY?{C(pXDG4>T#Ns)yTkwLU{S&l$ zB4}dNBKMNFzQ`Gn8bO&P4?f0Q=58>EGeZHX!9-&PV@K5L%cHd?K}+GNSbt{LhXCwy zi#3s-{yNqwo1Q|2y**@w?!|8#4}unZ`<^(g;DIC3chh-PP1eo5ta--%%z}Eka9l|gFC3YOl{w;R?YsX))g9Hv}1^zR3T2Tmr04y~LewGsZmG@)&PGku! zB+tRYpj-?~TOJ892uHugC_%F#t~(^<7r)!QZ5fB(?ebF3H6%e5s$h`u-Q-EMtN>O3 z7och!tk7?}crSVJ;vD}z-Tc??w?5Qeuje+c1xwBig+VR7Ib%$67}hOEln=~y@pov5 zudFz`O|xjhr{a|sTA!YuwpdXE=H^Jp;KoDzy4(KPlK8nWe?BE0+z`A+F}Nnf?&W#09{-Cv*S17YH^fQk`BcPsfQ(J8HHxi z&_4O3CZiG&7#JE0ID6o%s7Y~P^#i5CNP89%Fh9N<>9t7i3_5~-Kq_6PSF3b^XnHN4 zz6vbmC`gR2VoZSN%TcH@)n(Z%E(237J)sj8gPJGgBc z`iw<9VaiopV-7jGo<52&$%&o*?unrV9?ptCn%oRnVJ{@p?%4MnXC{X?7d1$Im0U5O z3&x*}T`XCAaGH*?apkng_yIaLkEsfnoa_peD&fA1@RfcLd~1wirdeMQ{z zcWQvwkg##JFmrcu^+A`AGGb%r;$-J$<>qB!XW`*tp?}X+FqVH;p7dlnXwA{W$m~8Fm(d^ zzlGWHst~`0euhPNCJ|oqXPlX?G)v>%DB9I;FMmH&w=F(AD2@*_>4L)aWR#4p^SE$K z$`=G{=+oU&{V9I(1xuteCZ<;O+I#zc$ICW%IH4V%6{cr^H%7Y(>|4 z_DMCzR;0^0mJ*AOR<&DyCbq%~zKj7WwGiKQtQRY#L#hVylaf5}kaQ#?qL_AU9 zt@C*{-VJK{0uOQey}zE3dhH!5<+zgSrKij>7Yz9%K&e_iC}^h~(zQ|dOn-cfXh7Rv zhR~g(e1R4!zZUt{GoRmWSM_3ZYI@CCs)2t&eYM4=2NVh>p5(@KxV$lidRDc$xln{m zzj~(|wSqh-@l%!UT`M?MA2`yP@Ag7r;FiMpil3n8)`Jm%QF7|XAjyM@=uTRvgG=M?5L^>9NN^AC?(THsE{(fn&V87w zTk|x(Vb@oCt%ntx53E0NM)q1xEK?fkg}X8eIkC<=Nr`6D3oq_t2p$WtrWI4iea$rw zQYkMCWK?-g!avEisKIhtJ=yX0QG@-@)M6c}nzOEpqgSP^o~D>jh?K~;+A61qzwHA6nEL}i zn@R%6+0_VYU&Pq!YLSJ@5cAT)@;yn$rkuN5f@8c^Fti9=*o^ zKtR90GL;=z7BG>vKjdAOD#-(eA?m$8T*d|%Bk?)*VOMJ`wRkgRrW5VXM|R8RDq^S}t`j5*(ZQT<9NJjj%QUy1_bqP7xZAD41#-k+pB9d1y*lW%)uY z@Chdf2EAi8+;_8fuZgX%rXog?Q)B+Sme8lV%`~MNS0ZUK?RH8_kfx>d;B> zyRQV!zJIXfca`X?8H*F_Q(LzRK1qrKG%-2yeGOCa5)L1b-Wn4Bqg{^`#aRE7hzSN- z*y-;;xnzjtZe6XbtT_YoPoC|2QdO;vtA&?bRi86-rD#!^xfv!ef2xCvQqiGd)@!`>fxJ@58$BRzzyA>E`$xG$xI` zkFvYq>LoNH7v-4~i2R_NnycLA+96v)x~KU5C@dKtwW~6XsQFr_cQJ&RjJYt&9!AiP z#_k2@M(G4hyww|h_|*C0gx?edtMkA)e_NdYSJhRkW4f&8J!d>~yWVIgLhX<0icCzu z5963Bi`qtL%%&iTrlixElMsOK%phx`{+qe_s{@EYKmT^%8BPA|TiO5+X|}U^%x_dP zCltObj<4-cs~@yt{)W%_+=hMq@b{1qhUEA`Qkh6BF7#ybDaY`fC;HsxJA!zrIN|bg zE|L>uxVmRdjk3oLq)^Wf8b4TI9y2KJcS(i$z^m~v^qR`{0&&?bZ{n5&sD}9=Qty_# zl*cK;JfhQVvEVgrXs8gEmAmd z!~Y=IlrVF_rWayGww!g-029B*HP;tpgP&Obq(Zh!LA%f~*`EN_vaqj!p1BagyV?X4>u= z4yT+~l0<3I|L%uPgCoEyq)imQo;@iILG=X>(M|ns-TUHPlTTzEyF*yTs4snWz%Lib z&CzaJR7>P=(i<@et5c)%5Y5PKh{9w5lWjk>U?GWelW20$YprOHJKrfu3`GYs>^We& z6<43iyb;g$^7z^dMgCDz3}nK)npma`;%qjaPea{1l}R9k^GQ^xWrP=|B|E7q8VS|u zmQ!~pu7ir7zjYN6y21vWyXZWbgd=ybDxOPDM~mQWzV5fyO1Guxb>OkjB%ZegH4I`z zmwW&EbRzoc9b!SWfl+9Rd9VS%{+i^b&7fT%8;o&1CxTO zuL~QggN@e*8vWFXMYvbLyG}2+(k-j;9?Ee?2byn5GYCqjaa0RkMJ*dL9iLxk`c^_R z>rNVh;$o7oUW!D0A zc6jc>^kCQ90-FXuRN%JCBCmcR_TB0vnT%K6%X6gwxhcWtGtZnf<3aeTEK&~a6$!cH zIaheWGoKTSB-1uWfL*XecK~K+gXDWT-^F*p3A#NUrkswt1(IX0_!-V3ylKI_uxszN zir;+xAVgiZ{uQpylK?;GmhQ-Of!0}y-!1jYQ}1>~fK|*1b>YRdvC>2jwzV%!gMrco z5}BRou~v^HjKQqy20t`wf^1H4rzobG)#m4!{VTQdNUnyFVy@Vv7W*Yj^HECnflKKT z!7WsXc+i)e^>C zxxbrEZi~&jELU2k1JLY+HR#2N80!aU%E7|hSHwNVwiq%QJRr@=-G8m8Im$w%R#Dfk z>_R7Kb=L6SOw%^!#K;PpTNDkp^d&QVFAax3c^zW9Izx>>jmZ9To2?0PeF zhioKdcH|~UVV9B1t)gX-Y|Q%W`%PIw_lKfM>* zMGG^G`aR;)eMe^zLJG+Q<_?2lb>*tdj^a-!0p6rDOURUr@$M^OP1h~f6)1_puO}B- z7+6w5QVlLzUHXBje@)!Kim$)XoTAX+xXjG@_n``MuO4E@vojlI(O8uGcK&-{}$C(n|7mVUfuf4yA_v4E^|e0HR=?94@$%tscg02 zVBt51#e%&I9r4bR^@-yO-;@Tv(%}yBbv^&Wz(B!ywAmh z?3E^=AB5aW+215s0A0R_pXSw9`uyaW5UH~dq;bj(eo-T+2NGO&jN>$?hU6q>C*@%D zZOI@6@q-u&s4t0F-tu~RP2c(xfcQ7sVfHfEmZX<5Hyn*EeGzXMlwLb)MZRutkvRK7 zpJ_2ahvpT@-JoHv-=Zn&hveTf6fWzf??4zZHpHCRIAkA;`|>=|gGLFdglpoW+?i!} zwbSa2e@ z6FjrS06&H|Jr?}V1KH&+Zoez0wSaPz$gMIV&dqmD2i9%t+waLW9zuM}&e_=FRAXCa z{$O3f))lEjvlg7=#=yUOc0-$o%TPGyR!F)>1M#?0Av)%v6d88zt_2c=O~|`O;kPr9 z3@k%%HZ-E|c4_g-!W+3XbtLalYl9xA`j=#}Y3HCn7V9BB*8LQ<>`iIO0f(uOx~EMG zJo+?O*J=l1VvDMvBF4#3?$Ymir8Gqa%@uxn1Q3GmvK+EfB0?{Xj9|-eIx_U^eXPZG zRLZ%>SX=Kb7B7|%%14VMAaCnsaF`cvMjM^nd1dkr#o?&QWb&3ADH%mtuPNBF=kJNT zkn09sJw(;)rXG3F=A3Hf3dWJnXS%-C)k$ea_!D*qhqpdOJ=2w*^nqh%-H7r+LWHe< z$}bU8q+!*&+zU!*U}Tnf{75?)eFq%ujJ6>t)7C>zJ4z@SZd%jP{0c_sq>#S6L+I8s z^r?EJLFU9gvoB1Dx$A*}@FyX0(#N0R-7vE>!Xk&Gov|kl_6fo@a{=j5!9T1%0&p87 zFzqU?3sCDs@ZZV7DF$peI>cCD`G9D~uXY6F5lgC865!m_!8jRe`4N_&hIcxm$0w(C zA3!sv0`cYigRXdijM*mPlG|o9yR*`aNOA9e3jB(5`6Mdk(uX~w8=mtcPyKQnLVw5F zP8-cJu8u<3(nhAwc(Q2E&jQR6VV8Mek^33f z?>ATPLb&v$MiE&CneflHqjByo;P<}$$zl{|487Qy=f2JUcwb7L?i~8rpCkH9HcRGC z4`pQPOpPbgvv7Q*nN8osh9W$r?TEvIzA;$-ot~Fdl(91emqk*fma{4U0%g<%p$&%DGQHdC69l6a8Yf&*i>AXv~#N zk%u?Gd8}7+{>tw+>Zb2+i{v=Yp7$d5m{?FcZ|9|ae7)+N8lTbfII^O5W=>n22-Zqa z(eEhan0$m0+5DCek&W~s|2c9GIi8b{<(M}1(X@8?76(4CSmOrg)6ZJQ+ooO4czH(lgVw-pf?K5iNYwsgKZPBKth?2BtBuCbzh=}g6}}Jthw3o$>K-6VDKR3m+kVJJULWeN0|Uf~B@1Rd zkK2cGq?`nKPsLp^O|vF#0zZq%Cw8S9+h*eL0xPT3+ipblISzev%5PieObdV9$i{zQ z@E~8A{N8rL_omQp76@U?%yUw!YV&{!X zN7U*giAL9v4d?X&dzmoJN8XmR+F8`c03nipwEuL)pznXLX8mp%v6a8*7mhvj!}`ps z5300YCSkBIs*(4~V0w=Bv?@k5?Tab7m-h35oxCh=r`JiocU?P!_uu@EH_Z3QFv@gr z%#Es4!X~=f^HlW0dQXDWR{w7`g+VuLP^{2vcjJlRX2JB!tfm`7RL4K*>Jh0qa^Rd8 z4$GS)i&r1!0Pb6#$W(%-xy`K6n?3s=uHUbaqX=8@9Lh8wS-Vk4xY|+ty59P#5m_>e zfwVv&-RU>+>OE$52A5Lt@;$sS^?#@;I*`~8gD2m_!Vvv3InOmWCms6--?jW}ZGKJ& zdPKRO)wG*2gboTN$ocaad9i9jb$*^n>9^ePa!Mq>5!!(0(o&4(=G0CSwm#X;25hUi zsyV1DUkQ>+%n))KPNQH7XP3IdcdjbQQFkBfYy_iKz4~Z~##9`DTp;N|&~MQ~nT>tq z-VtOPz-lQi67>>Keu8s2e_9D;een`GcZrr+FWK*xA|6=_j00wzDC_F1LL{;E zmsW+&fN-BOk$<2jlEv5#Vzn`eCLekC^*OvN)o&ka_-6?YSU1Ye%jj8#pk~~Mf^Pu` z%tsi_RSx=x0mZkPhqUT);X;f`1ZpI3{&83xQDf3G#b@^zbu`Fkxl@@vB={%tFu%!G zshi~R^HmJeMH6GZzF0zeBC#kqrG==u{3U)BY?$>!t%-bTS&yT=3so4K9i(n^5>dRE zUGR+I0e(E?q*;}BpU#Ez)z8xX0pjPVo#C9K)7-rMb_QmTb$e%J#X#Y|fwZz~j8Ds; zN$-yW@0G9+(?64apuS@QQ_n9KFJ>qQ1j}go(szDW#{!u~Lsl+kUumM)BhdXa#LglL z!0P30-Lggg|FJMN%R&Bh6K3)l9AJfzvDFBs$V^WjhQq~Lhz|7(FQFjS{8!kCtiV@h zFE#5}RFsryCHdFnhAtt9`M(qfsIv1T@9*`Q%`DtG9?^q((FoiJI`j39`KU{zKo`C8 zRO6JoPLg*m=;!3T{&5r4pC0Dw9zwOG0OP^xS2uNEHf^U3Dwi$Y2Z1=@3l5Yjz5m7@ z7W3bOYJ+EgL`nI`paDSCG28L+3hK0p+VhLuegpRMv<_4WqP&@lA{c^|os0TJ0WUwn zym~bnM;eEl@K!aC_Ch7peudn=sG1?zd^*D<471*t|QYeYbqLt8^HcZkZvc(x2=_?W4kuPbA z9(F{|m*3s$ePe6~x~@tsckB=5M}RS*wd7Zd%ALu5-)J=W&8ygV#l(j;T)64boYxr2 zNUmtu94**Zz%zDY|M9d`pIeVa;3G3j4TEiKUcnBHZyk%z5b2LeM_F7`g5(Zg(4%>a z0IBZC1x#ChdGA|f^}hc2oe6t5+ z)S1qUTeAO8e0ApY=r2cPznt=eu-L`-;Yl*NiyC>(HcH|%cjdAfO@gTXA|Hg$)9Tyf zzhaEt$;KY>jy8+qgbP__bPenX8-MetuaU*!hPgUQDbQ5(+AOaAN~>Rx@@BV{x>1xG zuSqX{+Gh6l1qr7SNI%3FQa5G6tXqv90(?d9LuBE9dRu$A8!|nWe_i5Ulf}b4Mr^yL5jiP- z?l6FeaSr*0iJpJ)FI4TtJ}?u7>25y8u&5y$&GzC~^?O`{1mp_Ugf9vsAtGX&?>wBs zUtu`~%P96H#M&BV#(Ls{E@hFRN=ao4Oh12(1|QMNCsN5e!#Q6C_LZ81X6%6um$}vo zd4z^Q7)=eSSD{zI29H4Q*=t3MZiZp^KBDiL+(Xj@8iCCvCNc0kOlo9LXr+ghg5ZH@ zTPKIKc5>5pPT^Bj**d`2)6E;|+!5@Cw#8^8Ikx=(PuBq{x;Lfpqb$xQ+%xy6bUSZO zfkQ6%`{q|}5Q)+wHr`$LRg5!M&~$enY@V!CJA=gO=jA7U>N98hyex*f!VgOs5k&4_ zVB>5aHM)={;R~Yl$V{H4GvKe2*J;1&HZ%u33x{tHJx#i9!W+;=;Mco@$%R{Y!_i(x zn6nQmIPfW=ALRP+NiBBZSFo9XG;zCXbKcI34M%gJ`%=eX z$*K2E#~H!pDi3~AhzKSJq0C0o+T_Po;NZ9`72+%nmF9+SObbv^(G-uLq2ze_OO=y( zmxfU7lZ8T)LMs#1DYImW9+d_7Kl?~wE@s;az2d=`WJ}vYw?e)Va~Oa$CHo;%-^-~X zIbgwD!bLB_-Ak>&{WV5&>%z?0YGLnd`V^2sbE?+nCB}XHLqEFpg!bcbE&wg$!N|t* z7niSEVXr$)*CH9dVWvnhJLB9fJJPZyxW4kamEsm!COL%eUEsv&w5}~_!ET-EMriTk zG`E-P9{1CgNpzJ5K}-DD(gcz8LD+tZ@VNXnmAo0Z>_lWn!CjDR@fxkwvdmLY-~_^? z>x-r0zkr16%}jIQ)Op->Ho6t2o9Ey<&kqwax)iPP(Kj|@=fd%u{!%R`;}5K-xf$WA z(wflGPE4=yN0o|@WpiA!Pr6A6?s0maKZ$s`x-XOVS;;IfN2p5fWFaDGJT+mkRxnSh z#R{x(DLdHjoV&a>Dk*+E*@mm}pNif4!LZA z7f!+PIniUIv?4E(^f&niuL&Urqz+ivDIZUbmIW)Ht*U$BfMuID{LDRCXOklK@4e?A zJKx3BVUhMIRYn#fpUGt}GzehCVdz_;!Y&X^A;{On(4*7Muz_pBRwVGmO#50$J^s4^ z#jrgCcNMgWtJB=u9Lk{YhKB{6Hg;_swWQExb}_XDXSg9@HlC0$nlYr(I7z?;r~1^h z7f-Ltoi0*kp>IVil|4*(g_njhYeKqOY`@kc-DA~Ob)8A zOQ!j6veA@gZLJ|>{Zqds)P1UoGF3oZ&ZXR~vB#dyxj z?Zv2KG7v&E)NT=iez#1_wGu#lDnfwh#mxl8PP<|&=^DuP77tF`bmW}Bj1Kuj0p-`+ zqf6sTbl-mpCxE8M z`Xrb>5=*Z~)&H#ITqnj7W>357oTE5!4e95J_wDXYa%C!>os-X=vQ2m<)IR$LOBcm0 zDF|mc13VF;knaVT8Fs+Sob^!-nOMRT{z)bZj*3n(hEM4}`X=>fNv0J+=d>T!ePGPngC=@06hewK3 zAzi4Vj7?Qa-qLU#p?$%-)Qy8mxvtl?nmaF;kqx`u3P;o+h23&%T&Uq(4C(w`uuU^H zlX}G!JjeJ#SaQ56J8vwVzr#MC6U056pl~RNVKJb)(^YoxL5)7ZH_E7&-p|ri?R@o$ ztp1?I2DPt>B>Xh+$O-cw+?A8Xjdx8Ki{N9O4KaW=e)mlu0=5R(L3}2Qs^Fc2v;s;< zM$|zpT9ak6RdW*J3#Q;1(BtC5He48>Fe_o))_5!{%2(=s&H32Sr4A$IpThb;FnPx% zwo0E$2RUYXPoR3>VmfnE3KvPP7cYl>&7uNn8Nf(rhF(y+fVy}`4Y18yELS?0z&9Lj zlQC@VBb2nF1FI%lHSLa9Vwp0EU460lLfNJl17x28)|Urn`FK)}V(vFkY0v|nz&%Ox zslnzE!@ddv0YMSc(?&N*Vnc?7Fy&tI@nWL+zaZEqfIUAY(+AAjqOEtn&7YCp82g7nz42N`F15b^bu zz%hG=T{UntaNdz?!(-5IEADI-N^>*aPVr^tIAmzR6ty_;LcbA_XdcE|{)1WOZ)A!KdQQragr^XMt%RMUE2eX-4v- zHW-hc@vypUEZH?VSvJ94v-8boNQco_<3)77-veOKr&0^m#B8{ir z^O3*f_iMng0l4v!tor0osxdjfNBr1#)Pe-SwAH%$h>q|3H1O8;v%JHsx1(E}eSTrA zMd;luPI13PU`~iEhV&D3E>x9O9((KnqTq88`ey??TrWvHA5~q!0G1<4v#J@z0k91D zfe%KkjbQjgn85fK<*0Wb$~0_(Xxc$1HRxQ~$+M=+5Z1g^f7^`D<6jBs$}^Z) z>Mes547JCrjddI&9V~j9Kj#s8iL^Ij>{&m3@mqmyVgG~Dp5Jvxh`4sQgin!OR{1m%Zp-QoFTn_ROU`V3!blSfdAl+oP*|IP8fiRw`_l#n( z=zJ37OPB`%tRHcS$Oh3~LfVXoV%x@Iss|1z0G{I>(`V5ENtrtl;^&8NEv6yOZv1-_?Od(mY?N`weSVe~IF6;3e>w`b`-_EDb6 zxQ$j9CySp##lnfUzH@?ErpjIyIbGyzUGg<++X>9}AwI`o_sLmB_iJ`_0LAp}3&l>#m_(#`{guM+x7TInUuQzF60 z)%pxp)?LW7N8kA&a&5C4x`lp*ar*ZozIpuznFJ4f$2!80c?YgS6VAhFm%J~&c>SrV)j-r!?bXO#70FM1i=r95mh z3x;@2f)Q3_-xee8>A%l@g~9beWSSE|01odU)u~M?L#%$Y+8j{jW+i(y!}SBxs|ceY zGtp+4+~NIdc<6+bBVEKLkgyCt^2W}AbH&Y_@)jhEi$dEH+*S8~15KtDlMwj)TWO~g z8A^b-^in_=)}A(X@z-(AZLKfE;(ZT!IsZhpDN-`U!x14}h;@7A?s>h*zG2#vG#842 z;aXd#XnS2|JE}T7ooJ@7u2q+;iBLWJO%{T6nYPWX0TohIra3^dW*A? z^d{o0NgvLB-$PTXw3Psh=toMrtp!(V&$5kNh=&0)$v2fm;mP1$dWQy^!h#`N5>C9VgvzhsT5T*@2SE zkYMZ-20<7>OyK|${ie5ZoabmNKVlj`?54~7&wq-ZwT)3w8ivC} zSVgGp;d=?Pn_kc&YKY+m%Gygf`pn8U+rQ!>vV^B_>grml;y1@Z6ZkqpNvuuxih`AB zIS|F&wDbU&UkxI#zx#@p=ZAP0+dGnBF^k$Ub!In#|> z01-I;o{N7}vkD~-eylvq3&5UVEC>pz_m!983!Q&{IfND66S>*U$mU?iBf=%s3c`J_J>e1(;O42onVBAnPK$C) z%1$F%u6>5bRfBJII_H$kLOl&dj+~*V$?WC-g#6Tw(!)K!6&MYKVFFZ~ck(^X{dFMe?CY0QL3b5*6Ut5bbjkM! ziaRcw$%tyLZu_gJRg*kf74T30p&zCCuSmMVkAfoND2p$o6yJ_Q4+P+aJ>}S6Hup!N z5(GE$Buno)bAcoHe%LjRz|fyTg3~54=xzuIt9;mIL4QxwZ0B-=$#yyBS7!#LB@PWu zhi&^E3ywI}!!v~k$-{Iz&>L&7idw1BFa8?Wq0aSsG4fvIc7sV^U_j`+ZO*P1n1CH8 zN%&*=p%@<=!&7CE2d%)b!8si&g=N2RHhjOvnNx_bE`ewL7Pfs0w8urt>y5@~K^$Ml zd60d@WS6O8#y7%$9g?S}!AM|^(gsL&#T1o2wXcn5G1EH)yjAGr2}vl-81km`Hh z#cKKB9?M-<=9_GysaoRA&LYiv#a2S!?U1^ND!UP;z;Okm?jg39Jmp;pKiwpy zJ1?<%r{Of-&zIfMrP974y%{-1Tx%8115P-}?NncYvS(`C-w8G7OccU)Jm*+b>^NGfxh7+=i7 zgj_3GN**;QOdjq>@@a?us(=k3zZLb70hE+A@rJ!pcR$6&x+437eq$aKh#Rd7iozZe zK+q!OE6rV|-Vgl`j9B2^MZ8898vLmFLHRqMoZu5&(gi)GaKKwGc2$=Dp zm^gGko}ZJi7K2GP!6WL%e$xjf9|^$-zF8;fkp?SG;U7F-WJG$yqMu8xGzI`AxC(h8WmxGApfnXg~{Bh0*jVFVxVMMXZ8fl@7&il|n7&DDxtt zjT5w6uZM+=iUjF}r!T*GCpaW_&1M}cAq+YE1vxA8W2Sl3x}aR~hQ>R5@;b5tT(Kvu zk05R=8Qv-OM$?!r1(tjfj+gi4pedON;Sw3lyH{~Ufm$rTA)tF=H$ugr`{aeOZ4|^C zt}YI#p>7;kmCi;o&?ISO3h7d(=mp^f_=^_azn5;ofs(3Q+5K4o$FsO~Bb}k{?>c7f z`9#l<^-%Q3yM|eLX zup@-(-m^e|34E`^Qx zj>QTk2u~uXQpJdFdmCJRi7_5Inw1pan`tl6Ik$%`&QA%3enW={Z*qPwzj%$7zhrU@ z(hljbA(ig@K9q}?ddQAOsdoqSK1AYWTs#{=XHa8v4;xytB~0`7<!rZ5 z2>em5t?BS9?Me`XG$?BBZ*xK$vci)K$Nrfol_rDL;nUZep4}s7e%;gLtSTeJp&Yp1 zU4*mdnKZrb`ax4h<@z1toIUrW1^=Wr*>v65S(GBUo}a}2L_RXD8o88X3~BkMT6khM z=!h=BAGE9^F%STqDeXGyKEE;(1njkIf>SZOSLDx{=;usMXWHHo0RmwUh(x@H(ubRDOugu=R(tHwGKpd zLiu~e+<1dqZvP|^ht-QJ^Ok%}PezAP?N#MzvlU@-v@^K#RYErDJo%{HkOUD%ME`-L zTmNrVt*gP^o=q=)GGu;?3R5Nq_M83MH!$Pjf968{wI{Use0lVlB?gMT>rAO&Jn8g* zI*f9Ps$lIZE|X#wMM6-G%=JORMG!aBKhoP#(^YICaIZAVLvq9`JswJ?d(q)zSXv`^ zdwD3>>)uG$0g)>Z!tjpJugz>lNw-4+vWyjd>^h=etN2ffW${?3ig z590dl2!eOTV*%z^adkA3eR!!_@&+Q~=m@WxyUemo3xj`dZjSJw{*2 zC{Io!+KKt>UdM?x;azJ}{R6+gvkfV2`<+KNl4o2Zr3i2efk;6~6K!UC4%1?i#Jif- z_#EMbj*MSYX4)nijioUgP;)=C9cA`kVGKX8eP5q)D+5CNMTTKq9!~(R99%O~v1h5# ztM8}jH#nsq4+{)J2`ZySq;m-GZh}CGUw@R zjP?-yBjUk50ep;Ax#v)#}LA@7S}K%4@Q6v3A!9h(t?bk_93^sQmphc^N1Wsr@d?D` zba&`!52^iejUB!EVS(tZBe!L5E5a^t9vC!E#g%UP^0$W9bwwsL!~NJAqJn+j$8&5G zu=I1tQ0)TZDYgcqK!OdKivGQp$uCQ8Cgp;8>nM6A;t0fpwXG?xW3x#WFF&hq}PuUVM zk>Zj|AuRfwykW=l2XGaGrgTnFoY@35nzVa{(YmxaOQa|8cBDKSeHWbKjzh>s$8~k4 z^BnOr3EZqUqGmuEiuQ~JZf73B+&NsKO6n@-vI>rWp8m|uC$AjC<$C3gs{pnMnB{l8 z=JO~bGu{-A<_#hi5rgGpgQ2?jFPyzI?WCSW>APR3!h3%JI|T_jV0w;w)nNW3|S8t0r%xbKEQ` z+X`9rIbV!4>g#mm^kbc_z`xI4-*Lmp-JsOe0i=wD<@n=rD&0uKKv}I;l54Kn7t-yUn8+#-eWH9F_^S#M&zb&|S&R7l0FN z%h5Lf4rel`E@bk)hPji$NHISIP8W;AJfli_YDOnTR4W>vv64;;NDEC;ne}&B&=@&$ zdwBn>kkV~F>6_Ubq-+(R&qe&a8$ml_HPA)0lj@WPyM$y0CO`hGXLTBY#+LN2u3|kQ(nJqMqsH0FN%_VYsK@tkv>+lsAq~R~(oHrlJga!XleSZF755 z9O-8fe4bNp$IX*WD5LY>^4t4EWsXF@ z(R)1UMzWH|pjI|cXJykFCwP$<{g8-m$nNuE$iY>VQqerSAnvS1AFeqUp=l=D6a`D+290RtdT89LCDNXq z2yU#2g5>F~s*yyY{#DoF96gJhn5w z108&ReWCI!H$CK&;;97hA9r z3`V~H?kdUg=sG-H5h2&ui&aJNqsH!OgMI8w7Jz5$NsH|DLixvey2BmL^iOB-+-h!W6FHaXF%2;Nq=VCX$uFO%iICv#s`XR5x{O-$7)DOb#3LiQ6Kt;Bx zsuKJg9e&tEz@VuEdvFH^lI`QXh$9K0=-*D<)oM?6o4jI-yWMO@KKcp;`f6qC@|`tZyXvv8G$Z_it7}B=|=UiL~X*auWe| zNr*jwe$8dLx(!m76j7AHeX{g%LoUUe3SU(5H0CD?6Exv*s&7UIQvoRVH~Ol*WO&~_ zsZec2BQ-KR^b7A<70zFj9 zyk7->&-#DkUuSB&l)ch-79=PQE2AXw;E>z!MVVq3ZWT-;v%)O>5X`n;^0Nx~Xcu~7 zXQIr{A>DH^4mS?Q8gm|-n$*eWbp#AU+6HOGq6`OIl(-^@S7kq(c#|xMS<2k}E9sH=< zh0;=f*rC?{rc+G3hm(2ISFh>tJp3QaJ&<76&`+wyEKl5;YW#?(~R-6v7<1ga;O5p>B$B$VJ2RN`x3FUxu<MD zS)ardf5ww=uL{>KyD;3Z3RRy+v>fBIkq~ZEy@*ph>UwLTqzCcM-B;CZM=oHm3km}c z%NqX1t(sqblPk#BV+qJlUbm!V`IszK5JIz^jyIBNsSLFJ(0LpvA;t7qNRBvK3^z@f zaIAcZ4HOtUMRsq>{jxBTn&^=`72SV3+1fcyh#JJ_;d?*;!Pqtg?Xx9LNx`nfl+lBx z_D?uoPiy3qT_h}2Pe!W8yO9BWi4gDe2OLjg?l86?nN&<=L5KaS+@SJap05C^H-xgSR4sHIP9#r?}zthw_+t8fAGg zFF*!6toM$t@3`8afRAt^^`*9SiPD&k2s*!V3li+ZGLfNzKkm(MmHbAfw!mARBXU!= zo?8O{{vOy|(vn9Md4*5m%Mlrp0>%D6sgI<;V|`LgpChch;z>OG5a-RzBO!e0*eZ#9 zS0eC*hi;Z5gZ3O7DRD zEj)3@%$9NFnSUgsSPKljEe1KKc`292QaOJf!~MH2wmi9NgtyIbiq^agZ2U1k_aHF7 z&=)pL6mp>Ryw&yF-J5p4znM=D|6K?}ejnr!RXR)~h z21^^mXgwgVq-_|@URWQatMY>Dq^+V%B@H0BLom(tpG}#MWUlO3JWUgr^x$leh8aX1 z)@2kEo5xIOcwc2?TibL;fz@`0uq202mZ1*mX_9S@33^HdgBp3sO(sW z1pdBXm1#P(zUWf$yV)%O($pO-9yrsCAfaK&n9d;|z@JV$)_v~;aIs&DaD3NBkN*OA z-vAY<`8SmBGhaT(UF-f$*;(W1uE}^mkK{FR-BxlC?SlQZ)EG-r6NWuw0fx| z9dn3I-au~azRR!w+1XNzjlpnjK84d%K?0SLb&$_$c@el(OAxZ_+h%oD_0EsvWx>tMIqIUnZuhJa%Kh zh9{z3t>}1BermNF4wA6!sA@QEjCKn+DpXu3IrJaUIJX&Y8?b${rRlM!Xm{NurIu4S zkNl2G^Dl$M<>`&g@Fa8J|B%MeT)Ze$L7kBq`UyTb%>nB}Kto#Xg<-EQMNhl~!BjqU zjp4{qeBtht1%op8PB9FZ>FOD_cP*cwd^XWX=pR;gNe?aFrnh7YL4Tib3|6rKwQTPj zCpKZ8%eF~F_{U3(w>q4jO(@>>4^OScd8u__dxC$r3isd0O4(B#-6qBdG8Gf-nF=PGQp zCUUjmXL}Q7>HUr4nfkhqQoAu4o>~0Jk5__ma;_adP~5L*C?JjLAFi$kUED}DU3_%n z3F~~FS3X(uH?Xi%&c_6_cEC2o(Hx4Z}cfy0&fGw(a(=ZQH$S+qP}nwr$&XpLu7JNxsb1{E4-4ZX9TsqH``;TY`A5 zdQh~o{(D$_4wVZt!;;sM!Tk5ZBYUat#4yei&Oj% zl*7YVySC#v4!h)#i3W`UHr2qIJU8H$tZB0hcrEX2WM24SRi(+^eEO0^3+F6+p5U|1 z=0PV~?l*QzyfSLjePucD??KOMEYN}@AlJ(MDqX9i;e99+9`(RI`0pVviVuHXXF|;u z^T|)@VWjVe?b~EMG%W|S;VPBJpCweBd)mPDpE&R{QN%#!MXi;np;oywV=IYs16?%H z_Ph&;9-O-UJna=1x@F}ty#7JLQpooHj#xLreO#Kl%0G#drshh`tbLf&@*L zh0R*HP(~?lIo?YO&j31uyUW*(x#rdD0~VPRzX?Q~gwCl;nNlVFBW zxOXalo{0qqh^MP*y%}9R^&V60s&aj0Q=0Gp;yP*&+Bh3YysF@dd$mWsC{a}I#1I}* zbh>s6QC}*#$M2cQ;?~nViwPr6G3foaqA{!UjvpV&1arTsDEw%UZaI0)_cKTV2nap` zqSkIjqeJ=F!2b)@I%+cVJ|~eVm9;><2QGwD4ujBzSJF&k`^mIpPXSd*G0~rxjb_bl|tnel^SFANwO`y2}wTKJ$jAonIGIwy_@EV(Y*O4)O_ibn#C%zd>>?JOTR zbRx9am4^B6$gbNZUB(aF+kVXs4ea^WrNr*lsC7xMJ;!zku)pKY@-X^K)H1fX zwe;7$LE>|joXkcfk5+2P8eEvA4>IiNJ;U)65Avw2H`d`~6rfA#tcp!=^Hp$EEd6)z zmC68Uw?L}#UQw(m;0X3TiOOSH*Fu8LA-;DmtF-4Cn*QUbk@}X~-(i@2f!@NlSHq~e z@32cXquiH7;~vs<&8+Vk{dlsQhd}tCFF5Q5A3(|)0mcKLx|BBT5}tb;`{B7<9zK2g zhlWX#@4-gP4pCDRHf7I8T8C$zh}ms&dHH`gpbrF;k}mMD1(d+HJ5fQ&v&5V?#Wv%= z&Hr1!lOw%>wBGJmBReEzx%pR#XH>|dI9*p)to(KhqOcbSa6g|8c1e>qyF9Uwp?N^k z`|)w-`hi+T>DhLiTIw~i^oC1T>F+qz^1JTvU#9GQ7lvDGRxc&?%L5_x6A!frf@$~0^ zG60sJt$P;Z!P!$Wo^9k4lX0@oh~lV#$$m%X=3E@|1`v0+-s-ITO@U_7*9`s>lvDeR z)rSw75+O=u?1-YA<$;R=fb`647kN0~t60bj;ke-S%JXT1iM7~EWe4r;uMR%@GA3D2 z{77rSmSdqX^$#v$u^EgD)As&LYg42mAg)EtFpbD`h#HG=Hc_*{jEewIf1s|(2C30! zHlu$mr`BAFzF$7|SkeVSkN_gN!v-lCz`zc!K-%$MGzA)aQt_-2uDi>+jj4LntFRq$ zAFAoJzHst>bu>dERh~0lx#LSh+kXxu`CnijJ5$CQVNdBS8C1PJY|a)345Q*$$ZaD< z3ZIL#L1snFIbu|Nf2tdRs-52jZH1w}qj4q2sdb-C$uQ4|<;|I5F3ix$SeT#=H z6R(796}Yu(%jzHMiz~09l3ebw6;lz`E(*;Cos<9Fs}N1z=XPna?Vp|~nd$!AhPAe7 zPdrB5>l#v@zjnZaFaXG58o0tChiiKfBS?Z>*t3jMVvg%j6f?1hTTOGN-_KT0GI*3V za@lbjH-dk4ddmTeDL<=XyHp#dog=kpwxfbOm;H3`IwFKOMEy`lqm-d_wBgt5fa}~~ z*Ar~*_hx3~)%s>em&uiP9P7|VZGp?eYTy5`CoffGM2A;%HYkwDoI>8=9l5)h9ID`7 z8R&y&4raoy=M>@|?p`7bn1wz(1Ni4-ZVXEb#74+!HM zMImB83GXN@K3D#-y1)$4xaCAu$TFOy?2$jQ`j!jyv_MweccSzN zAQ^xg88hFUq^@hl{>Y)q6CWC1Cu=kFAs6yS9s{Hgs2uP)E4=M53YuMsa_u6-WfUIY z((oCy?>cxZgSAH_op}g!#n13Ox!|2g+78#NaL1~PYa2Y_-bS`jIUIWITONsiKyk|5 zpq*7wDK&8UaZO0w6BYg3Qjpr$qAEx_EwgsND%l+{Kxhys^(s|3b&7jgIxz1{cf3t-QcS9 zv4nWsBMRTyRBXjW0Ekb1V?WW23r}t$kaLxc3mqROuMKyHy&(iZRHLgCr~Zb5n`eQh(syWT7dpKh6}m7n*d#WHjb#K(gjkQQ--q1v4*achdzLn~RmX;UeG3shsM` zi$6T9#Qwl27V=JN2*5C8LyVp*K!pmU@LZpG(Ew3#*tglpG4G8%rp<$xd!>_;U&2rp8z z*Fy7LD}=@WgnR+hisZB_@37Z$>~Ei;{nSkE*xY#KM9c+wE9<|(k|Eq3K(;WtAmNUa zZBDXnnCNISH39OuG8g?Omg1_QORpy6&Zb)s#?w})&^o`Qu zN?mW7Zx2ud>2YPk_2*N@_@ODUyo@6D;X{0|UaS-Z3f*VqxBPh1%BUrLcI{6)f9Uuz z1~um80=r=lfxgUNM}GpkJF|D1C(wId#0BQeJ?Wcg7-TEx9eQ|doR>>u;rBeh8+CE-RlD1Xb2;rzc^3^ zF-4DGP}+PXW1LG5vFiPfLe4{Rth_&h<}=aKKVoPm2!R|u@t88(xs6_Nvu$w~vK}aP zlnsWochKIrx@#gNrURG(kj|t6JLDG=lJ>j~(l=@P5Orh{hW0ApJzD`w#ljOjhdU+7 znjZoyTob{xqI|%L3|e3#PKy zwvhy5q&DM`6WkW*V3fk4pHC}3TqlHx*UO&7;n0eUFaT22>RK;h^D<~SWeFDL?f|md zc;I`t)7j8(YNIz2VDNkShEs(cFuaF>`B+Y|jLM%K0{Do3utH>uq!@&_=(4BXa6D~0 z2sHH3DIT=tmDvo!UpK|q($N(Rq@p`MZ6i{UP6LOIIHn9}Ba_ElZFSW!K1^^Gb5b_| zD%0ZoDbMd%5ad5V$}y|gWS()APXk_y-iUa;+tXD)onOwX?NJ^HXcg|~(e1yOqG@ny!zDMWOE{G_sbH~z}N}Lis;lgI7H0(@1 zowhIWl^LjBf(;vEogmXLFOt*#v{*!b(5vJ1r&>?;Vhcj zhzcU7xN496-ae*>pZW4EgZ$~jxJf%nK8+lplD>K$Pn{oS#M)ut9{>@D^v)@9xK#1gj6V{a)4%ULL~qDXLb9 z9ld7I87SjD198(%)bF+izHrTLzCg^@vdiIak(KSVTe42XmEo2mC#JUCxJ_h1b&uVQx?)ghkz-clXGNPCPX zZ9cWklDbe{o_0hEb&ctUF5)y5eVF)JJ4G_drC)Sz)pCAqE-~>#H!mIF`(+agGUAjx@6s=0LuNs`Uzcdoym_u zH)eY~Fd1$>%TRXRP~N^5-#g=Z2;_y~JboLSn=dVPp|~UHd6|}lHJNIwj355{)Mm%b zhs-r2dZI3A*@cNG+94z>^R{4x!+c@cL$*4Od-zsND%oJ?@K{C3vUWp!L~d06zBxne z{wrWZj}Qs>6>!HRZ_FnVS%+E}%PS8yo1J9%g}_I^`IW?%!i6vSly%;Cvg$Vy$VZ6W zi(8p;-DGC;EPteHITK_69=Jg95wioM;?#+$G}JAI&W}+g+il5IFb>thb4U`;V!0a( zN&T?pjTDp}P?7$|s@#1Pm!&1W)^YybKk1#ypfzA3Fe;^_-M__(OoR%PT->Vx)BB0-eJ0?|tq99R((|2Rf7O34mM% z+mT9w_9K~U>g_PFXsAB3p!pv5<>3L#~GqnI7dy`SEmklB($gF7m_PhAv8aN?^ z%De&n7aVTtlBLDlu3Il2tZ`AeZaNNL_ll~`!NTHFC|Xjj0IomG=q%`Tl^Q)emN%qy z>COgHcf!tkexZHKD1$e5IouRq0xTdKG}|*2zBme0`E4G(D$qymL}04>b?5$KJV5n^ zjLHZv7IUn|DZwZn%8KbfYhi5d`?wLu$Rx1jz~9zVP&z=QQGgx&1E!{K|OzvI<{%XVIQF!@92nK(ZT{O_SoIOR=2&`)56)&#;C zc*vc$wm;x!E#%}HF&8Ow^+s!TvK#MuP1uBF5ruKsj(U;%LQ&qc;6r7JCF|wc!s|Q`&9BDQ&EX#ev((N$9q=R> z`=o(eb~<6*u@u)P3=fugTI#jG0hrE87`<9 zGVLHA9L^HO7T}49-l57Ev8g@CjP2q7vJFP3XG#m=J{VEvZ*V$FP(RKDp!4_ARY5wL zSgsO-Cbqcj8{kHOF4J_m?ubBUJ)NW!+g0=QNOeC0<%mujOlLGmo;X-+%@J8VZMGRI z{fUQs84eInC7Q{ZRoW6@iqX_y(*tV;EoZ}KS7 z-m@z~ny=zY%E>34I8EwUtzJ4+lbPuufa+@b1pmVhxU;wC;ejB_px?#YSD16QqY;kX zFUmafFBq=PNcCt$@#;S^8i_Y=`3nxbi$IV?RUl0IqL0TC;0xMZOA{Gh^k8o#JRW#8<>7cX ziEbg3Md-jvXzo*T^PoUNX-TqQ!Y=K>qn5desV4NplX;gP+Mj1C_{udu88rmvLIdp$ zXIScGEX)ZyJaYr{VEEX2)2GXM8!W!k(Q6e1HD6GP>-Xi0_N?I8W`t(sCa63e55aoc zR3new0J`KENV@apWJ9b3@4|IBm#&<_nN?{VL`(X>EW?#7FdSb*le5C(Quw<_UZXD? zyYy+$zDQ~21I+ywN#%R9X^koUcMES=kaq&jmOlZsF+mf+3qKv(_uKS>;RA*9DE&aI z=jb<0XQkhu#Lo1ko!#DADZ!QTv6!n2-JEc9U?6!+)+}t5j zgBd1PpJZ(RGBENtyusF5C;cKm*-ak$OhBhZfJyo4RNnMT^FO%Kj&;kY=xD$hih1=o z@kmLJ2KeA3%c~y-=tw)8ra%Vdxgj37PXHL<_zTUK;nP)3l+mNSaM4S^{z!esmoJiq zeKo?nljGbUMb%SH5%2xs;eAassJ;%FN?rL@ll%P z*H1ijGZs){5v1utmqXjX9QD9k3w4f+>RdqFtBywVSh6@~&!W88?7^>L_~}APy-Lx5 zbI=~9*%c8E&ZvO4({J2qzObjT}VJ6D^DX}(uc zyjDbhr3411s6A@f=9S1w=>K7BinFUQU6^H{qwx|Cs|^{<%z6xAV|jw|+r-irj~(!J z(#tGQa{sD7D8;&z8P8IXPW@iw>Pe#Ag%2VApw#QxZvygym?IiKbkdFJc+-h6p(mWb zF3c9#qZ_pAo{aZHdAy##mW2nobgqW9d5tKKs9>h#MDcKNZB?6^?@W5en`1g(kZ~_J z&f1Ixw|ML)Yz1#J>6>l(s%}jt0BP?c8*ee)S#^hP>xih+*c6~(Z9 z|6s(Gp|*bCrRN)tI+9J)c0;w7nHf78L@I%i5uVeK^$cTiretgnfyZ)?$@#GdQ!-_c z%;VE$c^xSH?YeI85 z4y4#Tt#ZtpFqN7eHJEcd_CbQe;WM3XskUgSJj#|Qz*up|`ft}Pi+l;*oa-B_nsVQX z%ehkX{4N{rz0kxSr_Vpfk;6(^J;x=aDz@$h@Z;$${rbYHn_=2|jxpiW?1th0ie6vl z(Yf|sOh+&o^IaEDSMGzXcp{Ri=*7dXdSev)(17)iH;?s`RT?v+uY8YbE9EN&Pb@S8m&d#HWh~LVZ^-hAkA&Qw7w8}r1eKY7cJ6; zJ7FZ--WCO%gN1G9sY9~d+s;tZCi%D@JFJ+`urg)>Hby?k9j!WL5P*w@(|b8xZo|8U z9jbzxe<~c>H*^>A0@;dzRLjZSWq+nx$L953j7!cZS-$i*!?P#pNSuF6^ADUjDf$zm zTjH)r+>NGDtlSIN_zg|b;?|v%^I^QJYyUM}u9quitXb_mO()*1 zY>aacZd60SeeZ+fq}+o`I)xo}!yF^=5v~^p6nxKDOgs1mZtS4##O+=~2P6T|{}tfg zi>3^z30nMdgj)Y0`4nU35Otdp1!zfNJTbIk;Wkgq(}BBrmSJ-26#;HlNcmiy%&fu- z1Km~#<-eq3o|>#g9cmpt_@}e0-=g%?gOZydc*)FGm-hQkwXZ=-1t1?@xAnx`dsvW1 z;l?#f_(frRpe+rK6O2zLjr(FHVb^sdF}FBnpSrANFwZZG0L}^x9QwtfV58oSWN7i_RN{V;HJ5gwZZbh8Se~L!- zZGaAWm=Sv^QU(rPjFF~T0CC$(Rl{-~xMkEpl6f!}2B7v2Ca^Y~`YgvaCQ^K&;KzzV z$QgrJO4iLdLw6#rtHs8uUNJgq-7ITVHdBj$6vBahtl*Bop1e6`wNH#f)VqwR6*LH| z6eG5Mn{5I-F40d3R_i_N4VT@$PfTp(_Qh$XKS!!pqrPm<7wU5_tRL+W11N~fC&sDj}C z>n*i6o`|qqRK2l}jQXha0$_b<;`PvIi~MJp&0ZXud6VIeaj2`Mu97Q=gGn8)8b={M(#C&fHc@H zFWa2eMvco%!#7rD!ng8Mg z2aYhz`})#e0d#TxvE*T=oZdNq(&1T|OY1jD0gB2KqUBSG2Eev?3{kmSX#+0a2n^Mjyz|dhL&$xi2iQhFP{L$-XshHqfZ2 z5-T9}RoLF}Y3VE|N;3jardt!WD)*znOFZ83|LGk)*K%h52bTY~k-j&tM&%5QhVzpY zy)^prwyQXPjyP!9s{*@j%VptNR;`@x`$dpA==h)h?~F`-*g9~IGDBYoLXT5vH01ml z9ieVlrTvAtu)pF-c9uuHBO(QwCk>pvhjRKCIeMCQW#x{X_LrLkDfP7V} z0}B6-q{K~~j=;3K>BfvRh3!rxW;x40B<{S6HQ*80 zkSiw&cHtM~83AP6fg7|u>5nfvzC!$3y})Z7`Oy;}IX}PFxUkr{N8gI;S#%2nb9v~L z7AwSiR(g!GG{%ad2i$yHk-9x{`P+tN&7TH)URdd_qtkzV8UJx7D^Dfp%lG!Y5>;-l z6^`-14DR-ib8cMr0DHHrX3X>Fqnk!~)j`6t4TEgeYz6s)FVvNxfjX&7p(_m`as;hEcc7qq8mSnS9md$kUl6z+Sk^YRBZ%#%m zL-yc1@diBRjc*pW9@eitaD+LT@kcw`=DH9@pIu!V2I~RK?S_uoz_zp?J9#$!I! zq$4c?8-u0gL5Aqh7F5uH%|G|OTDXldwvt{c;$|y=`X#PwgPu+34KdiWHmj`N^@Hh> z0bj0tFmwPZ3gbuO=(yi6oh`j1!5($y)E?b zg^Atqt<<+0xC73GpPu@%JMVhGS``f!>hcnY%__T-`OGy`ce^cY=lQQBFP+0|s)B`jGLw&K(Iro)@Z9M~UKNGntlVl+SuaF}X z0$qV**`3C$iVT1F-8gg!R?^Nj*O~`KNN%EMB1lsKw9xu--O2~4t}%y&&n~#csxx9w zuTe^fdo37SS|prr*iq|m>j*nM`CnP&L{2a7g;urLcK)Denm`vs_9^bLwknA4kgwI9 zYjm+n-jwA-M%V>+gvZ@|?FD}H4$1e9P2gmQ9eUZd{4<>R5|zuMGGYHg<6%MC@iSIp z{dpc1>i`+z^(NROd`#X6uUS4_DvZQ-EO^BQ|U$my$W>pHV;EsR?cxvK_VTl*Q<&pc@8 zKF)3rF8m(f(8wlXeAs@}Y8yL*hjm9%m= zTf9_m#Y2YYn0a(TNr%GM;b4Du2FxH>}?yAg*wrH6ZAhKZwXMwJPs2xYH(^? zh&^TfspleuxRX1|(+KU8jYtHDq6lrfJM>3Ud zJf6u1&eAMvnZzX{MNWKD6l-{8;6(v*-g}bwpB*c=^WrGP8Le>9vv?ob zDH4a|_>oaxKJvxCR?D+3rhJc42*Nv{`A65dJByj41}Zp*$mJ8JFqiG<`2}E`5B+ho z?bf6TUl@^R`MWb}4JFTD643fZsMiT|^5TNd@gCPBe#3U&hNX7!SpGN-;bkGEL;oW5$%vcE|o zW0P2=kx;_}xv^~@==4Qn3>AMUf-^Sy$Sv@{ONgkFI1stDOjYRL;PC0NB_a?Yq6qx| zN5pY|{2wAt?f(^Vk!$~75eH!|2k`v=L*g?3ZxWZq{eO_S&>3Ku71T2(B!D8%%Y=(N zq!JaRLpM3E7ND`+ua||mujf|L$bD_O(llSADLFKZy%XAPo#v5A6+s0-83D$Xv;6`B z&IM{A_fv7*_Pz_O{9jYbC^`$9HIz~lZRRs_b7H}u5ghqqyi^WbUC!LQuvHm7pb}^p zzH+--4e33VShCq7y9R4`vn-7)_CSsg-~ls_e=hgjgie2=s;ME}W>A1E!m(@hz;raoAKW?}KkGzVuIF^MMo{88uy>;+5eukwuQ8Tk zbNjM@+_3_cN8TU#U#5o!?&>DAJYW?IQX&m@4|DXJV?-L~Fd>G_W&QT}qMy(|&l(zf zBa%WHQ>`cLzR>A+K50l5y_P^_3`X@NBC7c7bD~ciy5pZN(URi@W}WR6Q%1iZkg>M+ z`f(#6CbKq*1ZDG~&j#td{RwF&{$yDXW5d2c!P>}>-ed8c&<61ekRQwMvCFzm;1_?w znc{ecx1f~Clp1c)7+=#e1rq<4A^cY5*yaOYS<1~Y8F+3;6i|)gK1D^)l7~ZG?Hr!7 zTnd5W8|`qv%H!6D#k6^EEEixxkgy|ya51YFQ+sbtrkFP%qLK_O8oElhYPlsU>EU!V z=)$iMEjZp?6;>f04KNX$^(}L1cyGxZ(d`;-(?I2b@R=tl)oq! z0}Xb(Hr0+AH2a|tDLVF~Xz*`r=-05elEV0_f-)rHMX{Yt&lEg|)2i5*vT`viQ)1wm zAxxrUHGGUPG6>q+3g?T!#;65}SiYe)p0GO_ICtC`^rZzIRUj?Ve%SrYlaLB!s?cAQ zL$7+CE(j*sPIGH$P=c7VHV3ji#JhArKh~I*GTFmfQ+jLCI`{U>TIV^4Cd)d;nOGDwDWmsxl~IgZwE>$Bk)}J z@c@EBZpa>n?4#+(^PGGH#z(zPI1?r%1+@%#QC!N-O!Z?}mnH?G3`c$kkpqTaav~q$ zP`tonC8H^_!IHRm)M*zdW5`mdzMc#0IHsP4{us&dzm}}2f!NQ&CH4%aBf)?z04*8~ zf2HV`rRlqmzZRL^z-9C!1d+=GKME-);gt zLOj4R)r>RY%c^ZD`le}--u=ZDLvkuf~pYZ>t^DfA3*&Bud2j}?SL+??nYgFSNc&mB8eX!^%;b2+#Z3b&|?jCCul&- z6~{vsKM8zMcyblt)IZ<{m0l02-SMMHv}UkS7CZ)WR6hQ4u*_>tG_b&=bij!RIpg9A zFVAZj{?pv_l{jkUQ#2cxY_#e~GOkXUbHo5$IJ)A7TY>f|F|xvx%)d+K4XrB6nyp_nAL!j%H_m9a*{f`n0K*A{Wo z$TWN-2P0>2%!XQ1K9p!1l6`6S6laN%j9V7?3f-Sd^B{}I!={8)rrsPJ{!YX?sN!8Q z&}s%Y;7r!LP(lXbAA_53hHmz<<1wq1se9O3%x(xPQ2i<-EA->F%blA}a(3ab~ zYyJ>jw(J_=$QkSaSl!O5vn7+QEsB}iVADKc{K4RI2sI14UXAc;{<|5X@w=B7>%l-@ z73|bof`z)d0pqt6bcc}Sj1(?UC75{J8j@KQ6tlNb-l6zzu6+CN%=9&XaeLUSAHLsYBkTjS#aiR$A zaP!Cxp1ox=m`x^a(X|2IPFD-LfFO?oJSzxV5R-Gjb>d(CsK-l~`_!qw&}b-osh75JZ5cif$l_QUv9sIkpGSDT}e2 zBp$VC0g2dwtF^i2Wod9e8Zu`h5R#(XSyNRSY12*8?w~=E&Ckl*a#OS!l2`J*AwXwj zMM=j{k_aQ%wt>Ezi&;F}oQ=NML@hRRBrS$!M8%QH!1-e>G1-tiTZ8Jsv8_^;o}oBa zPYZ!NK?2w5DxgGAJWH^egK0k^$&J4x;qA^d_XaGRzVuYv?fsk-+P~kR`(k?1EhM<6 zFnnA#rX*4FO=BMliP^O-;f{NdKfh9e-Sq5k?yZ~s@)eTM=nhFC;{^pEJD5OkX}V7Y zm0xc4q7^{kf&$aVgM$WSOx@AOw1>n(7-EW?YcYLMCdZZ`?b%MM+wr=j>Y^WyF6^{c zi0e{rP8t)jaK-D^?=K>O>@z5B74WK^G||hjhKVhIT8&RH`Vf3DmKVGmng*C3q;}m> z#h!_byb=c_oZvmczkhP0=)`?pf~%n(Rj4-ow!Rn=Rv7OBWR>SR&JX@;K^j$%8?es| zg7%C=&t9Kg*q2CUDHUgmis-GVv}+cksx`V_elj% zW7O^*wJ@Xcrw_v@^4Jw{M|R|`fG))4s%`7)fW2QO5POcHlW#B32DSqavWaR<-Z2!l zY}-iusM8a&?4ISmF`bxP6Br@g!!s=WQ}MZ};b$&4?ZO%rM>X!j4BeGS!%cjDJAF^A zoYgN?_1+y7re)SHFp(-;B*5YApLvePgl4ThuM`$G*VB2z*T=m8g_^LXc9wO?t|_wl zGDInlJaNJbf$nPbN1ySiP$5gz+`r@OAJs<7c4zg{``qF@nw6+jZNOAtu%3Q+D+hPOgBJnf(Ha5;y{6 z#r1=~gZ*7Oek&FNrz^DD)SxJx3A5wI3xbR8=MD@Rd6k(^Dp~a@TyuFMkfh|lRe8$O z6o!DA46?Cfo?ne=bJBsvZHZJjFD`(TTD|5 z%SCl_s1@->4f19lcTk_sx=MF7Wz)YD!@%Xs(mRPiIj~~Eqg_H}Sn>Pk1PUp`^DjNU zvE0D^gp%XtQLN0kqoltsPK_|X1Xay0dhk=`-pe755dwDg5t#3WqW}SzBOm&7)--*YHOMb)vG0t^)q8Odzr!tLfitV>p zUKAPVPi4Ei#;815GHoAqeo$}qBNEXtMc!kfvLnIeGT^>H%_S#41GElojo^E7yV>)o zAuxW)H>e>$QM#j{GQTnSx;ikBH3&^@o%VZ$o(GCQm@_yw^NpJYPYRUUNCJ<&H=r}t zYtY)0chI$^1`-vP#e&5XonmcdTwAjfLcj&YUnKF?{=X*=BYD=qw8TQ_&(Fz zw6CSEsC3Eyt2SB=*UWsNaS}ejmh;I9eZSupdTbcXISbgHSczCy-PnRA;~ju94*aP= z3(a%hb|aJEo(BdG%BXg78{S-PBHmr|!A2Ku#D4hfN$DW%mYS+EXB{>3j}`BlIbY34 z4)eN19kJ0j^uvT0_KppT&XIV4X;92_{(DzMPjxKh{up4+g>TH*`OoW=(X z1qlR$Qx8)!y+U_|Fp#1-#XUoN+oI!lV>SLa765@D+RQXpyW`YVM^C7FJmC4@Nf?ZE zJ={rBX2*&bgl(M!n8q~bK(Vp>2{jgXFfuxg1cvHeRGr&9EbEFBy$(y_GTk-=jrCOk zAKbC6yr^cU%uhGp)6@6ukA4w1(X>q!>gJ6HKX{jlJygX( zYcG#W#21QN&QIVq<{)pOCt*N5D|r%{9?JM(D@=aUQw#jCexCU+BGFC(U+fPRXc1o> zsS5{N(*uO;UCErv6O*jTnI44fmj>*r){((4J?Ni*P)u%+_PS1B{!kbf;A_!388o1w zD;^K(K)n;-41;EoZ>Ts2@CEuwR(c~QQT~aKUY`XKM$nv&F499krYQ^hybyI{<69;@ zc`N!93ZF7D(iD_X@>I8*;PBEFv5K48PXrS1RUTC*yr5lSlH%q}P7@qIDwf5w#3X`v zE|sVTF2tT^{#=j{yIjzA^jX?#u$o^z!gjZ9}kiAvb8)MZFL)EC(zO zUT6nmsv+gEM3B%5UQGacr^!60li|9=Q-^#xDJ&6$%1-s@P4o0Uhs-$#ALmYuT$<=L z-D9Up+iQ)!2@Z!GWC*Owk{y0F~RhSc`*!S_5dK>jNPdrAiBe!m>*~mBzE63+~)CD1`mp zVZ(&Pt78&$KFvadqBfhqR%GO6?#G2e{f49ypd+7S8ZoloULSHVCL_dJ2vLxOx>o1xmOE6f3Lrg)uvd9mb}2 z$@Jf)+@S)+qss){Cykt|wmozS%61*C&CHgD;Hb)_XNGPu-puJz)6%U&4(eE5kGjGI zTZVKo%{k(M^!*>7n{Zr&J}(F2eGHbxBxU9F#3vmJ=4O~G;yFqycaG|p`a}Qve0o7jg?2+?6uNoRHKj?2Yiu}A z3w6bwD)IU(Ou$;*2mbL8#<{P9}FFf zS+nIj{0|N$#9jDi1Axv18XBVOltm}i-H81$myo}sPtW~uP#z!Gh3Q1c@~>FY+tPO+ z>uVsHb4dQP4RHc@SK=2zE+c@|4tYCu1Uy$X z(zP`v57BsKm_9AqD=X}!Ia(EcL%ZP{c0zX%;YQ9gf~Sx z;{&~@*}Kh}Pb=sgOb;DOgWaVhe<;HcEKw{3`yC+zxgB61##UwTu`HA3OCb?!Pp7nq zvrtjYnW`PIB(d4$4}<2YouiwYkDd^nN_W=iX62fyYfB!tjOpPS<{f=gkYYp*B}%8-+2h(qcc{p1dgm!Sx`7&NQ8_g z5P_0aT)FpIOz(6rSD`{RU8_TW2-fm`sk2n-SvFr<6$P=8qK=?(i_z^pe2WYfd>PdV z!dotIOMdi0;pMVJBaJf)L8nLJ+(r}|r2ml4?AD)V!DZIW=#7;6JQq+wM#Ihii@EI zn5Wb9gv^iIwZe@#?zmbDb+KrRtVhrnJ1rwZ#U}n|$quODjN{bTd=li5yW^$Pexr&9 zM}%4Z8@DiGGy*+EZ1kDo-FB{Dzy?7izTS>)bY?W1zf)t+)r1Q|wJSf9o9|0#qO~Ko z;M}HRbP9H&bS&JQM!>Eeg?LEqfohe|jQR}>f~3sl1z^*`4EcHBAYNMp>5pIzOCodKPkKdccT;>n@PHz2^3Ie)<-#-lQ(0kj2bmlC-dFXp$GVp&QrZx;L+vbFAvBWaRMcXzKADDSAhaq;` zNu(Sn00X_kW(omjBKhk-lT6kcYnUK{(mumTkars; zBa;Z@7otl1_>`-{eOEto#!5n>)%sK*}oN_h|&XUlvKKSYTM_i$h$g9Y+dXSQAtOn%}7~nmT$_EYeBjgI%UY;O9!D zD)|=iS%4$JjDXy=H@3#R+lHA3Qi^cyrIe)^D*J0nUyW-WE_@DH=!TTj@Kp;G1b5oy zcASrYTu14Jp=V;R91=7~LLu_^3v^P?=*o^G$!NTN6vWSGpoIg&u%ZXT=F@y+082o$ zzo3Gki`_-9L&;K^#i*RT?v70pV^2sYu2bGL@wP+^`hDc#1Ru$^_b%`PRXcaPw$9HH z4YB1b6dSA=lRBV{IIH!Tjz8nDML98WZAAbzh8{-LQ1L&bzZU~)DJGK9?;Gz8rO6WRY}oK8$}`xtth>dB;^iN2v+54b=dX68R5 zo?~;&r$0!Um_OF;gKB0Oe7Ddt2vwRRYg)sbbq@k+Yr3t4N=HJTLXX$pp%c^GmoP?t48Ew-?a}BxyREGc5giJpjFu1>bQ3HFA zFlqfpWAr(hy4$FU=w7SqL$i^VH?wq^X0Fo(ipZ-TO#B8pQsJ_lMoG4C?y0-*H&^%u z?`}Y?;omaAC4DX6fn-MMU32h1JeaB3vox+@rKdM*lgjskjpsqd)j%MGcoe8==Osvg0^E+M`JW%1)Gq=U6lYa&u0M#< zi!DQ(FA>Vruhr31TC`JpIdX~phZ=__z{!m{E|&KSTJ*=HnqjX???BdZr&lSRlHMHi zQ-oEKsge%;zai0@=8nKo%mWO5y#R*3E1Oc};hYFlG8-p7E+WVLC{pif(X?9FfeFAs zh1FGZ^s9$rK2BSV66g@WH59uEzc6G)cb9Y`D%R61n-%aO1ackUGGeWt8hG3tjB!=s z4pzR}S^xrgO|W>x+>{Fyzg~T&Z*^K}|vnvQph<= zzc-6rgwsvp+-&i!F$0)@ISoqq^9o`deyK#BEe-?sY;bgQBb{`wmIUfqn`8lZ3;{t+ z3Ce_Gr%;A?aupY{M$tM?>o%TiK+YZBC^u0IxmQ@yl12pGv2vA0`9svZ#hZyDEY&4{ z$Rbp?`fcFawdjFr7aIXv++(9YTZc7R2X{=QGleX&&~;DZ`3Ot!;Z0c^CZ>*)7JX8@ z&(BIEZQ2iFP`u($rXK;emcF@k3N{oXk3;s-k!Td$2VEwC7VNJMr${C}^&)VutKg+;BsP?_ zpRiadcdP7RT!8e6qqjQ$SJ>M|z=F<+8r zR5W_UD(W69-oNua3^TCDBUDrEKlluhkIMdw|+aa_AOeja#oZpU=L|HE|(-S zUls?*d5tC)(Tn0dRHmurHcCi-y{pS(f^3&^IB0pkpSNE2ds9|}Zxgx#4nQ81TaLZd zW(8Cb{AiAU%rN`im~W=Uow3oYXx#ESOE)X;YQ!6$K=8*uyGkJt;1xyAV*-|Gh6_ww z$SDTV3rdV?jO!xgQIv=tJ1%64*&K$27FI}c#NhTIv)C8g4KS8{-cQJq*b_ zaNa^d){3k2ql_2YaR3IYGrJE2i?TQfTOvDP;iu}&;0Y}NWv%3~8u6{Dzho~IRPn5Y zkoUK+vC@HVC739_}^zs1;$%BczFJqNk5ft;e z*%qek`?PFhmvme-aq|LP;~dJ;0WOI}l?29FL$i#b9eoN-o<+UlUFryz`kn;wUs7Iz zgG!ncSoql%j4!7H#Jh4B_rYaB9udBf%`c#(phpi-^a+;bm14@n%fuUZY{XOR- zAmomxY+A?=q3D5IRf~i8zo4X{{7JjVor zmq7>(2o`PRQtFOf+MyQ34N(K*qi7xG$ zfO#Jr)&i2s-!s;j7;%vWSrZ{e{)UvNC+Va&dCZ!56KQ2EzdlCXn-$NL6e&G9X~WVZ ze44FoW$o}%D2*1m{GPK$n3rKeUGYS)nH;O~a=1iNTJ5VT{x~3f8WBN)_fe3IeATHR z0^iGSJb9`052#VnF3P#&+spvVeBfwftk^p{iUr!UDVaAeF0$Yl7|Ex$o-`E ziKN`+WGvAcSG~2F_R(i?RmRntJ;Hv$G%4}G5l5nL%7cy8L3V=N)&}4yKzw7wj--Ra zyD&<Y6)4b3U z#w`TkTOwJ&1XkfRX3D~n;n|Jdb+w0?#?2jHx_Sph*P*yuj~+UM)o8rw&O!vXs}6S2 zkGu#Bko@OmDyJ=+hd@V|2xXCFu^@7wwrSHUdhzCXCI+(Mx=r6uy9zR5C+KGZ&FToY zZROX_0T1+oJytY|Y`0{qAz`eg$E0TRpNbfe4yg-6^j1ffEL*r)_pN*yITv4Wi& z%P%{)FnsM*1I3LS1-~(Hn@VL?r}Ki!_#?@o>%gP4OidS|%*<-eopV5Y693l{q&W(f zg8_+|d=wvi~Gjp>6TMNPZ^~W#mm=#?=pMLH3VQBPBzDel*GE zoFMB5IG9HSXl$hx4!f@-te~8Y6;6f4 zDJ)wGudu!0e(@+ox8>o+>nT;8eJNo(JZEOW>`$d4-?_x@C1R~@KcaUL+gg070Hi%7 zuZzO|blUz?E!1hEFwIM7PG{Ot7LWjAErrKQZ`QCJLNu4mXzxcbdmP zBW6uX3?;tbBsKP9WdJbl%!wDRRYTus$i7um^bZI4(2d!&{hYkYvh#!|4@&Y8!!f86 z&ZvD1?_gxYqeSW%u49=)=5wTetW+0v)u~=d+GC?5_hEKSCV{7^MmqWJ3@FX!89A$o zbHorQ1F2;Z_l5Lr@`l4$<+ur)x0N?t`K0BSg)=hcQ(~gN|nd zY2^?3LgBU?YC8_7iGR5qO*C$bMgO?JV9eF6yAx`V4C+QF>e0WA- zzHuRiX+Z^ERM8-&xdnR0P?k_b3Mnl7aRzZLyvg}qt+ozzVXXuQ!b>)sUdAj}nTmd( zJS+teh+7DSn0I#r?p5t%cFEC&M$r+GuIWh>`=Ri(_`)OGe}hDBTmt=Gk|aMZkNZF4 zC3oPlcIRsRp#9ka1n(mzKf{po(m4ZPweqt35Eg;sk#(D*Ve0X?w)PT5sC#75@5k+1 zxd9>zGlMF2?*Vi>P8Ok7LIinY%^9Y zvgu*^jl^i}qnJ+UdS3k!6BO!PFwMOod$pLF2Vcyv5XA;go)M5-{~&S&&10WazehGa zlZeCeDv70LNUPc@JfB5CEJt1P8y{HBk}TdgOPy+>9-d(R%7`Ug;a z+g4^Ewg$UfE_yn4jgSb}WWb*27c;P7Q&G5D9qRm$wT{$!#=PXv;$*u7;Bv`;UkSXL zRGF@HU6BnU+@Hh+Lo!TyA~5P0vN%f9nMkDbb`d|xgGk=g=OD*X-E%`NvHgo$7b6vB zKE=HHI}znXKSJgeB+PuK%#LJwVY3pOW48#{a7T3g!M@I5{8&6Qlr!MeCQDRgT4Gkr zi!5pnIl1f5S0PlwJ>(qZ>jP;gMJNKr{%}%O%O9#hNtPG>Dgig>ica*gwaekGns`j5 z8L}b+rFzRGV{f@)sQmsF+Ke`i`@T@0j!?KM!O@YyC?^KbYQBi@RpWZjUd4Ez){o(X zKu7XFnUdJ+PE8Fjq4v+}o0nW(7@!`%;ELly;2DmPXFM(dxdDZj@P*(Q^>Hk{V`;(N zVh>M+F9Qr%1pOvob}0O0g7Uo}s}k*vjj{Ekf#Aw!L-w8Ud~1!I9CTvP_Lx(A+&}=W zk!1M-7P&*}s$u;+SRn5Tp+@8ft**dC?|Q}+*5*;|I5*6bw(AZawTB`SlShQNcvKua zE#f)(J1Bp{4+|9FyB}3tZ5X{*yO`NO&A19V)5#NYe5gdk{`co3n`CTCqm9@Rl=x?j zq{@Vw5)bSMLq5WrSlo%L%ncJn{cfygmlLa<`MTAy=s}>m?BW*xTevM?CUp9V0YUmn zn4N%ivhb`z71KEz!gTQtSmmRw;e&^sy9K$Bt)6gv#Wr&5k1pQ68=&e!rod1OYEPZK>PvDlj7?#r$1HcVr55>^sbTrP zf?t-1g-j|LJS;Ie z`-CN$=ZOMcwQ{MpCMV&>iz2DtGkZQrMVNlmjOTuH9bYNOO>h9A2{DXc6NRac%MFkEH?&ov~p30LwJ_n9i6!+_?Ivt^BbwOF2Wa6e7GF%ADa5F&PUa7s<&Y zrs4rSw;^3D_)L43@h<_fwF-;ZOA2QB7)gy^e{=mW1_=B5A^3GDI{QIeCclT-`Z_MD zOhr>ZV40K%Zlgv#MgezabJQcV(Z7{=%0v0FmAl%YU#D4t;q>e|^lNKJJcY^<^!AZ9 zF2C+d>Q4e9$<_(|!8~50ZmiJZZt+AkKZEB9in9jKdAJypy7#%9E7e=f3T!{=ky8Fs-%L9b)h_HVpB?3dF$xV2YVF1f<(UH=8y;^a zI?a~JiKE(|>DljCQ&_eyKtF=6vQ3SNbd41St$c~-pr(M4FX*U*R3HBn(FW~s6Df=# za5Wflu*@E$QQjpVd6Pi@`SD5sBCxYC(vKE7!Kwg6k^`58G)p-ydsoEnwi^~A2G4fX z1ed>~QCM>1QinEjOWKHZBY_L0IfPj(Z;kEDi<-^6sSUq=ltJDwXe^>}Va|$v9~5VL z42Lg-ZIM5B7Gt;s)U>MbgAPV0r!DqsEJe~zpVM={lK}X+7(B1HMA_Ye3U@`>wZ|VE zGpx?XU3HCJ;l|e@p6z4Ww?5`$)N#dyamsn`(ViBJ>M+~oWBffF` z&FP5Nk{MyP9j3)1uMC%09?qqE0=RQAEaic=v1nRyWTcaQ%iiB0)NQN;K5)56JbAl>9@=1bll>} zWR%e;V@I3=@gE*760be8pE+bh?KQa59?tMdsmOMh{5^%;47>p|T0mnh?i+XXp!Pk; zJuYY9^B0~&Jb|zRyc|sVmETB0&#);lVNhd7@yYQX@^|OsNP_Qq^%XBu(ePo%?SmwhE{BEw<(LT!x8ib>7Tu$DjF$AVoGUdeEGyrsnF58w(C@KnbO;J3861kY8Suq zz@p&?+V1kq__PM|V-vk!mb~5gc|^hw2ME;-RicgnaP~~RDaD?BU63ah0~cY=Bd~_c z&w!Y6r;)U6R1A%uE%eeSbBG<^F#6xeAAFp^;;2vE8Y%r~U{TXvsWUr_#` zlUCpkbnXdY!D42y!}$lr>{%e!`LE$;ytUFSS#xkJG}rbZZCA9 z&6f9DAP^0^QCnrrSL_g@F8~B8gJ5&#jMZkP)*x~lJ#mI2#O-%VhS>OebJA1mb6Qp* zGkdrt(eL{7<{y{LC82=dh&taFDz+>Q@-L@mgI;^%+u=f;*9=SsqBh$bI)&?OgPz@i1SMA! zs!AbdKt~B@U_nbZWt`4=D=L9{14eh2_KHzz#(swo6c%wEw1>?1qMn`5$Qd<4{Lo)LiS7<8c)TtSX*rNo-`!>1Ad#C_2uU&fa@C@j9|`IIFtWLCFYQh;;b zR+GE+sZ{D|$hQGyQ#Y!QKn{j33z6Oh@qoI>&4h9l-zuODCcm8iBqVQ7HNHP&fy$uU z7PPF@b}$ofX`%fYVb_|3N@2i!hLsV~irl5KOt!mq8F50!4=j=EeAiyUT6*)*LwxL3|8#mdZzTA8BZnv8Ut~S(q!QeEe?C z6~x?hNxIiGRKOF(R$es^*gF|6a%&iC^js7 z3Z0wJlw|(Dc3NH;`mAI5zBSV$gb&8#bT73g=MDypj-T+$gkLZSGrS`=jmSf+y}OiQ zIZ1t}b7ro;pyXA0#^CLEJU*C%S`8RckdQjhM=mu=JC$FMnE2yOJ=%WfC;)VbNNR<` znmcE#zsU7*1cozD6=Z;{^%%tDElQ4Kpv(rroY+TrOa=PRS?5lXHj5fBEF*)K>tXn(C(q3kAW8SY*2)c>@S1gJuDjr2!!nXF-!L` zJ8hN365?iWt71Kq!)Pzw&n(bpS)D{mAl1nmWrjMZ)mS2Z;)`o@_65 z&e;u0n98|hq%?g%Amhyu_yv*Zvr+)V{}nQxj|?z(?D329`DtohJk&CmpXH~@ zy`&3{nrQnpM(y&`hscgq5)}noZu|c0Rd?kie$zY?o1$SEJ|V_zZ(3kDyUa8$MW)gg z?{f~H!VnS~rTY*)$0rdT*oJB%ibICzu+_^QRYEZH0&auOW*P#!N7pS-aEr=%hfCPrNP~UL32~C~>vAgYPs-Ji7t3wW8~^xnarivq#M;idBK?<)UnK zrYV--jzu8NhQ>DUK)d6`xLQ$XL{6KxMDMDIB+Afz65O{GbS3Rx@*h><3a&eqBMP^a zTR5w!YZi$A_W&xF!bikA%9%8N=vl}=`3rB=S|--SDXrU-V`w{CjtUpuaVuzEHujvn zSweO1m*!ff1}-u}LKX58ryHs-a2*ZLR)oX0U=cvMni&EMCY3Gs@qw7F-cJnZq3Tye zRIQ^LH-vr%KR5b|l|^XYfYZ|I1pNy^I`nV*m#G3;XwqlRfg@`Q*oy)6E@%Agc$>b) zNC|6C6C9`9$K=F~2h>Cnyj9>RpMZQTDM^80f+^>4l?+=kB-UMqLJRIZ2@tdCMWMI6zFi} z#-|Dy60bDQTAz18aVehuO$S#MkH#VM6+>3KG|H(a*Vx0?=K&j{N@O1-F-hJ9#>8e< z)tg~_#dVr>6K!G&TSj?t{_fPSv}@YYq{w*g+gXr1X*0<&!I%xVfM`o;MyZ7!GRHWP z`hkK0+yc>`UcRFuQybCsn7$f##K zXy}-6QRKZ81TDkDW!WhV*Bx5;^EPtCk|B{Pp~mo!y2`RMvVPs)+u(Hh!_-8ZG@WNC zqSgsSWi75akdS6!>ENBJ7)rlVq9_Kkrg0rh_(zzMOgk)_G&VI&?E9#VHE-na>Dq z5tmb-h%=GDO zg)kD6Gppwjwf-NS{|@jDaG^Xl!SWJi)d(+dM>a1tb_Dt8MKkq3i<@}Ql(x@f%-!$f z2<;BISZwFQC#4;_EPVGDTg+76+KJRY?1NEV>2h51k4E0&CANzatPt@71qOn;{37}f z7zl_5^8e*N_5Z)_b9nCm*L@=Vf83{%gPpm&v5U+9fB#wdKmS?y|Ms7~|MQ=WXUzZe zpEE&}=A_Mh0@Y8#?o9{Lr4jfVw?XWv|61#NS-rgTb(@m$EP(V~OGVOR!$7nU{zpI+ zPGgw!W|^W!kHBnh>d>1Lfvh0AMBH0mke-hEO$q64qNeFybW;E#yqYV-J=G5<)%TErFcyR~Yx2NIxi1 zQyp0)rfatVw!6-SeMX5*oPR%#AC&|3XziZKT+W%%%66hHN&MJJ|%f<#{~ zE}Zk|T%q~F9r3s!ypdz%zZy2*&J?Jg6X+$-HlpG~W)&u|(iwWP*5^!TBK)8XsCux7 z{kYS_LwOw7lw2Z;O|v+vS-p^{8|o%c|6rtvzre#_M3aps^&N5ntjjWs>OwQqMXaAL zX3-PY`W-<4P45QKFemM$uN@L0#Hwd}hu5pUS*@_V7I=V7w zx+8ICHIh;x=`xU8CL@iXWQzH{@k6p?tKK^pEAvrqJ?FG~#lKtR=c z1oT|Vk6kACLz!dE(Wv!a$6}#csk6ur!6lzcHb+Yg9)?Lz?#04e=ZsKKl_x5e3qG7u z4s}*}he$1%FB4P#Kg*-%>$<6t)crMm@bLx6aEp$+Yh?$Z;x^eB>ZWOpeRs@~1us}D zBw4O&k~i>?j5qG3%3>*DPwMh4-N)I+)BU%>N}$Gc7)Ju~%HjEtgTE3Q5Wy#&o_o>b zn^WE$*IN0$y}=r-IaG{JDTtD|gD`3i*PP{NT% zTaRjPm0{?Tr@TB%`VHl+sVpxm}))3XEXJkm&O#u$L$- z8eb))&pZUO<+{9_DCpe++O%PHRm@0~Q}2_p?dkW$2r6;_)sQsbT z!sD3OEwxr2hnoInJ}`bW{CAT-MG>M&yL`l*cEuy;sv2VXC*KQv6DZ@4Xd(FLVr++FH0 zaS4nEU59e~p4E;58+OqWn#`-zX}+!;N+Rv#(AJ^uZIM3e5jFJ4?FjKhj$tTTLMY;) zvU?-X)MD>lMb3v!c*>|#GZwFSQ{p%+lIJVp>-(|dXW2oZMfoEj*C-01B9((A-jQ%h zcqAsx%R^4SgSvZ~BUJrE>`rrpbn@;N!|iHUfd&RVBv*T!7?^743@HA9Y|DdExcnt@ zb)wP%ya<&?deA4R1S({PQ0Xd2HL?a|sMy>_J(&rc_VHnx?IAp!ouD8WH|h*`xY=nNF$bX1LLAFYUULN5q+c z9vw>n{UMDS%%`A0`2~=PyF?Sg*pQ)6b*AWh_9RlR$RvvO$RLsy{2VkKq1+Xet=~9ny}i17gdokOAF3YMsQ4cZaJ9yvZ^c;sG5Y+EAIh5^Ao5VOfz zqx8(6K}9~o_w6(#eqgGn#40dr5LY2ztQ|y0MEe*AeCg7B6pLzh4{uLm1V%aHNBc2+ zr^?U};srM}@>XSNUHss?RdT4Khp8SNKe8cnIf#(MWGL@t4NWQo{K<8i7QA6Pt30ZFqx)`fxthy0i! zs;d&CIePgXjW$ygbtXFmG0JgT=#H(YlL=NVj#@A}dB}j`Ju=s2t^p(a ziY=ys?WY-qW7CnnYcFRxZti?goG3=@@SSk+Tg@@znDrgw0Q>AQD~d(>dV=JI+K}>t z!JZ8cxz63#aMAT?m#BVS=NQ zJFgX#%1qbtX$@d13zy06pD`|#&IyRzxB+*wd25|fMgp_T73h?1_awLq+@2Dws4&WS z@~U%L-sTB$Nu$2GtZw4wi4Pbh$FEClE7dwKotd%AZ~Q=J;z~$H32G&S+ojXPl{jl* z`nGS}GNU!tD_5rGuT9-lI|FQACm+#(PAq5eWeI26%Pc}izDOp`7kFOz`L3r6bW?bg@B!rQ zP@;lq!;U}zjt$42UF39Oz^n~{0+(l`E7oI!a~j5A;Vi$;!k=rkjNww_YiYBn_bZ7>n#e@m>KfNQ59R^r;fkPrn+I<;uY zfYIJllyh2cb6-{JV8hZIM2?tT*K1Tf?HJ&0FWb?rbRv8Z!B6PVKn`LpA&74HO$cj#(xQ*ei&SRZHP50UO=d}bVRNX zuWCpU>mf>4_yv##z`(@Mb2}P(q}B8q!*9FwK~21{r!}WyK??#xNjID;2UUg9g zWtKZlP9oC;20-xJpeRgV6qNJfvtYf2nYj5Bkum9S8P7H#dUHi&MSBvtOmQBi_-RpD z4i5pNRtXx2L-y?jnb5gZ?Z>j*C0KGThLxSiRKkgI7hWkDdXS)V{s;pr zs90O17q|e6db@dDyK7wy2ya9~5mTRejTV*~xh~p8TDAm<06imSCZiS=ycAIn`B6fC z5S1uB>m~woIvEEI6a1Xv=1T9#+&qg6k@3f^=W^;ckr?nKwOeJ6FkRhFKy~(w%epE7Q7%fRC-OQd9 z5<9I#+^==KOM7@O>5+1>lu~CHNUzNW3n{!{1seagm9&eP zKaolv^KAfOKBtP7V7*8>D)iti0maN&u<0u(QiVVzyH9PVwM1k&MMnFk9ga%?Tb=Zq z(MNT95ra_#{ebwP=^s&$VR=bnruTtL=85W9gG5`ih)N!8K0+TLb`R|k`@VW$AxbqG zDPqF_dl=(AH8J?2eDvbCx>5p zxl1B8eh0T)iXxsO8q9eVZW_Mbx{mWp7VpRl;-mNMT76AtdUf!e3V;Oi%kHZyml^hCTMP$jkjqG*Wu(zo0;@1YO$Opo=S3r*Ea+2h za4nzFH8xl9Jl-9#NG%NNkawwg4bGWDwKXRW()S6v4_1z}{Z_J(>C&SNEue4mv=b9q zdX-)9T+@wQ=9?-Cz_cYj4@9HgP)RSQc~nE1S70}kv3gGF ztTOjDPlxm?zZ?IAdRz~caW)IjP-I3U;JN8NhCqR$g#V&tu`9xvOxQwMBDbQFNxqYp z=f9O+JR3K#qWY~?t+1qMOt;B%aHNyx{91Ay-^;#GlIl0r{1)x>iZPqZ~Rn4{8fa7ZE8hVMpr84u!3eY@UgJIoXrW${c~10%0L&J zH6&XPz)`cq=rEZEfgBIXLbO{~pyJN~#US+=4VMGa zJQT|apDu{55as-TJF4c@5pqMG)~EgTDF&6? z=rSVZw}-g`3OCce0(uNon#xBl9-0+(Wy~Tl0cq7uc4ybHb(yXXkU?ypp zfzbGldMNbySA1D+J@B1nw6i5GV0qH;)LU##4zhVq_6`}X^C;^kkPsQns7j=5P8mVB zJc(!o(ed-#14`lhcEJO)K(I4SZtf0f8{&$MO1l&S@`MVogxNKWlVPeN_pL~k5tSEg zz^hIY_S+9YkPJ=M=c+Qrcif~N(L%CJ9BpcE+QlVb;%V9*X#X1XGKjfEkp=HdQ<$=a zYzTTrAd*Cfl#j@hU3F1j$BIhV>is4_lf`z88!nasNea!%PjzU2b+bJ$lqCn+aNZFsDw6{?jRZfgcJ8uJ$af z;-<9}Hl6*64>{{@w5~tvVG(B0xHoD#~pf-0Zum{lTmm> zVxq-~Jw@Y|tD{|mRXHT7F#`}#(%c|~81l)LFVr)$9ymaB+-)qt%!8ge=k=E}US;q2 zA2Yk@>M(lS2Imk8yZsAqltk@hvW(UOWos{Vw&rv}HzEf$*MY|vr+>Ft(ag^Q7AK`J z;V5M;LrxFy9k@(Y{cN)OFr4g-(gq~4dw~S zB*AxnYkQpGGecAqG9s7f_=8K1*gG(|#z{R?JdEY#EAL2!2R6+@6fc~TvMv?_uqv#x2%(?~3Vexfu!u3BJ6ZL%w>uxvne}1SPS@MP_rGN})A|5)3ZG1Q@YudTQCMx^uR{xcZmUzot0~7AuXU(Em$XlY_fdXhSJMYzpTg zq^+R9z>moFtmGi-P*&Ygz6c|8JM)gp^@6rVv<(@%WwPu!9BEn){-%c_>9URpup83^ zqE1byq)i3V+4P_}Ust-}w`$aHJLeQuQlzBX4G~zpu?mM_Dd+db7K=B6M4q})sH!j} z58>>_g|5UaJWIjZI$5dUj>CeSGfn{i9VFSOyMCJps9fWQbjwdqY#1CPb}12EX4{Yx zx0BU08*4)mh>Dg%5-hIu!~h)xW{7)?%i;K%<6oRAF^-VlnLJab?*&Z;my3|*AH`lK zQt+8#S=T3(9ojiR)0NF9@gpS{!Izu@^1D(rus?ET=P82Kg3!%Xm(GC}fR2siRESx* z1)P)M>wM(ko+`+dMv}~OR-&g=#0e zkON&K5z_AP1ONi$2&bWE%my&O3lXjHO_!*sJ{SK4u;iTq0zsR!(MesbVlW%ivhzF= z%x#tro}MwH6?3kqz<1C~q5=b?xYN~P{K9-*>p8vo4(AH0xtFk2@#_|NC|11CDn>}7 zp4t#qZ!t3@>5Mz9)gvshY<6V*<_&j~x2vkARX|+fI^|ecfSg7`SPyg)%xC8D0pK! z+^3a-*W0Poz~gnyhbV`+8y?lUl4)aJ5G?BNI@x<+r=QO)L{P@PWS(u8*0DUQ<8`g> zbD=oygC_y$EeCDrA(h@wK2(xy>w`Bnk2oOYYMKzv`;r};!gy!-SGlENpLEr<*^~8y zO{aE7&1uMt71q}T4er9En>?bPZ!)b)(>U}($TJLK%kwN$Ugd&kiQETT z$+^7JBnLdk55OV6ZQ119L>zM9LrkmSo~Bs5$x82hjefv9EMx4$MGY}e>^AssNqtl_ zz_YDfd42t+B~UYGajQztY+rq-SP|^-AlUKbL6uwQi$xtF#(Mz6V$pP*0<`E!YD_L4 ztT>)u!a`AZNJj7!ZD1yAsuNu9qX`{!`i6;K#z&^^z|MPQHP=dM$HUcm#K!mS2#5-! zBfbpNVXQ-Fc)|3k4!AkHq;7P&a`VWoUX*zktb!0t_Za)2gUx~_YNHM^dRxE|#AOO; zwbZHgTOMLjUJ~q0H7cW>(;j@4nvLvAtCgm=OS9azKj9;%mDL%R()-!O65%6wX-?1k zrPWyKt|O764u}2q>A8UI5((hdkQTtiLWCyMPsc=LP-Ooog@M$rzJVJHfiCg`G|sK^%!2}8K^3@lVU2Lrxr|FLBpI$Yz}t)itvHfK z(fxNu?;$W&;x#R#b>Jjq_f@(E!FW)1)k~tfVx1l8?Ordpyju9g#cjnBkC@sujJkeC zed+_IGS!o@bDG|n#h-&s@d%BcyZu}Xt%qhi#mN>tV{V4$5lAbbc;g78;{$8CT!8aF%XPZ27XxDRfHRSX8BVX3?d6 zwMVXaH3-fd1g~|2?KYGmq5AiEjvWjFM|$|#U8_}b*k9iTISZgMPc1>$taQ*laM6yO znQTkCGpUQ#9=apo2s=*-kgz|UtqM!6U;TgO3?gx9eX~o8t1K`t&Rk+!ijwMv6xUZi zbU-V%_P!407JC#?BU~YfJVMBru~zhKdL!kPqTTc>bJtQN{7J{O20o~{}18z*qaLjyb1iS-QKlr+qP}nHcs19+qP}nwr$((>8Z~? zo6RQw?3?`pGm}g*x#q<$A%T}*r)Xa!MNUFv+pieZC@=J~B?F_1Ckm5ApTl3;4Iffw z527MKa~WY5;89$cWZTurHsVuF7FNp!5$6&7JmlzfXJrs#Pg`Lu28BQ~U z31FLpv?*+huNJgFD;1cbNbYQij*zeiJtg*a@k^U3%&3Y%Z;>kt-oG+B-Pe2ng=&>& zMz1@BR}T85YbnQ53B%j&ytdj&9l#eHydZIwVWk0P%qN}2=xJK5Ka8fu<@z*`F8mlJ z|2tvSR?3t!A#?inY+-=oI#K91G$`@eVR@_e05d?$ze(yZ;2@+&%QBElmc zxV9cbC}_8=>2Ew(Ml-f{Sb}oc$@zG2JO&4~A5!4~WT=6>z?I9*mkTE{{5@?D>@j=YY9nWfw3I}|HClbLT!JY|o%wFq= zy0MdMUh;QTW5m^`zFZ0pT5?4NgM}=|y_wrj4S)p0Pn^?DHu<~5#Pv*;aO)XMr=bJK zZU22qk5xf&&Wjl*o^8=F%qX2=58$lH@nWYCWyfY!+i36a_@@Ig;8lMkbU;jGailpa z?anaAQqIeH)&}deWBQZ_gF7f^i+4sb#`BNv-V*lt`Wq9MTI-A(L*T{kN5eKOjY4`S zp-VO;vL}%qe)9k$Q8MJ2GI}y;Y=x{v$p;LFl9DY7UOlZ5+;0xL$nD!$>otCCjYW zC=Bn841F~A%KVV;_}EAVw{&mGn9QP;U)6XKU0@p_n5np7AKTJ5Wnk8p%dbXUoCG=^;9~=~>KJAFp!vK^K?Xh)|yBUPJ*U+}y=Ci!QAD^eLjA zFG;W;(SAd3b$`Yr)NnVR2nZ*4=#7EHW3z!>`Q{Ez-1OBh`Yjg2vk{&# zy5*GMM>Tw6(KBssbb325Nv%XB3gEqs3DgX77HaQXbivY3{l)Yoi^PNVeD8Z!EwA`< zwjm_go3~l%spMf%9%X1pYKo~HFucAZbf~Z}vKfvkl}_y7ea`Lih;emkFkRJX2_N}{ zT${$60awE-NgT1!Dh=k9Kp(kQZPbw;<6{AhaU_8M9rqSS!qI5Fd0U1@7eWZkeIuw_ z?H93RG#DD5Y^yy)kB_yuqHG(S4G}F8SSrGmCAezlzO<)f4d0ezo54+q+tliG*bC8E z%XVt{qR>W6GXovRC3)l52%+noPQgKHXI{V*^R}Yq+Xu2_{JfTE|FK-e6-AP%E5>(0 zjqdmnS{o||r65JRPCdmxJ;_vPngehSBr89(&<+U4)n-I~Ed-!AgF<4yEP9T&JL~xj z1C?+=ahY{N^>R4j2ViiUCbqN9j6758FbHXMtD~JxUm>(O=glBkJxRd>$<0xn0yk;@ zSum|$vW34Mf|mDx&;hSYD{_Ai1o?3~$yMuU2WRGRu;bAkywW6IR_O3QU*M1_je`C* zK<70Ib}_If&<%Se#qQM<9vNpYBoaOjkYaLG-}0DN^5@^S$fOu8`h_4yt9iRmzeTYN93x@o2g7>0JIp zB6m_8OWravpp&`DoI8EZQT?x#Pm$LH0li z#nJ;2v*U9*WO!rv0I8qVCu(_b;A$1w&SO7}@Y_7jMbT+t6x|eQ#E|6e62~O^Q)XG} zZvau@I(;No=R}+m|MmH~{FK}m0gcpaI7>&igJkT6tA-O4RS;A&v(Iz0iPzDF1oLw; zdyQivCM*Ll=Uar4*qu$_!!^;wRGVqSoVVJ6JXO#l&`91rY7_n!e4Lm*C+C?8RL@11 zZ0)`=;@)^x>U|a9(v_jtWT%T;{tUzR7j`j;Dl)|k?&$rqe0jnmk=#yVWt6)E0g|8x z+&o%S!XQf5RZFY_T+#^jFy1JLRg3jD6E{JqJ-QOl^Ey0utMj>u)e^mdx~25R6Nb!y zt|$rWz6mxLRN?ZgLxBH`FO%69VQ~hxST0078|A?D-MCAo;!fl3(E1;UMaql`y%|9M z@7@m|Ek=YkP$I853({M|-GNP)Gn|B>@bxW9+&bcWIf}Tz01>)3C%=_6sP%UrB&#OqeemQG zx*%}nAlE|hwIBed3;pkST%z?SNx})HKC^}G)B|X%8#^$2l-NZA;unuwNMYD&A~69v z(Kx+s@e5^Q-!6^})ES7AIZ`9`YNEU@8*(__@Amfd3XoR=NXms9F+>@>X!J8(rOYox z`rWgv9M>rTPtIe-EN%yRv8kZbyQWe&d{Ja%2kXr_d`p-MGPS&-R=KmlFoemol9um4 z3x{A&(KDW-5ob_clBj`JPNkgHs!?J)t{n*Oxd_o~X|Rw0{3u$!5ICY8EblerHe(}J zDB8baji+q`;h~;&JhM)4_XIVR;;X>5tXv=WXng& z&?4+A;1j)Igny1{AYmTN!<#59XCaJHFpXcLVF!l*9`t(qG2lYZQKCaO9WLcRgPPbsl*7a*Q*$0IztOb}!%) zQ}V6*f?06mc6~so=i=CmhB|VaB3?$5Y zSBzHp7i$uTTVeS+L&S>%hAs?4@!IJ51WpJAo1m9^^eHQk*UW0xU7U6bK2kV6ClaALUkz;T1*IsVpHw36`Z~@A?1gIiPNT+Z2-bla z)A-fcm^Bl{Dw(&zOb*Ue;&#%LgZCzAo(HI+oGUi0V8_AeN(^I&e{?s-(@h*-DigKM zlRn$bS@7O5*k;Viz$}D9hHwgIiEB&D9ZX_Du1Nfr>=~&EsIXKI!h@+eq||I*n3@f5 z>Lv8X0Ny4o*_^D63o4c$e7Aq0^>@Jy-(Qz{C!<{ND3X$?7fx0-OKdOzvn z>JP{nMLQy2CflI30SOSb2ILqH6Om)y#+1wJ3UxbiK9O7aMXr@L{zbvq;dkm>AzeNE?$TI#x>E#y7VrpPw-s zk7;g)1rUdwSvdufHW1DpPNTE%HkD9E)=DEb%0l2E_9k8{1e0jyrQ^~y&f&NYb6dAA z>s`@N^u{?xzX+1`co2PH*632ia?R!u*j~dsew9f!<+uXX zJ{m2f@6kJ2-(An7WneM@s`E1ovJ!D2iloe-F@EYo zMWhb^7ycW=Qt2Mz@<1!9dyigy!5>618SNPmN?2C0(yT4oyr+{D?NIowO<3!SmTP8+ zES(I}sL%nAd@ro;sSAV1nBD{yuBv2Wte|pqwtXrp4>mY-phjm%DinZ4>#TwnOtgIB z?ZLJ)5hmx@`}w5WKsr;jyd+sp)^%0CVe4VWda$_T@F6mw3&mbgEpk2GuKg(X&x?PP z;7zO*0R`}L&Um*?5gQXTeLRW*LgZ{aG`LX53T(x}h~5>9^BmaUcHyOgnAK-KbGfIi-QJ$^&{wP` z{9J`voEs#YZqH60Eox>z91y`8hf?J zu@tB|OVpzV!JOf27mn&NHtOyW*ph`uM2tH zkNXS~*RiPS=HcKYLK~+|?WvVb`Gm1j*Ey4aXeUhT!kZ-GKv^31YbplCAf#=WpEIzh zJ=2~!g8*xbb|gUpNb#a2D>4rO1(XOjp&~ta5y0Mh<8A1A*9-+7ry4)EQ?v50ASs}h zDy>?%0sUv4SG%>8opjKw4XF&N`bDYpejpiE=`1KA{7sI$wLyz~gTkZmtEor#*!X{l zU#^bb2B!>YY=6}u&f6kae5ip)I*>_W$PFyyQ%Wi8c@|8-;i4T{A9wLdg6`lGO%d~r zo!`fwAbc2YJG4&DPM8Ue+PQ0DwcI%bZCYMl*~_yZ>h18$w5Y({uW7%t~=3p?l` zJzpW-e|~cndrt8S;0(CTE!~pn28YfGB&+!}f<9zR9}Mz$9Bt&g0?#lr3SCn<2n~fA zl-{fD-Rp~f1_N!1yJy(r!t6*#%rWDA<0p!=Krp5Bg`OtViz5WC;9+>7uG7*N1D_&O z9_}~@W$_SUWjxtTK-x2amX-^PMtM(4|6Jm?Wb7vH0l%Jk#HRBi*XHrcn*$WJ&3$PD z`R_;uH`5BhXVZyt457dTFpKG*FzhKfQ9$4vXis5yqR_!pAfN~Q)Y32hJ1mvp*fqES zw3VJn>65VVY{SpAuHEYszUYh(K;mj}EsR4?l}7D`*o$s;k)r42#WS#$+$}+15WD{B zx{&DYs|dON-Y%Dp@QRX0^09T3m#*)pQvxoWnYRhsYsrBSJv9Sm?@_g4PU z-Ck#A=jiy>3AxwDnCZ_L;H-wR-OWwI+GA6&?VYb(zZpEx)iH}iRbRS-O)%hTjT(p! zC^+*qvEsWdan78t0emh}V3{>guFSlLM%0+ZsoMq2NymJ4p4`*eIaO9|TB;lvtpQU{ zO2rJk5DRQr_oF$Pu7QQK#!Q!zn{1ar1NaLDC4Z|%%KQh{-BDggEO#ur$@!s^ZZItC zx48NQ2Qc#}SugJo*jc4r#gZ0#2r#i$pfY|OxwR{;{rjU2Ov#qKa#FV?YD}6b2(v*b zaNZQf0|9ixf<}4E(q6bt_4sRMmtT^Fj3eVl84@#Z7QKdmY03;U?tSIIrBWL}7tvGE zw92mBU6x~IAen+`+l>S%c>eCinIK^$fOsei+6NYXNaw?rC3wl>$X?~Bh7C%-y zYU#1L$->i^i;FFDhFOV&ot=|qYF}({@553++nPj5hB5;?&}sYi`|^01TG4A!**5e8 zrY%MQUwzxa95%N`>0-7?=5IQJ?*1DLG*U-*K_VW~ck86``~v)wojCykly%5`8TPi| zFQ>OEvLH8F!C`-<0q}b|=b=)g#+m;;Isy|otM=)2w9dx}E=u4CO_$aJT??>1NORD# zBeTdASg@0X<7+pH#IslJu>vAIeo>dj#h=!O9_{Y&#z54HJGsBcM_J@LUPSEBjBL@O zg_o+SP|*-c0@!3NDr-r?>&(6w3KYx@giH@|IsjLRd;vua|A;~+T2DMLorVNsxH~*} zwl|7!EnyZGcr6{*j8Kmb-|35N{>ri86)*md3Vo%2^byh&)3~D}VZj%jt!meXI7ILo zv!itr@K_;*Tu`qm$UvG3e4kD1gIZaLe=s@r5i?>>Wh>g6il0P~;yQ|tQNHwej_XOF zaq1JA1^jI?mdG&^S)zC%AD&}tM7ziI`_V{hixkO^m4JATwrb8{o~5qa-HALUFVC7s zAD3X7J_;^y39L2K>5C#C%2!mo zw4RFv{(Vy%o;jp@#a$=8Z(0K<7d)*>$qg5sy951XX&upmW{ZfWejNn`cv=dw>vTmd zcOj+5*$*>VRdptPk^17{)J#eK*Or(Cqdk4nkPG#3^m)ZuWR?-w_ckIbSdv#5mmCZI zdD0J`(x-Kh?RpC`8TLS+2cybhMG2l03uE>FJR@z5I2G5s% zbj_Z`_Lg=!o;lv|SV+H9Ae) zT|9LHp}#TFA`lW#C#}yxU8?(CgkGl`Kz3B4EgI@Mf>RLQI~6rawb+=QGk{#2=yV{Z zwA{80#$KPIT*xuC!*t%c*(}|EHoqT6+aLA?({}u&2Vbdc50jBkDK9T zPzYK7)>?Qx9^!+kP|WJl>y(tw=$b_MNyemjTRL=FQYzx z*nC$N*>*t3Fyc##EcE{tKJ=Uj;Ta@9r?gVp76HDEw2HV)AUI@tz;@+fc}kS-0En(3%=p(}ew9eYr;OqcZR3lx!@fIS@73{D9&-d5aGsZv<~^ z>pw7=FeuV|Yp^()z>B?!4GRV*Yzk{#Tv1>r#JVbP;Q7#7Q0S$Ar{ge&xD@w*cPb`E z`Dlb&i(Y7Wks~J2nL~hd2=l6P|ErPg{k+ZZA@rDkew0ldveK*{!tiqO&7@~$!R%?& zQcguHH#nH@AOm`!!eQv{uyd+79q@Jy?1Uqyoe1WN`zb;z)pYhe@AZQ{6sb!2FNdvo z&%+nwc$Eh03bTyOCqVQiIF8Ec!{h)Q!oLA)7oxP3y~5iSzc?-z#1bxEvOv z*eP{+YUdTftfiQtR=L622OFOqwV2y(Ft#X~DM}87u}@ybn$metj(~)N>*-FWCt=Zk}~f zzA#4`*~ScuCSerr)O6w4(SHLBwIPG2bmX6^=4| zAoqGIWf&=0oAeA0TRu9M4+5CV{B|)iVIcLaAgKg9?P|=e*!o`!i_V`^*tEZoCda(u zN430SR?f$%+DVC2;;W!zUdJHDrt>~+MtkolMZb&;E+_6QNdK63A;$t(qge;)3vj^h zVwKx-eaNh_Sd$P6mnPthLG6i+2sjaCbnVefhPt)MK6+S{9W1v_)wFbu8H0@5z*fr@ zbpYnm4R+rIf&ljHP+UbD&(&HQl*4eliYyS?Yr6>m@qq*%QX?UKH20I_YB%s^30)>| zZ@O(peKY3^x%Dni(a1l10PPOlq#|!BGB&0wAi{!JaZ#7|gbzc_iPZhDu$92=ZAQHP z95*ED-yVVQ|6ripXa9qNn*3h|`n~%9GEmh2!$4KcO^xkL-R+Fs%#}3${}#0De_POB z|I>oTPJ_U%q@OYYopgDifyTuo)ywkFOC*Vvkz{|D+U^=tgV5i}(w!XeT!WS){5M(Sc|mpnew=yJ0L>2vaq zjmdF;`ld1~EI(oEq}K+9qv3}lvM2#WBi*Nk_W4wpZdv)+eiETrNW;v(P}E=W(1Z7C zGKqpPnkB?&BM%Sw+oyAi(o`Ycjt*?f)cU6#oqu1&Shtl72@aZG(CNXsm*Z}hrF?6r z-bWLB#6ODG9=-2n+u~##qX}$vHA>q04vvUQ=eNg+$u#V}&2C(jLyWVJ}nhYkh zF~)_Z%+EkUmnPW`?4%%NT#ZRAiW_pDd73Gowk?+J+#qM#X3!f5PwgUbcM=yGm}C0f zJR81CQ&3%@+2Q!&!BaZ}5aIcc#Md}Tbtni3&)#0&iDkK!8+2p${NXpxJVg$+1uVsN zWlMrF%~)L+cTr4Qa~j{HFyRC^0x!}0E3LGLSHsDjj2!4tPCLnjeXj4ao;#EsNL2*8 zH5`y*4p3qbN$c$$80v zf5j<|q~E3@NbXlpifp; zq3c+bR5mf^2r~Xj={Rj0A~qq%zY!ZfUJ!+5)`r^O`Exv z$eledi1&?V;G2BPG6VUVE<1jz{m9WpJ<@;+a!xy^S^{LlQH>$KV=ISzA^BrUhoFvd z$lqPe(U5;hhF4qNAT#89t?aNh;a;!8^*Y<=h9Q|ogQII<9>PQX`ba1rS}raSW@$K|4d z{p$_Q)z#qp>J z9~M8dHVnyD{M1C9eIFteB{xax5VkNpAnClw+F$kPLuy_hFA|X)kF_}5-r@3{K+4+{ z;81RfOvl;|O}4~r(d0(~R$zd7OgvqLb1MSs-ZhO^lxF|2nIMoiBu}$&qJSc?e=*?k z8T4OkuiUw2(DmsyN%Te}qNDj59l!RK%2*w6359LuzcmJ>^C843zd-szW#{u$M{rV zD*iBkKJsP2+DTxF9wI;~^~BLqn86#P_KC)at;ZoC3*Jutgf;F`G??<-Lj#wj@Hiqe z-4b_1AA)=@*T(;rByD&!X?;v2=F`V>FQw*EwPhJ@gkurffb)_5Os|%my#r6UnV9|f zphKTvz;(`Gn>hSmPA=TRpeny!#Tqr!Gn4$_U#LcF6&oLLiW zd1s`REKuEDM7s9(7e;34(|q{Af%-o$p(Aa^QD-k|a|3mMLXOG^>|Qqa19I8JnoT{0 z*$q*W^W=<;x3P#@Oq*+FRk?Dk!SMaRWOr<6bST#tu7*0dT_i7n=yJbhPLs+KWW~~) zqmKi6Gd`{{Wa`TRDd?pE9kKMxCf!&Gjw8^Q(QOrnC=8T0vK5n{D`U%u-W?)eA@Xto?Zj4%j< zXlYs`Bhjozy2?g(cHkv@K*13VX`6rWk~2BKtu8ywtai13+j&~j4}G(Dn+o9vd-xU~ znNS%V^y)!j5&GF0HC`;(VCv>f*-ji2%zIB$ST_TTnuf{2-<0%_m{^I@KN#o)`sKo3 zp((`U_Odk_)opo4%_=#59V091Xbq2uK1F&As^=x0X-$b8n7HbaN**dAE73+@7r6z% zxg)fTP~QOiB}Az+{A>=hdPv)DktHyFxX@>{CYPvr{P(7F?C9%F>IK`S8g9Id*!$-z z;%%!^jcFCSA2YKt(-5jvmNX6a%z~=ViyJV-z>?3Xr6-a6gdpbgsP~LgK4yDx4sDCM zYPxT+^U-d$whNjsUs^8_LV#mz8l~S8v59LPglx&!T(1}u`8ZKX4;&)b?rV$ke`5+qu+dKas*D%! zzNa5$p)9&Z63gaxyI}|=Vg+vUL-tqQpXipDHgM3qK#G|YoBy^bT~v{nD2g$Ta+sXF zRauw_3R_hRE~2#~F-tN`2D#yFz5fmBH{VOHo`C$*y^>?XQ9lbetrADg=j8ez#7ycF zl7a4E6w@sJKyu4e(tLy{3E9ga75G;HWVvTw3=Y9!!9!#xQ_qoai=;9pG=7rN>KUqG zyqMJJU^!b5+;?m?v)1C|s+YdY0{}-k=9FiaWqmtf;A-+2s;`?pSd>$L7Bx%7Cz=a) zY~p1_KXo@)ed-o@cVH_d!&-h&=!3~`(+l){j@BXEyAq2Dog2kVKP)ypf0WWNkA3L zepa-%GzaZd2_MKeiT;x%5^8Nh^g()4O(UUNwD>^Tpe;a;I#M$jZlft(xl+`x#EQI( z6K4XEswu(6%9=Hq8>dWqN@IrL5sw8oWP-odskSCVd&-cZO6Gki&fxvFiLBLt#LUH# zm2w@U>e1yW7Rd>R2dnUxtqog=+AjgMs{T9ZPmwW1uPqICvGR{sX?2MxRS@c4011?ZUM6;n>VeN{~(qf! zUpTi@7~jdF=m6CWSHwUs%pmTQF>vS{Jb@yvNh~lNipyCaRBS8gC~fWN;!}eIpFJH+ z!kN6Hr2iHp%spdij;X1RAZhw2{Yt5Km{JNAg=pE-jLBvLI&qF&`@%+>$3>6wgtpT- z(JwpZjUg3(k7i*y25s*#ufrH`0@+(|&^>1v%i0n<#^v0o=z(u6$G5rh4M1jOMIs_P z4w3ul$UfAcl5r{7B4o<1IuA91>;tXbVJd@1;E}1YiCRQ3g{f!NnH?>`4O|^_K!yX4 zv8a9*5J>kIvR>J6M+mziRvY8ZD6)|4#djVmg*Ft{?P)Sx|1z<+H7K|YLV}i@5|ruS z6Ay)Lx-G4gn_hoTZz(WP6LF$MzWAWfX?hMd9BDwT^{wd@!as6%LKItzt;|m2$A0F*JT6Sk5j>>HC83;FFqe+!xZwCU|gS3zWvtM0v=?lFM<6 z?*}I3cvxtnYcV2k;<$l}gBMC}sJ6VXs!-JRSiHGUm3OI+S9P;oS5d2+&Vi!OUj2UUG&v|A zzO#X1MPr8V%eh}lliOy6rd8pG#Qn7od?@&6+_guSCiof=qxIq#aV87nJ_ZVP=*GgL z8h!>GhjsVp`_n6ZA$H3DV*sQ~rVT`-l5~%G(a-cn&M0ymc05P>v-5dKO~hE6S2_N~ zaL^K5&44X9{}6i;?L-zj|FR}t>P37L(4>0JoXO_pSPm9IDZ%}j1%J{2i!-otnUo`< zlaz3GI-n)gG+zbQ@JbrPcG}(s8zh9B3aWVIQ;j72qcLjM2j}{v^v|7-C|Ykfi1)A~ z*=lbXoTc)joKwi4K;Z}S$0NtF zqVagPVQc@CmzxiqF|Bja&<)VZIKLgHLoznmMipB5;^54IuYEYlfb_9Ej`EPAKw`*? z^0EW3@JfI}TdNtslb>GEgI(wljNRNtzra;^=*zTV&IIC#z$=FUiFv~6m$M;9=E8xr z*ULmepT6lRn-LqZq%J@wYA)*&>m`S&-UQ&vb}mDC8y3pQ#+KfAFOHu@y#BSLOgQ$c z;J%_%KxePXh|Pgf%b{znO^V93{KZqti-W5)1byesLqRZ~0P68jMYR_7S4sOeqPx-AE&>dB!v%;zy|lo@IW z3Mksp;#71PZKwGwNek-{-Go8@3s{DEf*iKMu?{A7#*YTbXou^aB|DpZ$k9Zz!876@ z;nMt$9uwIQ0)J`-F3#xMy4Vqu;QSuWTj`U1Zmx7P@n#pd*?WdO6XHtk^D*Ce;1j_! zLc*IeV4n`}oytBYLtOV?y|E#@6n`R%N&31#MAa2bWZ*CH?y|RMoCt(Jcts_qG#E}m z^p-h}6)X`R%&v0F%x3%JC4Rq)+fz4T#H@i-1Oe~e%q&Iuw)@qd-VnMn(UKmt8(vW+ z`bZM{ZuM(#UNWJ>s$K%CVjxC4Js=|oljz2VS-?ww4hu+NyS#~5HDXg%xrZGMQvFYl zn5ypt>=%Lh4@cR;ioguZg@Zs-b9xYOFM=@_L0XY-wxyULx7C&=1DJ1NRmEDU@tbZ3 zo?R)wgkg}8j4ag2e{j?iA8J*KQ z0;?=%CJ)WVr%OmVd#k)z`txGrDyV`CcQqy;VRg`Cu&_FDzxicicuAT=72Rqk21Dd4 z9vf+NdkPymynJ~u-IG@NmZevyCmqg+qP=l7u6IeKd!iLSbmi^xmD3#PRTN)p3>~Er z1UDQ)(Is1J2`j7yuHjL{gZIvt1(T`H{jbtubvNM$P9r@F603->x)|yjcgX`%`PK=; zm5j+ak(D-7Wcq53%ZnZn@NE%nsOAdXbp1fcYC3YFmDU~)o2t1PPja6E-s24e`FLtY z-h&SqSju*-yTV`8OcxLV32lia+v!_4>g^E6KdwCGQ8}gpY3?*(Dcg_sHbj5p!-(5e zn0b>Zk_laVepON7nE|xx%j38We5PIkFhqwNkxYI0)A_*aE{z7$t+XhvEHg9C;a~^U z0yZ~s9h5Ry8-(28Lm_?FgfGtj2)(G`v>5BF19*TDvaF3xRm&QkY~YYSa~{STjvswp zl`y^AHx&H`0Zm-#`H)agIPRmRC_Zj6##k~XB@Fuf#N9m5tn+c1Csa)k0uBQy*o`W) z(Qk>F^Cx2-Sa^q8;&9WLy2s7&4VxLsEf0%~bg>?_3<14tpfjRWa@*W`L?4VR2;XMu z7xfEH5Yq#+2Xqc*=`HYws?dCM0=g+IWLyuQbrinjCfZ;aJ3-g+#3UVYS*YFMuz0=I z&0{udw06C{IQh~CL+!VGv9)zQmr|G+eX6B=CSY5dy2E0I+|3WZx(q$4V_5Y=1kwL$ zgL&a06&#g=7~~FI9`Y{$J|IFQhG4K{v%dx+1io7zlQ|jel#o-h{sx`(*{`P1Z=~6v z@@eAO3Eva1q;1egkv-7s3^QjTlM95QkLVW*W$tQ4eB^W*)}eKBdqNH{Zv!6Q{C$;s zoFnSAkmUAnOe+;XFDdL%GZ1p16fhgsAw}p*!fF+(4y?%QP~EUV3@nAo zR`OxJd*;B92y9h(o4*sT_MntLpCe%ei7ciR$;fBZ8bbUFBH{LLMP8arw$8DVAB+iI z_}j1U=D(^Y`+HlmpGB9S1J&oK3*Lq>5%st;l|i~(Y{%!8Kra>8oHmeue1GCp(qzY1 z&h`LZ@g*fQlnEkPt{USWNea--_VcSqyKhfW3c)v2ZTxwYaVcjvAzN-rS~ql|oliNm z>F*HHzbAlt7M()Hm_ZQF5tu0#80Lz37?7WpQfBAi$mFaUgC|5DMpMKd6VE1z9le>T zkTs^RQb>7+S1cr?EI~bt#`z3;+>@CIn}n{XMb&VJVCEb%qC}rh1U#}E0PU?X?e?c0k3~@!KD#3@F$>Sh@%lK@W(v4)!&|HqI1NW`v z2G+M{L3+uTr_@=2SiJ6$FKyb2_m5{B#mLWZ2JmbfH8xVl)H;k$*f-d-e?+fdB(TA} z{fUeu-<_A#4=diCL?C0`U@AP<5UqF=CA6W^LUG04d};MQI5M~K@;{tG?{t|>Jf{xq zty{rnU`pExz52aM0(8oCj=pW2iH0$Ey_|R94pj|Fgp4IyUU1^13>Z|-C2NEq390rx zNef22A0|F&Bu4r}KL*h2vu^02qV(WkDR<4UFJd!79EL1xct3z>VAe-Qa5#gT8m7Wc zND}%FgrWFN84|tk!Hk%(?$OU}&3T{gK}q96$%ia0*#h5PO$g4(Jr03X_NAv62t{dp zspu`YBqkRn#O!%fSo4}WOotHEZ_vT$D+&Efmm4}GC61F;#-F{3mc>Jh0&7@(#dtO6 zc1jO&Zx4Lwb@#^F`8#M)x3u(|DXB9bc6cEQBO(Msxxu!@>3PxQELfvPZ?sGEvt)sw zpUTHw=_s8BOMfiZzkyF>wc5FGVQu)9Et(vQ>;=-J_?r~AzpI_?K5eU>Hno9BuWxes^RP7_j=PY+^s z?GBc#JbWJ*m5O##NvRy%K{+%Bg`ZUvU1rj(1>04)GnVn{d(ID{u$>544dZyGRK<*Q z+!1a+BXSPGZXDb&H+mJ>i-d{;LEh>!Ony~1jmVY{I8e6Nd$vsPh|EDd_i)NDL-)#? zHo~SfqX0NwbE!=>ELMUM!Agf9{{+Etd>$Rik2LsU=0F-T5m#LZv1z-QU_F7DDQ}1= zfO|9O<8eZfp?RcwJ&|tf5mp91!jZQDY!- zn(-yUxhU*hXUZjn!hTj>XE*$s(wD}|DUVJHp2p%&Le_2z>JcrUO8SFW> zk=b_36);^qTt{!kXUVD=`3~0pP^HuKs~$zYMIANw$Z2%jLI=A$DPL{$$vt76cx;~l zzPRM93M$a}UutY@)YYwe7qNPYjkLA2)vZZ^c967qo1tXhA1dE z?SygNH1a84VDuXr-TIBV{cldlj#_uY&WoNosFp%ira#7KFUV-#9`Q8e^*l|dCLJdp z)uE;K6hl$|H6q5Uk5o%Oa1OaM>$SK;R)5GC8RXvs7~+V}>F!SUY!(n}5U2tb%Xr?E zKy{w8rYaf&RnTx)qVMk`jBRS@o|xT-h?o#QXr+-5ld!FnbeVU+}T334qX^V1o zzZ5n^Du)ltR(1bR3H_3~Fa;HH!PQf+`(2$$qt;=+67Y@~hlIwTGJ};yvV%~@aHH#pRp!${jnIjVcl(FnYA`+~> z?nK*mFb@LZwhM0>=|eM}pf3KzxQQSQ@;o>Q#yZpbc^Sf~zx)Z$D6ZXeCDYQF_EVzBCQ`K`L3d?8 zs@OJ@L=|!1pS6=Idp^|S2V~9EHsYt?+A z_Qk)iN6K)mLk1i8d;{g5aD2-35bY_@joV$`vL#hR4O+y~*JX0OO6S+Q3g33 z@x(I78C;H=y)A8}bKvypxU(h0O;Fj8ObiP1hz#-_&1mkG*Z?;;9e`*N) zua(x9L0>CY4V_fap2XpPCMh2r4k3b3u;guYL@#_?*qA^8qBk&2+dkJ(%*JyfSSZ+O zW=#;N$sp4Z|7n>NP9}yO&RQf3Kuu>}*vel~dzcu@^qrGAgEqzjkyqM{29mj@qrndN z%#67w4`axokP4)ZTWbRCEH7|iOntW28yze|z4eNaf>NohhVAhpYm8OLToAb9b!Q1! zKyBiz3zm)U5MJL1DOvGl&gB-XJ|iaB4QltsS1H3`AM@y{pb~U9*G%f>7}La|g+MI)*0jCJCxH-s2VCnNyUM*^ae zv|Q>ZI3G~}lvCxGHSiM#Wg!9X0&B%jP@C}&z%CscY$vUT-U7FFWolHo2J0mfp&kdB z+O(3?A;gfW~_RpI-Rj2Nw@z+A^QA2*Pl|3ivb%boWY zX$vy|#;^b-erJ2Sg7pHxhr%J4x8^tiVQlzG8(=U0?afs;p(?!my}%J<_7=*E^*xK> z^v}=!PQ4paK%;60J5Fj)3@XZEetyI$7Jp8E6lF4+4tYrd&AS7EW@!(wVZ^Yk)75B} z=A8K`9qbCYZ6na@YMS_(Gl{F)x)(qE!E5foJuk~^uX$PZZSxNdp)y{O#1)3R(g3wkp~w6@HU!1I@@}#t9jKJH zXdxxXhBQ&cW}}95lAgKfA}ge}Q9&0r>2-aVTTT(AXHuh-Fz2!u&sgSUZ>El0v>pMU zYiG?glPJnCkmLFF9$@3JVVVV36XX7AFwL5Y?3Q?;P*)1$m|YjR>izD^n-;<_D$(Pm zT~=cq+3V;AZOn!#5&w=j)plFvew|>lc;M?Odt)(ML(^=4`6-7aQ~w9{n@kV9H8pF? z8EUqG!DvE#qh91&5S)W0w-)5D?(=gJ@x@eiw~35Eu_qi@09*cAS+M^WPcRqQ7VI^^ zzN}`k)$1}P(r$w>C0N8Um&2x_2&}sm@|0H^Gzi(~Do|4??^5TXFg{b|s!S=YBOQT( z5l+kzCO9Q)JdANRYsAtZiPS2FJnYi7w5}zjdy;?k{3GmmO?S@c0rJ;x0w|(Kb!CJQ z*9z)J_E3U+S11@oG_jSoaGxJjScKUD_XyFei#d<#2BUH=)IL}ddBQ0NZvt~A{OUil zrXa7qaT}@s5QYo=D($@Bf)ksAa7m#^%)50~ppb%!lgVcxL;hm0e^)E2*%4paNKWzo z@JPHY#tih;NThPukgRCJAJ~Br$$4fc&JyULt?Kq2STSQFV>Wlb5t@qId$pVV%K|Km z$n;NuX`FLUSf#&@WTM44qb@;+n6ehf2s5{7tQTZ+Ye!Uw@>w>pRI z$$ml%9}0x_3Q_kJ0#UbNQ7L;tlwIXyh9{^?sYdlnxo}^^6L1G*Uu4^dmMMJ|2!`xa z97Xk)ENHI;;w|m$z}P?0%0lLNOUy=S9FE+uAR^x<10HQjfG>i?9Hx|#J_a)g7(CEx zH|5xOH{E1WdsZV()g8opbUS+d@WX0tM!4LHNyJ%5wr)`0~Scv}t^fAv9Q10ViXzpI`ixJ#!~*mxjpR zJ*nuhujy#N4P=RoyoT{J9a)4DUY1$vAS;jKaG;UbllhmV53J^E#PrLHwuM zcF_Is72PT3BOcR;dCf``{g5Pd9aXv@iz8;WFOKiY^5@;StLtKcP+N{H^B}Myaa*C7 zxJ4^O9I7A+up{z%cCC`()X6Z7l;Iz$4;^V}{nuJCb#qbLD$%tVGy0ZCc$$yh!HnEb zz7G&SZLHnZIUBN?wybnRdR&`3T3JRY+w+Vy{k&HU`T>PZqBVSjvDuP%^ZR6>W7jgZ zK?`xx60q5|kBI7Jjk(~@bUdShjM3`NAO8Z;Pu+Ko+qO@=NO>vIlgTJ(7zPrjF*II+ z5DfTBf)3hn3vre!0^LfJAEG^gW$%&b&VHOA^S~vN5)@99`+yPG%F4K0Gjq}fmFKhb zr%8!nx07f}u$pbocq_=?R$-h{XW#)ltb)xVMuQoKL`qkp5JP)OW?r*mJ-8vUAZT5% zYNp&9gD*{4)l+5DP6Ly%#lkvW)cfnOR>^@d1a*#ILYC=%03V8Wn!U)xCb(&F zI|oRZ2Ys2GKY)V>m(MJW7qiL4%%Pbzw?cgltZ#s_w|Ay90`G^eU-TM7T)s28dFR0k zqQW@L9PO+bDC&(|{I^Nqtv54aDX-#E%>*&TtKjOZo3MqqMG}RH%%c0bilkU<{hjRX z`|zmo5`vVK@FM8e`>H~6lJ`RDwg#cow;X-5jCKC4yIB>?vc$j7n3udYv0H>?bIPs6 zdoNaKPI{?-ES<a!M-?fG~xYb@Ll+9`)|Cr!b*OOAeHBNJp03A5FInq%;oqh8HIE_mG>PxX%$ZyAgR%Oz zsTHfZDYn#34*Ck*?na`)4MWK!BMNho&yBU`JOpx?3tAZY#O{t%Z+v}*(+QwvOF23RWid(v zuQKu=(*I)bt)t@Tx^>^i-QC>@9;Ca0#@#)*1qc@09fE6cCqVGv){Q#^hu|9AHAo1_ zN#5^%d%ycT``o?HJ@?Pkqib}HRaI;KYK&+0to4jBSEWL_@s%V@b$Wj%cT)0gJgA3Z zM9GFTeILzD>2y}$jWCOUZ&gF58k|?yXZTApf>(462TjBQD0hxwE6A4&)}L_T=Z4}G z5W{TF1iWb&u)q?;;yy@A5#5F>GxBZU{m1c@6C0(U$IDr|5zYh|qp3gLC~tGf!Zl=> zVJv@{=35JYNgDW-&H*LZ+TE0uw1<&^>6gyH8fMSDjmag_06##$zXa9*(c{^hnyEU3 zFR96uW_acTCKItN_2kqw@r8?C*pw$*(UUuxL&83+_R5VIb{Jvi+b!zb^FMtH+rRJ> zEqUln-VwFp8m23c|1e*S(+wslM=PQJX={-xTd(_(20;EG$^oq1-*O8C<9dR5N1SI% zu5K_c-%Wcyyq1->Vb53k{%+*-lt{i;Db~q{w#aJ5_IlB+%)NabowDJJzE# zgJ?n2*C1NozSoQ~edRpTgU#8JYiQEZC@I?JvYMcy!UEME@|06Iv?Q?%x)0sW(YF%f z*tUGqwBz}-CdFGPt5)wpuObR+)9Vq#Ueoh^Q|7Ge5=s-;zeZa%zDD-0h*o@&aq=WG zg!>B}123C*bg{s?ebPx4Q^+Bc3g@P0yo|MT74O)gI~bcRD8fRTX1StqCsW!~GxNp? zs@lbs{*44&Q3ty{^eL5LSK<$;UsbAr!md+#sX0TRrnySH$lV znZu<9x~UjRi3UNmg4eOrdkp=gmXLB`q0{WG#K+xhc+%Uq0+h5=%XYHkGW2m}GbwAf znAVS)E@wd>z3r|DaywaDF599)Rw7QaZLTQZ4_o%s5$A0Ovh!_u&{(ZY)(AdzFt)J>R~L9 zFHhXOH*1^yUipckXY{n`tfUC{9FZ%05+XI~cRtyKL?M5TtP08-p$|=;Mb0;rVx!{r zJlAWg54FCO$K$S__T!JjX?hilku9Y3KZ*k$I z+P)rI2qv#y4$V6rdj8l~=ue+8do%?9xFfPHG0d_X%yD)3742OvVFsL*@aF(i6r<5- zkeSyW{&-@veHWM^`OZlPcL1Y$0G&h~^+6eOFi@c!)D0Q#5iEJ)bJpO^GX~eKSgR?h z4qi_QDy@rq3z+HEkh%|W+uz3YsxNEf>HX~8lJ^czns1pQ7*h212pl(=!cO~f?LaCf zZiBo4n#uYVdblD6)VR;I0XWouowzGz-_pjk5yoFm%J7XtuXRxX;+Mi@;mj%TIJPSo z3;13a=p)?WQI}tHAYmKU^NoUpm!tGr-EWCn=}f~32fI>2#`ffse+&~R>iJf@U)(zM zrH{18{!G^KSSE*&89ns%B7M)1gOawv_Uj_pd&i6#1JJyjP2If5U6}Bl;zoYKAVY_5 zTMDn@v}=kA7O`3yXdUvXV5aW>*=p~pJ>#*T3NgT!AM#Y~a{Wri-Ik|L>qY9TJ5q-* z%4jv!hZGrX1FkyFxum-9cw?nL!dsOvYM^0R2F|FpgFU=sp-d0^}&{%ZW zVTD8M%m*kd0xCJDZA@5FhX-SR!=+g!b3qT{bW42=z3ePO4uv+mnCTQ@Ms&D0l%>SY z;V}H5Ld&%qC~qq1V`)jJ#Ba%K{9W@!12tmYm##|l-IusKg6~Od6W}Gn3dmqSWG-$$ z`{K&~M2gscXue{P#V_31L#y!1mISiiOA6W|Fa$RqjBu*9AlcuK#>uv&BkZ}^q8=G( zu4l8v%$6-pan>Zd*_lBci-X{ddL6BHf2@+I%IJa1#_TC7w2WsN7amj_mG~}K ziQbES<*nj`RA5rHlzmLibi0w!lOk3G3BnI566(DpZJ7q+A{4}U#6!RN zNbJ7j!E;j6%v;a{A|JY^v3kP!PJ`P^4O#DWDovUl!6D1k!_?mEma%H~{t^huQc|6d-vPJp2_)B2;Qk%4m7z>Id2v6x~cwDso zGu!C-K+=PvO}IJAdwXgo$iXV9WKUMp^Qc8Pn`^G_Kk2be4+`FEu~eA}8#;-Z zBOdSXnRKECQHcHVvU26zBhTA%%tns@K^hvl9Q02PuZoSoGzk#2Nt#+u_f-`hA2O;? zz<55Bx5sL}53&yXrpzbBJ$Ti>bJ@cacy_zm4ucd75_?W+Zy&xaQNR4m1h;Fr!TAYr zV;8npNy+1OwBZ zw&CtL9C}E`X2XZ_lZ2KBm6Spy9}Ou72FviL^5-iiLhos+pX|m``0-P>*XQN+-OJd$ zbJ*7*V>phV#=EWM%idEn{(1pGb}T_F^V669E?|`)CQGP~c^C4;vJOz&m5qtb-MR%@KELH(FssURL4+ z*dEQm8wZgh4o6;r*I!3wZ&MK%=f_3plSz{nO!kZVqe&kjbsTX}Jw8A(2gU2yq_4-=v_Hh0&OT zZwt9N!sTz7d*oW!PrAtmwW;T$;aCj36(`bID>kbZqdegML$_#f z<=vH=o%iZv>=`9vqCc2m&_C? z!m~~VP8+(!Yh!5z4ib*;hVGMcbzu0uR7d5 zH_`d`zSU*#?IdOrlGRu&=|o@qzL>&5Qx_qIJ{yk>|26JG0{MmC;@IoYg4+R1@8s9Q zYUACQw$@B?F9~EpIbWXi!bFa;F%uipV?7?Y;fs@K3u$XI7tSL3J%Y=io;1Ki1 z0+eK}xYxFn4U8wH*lw+FnM+z*`~!)&gx=CHl)cwLb;rv8_#Kk)$g7=z%C&}hz6P@BX&u{NjZ;2(%jBn+$zpCIwJ;tR6PB@=}Iur)Oo-yuRNRd{yDW+4s34h{ivW2KfM^ZomH0wa=RbGw&)I$Aye1 z2M3K4Ud+7ZBfoXw8zu@-5fzU9TymH-r{GoD+{mklRpr$0xzn4Q&2M>5?g}SWGfPBq zCvkH|l8x2AW`4(NSOSM74T&?n-s-^?YLzH96~OT z)je!>uoFu}d)wcHy+PdPpvN`Sm7M9VBv`mgn;(2u#?3(EY32Z1cs^o`QuafA@3U%K zx?sYeZ@7pusyaru6@>$Cj$V)xnui~FasSqR=M0wz14a?F!+$OmNk!pgbcD~o))rDF z-fan2y4T-XGcY#VU$|{3nd$ch@Nx08)K*q~!$!YMG3Iv^)}Iw`Qd*^nJ0qA#Ooe4e zMo~vxHT${AVu?gAXf49R2FrOeX7Gw4Xfd7gc#=&*t+i_VD!dVsEF76w!#9)@^AR91 znX1uY>yV3xT-^bWbfW5Q$WY;fqds|1A?kkTEdBvAj>=u9w*rb<1@9TMe5)(Wtwpn+t_d%yW&4(wj+zJ;?n#jTd?Ni#-7!xh)+@#F}-x)hRT*u=!1G@=hZ!+tf_ zWNx*T;?@D76(1}*!jTKh;XYEG+j{Y#m>6eMv39kEKD+LH>c}_kq1h~AUM0C?&B{Ul z4)16t_w3Kayy8*_KYDrj^keXlX!ek1rxcNd%`>aI`;z0;ywNB&&ETem@CozgSd=K( zqKclZ=Ajwb5?>2m`fNThC|332L({mkFRF=9iX7o(a^=up7SkE$Yp-;py z`R2~ri_J_bmT8-wThZi9VxoBvk?l)P``1>tDmRWo5hKEo3QiCj`9Tz2)An7tJ=wt_ zGnKppc~Waa&d>=_t7V0X3+@tM=30D-QhKEMM;X=r5t%^Q%}q!K!w*R9O@+6r7n^

    8NF`4Wpds`_!~xr?ECOEXJ@lzv>w5IQB(%cEJ~TKl$agIw&{`LRH=@| zCVQtXgzfqPqfU;`8lZ&A#Ak`evzfzp#f2|nH9p@Y;Dg0J8we#Z;!78|FBNLg1qGk% z3p`X8#N{E+ea^zHo)(np;bMyV2vRXWt<%p&$diQHMAaFL&~0$lBMf|G=YPsW*ohrl z_^}MnF{LZ}f>WmKQNDXmOR{9d?X6{CNqP_VS>bW1h+kj81*QWNgyANG>|@4Y>7@u* zfF@N-?bGod9ZDS>+hR0+1e^e~ovHjH3Vb>Tb8&GqNp;qe0{X*Ge$+V;*6&doUcGH| zHAz9+Qb*XIj+ilX1tXjMS*Ndz5 zNanOb%j}L?0j$xAF(deCJ|?K6Am+_%&jB%F7+x9pUPZtru7+C2?;W^Qh@{yJ|66%9@I`|&d)*4GA zs$uaKUSXSJ_>;nAn4WN^%$qkmdzOAyaoq9>h@d(N1c$GlJtVO%WXle4H7&1l>$>Bv z)-?Hkd{2xgvyKM zr{NBzJ<+iq8UMjte6?5y#+iAPqKKkeu^}J5+c%iH3-7OAq{nnwsqf$Hea}Jd!Mokh z_`*S#QEInc`^9jYQBmSRV7!F;n+LX56r&-ocQ3vX9P1$y`Da+~&6TSQf5a`jHG7-X z@ea7&K5UzDic&KDaxu4wJ0>Z%W&SOD8FvBV+-(};+--=?mGHk;c>;KD3KjHpS=!w(vr_hrg0MNks zN1>+%_8h}i)k7;$)G^WL0RRNqKb5t3Q-6U;{=NiLBou%_(~P98?P_iPKQa7I4ZjJV-~m&3 z{~(ycjVA%f8rsTVCIRhT$w%4-zJ#41-Ok@1t}QK^ zI%mGqP6!AoX`zT97NDmSlz~ou^H6CWHKbLj5QP5Wqwq6P5(=t)seQwxsUAo{z1iXt+7YRW5$@=&dk8j9g2Q|Cv-%Rf2 zV0U-lIkwZ@(eeAjY=b^f|3b9Q-&RI_pZ zWbRo1&B~H5#S8e5!T!g=4>*+;T@x>ht+M;5q_1-mV*l!yatGxnLeYW>*@#p76l>OO zZJ%Pamy$<4Ibx%PS3{1vijhdK;m|Vx0I&Ziif~*0J&M31{~?MTE&nBo z{$s=MD8hmVwBY_Didt}}Z~?@c(jcBvhlL+|4p3}qT`bSOzTiB<*KdTSB@vwb=AuO{ ziv_Q+)E@mV^Vj7azqKjJKGe_#S7^W?CUh_)v+)9W0fK<45x5V2>m^$$bH_&%HyKvf zo9W$nn_dsCy0foet|<5EzM3{8VnE?tbHaHhYLohbj1a_2y4g5|A95g7X|4Oy^XD7l z=w2%;tUY+MevrYsKZy)Q9?GwuGLDKRaJ4wj#)}LRYnU*#6=S#|&$tKtDxSq4KxV5W zXXa~-?d1wafg1$C)_SH!&ZRWtnV4l9OE6M*N)IzXSjHgx6w;XwNxvf`)Se~Xg6G9c zj)$x3{V0yLWi5>|T44IBS!ScpDQXl^^(3QO9TvsfWqlt6p3ha59$6$DgU_7=EhoIk z)Aj#+{>zuucey;NmMs-YINqz_hfq-3m#y!K`D0v4_SN8gr4Xeql1wb#tRB1Xvwc8^ zuqPVAlnTsBPVh=CI;G^fPmTwS>uoqv>9uNAIg@ut>jd&4k5uBgtCaRMc1#^dG*z-Q zKgZQQXEQpQ4Jd}e61T!ZOuo&j`yt*^k$gJ3kL5I_VkQp`ltNM>Q}Xp717~4>Tg$MH zL$$up{maksYP6R+nCgF$Z1f*p0liq?;O+n9FL>6!Ky?3^zr-v4HGiSJ{_{rf|0HqzeH{lt%KSa+8 zM}!Lyv%2c(7|29~Mrl>--XHYnv`ED_?-yDv3!)f_x`wD)bp6WEXr2n}8qUsW@ zFqY273&ReS!80pxezzeb|Mc^+GF@%$Q!hV?9l!zb1~8n}SKz-J_=LY9E&tYf@;gD! zH^wPrhgcz!5oTIV)X>BduWFUSNhEE$&=00km$K;+cOx<(~ z{|;9znKEz(+5aO;t`fy1Ki7r{{bWwuzB6Yq_gl?Mu0R^mV3wKcUzJO%S zR3j%|TAlD0me6G28mB8S`ttd<%RJz*ZnAIq+nCwcrKA}5E=@5T`01o=0=8DV)$4+i z>3NdRI_!_Ak%TA}$DAo?kD(0T)6h<-(xrbv>=!M}sD@o_7zN+I@C-NV z$!%DqXl3N@2na}x2_3}uLm7f(Zkmep+K$iq>$+qHg<`_%bfTZInzN=>y039>wY9Ez zD>w8^AyqP@YhOI6-HHO_7TU3~VQDyCg7)_lE9dZL(uP;la)>@}jr74s0x9GDAL^Xd z!%nPXS%~R+F(xuxB!Dm|&{}{mqX>dk@4Cs@JLu;@gsbzNJf%$z9 z1{fwJBN$17fDr?dV+|88gUXAS4)Q>71koT^X{h3@teTLfMkDbcqsrf63HY1#bpEM5 z>7;+v9`ZkyuKBOU7XT1Oyg&uD+a$oGi*sSwx_4k43QkxW>Q(zXK^KU>G!~?$p#h|8 zUVxDkVuM~h!oa2vV;~oYunukvOpy4V5paTv8hTeo0aD0f0d|lHz&70pMS2n8fJJy9 zAj>KQcoh8_#AI*^J3^>hJJf1SVe@LAM6_q+ z+Kifl!l)c zq(z($($b|DS>L$<57W1TcoH07Lx);GOIqrd^u9^nnm`X#-qc+<~ z-^+u{3{g5t`JO-~R5_sht#4h(E3xf6#%a(Pb{h~)`wr;y)|!aQr%zD-PbW}0uqlYb z|2+`Z#0I#;bpn!rTZ88AZoy(IIy4uIRS5+F>jJ6O5jJXFs1MF(Mc7tA_>6WCB} z13XNN0?PYV0PhedIv71;VQd0!AV~->EQyf;sEj<-p;;;YTPzWO6QA)v#V3dLuj0f0 zhxpW;9jyN(+y7dG5ddK{Tu(4_i!w~5{2EsEq6|z;{1sLvA>Y2=6$}#6cLeF1h5;F> zw_xNxbRd3_b+GA=2~bS!Vu$HUA_yql1)PlAgWl_1gOvIgfPKKP9q=cXA{}gUz(Si2 zAR9^p@Q}$4#Ez5D0Y4B8dZh>h0esy-Tn^FD$v8Jyrgj9V03z5PWoZcvH;4kgiM<7z zDat|f%1U8gMp7MG>ZUL|1vK#Nr(ocxrWa7k`e#_Ph&?nfSxp2NfCbVnJAsKyb#}~I zc)?y+%flKK-J!vS2QXR3iuR;7>kcfknQ2#4=TN}7S0dwW6oV>Lk* zGIb#RQc97V+)eP(j~Ni~01YcQdnxG-lT_8=bC1}Obb30kn zH<0;NU`O5Q7|3IY8q`zC&_$q0*S@FE34P}g0@7-t03FLsim2!oL;Y!#pmOJ{AUfS2 zK=h<1;92l@kdh1>^g~%SEbbLThl~I<2#(Sb#1@+ftExeTD#1cKsOt`40kqt}Cdysl zIXV<5r@RhAvX1TmMGwH3=fXjXroynq(kGxrt8RyR^u}+o#QaT!|6IHaQz7O5c=4{k zlo$hm;xG${%D6vwsFsMps&8k&OcR-%xY|NM0Tl^QK#?T~@}3T)I*-wT5K#aUAi@QA zsp^8p+VwkzZGm8(9a)fLNIi_+tpMb-oDBSq(*jFzZx)F;-vgbTv_Q+V)q!h_YM@^f zxgCi!EFkkiT;PG@HLyxq4%!W`4>Qe41xMokg6f7gf=WM`yPRrm z<{%nagw0Q=%tcBENgaJ#C1eDulPhbb($uNSG$z3~wv4X)gR)Ee-Dnpok z?iz?>0ujp1+YBp2IFieZH>zqTn*R&^vP(8H>V_JQWPfVRrnJ?OHj2B;-G zxr3PEGbk*A2-MpC8bsHa0Q;7p+|fLz*Tt3pwiBUA9_E`Y4?}gz23gQqf$EntL=w>~ zMJalm!5tI7V4f)Xpyk?r=;_y)_AR(v(Bb|$tn&E_ST)`WHrI^`ouSAAXL!DcH4@AN zi=J}8ku1BN`Q(gHXOvMGJ03SUWNQixj*oAD7Lfo&N;g0|@1nrykr%+G->Hd3CI!4J z4eX%xeAmJC4xuAn;s=;7ssQ}n1P*qv020pYXzk!M7wlj~%>a{J>4M|sg+W9)Q9wfe ztPbZ;K3KAZIH>2l9&B6E15_*)(-G|XTR4Ef{tf{#|IuJnru_fIVEiLSz{Q^#2+3dj ze`X-GF&@8n{xb960m##MXl8#-4Er0zzqyLaMgI!%|Ita7!xPYt4Jv%MJ;Jh@9;F@!*N!_>AG#k{Hr$v`%Q$MbA z&DP}MC7ql@=<_l+`;2L5=4}k08z(J^`3AY;BI2X&iIe>gX~ul^N=o8!S>_fv;T)HH zlc-W@oFnA2{`Uc?<@0u|XbtO)(x&jfaZ{@TKbd#*+&7T+aKW?q1QJ*JeWYmW!s$%% zDaG(t{3%if>N(_3eA_i>0*<9c%!2?8Bz_%Q>gedyN)-(w-Fm@!vHHqejTE>)E}-q3 zf4YEMp+$Ij2hVO42u9(gX?YvJJg;}gT$Thw9B@x<0#N7|%*=#(A?iTQ&M;Na<-+Ag zC%5>BP~L)XKDbbOUhsXZzGExecgiD&Bw-P<<~Os)2Cd6W~r8j0~`KVe*L6jjk!jWJExmWDufTliXbj~wt`jIUzXxSeC4sSMg4&6Y(9s(L( zuHxn_45J4-YSd4c_cEr;VoIAO|1gdarY5wU3>(JxjS7U-*CsW{p0%Y@#gi44f^tM% zsHl4zg2}(7BH}YSTgHB_;EPqL8=UMBxwfB^z1~p~X)`$CdQA?myens!Lr&F&n)XRH zTO>*SeP1xme`W!yfBp~Q@_#MB|7!vMA6bB&X8*7NwHN^ZYYR|-M_AGNCdXig-}yTDE1)yr3;cHsEKC$kpujUcU!x#0K-X-%zlxfsGUr3 zuj)97pA-tSKlg05bH#eU zzaju1`NxBCvL|c(5|){~9ANS(>HhJ9^u*vp$}sJ~ISZ#~DAkTqs6gA8R_9slV+1_W z&+CP}lEM5t_f3g?M`N_LZEbe}yd^!W%qOKO$5vz)MA{mL!W91@8ZUMA%tpo}tx>D3 zZV@8gxdW;xMh^lnk0BjVWYyV&SpyMf{L%l=*SkW++t$#dojS8=Op1pVgR z=bOB)>XTmYj9@RJaLqGik|_>KO$wb?Ad<#!I^hGgnMHc9-d8oPxn!YHa3^&tr+Nah z7A_7AyflV|iF78(tSwL&ffvnsMyd$Ap9DtNU+=e&QtX83doa9f^NOWVAG?>Z{VAcg z9>ROB>Xv5mPFuA~*+sR#xnTUBtZnzFtE5pnwI2uVplN-(o_B*#82KraY8^`S;AGU4 zo38EASB)!JEn_x9ZvQ9_r+6{{1TAsEf4nNx|6Zh0j9~Y$1FHhEr z#C1Nub>zI8#6z5wp_PSaR6(=?v_J|h0gt@YHs}Iild#*2!|foh@<&N zG+1IkA+%gbJ+uQW`oIRUfWxj$5(`&(V_@(`P_y7(rk$gwBc$Uzc6?UvR5HWd+E~39 zw(0L9=QjT|oAJGr+k*wVgcWu5vvgGSJx2>~?i&>NKB{VIP*Twiss3ePh;2X;*M7h! zVG<*R`{dqzz0@|WbgRyREI;_{$)Ub5D#T0=8E-$1zE#-Bz`88^0owf9L`lkbGWtRB zR7I}HNME9ZjQ}8PkU-?KY}H+t(9{m4NSBNRi0S32Ao{$@*gKGY(Q_i&jiUR*J99hZ zA@T$Bji!E!y&u-Uu&o#Y!czl{(B z)Oe`G%u~eio+FRE73Wylrtc&bm_UlG+br@E)sK0Pwsro>4jNb2{bbb{X8Vc%Y6tsJ z9lB0%uNS%GcKQ8&21*V*aKr8JvRj?eXFO;;^f5r+XC@6OB^hj$mmH3$dd%0Fq6uj3 zPWB`DFnB8a=FDdyGrkPx3P}DghaPYaM7vc5b%J8H5{|=fn&rM%(7pTB^PQb5f#iD5 zXmOmCpG}88k*X|LN+qn&?oY_O3;*+1{W&?Dp+6v0QXRzJ%%J?fuu6FlmOs2PMu|q^B z3OwcEd4g`Eg-ZnPb^Y?E;diqODt8hn{e@&TyMxirDW#WQNQg|@A^H_CjlD$skQZ{= zo+)(dsY$0N<(iwC(Qbabj#Y)Ts;1dN-SVvk*g(d{u39#61;szNcV&}HdBq|n&7!@# zCWYaJ0N5ms^MF^c+2MKXmCa}ztbhK#i8ZqMU2A-cleFx{MXrW(nt(WAq_eE8=kSrf z+;n*!?t33>`0va&i$+;?!b@5A2FI)A*=7{8S7r{M^>7A^Yc#yR$vsx-3X#%JNThwZ zoSAZj44E7@gsrE%!`*Z*6(QxjaE>@@32&kbneux@cf}*I|Fx~yU4NLT19w`m z)z-?Z9|S8BLZmwSu&|aPw6>q3v_4_DR;kaL*t3C!Fn^_M<%JSTCMRi|DAn6e{1P>P zu9pgxxPeKc@G^sa=!|Rcg_MkIov&ctdwa5!=C59MM^v)L z%laMRb*qw_P=#cZhyO|rXXGkZCaK)6Lgzq<7mw{^h_GEyxbHjqQ`cl_S?I}Zp?KFi%Uv9zL)el*$xHk zzybli(9NnH!%)I*-j0j+UEI*;)vp zcY&K2OKP)Vj>y3X?(m?u%OXSnLlN4Ap=QN&S-J!cK#w8G2T@r8DV0u;Q`uq4=Dw)+R7B)rl9+yZ3^w9tW5^mGpB(}2xYd3I zU=I>ab8%NWkqT@tP|ubSx6)~;gGk~wLI7&4r-be1h+w}d5nx-ca?MMJKA#!g4*|5R z2EVL=*fm@+p)#UQQsjU#K9HOA!Y56%MV+i}1yp2_Q4BioTjt{M_{kKqVMe*pWl?b| zZn)-`)sq8296k^hk>mGAv3Oh5GGG#$@r{B0x2#2|kCt!e{PR zs(x{V^Dva7_cBppbl8r4c1(pLOI~0=>OY4}e+ub!k+(ipn_O6BoX#H@da4FY8^0Qj z4cY%h7<|PbOg&1rU;N5b3^R38-`$gqzkw>+S8?K=aj-o~W&FZSlm$?2ES=gJ4FHWMHuxiGJXB6o`aC`Hg!ycf9R zFzZw+uk%XQ9!guHtDPCiI|aZfHILp(tqs)|K4e@s#+e0Tpunj2t__Xmk(OU2p7f|z z&ab=KHerQLfYOyN!akAPcd`9@9$JcnQyou_d*Y z!mk{8a($G{8`|<^#a4?PHR4fuky_k z(k9TfWbQm0|Jytlf1}Bj4pIDUq z34Gc%d7(mV^-k7PE|OY9H`%)rpNBTIB%5HCDO1S?K{Frn1}khdJ~+H;Nk=gIXpH}z zYaav1O?9EHZ*MqzbsnL0(;|E(Tc|CJYwlYke;k$HB$svLAE&#CJ;HfEKzpI5!@5?1 z^Ns?`K)lH2%Ba5&kgmKlvKHpGL4+9_aIOO@K6c&%f z5SRR_1y`-$$*I{CZunpk8dATT71uT8Z4f`kir>(Nh@em?)j49S1#FT1z%g?#SC&kV zS57qV%j6N#wUGEZ`BEyz)-aXxWRI(xqtMAy*|}HA$?qI3&eMHYy>- zR*gRumKwI_hO167Ljqfsw>fA71rCQk#ken8X544t_+_*QvJkYL(Q3E>gWXVGZEYNn ze6me)<%}IMX_U%EmFxm#SCl~(#>0Z)yy#PE@}PKbP`HG* zN0b38Y2_sHy8z;DQ=~+3@bq_C&-;ah-d8YrZob);bsbs{me@63STHQDUyntBk>ifi z6hRCfBsVzYtR7I}_rv>y_4dN3PEjpg>&{VUo)To-iva>%s57qedw(b9h>Z}YI2w}jq9vWh~lSUJQox4 z4Q4u2s$tGOM%Q*JpNMm`lq+ns4dUI1M|^$PT9H@S41J*YfJ~v@h7SD9du3%FP6><~ z#)=i{h_9XR>N`J0ZXkz?{+g}4;7`3h$Ibk~aq*~F`g}eZ@`cnc$U5SAsN@@)&Y_dX zz0p~+9|q+~AnGGFT*Mj+B|BQ80lJL_Xv-=nsl%szO~VlE-kncECDTsYdv5f0{Q(QRUy)eT4c z=uOuD@|n5MVZYD~&U??WV=CBmhR_EqlMc9lNESnc+hO?Ggi;s$98S7U856|NwkKrr zu}e>I&st~UqPiOEbuX|`<4l%j9LIKtG8jJPz1g+sLGLAbQnqtQlL?2ycbc3#xU~5T z^@gy%S^ghrX!j)4W2%h(ol>cu*e`NT(Z1xWQ^UknycgfzI~}TRX5FrE2$)|Ke!l2b zxzK~J7eY5gv2_suLX<{Le2r2s^d{SfDLj6UCt;s%!-h4P!j&go zG*5_VBI49@N;X$$p9`wbEpx-zx`W!ay5!RPgzQB;U+zz9gMCS&cJppb?5;(uU}slp>wH z@|<6{0_8-*d1=_EG5{?ok+XJl?y?(a`}6T#%bG%$dLU~s>C+dIbFQ>8)4u@FM0}&k zGKH1$s{qwc?hGGNPWa}*nmMr2!mGUC%Dtp6*2v)3R58~%ySym5=J%hzE}i5=N&rCS z$oH&(wiEUwe}%+v>S5zt#SQr(=ud?dFpnhBMagm}WJFRSnS(sdtX+0R(OD5MOvy7R z?FBUh*V<<0XIWam!ZbDh#mUmzM>^~=Dffrpb1h5xQq=>*fXiUuE7k)}fL{Sy$d8ez zd(ns`f=;uGoQS(fz9EnuE=4qJd&u-eKnNB~>IBPe?TZul*qBw^xw{Okk};K_RoTk$Uo^Z=j}W ztJdI7(!YNukGKJ4L6>$TCOMkpKE>P1)Ebr+$TI3>)-T2kzag;1NRuYmno3kZ z&8EKFwI@qCyX+!SzCu>*RM1>;0*Da$fP9i7)`UaON4?OSCtUVC8`ZX*+D=2STz38X zF$vMDEdKflXJx(cw25jr`iWiJ4uq?9-za@9-;$|h-r$G7y*Bv%2VU77N5rw8K`zew zwE)|=E9N{u?nNh|$^|vDM{FC9AdQAdyKUsuC@SQb#%2FPzqXS+61?45e@1a4$unNs z0DJE-D!EXZc6M}L2S*fN0wGiA@s}i#!Kk2*uURg(!ru-nu57gyKkBdvoV$wCk z3V?GoynMBg0qQ*+5F3j9aDC``wznRj)L5MeM67dGj9brgbt7Kb^lQs+Rd#vJ!84!a z>ok{wmfvcM=$FzR--k7G@3&%XI5&75(-*X^HZ$%|C^Y-h!2*$kk{9a!r$6DNMMt(= zsopM}e?=6<2;X)h#EoRKe~8rbb^dUJtq(TjNq9z%@@gf#QFfvR4?7gl#RSONZ?ocL zN=5Db7^d-L4<|~8>phcIy%)kcv2t2FSyD_?U&YE4`cd>fQh1R6qVl$O;1pS!6881d z^+^QrI}KsFNvfU(y;>-g7T{qiE_ae-Uoltj;UO2<%vf+5#@K{?ICLy-^9&L8!WW`k zD`^WX05Cw$zm#6F3v|97^ukDgKoaRhiWK19;LqOI6buPh|#%K_olcFrximi3ii za9MPv(ESfa?y0*HK-&^YN+jg>J+qP}nNmXpyX2mvl?4;_R+Ydd?=%@Y@bItYe z%{R(W*rLxeg1OR@ym+9Eed>y=(QMjjp!(U_N}E!&vtUf|Cy3A%Wb&|K9QZycjqBtW zDCtC9us6|o++HC>5QxAnM`})MK->&>zGyfPEH}uJFu(22Q z=RF)`#W_**yf+e+^ZKDn5k?tM%6TUSMHIO?>+k4@3$Ai@oG)ANMD;6OK7|6+)Wo|R zb4I0LB>rnN*R}ZSmRYb1w*<`x6RUea)a-+|sFK{AE1=^OOCdOL#ygRI zerON}dDv#y^fA-VdesxQvwa``ZeHb9Kxn9L@>e2^iZ219Q(4LYJ_5f0t2Qu@XmycHUxW(b>! z2byD&o5aAp>b@L^6#N!C4-L4?TbSPyX97AWtP_WoOtT;%T>VD(r16TcG7d2Wo%N0&u)>ZRsviyZtEEG?Bsy^Xwd@9f$?mW| zRx*inoT$D-W;R6CUD>pD)`^nyhl+JN2u6<_BvDtST|C7Xo;@nS6e zv;>d;f^R8+f_CQ%$#shv3^Z|Y;QzgE8@fnJAtnSCBXpGP1}%50hgKe7CGE#QS`gg~ zh=y#PqVax9nd*zqR=WfzWq{UlXXk+0xmlb^~Pa6}zN|A0SqA#jX|ve5NUgm>1-2hod}?5Huj ziw4B<{~i(okJ)nv>tg@e`G=Dp02brF7|M^oF*2;KjV7{}-`i?Mv-16J%#&~I)*|gz z^sZ)N0Ww|Wb6a0cp{-6^FqFSHq7?w0spgfeK>Z-%ljP2C-ct?P=yI3)g1D2B zx=OXZ6x(b(Wh94lp*Q?1MH1o0gEmQd(&QJ1+gNlULUdG(RL)Bvg|PH41KH~Y!SaRT-&b63H3 zhaOHC1AfEA@RtGfyl`~(_9V)+iP6~z)!0b{6UfKuC1^RyZ@{JmwSG*fqpb4oA4h$j zB~~0~+ifH#0@QW6MRDhiDhvOa%Ksvc>7IjeZqWD*Sc-a~Mgt_r@8-dgiusIoO?byW zkv_pXq(vr5{OW}*>w+g2;5Mb42Q-qLBj<=%7qAUVEd$ z-9{HO|cAieu)xHgAZs|H1XDw&`ij_)g+uMU&Kv3$wdM8P~RfKF*!~SU{d}kHnU^1 zx4H!-RVZYnM~AYPF`>fE_S!F$yoXam_fG5==5)->JNj&ad>&sailfo*(9IY^kjG#w&M-)Af-Lr3daGBc$W*_Rp1luE&a6aLcuw!TaB)?27 zhWd2P0mry-9Ri?K<$>7_d}Rx}fo{m<-i;Rr8>*jD_G#dFD~Wq!=UPQ_3;jkcJ_(0m z^-hQIk|2o0_ZII6CHs>5E_{4ZUE7Ofi6o+q`$8uL<_kSLOksx2-2AXD1Z>21K3JP* z_)e3${MJX#c%s115A#VD!ZzQXHwkn{ zxzpN;tlD1Rp>vTNbuTCNTgV*ZPOc;}OtjmM?_p;Sq{lUa&k)vwQ)EZn*`&im1N!J( zsOJ5zHPr4@%kh6Q2RGU0U&!^Lgv)-(DYvXI5ldmQ8Qk9O@`;J~8GG?gop|D&K1rwg zqgcMpiEeKf{_phs_;`0!`%g>H!5(|feabgu*w~_5+Pu&jPXYN+AldjkJl0hclw>Cp zl20DyYaf-L6WVBC)|%HIOrK`!IZ5oT{p5yt3M(<#G?0U9>(rXFV~G-wl+a7Q>TTF@ z=)`G`O(gc7sn+vBU_Ad;<%34fpfL*5uTAQmggWz)gY+f=n|@m!*$t&SMe2X~1)Bb< zMU@+speCK+E?idn25NiZ_qR3cRM(LkegxnwKrAx3PchwzuFlFFtHxa#2}F#)IHM>b z9IES5Z&MDlNQ_*2!+|-qO=cO;__YfQ(>G+yLkux|oVyQ??s6o$w8RBGOO8rSV#*a;_F0yLP< zTYx(g7)^c`Wxa|Egpw(NCSqS@yfdJT92;O;^J0rVc*sEG&~d*X%ms{##A&z(gr>c= zlTAWWRKIESf-%GvABfa#6{3ENd^I8YN&a}T1xQ>IZuaY4R0e2j8X)0R!;n|XPD1sK zF+x+va$A3Rguz0Da7oGT(j!1Q_Lac+&MUe&>`+#Dapq%jdCymmrR2AUC{BpTIj7}n z04?YXtYJ3v;<F?Wg|9} z2~q4EkX|6)$)&tse)NkZ8vfI^o@(-5()=PHN@SnXvNM+b*r>XdI6?q>>^EQm(7;lS zxdrA^PoMZ+3gtbqc+wwP5)ct~;?t8qQ=-!#UItK_@MVVyvp^^Y(!zZHYJ3$QQogrx zIxjy_&>XX{_U)&g|BUW_VaSU&vi^I3yB{p>`5fG{h5Cj~Guz(N#{En3&d&EXL}wOB zLks}}llnuu^z-j&giEEh!WA0RT(zSv2mC=06qSkh7JPDvy@k^GwtxNSY%PmP9 z9Yf#JFANR#q@eOdS2%~uytB|>PH~R$o2hJZqp_tfcQYD{C{T#wW&#KL*^73n<-77q z2aubgbd=H#Pm9hBMBa5O5o+I`7Qh_1s_N!DMgK88S=!Sh>+6Vl`8xsq1!A)k#-E#& zqhEDAgb*TmG>>!TY}txkC=wI_jSUBtWf(r)lM8jpPNAct{p(fB{_DW_s|;maS)-{( zN#%(!Xx7ENNxxRY7Z7_!z*5o|>Z7bt445u>rSY+7;dM?BT*H<1u1bX`RL1ISI#7dV zKYW9v!46zG0}285+;FPDcxeJ42>OGp-&q5J^PwVl^a#u1vouOprFSHOI~HA{zzKVy zsEY0A#5WCz3oQR@uH#F4C8tr+2SF#%hyZvBPbh>%e8GKcSeGRI(fX}szX-^a8Tf@F z6q|oy{m9$yu*tE?E~7|ZaX{JPjkOv1h1K5yTDXrmwHpx!zLajcb|xI(Ho=buS-IP} zr++<-0ZPA4%@(&118{ZV^G@c$R{<>^ieB;Cpx0k%zg|!xHrAPNpdsJ#CBffNf)>p^P~WBEJ!b%y{hBI+?}UtN;2WfO0gl z$=o%=axutoE>UIa1gB##3=97%2id8Z{46bUSHNEz5b*gL&)dC#cW+~V6+>K5M$pUK zi18r+pNXP40752o!_qjbPX-tI|JehZvqf;*x2q_WI{JX+dNs*=?UA{qD{b`33I8jH z9>HH{%A8hzOu4@<`l=ha>Sz+@*e@@Jbu&B@L#>cP|G$o0os;4j#s6Ja=P zBzZ_*+*UpW*qrF(bY7za5YZf%J)eng=~GxE`@j*mr9HUIXqmhLh+e4k_aUx;@`1vf z;yw{E9E^YABEE~Ly00XG0>WEo{K^;@UeC=RF_jM1Fdrc7wX^ zRHjjMAveAmhAbwvE(A2{?3+D>_+5xW4F!;iKdCxzeV|m7ZTVoZPtcoOY_BDHfPXgr zOR>ueuJ$Qb@iM|OyK{|jVx^cpELJ5h#^A4n^yTLH(w_jG9EhjWPr^S_(`()5t^e25 z7&x-@$l_uHt(rk3wWcq-Zx)ZoF9vc6#$tk;A}v_2Oqf=DW<15I2k zu&#IT>i$1NKh1tZH}#V9~{`>v?y`+A#|9e>-90BLAPk-Qz= zDV@8P3x}@0=hBjAa_eQtV9~>VQ4fyMS7o)GiQ0>n_DKh7sjn1q;`ghcm5MV9^UZ(* zsjUF9OzOoyy)e1_uu2oV@$;Jmx3mJhPQ#Fd^908rgCWlG_;&$VS5jycf`}!%(ia=M zGYcPZEVm78P1KOaSI;hPY7rr6O~RqbP8d5ETI==!$u|>Pp=3o_Vln=w+_auj`?II+M0ku zlpn5WAFp|`UsU#M3FUdHndiz+of$1ifl8K_LS}MV%BWEFI{_NA7mDnF;;o4`>Y5`2 z$a6RLO(^Lk1tE!L>d?q*A{6H@Us^f!RNlseFUWMIdnW4;#gGf(uUO-z| z^5H8X*c~52ZPepI|IAwC9Sf+xGeRVq>wyYBB6wunN4_PgAf#xPD`p!;4kRI) zCNO0*3okrMARJ#CbBY*O7We#2{DQcD$s1j(Qb~*}m{e2J<)J`$cpEo`3%ADEEwjd6 zWT>nNJaB{}`AikDQ^KOem16Y=(zk18!Wx3Y7y|J`yR>Smx8*0qQS}65BVK=B4Slmo&P!&awXD-1|9HKwF(JyWvsaei8fTLh zw=~ABcU2I+|0LJ4wIb%F8ZdM1tyfiY)F)5-$}DwOHrS|~qu!sX$2?<)&0z5gE?z_} z{e(r6Ulx7ZA2royQ}!dR|E1>=U}I0Msu2`+`U4x|Ll1uIVs=e$*;E7SDkS#H;7`mc z#(jPRp1Kz(Y9aSk(_1M>Y=>$_;;`zTc=8SZQ7gTye!T_OBOB%P(4ccsxY;d*(<_(6 zNEe+x5IJ!!D%jGAq(mST_6G$w?r^ry{B5nY~R|=C=Fy+tKyh287?sFL>IwV7`D}lZdD*X zs{e^#R}f}={(RhURHmm=e;&QU6k9a*ot$)hY*Dq)Bt7EVy;wb#+>5Z28%5foss(Gh zX3AANZ_P?$SRZ@Kf9#l>k=JM8LzO#%8;GXF;VM8bXMK*vx(5;%jK zZmrfkMST{`*Vtz^WuR8q#a!O?)usMMMn8hxXIhj#0?^#-!Hsm6SKCOT+4+F#x+XmV z4%HJbfb7Y$%#1jjDBqX@oFx`7#>w-s#+Eqq;kqx~r$000Y zmHEICn*X`@6l>l~fxb`tQ^rfxe&$d0&1kC91=9UD2KEgz%-M5y({q@a_ zFoE7Q>&l9M3veDK5P zQM#LUnWi3?)ckO)Hj{{tACN3xLW%jq0~4Sz?4yDGs!NW_wi>mUe)pCUAuQ40+^!Mk z>OyPVHtL|aG4*-ng_yl$>L(Z-4wiwa03@x4`1Dx`1!5M)g*`u#j~NYSN2!LT-(geX zkcKawwug9i6Oviti0&wf4kiQK6OIHmh~%#OoEM7Us-TF=-|{6l7LO6pw!2`2Ey(J_ zJ-d)?mHAaB0&}KQG(LKDAce>YW2xr8fvH3%R)N)M);A{Yvyk?VaH}gf#4x&C=AaX* z;KuIvD%aCA0Hx$CEIIp}wD=aGYES;%#BULEC$wZ^#Go}HH2jMZ@)m)ji{d@|8*ZiJzP3kx5 zAp_G=#`Y=Y=0?g9f8e5jtHwnlP)noLSrY_=Gw{FU!~b2R2(SEq<-`BSBE|o44~_rp z9!NR=%RTf}gLb!~uQH%G3m`xbYK-FMRBDB0$5i@8e+B;h!z>U4iQQ6()<$rrrZ)sl z&^T?oYM^IEc*p{x}QXK*DTZ=h&i1fA8=qUb>pI(%;^7|{_{%*!F zT7uEDK7m|!)LUnGI3w@lSAFzI zBuaO?Gq9`E%zPDW@b>RK45#bw5FWkE7Qc!FZ`Q25vPIDV;ygv_&7tn_>amd@(Eb|B z*Yq)-yW?wnVkI;ShIUaw*za-+e;HqN?N0rrhmA6x32r{9-UQqxeAHWiC(CRnzp5O9%Tj|cV+rvF9^~XqCRy&+TdEv!K% z*SGi3 z*J7zb+v=F0y7GW{#gmQ!mC~=yBaK`QKbnwbM9o^BG9|Nr{ffM)La4Xy_N5Q^L>4rz zl?z97-V8DdPe@R!^>y$oO@jH)3?$A~EC@YLDW}3GGJ)stK%_;TJDJjRk$mUY6O4#? zUeZq%H<|URx(_%8v!c|M17Rzm54{p3cJ6I>qW7M#jQ;@#G z3?kv(p=%m<9mcipl{&to=&1BNw08d}l(9PKwqv^{5oOE}5AsTlg@f}aegX?^(8#y_ zE(fxqj=BSS>H2%)3Ft7Z-tll4Cz_H?NcA~%(U(G)-(E~Lu}K7$H-_|LRSzA7sP`aYOFyHTzs;Ji{%$hIuEh^QiE<19Y|D4#Yj$7{Q>FP=g( z=j@ssnHJWX!auDns3{nMbgjr-ZM`mnjqDmSsM@MHr>qx%RN^>lWM9`e8LPw%dT^ko zWN(ydA!Q`n%xQ&Udcv7$)Q|$=Jy1%7ytL^?OAYY^LEB&@hT|;X!gxD*{KZ0xA^pKp`UHjBTp9#oSe}S0zt)sU0PYd$vBCKy; zq1-c>x3kUD8$Vg(>{fH!$k_94vmx4MmhgH|Zp}csNS~_b{zevzyB(@b_>fbE<%>jj-xA4Ot;Fdst*(b(MzS?b^eon8VW(fcC? zFOVJFw?wk3xka(p6i@u!OEofPgeEaTP+Ug={b3QJ53J3~cp{k_eK;W;lx7alivU+2 z?7_0$%Dr-_oh%8s{bTW*w@)O_h{6#oJXK$_)cMLK`S06M67Eb5|E7lIB1e}(@99-? znJHI>J(OK5?M+9@=0GW=@fALj!cN&5{;BtOZ14g`NXD6UY*w+t^O3>RR-FFz<)>t} za-C{Uj5m+@cVEFbn@zNXMCJ}VJ0NOxIBQ+*;!9|_zj0cX_r zFd`cQl8AXZ;z;>KM9w};rWIDavcA|bQ5{pqpSBTWGg?Ch5->H`F=9J$C9FinFV*Tn zs{}9;EoCrCTuErhOb7hWW=smcDe|5FxQ=-Xz27t8a1+eLm+M%FTdQzwnJ*kz%LZBB zi4Mr;>_*3!tuJ#RGA6eWaw3r1XF9XB*k>H@s7!KiB;(E;9zW8? zfBj91n=}w9;-+(6F{*cO+lHv4XDwY7(5r1HvIvPHx%vtr9JBLDuJ~oFuB;D!j96cu zc-860J3WJK5qytiTcr%@w`S@9IX_W)tv@=*RTI33rGW3-$l_S!a!|4fQCk2>p1rcU z@z;uH%n1fSlqC}UPZnkgn@?Q1yu&yV&wf#ox8fh#@gHw`h*=tg3L+dFYZqepKC4blS0=~bRT|Cg3KCKtTs=4tS4xnF zVEkC`Be|EsvMs>+?ko?U~i^L7WW zM3X{4OlKD}xk)NcB?s~OdLxq5qnvQVLciB7-q;v-lg&SEI3fWxNmlJ9QrjjY5`pHC z6E@P5Q&N%T!fvC-1CkGj6WoS08ebR)G{V<^`p>v;pvo`$q1&gw3hNUk73F3mNj(|N zR=0t(lk{Q`J~+oJJ-_>`Pwz}? zH2};WBM(aK!qcM_Ui~o}c>%Sce_gxk|rv~(fju{t6s*Om**A_ql;dn(@I<#N15iN zw`)_sO*YHAXp%vv&QnjL>&*#o&N*X)%D`1KEkg)&wwg)BK0AX0eQFotaMLGu12|-; z-||6!3_PP0##S10r*w~k@nJEyp=WY0TZvi#X;76NmOe-q)gH%e7)(&Nle?Y@1v6^l z;yACa>j*z9oMp%>8{a^MIB2_}B|0Gi!I;Nr1q+y9ADfw1Od!OL1V}M*^q5Vq0r|&! zh?>`C$TFjrM=Kgt@uLz_=k-VP51RHxu0YJL`SZ+*mT-RDxc&AK%(PaMkJE9;J0jiW zyqAV=PyO};A0S2gsosBFW1$Vl=f1yf3IF!cLlxtW(R)g8oFOYyMNCRGWtDgWcZ7NW?3;aJU}90>Pf2L zeFc>gy7c`E548Cf6P`XO#C1-@Qqo^8elWrxblIw%h8LZL%MB@MgBPR8lVNqvz{>Oq z5Zxa@H**lph-4tLcx55o)lV9{c$rJ1FVp(sBOt{;?IZ=g!cce(d%eP8r`!YiAw@mT zo$!7$eh3+5qE}LqPx*Rtm99m0+-Xx!@Q>B=Q7g{$AKvMMF&&E@=hz={WE=m9Okb8Dox!lV47sX$B%wXRSu)18&NmLC0-q3~; z9vy!)WY2%H0gIY?A^r%Z%Sr5`bM6+&4Xvav6*CmmRd_#!Qc|1xGWy!8wf2z?`w^=f3)TSJnx;8?2afF9O zB&W!vi!5Hhx(p}6s+161i#cl6lkJaKGTy*)?MoSS z@k9~|4D(Pu*65F!dPT|`s;j%|AZi;>LRX*+ne&san=^!9xXJabz+sQdMJeh6pyrkJ z59ivms45vrUk1^IX*?q7wha%!1{I_#s>{N=0`gewxi>gn@f;ZH!*nb1-e*mmc=W5* z@53Ybb0==vd?;$$3Q(JswhMe2BbN##T6~K(lEPT`W`(-fECq1OunUK{Mn2YFvIf@! zAMm#rE#B3jD|>6TT6sIWUNNZ-(vd%~fw31$2!6*;Y&a(Pt1~uSL&hVUY9NJ?dI@Wo@VOt06yNstS@!TkIpkzS zYvdDx9=`mZEw}1iF75??=4-?3ULpept$se14F|KaL9Vv2tbcu@*pGRDP})%VWD462 z4Qv^IT|pf}hjGUjJV0X&yDzP5(6Y146;vf;nVhyq#gpYVzjpXI7z?!x9`L8-+W@BE z?`F`p#q==t%b-dhoK?Thm_}S0o&TOlPEKHCKi~~nQHLJ2P@cQbM^!)5aO4J{hx?$( z+PHzBc<(=@R`B|xd8O}8P@|!JXq}`faWFkHX(keAUdTh!8vEpS_C4i*T;Xf`<}1Ks zQH$&OGWgg*2V?KBUzIMS`>*pks#kO6;F!Bs7&J{|EDa`=g)UOo|hvnU4_&{G*ZALrkD(T5gf6jEE1 zUBi)s4kCSY`m9u zXTNBlt5p}5(wCcrGkIN#n!eAj_WMlo)0X5_NirtWq)F4T($rc}~1m zI%nu*kCy&+RqI7vaa0_0xuA(>C@DvW3#(_F*iCN_N<5f&iYvkEqC5`YibEO03H&bo zf{#?EKZ5BzsmhM{p?iy-gT;_mey?E?@fCwUS{VR&!(P{uP^QDa%{BIl-Vl`pTPlgv zSL4hWEW(bHNS+|(B`?3ZSndVkcF8S|xFBZZ*`tciR!%uLH|hB$n|UkiUkq^2xapT% zb+nRVAJAFJ0LO48a*nW@fH}?44qkhLa`WMQlGRVNn&Np zQ5p2ZU2Q)Bi-qEVofUbP3;C>z{LVH=qp_7cN8q+^4wFm#%wEwxU9V&QbinsIN9C5?x~{2SFmF-#3JrVU3~U^XM!aV>v-@ zu*RPRGOcMt<>>|PWI=9}qVgio_N?McJEG|y&?u-$kPw%&h86@P(AW+T&%Tu?ok1XB zLte77t!8S$;Kp%Z)ySwpH8Bo^ot(Eeu%~sT{?AneghbjP_kbT&ZTaIjk#IQ@%1K3;%+L`bNp>sQ4^u7lLkT{E+MIs%s04@fa@aWLNo&Ny_RM<4oSwO}uxkJ|gD+ww#YI;|i_ zO(K~J6Se$>06>8Jc2~kD&4hi{5`&8J7iz~WD+ZD;3WNe^L4RYf1+6!jlnbTA_t<%8 zl*2R>0v`wInY4Kvqak4^vpgRa3ghR5re?W#+JRXB7U%|ctQVQt>JnVAkhy$8W}0-X4fCvKQu{Fj7K1;Q;hg}T z$S4VEq9sCmW~hNZU}tjM=hHZV;jo0!%C$eneOzyyjC`Eyrov$9U>`2S?X%f0307aj zSV<@wH{PH3m4b-N;EiKk-I2bO7ZMmSZ*`Na0l>?M4XK%i;)d#N`bZoO$uoU-ru5Sm z2CcZR4VF8h#MIr&hCCYSH2guf9g=quDY6(Ij|g36@&Lbam;gPif)nEwbUpYjiR&0Y zebj0|euiDE&K--MJ0|C%)Kw~91p9YUs>PK(S+zyG(zWvviv*daxD{4r-qR92+E4M} z8@l;b-SDVens!;CL~cFhJ^fXO{yc#$PhduTJH`cdz%rX1f2xr`9#uz>jQ(1662v2z zg+I`u@mfHh=qttML8-S}32I$E^C2P{p=?1)eDatyE&KN;N=b0T)-O-IxEft(%?|9& zMweQFrQ;IK&KNzmEKvf^>);t)JH5*SnSVsHpEOYsy1k(dV8T>(4&gv5tDF0-74ZIT*6f*AX_`(89%T>caX7EtY>>$y+V#Bj2+t z{^0U(?IxsE#pK3+q@m6GpOi`6ZHT%pQ&-f3RJNNvc?-$XZ9DRG-r@V%_7Xt{hS3aG zxq=L|BR@9qCu7?i`@qX)zon50K%ja|w6ZRw~?@j;9M(FGOH!yVpT?3Ccu26tE-_%h5l|VQ6X}fj+3A%4|J2T&k>@0bt-FHts@3Von|WQE#Y1Y3YhLo?uz#XB zsTYuWup)t-DGjP~iD3*vARC>xE^UxJfREZGOO{5baF@%Mve@n{v^R zo5-mR04J9EY|j|yuPfa0nsHF3oI)Nvl20OxxP(zT(S@d-`zD>4-_EY?tc@Qe4^dy% z@1!GWWEfLSIt@)X*&mL3BIih{`oha?f$<8IrcUAtXx_GW7m_wBX0O^+aYhWNk#3nL zEz`?Mw_@0A&ymMu4k42P#}x)>x{u5EDB)i*UAq&9?s-p_?OPtq%JLT0i!)T(j8+>; z0jHd>83oY9Lox+I?V&kBC-bNs14ATF9)tkymW>-F7@EA1lr&pe8y8Nff%KYcQRt!N zF0pX>!&?V{Xjh(^+9O7gro1_Ov7#eaD6 zW;k-YsCmzi)!b^!bl@qh%y9)AEt6WB%)v!=5r!EXbSQ$*A0sB348>~E}+8f+7?seP5Wlmu;QKECTBoCPomUR;pp}8P7`Gh5C zcjs#72^r2-|5bX1%JhZD3E`sL#Kwv3vwGF7x=0RMX6z_x@enG(u>%^8TmUwhik!Ro zfNYhlcX9JvtaZ~*KS>LJx7E3XoJh1v=x1u1_O?~~szJSDgwg3h+Jls|ZQ4hi;KQ5YJ7-KA3vG!lCD2ct`*x@7`{rrrz2j`El# zNmOFx3S()1k!+QHg{=Cy@50;e-Z}k*W8WLaie$LLl$p`4i`9^C_*i zE*T$oufM$w3Pa@bIJC>+E?yWz3nLF}teIq}2(urN75OwD8c~Qj#gmNqo7~(LSWa`; z5ZzB0ge=Np@%)4kMm}+U{6vSY4T;!H`tVFDb=Q0yjBd66-15_1#ykn3x(wsUGz`=C z9ncIa%**?2RwM-m?~B&^+* zJmu}za)TM#aDZ6+Q#q!)j*azUWKySYDtW?bG5Or!iP>rYW2^T{7~{!d1x;ns=39#9=g-WY6x|9 zrDq+NJCiV=RY$+VAFJ!cq2og(vxpDUxT#~S#g>T#jlF!rpN;N7{dtu`N3~7v)UBmB>vdZ0YPFF_Bf;O7P zv~1U?t3(cqf1G8K6u+#>Bnc9_;y5Xqcd9ju9%y<{>QJyr?`HMYGqKNt-|1HIyyztb z)1Z*foy#vw5FnWSyg8X8NPvG}<0n$aeGi-0{4T#|H9Z%%o**yKvxxYkCif0K2l>Eg ze-l)V-WjJ3{7Am`UYzcga`$?$jShH&E_3ra{{ug#!d_dRX3ssX9p+y()pFr+y5nOVn z8eQdTnYt#Sq2OPpZS|RZe+6xuX4lm$jLyIZ#El%wb(%^4=KH*BxF4x)S7Ml{u%Hvm za+|s3K&VjEKa_Ujf|@oYM=}zTvie#KK456a@J9_leh7B@TS@mavt~~#8e#?Z+6y8` zr98U0rG6620f)%n0;B`{BdPwvkX;HB3Y{~pPwuDnpf_?s^)c3oUiew_yvT$t(m)d+ z1?(1(Byi|pVgPinSDaDTd_87sdbbXm+$=>d>H8!d%VD-V!fm_I!xySxWu4n_<@qFz zHS@#-_vGP6xxma;BxL3MMOPo@{^|*TO1|ii;sna5CgDR}b|vBY{#a2KYb&F?qBG53 z=00DD=IvOasvHW`!*(N@3!cZH`|U*kRaghqJvU)zdG1ijceYG&`Q(L={AkU%(bkpY zgG=v0Fl{O()gxh8SIT<$6bIoxRb0z~T#O{PzD@+U83Ss~ap*6-&^ z{e|kot)D~^_L|sj`}y|nK@9ZzPOd83lC^A*M_K@8?s5~;lt1q2>nX>toRJys$(u=u zWOSe1m2Km{M9XR-J&Z0nJ>WRg{nZ=Q_aN)9_xT}^8GaV2{B=0fZPMeX#SfJRwzYd!A8d^dw+ciW7Hr-kNC6(@zOu6PHj_9A1i2sf{mbOuxSRWK+L-ZS3k zp>lU(u{u58V#^0j`pYqN`5s)YDnJTG!47w~T^*)?H)a9&MFctP=Kc%$yVQ$p0M#*a zV#Q)07^ysVk2TqYD~T6U`F?`~z0`@p6qS=7Ygt{QbI&;3 zXoOuf{+i^W74HX+Gj;zJ#J|0fvq2|g75tA}0lQR8-lr9No| z^Imx*HYC#xOdPD@^WrD`SGYA@C^4tZ&R893g~w|ipt)^WFtu=pH0KetvHh9}$OdSewtm|Ia#dHJY=x^64`bh9 zD7@T>Z_SE)Ux+667TPGLJ`++Ox!^=nwnK^a!|9T-g4=y}nU?PEQ&+@X-Fh-d9fd8G zUNJPM><;Q&AmtN~)qE<#-a(ci;xV?R*Pmd674zVhaW@<29~li*_U`Qm4LT#KX9||x zBTJ8z(ClC4=1GG-?m6IhX1}UM>_iwXv_;L^WW^=-A!Ti^@ut4h`DV2zQ~k0^*cCm^ zya(GS{sByEMoE9Ofpn4g1y9E)L>&!Xch=_zn`SvShd2wdc^$KepmJzN0KX?VVXYME66?LWJKJ( zKEGo@DdmdC<4dP*zEpD>Y@*A^$Kk5klE@i#!6)8Z>U!3bzp^W1a{YCqxl${(1}w1N zp>X-+r%Jv57A~p^clAQFkkZSF9Y>$Zw?yn8$f7(9q1YjmD4ZW*@RR6Tu|pA@GXg<$=|M>}W&wjJ*Dp~m$TFs(4F%d;DQgZ{ zRD$I#*roek_jfI~wrAMn%2RX5J5B=;vKhj|vP6|v>ce|dQ4F|@*-vkTcd7Eic`>Km zh5+p?e9X4+PI+qrL2$z#0$-f--Ij|^2by}cL?4iL{jan17A|&-<8ty$xH)gqP)p<* zl{?IByXFbRe}2WD!5>n ziXh(rn}rCod&kes&r%Baq&O76LgooX`}O1B&0_x`;Fkty5Q0=XYvf1^%Bs)gtD8lD z@a+EZqC{TJ5Z0CjrNv<+OAnZYSo`W_mRL^?y&=u({g9t&+pZ?hI1}ATsy)7{h9`OH znjbN|d0j};I^xA80w*B3l{>LF7$mDeim41sI;3g4p{17_cT3RW#7@KRojB%V%b)ps?bK|Xa~l<=l6or*kh8~<8ocqj z6+aOO_kLpY`#7GPg|mF=x4PhuQKk*J;c{CUZoqLAE_k$|tyb7RAPFB6J8gFaFktz^ z?32)yP`+~GkFblKebfOc!p)SI#$5hMhr>W0DTvpSv}Np~MHfLj-G8v5%f3YK{U$m? zKU7)uF`h@7tpG0La9>1zC)S`=gwA6!=c6e zq!QvYh9rG3>;7w4Ub3GsnPs=EMzR{dmL+@1ld^uIuyrK*XL(>~hQ+ZTHHP$TTRvs- z@TsQw*RloGAwpa9nGB}EOFPKFc#CKdqCIPld?JkP$9&xe-9lM1UOrWjqf&cMHNuI<+^YeX%BfAE-Pb(dVlx+uC2a-c;)?V_G@$5mE*i?)w3<}$BcL8OopQV+Vovc)S)Ns?iLK#L0*H?|5>50dnr|nLWnUoz4TjXuR zu5&-=a98U$zk62|hm!Gfz6iTJm=Jfb;j%kUSBwKO5%W~&pd+TD)<0fCw{SXKxp&TY z>`)c4CALJ+X%n?1X5OIQ{PWT!a!jBik8CuT4YX$p$SI%v*$YSNxoO_;+?8u*<_5Aixi+|Cmhjnx{Gd7p4CReR|sc zy)YbAamAp6AQ&=E!y+oEG%h*jp|#tc@?3p4|dA2mBW-WiZwRa*r!&KGunh8FQixagvx1ETc9~LO!0k z_;gv@71+zO^4bn%oOv+$NlvGwhjc%V-?k}y5Y@wS3*_fLdtk~`49sRPA4@CFW_BxZ zJU_9$gE+Fm*6|9;JzUit06ft}j0Xj)dNWQ=r8)yoDnpftcrgFxyK4TpBQDF1Yy6ak z#X?ai+A?dF@m)+rlXvq9Y*m_ye}Jv=nzDuYUX zK#YL{G?yT?m+{ZsI%5&nPKQ+oFC4o1k0YPvU*l=(6=*pQB-QMVGOBOQioB3r+;{Y? zO#YJ}KaX`+CZb}y7B@mZ>nB|yPSEu~Er>Eg@hd)-N}p^i0u;>Dc#w7OWw=sK_+UfW zOhYQNrPq) zny#aUO428nWV2^c&6Sl26IIu&7!iprKz5o8kdOD};TeEuqvtYVwaW$!pUprcoD_d{ zWxIR#0Mh7hfrF>#ll}%nI7#^M7rna%afOzY`LmIOT8Pujt(?_XUuwr%tFFZ4vPZiS zzVjO#e?_%sKf-z77c3O~vbj-QsTg7s4X=1E2;5N-5G#+e>D6gaD5$%Z|JjiU%+j3l5~C36xDOJt5^}_VsBMAe z?ajStQtR3DyMLUE3t$^)!(edPOrS>o zW7B;gHOV*^3%gF}2|{+edEP9{SEd~NiN}-OJHUBTD=)f7$Gagfhi{}jdc}{_ZJj&0 zWR;Zpxd^|7?v!dYtr@2DPUwo*2X~@Z@oh0{G?ry}#LibIE{6KpWFtljKYN!%^4lFu zF)U9W9YbKThg7F(gFPL%%#olp zew=v%7e}ycWQG|S+i))}+eWrz9oSlTK{lQ1kEW{3w>*&#dNkz;XN77Yfh_Q^)7Yu^ zOjD*n>qFcqevW<%7>O>GhIKg+PiQ}5EHrRRD|-?|VjsZk zdS{eyWVRH0VrRCX4y8VB4-DS86!2{ zX7-$9YH1PH}$K>u*AlGGK8>PEP+?R&Je z^iT5ANOe>$bLhkey&5q{l>TUxDohC!dptIO@&$JPsF4FVJHKL0Z=iJ39qfITM=b{P)(7-4a`=Wr?sy z#XD1Ov~vvQ+wn~M`m4yNKB^xK$HUplSRI=nSViRa z5SC3V2maI6+zPb_-mi6Md!!sV0T2a;&{F(gRe1|K37K0pQHqyj(WY#AEcG;{Bdd_c z?g5(-UG;%kLS|mv)`t1T&4obkdP8%@F%iwqKy>gz?k1=MSh(DNxu`oLA)4^P#hq3X zpCk0@R~s?nNh6JKeP?l#dM(3G;(QCSiP=EP_yM*1mN)&{>J2;efi9q$Lp2?1UE$_d zm!6CHZnH0r3a)_DvaV4L)=78tA>0>P34EiDQbf)Jt9M*!6x|;jEWeXCaH+~w2QSX4 z>rf7*z^SRGnTEta6G?V!DC>T=g<~%*QC?n&<(mNhkNkt{`+(39AW8gy+SmR9iNm_^ zC5IiH^OnaH`R}`@50@2I22>u(Mm5&(i}qbqD;lpWtwf#lUegCo{v5-1sg)9GnI!r{ ziYJ;QXaa2IQMDWae*^Yt<-wg`ypw|0!>m05pd)Yw_KVmO-xpRU>gHqg$xJ+?@iD9o zS>nuJ`R2k@4yYf6n-;{nvh4+E3wV!p!zR};kVc)`@iCjGwKnZwt+&1w^)0bA)J-p}*wav+g|eGe>G5g<7ujp&Z&ah##=l|3~V&kOwglt>8{J zG#2NQES)xee)xAg)1MMAi{TM7s;LVVh>%HwEir(0Ca4OopnFI6?!@43oFUF(^%+bw zR=f!=?;ha(@RU&IC|%BWM^#B5SiCX1Tar~!qBs#wSGzYObEKfc|7_=U&5nR9IAyn% z*k$e6NN|Sl=FC(kd4&*RbH=V4^+RrdEH57MpARMz#bNTm>Z?9|0{I?pQD=6V>e3umuinzZ z@o{+t*!Pj8x-PM}oh>=^ypjgK?+jBvS18y&earL2|6KVI(y`v{P>%JTc{s0XQ;GCR z3gd<{@qHEra1l|q9wXM~JllA#s`d&aWG+nUX~Iusio+WuH$W|GRR){a~FIX~{cR0B&@XDz24i>ZhR|0Yl6pm;(?OQPwCZR! z@xm$4Z+zf6gact|2QpT804@Cg4eef9q~S$qCJ{j>i+ zP1gU1Up4<gAx8u82uUIHR3*ETP{(E=y8L)`>q2G!hE8&Y-x{=@C)(wF?Jln zUSkiGG@kOkiq??0_OF4QpDLO~3#w(P&TIr$7A!LO!%F7vI$@P7Bdw65Zs=-rnvK5- zs(^uF8Y*>b-xn!Sz;-wxhWBs|J|0pWXi$Gl$vp;*FRcm64;@+Lcxu>z)Wcmxi{`Q7 z6+*l6LG&CX2&Da)t|fLhnGdcI7n?3Y<81V>N7~r;Xe~z+3SqQ4I?*vnAY+TB)0w!A zKwIxWUZWZBMKfZ8^(c#=Ioy^Yo#}Bc&?JEcmk0zLi1-3`f(J_~`sl!wa%-y+Q$d4+ z#9J(ko_(pI*;IDSWj4dKE)*WC`z_iRr=&F*!5hOL5IBC5in4jdV?T(PyJ1rpAcuSR_~TW&J_aR%}G#zdVh{!MGdxaQ)z6zO3{NPh#cR7 z3(~s~*gp*R*$W09|&W;%T)bv@AK%miE}SK*ibNjH)XKew$eR6g8!A@a=X*LRc=i9dZD`;cX%# z;%1E!>N_Ni%E<+5B+(gHSN<~+)T~kT|5>jQ~kn+(;D&D^{I)?)q;>G z38`3eDNuaqB>bB73020d85ta@cM!H+?2**{qvo$m^*?MQKZ^m$fRzhk1UmXD#_~ zPTGKo-UEOyb#BR|vpC%;a)VF-r%VK47Wh;o?@JnJ_T-x(>I@+Sz2t<*YEdT4@R%BZ zv=Jjqs=my6EMqVIh~~qvcQFFPJwy*z(`{8E^Jey|-j&)juezw8Gi_wx@f?d!{u%U4DrIu%6dK{X5Cg;Fm_HFNdZnb>~j|B$hwa2qN0ZXW)oPI zfD-anw)ieqAzmwFr?uV#H3PbToQ=6YCC|$?3^Z3FB9t!+=L8MJ;I;$Mm7_s4Lb+mi z^_^I4MgTNzhB zn(JUUdeTR<99Cf_U8i`k<9KdRYJo@uK|GkE$xRhiD%k7BGkqbcQQBA{GD50W(JN{fq(XPiz;3?{X7!M2bU9W|quTj~a<9JXG_c7$31^ zK3Skq%#ihObFam@($h^BHrCMsSAwr+OcAm7bH&Um%-_IPw-d4~9S|}}Flofn}AEhFV&!wSK@plzmC3fo1p$-JWroI*5 z5t;9Gsddwx*2FjtUHoNXgTF0ExAtAf8t8$A= z4<{b7!9-`L|De%}J0)8#L<2ztQ;g9Yml)*VVnzEtL~fS?<6O5L>+~+ziK6kQ8e)7V z5u=5pyH;%rguG2I?*a|B{Axt-eB<$AH=iFC=zB?vJJndZllW1Q{P;g4txbL-!tS`- zC`a@Kq2?gy5V>)BK%0^9lGYh8r`Tu80^{RuGNXczH*Fa`s8a4b^lLo&QPOhYlNclF zw-1eCdV_FFkdf52UrHgp-_&5)^g$q%b%!f&97#T2R6L~I@bI1ZRppC`{_6g?hPQju zv}-@6P>Zo!+#Wr5{oJ4#VL3{`ArMQdbqx6f2?n*tXGi5?_EXhM^Yc({tGIcbb8y+1 zmCBqsi`5V?qnHp+9Hoxrc6 zIlkS>a-`^H*AGTtLhLSaY#emCAW$KmwQs2^t=7=QOHYiAa9H(iov&xEB@EBk3ij^R zUNf|O0o~!Fwp?(5-E{R-5UR4qiQ{@%4L@5Mvs-}pj)ixAI#x;Vml{F9agG05S>NPK zqc3KOVcIu{uEEoNv6GVMEEtZeihBcseexZ`=)mWW&aL%=<-9Ek>RY(&c9%IfUBb3>F6SLAL_CUrk#Q!93VS-JL?*M*K z*F#H#AOH9}i(MvhW0*A*M5-`MW2EwGLz9c=f^XNF)FoW865lb7ClDpYb_l-BGG%1^+HKJ$TE;edwZ+`B)_h z#UFp7Z&lw$Hi$9SX zKV#k5B7$=9YB)1?m^ND+ZzmKRIc|u7JFsdAo(3ct^qF66 z!rjK;e>@2mV;UmnYQM6B3|UvuvgTAn>~1UFIv24p2ZH6|DP3B!T#*Dg2%>fBay zgr$95zTi4y&LCX`WCBcRdX<372qU&KosSCctlY*0+c`De2P7}$qQVpOpode7pO^BS zc|s$or4ChJW0ECdL$)_8e>feBcVw<|zbz-14V%t&^C`yDAAo8fa+vpNk))NUCdY~@ zB!_cLmz4o{y1g7h7q)Dsp2RNUHB4-6my+xlf+o^BHW65$N0>rqH&yGByKh5ERyuueEcdBk|}C9NMSE;+ta{Sy$2m@Xv*bjA*-65B27Nir()*XjU&&xZ>fiQ}$gS zVXnhPTlk3ki#nSY7&=YVuyQhnm0bB{?;PokiG}xtMwNg}6+A0sHZ&_h?evsbV(p-& zPVp5RTr7c7wO^#}xA@(h>L1TAc1q z7~`X9Kh-SdP03&`L4;>z62$YV{yBU)-~n1z$}_iW<5zT(o~rEVyr7TIFoIz#GAFsy zR`g8=tjvsYTS_>twfb}?dLuN*#HeVsld)uZvUe)_=Y|rOpcbIkOX6(0M<5X(fgUk1 zhB@Sz6ocCcDFg&fPN@eDNlC4(G=p zCg(7BZ1QEJY3j@rqqyxN_U~9!$I-IRmLm9*RNv5WaQut~>}A7p{HF3>tw1v8Qyg!S z_j)`Z_!6_M5tWW5vc(;b2nGjQPQ({XSZU-zhPh@GMsro+fMEs&2mLY0t6SdiXo)Nb zGK4&9ZEl9VWN2iAS1w+^u{^=MxZ3?D)4{uv;t(TOhG!k5v0tVIAiXAU@nvv?C(<}c zCOMRhP3j+r1POpLJRR+@y)=|pI5%?3A`%PUv+86cYtOsWI6>QEpp{lOeg{0HAUE)P!J$ zMLH;e@I`om)zJw5eWt%?l*tTCoQdVxbaP@412#15lJ}2dhLp9e5AqGW`Xr0gh)bG- zwG%QMvtXbk&+QeKnaiR+xu+5JW-p@x`AMz-;WGSjAO$*q!_&}*dUkY`1*~}m$|e=s zAkPNMdTy~u?B_9CYW}OD81`s}^hdwqOw5uO1dB{P1pdKz`_jF1heWUlbjR77?d z6D6)jV>mD>9eG2r5b@^l^Klwum?9_Sos$IV8*Ncnv*(;8QW{JfzB_TbG5fmurmL(l zV%5uRSxB!SqF{XVXhZ`rik0d{7i}5WCm#TXRhr)sM!4!-DLUHmSDPc0^`fK3xKZ`e z6|qAFASsEq=i4W!9ciBMW-R@>)KRt-hM>=vOe2IjK@Q}#42YMU-R_z(V|cT&NHfc| zqIMBL|LOp}|HVd#)C1cj4Aw#x{L%rOp*B<9Oe6`4P}YZ5$0}DdgkRfuAl=HgB`b(7 z&x+q*?+KbES_k2fMr0!n6{#ujfFq459YzCT_eVP;v7smG9S=u^6$+!U^aed>94yD< z$^BB*)?-9;QWfQ96{rLQixtX{rD=XrlIrf8gW`RyZ~tMbf$B|OOJX+ zkAou+LJ^EVKJy@_s?cf@DZ2h8K`|y~Rt?S~`mlt~+LvWAx?$5t{2QFP66p&%cNH7S$6 zTrfvTcw3^1jtPBCt#q=AivtKOP(uys;d3si00-dU0saw8bYVZ)tCYGtzSr22fdrE} zwe9>IYkK@A>`d~y2=K)l$ZmmF+-^*BR>d!{>vN4%jiintajj#%LZL8mgf9ZoAB}d& zZ}J;(3ekcqbq?%K_E>D4r}?0gW%>$3kouv5oKhv6{fY$%%d%yPiG`&@h1VT|qnC1h zAhARm<+q}L$wTD1Kce6y<^(>3)Xy&pb0wI7G=owj=L)Xm0OHJHuXHIT#>Cxge4l~> zVX@iI(^ACOdeWQVWhwu}RV8U-lA@5)DFxPo7pxzddPpj2Wg&H{>Nbo$k{5@nq1Q z>nK4RoGNNV3R_tWaNyjCq-JX_&@cRv8ptNnas*>xF|n^I ze{IBh@?q+pm&$~8Wy|20foJD_rbI`YbPt&%ZdZ!gqKPI>)BoudnWFzC`RdU<9KQdc zyJ*C}UKwg`+2*z{5NNt!o&N4e$;}Wrc$-J2A$=&+>D|T9J*8C4yovPi#)C_0I2M8L zheCI52pLmOAfX-kkBa1y!0cpTjC)2o(?GU;Bd6Q&s^GZES@SCca)u!cI%E9{_-1Tl zb+F1x?++R+XS_J9%I>hVg(<_~n=7updx1v|1xk7;8Jq&d)Ct~ZZ@TGU(=&!rS>F&m+Qs~Z#06ru9{Zb+I(P9x4qOGWad%Lya2!5R_jRdXLv-VpD;4AH_s`{za|NaLZ_ z#;%Pn)*2+4Niy&;ow2-NARq-w!N-NelqHv@eGd$w%V_7xwIDj(zWtJ2$iZ}7@=!|s zv!0tGNM67QT6k11}jW)9(p$H_W`$DJ~K z)z<86g6DG14+ol=wIs||v^ATL;EjL}Z>+AU`VV7HZYvOwez8xoSf9Hp-P-D=@vrK-s^{h;MC3iI^q#c#)pnb@126d} zyn)3+mK$tLEk5dy>~$yZ=3hfuYcK8Ybb3X>-h>=o z^ITgk zDz_OiVD&BeTxTdfs0+=%a?~^qRT_T3wnllpx%U9E8lxYFn6f7$1fnsH8M*-FVNiOC z?DA?w^)1U@jem{hCihSrA=4KGWkI3}PyXo7t($W`i7N7{>S*W9BnvdHKma+uOB*`G z0^@KPia<8_pj)=U+8Cri7*kJItlSjx1Nfy}a?bYT z_)#gW(VR3nK_7v5!dmHp36u()*s+I5tEG9I1C^96k;U_=ooL<7{Lq5nVB9$np&%+( zLDvUcrAhfXGNU&I_W=J}HMixC5@=5L<@#p*IIPX{5JuG<#8)<$NF}>Ugs|aEUWJsfuXz;rvHI*%qToxAPsb3vNHgCC_C;JZ8bqtxqp3m* z+#DU9b}kThGUdjo2pO4bv_4tdn;<}77siL`)8Z$2!NAJELdO)N_PA{BCUKop#0WmBZ%rFQ#&}GBy%;iD|!)IKY*vu2ijhz1CT0F6I zTXA65Rm>lGcbxa6Wk;JJ@?zn!7LKr336WD@m53x7eS}GG+ZuUmQ03s+z}Y2eFz)iz z2I6@(e%%r;vOA~rxJ?%D>B6v27~uUI_<_vwfNT3)A_xgW2Fq(xmP}+?$r{8#EA(H1HmZxxsTU3@R z&Dk*WISrIYTIRyvU_sYs9U=u<3@N@HNi9QP8rs_xZU9~0n@Pvbtrmr3_DL^|5w;M= zV^_6Z1Y8I-&4MPw!2LkrsHjDz-}aWOvm9xZ)=ES_NGA%Q(mM>Q?k9X|C_(ZaBUu;W65)zLlZZuPz5o*vlbbfFNyW zG%D9t2or)Hn=95nhT_DbWapbS#PUk<{aX`aVnU7Ju#Xty{55J?B4l#W>Vn(lgUk_4 zB#QC4-N10yPuTQ`IXvV5QXdSz$+z0#P&6x8tS@v8j3mDOJWK+qvDP3_4T zDf$4@cjl?Gzgq*ESJfIZ48Z&$%T2qO`jhW6mS-zwKZUB5;0Jw}*oG%O4*i2rq2W!0 z!X$f`MRZH7RNze!W5CnNw3-Xiii0cZH_tpy)eLiW$_7@Tcn|Wr5Hcv7uW@KYmE2rrhvUg~zzZh&FrGzL?YBQMnWG8P4 zfPTRUR7jk{e51eou3AViKa0qcubg$kb-?#NpPe@cSRWhk2eao8(Dy_#Sh*#W4|ew9 z1wb_K^cSHH-!GG_5aS&ll`;^yQ{rbgrVeuuZ*rt9<st-lUtaui1ct7RMy=@kj1VK z6Mh;E03VKGk3~jMqJ#!GK3;m2_ZtUf{2EjhKl? z?Lq5F-fHc15yn7a1ie|a$^$Ul0trq+O($}^pW|G{GoSYytWV1#s9wuN8woCrn%I1W zOJB&&v5V&nE?@-ELC^!y#OHZ@N!BnG0?aR&3hsDbGKdByVcz@(1`L~U4DR6)!vsXm z6&`RKgmLnJM{SGV}BeB%7%8b)dZ|@PPfH z5y>x*3q`%JK^@X{F8|%HOENyg940d`xs_6->WRrrf@IYgFf`ekEsM(bMnonqv^k@6 zL%~0g=*q)axLX-O@S6i%Dc#v#J({(tbr@xR$mf{GuiG6W5O*Jb4q_N5lGCfMD1AIL zKm=}&*Hw63xaWm;cnZ4DE!B~x51s#70_i;jy;E_Jq?^-^4M$BkO)+=`AelL~UsqN4 z`Z?X0cnK%y`eHs+F6=qk*8TzlY z_AUtHdwLPGz@5rL2K&~bp6W>sd5f*j2|UQ60Vqe4Kn%HnNM`XCCe*UdNEzq*MKC~6 zKTn|EMc%|RMf`jj+N-LODS-^Pl)+%QpN&iGXjKSb52$wdrYPQ>HJZY*LlhkRKO8hD zqkzMgW+wb>EcpZYhbOj~c+`(342h#YY8kUZ8WL74L&zTYC}8DQ%YYg6tCzUrfmGXn zEj(l`)I{ff?+Iz5zf>YnkU}!bQ)ugS3EHV%Jl-iA4v}W%FxI;c{oRi`=!2=iBsre+)=}0La*w-lTJLM`= zo>V)c89*L0sgN^Cr-;pHU-M}1U5*JovJ613OmB~ zv1@^Su*LCTvH&1SsbA|Hb0GO@u6g5wXYOoAKxia?HZ6K1+B$e6Ghpwm8dQJaszVX^ zadDHMVcZj_yB>dd!>pA|UHzVu_rt?`Na)1l%&A`XjlnF?XG#9jXS${Yo}6T5z?G>7 zp1P&2Ys0Nt9$IV5dStKW(19A&&{?!?83|-~#Yol}n9TfVNHQ(s#Cq%v4c_jGyIt2; z5ih-hTHsB{VPK>sw+Z!v`pTGW0knc+edcoB0WDhsjQ~Xg>S+G=K?aU>(ak!(dsT7K zn-sp81_LtMRbKsHdGLXs%V_{T+QLHh^jFL)Z7!wZOWeR4s%#H@Ubflo#VoM^$i7S3G z2a9|OPp)6w#vFf$1#h$-PtWjDW$h4MU>JkMe-^W8`7mRH9qi_V-4MDfxk_N~n4Pun zPtO+?A|>{N+ZCJi3j2j<4oUd234k?NioQpb*be<;7UFFDohl18d%bBk{)CLiZZt_; zTu7=^MO)Eet0AO7RF*|%{T^H)YUFUMJxAmcOsQ+FyMCK${B_5ZjeoN=Eczb=DWHpj zStE7c$%^OYxX(_&PFVRI{zy0;tz0r(dXX@1T8{90%7B35K%7N3;`g_OMdcY(|lfj}>sWE$04T3fTiQ4-mHo!Prr7h77&89Za;8AXK3eI$C4ijZYm7u zhd+Y~bor z_dzF89La}cGUcOD7|#YH<|tt?{u67vl&oprt(Oz%X`EeL`yN>(Z2C3PQ{GXlASvGb zpPfMEj`XB|S2f#a7S|Rol9l3x(s7wKJxBn zcv-yEptk)CrB5j}b3u=2t8vmnuzXCCEwA8-Z3MGM_*8(%#EeORe6TazR)QpX+zjFY9)49%lsz z(ws7yssmenuXloNH?YIBPYKYcH{F!g>p-IqGG+HRpa`#gh>W$2Lonq$FzAW9n#H!6 z>OwmyF$rApSdxs$l+U%xJ~txq=P!6*>`(HETsY`z7L-;fFF7UBf?Y6SuKOG-#){@BX$ z)FoYAmrUpvf1n&?FoPdlW@*Q{Yjao=P4$l_8=;6c7 zd=i*ti191lk>T=jV?_@O_|y(C3S7IQnIU{9lVB6hWTbB*+D4#tZHQ+WkL{{~|Itm% z%*Y}By#L#No}Zv&qqkVfavM zCMg_)!8_cKNT&;O5}UvfF7xd%6%gUl^D5~796eIX$MYo-Yn1fD$tI@cep2*x87O4V z`75BqN2&#Voq+w)9va`QT`FyO*sMa65W(4TOPca~-piFKdS|+&+*?<%sXC5q-I6E4 z-vnlP-UMVD(BpG9L^K%ODUKnGdNfDe#Rhl%Y&I|FnQHK6yh~D z>6L9rvX;D3ht6B4y#Mw{uI6#RsmmuB=6;q~+gGt_365=_&<$uA;hV=v0ZoFp33(1! zcz7Ps_OyKXMGwBb!fFe%R7@wj2f_Z3_&(?B1`@^IoT`}}4-}<3Ax}I!t96;a%Vp8{ zXra06ldsSGHyjs0oJQmmngCMRf;!fYlMhgosDWOI?!umI4r6D4X<3QdvTcCLWs0m* z=@b&(k;^gr!=VnF2SlHY4L&|jFM4Z7w^k+mqZ(f5SefJs%lgI4r`AUdN9+ax>S_eV z74ktF8B{dMu}wXkqIJ4L7HebqO_tgw(aQRKZr+1s&P;FGq?&^NF$pN0UoKW&e^N*; zPJ`W2@3FAP)yL%8z@ynaGllK@EN2vA@M!%Dci>Fy0)CD{8I839#h~^5b(s$?XnfqN zu2hr$7tX%lJC`n4SzoTJzj59p2fh+cf&KksxLsb@+1H`$b7 z>l7xhweN%a?0CcHl}w$UC>n+66pHcqE{d6SKWsWZBi=fu4Ys$?FwC8m5*Ho^q54lYy)rdr7#Qo4jn1c8H&PXmX@>2 z7~6Wt01NJ-`dhu7bvyzpLi3bzZMq6=R0o9RbiZ3RK-``lBj~DP(~KltjM**v{iZ^> zKn9D7uIIS8rBPy_K3aam>swtkiw)O%o>?HOS9uZUn7=_4!QP9@$lV)8coHD{6Et{w zX(yA8YJ|%R<4?jgfVWAHSgmX)(Z#G^`@}m%-GJ=!=x#Y$TCTJLpF@JG1e$7pr&u|`^#*oUSPDBh7h*G(d#3LA|z9R!LxXkdxz#Lcsvv_fDt*i zOw`g(KO1F$^r12Z6f90;)&s<|?52zirOka%iHnShJA`&ps%V&wE!&2^;{?p7Gm%Zp z+!S`na;=Sa>0Zoa#YL^}IN@kH@CMm>LG(hMoXbTDMXSDOTj>*gNq;@*RKs@bK9-Dx z%1-7PT?t@AX43^=-{TEMI#r<$r_x?N*kqikf`l>pv9)QqL%L6KAee%rt8yw1NFwL$ zo8P@6q>;V##;Fm)bEsI<-wmt+Z`iHW_NSpS{0M2&{k&yjF;|CvRg=B^cIUGfszPk2 zh`2h8(i4KpOAZO$;5i~Mn}4W!aC)aRy|P}GN;fFH35Oy9sd~#yCKv;G7MsG+vwxdy zQg)QzG{uYgmMk|ux>2+!C#9R%YJIme_GH;gb{fEQCyW&+KfD)p4fLwFZWjk{7ro zRp{e7nfCJ*Y=?!y-jSn3N3`uAOG}@1y7mOp)D0Dan$~nUSxYT!|2H2TUxFsL@bvM>T+8qtmmwbOClB#sJqrcL`@&VRJq6;*KA#RF2Y&vFN zpO~V3|2A$^WrA>Q>hHvOmpdf+Zx-PXl%?NyW{FHSQYpP}WFaha`{>kgc8XW%YXaF}r$iIyplqcMkOYYhP zkX)5zq?mOk%fUJl!^lXjMgOzMIu}>2(G!MJ=VJ?+l3R}RAXBgA&X|haj2nxtH1;Yd z*XvpK_W~F-(e{4`xyR;800v9Iv2SeKwr$&1$L`p+ZQFKkk{jE$(Q&7fbduhAYj&%q z=F9$u^XZ(b=LCMyWsnPwILPTNN}fcl)Z3J@YaX1%9s*oAhB~2)1Vf;U2gMl<=lTnI zE3&|PL(^N|rV(7d)LKP1GT_!^ll)srkR=_btm{g^7O!~BV~-IXSUZwZ*akmpjw4hp zcnZwV>`44~W8`KccSlTla#)`}Tum_<#BJByqytU2v<8J}Vdn<9I`&{JK{U_OqBTil z(7jT*`t{Z_E?C6aLlXJOy%S;d{^chw2IHvYGrhjQsA8;5$G`~sjQhYB2J8eC3i?1 zW{D7lp>7Tw;V=hMNVL`D`M6~>1`&Xf~J4I?J?4uqhZF9Ffc`amQSnYht&) zB_toG^!bnKGgti`nncN}rKVVe@5ltQc?!f37TZ<{NFSm6-~Q63qHp(x07YKluRO&y>{SDoyB5SH{>W`qgV5;CO)YT=Q@N~* zVd|;hR$L67ZjAI=t%z4T*4-{Q^&xNJ43&Lkg(kR-Lml2f=`3R8nU*>;; zvt%Oz3*0&cXVd(_NMn_IdErs`S`YI!=a(8>$nzno@)Xc%F`A$Yf3o?0kD+T)^)n!J zenlZ%+C0$@G%(Cx^7rUD_FAo_JYa&XjNbxzrtgeFGl%ZQR*7BZs%g9whsKe-p zuOjIr@8=E}>NK7JYhHN{4hFa2?i+4PyNonb$)_=_`$ z|Fy#N@GL!gE9f11>v8ZB1uNZDvO(AlTJ7$*(uVYtoCR;8f-PCliTP`Rnw=}eMdt?~ zJ}On|ZPtmxgP@ex!)c}zer=u8x*@3Rw@9&K_Mb*GtAqr15`tb&W2fX^r!gmqYv zWT?ren<_~ZLQGSA(5eeUgl-IJ+6A7aC2W5#|*C~FtmZ7TpE>a-4nxez| z%BDq(=7jDzO5R?zYB1vO7lX_sKS18#)BW%Y3ku(lLVDRy%;z$ooej~@dB@V<$E67m z)Xa<_YAz3{73HDc^@hccM{*N>X2akE=f77}D~-3K5>ozM1(-0i#KVO!(NVTFUJXb)WB=3YliT`S8+I5b?8{!*EXb7WBC zI|nDZ`x!Mj^up5hn|a57Sl6TD$^qcKEF#u5ia^&YBD?@AX)^^rV5~i7@G=)RKm=_# znh3@s5E;E(FiwzaCn}vD)?O*svA^VNOXrAK>0`u@eA@HaD)K<6(3(=l^fiP`KOnps z`)(Pnw_(!ynprat91IMMSNMPML8Jf22cIndHy=d)Z$7B%>|mv2=I;LgXM{cfVT7Ci zlM(*>4zK=+h&s^+}96L?xgXd~m_C7kjQ=`)$K94M|7wF=)`5Mm0gp<7`W3 z^n+^~a0@sA2;|Sd3cupP)8{qDB=Oxyty~gB((uc-u`!P4G&j>?DCj4ID!pqe6TGt` zKWh0oJ|W;GN`c#&As#?G>$1JoTWcHpU7Y$!)$V6opO)bVc;^vR8?;DyL&|f%#~&uvzhi%hB_1v@R8Smq$X1R@;BN9BOU*54um$b!ynH)|3_*Y)l|@%ZF_Jl9UA| z1m~pW!MG$hy#W)I&tHKS!Ej52v~j?s+>s0ZOJ52ktH)a1MMA3)+zpeDLmInR?VXWb zBLhndSbpm6MCf!9IKTsDo}`&wZ@L|su#$kaN;4Vd%mysiV-_CtEcaU_CkY`cMyb2U6ey35eB|2EKe=Q!j;ly zR5yC@MHUL^g?}ham2VOsGxMjMXTEFkdc}eW@p!!kb`zm3?86#l$!x({PjJvYV$I_T zXNQg+_`q%J5S!o9(HB}T?_j!8r;ae$MZ~=l44*}eR=w3%SL}m@8r8Gm+7_?!usAd> zM$t3-ME!ci@D+NY!lmCrYI2#lDz&&s&R@+8wj^dta$g9ce*g#-_M^iuDxt0|3Y0uE zY#|nIICNgWgZHT_{ydFFz{P&^5PP&cca7ql=c>J~)?_VkUHdLVz&vSTgi zw7`ee21}smxvaA`Kk^%O2G#w_OGNwU)-pJ38lOyJiTN_k5DYf~F~dD1Jd)w9cwF`{ zeveT2skT!byD7C+C{&^76_-M8>YPTZ-FbiY?q?g>yN-GVy1p|7u4X#_H3Q#)CS^el(0{AVB3NMps zL2>A@cAf9$_G>z3C}W zjw=!F<|3ia09~N9+GCm(O`htYG7t_zbK}~SO9fl~Z5_3mwV~7J@+)WUhcZkRT)bnt;XBNqjack3t&g`f(Ov z?+!`PLf|IE&uVI`<-YF$-|p26=fUM9M;w#asI6YMo5AAr2ct`J&(?Z)^lj>~#tkXF zU<~n)GGEe^3L)G#q*t-KKC;Bi)_X+(-=!;6HKWQiBxga^c0i1XFn-K&nB=_sW0um- zV05jts6cqLJW)>{Q+dK>Lo=_S#Dn{;jWC_T8O(46iuJIpA?E_Z{%X*AH-0tKGA3Bq)^k==Thz<6y+^QnDHs`K#_AJ zLp?`L9xMVp#sB~jW9-(%VdT4uSb%O14?2(rE3Vg>>Lz$2?xdO4{y7 zS+rtPyWBx2#aB8^3_GfQC>oslS8@@ydK-${Q0?`{gcYR*sRptUoN}VG12_&z1iI!E z?lx5AD*o+a ztLu(Z-`s2gf)G_<@G~ z_y_v?c}p_bQD*!TO zQdYawp%n#sP~vp$)2rOv-c(@KsTdTfHi`S$E7;P_8n<{GzC3a9jl0ba^Y$J&B@qN2 z+UW`n_U>Qd{N38?r^M>cX_Z+!2U`wcJd;Oa-9|S09;JspKi(-73(GYW&95#@4G~qD zi}^{Pjb+NKBQhl6h&nSCk}tDxJKGGY4sv5k?LWW>>j~p{u*=?k%Jjh1`P8%wl=HTX(k&+) zMyGV+=?xCs4#DyQKgOVzeuH!!S$xp(#VSgM{ExMdGvVYmtSc$MvSjb$qjN;Hf z=JKe$k*nyNic8Qs3z8!O}}3GefaH+1F&&gFyRgG4Rl& zhULJ(v37h z${mX!swo$CBAJ-A+f@I$tdcnZV^rf07?i8=#}o-K6D+0yhBLit* z${4+&6IiUox84i)efpJ$NQ-I^sdeN;FVuwys}{%MGTuQF%Ajg0RG=yChI4?BFiI5@ z@iFA53fHMWbDl>R`!iE6>1G_i)b~+s{3x*WV|t)>q#%Tscyazx!+Wgzu<^8RD*8}C zqPH>QQwU?LBEYIPwhR6BI}bzV1&k^;FK+r6W|ZCRAfaFj64?Gp#~YxrbhH0g{fkG- z8+3p|WzLmlM-Z~U>&X}FFAqccL?45FFAaI{3G*DA_HcM&@dEdbmKVAJJeS%iG%F)f zJqrjXPb?gHxMzb7@QxzZQE87EC%Qs+Al7QfRY2O=1G?L(h^vn|YOWDJNgQQ{wp(q9 z|7tys(NkYkO&b

    Gg7Epyy@ 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%0Dw0K)I%?GHwg^&A0 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

    7Ygu_6#pb-r3?Lo&XE^abg+)w>{#vx7Pdd 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
    A$oiV}lbusr){n>Ki+y-&d$_ODy(3AB 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

    jazPB8!02aMwX=z~B~Q52e* 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"x}{gYEFQb! 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%0D7XoxvJq)-c&Oo#vLgxe)`&)zSVekn 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

    <}OV^-v*$JZlms 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 z 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 z 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 CS=)}y3EI0YAvh*P@n|mxc`J-o%2bAUD3Pmk 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 D(jc=(zu+ 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⋙Oeg>Vd;L!$mc5_qPylK^2`)ZZ7O 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%0ARpEvZ_1;M@^Ai}>S_y<-Y+ffWt7L`HgV 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ξilBa5g^}%nqwd-Ym-{(0?|tE!jt8So1>~6{ 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

    }-3JJ1J?^V^4 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±p-Wfk8PuG#GG${ z*cJwkIOJwcS(9vb33N@Rg4xW!Om|CQ-;tFcVIs67(Y~`sUc}-9BYYQDoTac@FZo=O zM=+8-J5abivO;WkvELWAOSc*ErSNIDv?$#7DR__sAtf{8Hm_z(!Smv{%dcBSKXyVx z`Y*%(Nt*}3i<=~eTo-T-2vh=?g9*0I)w2K*q=V0>M&SVG7wd;mySLXAm>X znayOy2VgFYw9^V;&?vU1w4u|MGx>v1d+0Jor#3n)tybtuc5hfz%UWui(vjbMl(iP~FA93F_en)64u8o-vJojeaA=l@;m@p~5>*>?VmTWA;Ww+m; zNf*Bx$Ruq#`vD#iyaMatPOgc=GacYi-MpJaAu^Q7CU%VmSk<-7 z8BRBCbE4MSLl`RIN&x|Nh4DXZMI&`*>0

    *FpUq&B<%vxNoWE1U@{Mf|OBnK(?yK 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

    xzq+4?OA`(wsI{Ck6Zy#R_9c6 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%0AQU%FF%l#+FoQt-ou#-! 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�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�``i3(ASqc8 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 z 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

    JNcYv_o7O|h_en6 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≺lf_M z8F-4o0jJyXMfN}Ulpr@Xa85e#=Sormy&voAfK$IpBbKK4_Nb6Yy-e-P4TqfW8NF>Df7{;~!x{*J z_R)*=8W7}E;%tL4BKOz4Kgrxu?2n~2ufA2G#eGS zvgWac_V=WZ=9$j?0g>XE5g|o&xk6`h{MYYNtP35mt)u7?r{QmF<#k4zQDO#e%Xqv1 zj2b3A64Nh{uBmcu5Rqb%-UZRM?_a?n0&O?gHBi?9CnX%?`>K`TpRGUN&=^g;VP$lg zNQeL*X1XV}KcbQHfWoNUd!QR^W!d-itaMK4qenoxMt2N;f-ffFY#C)=M4Dsb8yFPY z6{d|q3vJSVc4178;{sL;pQ7|f9ReDz>{riT_5$pNaMPa=S(6ix4F>ELUbUttA!VV0n^E7S(v8^?>aQSi?=0ZJo=qzNZDfx>#l z#99W#B&prvb_?-RPL-6vU=i~q#62i;paiCr7Y=zzJFzL5))*T|oJ%jB*Q#jH{M3KKRt$8yr)Cd}2Qw7T_Y!&_}|Psbf8{`%y?`FA+slH*Gx1E_|ig2^{O z3&zgc9qY7l(+97Sj}4v9^f*TE>e%s&#K&HET#vfIN$b4BwXU=bf(MPY3J51M!Q~ZC z!ri7o-+BCmU(EFZpkCu#r6s#OSwJj2rBja6@??#vi zPsG1(z-(lJVb`#3`eBNxwK!nKjeNi)PfReL$LQ6*rRRc}gPbtP`LojwPgbKuqF4#V zBur(nCj0FYXWB$(j|a|qXLC@0IV-i%fXl1m98@9t&;-}R`Nvaqn^cZ@p*JM>qbp)e zmo~M;{D9gI1q#l9w_g~zSchBY> zxBWBDT6H4svRrglAwlmCvYo z*TI)k1CZL6aUjE`6-DcuKN})FW;ZcrRNsY&FmPh=4$4jKBL2ir7_j%i-w`9I%%Fdi z9O@oC!75B0;n-jucOnP8-60GvPZqAU;=k*Hq*H0YR_{V>)pP_hF|>faDAwHCIOOI8{YM7K2Rwl{)p96=h>wHZTrz0ARv)0Y{oe+F646^8Dkw zCs-wwwCWl(pBs_@ZToWUW|zS0D$7LWZ^a()uCTo2Gzh!q7RKm%fJE_48<+`}3M|>C zs(A2?=fMksBtskt$gZoxvuhX5g)Y(#TW!jyOZSt$-y$GmgRR%e{bD76+9=LT>cIAw zdTx?J7X46Ls<2l)D-w>ANgK)>9o@LT=VNMT*+mJz-GCnjEXm=) zM}JF6F;ii>>Ss?PFTJM?98p&K7`<-wHqci=7~=Om3XQ>Om|K0OW9Hd zK-9wW8=k$_@$8s`cZT(Ggm=X0gYrP}*%>#iHr9a3N9~em$T%4ywltq>(o-dOA>hCk z`!OqQi+jEa5qBY%%GQ>>%mK8I3~>iTmJU+iISg$ZK;+5CSYTgV-SYo5h0e^>=`RrL zc=T7;n*SBSROG9F`tSzxWkAU?(Oq6PsGj(Mw}9WeJ_?~i2e#5^U$ue6Hk8Bl&mS;Z zfR5UJU{URCdwM>o=My{!!jro}x53$Iom78mQ80ux1PJkZ5Ko{!AfrX$NL&H;vCQ=j zwV*$-wQH&7L%86QP>S_guHGWuIT?iOSS}Q6*sO3CO^p@$sN40C zHhr14wQMtT48<)1Tew@9bt>$ql}8eTYV=b7sLAwdDp!Rp54h%@3Jz|;1#;;)1r-nw zdl_2`0iPJlX+PV-gmg~08=)Zu@Y*Li`oB0BQVAk*EFu77F0uVUDYW?fl^%J3QIvvD>fKVdkU`)yzy~#ZSh=n;}>;+>2Vb&jGP;1TQ$|A#0ZLx%l~F zN2B>qi9q~L{dm)bNg$99EgHr^BNYp4?skZa6I^PxpSEE|a6BAD{dEXh&_{8!5kR!# z&@fw+A+EAgC&%oDJuSs#^X?DTi7~CoMZri!; zmSo9VkPLsPj7f_XXHpn%I>?;lwK&Q%o(iS%h)ga)i1_6aKHnRE!qv3-q(Fdf1ec!L zSeuE;kgtGX6e)Z3w+J7|XD=F1nt5LU%;3H4;^f8|hgl|*ILAip1tMlA!xdc ztn!%666Aszif6^vW_(wQ{$T2fM4W9ed&5J^b9)vDu`5o0|J9d|I3+f2rVMe4s2#~$ z5UtyOU*>@MK5t7LtKFk&bUqCfTo@lXIZM~0*kgr+=Z;xD-QTaPq7BdfBkh z?+T2YGf?_Okt0Y8Bb4MiBjeN$9qGj)7BMbF`06r6*^Ueu=b8BQuL21N|M0}Ah8i*I zGCCJ&^MlcE4k2R>SS}hTXhrAzhU-SU>OCzpdBpxqSOB&y^3N0sCm>=Ds8`(NG=U7k zgS~vC10AA-XEu6J30St*Fb1CBEIP|S-Gr}t6q~c#`3u^?mpd9^RtY{`B5ue*RyD>X zEj?Ue@_69!Vh@Bp$0J1{>4VtG3il28)P^04 zi&-j|50jvF7c2O) z;onfAGpj{J`&SUrna-Pu6Nv(%1IOh8HrmS@$l7%CFZh^hd#u1mS^?qxL8?wTJ0@{Y}`s6<*m_!*u>t4R#` zk;xev5oZbWQJOd~)90YcI(@K9mV1RE6LJBQn`|4`dbf8|{68**_{+*ZtW*Xo?gB*@ z7|dOHs?*27UL80S>i2_wWo|ndVg4b))x8A+R_L~U*XtFK4JS;BaPT z&&E1}ufqm}zpDP5I4ljSPaC$@VY3mGbZfxa(Q^1*< zQ+b#p;sQy$9>|v>?L>~sJr5LbS=2`c9&_BetwP?@%bGuQNG^41s2=0e zoVMW*B=LdQX6jxJV{12T2GM*V{GWI_#_5#2JOZzIG98{tltc{Z9((?fit#FwV40Hy z&6=)2-P;>SxkYd(9@IJqf69t4|29)PRdQ<*CPGYRzl@m%0-fp0y-b&r&N=a34qA=DSvf;31lrYIcJ;2r9j zEmMP&sFO>#3lGAId7e6L$SA0mg}PW%Di|o0UEP53C_8HhZq$~=Tquuf=t{nyXgp2% zIAHgJ8Z~s0JYwW;;47q6v{$Lna>5weOQz*tjzo@g{wRrU5PNUpax@|7(A+nY)tA9w z+S5@w0goXwhJA|lh)ZiF#Hns*taAEui|QQKt9XV^8~Rg7)k+zh^b!R=*XBb!^Y0p( zmW6rM(qN=BP7$JvEVN&R%EuRZbQ5049uS91eseZ67uS;N(g`zE=6n{@zG<1D<_$6f zY9_glt2*3kcfyZ@ z7WR}<#2N1%Y%TsrZYfDE?tlud)PV-K6!56>*sS`w0SkY$30Ct1i6v}O4lv?4A}{wd zR5Si(@P}zw4iGcz^Kn=!thx`11?n4S;DR`4F!C)3a8E1)C|I{PA-;PYN#R1YC*WB0 zt7BMm@@;$sfKu5?OIA*^u|(K*NR3L4XpUAX0_k(a6-Ij;o{f478me%SoLlpEb6h9n zY0XndV@Q)$*hVCJs4#V>Up1bL@+uXZ3ZDJ=bGh6!vu+P|Ubj^$MWR~Je+0&_$gRjV zS09{QS2Mzk28VE2L+EwV&Rct+MT z3q1XBSH~mF7j77y6@WxOiHi9W?MH6JmQ}PL3RVbw9eh*W4NhZ`a@e;JJ7RGY7h&{i z@`)@$nisA$+n0QJ)TQCnKC5#v7LrGkpC(w6);V?+OHn;%(IntDj9@b^#{%8&8KcX# za-UgCMtwujDWz|5KR~MU_?Y7ztqEe0!3fGm_z?rxA+b?nj%77RZKV@?f@2`|<|vob#1V-vSY_wNl|_^QC{q}r;q z+L5e46!6X{WEn&zCsOd1R%gx;79Q(kLG7czjPB4Km;?$@jhz9buBg`z4?H50?fhAW z#7qSLq<0J5IcClMhFW~n=E}^aXdVecf^pz)g}z14XLqnm+ZlP)0m;ZjdLW&m3LDMn z-5&I*vlC-{36UTK?AYKK#=z#*miSBx=$`kg;43yHM4J3($seOYCrg2LupQ^dT082l z?A?Bic7PEO0w`lQyf{AQXl+Uj)*!cb$wD#Kpfb<=h{AU`6ga&MvhIEl#a^&f=9}=p zt~DT3EvTjSwiwUPph$B4L0Kb=sWLzUXRS; z?=zf+T3r2(=eH6qP-Iy5lO}No`o_x^NSa$c0NCHq7 zD!MuE+)d@WeKgo&CnHD?_(z&;ZETxl+N%T3wA{n2Sawgcb;n-K#nkehj*s0HU@I0HK#7A5`>o_&)GYBEi z5e1Jx;`j?CS5&2mGDi3}RG8Dj3=gF4t+vsq<|K+AB0`(*vdMok?oLs-jmIX!D_@(u z8G{B$e(n9IM#%+7M3$Emnq+(Z^hLwvCTS<~sq{wQ zdlJE_e-eIrlU2jyn87t+ZQllXHt0sREW6~fH^q-9p3TLpDT|sUb=Ia zNLh>~%%&cNs$4@7iVb?Ok^Qg-u|t3H{Jv=CCs@-`*Ypb`69FKWzt9OY6E5-w8TM4b zn+Duu(N8gW=VMO)r0_5%^%%&&Kc#tM(B@ zCqYGf_k&t5^Hch^rqC;6D^5f?N`g;LLmm?aLXej|AhUW#(8g|tpinl)GV^CghB?ES z18rVW);|o5g!bq_8oQ%Y$lj9vHUg75VK1wKe*?y|;4((T321~X;HiN-V7KJtfGn*! zt^@^#iPfz@jKrQ{IF#)U(5ImPE^NYPg!HZ}1^pBGyp5z8s3GYI zAG8P<*F&=$;UpIjgM^pu$ROi4wq0p1>1@nE6u^^GxeVL>FkqY=2L#6qQ4*8G z$fUhz;u@BW+9I{|E~HY#Kvb>w27pU6QwO9nKl}KtkA?Gl zRbImhmN({Qb8?3!knL)tX^YO+AUn`xqQCyZBi}7j42TQDX&5e8ykdzJsVkhr6604H+fXCdtp6qam z%q`ZhKD)ZTm-B&Q36r0!-nJft>{QWT#3f9NwN5_pw&dZV! z>i2HT!T%y^M0c}*LHC-Bj)Iu;^~jZ_e8J6X;z7R{Hm(bM$bsRp>o|D{+92F~7iRWW z>we*=lW7A*eb81FM)3v~7cUha$*`LBkY8tcK%a}_f>>KD(NvAnUs~IV$w9F#y?OTS zy8W}-3a+Ox3VbJ5`-QJFy0|V{)ZsJ(qR>Jb0#A&6P1=#us85okh-hbgP)epN7f3s$ zH>BR_+4b9EeVrfISP;d)tGyM&HPJUeY&k#25m!1fqp!svHrw$Nfk&};!OQ*UoTljcGtnnBH-s+?X=Y!i6RYF>i zkShFlCIjBSko6=j73Ark;Dae^tR`VfC}R{@(vsIdwP2kT8J(MS5E`;2#xOg>Q&sJ; zmM8+#OlH&VtzQE)JI1f8mx%tpw*k>AaG|lPVIoAf`P9X&s2xHZnkWMso%X`*VR!=0 ziHqlE#D&W4j$}^EbL+DM777}YYAg0Rc!W68+4hi+!*-cw z6by)Z3VKoCeDnW={D(%B9z=_mQk*yfGR5k$) z5^%IpB+q7-;Hz8aH>~T)kJXd{V~KueM6I=GN11Y7)2x8@n%>`WgJZZw93up zgV~Vo=oz?8{#H?_2*tVWupWKAM(uz4_|b1haP8@)_-j90knxOsqs>8RMTL~O+e?($ zSQw2mas!qf%_N?1Na^;ViIFyh)ge6+Bdf}i9*!;YYr4;2GASF`e~2irJd)^ujh49? zaA&~L_PFQ-jVso5u->Ff6%H1E=q-w7THN#?(G31Jw2Gc!Lc5)ffJn3?B8KzO{1Rib zXl79wC_bPq$xcNk@w%O2RNs`6RG6=1esUm@yrHu+AUth7k1=waFx4sHB}6Yxt14X~ z{@JmiVre>)CkAESjDfJ52#DZRMkuW|liGowx^O=MMtd8`_SqJ#(UL@j#gDiWic>ax z^GifI8Iy(gYET`!rL{Tu)6lZ0V-9o#$1rrEzA^bPX=awDYG&3|e#3#roSPstAptXK zvb2qedhw7%Y9aW{4B2wF2uX3G#x9hu zlVwWGH9?BaQmya8M>Kt;GCG~I5o;I@wb&S8)Ma-B=17F0xknG=lqX6qFM=O=*b%;{ zVW*1EF(O8Kuk^f9gx`f=k&N0#wXK82c3TNifmTIa`QyVhO@O0{ZiObD+0ZFObZ#dScw=2yaY4<@dN7(H zt8pmf%rP}yheOy;`Lz5^1QN1EjQ~0$EgF?0I&G+)Jg{K@oHJ>QZt?>c*FmrPjH9>p zF^t*Flz`k+(<=5NSjT~1=`!72$ilCeLGhS`uJT%lnHC15an^43=Wd9ls$V|uf~9-B z&Vg)rjh1bO1!*)rdFsR3Xk^2c(V-_?h`kSe(*UyouZh#R;S#VO@jIym;rHx_Mj4@6 zETUAwZ-Di$uQ3TN`p}`N{#y4Y7uO!~4E0nAgZCaKQ|*EEtRT^`TGkace?{EYY2=Uz z`m%z&{%KK&q@D=rgDHi1v9KBQPTAniM7U{lO1w25HIPxtJoF1Hsnvd*cf%?F{u-ir zaapje7nkGbEQJ=g9{Rf84Prma-xZH4x=AGoz3b)LnvnSMfEt+jvdlTi*3}T#KzD` zqmQu>JNBzCz4W_iRXj&*CQKMu@I=-yQ}4pEMI&wEnZjMR5xW<^9-wqAb5PyvuNia$ zWPW5;&245Pqe7ss3}q^FTl&Dti#8FYEzno)5aEF+7Qr`_Rc(G!oA5IkKMU~qsJClu zz(M2VNYZ4;pEQlJi4GXZ2@{@6vt8a%&I&LhW~Ap2h@t;xQ-}3O)OEl&>(D13`|HD< z{euTUB6zN_B1PDU886^ikZgnL7fWqu&l-AZGGfSw1BTe`loUx1mVnZ>FH!Mhd8)kwT=HOl!K)^60yaoay3YLaQ{T^G}R|(NAD8`dqru$mN;kvoz-iF zez-PDzLjaSuZUZTXfx=-)Gnz78%fL(0v`Biv6B`=dSb^NzxMgs-Rd>LID@pvv+{P-Z^c%q=KS4uLE zC(#V{BcKA@WxWT#;An!%%i=AR3-;N3A+F44@vY5D=vfznQX9l9U?Ub~B0T!q(+2iS z%G3z~Q!ugzS{Fcy4&7%Y7Um(ET6>GiR2Mf+BRcjIS)c_sx7YD@B2fY62f29tn`jV| z!vi@rU6C|q#)7xO4JF2Pyn2d>Ahc>l*Lw{KjK&qx)Satk6w$0kZ$&_)+FDzkpl-A+ zCbJgFOlm18#EN0bMEkozrh;NNsLK&J{MuxB61^hb8PA6P3XVl_L?=gP%ptYvIZd6l zpM#d56bRCav$7Y&57Ree6MDyT5;ITU_8X6h=M`-?eRpY5OuSGym1$bbI0S@HD?AP7 zSv!NQ(P*SRY*_UJ3Lu#;v}MGIR%9QC3N7}1hO;7LC$gY-GICu6BPw*Jt76?`xzMyQ zN_cQIbEM5x+Gj1WN7!ybwFbB>6+>_cB&}T&+bGS3n})dQ;(^>H54A92hOx$Zt{%q< zNw|6Id3k{HmS>Fz#KB|IILPB5Kj&obgnd~TAtPd4mLRA-TbLw-Cp;K&O$o>62Jc9L zwM@85s~(ZaX`49ijQEV;sBEl|tVsoM84XMTKlg2EI3wzitZ_;k# zrW~R>m_}k?4I7ww*Zx52Nph-ZqrQh<&&l9mI4~G)SYTD<`-6psy+cB&*q#j~X+npA z-ktb7SndIF8mEincZD5xtH7L6plV(qL>Qk?T1D->8#p9~5|382q4CDfUhG)0v7IB( z15Uz;5v&AdFo9#Mv>u?R{Dz$YqcOFb%o3Sxhq-^J& z5j*V%+`XV|iYs_(&z59R+XAG3`7 zfag9Krew+^TR<@vt5LWzgU3uEt_Vc6{f7zMPw52H}g-#E0#&!b3;K`@v&TFu2i1X*K5qNTyk^(-p=* z~SVT=628KRQf+qehhFLOXR>kK8Y=D+v8iL1kWOmZ8B{2A}|+gGjc%X zT@Q`;oZC;|m+uTpaV|xnj658&*Uf#(edtUwy9IY4%Mq|4rm+{i0a;l#ody;Hou!+` zG=vv`vWM7M11sFM)56XNXA#zB?Uum&89|-H6d@n4lgP3 zbo^7M7h~JU4>`e1LZXnXV>Pv7^)`x9_NM*gK?J zaXeEHI~Xc!MN_EnS4?Y1rp~QBNlZ;EcK?&`VM7P4+M=GMQ+`MaCe{P}IbOF!ZzONU zNjU0=OF4g@MTLZPAlO>Q@bP1w9M{+6*pe{;=r01s!uMKwkv9R-PED!-3kVgM&jPE8 zOVniSKc|4xSz)pwXU37v<=oSCp|J#k%K+Y3;##+1x-Cn*_?+aK@_Ip@)z1A+0kElH z;@~zs^`J}4+1T=#A`azYwP4&uNm0!7>3o?c?2iR5e1vncCDb8?Or4Cd*~TjUdLzbx z?@nXOxn$>W8u>bb@nn~`2fkkv7C*?T4FOihk~deK6!<1^Ojj0+T6H`Z5|g*MXy2slf}G8vG=7Ib zO4G>iJ|OydC%h}V^if>@MYuh7N5TMXf=(({#kOtRwr#6oql1cV+crA3jgD=0)N%K- z@0{H|XU=??A93T$b&Vou5hzU6nx}&vx zu9$=^D~|WseEFJVq|1X2y`AWp3 zEjm%&@B5^^v|gQtp4~Dnq_VzzK=mtG&_tntiQ9wCaBp&E?oX;ncUA}=c?*$S6Y`dM zH%>3WLvY@>;8|aGdyVYN1oCqM(RG3)AX@Pt@`w-gcr*+pSNq^(S;tH>^>bmeslJfT zZs@X-P=)!eJVf2e+DaHsm&ANEU%@49q|(Ogc2@jCDnw8&0|dT;mc(70ajhv_XLa5hbb}J2bTBw+Q@_yqDzQU*JR(sXr5gI{YOyeJtZi zj);Hh*b;yq(&d<(uJdIAI6>{o4WRJr*V5uR!S+z(gD^JROn11lxa*9|j)3duTmM6C z8r}T6l(EJab1tNW?pVkjjA#xy_E*mKd?(^)Es{8~#Q(?vvm4R6xx9Yl4~51QE_wu5 zq7~!og6wNo_E)(oQ1%}#(SpbNYTk?VX?vyc^>%6~mJ2cq300cu@4)>{S2nC3&zpQ0 zTms1Pydkp(X)Wy`X)9cxtVVo+QD83!zLU$!54JN_J1!&oKjO2vLAvB<(;=WerV?ad zNEl}DMilJ+Dr9wvo#Mp~$!-w9ezsBJ>w#QubVx#2LdaJCTHnB^$yTq3e>@^?HPere(mnsZEM;@0H z*Ak{`eFbfZPt+~6>S|l1u0HQrV;+mn6F>9CR5tESY$E?7^7ZJiUqbPmUN6=+mrfxq zFEDOrKF~&M%v>Q`?zo^Mq{Ujtsi7x5;JYs`mC!AalB#1FUoZ>sv}R0*Bhz2qOzwfm zEo^vN-N_kVR@7q^SQDz3^k^1+OH~muS}SVOqQr?ZHbIyG*nq=1#)PagZ}tAE^VXh) zXXTAwB}z&i@CepZcR8$!W?AZbYshaRcCeHTR0xgw@i=|dBq3~+pytCHdbMDstz}-* zb3ZC(Q7K7D$OmSDH?ePAfr9(uN)%hYTNN83IfA|{JA8<3A}YVb36*$Pd$ut1eJ^JiWV~f&ILGSfAM%N38mwBprnvDLEp_cjJ956It8>}KfD922rmct&)H}flavwRu6tnMU zLYJI+F1G=&UrKeZ&>}vdkGM=U;Aw^BRBVe@YNf&m9TE!ad1qo-p*sY;s0C^>a;R;3XG&_jO@ygSLOyWc6Fl9I-2Al`mF4>Z9?*y)2RW}b?)Fsl|9%|P9xB>9H_9~Bx zyl8$DZY1V7IWXR#v}tT%yw={7N!UM`0WiFWcBhh=c-JCKTDoYq9W@T=!uw{86AlVD z29*o0(5~5b$mAN+vw~*_MV^qv7OK2k9W$Qw!mp}0sD$%! zm2H`Hhh4U4zPZ_a2W_9A8UaObLRjDcBrK;t>{&UljyjrdBA`Dl4&|A-C>yton^u&+ zb^9;cr3@jnpF=BMr~!Zwryp9mfH{Ewdx;yqks?BSE;QNh>#{{GDj^1h*wz@XU})Ys zgxB`8`%Cvl9zliJ`x}y4H zoZ4f6$;3o}`MjIiI7_t^P@uNZHPB)qf=AKWbSbmL6drGswwZaffR;W3BFs3*af&L%! z`#yz7Dh*xJ;gFrbqmp4Hc@lM1GkvC%(Aj0q#{Fb;nLeBLU;X0lO;2PK+S?uN&hN-gfaeGZ#FFe^x*uTfc9fHM=p9s5;`fHPEH;|wXA2-MBIO9>j znNUz}%WI&S0KXzI7o@Yp5uML!G3>b1?Jl~+<-OEZ^cuJns`sd3Hf61hazn!Len=a% z6Dz?7_|`E+-Vp9NP=I)|bO7{vZVM8l}+U>_;=G_g`3b9tp*$vKGD?D+6D;$=WX zGyO#xUC3QiX?^kJSQyV`Z{=7nl`sd)O5scWZ4+!?vec70hV=8A~XEa}4Q4rpmkBJk{6-ZFxsJJEjqf!leQ!g5L&Vpq5YoZg`9MIDb0S}QAKF)YxdOaL4s_n zoP~YmT8ZCu&i^LE&;&|WWbxj;yihyY9`KJ5qO#i`ri7Xb#H%H30Dj8IXf}5saKXFR z8{mWBS6%s~4GX_Ng|DDco-lP6dqY9SQ4n%kve<;5Nb8AsDlZ;f#7bO%>}Z_}P)o7y*}dO1R}fTTTV0C;-l{u;UXL zX`<+j>@dIacIGAw$VirDIPyaGV;S2a|5U-7Z(nsrQDuLc4^A?VzGPw%PfK%}eDSa) zrcn5szzv!U+CGCN&}Fr6g3{8O>ZceoA~{fK8n85<-AHsR`^Qk*jz5Qi&A{1qsBd&^ z>LOG>;3qW&Ag8| z64CTNoJ;NF-5tq{pC?(Lt~>4Kj!nN)*E$0)orm&gYlUghiyOg5f8v3;5+xA(_n<2% z6ICv{PFnHol2P4lA$&n&jymSjoR+HphH*PSN(yPmeMI!Kso5lxnv{7N%T$kG-Dx0j zu$}|q9gI~h`bGG>sjz57=|z`_7Oo|D<-5u_<@o_qrv4gANg^5+7dl(;@xshac<&}+ zOW~-J*RqiGcJ+86?Z|aUu*oGfd3!gDz4Vo9O&`FD1AWXa;whT;5nFYN2r5%3+l-4j z25#%`Nsxi;me`6-pd&(G1=`jOtysVDceR-+Wq|r($C#qSuhyggl-@byq`dL(VD;}J zDxHopruINOvh^raU<{ySZI^uEUG#-^xES|@4Kh`Q{BtQ{{Q-lDOGv|&~>Z8Tv zlObK~

    9SFCk+9{l!e?gKPsw02ag4R5OEuP99D!3oIGKI=4Fnea#0HUsgK z%%24T(FwWX@(h2y2Y(p4k01({*1;pgT#qWvjxzk_Z8V$>&1VqPhxLT6q4R`@x zIh`rI>!OYs(jLsoOPzrdIl1<%UcdTbtkRC)1&uM3k@2v!;^rb034b;qj8XpdpV7%R z5MJ;+78rov(yq6AC8Sh7)&9l*p=5#CT|>XphB%cCIoua2f0`WD)^i)=loerFDgJ(LRNVHsFV&bLM6~r-n)~(3`9!C=yl_ehh zLpJn;kc%#%y_`E29w!q-6+161^Qe*CO%AAQl$LE4wBF;ULee~)o0zrr z_cEVZqyI^ZE!HExvm*v}2BH?&@dkNDH`Qb^KQH~~TC&{`BhxDckN%@&tjHj-J-lR>_n^b3~bwld+1wcEyZQCiFwvrhJk zS4`H2IVVK&9|@C-N$+aVQN9w#A#Dw8MAOWT;Nc9`m=S@%m})mPnk@^Ss^B%jPs)VY z&uGlLBm*Q5d{c@SE90eG{ZrqFK-c?6sHv`u$Pinqv1eS#AN~mj1yPlDUu?R`JMh^9 z{8Fh`=N=Xp#mo}6^saVgAR7G3M8m4gYh@D_{a5SUbZW)WL((vyk#?SY$tiTT$QNcmJJj3Rsk;f`GHI#SE z6tvC+>bizYDln&-Cb$Iz?_7Z;wNF#?2DF0bPfdZ@M=14mTT2=HF$%DBTyku;Ok$oN zJqtC2)OcFd7I=V`gLH$&e}X;s;d!1%`GiL|{4XogjS?p{I7@z*cQq{YdFcy-5;FhE z1~%ENLXT{pI#iW4u9zVaApJVeqNFE&5l(E|s^I}kaWzCu=9V;fZi3O5A6cB!{SvK) znaKWNLJ?1bV3{2RkjG0nQ9Qe$OxM}RAe(X#m%tE(NPTi6P!xp;nL<6T;`-q?`kd4B zg9HKsLSW>7Gpok`zgdkg`9IAn@c%WdYA#OJ%H|#(|987;{J-p~(f@8&Gya!d<^BKc z>Kf+*>V3E%>n^R}H2IZLfiQgQOxVqVKkPm`{nx=Fnc%d!j#G$fck@1&A_5o+j0MW6 z5`VX|hFcm>-4s@zfRtq63@3M?em`ASM7&R%%R{TV@hCF%hNxBsXiPtmSOp5eE5jFX z!@fijfnRBjy0DS6zsETQjU%h2n5b3nAoI-lf1}0C0vtB2SA^CSoMH#Ntqatj{cpw8 zV4kn>>rFK#UwiCiba6C2^3>*wRn><@Mp3JAS8bebrKu0k(JP!I=SN#mE@)Y0<9Z}5 z11#tqq+YdAs&Q|REVEKBUJ<3xc3m16;;lvynZy2giR#}Kv${a{Ah0asfs>$Yp=3jE z>wEbv)%83#C`mkY$m^l-&F_xIB-^!J$+w>&hzQ2gai2nID%jv*0$gmS-QJo*$X@*= zJlT~jY@30OeHgH1eJRt}Khc1dEE)#KTY8YWjyb>|6UjcoiZjN3TAvw~=^{~H=Z0>+ zcH3MrElz}tJ1l^LQF(yr2p-yfdldflY-j;)`QORkO8IDFJ` zmrkZH*PL$0eB0PDg4^pAbj6Yw4C3LpZz-zXixLd(SD6b;s{f1zDP=cz^t|wq5~TQ0 zp?4iL`}GrlN*n*WHVh(zLQB-tCr4qCCRy0qyd_NddLtHa~P)rPB2{v zJkmCsl2naT0`} zu?l3@WK9J6!RJT(*L7a^Q@(|hs4B8c1IDv=W#hIqWwLYFzK5_G;40w9_G(oKxnXOX z=m0zZy?Xg z1A?VW++Gla{sFo5?woqCDH~VKmk{}kb+~ErEOiTOW@|IpAxG|WG)$RTutUNof8GSz zU-E7Y>Ot5)o283evll}uOiRdNq;CjsYaVXi_{CxxLj!wIJcg8$Juf*}HvA=StaG3U z)MCd)7b8rZDIkO&=EQ8-d148NCcLbk%)~0;LZwH$=pD0uE5f7dNED*nj)*1xK?Zp? zSM`dA$&vffIntM~C2`4&#`YlWTlBRMr?YonC%!A4QypVuI9H;c=11mtQEC1pU(iqm(uWmZWq;YrJJUS?9yCT_x`xGTQEzn|J4wyOfG2Jb<#U*4i5~?ZAMrQ zRAgh=k$aYLMDy4#u=@TM!`z(Qv@%zj=W@M(5zQ*2^186Ywu2Srv)O2eAh=bSLWY&9 zq}AA3#^ReLfk^IlK7E>WIe7Q`Ed=o(!lrTM420`5y@hbjt*N0;fbfr%YTIl`Jiv|C zDi3f*F}*!H5ux(@F^W}W%RWC(ZKTheTgP-UTvKxvGrQJGVzp~PK^u~N&YLi%qaq5=ECkah@sk7i~!Fb4J-bhc66^u^N z*3+)(_)Adzj|Kk>(aH#3e@V!ZQ^nZ`lwNDZ*D(k|Nlyz4ca!1;+hU`WewAo~9eyY@ z$BKG^;M!>1Zot(S2Z`m9585?YqC6%?W$RW9=-a7>iz4879fy-Z_+mH!^CJqf^4uSj zG@2!vsn%DjGD7*G6YBW2BCo(B(O)2h)M_9K@r{4i`KnjHJZg0YZ~@`JN59XiW8}Dt zk!UpL@6%y|ha)g~gvF`ZS^QUwO?!2fO1BpUJycBR>b(rkK5nx$38eRZRK(fE? z*KYEUIY(-9JpzhjO#VlwKKeF#bXn29Ucf|u5#M=kP%ky#?J$>#%RBgr806|ZN+Zlt zBD0ZAI6OXxa{3~m%=Z^wx0H74-@H(~?yzZzQof3@$Hrep~Z6=i`Bl-dOcbdV=Vu1kk_$E{A9icLYe!>*bIwIfJQ z-wzT~#CdX1yuU3hWAe`!CK6jMdgHX-A9LYM>;z20NMXELO*BSe(^{tgh7iG8yvL+h zLX!F;Rkz~F;7;O&6^7gs@#vUZ0nz?y{V*Ac8zNj@191`R_Q8b-2~)Y~=rrW5S(O(K zHRj2`prUO@2qYXgB4q491NvOj#y{g_Lw~P*oXY~<&S@CR|f9_OO?14cT z%hK!}m8P0^`9lVuh;d&}|Kc!n4VWP0V_XPdI;>?_CC&x}TCdUUswHie1$9^An_q z;hTnm!!DNEzE~N0oH*6#_vzYoJo3xT$9m0*(%SRe6+)<@tpn*|y4dpY z>!Qcevwd)i_2>h4<2pNVMt7EZOlb(}@p{Rtu$37W$0bS_CE0wZTG-m|*XnsaNS9OG z6K|Q=Un+~`pcnfXsywhGSFm53jrd~;Rk$ZScA}^j6MbXZ@M(>!nb!;goEau@q>UzZ z3DoitJ9x6SX>dHra8E6~myB?6PYny-tbNoa!#`JLW9B7awWsLO+rSs!5;G~jfTlWq`>1RXCMNDG@hA}L zX`w3JJQ$n$S4%=O%fx0TH`IloLmJ&ya_Z6>I`uWD;Q>9LcT+(U|Dkz2P#$Q!^#^~B6q}x)5(d0i$T!FLW;&?o2xDeeMg!7QV2*; z!VZgQ>7uyx>>QSUSFc$-f1Pz!)FKE$X?w`gsq*g{OQt@IJp!tFRG^J4fqRK+akZMP z=Hw6tgd!RC{W=-#lF`wYqevUpt&=d7=0w;9C?+$W0h@E`Pd~w$8kkPU{j zNVZ0CNEGZ;dPu{L!&Q~s_BYpeB%Hc{Z`|<^n>12j6nh=s7a%ngU$C57@fk&Lpk6Bf73NW zb+;8ZOLeJqRbIn~!{j!l|8$r(@+H)NX?t3V(2K2Ao4m!Qh7Gwhj$yt9flkO)p3VBx z8yxB4p?zY=ogTXN?@2jC{fPvhgjj)-ejjJR34*#kABV-wRQ&Okm~1loN@Qwje|eL0L0vl=;5So5!9{2>q|du{vM_%k~RjZ$+Y3E?0c7 zs4*g9pDvmJM;v0IGdB)VrXsQw1$ zeH*WU3NkpSJ1M`6C6#4}ev`1$Zj`ny7i8Zhf0*)1_bllWA<F+wgX{Ax|efvLok)7c4>3U_&A5#uH^N<)evsr%-Q$~4NHD^m74|I8i4 zvtDMj=FF!(cW|6tTV>!Dsmdae-X$(Tu~r4@5voM9a)Bi7-|ZF`MAzEGQ=vldSuP9L z_qa-pVa+LdIALo=(1#&qA?*IOC}2W4XlM`)H4out>LomYxq}#5`w>gyXAZn7`p13E z^^TO40~4*X>1L-a&hQM9Y$*N>G);v_eW>d9aP$=u9QG_Bn$Q!M)w&T}mmEVTQ9$EDW8uD z-1CCU8oKKnX*aVGg6kBR*EVhCe@dAOOi%e|9W z?D)oW)(0pmGkRjoE&5pVJiJXT1>10lg1l6D*vhX#APAY}3mTi*VKK=Rw`bzxmAsz> zVJ0>ldkk7Nb`s^Hzw1%ZP=8XV#3(#1VfH=II=Oq>>*9MZwc+<{x+S{OJpB3se6mn$cMJEyV+4>DxZ!=X@Le8beXAX=$hVk zC&I2~rU@~1vJqw{68j5NRaF08@`n8cgM&lOUE2LI*D3b1aLi>!wq9bIB}F6)Pz||9 zDs`wO+HS;}(PnE8M~qzYid+FF|7dEmPRNFw1g|f{6$H$OG&htXKx0vU785Ofc*J(< zL%3${?T<|5BO(gl!gG`(y|(X@)K8VI34#5{{`H~2g4$IviK zj)?;)EYY2|3q42gX0ecukyTY}*u$xMggVUjBZ#mDaV>8*-pOtSJlfA2Ng0fA(rY1q zzVmOU8SueozH0o97A8R{o=kJ57`0Y6C_}kZ+n@(^(BJML*yqdS!25A~4b`70W-+%@ zNOr;Mp9bh57jw2jEQ<)}IXCX#vMi5PC!if+P{ur;Y#$wyrSXRa!3Zj5RV+PQ!CG9< zB7@Ak$x{}}EF-?eWBsaX!`_uB{S&mgTMObb1m|=6kT6~UMlVadj4qcb7D>3J(ARlxx*v`(R7)1TrdJwKPnnAse-jbHfx!gnyBvdrr zQR?iZ%q+FLVyCO>BOya+* z2t#~T@*6v_8QY>}AMZ2?{?Ysw)^3{*P_=(KPmw{iB2cg+6&#t8MghAvGFvXJ^9$}2 zD4VhmyTCR)9V3eTG>M+0&}qZCE{YT2G6A5PRE6wF>X)+xtlLju+av^j>{=K{1HmqI zP}_yVq9hiaAz3s83$`{4#|UOtxvck@j2(a5?JmytV`En%xQT|bZOB4w+uiE@JJ~g_RWN2tlWuPityxom1>?6z2rQXB&I7$ zK)Or}V}2(`aO*+A#AT&txFO2E_O*9a-b#@h>X9=PcaLt9Y2pBTkoJ}iYDRuW9`4S0 zSYW2lWzzFT^gg42M~pBRt|eQZc<`d(Jy26e{%#M!ygA0c@eS~8#Z=oL0?e6;92F`Y zwZN) znoHgB!m-~KVGH^pu*ULd=uVis+P5-GO+>b3#sulO#&BJ0+-Y>J9to*!JVKDPUx9ea z1AKzL;iTo+PY~&%{ZD-kSvdV8s$fZ=|6JD0d8fs%TPirqz?ihU$I|ol-F!#3rkcJd zYWccN$@H2;cByeV6TTTup@Lgdp(5X9xUE3#igoQBz_}V}ZefHi5@ChegPL9Py(W|N zkMgG$$KnLtwjs6-^A6D{ckp`}6~qY+n*(>@&YPxcMR3^eBDB)rzh%d#pnv^JGhrYM zemOJJ{1yT1X{$v|0xhKac65Ox%uTz3rg{4)gXT&yLt>pI*Y7040xeriZ`V@5*zF(`EEKpc-teo#G1GHs*&P~&@xEA&7)imkJoi`lc9yHcGb-+90g z+0dfD?OeTG-X3T;h24!h1pLvjW_#RLFx#W#5cEOeugzv=N$4w4m~w(pPA)J%d81>JI`wWE*D@AS|@JzAyW4{6C$Tin1CNdz=RTyg*#=>+yM zXB5>y<`qKV1v4ye67qC{%=na^Yq}7Y0bZ}XSqQNdjhF0*vhw6q=_-ibm!eAgtG;SZ z5ax*=lf}TOJjy_c->2dt8!&;^iPr^cIxBkD=+4qY~t{pOuq9W1tUxe8y8{LMq${u&QP`wDA#$uhsM+Zu8F zdmo_$cNE3gVXd$Yo7I(bm*jR7tpQRx`=c)Durg&!W zs0ncKXT^P3w#Q$CvWbe)Kg%S!ChVCtk^8cB9dG%I=bg*sw!8x~=L`+jf^cVAS+dU7 z;-*vI8JTb;*&m`~!@Kc(&r+rF#Fn>pIF2}BL(fju9VKCd%RTCTkCooDf<(RPqD7r4 zxYVP%OKRaXnVh*2omsausl7QOz?hljk5K8K|K{z#YT(ETS(j*a&R({n99hRJC%ORQtU-r*ch zgTG=14qPtbZTEEv8rg?QTMl>gd}5Qcy6-PQBQsffQZjA?V2nfZOA-79Lr=)K=sPcW-uW}jiqmlNB(g#!3@)sAW3WF= zGR04n|Lkfb89gi{C+>Z2o%xowLY_Nqc?gPBa^k5d;J}P(9LRk_C<7j$pLDbF!L_)n zan?q2>WU+TDviE%OFd;9AFWDJju`h4Q4bIsc*7PJe0+8)OYmU z1lIS=8J=1ms}L&{o*Ymp^%=C~7t*ZHGE>3YLphBFY9PRGr7gEQ+E_==kzxOC8Y#A4 zu5b8|ML3*gcSYd*C=M}AZoO{Ak|Ht7@OrjRd=Ny{HF-f3N0wAFn%lCNy$4%tT5J6E zy@5|^OvvC{tvwjUGq7a=EPP9&7?L{vnQ8VE=1kk9GPuEZ`)`h&f;J_b8#h@na7vuq zJxlR~#Di-1SG@EZ2T8;J9MlXmp_n6_I^W*~(=wxqxmZkT3Aaun(U%ZGUcxYp82#Zr z?f921FFw8wNAOERl>W_p}*b0oB1~67#R!j(L#9Q`y|5q-LiL2dh5^s*EHpc)Jy;2J$)eo{*Ws zo03xFcqJi%9LKQpu_S3I;RsZr{)ao!U~jRK&!zuQ@!w#8(y5Xupgq1a;cw|MkgX@A zQtEEPY8IO;v{^LSb=SsHS@kC@Hs%AzmBy9@Xhsvlgn>MIVy8}2&{nNakr=HjpxcO^p_NU;MyGPy-NGYDP2>}KQfIZ`HV z`OQuTcM-eHQHEswOTCy%#9z(BDFawhRB%%OwJ>nMhvdLS(bFNH{OalSza=aCyRsA> z3-Ggqp%$EQ*_a-^j5&N$3nCjWQ--rvmu772HQSS@we!5?aEct<%IR%^BENVTP{~uC zI>ow8;aozCaIM0+LRze5bCo@r8In-_+dc3Vj0A@Zz<-Cn zhN1scrH(@VI*BPfInr1-JXhhp@@?Lu3wemA;5%cGD{dttj~^13K4`#|U95{&FBR7$ zv%k+~{JdF0=1o&VM`;JBH^xF7Zd5}5l{3gEWg}Xx6iM8TxZTP6nLfzjX%&ux#_l0} z^dPG;c8O(-+LBEX-h6Xey5R8bz=l6E1gcVO!Qk76F~W1u?6&(CShhi-gMS_2 zal%>FBJ8k0$l#gWjiEv#bJ~FqS&z&6CsORsKZih|@Ox-jw^y1piE$D-kJX2}Y|1=WU$BSe9iSoD| z7^=wrbn3i(n>Kp!=d{v^TA=h8o~@p?TMaJwlW0XgdDDm+B@|yde?xzq98CMtdc-`Y z?u?Kvb*zhL?vJ>aAJuj~95+!KlucK}3ZtC+I)^qStM#!Q?wUZ7S3X7P%i>GrLU~%U zA|Z+qm5_=4aX8(>!H0l}crH;VAlrxW0%SZMxSJ-*UW~wjD~r@hJi+4*SE~a{&r5j~ z@3;xHXZmYDuTc{z&#+$$obmHQSTp|>j})|kDw=+uajPt}gZ6=*vl7EThqHz6ED(YG zk1}O#RElsFO_Wkvn0F9=@Ftja2>v&CbF8QKW3bcRwpO zuVBXrsWH~40W+SnJvsTSzLZCC1aL-&DyF3DddtfNjV4fR2gt;|ikp@Hq>EWkS3tI< z_~DQ{T(~8KcOfrx9_Rdz|GU`*!r1Q@H0o}EjPs9PRtxFr1-y|gR?ZAbxMw>827UO0 zqQWPky-?ZD4JNw)hDv$2L#-P^e3ENGo0kdXO44Kqru6w%{NL(Xsh~erswSyw*J|%< z9i;I;b)S|0veZSlgbCN@h@&=4XvMAxgUK%Gept0PAdnWzc`tN_lf{B^!(j0XCYrjZ zRv~{gMMmJNw_qJ?_N@duM)%!I2h;x+8mArod~)gpC!Ps-yhmTU3CF54OwBn_1f* zWiwdkOhDN)B0>B;-39|2g3F@rHTwfQzF4p%IP(pIioG$_wN~79dCbHg{6GTc{3i=I zqVY^yQ;oqZltU-xps6Ym@k*5$XggZ@+Xt}~X$5Nm5U27by(o<0;mWpVQ|FIr;2f|T z&rlRRb%;z5+am8)N?xva9mkv?v!j)F^~mOwcquR0Vk&0rz&SZ6X8t|h_| zNS?j?j!5<<%o#nlewKC1!*LOSyE+?%;HXi535k`3XAi;*v@iROHu;*4k=BN>%t<<0 z`O;)eU4%az(&)_5HUIL@L`8{&7k!FFrc`J*3v3iDiCy6ro-Xyb8=vL}`tWmu+4=ez z#NVDhp1LO2sNao8!6^Dl!n%(6=3`?;BspsK4GZDPG-?ec+? zGw`J=wF=N$ca>XEA-{DInldhhNZ>OJOZ$Fgw8-0Hb2x=$uyOQBHQd+z++GT3L(5k8 zpM2_2$Mg0&R%CZ5iQC=B5TBL6TpY=U_|Q^4#r7pFtQ5E79;Q>>$fIW9hcAh~>-Sy( z-)L`X{q;jfmb z2R;*(sFefg+1L2ljD_M2TY^pZQL1b7lf>tjP3l{O{x|?__FR|5jDR_|?#sG)RZr}O zWUX-&84$AXP|1Bh9?jToV1Sm;&v5`{vmI0^5pVsWHI{;}Qy`p&fP) zQTFjCQCaC(x#8HuMauPyJ+mYV(7N`e#I@8;z@znjF9gpu6HawwXdK=t;x`zMkFl%( z@x{J`C_fLjc%xCM6YAb9aA+fkZCg^ZU&bBr0~ z3V1VQxL%Im+O6R2cH(CO50w-b9F$;)%|%qMV~%NrUiCrr?27ediJxCv5<(qJIqvI} z2OIr1v|NZQKEElHGzzG=H14M1g9o;>Eyv>!%zG?BSCe=l0h9;K9<`uat$*U+Yy5W{ zCxJvUll@UIbbw42cb`DM^6r3;ffG&@uA&YZm!*;Ow}PBzU;E_NzPRz4zM9+F`xGct zwH`^7wINwV!xK7xOlJV9pWVA8`<&=1{XIf^uB~ZmwvHZnUuyxzp(Jaq(`uL0tO>)n z9X?$%LZdP9mW!@pB-p{^u}bN0zvRnjNfvy9!$uL1!y432DDhK5c$Z|-`h8WbIcg}~ za*`X8WK=BOiDT=;xc=dnK+Tg2hvi_~KhonUzF2<@tWexX0qL!=eE_;GCR3iKh(#cQ-2(HvRieD0Wsf(57kC;uhq^!`vnQZKbOthB3 z@e$15n;E*9L>+5JnRxe9Alhzwzp(wt*q6LQzCEny<$#YNjvf4Ap0dY~{!m1@XLM@q zwo3I=O}W5lLxTKU?&?(4_Y=-ZfmR#(lHA-Dh^)5C%kPdUxuqd0*`mGGLqVAc`FOtA z(I=caE&|T?Je6XX9AX3>EhG--3C}1ZX{DqlKZ#z^4kg~(y%g0ufG3(>y@l`?v47^s zXT3F%m0nsXA%CRz#smRrLfEa%vjcw}LH(a2%==7A;z^^M>)@cJ7SNm$W{H?=r%isQXzPkb2 zE1_(QJ!ZDGsCiHDJTmb@Y?Pn{1$CxpD!Q&~c1z(~;PZt=6RJ?UT&&*OO`#scnYt@z z!AJ_J*I-0x*uFdcoph@dRc4cvX0%4cp>M}zfP5z=e?WHY#$;&pRU{<%lAtaoxJ*gI zsA~OBT9M}qa_{niC)JvfUcb;XY}dPNj#3jGFLdwI{S2u1j68D`&u*KgkT3#=yCkDF z)xdE+O?k}AdnbpY+8EooON%aY<7qfHct~bxl!*T!#1}U z_Zo_q({h)-UoOyFEm4i;`lRwyLKywbsO=6Md}Hs=9TfHTKO59l3spT&=7z@F8sk;U zX7iHA1!a&i=LmAQTK2F)cxq$l5?w!O!B4R3PK_1xpv4zup>QbUKD?&p6OvCiYh>l#!}}Gg2*Ix-AmlO{TSmV zMiD{KEkfO~HEy~EcS}WBDy~})6`}o(xuiPRSayPybHpKV2)d&@SJETwfJ%&rQbl~Q zjxB$F33r9}9FLIY`#I&QtPR)% z-V9qLi~#s-{n`%r1kwkaO#Sd>mJ?u8-8|@}$N4DafO^nC8N9E%!4uZY=E{rVe0NES zBCJ;PX3;vCFue&UIXhITrRyX_QMV-Xe&t$1k|>~d^XRoI5W&JyQ>{iUCG2n-1ArrY zRNhyJfF-aAodmc$kTKDreI-jJs!EB=rhG74$BU_9dZMgRS!D!zmDY>NCqh`J`MZ24@N04+0Q0M3#_w75+ynZv9L3&3F51U)L%x zusO^yQ?}lSEY1- z#Pt|Ay6F(d4Lryl`}!$(&4e@9j)HyUF0zr*;^#qj@;Xn(bgp#JysSYkHiaa)=4 zP@EL~C}R~U^q|ZNI;A9CiViv&XR&U$12%%iw{Lj&YO}l1wxC>Oz1YJ0b^#N>-4p3T5;oJYjnn)g^vfqAJ zT4mgkIm^bMOk)3xgX;22RDmx_KGcCjEIHOO7dBO94HK>88MY0L*>xhGuqb6$^@y1e zOOSxiDFAa!GL}Amb`u)s0*!AXjV&kBGR+RIl^1%C=aY0QAaIiWxQ^sr2!dAsAHwai zxe|au7I02%+qP}nnAo;$+qUf!b7I@J?PQ|K?7MaAR&DK<{SRGT-5(wa6}xVkDzyz3 zP%v4XRrjKxWE>%(n*l9mf=>$U*fHw(RTE+7s{5)AOa>K68{20k;?AsCycUA0_j47c zBuDDPMI2f*F5^6?eJ0sdCG#;TsFRYDR=wQE&~-G|OL~a$ry{$vBgk_V=&B|R;%p0DBX%+ zi8oAQL&T;WC~#t*Lo)E0_X$9V+=e{*ODV*=&A0b50A>Mzc=~r>RgU;VL!;2Da*Fy1 za%`mkp=`mDKjLZ)$DTzGfF8 zLn7;DLXmD;_9k?m4&6nQ%{M)#Wn%$#;8;SN1qH@D}%eWKF+*R9Jn|@JfNFU3(sUjD|4)qxs;PUp=}QH z(A{Pt^r+67K)i)KtgoHI^j&pHR*wO}UW42U225U0YRGcm@*H97oLbkYkEQP8T}9f1 zrZBr)hv9Qz2)U+7O)hjzGWH{nak|E-Tdf+1M2#To_^#U%ey+F$b5=0xNyt~5%sc`6 z_-F*Cq`de$fzXiTeT@)R`z79f7xZSd^{71;Z!Q@RWD|KE(H-tHO}q767N^FY;1qD-gDc|aaPX99_K`6e49(Jfgk7d$Ztm^?gWRRf={1w&_{669v5Q#bl5zIz!=AGPE#lPC&|Bw1xCI(;TBRwhL0VJt@grWARF9F06ob#FSsQh zY{Hk0KF4qze@I~0=5pA2%+=x^hK$87=|r^_8odH^ z;0r3|>(l12w>tGFjtZ@k#S{M2@rNpu-{W!CHq4V^^$SSEt^!#?rUow$#`e0<*bYHf z3Ljs7|dAxsbKaHzDS*9~#4dnYCpi>Ndz8%iog( zv8m}KqskF4{@we)YhI1vcHpA7wjkAwX`;%c>z5&WP7W9gSRfhDKqx-+op=>6hzI|y z@)%hA`Y3@YrMIN9#x^OZVfVhDIMhrw?g^}E-AI){cf8;;c2!!Au0YEFwJ^e+rh2}pM=1b`sb-W zdz5NemFhlU)*l|I^0!4~e+D<`Gepm1M_8oPm7A@Gr8EyFA*&bG(Q;Z6<#$UR) z;{KQJ#rRnNpVu`DHBc+&Qtj7}#W0`mwVpBi%Ca$?R5PPilGOWkF)~cR2OHm|(*X*o zrPUZ6_tC}}S9d}d00%LjJP>?N=^Q!eLp2YY2n?NgYq=HrCW76nFGS2dz?j_1flaDP z@-U#qq-m%OwbxG=(+*ztgi0|z=-kWfu?~V|b#(1y z0|bcvj>GHH98nD)_-7bu%N;a^rrgh)s#N8@nR(HiAKH}zuH0Z0)GQz#mnhM8X3=Bj zr5FBK%}x?(C3jNreFhrCf*z>z-Yg&9pZ^HksEvHu&M|VNQl(x$xNx0L-~w6@0(ouR znRLLf;%C7YsoI1|Q(I9|QaMl0JFD$JcGFH87f7u>xX=Cm0u4^79}l(atq9R9KutRN zrChop(93qJ!2{_NwbaG~md4+Rj^1T>6caN_pZ(65zVp7|>{R&}Ow0)ob;cq#-34Fy zVb4axwxqCGHuy#Hsh|*nl@of5q!-4TMo`fSU2=o@dHmp_F5DiC>Fk1sD`Cb*uS7UH zL?c<2Bm$;B2mCXf*E5Lop@m;zTD`bn9YTMBIeM^CE~6AMq)8CTj23OFf9in@w`o68 z8x!d41d_ngc|a%EoCT4$h`dgTvKgov)PxJBZN}*sm1`XX`mejF6b65*q zpZ~(lTwRF-HJ2hJ$85y%HA0-ggmSuEZ#alhRx_;zVNYH9IdSkiQ#sRcDWu6XdF9*y zSdzby%^czgs0896v?yWfC3rx($R*R*+Zm6dj#oSmMqL^7F&)8z6R5@oKjZUBY#pDO z0F1jCkXC972skiwe~(>fN3qHZd!u8soCeq4qpU+^V$#PL;6EIazCIkpos6p#k_O)>joO| z*Sm?^uuH8g-b<28DY+5zW!MihFz)9TC!LS}ecRHVzu^2*j(=r+E&gQaK|R5ZBb`(@ zpixEi&nyDM&ARb@IwpG;X=bpti>=cBY!q79i`w?ByPi`OQ`g29m5 zGm;jp*cnryzeR%I2vswNH8H(`Zy<=KaFlyhR6ZcrDUr!xiTW}D_ekndWN#K4pCRjD z)WCI36m9Op6U+rq)7qE2^(KFc8+(m zSD&@&0@?#zNWPx+Yq6xpM(}Z6M|*fzwWczD>61#oK44dR=*Vgd%=jP8u*$uJ#czbW z+?Igo1y9xx3kP&iGd%f&I${|lrbr0z0tx-X``hp<0@v8RPl!J`fvLVAkz?7g*y#up zV+&M#zg_JwbS_Z9hZ=H>Hs65cF>v;m&GA_e%R&~q9c6W81q7(8=}YaM1mN!0JOd~Q zrh_S*&61yj0wIOu@s4w$u+JU!=vvP4wL9@yH^`X5U>>8EH~}z6{nRlhWLt zhnUVU5?b>8ZP7Yan)C@B^~V4%5`>Y`*Ih*d$+UF)9`50L+Y4^*qJYgrM;I4+j+|sl z?G*e%i3wTC0D9L@dhLuE99rMq^_uOx!A_gnBmffO53aD;fnc)15xcj!KA*5buOg+T z=2(0Kk}))Zbu_ zDUqOj6aHtw3QeeFZ|oO)b4>yT(zuKXqqNE%9P%Yocc-7kI5W{9@`0v`zt?{Y*7W}& zSWW)FU>!F7-+~qG{|Q!Ab5mnGQ+GRKH*;l;|C_Oz{5NBz{hy2#Vi5p);CR7|?4--f zY|67-ly5&ehZ;ArGE=t!@3120@VtOD?YiSW!qs6QUXd}pxi>9v-Ejr&is*;vgV??u zj0AhI)RE3Kn&TWZ$32Cx`?|b;suin4+0C8rE>O zcg#qBghGR~L*sZGOF@Hp>@Jk&=~4_qhMjC3cPef&gw1=ReC|{zwA{0|b~$f0_iiL$ zdm8r`^`I=|y`p*rEU%wo;l$-nx*>JB&Mm?1#0VlIn!7-*5N8fl5c89>hmzS7!|L*g zI?%K!7#E6m)AWO1tOM(q`3>{dUr`O-*-!m7H=$k`eA8X;%vxlSR^NAw|3J6%+R)^v?0*p=gahV1P#Qw;aig+EWRT&Uw zU03-tH1&a%1DH&=Pp5H(xM2~Ba~V1=RiH0co`d`BN$F;2G$Hnt;=vTAL~S!{Sqk>& zWOvhs;-Ny_@~Lj>Bg&VgL%h>awhacS@H57qqsummMDQ1mJm_J2adFe+etLhfNy;|? z0Cw$X4w;*ikfk~ZQ8x_sd`#=JvX#sIn{uZ#^WFj9El#Yh-SqyF?~vnHMx zZ>VQsv+cZ>I9HNw=hSoWRCZEA9@q~^cY9s9jaKEDkvibfH9+dN&hszOH##n2qh|9R z`9)|O=Z^CS>9Nksf)`@q)M2Szc$QL(%LNl&+*}93Eps=Q(}Epw zO%CC9E_ts*OVF`5EOG;0k;~M)GnTU<`;R(~Eq+dQDYfE~5j8EA9nH18F=2Ert3@Q; zvqC5~u++`Fu>KsS8YcVn;nI{YO0P!*?SSTUh*%@e zvvD0LVAa8B`vtl{-d{6iHPwaLWmp2;nCUbb$!c&TLO!aQ%&fu|fro!JZi(dZfgP3r zWAD(dJhr>+0nR)tsPG~g5LrnZ=5BOiUB6q|Z;Fb1#_h^TXLinE*!7)@Ao=H!ugLV` z!PC6C^be@J6)o1#XZqzDmYvL16)!=&1>|7uMae9ue#6XfOZvEIYQ5xS7Z7JI0o;FK zH1bk7#av*gCst$(Ra{opPh5l|hN2Y_k|+R?&ge}1{n@Eqb1hUoPWD}UxgrM-*}+t4 zLSdQs^$1+N9(@t8U%^|;=qc%;YzFsrYX z3{)ucnkO{sXt!+UvPU3t;4Fm>Ba?) zE(mHH>k*!qId-+j{wxA^%t|_!wQQ0WGrqU% zMYJBKxu9MN2q`GVqMa@wdVZW}sU{d~5!{g)bL)1wl1D6@^)BgB7=qlQH{Gs$F^&(F>_es$sCQ3uM^uM_$|^GpY>U zvqez8uSlFJqL8zYefiGSB3Chw<;6g=R1y>Mx(X_^G>98W;TZ$<{Nlmr(4$_#C?=zhS-WqT@j7AV2_9#2~$j)|zxC)#N4ofqf)RO;kLRpw3MpP5WhUvebHJzLHtJg=$eE2sEj`tEN2{Q(9@V9U_Dcsj+ zkXvCngtwt?Y>Wqk!*d_a+nB9>4hHn)a}=TFzLQQ*Rt5wdOly^37@IG*6R*(N|J>@Z zlI+0`?Fk`NhpDgu+cfNP=9@6QxO9n{1<7ru8LSpSvA|#1#xGh+Hn0y@7+y+m7zddx zmr-AM;--Zbr3wzrh&`26_ksQikhPNmF*MRosqlhd(8*}Y^jL_k}gAhohUuYP+5Z8Mc2R!mH-KLE~<>$3ONd7crFJ82b= zv?K@!W;V8a#g#~5k@37(RM38dND{RaC6|;kgKrTJ<%Pt1Y<@SBrZR3#wX8;^Mok8! zo2?KOG$jtqc!SnKclhD+k!C56@0y$_YKALS1Y!K?#w!8be8+g3xwgYotT*xz8`GP| zyFvzqDc=)LeURl{%p54hLn**s(I#;Q9xaE>fZeb)3`PworLkP9GT9oOXmn}YMcXrK z7x1CE_ebNR-2vdpurvC3|A_*O3DF9MI3)y@_6Zj6J+ypwcW1nbR z9rd=tE`io8Z@dlyd#Tp3{Vb=wxO9qm?wX;uq@UJZ^b&JfEvNdPbsJq~Y5Rk=YjQ>U zS?a34zxu^$6O06!pC9^8J9pzIp zKCAsFV72hzH6*Z-h57CmC|r|eag0>;Mh`|+X%S!PjQa(Ob}~yfE8vdYSg;D5qUyoA zJz@8JkyHE#4yh~SL5=i|BZ~sS!JdocN({S+&r$f{F33I8Fj&&fCItHaYG;%KzMcvPW)02yaL-6;1&Fm zjWA%wtwNj+mTqVPX-T%V!#?0|u<}Wd+26h>fwT*rSMM13i_pJDnq( zlN^`ceXde=7W{gyQ{UHYN}EDul3U88KjIfUdCq0LwaMdj5r=m`>}3d-dW_E%{K)~o zIA+?KZVm!`P!=aX9dFt_yCw6h$B#Vd!3ArtR`iNEY%|w*8i@IGv-ZxU!^XxpgY36=Hd9+BoQIg0=TIKRxli)h zu=X)^%hFgQ$y@vwP!r7bBj&Jtr#Tj3ap?f5VlyHxXZfv5J}<)U`^i2#tS9j?3?|d- zbCtEq3@$cyFSgn|nbu~_q#fIzX~Abp0FA1c&wu<2US)>Yh*f_$mR@OS?uAWQ-vO+G zYs{fGxmj}^?(jRg}PU}T59V73l!f?wy0catl z-t*%FoukN3@)qzCuAB{+>gCztBuoHc0R*a{6`oT z!{vNbdBepF(tg+s{a&rN#`aM2YzWrIJHapR5MQ1%Y}a{2j^4?0oGi~XsWr!M)I4tM zAY&u7D$5g-h-V-Ect4zPrn^`2r=d@)zsu8XABEzBd_O#2$GbaT^bbFL@&FnS%Yod& z1$PXPf`KA7%kvgE%%_PE7;n0ReIt*Ue~fe906aj$zgj0=j^4`uQJj4p8iqOL+LG

    BB&^i}c1~8} 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
    )725zftMq>!`oZ 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 -HxN6Q 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�vabfO*6Ehx@^zaG})W;QJFuaf{cKZ&K&lEy*0!BYh`UM1@5OISN zkVF<+dM51REL)W?gqd*6!B~}gmuk+h{}O#K z-dJsBj@H`l@n<=Ht3799G2pp}t>XGY0GJz74Z8-8ecE;0piqe3?lsw3x&{Hv^}qBI zNSW;Vm&Ckr%4u&sjdM_XtMBVZsTs{fkz7(J>lnc@?;emeUt^G^e;pXOv!aMfIgI5?dCKMhtP4KmKUh_CPtc=A}Q3f-nHEwYU51gBLW- zis{vY$NxM79gBOj_MwK@yH0$-@G>t9F{(rR;-$7WT#LL*r@Q`hJ6j~?UidU7fbV2| zcET(G+5yX+ll}a>2R7F50$ZzrJQVXa5FqlS>AUPI-uACe`w`X9$BYOL9!2T?HU?Wo zSPr(sF^Yr)v7;Cp)sFLwmo! z$kZ%%`9MpgW~Pr;uwNI`9E(a76iHg2S2uo~6^44!4{DU0N_sNfU9WhoIyA{BwHI3} zKCFduMo|H9F=Vos+iJb{z*1=NBn<^?zd6Q8#;>wjcGyz*F+z^$`jL+P_ONRht93&C z8^sg}X`yne;UO7s61||e!4zB??MbWr&de*_3`225Ee>wO&`0}~u{b1MQF_Q_8(>Q; zE+FOT#OA~@E~5=4`VpyY#4IM0t8f{7!7sz3m!;Wc73y#jR-MUO1Kohrk$j^A$iMIkYzhg2c}0yev)W!i(|PcYdb;W zPr?y|Ko&Fq#WbAN&^N$;luFBDpH-xZy!Pr2|BB?_`c5F2x#K1kD5!t*LB{z9Ta+#p z1J&;nmoTyVUE-`sNE(XsGI$%k_QXOL6M;ZMHd-=R#AjKKwU0;)b$!V5-JvQjAY=5# z)?N!h(c9Vg09@rDJ|g%B`%;|jsBg_ho;SLaC#FhM@lbrLQDH>(UW?lVVOW4h_ql!p zp3qV($gaIvgJKZ$?{(nLR1F+OPue=2sSaJ9|Ff(3+>lAJe2vLqbs2D<2nvm-9jLnw zoe9245>t-c8q@OXe#&HABu5-#D2A6#2+l=<3MpN0#{eS4w&+9#_14%_4y1x zs1dM&Y-&(`P4!=>eA0Zh z${~B~ZC7w3ykDxtD!nEDE<_BK>jpG>KJDv!T~S>fdF#AABYqxyB3rAP%V>tc7GMj$ zd~f?$@VxX%gtguv@}_`r((BNd4TBKjrUut8a>*l*VW{kg+wh9^fqrbjsf}J!&=JY6 ziITp!-B{d!bhOCR9^=A^5TGzPRNK;F(t)By!w^AvL}^!f57(@M>v-Sl#dW}jT2ra0 zLUCn^Zcs3RgD{U0tSr#_VoRQ2;k)D-UC52}y*w=R$mqvT}0!kV=(JDk6DGG_kZW znU>&KRu>twRiVA!boe-(T||ruI?fQ3_csrmW-PyYNid-E4~kf#qb|7JagQ4*@+9DTmDD)L#tJB6WA2=doSZGx3I)`bTs2hA><9chu9wuyn|RpdYAwu zmKS^40LQ&KNIFyh5hjn$-~o1{C4y^6ygH#Mn?sz9EB^r){l5Jh%#J#Tt z`F4M?Y08JEKqmRpho{A*d7;j`$l^;tFtNxUVvF+tF`t$=K@bKr)l0LBw*qy+9@%LN z0ZHN;%#7fT2%K}w^f-f0wTw4Zxg5~k_0ELo-xq2;$;ujG?dw z+S1!@K9H7);BhB+Bw5+MGTNiBo7wLM`Q%!O+!4AuSlzuORQrCnIDTi9@oyd$Tsx#}u3h!6Usbnh;0%KNRKQ3Y3BD(Mi zuIcf)rL)UfM87a|8Cj2zA)d4&%KL{;FG)l1c%YXsaH@-c@esHk5bLVb3u{D$q;-D8 zU}qBo%O6G%p}7?3&T;~Q)}$>Q^*oJ&VuS3(yj}D9u=9cBPiGxP3G@rd*Plzt((S%K zvz~99W>rv?y{l6%;%YCvMGABfuq6yts3;#ta|-#72EAbS#yX)ExbD%^l#5;f+!Bz; zV{5`s-RGWrq~~v2;e^jB>;q?y&SExNrs6s@22(N?Nhb|27GKrc9G*`~>?PxgpNFRF+6z~%nkD%3 z7G-xDgj`-K2|v|Ev);q`Hph6?o(N2Qo{<}Z#)U(V`(ir;ud2(@FG08xR`yCJhfaj( zEZ+6BYDM44lSc!=yX8|e!12$5(-scoImqzHV_5yKZ-%E2-x~z zUoSq^2GIr0A0l~GguO79B_u_8PIMw%?l8=QrseeGx`0GfESF=K?sUmHH; zSgmOWFzmh~-^ZyY(f{0^=G|VN#WL&>PbQyu`qVy9BOT-#8NJ-Et?Ng4A2cwM|Hbum zmM|_+ZjKP!A{|}?v6S|`saz`FyGI@7D*S>{(qqZgH^qop0`hI9xkyw9!5wqHkbJ$V zL{7eI*KYE@N85-Hv)7qVVj(pg!e2I`b!cgBnBCoTL~)4|qM>N=QBy>tS4~3{>kt5} z&}`X?!HMHZwM*K3+&t+S;$5%nZAqUVe89}bwAK%+LHHvsR(ji{*uj^Qe2jQaF_rCG zRZh$mfrPL?p{jo`?lsyY7$=K*LHRDlNys6u9D#RHLDsQL4I7Z${*76#XsSb^)SM_3xb?pF3cB9L zJ_go(znU%4EZy)eMAyNZ8@zM&QV^gOO>g9c8_cv%d%7sQvcn(vK;j0%?r6W`7+Uz3 zPF`0l+v9|k+@v&JYkbu`BO32l_dhAv@F{9aeV9x!?5@Fp{w`IWv@m)7Bw^JmuYgJ9 zYj{ctPFD4rQ|((C0Nrzj*fWHoU3eJ8{2s5Ahxpnv&kSpZcz$IWaPRze4vt_(imJ6zjsPzTD3S>G+~CfhjfFne(XS+sB?QR;CW>HuMHa{gmVsP; z9_g2QIKUbDm!>x|$(m_71|(uDkj=AP0EHDW6gg)3kn>D{_a2NrlStCwM0RZ1+}tBY zuPeF1a-jwg5o~~0=$MYd*c<0Enrp&30Dm_3V5C}WH^yB6FBSkGk~TR=1O=H!Gv}t! z0lP7Izza~TPwMu!PGQG~eo3lZ+8#c6gNJJB(YH$zQZ>G^b^xY3gq&Sh5i$ByVJ_ct z)4a}#p3hae$(OA-#|-zeA409r z@g(aP=yrxK5pY)hjN;q#^acJ%_&<9%ljj0TsQmDcwJ{gue-b#!`XmNnJ&$1g;lvye z%~BV=n4k}U07(=eC=rpEZY3%RipUl*%lRHwG_A^alVWlaS6XgT?D_l0CC4&m zb*)Qj`C4`Cpid&;G>7u0X&XAL+8RHUS1+21o=VG%l%@f zpIIbzU!jc;r9CCPz^xD4@rfKLP(>LuKB=8x+F#LDe=9rJ-iV1Vp@$~ok7z{v;31po zgCfp7L76^H*2`joCJjPm#vE&UzDG`GQJu3%(s91CU=I?1?jn0BKQ)=PpjKHhJz%{j zZGJT}aU)2|m%_e<{6e_mB+sw}fEkSBIfE}W2PF~BEa#KnZ8l<7a&1kRmRJwDZbbHw zODL?5NiSf&E3t{jn^2Fk6rBvfE#o8}$1cbWH!mvgWL>ELY zkCyznQ%PKu~wcDX4Y&7tT7?T*LWNq|4M9|~&EK(4Nd zHy_0ma|536HVZ0(jAVAjXgzPJtnusxT;wDrw}_bsm?jY_D?Rb2EIJg^zuh-=5(l7hfxd>R!JR9taxUh7IL--3Vg?gLuhSPhX{g&X&*rl!GOKL`%nDf_v9Ri0~v-~CB^mz4BnR~KS($1 z=t@G|l(FZ1nO5bnOgr~{y12h39_Znqpzf^hs(2GY>u*S6W4oV#_mY$(1y$2|aV{iZ zCZXnx6_KwYCF0_Otrs#1qz@K{-28#ZwdKkQV+q`(*)g%0Tplop_qOnK$n*ggiQHh8 zG3wqgp2kDmf!qfH36$L>=a}W!jgPjcmET4fgBX7)q}U zIkJ*u%AXk;3Ov_J5_fhT@TA<27bW}}`aw{MmPO3M5W=Cu?4aJ9ihDdlP^W#9RT^0hpG- zhoc9bn}3P;C<2iMs_R*2k%mfD4>V8`h_n!o?Ho}Zu_a^y2Va{qZjrg;sLTAUk^B}7 zzGBhZWWdRxAO~#}%_~MSI66(98of&c1n%b^vkBoPm6vCV5vWoL>(&KxA-* zD&Z)UNDaV+41zfUOSU*6sx2#a?s{Y?Nk}?HLwu8_y;=PW^u3EMmwm13jQi6r$YMS@ zN|c%pR}aaQf^Ya3Gt5kxA`ZGr`ahY%TjocxAt_}>yx{bDs zRDQLIl;Tmpvz$kp=mkz!2O{w#9sjS7oPK> zbQn9q>6-;^?OO;e)wd*enh}58*mI|+T455B*};hz6G>lB;$2o9XH*USeFr1q!Tbd7 zU-sU9xG%|@$(Y8j9CE(map-z*SVI3{pbcop*MhXH?}Q>Mj=BCyzXLC-alTK9x4@q= z&7b8jc~~gED9HufLo-)q1{p(~&Ued1_V0S}jb6T69$1<`oN^>C8heK0#WP14!8(fC zw`1E2}md@u{%xPKjeD!hz(0GXo zjvq@4=D>hqNj45`69oE(E+@g|r2wrh_)IWe+fHa3=S^VoeiSEOP8i+ua4FY)S_rzM znfOQaiI@W6i5aX>#BU82xfaXJ>a3OEiv%Z|_w06ITx!{al+Igc*r>S{tdh?FkpXS9s`!#vG%w*1Du2>79~5MP4#VQ)bv6@YN+qTUe z+eXK>opjK#ZF9bSWbZstdW{h3Y`*;f{e-NcPjo3X-vj6{1@QADtp4d&QYJll!M~C&$i<^>w6!xX0)LN} zRK|DGetM@OfZ+?cM+{)m(DcI+=qGs5cjYF8A5$tSydbS@1g`CS0LoHR5SX+a$oReySoLu*>FMr5Xjg#!NDRN!7kp+akcc6YsEpEut{UMsdw`Or1Yya zB;9{kUTT9*Xt4L=AVH$N(31P|2T~3l7;(6PzeGACXfbc%cKhX6rIBN-*5K;HaqjU+ zm;(kNLE^y#?JVTaE_F~{@|O0_hW@ihIh5JWAYn|RJ+Ww=G!Rnz8L@!DumkmH=U#-0 zl{Ukn2isWHZ|r{P8_du+03_%>s$lF#^z0fIjIMVxin0Ta`1w${+x~1UNyPY)+izU% ze@`My*cwxSx3Wt(?1+nG0a(a4Fth&0MYzdXv4>}`8XYJLpuQqFCd-;j0jS_ZSqkxt zDCb^VLmGed(tkeL_?Z>EQoCv;z)C_v!Aq`4i9$hl_moY z!`}2$?qQiHMtI|@zfro;w;%Un^}0z#!vmhY-9QH;66g97ibSs6l6a@+Qvn7B7UJ>~ zn1K1G^1oDvJo<0C#Mu;3v@=)t^gIf&M1%JkZ~b9-1;L~j;A@cA?>`lec&NMVi{i^q z8`xjxR)NsT>0CpY9ZYcTQ0U)Xs35Y@qHQ0)GLI*-E4}PB&N9R8a~(Zso1Zo_oE$CL zj!&1?WSm~sX`P;BFK#?Mi)<{L!k(~8{bB3-iB50He7SJmm324{%QWhDh`S19n_wDg zB3Svu37nwg?soB>uXV>}3h;3FPbqbhySEo$D9w~!+{B@dHc`#&s537NcvoG~G=I&$ ziJmiE{(iTP0>q(Zz0xHbc4I{k-vps?OaC@$N+Iswx2QAJ1C82r_ghMHa-8dqw7U@M zGv!aVnB%!?xbP99HAuD|zkz|>i3RR?6FNk96VJ@{wwA?nPzcor_tKfw{XYKvMqF zI9$a@3++H7)4C7C(+U7V(AdVoyN^}Zxi)-S#`Aoi7LbSGK^aZ`p}~BEt(ekETy(d$ zx#Tr_aFXYA)Oi}WK5SBYJi<#{Dwr~=wT z&qZXFZ%C_c2p;mT!MU z`|WWpeQ;&qI{bh~S){Al-I{39dPY|Y?o^lT8A6bC>tv*6pYOgEA{4MIRUcq}*KEh^ zVgi?(iwQ3GzN&FZ^eFy*{9A;|m9RLHPH<$d&B#!=Xa2+^O3bQyrWU|~d_nB`VvmZ| zcQv_m;ulE(m$ihtx49%wsg6IQ{M&3fasD?4gV0zqE`K3af3VWQB<^g_Sl55hyvo!+ z7MH|d0wnooc*}bOc^#kx{>Y_3CvVC=)4_TQIkw;6N`>tfUe*&{#OACCZxToMwuJ?&kF;G zYK->Id_yrG8W~9d(|STPsJsUjmf?d+2iIQ>Er6L{z6TP}-^ZrE@Yedyy(rZh4%ZQl zJE1Bx?gK=aMSZXr59Lt6Iq8xdpr!uoEAqlc4vCTubNc=r7BS`DXe zeMEup*}gJd)8h2SLv9-`#&$cWMgs9IAwZ}vVJ`WX%JqfMh&rf`nU+&EQ4!HS*p5RB zsu1jb$j^n!YfQZV83=WeAH?O#qQ}a59El^~u=XaQKyytlT{w4zj0)ax`@l5Y%}S4r z!2debswXM(vkSJLqNe8kH|Av3H`g0!b*`pae0k!q)AtU&2>>a!GmX6pP1SIwfG>Ls z3P|)le^LCqD>}6U!GG76PiAz&b08_?#82-2i~D zw?CNZD^37es1Q1PN4!)iFo{fxGbp3NVM7J-pmWiYf|J*eZhC=Ci+4%c-E)Qzd1c$Z z>2d52eul_l0Y6r0VmdUQ8NQr93rahoM2Of^97tK-v1MBmrUlQ%GBkYy1t}CjkKa^Gmp{YH zAbZT`q-3J#t>hXTGygD0stAExNR;UCQraLH%w&A#b8)6VuK~)^c)8FwoZo#9VEqLqbeACMV`M0qHxZ%LQ}JBPSEbux2M>4@Nsd_IG&K>w)| z6Laci{$&$e3V$J@nd-|7k8P3r^|?jQdSWd1&iD|k?iMl+%A+LCI$H!kXJhS6tKX@h z_?In2O7sAs1|e7SJk){CVeTRO>}-C}4XCdmL7d-k4)t>hZ9U}VABoX0-3e6p zmH2F582wBh%U++0Ueg5RmHQl)Rrrq(!5y_|7cvN=Z^<0QcL+_o`9})|f~Hds&YPax z=n@Vi^wH&B$-|}H_1V4Hh;zsBd?|V6GW>gs@-Q8}P40!t<67xCv%5+dstn&cEh}#_ zh8EITcW=q`()2{_?Nwp0vEuPS#|zIDeG;A~$(D`%Y&1_4>ZJYR8I|X#g_kf8*e1b# zhxJOujst0t&&J_u`=BB(KJ>6-oK&ZCxq$5DszK%8WC8JTpe)O=`=#E5oSqUH<%kWG zQ|;XgHmI6kNy&_PkfV|DBBY!#=85~i!z(( zs^BaMtP*dwjPyJ9(;T|SLS;PGQs|U)>rcz(aDb`zD<;f)O32fMNuN70S&+UM-1CD& zxKpjz3m@3T2gKh)_)#@>ed20~XP3dpL_Xg->7joJ*MQLXmC)lA1_}PjKtT794ZrrGLcaoZa2bN=CrJ=L^dp@I96&X2z}@AnVEzd88AZ$e zYWf%{wm1J0G+pjKat`5XO#aGXha;qIRyk(z+2fu?53~W%%x-kO^i>XNr+}2`iJJvs zAb0-ABShOVMHfniy*$O1EpU%yan&DSt|Ebe{0@c}>72@N2UAugY_@Aw8mJOSjElWR z0?PUKBZscLpqx*@!10wHR{QvU`DQXe5MIP|<52@lHhI9BUkNs#; zt`Fb>zgs3H9~v_I8Gym+5BuBLq{W4W7lz8BH|X%lRXfWQBAN`J?DFjF4 zR6tQ}^3XEd6DmKiud!gpP2n&)VAql_jA+fGP_+HP;5E~!RYz27zW|s&7oKvi0C?=s zNCXR5UAst-&5v(kzi0C(>WFS@Oq_QSp&^MTX^?rw5bzN8NoLz zvmR~2WVJC|FV}AiI#pvcdId?Ppb4X+s@WIv;1c0jjL1Vy3W}!3lvDLfZ6~MZy}NJ6 z{{lw{ofvq~brWLZdEN@kun@w&QDw1=NznyoOGm0>VBxGVx?yyq(4x3%X-6y*SAPKu zh98YJ3K&i$HoRI4^=hK0tc|bsZUi?c8S1Mf8;VQ7ANa{p{)L9Qv z>hzq8-Py*_UE-78?G0Nh7hs9Y%FbgXm{!dui=ROfR~Cw3wtSpLPudw(3btXN@T5nz z_Ekv^|CIo7n|P$H8R95m+(+Sz|Fwwz~>7Ui!^_|9pK~$Kqd@5k`s;kg^)w3lG=ub(h-}k-5YlMd$=DBT2 zgIH_$aEDh=;Kn?ikAN)p6utK0>>ch#nuoUgxg zb0lH3l!L`~FQL@N9f2ZF&>rO&iZ4RpQ(AxbD30DHhCYm85%~HWh1da!EJrjWbW)-p z%>Ye0rg27W@LSSG>lhS^Xjgh_m394rOah%}3iD(RE8%TseD3fA23)Nxp4~9 z-|>iziwGm8j#oLbMpg0pt`-{_>+F8r!p=IVL${pcE`a@n8zv*FRH6<^o8ObmRNI6f zw~#MI*(YNH|1pOhJE_opGeEJ?uP`kek@4h(jiRcR7?BcyP5T5?s`R&LBKVDj2{HK9 z>=NP)hs|^L0IKpV3XfwyRITnh_4G625fU_9s0?2J(scc9zY~eC>y=Wd6le*5G{rMR zqoA_pAj`Q?Cp?Xk2mmGU6{3glWA|7yvR^aD2_ih+qzUg`dMPz( z6b)o3waxAa7OunCU|Hzs5L=vPE~Y!e6Vg70M=-a%DFC8w*RqHshMmvp?Yr|E+@4DN zCnSng&e7uwyf=|pB#7Vphiam~){0?m)>Ql)*QOU}C+>tfh>;G2;zhIx`C@)6`-_ej z+j@mQHnv)ITf?IXq;>5Rjyt! z8@84OH0I#BAqc%wwtAPL6}_~%SR}j`-x}1vwkDEu{~XOXL;A4c08K!$zd20KW{(Hk ztuaOUjWi!>W~uZy8X5|eYu)k}neyr)5^WDxiZZzGw^pZ(B`}r^0-s47;bAbRN!$y! z2V>xSwLSNJI2XK)FbNGnfzr<;2eS(hzTA-*p}E5h^!OeW%Fj-$XA<S*;>k0#q_cdnfS6+Dkh&DA1 ztXnGw{#xoqplbl2w%Ot~+vl<%A4y?+b7@hfcFxp1cOZPei`)JL%zu92BcofWk{_s0 z1?z5hK4bzm^I&9_3OyO`YbNjwR{PIdNM=-Hd#UIbt6I#MiQv= zgpXIrAn)JOF=}RstLoGK6Z75hHy8P+UQp=7KE13T>&DZNUJyQP^YCATPy-!-LZ9Zw z%grFp3#F}Me$*Uq1PG3tiU!e5D0Y8!LsF;>1~E?(`ZK+e1KDd2M@OI}3(}Le5nw<; zOi$@Zen3G$m@WPXDbf4?q@+ghf0GiV|3^v`9c<0yj9gs)Z(0)c-?Rjj`G3%op8uvL z^<(tNhC19-(n3_gJoKNjVs*0VkhR=;25gdVQ_RB8-Vl`_MZfYx7<4j0iBoDeOiKhi z1UCfM(1le-sy&MU%V)baP>l>Gq$MiOdWyd zYv7WsgwavNj;3T)iUquhldt|LW(9aP9t5rccz%mRKgW|PG*kxYJgVn<18E)^O(Oq7 z$s-BKPv90Bx{SKpp3>V(Mu zs+t$H!i&-KS`euKPdv5oW#n?%^F$acxGb37tT^-i9+r2K$qA zolQYT9>zrcD#((z`el~Wpw3F$Mb9R^zUv2P5x(Us2Id zv`eQ8n2?RO`gp+mpzj(TjeZ8C`-7=e?`Huv&pCdE0D7>b&_&f zshf+VKhp_LksDYRn-h=&fB%Q$xY%mMmV37U#yW?RmUPmQNT%LQ*A)!`vt&_4K^5yc1_IWN; zd?z`w##ON2`+RXAcU8`Z>;}2LziTVoo*LZLVXb~v4$s@EkUvQ%fFGn19f?IibpWDB zwgkoOwJ(7WEE}D@tK+a?O)>p)3Cg*%&~0+!ePFH+ybm-#irgqEK4C$H_uk zgG^;+j0xk0+6ev}N+8}73>Q3aslTeMZN4`o;)BPxuZ9|e1%L~^GfCRk(lsjsH$kfe4$W3oE)uy+&J#@p?L*&o2$WD2Z{cf>NLZ!EPL&W5|a zp8BoNmkTyZ)4ovt6?rYxiT)v8R7eSM`>O*)IRB^GYJqI^sKDKq=L>y~Ma5tc9%67~ z*7K!}bW<$;=Sm9)9{{l!XD{Ts+hQtt$D_XHzV#=Px{q^$YYGasGnsh@Nb~f@vQ6u1 z2sSO(xqEB2%>4$dNcwV~?PWsA?>h`29b+;VZ+7BN0_BkEw}H!+KjV_-;A%W?%waL+ z_yk=a@aEfej=YFL_P&!ckIZvD85FN!Jd)ZB{-l-w8N)N~w~F!)XjVIS;=d$%EFHZK z-Yd+h5MJuP7r;AsHlk_mO?SIBYCv^_t>NAo=6EodSv)6RBJ>e7Uhnc;psU?Xf4OsF z3Bi_WT2F6Z5%RDLP(A<9YS_>RiJ~QxCS5Hjr}8yc8m;#u;YBRo3&?wJjltTg;_ULn z$&k$dW8|b)_me2N`-!|T}&yd-Kq0n!g%Segg*W0-a82ZnaCPLrkR>@l+ z@inTY5^ve~49D4_UwBO~K!oi!97(V(Zc+%>E8*#GvW_zp!q5$-rP6_q^mVA)^{Rwo z&;@&bpTy8giN2Zt?HnAz3}D^U2Tgu9+$67m6deUGt|U(vg5F$R^K98~Xw+HW6yzX9 z_TDRs4J@hAYgfM~-sQa%p2`OriBy4~DRWlS=eL=|`plNqzW9(FJ&c01Cl_YcH-JBe zGtpZ@RGau;21O(Yo`30fu>`nHyHbzg5e@+(1z5UW*olVyi$|w_?YEsYgHgTOSCmB9 z6K^t)=QEhpucYSku;C%(T8PQ{pj+fV2Co-!k2-?A&=#FkqRDf>(q(N!R6H@Dmb`3on75XOUf{C}%hFLD z_7|5$`&+`^9g&N)8;~aZ{I(RvI!jqM1&jZdI;Gum7Y*}4LEbJO)8IcU?l5o^?{*08 z=eXd$L+U|mh0UexErTCUiDBUl#V>tfRxX_ec?riuh0pTSb?UvPTgNM)`B8$;+z0^| zeR-o5!lOQ`w3E2>TU1>wbDJN4M@ZtEk7;)RJMCx5M2LK9>hco9)pi5NOG{|~r*<&C z=x>eqTSr-DF_+3fPyS&d9S5Gpp-B5c+4k~sUJ|)4Ozc{Ik2!A|#)@NiZ(kSfW!VFI zxKq<>{wc#QVh+ynu=Y5yJ7V|WcGvRWh@bqk7rOJ*WEFoZ4as>6IRbzf`H>9T@tcA^ z^c@4qg2=d{5iz5^8ooc7+bkXkfOB)hnWV$(s9UwFH@#Ed%)(^=OEOSPe2n%K^?$A4 ze_+1Mcfb6S{T{3tz5aRWqRk;DPM|< zQ-4$JSv{Q(up;O*ZbP8kj$%OE6pn=KJ4mg~anau}(e05p1Wr@>*!G>q+>4;^IcfY` zASyDlnNn;TP}n-O+^-pn2-CVn#I%{47Q18B(sTf>sNqpD9#A{hSxeGYbq*cYUu3X) z6OI6Wx`xi}VtDhPBZ4@LtPj=MPrq@&L;?tckks6r$ThOB!LdgWMAas5*1#UY!k>We zgl{l78F^Zsx=_T!vwTLBw%g3%0eib2#kg>K5tua|iZjky>p~WRFej!edc6HOK`-Za$@3|p@MOngd*BW#;T zCxiN)3>f^hZZ@=EKDv8~LJOOJ_5 zV7gMUGJ4^l9*>)B}L_=WuQZWxL_-I;pkkG#~V9v{hjC>ZP(#G3GU1mtE#3qIz%E6gGp1 ztT(LAZo=fu`Gam%`OaON*njU3e!D*z z^=Qn#VrWb){@PCCm?VIbMH+Y2fsE-x1YsvR4IoIM5PIyBX>vy>&K#Aw5{@8*n>DGX(lN~n$B&=ED&y0-38^d{zDbw^IaX*a*zR1`R zXtuhY z7zxX7lf}{HAcuj?m~Xy{%~|DF>$k=M?$_xYovun z-&vUm3BIBS#4j44^xu(cZqq@M~p9tmSt(Y}1ux`C-0bi~g`8qUMMa3+1fR10?c}ml8@q zD2%W`3X0mpF8+qBS~v%)!1@m(8N*3|59Cmw0)*srJR6UXEOWTWnX~tAx~h6O;eYCe zBtIGqe_~VAhiFp5Yzga%@|y=;l`$dDDG(Wmz!9EmB^B(+r_LBm(({Ko&*d6?+p`m4 zA{2KA%Gb1uTXr)l6X1)j+3{7_6_O7^K$P#aGZK60(PT0a$C&8;fklUa#(RZ8Mg9|7 ztN{RyJb8(59-wh4KAWTK%iIupX4X%Rr;~483RHNWl;?9Vjq^f7C11RaG>NXk-lxnq z3=*ABRG?G~of;3QKABsVA z$Tw`N3*V&LKGG?j=ZeAq(X(IW>t^bNu3YU~XZ9gfz(5*h zKWvHWz&p33ZauZ=x!wiq(hi=+n5vyF!C>B?{R0NOBz&g_K9?x0?2Is+Bn5lT(pF7|(1_bN(;6M`ez{b-a zwIVRhR@I2(Q-_?WcaJpW4;$U#@{8+ABsr56(!Iks8s=TBo<>Q@3TUQI9{782irnef zASSkW@agQyhKeh)!^#Q>d4sZf8GNaHGlIYC?1nQ{@4<5OXW9kT+;Y{v?^I1 zSd7SL9_h~CQis9k1tFK^Z_0e45!P8YBc<^~kz5REo%&9RF9HAbyy13`oKkAGD&QR- zGCA@7>}$OW`a^AAdX3DWTI(UTJq*EJ`WhM9u1jPlE!}N(D%oxxoGyRPbAohDFkE9s z^K~QGoYL@3J2G(f^$n`f%vGQQ0|YF&k!W?;;WiPF!2eEWj*s%v6`foj4j<&YcDq;J z?n;M9?(fH_dz^_9gWP0ue#%72v+0%W>pSb;aWO`+B5%gp9e}3k2ZL=%PeujsLYzC; z;CHE{8FSe|RB}X$G%;DRt{Cp@X$|Y~Aq&uUg(Q~zWJCJrv_iL7LAN)95-D}vCymiX zS>&lN1Q8A7?AH_~>a3uypW)>@XbxPm8$N$W#wFq{$k8w~l@90&H#+a?Q2|O-+q2g~ z3jlPW1hFt-S|n+Cbwi@3DIlVT@iYVHExI!JS22?}Fknw3&7DZVFppK@iw+FP6u=Ss zT~r!wAL8Z6#iI6VTX==v0vN-lvcd_LKpR&ClXC(_lCaLAaJq@6RL7Zm(wYcPPos#u zSG{25?NTi7H_>U4fiR~#DSs|fl=>UJB};-$Z<7xq*RZk?_^oVTX`P_w8ZFD9=f7*A z&dWFgdkTn&F3`l8F$4$$px6R`*zz7zFZ-nskx{}@a9{+io|7>_Dvx+} znNH#Q>mqfR4*Z1^k5y9#r{&7Pbd5Xs#%M_5-~zJ>dk@T5!JHb%KaKvJZ#B-AP%9-2H3wT=r9jPlaM&_EctFLA6D^?ikBlSS{OPS0~k> zO3(@dd#*HEd_L0lvNI($=dg~xUa>KfW4j@PCRvJ2X`bT?+By|K15pu(WEY{}8RU0K z+~Qv@laV&Pr=C)q3s_+;pG3{P48O`oxXu{6QE4#U!;#|5kwo!7X_rO;6fo2cRd?j< zl5=7CtbQ&m@RdAL=t~cIr*IyHF5le}pM?zMzK!71(250}es-+4#ie*iYTzqjsRSQ| z1r6{98Hy}h(o`wY_nA^Qq5kNSiC0u0%NLngEI`0c00tpoplCVnVcgf6c~E5>`7qK! zDj>y7<9U8KIb7xZp16a+H#DQLnG?xHrlQb5xYq|Yn~`5QMiv?jcKq{n*C@H$)L1pSssBut!eAXTU#cr|0h?5t{`uJgvU_Ueul-O4t_Cj~- ziBgi$Ak*IpGU6c$d0Mc8N6T%(ipV@a3YB2IxGlkb?S`HEmL+T023rfVp;p=FEot?i z=5RurL2jzA5p*Uu)AYYlyWv|t?@cdO=v1d)D8B{S{qrjph`dzhjEElDEPqj8A#T(d zH6HH`qFI-4+u8+wiM~>AC;dY@fj0FFV>UJ4wO_1orlVY)&5z%RmF8|uD1~IrPocLF zUpxGQd(e@{DPK-pqKbBu_t#5f+1jL>n37mi@+WgIt7Dwh6;#Z~pE2)TMQZwyKvKP) zxbi?Vx!k&}n-W*J8q#4CV%I|et$Pw;Ga|a^L~N4McP0HcF0eiNi0$ctE^BU1%K0sm zTY{hb>{(pg%hNUm)Zo(P!%X53zQ1z|L6plD4a55kr6JxG3lP2KBVQe)n#PBqKF@=r z{1R@geQibaI6$!W3B59(a!vcKoh0p{^xKCB`q#Hl`>s#m=PL^7v<$uAKJ;@@o@9y( zTEN;SS=O{SiZ;5=ILBiR#Kr4&@iUKCb8Co1{>GTrsY#FpKHSPRp5c0YNr>#%hlVSE z*}s4=wP$db;M~EQWSn2Cfi_>(Z*-`O?rE##KW>~K03JDpZbi`{JJ|aq#~*+#{_S?j zp51|D3qG{jauA)}CvC}uT!K<}$7?zMv$<`!66P*^dmWh^)NAi(d&FJIh}0+PwRY74 zOY&gr*rqyCAjeJ2tEA#T!iAOuQr^~Fgk6nYEw^9Fp#YPLSq4hAWo~bLZwwSIyY% zW|8uaiw9--c4qJED_59-aVFW9!@cBjKqAMBH-+d&-D=jCnaA%M$g$|PLBt}3Bd>36 zmBW&}5(9ULjydl0-cY^xhrkS6{t(SB)Q%NB3ibI_mVgvrYly#>0&1Kkh=oVwCH~+8A?>F<9jWCt z_LGW%7y3rK%&=yxBj1+B43K`{k~u;6CwciDAlbVei0%%aZ8EQs$6S9DvMyE6m|=&% z;8TOhVlX_YYnwu28gB)1>(ajaWe5l*q&(;>6pv|_v4$29b#|X6`NNFH_~C@8R{$6j z84c>@++~eaX;ZJrvME@2#=~UcEk*`z2-%|&@ih!{T}txV%$q(@YZ>x-ESv_UX1tdX zvi4p4d#e;O$-j7iL{5L?HV7yD2M7;NZ~}Quw?gj4e0Uew8Ej6h7wu&8xTuwkx1XaG zY=oQCo=*u8oz$ca=Z%BC62SRs$1FPfMPAjA4YAOghF+;NaUQ#__%Iu^X1szZo5K-{ z=HehCeV~_oxTdG<&6&c1>VFxsA~cN5Js)G&hxVJD7!zb?H*%+!3+fZ2zsLgBEwypH zDE=dIY+2vPq-`&Lk{w!6)g$H8o2XZWJ+@#yNb!Q<;_@@IZ4tIOoPP{FNI~r!4b8W860v(F&PMBV)hU7yW*L5%}|!{gvNfR{jgiY0L#VA;-8?1QFzB4?1zj zHTxjV_tDXaUr!^gf8Fd@$W5`TnWz}_MbOIlm?A(^zYP9DjTG67v@yu9P_$8oLf(l- zclrla*tr$-_jbm}3=Q$#MRo>|9^>V`i|O1Z?b-jtrOcf-z7qZnCS&L{-Ifl+@Rb}a zw@t9?K|C(^32{VK6IwKKx}sgoOthShgH%?v?TmUw3^l?(2?DtdL|R5C%lR)lq2Lu2 zafxyLbMh*QNM{Immw$8wst+UrXEPD=Vm<#`ecE8wn5Y4fYT&OgOzkIePW(eLxg=uB~8!5|)}bUzU8 z+5CU3eNv%O#jp#nqcouLqVWE~Jp&evo|nw2MR}HoBY%r=x0~Htb(n{d`|dt8q1A%k zMLFsvNSj9r!!<5j$&3l%+df$N(_RC`K-wQ zVn3?W19WY}vGsA-B`q(Ze8HB%N+3KOH&Q-?NDEmw^}VQZQ*#5Y z+UqFLYeEF`yAzkt;$@DUu#y^1d*mg5xDL6M;!HN^MdE5>Oe^#|GdEpE5xYkWgKj|9 zF0`fLcn^((H-2GESbXlUJI$f9SXvlzVoj7_J}MxD z42DKLDbi;m2Eb79@J8061f2qgJI=lGF7-7=>Oa`odouxjWPy3_k}&W*Bj;;2FeJ|b zovHs$5U0bEIQZaFaC#x49B0Z!ub>^TxNs|P9_HUOM9}RD*>pm-qY^7Qf|w3u*zM`*5YO^kDyV+G|7f`in9>Ag$O znK%>%yGCrU_$~fD-~Qt+5Fy$Mdy}(S8yin3l>VtM7jd&M)+TDhblMMRnYS-J*=1_@ zSUN>Uh()oR6y|hZSuyry9XV`dkAJuMyTQ*yWZp)WCSR&*F1y}VcXSl#My-j7Mt-mt zk&5J7gz;8t*0?Qc{3$5Fw=VD|G6E%_1C<1~Ihnp*1NrV*hRpk0e5Ck>*XxU^7`hSj z@qCsk7J&%n3K#Zhb2oX|Nkacgnd=t&oUuVE~?~VRt`s;4rK^)R%^Ny*n)viDNKG zq0*|s>=Ml9ms5j+(1JC)44)ne!X5N0>=Hn_-;)wC;fi(RTtrQhHyMW0H&T4=<#oPe z0nTZQiF!1j3)&BR7AWpGJf?4`b?J(z*jMzY3XddU=X$l&-D=Tm90Qk~0CVO?_;^|A z(b)hxEpTRZApT~UmlrG!X=6sU_1H zf`nB!R<828%h`x<+wPWU&^{pCO?aqQ?`zk(?1Zzf<1F4#4+^*YrKaq;`i5X8l+zBa z!;U)ziVEq;&}|7WDOjwi)zzMb@1FNJL#N~TWVa49fWeI3c^b{`!=1K_kj2)G-0)ra%HTQ; z&P3;lDnt%!+DM=laj8PA5MYvhK$8ix!tSTkvLBfX-Ftf^wG6=?biq&dpYfFpSW_x9FWNpgvy#QGy!5Y1Ym+qeEO6G zgX>y(D>C$|A9I^3qv-s#$vpp6bQ{ee*y2=+*&2X;j>e-C{fW)Z(*u{ExJ3Ed?Qrsy zLPMcn^2zz1Y2yj$yR}?({u7LwlOa`RxLMW6I|04fC4~-@5M_OQcB}A#<+osK z2xli^=vf#v4r`M{kOe;o3dWBeUlm?}M{c-H`oAQ{&AOf=3ucZd<=i6s1DfC;)JkWQ zzY>p2(tSHn2~_s z=>dz8DkCsV(-{*ryw{R(eRFSe;ij`Y1M(jy0UOjx&?E6Jq&Ore0=cG}CRD>}aq!`e zBk@HQ#UBULh%0{etJ*Q^5xr~~@tN7Eb zs5)M+I4E99lk*L>xfHoD@e+k9syi1gt#10D9Rp3rqf8xqfy(yr&Ecid*6QMW6RoDP z+td;n(Yi&K#*N(42Ib7^P2^h()L#D72)GlW?b~Vr+uZ5;VU>N-j<|^piS4cXaO%Nl z1(SrWlv0yskoPJX)5`al7Ly;|n0?gE?O0&YL$3FZ@A&9mJ2odry?px3R*qw{M(&Rw z=@L`TR(BBw#?4R|{FqPU9)C0*KWv=S&Meiv3?J$iBFrfz43VcX&(K!MfhaJV!j8f1 ztQA}>;BgKmL#GYZhhKC%uCN;%8@MRm5M5pzQ$-JZeMB zM|>F?^=w=3;#jd;qPDL_GGwhQP;CtJVrTw> zRBhx?>_oxVPv#+ibS9>w=K6)7G%e^`;tv&Oesvx<>zJ?BmJ;GkrEKU>neI1)NU^4s z%256zxUIH;>zxG5`;kQyJ5&_4Rqf`7?1A{BLXZ98O$var{2-t` zTCnRP5mP>hS@s-YXxs@xOWVVkRMnk@yi=H4=b=-&es7QrJKdtc(UhpwNnF0kunFXM zm#n@8I&l_ZO#c^U?-ZPgx2=1>v2EM7ZQFLzv2EM7Z6|Niv2EMvxPwm8-+!%rc73b% zsXC|5xR@8SM$P#=&&{lH@vC`<%FQWsT6FJKlZSVGI~r?4{fTRw$ONkWUOHO(hs9;t zSHI4QgpuysB6^HzoGXn+K|!@% zH4o+QKlg(y;5mqP{PPfShn=QdJeR+^X#CuX@0C2=4&BbJ8GSpXmSN)QcrlS<`-Bgb z!LnX>%1!1?0G9Ro`^5M~PaI>(mI~0x-0OKcc=i&fd~E&v@>G-MSP1@Ul~NLt+06R> zlhXZpefRb^pyWE)l$_5Irhj*Mp{bwa^?sJmq|o5#T9w7sk-h8rRJ+=dY}xxbM~8`> zWMJC?`<;=F#=?j!JmH}IF+WM-rz6zmZ-KreG3@w&%D1&hH$rB*e#WIL%rQd6=oz6F z?mN1LLLYmX=Un8B>{NK}s}_@?8TXse;f&$7haO}GewdUIEOf}<3YoVn^tt|IFgnX# z#l1uzKd+2rW{tvfTVdt94KjQ#fAUHxS{yw%2F(&qp*-4B<9>q+ zZ(FgNw6RqY{H0V_E>sQfK8=l?X6`SYZdb@3nSNFEsK%2+rY}@6f9+I@xLJHG*yNJ^ z5qPN|fDymY_|SD^qJ;O_kkp$07JKX}&D@QyaVp26=rX;BoM`^*##@{_fgYnPNRi1u7agn)|{zR9w> zaRbqAYee+F*5OAaClX!+q^|D9MZ5O2>*tJ7NH>FhgX^U(yU@sO?*+++Rxa13nZY?h z`7da09KfAQ-LzV&Xzf0f+PU?67(RmAg>g+@fsh@N+{?+B*&kKnf8TF=^l>Bh^NP#P z;BoI20~|Ya=S<&s%;#zHyouH%r?kSWy!x>X&pK8q8{8!zFd349h~}}s&|p{XIY5N% zYh&Mgbn@=JFm}$SruU~%-f&E6dK2K;r)3xesuR|!_*4!!s&spQsf@#84xeTkT1fFJ z3#B9S>v7Jwbb`w9>Q#nilAd2=HOI_T1>LlljQ|ns!@^_FoMdnT4bnFYMYeZ=tFLg586wAi;TEQ8b>0YBYI-Z*

    |+b91_JVV?l()cp}?EhsR=HEGPG{&iV(FKi6yXk*h#T~Ql`<*mv0PSj3>0lr?hm{fizhp>e^8u*e*8hx~ zw2L*i3xSQ8`eu5!1Mhm{N>=j1=0ZCDP8!&oO!q_RzQYo$n5l;kCYHrq`EDOPM{sxO z@Frm1XL%M89|4n^!CLal!Eh@g8?_W@d{KZTi%v7-#tdT{u=Ne^sG82g=*2gf5!!1) z#_)a*De=Mrgg<7nAV?A6A&DKbJo8x)e=sv%S{C?-XdhmMa072Dw)Go<0$(+ZQSIT(e*;nN%LFUM;5x9#| zFf9-PA%s5=J++E2wXR9p_4=mfP^o~$ElK&M9_T<8oN!%ORH(a=tZ5Q_T_41sa1GYI z$3xEANa8e`j$!59@dUU+g1aqD7&b=ZF#ilY@wi4VyN7TshIYC$RE^BUjo-xU(7xsA zCpGXXf*|P2MnybkOpi{Frf$SQJ9*?ycRT0p@U+1*2~1ybTt@y2TxEe1UJJ9sVzX2s z-%nxtBB6MaMl;bmq3i>dLKWG2vgGyW|fj*{mn%=C-JHfYgxd_`#`)|kT(=6N=Fo}M5 zn6@S`83lz8L^op_q_$7N;P#q0?o$8{^n0u}Q7~<#Iab?-KWl=%E*5L|gWO?L3Q1ic zYH^24A>1L0%G45<7Tqs0T7ZcZ{5Ev;>^CYjqTqdlL+2vJ{nlz+b!5?8Hw*l-ktOjn z?NcS*-{u}XXcMH*<4@u-)DE)n39TEl170lD&XD60A~7G1KcK^Y4`;#qVa+cEGBv*e z-4M;p$ae3JP^z8JG7n-K)Sa8r&(~qGS=S|A225j6T1Wg3Dkjy5|)(^d^6Y z4pOMY+_9zl2EL0McavVS!l=v@T998|F?}OYk>WjIUmaHIHr%fqyNd8fn#?poc@JGp z9#IKxfJr=l=a2h$9u}S+@O$)tyEGWXAE)PvHT=JZd0`uLN+~%9h@e^t5IWr3v5Br! z?xD(5-aAP%?s9vNfEi)7g;84vDt2TBO{@3*ynJR#B-7v0w945i^nhDpq%=X*$eTcl z=Qkqi>~12K}DWLD%pfe>0@lqzW5VDsGqHju8-NPADyZ+FN%(5U-3gfxJZ#bU?G?l zO(8A|nwDFQ_=oqxt9~Jp+Pw7ugT5yY=7Qs{`a@LJ#(4z(;MQ^w9c%v?#|ycE5YOTt zNwn*R#aO%3cj1l)skR`RXZd@5%zKyLq|&f(FhwXLJO<-w@uRp1yzpcM(%=Pw=o8&x{5*Aw`|8e? zgx|{t3<15MOvHeZit@E$l?FZr+9HzjW@72Y432{2lrMLK03!7im%U2go%C3C$h}`! z321<>)Dn6dw!b|lhLw8k5xq73gHREs;J{@2FO!2P$HOjvgB5uJ==7&#Oy<6-M_{-E zR@eIRp+kAggCMA96S?KV8<;fQ)iM*}JTCn2nBkB>XlaXW?pa_eCUb`+MuGr@&V}R5 z!7fip-c92c(LCFc9_CZ?fvYrB;edILDqhPItugsI)MOv{OxH&k#}ko$QS1H z(#({_Ge4_vq2ZUa@f>NRYRFj00g`zd|E_y>a0X77bh%dA6pS`4rHXlGNOw}z4B)wF z#9z4Khe%(o2x|H9>Lurc3Xru9LRyX8Gvit?v#q(7U4oajC@GxSfM zb-ak^WCPa#mcwIKua7Vdf=ms%FC+_*#B=lKEDn>uL7eAu=7S%zNBFZd_omRu7 zkgiCC=f9q$%}Os991H`WG2G>UyV@HI}q|`g9Odpp}gw*NLnm{>#cR6&x5W5G+JY> z4XRxdtl3hhp9I7)Q9p;n$n1!(nc^@j#(fX*_$jOEuP;&`scImN!Qp`TQCQ{U55*}k zM75uJ1G)-4tf7RFv+0TTRZAd*czuuI_*PKV82C}+5!^Ia&wuUY`>2%lkf`-+;SK1w zsn{l4t#PaannDf>;V}i!Ayu~Aq`L^9)Oppx<~`LUrU;$|zLID~_v);hk(#>OkLW<4 z#0G{io@ee0!YMD65MX>XB=V(_lly4^@B!xldo4Bgw&k`6XL{KReuo|1j8mIs2b&4M zm26;#*;83B@|%`F+2CM?Oa4SGb>Z0fi|@L}x}0CbqcI6uyOEyjq2= zkIkPpw204CW86yN0nUuppj8F^IH8KMPH$e>m6?n#3M1g6Jn!)hoUtV#x5Z^$YT4JA z$9(gfAFy)vj^RMrZHbTsXw>=rDbP@5#-Ejg#%^q`IA^ z8zyKW@gtT6Ehg73x+BA+K`EQpje$k-lQ0W(_r$BrGl^zdlfdo-U0?CT_gu!4*vAFW zOEM9|ls=Fo^gJ@vYHwR(8aOf_@)VTovLXttL@HSj$?|n=2pBowp!ZpjYUw#f$2ky^ z$1r)iz){IrNR;@S z=3&831mOZsO}fcEQ@y?U@PgD4v`bla*R1b&L#c8^44=HJFT$JAL-lHuM zS?de7+)5KT-V|;?gMOns+%u2708y*9zhlB;z2{a>tnFVkzTWepl8arm&@YAy;LQ9; zwR1y`6Jky81<4i_dT0-9)sfU9>a3*;RO>nB@NbsfGo_hy0fI0hredsOtZv;S@z#W2 z2F51>Ns3Dom<<74gS6)7Aq z)D|Q6<8oYL4N_6`{OQ<8b*mw&mc0pX(WS@qXZ36`Rkc6thtiJG)zViz5RLEv5$g{4 z=rVq?L5|q+bQPCVF{(25RQjRYM!24Zrs0{xHZ9%)<`X`YCyrkbra2WpgfeX=8Uf4F^o6p_1oomPEf`ScYvM*8S4WQV9ktyqv4n{ zg-XC|`LC(Y;9ztU(y|k65QYr9k1&>fW3zjgy=OM>#V4DID$e4Bk*sm0mE2k{%!d1we2WWU0fj%SPd=H`Rq`Pqpx9 zqKb)W41D?f0`cVzad|>@SQ9cy(YF#ggnAN;$>qGscB1Usv;0PJs}!;;4#pi&(HE48lqk>i0JA#e$SAJ=-}lB+FG!T5i+!X)YM_)euC4NdNTDxVCU6 zgue$qdIqC?YC0U;D50XNOaSTGX|S9Sp>^ds^i>G=8AAV<{fIrBjvxWFraO6+n$LKI zCY5;zI1#NdJl=4L=!Rt~u_6F@QSMp!VPgR>FCM&pYE0T~5!!xZIaOwrBI_iC?{Igv z`V8Q7+HDWZ$#mg86V?L&9g23^3$xWVU7kU2d|q?mdd~FgS0+r72eM_2(*y2>P5CU4 zQ{P$D&-i>y6=6YRW8a0Xb*i19Cd&(aB86Kmyq;OO6dOlfT91wY;70;RJ4-vy__hxE zL2or|y~U5<@@`VSV$SHH+zn(W$|dfQ_d&BQYc*K{Ap0l>aK++Br?$ib+g-Ca+&CUYq%`ap5?H|lJI^R$6l`&@p7bUh*gp! zm&Xn*U({Z}yzvfqouRJ3u*%-^6z#-AszzL7+3Mn`i5OB&wH;GhGxWOK#o)tb6ndC~ zoyQR#;X{0!8Rv(6AD;wUHIXMN^+oB!as0um=lYwA|3RdrJgDde31oo^3BLk-*wl+)HUr4!6ZZZDTL;+Z6HkFs1d zyoxjC5?RV$LeZTkg$8=^g{8OAoR(dO;8Yo@CT+}?Rz0A08lQ@aenW@Qdyyk5?rEUJ z%&nkbSOLr0;7L*P!153hZ}=Z6s?ZIo%tupig_n3haoD05Adh7ELgIzn2NFew-Kqy9 z{yvb539)<)2{`KubP&X>j=jC-&yggig1?~X$vV>7u9-6C02`4cl`gJkF;*y-T^w_^av4?A2*1L}7S-C~daFsX~vE71)hNJ0y;~}!=bZW@foru!6qVY9}Z_@`!lr8*WmnFxu zi{Frpq=Jy4$K?e;4=6bjh2Llg{!T~MY{ky_kI$>MMX3JkPnDZPf&pP+i`UAfE=+=^ zpRg2R=h2HFHW@?SNWrM4^9 z&yc!edvc~FSj8Tf6nm(JT_RIl%`xm6zp~C#{Qax=4l0Wld{GQT-mbF_Q$YcsjzhoP zhs$O5Bg3TQ#1*p6L8V>#c&P7G2d0k8W_WNK=@Y%j zRL~*5ifko1WpRCWkU4)kPoHXwMG)cyPkBot`%ubf6J(cHT<^Re!MJf-&VZTb+^$i3 zMs^$(%WoYpyJaI`P2tESJuqGqc=n9ip<^d}D`2bzq=1(ruxWL{Q}9sp>}xEPKrEy`!^}d z@)5nf4W_l9l~T;$k5Xb9lS77^p_>Jhfk=jMWli>rZ69YF8n18GTm(EGb?EU9dS;`q zP4sW4Sn6EJ@!?iq6LusT42)amAKCz3K%u{~O*_%Lm9JjIuSsA72&5gtiM#cev|~D7 z{Jj(n1F&I^I?i?@<9tRvN1q)%Ap!{N3_@ENK>bTRZRdCt5;wXVosADoDnc0dTM;@Z-Sq2xvG>7%0DsBch}?!8!Y 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

    )!9i9hw{Ob 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≦+izz+G& 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 z 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 P$#vUPJ9bILa_T!IAHs`KrECxfii4}rnSJW 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

    En^kAA48b?MQt>G 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 z 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 WBc(Eq1E`x4&j= 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

    A=0LDDd$IbPOFqR} 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

    4(*Ow$IJFi$tfSRwnbf|4MjfH@MP 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